Bug 1251801 - Fully implement nsNSSShutDownObject and obviate manual NSS resource management. r=keeler draft
authorCykesiopka <cykesiopka.bmo@gmail.com>
Tue, 29 Mar 2016 18:14:28 -0700
changeset 345645 76ce9d66f60a61714ad54107b02a2ee20163c5a5
parent 345644 3ff2b12ffedc9e74d01013d685ab5a07d7c9f87b
child 345646 c3fd1dbf2fe4a5bb6cde03bc0eca04d8c60f7a65
push id14135
push usercykesiopka.bmo@gmail.com
push dateWed, 30 Mar 2016 01:39:15 +0000
reviewerskeeler
bugs1251801
milestone48.0a1
Bug 1251801 - Fully implement nsNSSShutDownObject and obviate manual NSS resource management. r=keeler MozReview-Commit-ID: A7a9TVikRPh
security/manager/ssl/nsPK11TokenDB.cpp
security/manager/ssl/nsPK11TokenDB.h
--- a/security/manager/ssl/nsPK11TokenDB.cpp
+++ b/security/manager/ssl/nsPK11TokenDB.cpp
@@ -14,73 +14,71 @@
 #include "ScopedNSSTypes.h"
 #include "secerr.h"
 
 extern mozilla::LazyLogModule gPIPNSSLog;
 
 NS_IMPL_ISUPPORTS(nsPK11Token, nsIPK11Token)
 
 nsPK11Token::nsPK11Token(PK11SlotInfo *slot)
+  : mUIContext(new PipUIContext())
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown())
     return;
 
-  PK11_ReferenceSlot(slot);
-  mSlot = slot;
+  mSlot.reset(PK11_ReferenceSlot(slot));
   mSeries = PK11_GetSlotSeries(slot);
 
-  refreshTokenInfo();
-  mUIContext = new PipUIContext();
+  refreshTokenInfo(locker);
 }
 
-void  
-nsPK11Token::refreshTokenInfo()
+void
+nsPK11Token::refreshTokenInfo(const nsNSSShutDownPreventionLock& /*proofOfLock*/)
 {
-  mTokenName = NS_ConvertUTF8toUTF16(PK11_GetTokenName(mSlot));
-
-  SECStatus srv;
-
-  CK_TOKEN_INFO tok_info;
-  srv = PK11_GetTokenInfo(mSlot, &tok_info);
-  if (srv == SECSuccess) {
-    // Set the Label field
-
-    const char *ccLabel = (const char*)tok_info.label;
-    const nsACString &cLabel = Substring(
-      ccLabel, 
-      ccLabel+PL_strnlen(ccLabel, sizeof(tok_info.label)));
-    mTokenLabel = NS_ConvertUTF8toUTF16(cLabel);
-    mTokenLabel.Trim(" ", false, true);
+  mTokenName = NS_ConvertUTF8toUTF16(PK11_GetTokenName(mSlot.get()));
 
-    // Set the Manufacturer field
-    const char *ccManID = (const char*)tok_info.manufacturerID;
-    const nsACString &cManID = Substring(
-      ccManID, 
-      ccManID+PL_strnlen(ccManID, sizeof(tok_info.manufacturerID)));
-    mTokenManID = NS_ConvertUTF8toUTF16(cManID);
-    mTokenManID.Trim(" ", false, true);
-
-    // Set the Hardware Version field
-    mTokenHWVersion.AppendInt(tok_info.hardwareVersion.major);
-    mTokenHWVersion.Append('.');
-    mTokenHWVersion.AppendInt(tok_info.hardwareVersion.minor);
-    // Set the Firmware Version field
-    mTokenFWVersion.AppendInt(tok_info.firmwareVersion.major);
-    mTokenFWVersion.Append('.');
-    mTokenFWVersion.AppendInt(tok_info.firmwareVersion.minor);
-    // Set the Serial Number field
-    const char *ccSerial = (const char*)tok_info.serialNumber;
-    const nsACString &cSerial = Substring(
-      ccSerial, 
-      ccSerial+PL_strnlen(ccSerial, sizeof(tok_info.serialNumber)));
-    mTokenSerialNum = NS_ConvertUTF8toUTF16(cSerial);
-    mTokenSerialNum.Trim(" ", false, true);
+  CK_TOKEN_INFO tokInfo;
+  if (PK11_GetTokenInfo(mSlot.get(), &tokInfo) != SECSuccess) {
+    return;
   }
 
+  // Set the Label field
+  const char* ccLabel = reinterpret_cast<const char*>(tokInfo.label);
+  const nsACString& cLabel = Substring(
+    ccLabel,
+    ccLabel + PL_strnlen(ccLabel, sizeof(tokInfo.label)));
+  mTokenLabel = NS_ConvertUTF8toUTF16(cLabel);
+  mTokenLabel.Trim(" ", false, true);
+
+  // Set the Manufacturer field
+  const char* ccManID = reinterpret_cast<const char*>(tokInfo.manufacturerID);
+  const nsACString& cManID = Substring(
+    ccManID,
+    ccManID + PL_strnlen(ccManID, sizeof(tokInfo.manufacturerID)));
+  mTokenManID = NS_ConvertUTF8toUTF16(cManID);
+  mTokenManID.Trim(" ", false, true);
+
+  // Set the Hardware Version field
+  mTokenHWVersion.AppendInt(tokInfo.hardwareVersion.major);
+  mTokenHWVersion.Append('.');
+  mTokenHWVersion.AppendInt(tokInfo.hardwareVersion.minor);
+
+  // Set the Firmware Version field
+  mTokenFWVersion.AppendInt(tokInfo.firmwareVersion.major);
+  mTokenFWVersion.Append('.');
+  mTokenFWVersion.AppendInt(tokInfo.firmwareVersion.minor);
+
+  // Set the Serial Number field
+  const char* ccSerial = reinterpret_cast<const char*>(tokInfo.serialNumber);
+  const nsACString& cSerial = Substring(
+    ccSerial,
+    ccSerial + PL_strnlen(ccSerial, sizeof(tokInfo.serialNumber)));
+  mTokenSerialNum = NS_ConvertUTF8toUTF16(cSerial);
+  mTokenSerialNum.Trim(" ", false, true);
 }
 
 nsPK11Token::~nsPK11Token()
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown()) {
     return;
   }
@@ -90,133 +88,158 @@ nsPK11Token::~nsPK11Token()
 
 void nsPK11Token::virtualDestroyNSSReference()
 {
   destructorSafeDestroyNSSReference();
 }
 
 void nsPK11Token::destructorSafeDestroyNSSReference()
 {
-  if (mSlot) {
-    PK11_FreeSlot(mSlot);
-    mSlot = nullptr;
-  }
+  mSlot = nullptr;
 }
 
 NS_IMETHODIMP nsPK11Token::GetTokenName(char16_t * *aTokenName)
 {
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   // handle removals/insertions
-  if (mSeries != PK11_GetSlotSeries(mSlot)) {
-    refreshTokenInfo();
+  if (PK11_GetSlotSeries(mSlot.get()) != mSeries) {
+    refreshTokenInfo(locker);
   }
   *aTokenName = ToNewUnicode(mTokenName);
   if (!*aTokenName) return NS_ERROR_OUT_OF_MEMORY;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsPK11Token::GetTokenLabel(char16_t **aTokLabel)
 {
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   // handle removals/insertions
-  if (mSeries != PK11_GetSlotSeries(mSlot)) {
-    refreshTokenInfo();
+  if (PK11_GetSlotSeries(mSlot.get()) != mSeries) {
+    refreshTokenInfo(locker);
   }
   *aTokLabel = ToNewUnicode(mTokenLabel);
   if (!*aTokLabel) return NS_ERROR_OUT_OF_MEMORY;
   return NS_OK;
 }
 
 NS_IMETHODIMP nsPK11Token::GetTokenManID(char16_t **aTokManID)
 {
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   // handle removals/insertions
-  if (mSeries != PK11_GetSlotSeries(mSlot)) {
-    refreshTokenInfo();
+  if (PK11_GetSlotSeries(mSlot.get()) != mSeries) {
+    refreshTokenInfo(locker);
   }
   *aTokManID = ToNewUnicode(mTokenManID);
   if (!*aTokManID) return NS_ERROR_OUT_OF_MEMORY;
   return NS_OK;
 }
 
 NS_IMETHODIMP nsPK11Token::GetTokenHWVersion(char16_t **aTokHWVersion)
 {
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   // handle removals/insertions
-  if (mSeries != PK11_GetSlotSeries(mSlot)) {
-    refreshTokenInfo();
+  if (PK11_GetSlotSeries(mSlot.get()) != mSeries) {
+    refreshTokenInfo(locker);
   }
   *aTokHWVersion = ToNewUnicode(mTokenHWVersion);
   if (!*aTokHWVersion) return NS_ERROR_OUT_OF_MEMORY;
   return NS_OK;
 }
 
 NS_IMETHODIMP nsPK11Token::GetTokenFWVersion(char16_t **aTokFWVersion)
 {
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   // handle removals/insertions
-  if (mSeries != PK11_GetSlotSeries(mSlot)) {
-    refreshTokenInfo();
+  if (PK11_GetSlotSeries(mSlot.get()) != mSeries) {
+    refreshTokenInfo(locker);
   }
   *aTokFWVersion = ToNewUnicode(mTokenFWVersion);
   if (!*aTokFWVersion) return NS_ERROR_OUT_OF_MEMORY;
   return NS_OK;
 }
 
 NS_IMETHODIMP nsPK11Token::GetTokenSerialNumber(char16_t **aTokSerialNum)
 {
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   // handle removals/insertions
-  if (mSeries != PK11_GetSlotSeries(mSlot)) {
-    refreshTokenInfo();
+  if (PK11_GetSlotSeries(mSlot.get()) != mSeries) {
+    refreshTokenInfo(locker);
   }
   *aTokSerialNum = ToNewUnicode(mTokenSerialNum);
   if (!*aTokSerialNum) return NS_ERROR_OUT_OF_MEMORY;
   return NS_OK;
 }
 
 NS_IMETHODIMP nsPK11Token::IsLoggedIn(bool *_retval)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown())
     return NS_ERROR_NOT_AVAILABLE;
 
-  nsresult rv = NS_OK;
+  *_retval = PK11_IsLoggedIn(mSlot.get(), 0);
 
-  *_retval = PK11_IsLoggedIn(mSlot, 0);
-
-  return rv;
+  return NS_OK;
 }
 
-NS_IMETHODIMP 
+NS_IMETHODIMP
 nsPK11Token::Login(bool force)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown())
     return NS_ERROR_NOT_AVAILABLE;
 
   nsresult rv;
   SECStatus srv;
   bool test;
   rv = this->NeedsLogin(&test);
   if (NS_FAILED(rv)) return rv;
   if (test && force) {
     rv = this->LogoutSimple();
     if (NS_FAILED(rv)) return rv;
   }
-  rv = setPassword(mSlot, mUIContext, locker);
+  rv = setPassword(mSlot.get(), mUIContext, locker);
   if (NS_FAILED(rv)) return rv;
-  srv = PK11_Authenticate(mSlot, true, mUIContext);
+  srv = PK11_Authenticate(mSlot.get(), true, mUIContext);
   return (srv == SECSuccess) ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP nsPK11Token::LogoutSimple()
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown())
     return NS_ERROR_NOT_AVAILABLE;
 
   // PK11_MapError sets CKR_USER_NOT_LOGGED_IN to SEC_ERROR_LIBRARY_FAILURE,
   // so not going to learn anything here by a failure.  Treat it like void.
-  PK11_Logout(mSlot);
+  PK11_Logout(mSlot.get());
   return NS_OK;
 }
 
 NS_IMETHODIMP nsPK11Token::LogoutAndDropAuthenticatedResources()
 {
   static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
 
   nsresult rv = LogoutSimple();
@@ -232,230 +255,230 @@ NS_IMETHODIMP nsPK11Token::LogoutAndDrop
 }
 
 NS_IMETHODIMP nsPK11Token::Reset()
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown())
     return NS_ERROR_NOT_AVAILABLE;
 
-  PK11_ResetToken(mSlot, 0);
+  PK11_ResetToken(mSlot.get(), 0);
   return NS_OK;
 }
 
 NS_IMETHODIMP nsPK11Token::GetMinimumPasswordLength(int32_t *aMinimumPasswordLength)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown())
     return NS_ERROR_NOT_AVAILABLE;
 
-  *aMinimumPasswordLength = PK11_GetMinimumPwdLength(mSlot);
+  *aMinimumPasswordLength = PK11_GetMinimumPwdLength(mSlot.get());
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsPK11Token::GetNeedsUserInit(bool *aNeedsUserInit)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown())
     return NS_ERROR_NOT_AVAILABLE;
 
-  *aNeedsUserInit = PK11_NeedUserInit(mSlot);
+  *aNeedsUserInit = PK11_NeedUserInit(mSlot.get());
   return NS_OK;
 }
 
 NS_IMETHODIMP nsPK11Token::CheckPassword(const char16_t *password, bool *_retval)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown())
     return NS_ERROR_NOT_AVAILABLE;
 
-  SECStatus srv;
-  int32_t prerr;
-  NS_ConvertUTF16toUTF8 aUtf8Password(password);
-  srv = PK11_CheckUserPassword(mSlot, 
-                  const_cast<char *>(aUtf8Password.get()));
+  NS_ConvertUTF16toUTF8 utf8Password(password);
+  SECStatus srv =
+    PK11_CheckUserPassword(mSlot.get(), const_cast<char*>(utf8Password.get()));
   if (srv != SECSuccess) {
     *_retval =  false;
-    prerr = PR_GetError();
-    if (prerr != SEC_ERROR_BAD_PASSWORD) {
+    if (PR_GetError() != SEC_ERROR_BAD_PASSWORD) {
       /* something really bad happened - throw an exception */
       return NS_ERROR_FAILURE;
     }
   } else {
     *_retval =  true;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP nsPK11Token::InitPassword(const char16_t *initialPassword)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown())
     return NS_ERROR_NOT_AVAILABLE;
 
-    nsresult rv = NS_OK;
-    SECStatus status;
+  NS_ConvertUTF16toUTF8 utf8Password(initialPassword);
+  if (PK11_InitPin(mSlot.get(), "", const_cast<char*>(utf8Password.get()))
+        != SECSuccess) {
+    return NS_ERROR_FAILURE;
+  }
 
-    NS_ConvertUTF16toUTF8 aUtf8InitialPassword(initialPassword);
-    status = PK11_InitPin(mSlot, "", const_cast<char*>(aUtf8InitialPassword.get()));
-    if (status == SECFailure) { rv = NS_ERROR_FAILURE; goto done; }
-
-done:
-    return rv;
+  return NS_OK;
 }
 
-NS_IMETHODIMP 
-nsPK11Token::GetAskPasswordTimes(int32_t *rvAskTimes)
+NS_IMETHODIMP
+nsPK11Token::GetAskPasswordTimes(int32_t* askTimes)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown())
     return NS_ERROR_NOT_AVAILABLE;
 
-    int askTimes, askTimeout;
-    PK11_GetSlotPWValues(mSlot, &askTimes, &askTimeout);
-    *rvAskTimes = askTimes;
-    return NS_OK;
+  int askTimeout;
+  PK11_GetSlotPWValues(mSlot.get(), askTimes, &askTimeout);
+  return NS_OK;
 }
 
-NS_IMETHODIMP 
-nsPK11Token::GetAskPasswordTimeout(int32_t *rvAskTimeout)
+NS_IMETHODIMP
+nsPK11Token::GetAskPasswordTimeout(int32_t* askTimeout)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown())
     return NS_ERROR_NOT_AVAILABLE;
 
-    int askTimes, askTimeout;
-    PK11_GetSlotPWValues(mSlot, &askTimes, &askTimeout);
-    *rvAskTimeout = askTimeout;
-    return NS_OK;
+  int askTimes;
+  PK11_GetSlotPWValues(mSlot.get(), &askTimes, askTimeout);
+  return NS_OK;
 }
 
-NS_IMETHODIMP 
+NS_IMETHODIMP
 nsPK11Token::SetAskPasswordDefaults(const int32_t askTimes,
                                     const int32_t askTimeout)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown())
     return NS_ERROR_NOT_AVAILABLE;
 
-    PK11_SetSlotPWValues(mSlot, askTimes, askTimeout);
-    return NS_OK;
+  PK11_SetSlotPWValues(mSlot.get(), askTimes, askTimeout);
+  return NS_OK;
 }
 
 NS_IMETHODIMP nsPK11Token::ChangePassword(const char16_t *oldPassword, const char16_t *newPassword)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown())
     return NS_ERROR_NOT_AVAILABLE;
 
-  SECStatus rv;
-  NS_ConvertUTF16toUTF8 aUtf8OldPassword(oldPassword);
-  NS_ConvertUTF16toUTF8 aUtf8NewPassword(newPassword);
+  NS_ConvertUTF16toUTF8 utf8OldPassword(oldPassword);
+  NS_ConvertUTF16toUTF8 utf8NewPassword(newPassword);
 
-  rv = PK11_ChangePW(mSlot, 
-         (oldPassword ? const_cast<char *>(aUtf8OldPassword.get()) : nullptr),
-         (newPassword ? const_cast<char *>(aUtf8NewPassword.get()) : nullptr));
-  return (rv == SECSuccess) ? NS_OK : NS_ERROR_FAILURE;
+  // nsCString.get() will return an empty string instead of nullptr even if it
+  // was initialized with nullptr. PK11_ChangePW() has different semantics for
+  // the empty string and for nullptr, so we can't just use get().
+  // See Bug 447589.
+  SECStatus srv = PK11_ChangePW(mSlot.get(),
+    (oldPassword ? const_cast<char*>(utf8OldPassword.get()) : nullptr),
+    (newPassword ? const_cast<char*>(utf8NewPassword.get()) : nullptr));
+  return (srv == SECSuccess) ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP nsPK11Token::IsHardwareToken(bool *_retval)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown())
     return NS_ERROR_NOT_AVAILABLE;
 
-  nsresult rv = NS_OK;
+  *_retval = PK11_IsHW(mSlot.get());
 
-  *_retval = PK11_IsHW(mSlot);
-
-  return rv;
+  return NS_OK;
 }
 
 NS_IMETHODIMP nsPK11Token::NeedsLogin(bool *_retval)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown())
     return NS_ERROR_NOT_AVAILABLE;
 
-  nsresult rv = NS_OK;
+  *_retval = PK11_NeedLogin(mSlot.get());
 
-  *_retval = PK11_NeedLogin(mSlot);
-
-  return rv;
+  return NS_OK;
 }
 
 NS_IMETHODIMP nsPK11Token::IsFriendly(bool *_retval)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown())
     return NS_ERROR_NOT_AVAILABLE;
 
-  nsresult rv = NS_OK;
+  *_retval = PK11_IsFriendly(mSlot.get());
 
-  *_retval = PK11_IsFriendly(mSlot);
-
-  return rv;
+  return NS_OK;
 }
 
 /*=========================================================*/
 
 NS_IMPL_ISUPPORTS(nsPK11TokenDB, nsIPK11TokenDB)
 
 nsPK11TokenDB::nsPK11TokenDB()
 {
-  /* member initializers and constructor code */
 }
 
 nsPK11TokenDB::~nsPK11TokenDB()
 {
-  /* destructor code */
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return;
+  }
+
+  shutdown(calledFromObject);
 }
 
 NS_IMETHODIMP nsPK11TokenDB::GetInternalKeyToken(nsIPK11Token **_retval)
 {
   nsNSSShutDownPreventionLock locker;
-  nsresult rv = NS_OK;
-  PK11SlotInfo *slot = 0;
-  nsCOMPtr<nsIPK11Token> token;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
 
-  slot = PK11_GetInternalKeySlot();
-  if (!slot) { rv = NS_ERROR_FAILURE; goto done; }
+  UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
+  if (!slot) {
+    return NS_ERROR_FAILURE;
+  }
 
-  token = new nsPK11Token(slot);
+  nsCOMPtr<nsIPK11Token> token = new nsPK11Token(slot.get());
   token.forget(_retval);
 
-done:
-  if (slot) PK11_FreeSlot(slot);
-  return rv;
+  return NS_OK;
 }
 
 NS_IMETHODIMP nsPK11TokenDB::
 FindTokenByName(const char16_t* tokenName, nsIPK11Token **_retval)
 {
   nsNSSShutDownPreventionLock locker;
-  nsresult rv = NS_OK;
-  PK11SlotInfo *slot = 0;
-  nsCOMPtr<nsIPK11Token> token;
-  NS_ConvertUTF16toUTF8 aUtf8TokenName(tokenName);
-  slot = PK11_FindSlotByName(const_cast<char*>(aUtf8TokenName.get()));
-  if (!slot) { rv = NS_ERROR_FAILURE; goto done; }
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
 
-  token = new nsPK11Token(slot);
+  NS_ConvertUTF16toUTF8 utf8TokenName(tokenName);
+  UniquePK11SlotInfo slot(
+    PK11_FindSlotByName(const_cast<char*>(utf8TokenName.get())));
+  if (!slot) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsCOMPtr<nsIPK11Token> token = new nsPK11Token(slot.get());
   token.forget(_retval);
 
-done:
-  if (slot) PK11_FreeSlot(slot);
-  return rv;
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPK11TokenDB::ListTokens(nsISimpleEnumerator** _retval)
 {
   nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID);
   if (!array) {
     return NS_ERROR_FAILURE;
   }
 
   *_retval = nullptr;
 
   UniquePK11SlotList list(
--- a/security/manager/ssl/nsPK11TokenDB.h
+++ b/security/manager/ssl/nsPK11TokenDB.h
@@ -1,63 +1,66 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef __NS_PK11TOKENDB_H__
-#define __NS_PK11TOKENDB_H__
+#ifndef nsPK11TokenDB_h
+#define nsPK11TokenDB_h
 
 #include "nsCOMPtr.h"
-#include "nsString.h"
-#include "nsISupports.h"
+#include "nsIPK11Token.h"
 #include "nsIPK11TokenDB.h"
-#include "nsIPK11Token.h"
+#include "nsISupports.h"
 #include "nsNSSHelper.h"
+#include "nsNSSShutDown.h"
+#include "nsString.h"
 #include "pk11func.h"
-#include "nsNSSShutDown.h"
+#include "ScopedNSSTypes.h"
 
 class nsPK11Token : public nsIPK11Token,
                     public nsNSSShutDownObject
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPK11TOKEN
 
   explicit nsPK11Token(PK11SlotInfo *slot);
-  /* additional members */
 
 protected:
   virtual ~nsPK11Token();
 
 private:
   friend class nsPK11TokenDB;
-  void refreshTokenInfo();
+  void refreshTokenInfo(const nsNSSShutDownPreventionLock& proofOfLock);
 
   nsString mTokenName;
   nsString mTokenLabel, mTokenManID, mTokenHWVersion, mTokenFWVersion;
   nsString mTokenSerialNum;
-  PK11SlotInfo *mSlot;
+  mozilla::UniquePK11SlotInfo mSlot;
   int mSeries;
   nsCOMPtr<nsIInterfaceRequestor> mUIContext;
   virtual void virtualDestroyNSSReference() override;
   void destructorSafeDestroyNSSReference();
 };
 
 class nsPK11TokenDB : public nsIPK11TokenDB
+                    , public nsNSSShutDownObject
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPK11TOKENDB
 
   nsPK11TokenDB();
 
 protected:
   virtual ~nsPK11TokenDB();
-  /* additional members */
+
+  // Nothing to release.
+  virtual void virtualDestroyNSSReference() override {}
 };
 
 #define NS_PK11TOKENDB_CID \
 { 0xb084a2ce, 0x1dd1, 0x11b2, \
   { 0xbf, 0x10, 0x83, 0x24, 0xf8, 0xe0, 0x65, 0xcc }}
 
-#endif
+#endif // nsPK11TokenDB_h