bug 1421084 - part 3/4 - remove nsNSSShutDownObject::shutdown and virtualDestroyNSSReference r=mt,ttaubert
authorDavid Keeler <dkeeler@mozilla.com>
Wed, 24 Jan 2018 14:29:08 -0800
changeset 441424 0d42218045d9de6b746b09669dedb0e30e8005c3
parent 441423 ecb9941ee0344bd6952724e371589c3d0834e30d
child 441425 e21956fd51a330cad2301e49bb458e2ca94c5368
push idunknown
push userunknown
push dateunknown
reviewersmt, ttaubert
bugs1421084
milestone60.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 1421084 - part 3/4 - remove nsNSSShutDownObject::shutdown and virtualDestroyNSSReference r=mt,ttaubert MozReview-Commit-ID: ErL7ZjAGVVC
dom/crypto/CryptoKey.cpp
dom/crypto/CryptoKey.h
dom/crypto/WebCryptoTask.cpp
dom/crypto/WebCryptoTask.h
dom/media/webrtc/RTCCertificate.cpp
dom/media/webrtc/RTCCertificate.h
dom/webauthn/U2FSoftTokenManager.cpp
dom/webauthn/U2FSoftTokenManager.h
netwerk/base/BackgroundFileSaver.cpp
netwerk/base/BackgroundFileSaver.h
security/apps/AppSignatureVerification.cpp
security/manager/ssl/ContentSignatureVerifier.cpp
security/manager/ssl/ContentSignatureVerifier.h
security/manager/ssl/CryptoTask.cpp
security/manager/ssl/CryptoTask.h
security/manager/ssl/LocalCertService.cpp
security/manager/ssl/PKCS11ModuleDB.cpp
security/manager/ssl/PKCS11ModuleDB.h
security/manager/ssl/SecretDecoderRing.cpp
security/manager/ssl/SecretDecoderRing.h
security/manager/ssl/TransportSecurityInfo.cpp
security/manager/ssl/TransportSecurityInfo.h
security/manager/ssl/nsCryptoHash.cpp
security/manager/ssl/nsCryptoHash.h
security/manager/ssl/nsDataSignatureVerifier.cpp
security/manager/ssl/nsDataSignatureVerifier.h
security/manager/ssl/nsKeyModule.cpp
security/manager/ssl/nsKeyModule.h
security/manager/ssl/nsKeygenHandler.cpp
security/manager/ssl/nsKeygenHandler.h
security/manager/ssl/nsNSSCallbacks.cpp
security/manager/ssl/nsNSSCertValidity.cpp
security/manager/ssl/nsNSSCertValidity.h
security/manager/ssl/nsNSSCertificate.cpp
security/manager/ssl/nsNSSCertificate.h
security/manager/ssl/nsNSSCertificateDB.cpp
security/manager/ssl/nsNSSCertificateDB.h
security/manager/ssl/nsNSSComponent.cpp
security/manager/ssl/nsNSSShutDown.h
security/manager/ssl/nsPK11TokenDB.cpp
security/manager/ssl/nsPK11TokenDB.h
security/manager/ssl/nsPKCS11Slot.cpp
security/manager/ssl/nsPKCS11Slot.h
security/manager/ssl/nsPKCS12Blob.cpp
security/manager/ssl/nsPKCS12Blob.h
security/manager/ssl/nsRandomGenerator.cpp
security/manager/ssl/nsRandomGenerator.h
security/manager/ssl/nsSSLStatus.cpp
security/manager/ssl/nsSSLStatus.h
services/crypto/component/IdentityCryptoService.cpp
--- a/dom/crypto/CryptoKey.cpp
+++ b/dom/crypto/CryptoKey.cpp
@@ -155,22 +155,16 @@ CryptoKey::CryptoKey(nsIGlobalObject* aG
   : mGlobal(aGlobal)
   , mAttributes(0)
   , mSymKey()
   , mPrivateKey(nullptr)
   , mPublicKey(nullptr)
 {
 }
 
-CryptoKey::~CryptoKey()
-{
-  destructorSafeDestroyNSSReference();
-  shutdown(ShutdownCalledFrom::Object);
-}
-
 JSObject*
 CryptoKey::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return CryptoKeyBinding::Wrap(aCx, this, aGivenProto);
 }
 
 void
 CryptoKey::GetType(nsString& aRetVal) const
@@ -489,27 +483,16 @@ UniqueSECKEYPublicKey
 CryptoKey::GetPublicKey() const
 {
   if (!mPublicKey) {
     return nullptr;
   }
   return UniqueSECKEYPublicKey(SECKEY_CopyPublicKey(mPublicKey.get()));
 }
 
-void CryptoKey::virtualDestroyNSSReference()
-{
-  destructorSafeDestroyNSSReference();
-}
-
-void CryptoKey::destructorSafeDestroyNSSReference()
-{
-  mPrivateKey = nullptr;
-  mPublicKey = nullptr;
-}
-
 
 // Serialization and deserialization convenience methods
 
 UniqueSECKEYPrivateKey
 CryptoKey::PrivateKeyFromPkcs8(CryptoBuffer& aKeyData)
 {
   UniquePK11SlotInfo slot(PK11_GetInternalSlot());
   if (!slot) {
--- a/dom/crypto/CryptoKey.h
+++ b/dom/crypto/CryptoKey.h
@@ -131,20 +131,16 @@ public:
   nsresult SetPrivateKey(SECKEYPrivateKey* aPrivateKey);
   nsresult SetPublicKey(SECKEYPublicKey* aPublicKey);
 
   // Accessors for the keys themselves
   const CryptoBuffer& GetSymKey() const;
   UniqueSECKEYPrivateKey GetPrivateKey() const;
   UniqueSECKEYPublicKey GetPublicKey() const;
 
-  // For nsNSSShutDownObject
-  virtual void virtualDestroyNSSReference() override;
-  void destructorSafeDestroyNSSReference();
-
   // Serialization and deserialization convenience methods
   // Note:
   // 1. The inputs aKeyData are non-const only because the NSS import
   //    functions lack the const modifier.  They should not be modified.
   // 2. All of the NSS key objects returned need to be freed by the caller.
   static UniqueSECKEYPrivateKey PrivateKeyFromPkcs8(CryptoBuffer& aKeyData);
   static nsresult PrivateKeyToPkcs8(SECKEYPrivateKey* aPrivKey,
                                     CryptoBuffer& aRetVal);
@@ -176,17 +172,17 @@ public:
 
   static bool PublicKeyValid(SECKEYPublicKey* aPubKey);
 
   // Structured clone methods use these to clone keys
   bool WriteStructuredClone(JSStructuredCloneWriter* aWriter) const;
   bool ReadStructuredClone(JSStructuredCloneReader* aReader);
 
 private:
-  ~CryptoKey();
+  ~CryptoKey() {}
 
   RefPtr<nsIGlobalObject> mGlobal;
   uint32_t mAttributes; // see above
   KeyAlgorithmProxy mAlgorithm;
 
   // Only one key handle should be set, according to the KeyType
   CryptoBuffer mSymKey;
   UniqueSECKEYPrivateKey mPrivateKey;
--- a/dom/crypto/WebCryptoTask.cpp
+++ b/dom/crypto/WebCryptoTask.cpp
@@ -366,20 +366,19 @@ WebCryptoTask::DispatchWithPromise(Promi
 
   // Fail if an error was set during the constructor
   MAYBE_EARLY_FAIL(mEarlyRv)
 
   // Perform pre-NSS operations, and fail if they fail
   mEarlyRv = BeforeCrypto();
   MAYBE_EARLY_FAIL(mEarlyRv)
 
-  // Skip NSS if we're already done, or launch a CryptoTask
+  // Skip dispatch if we're already done. Otherwise launch a CryptoTask
   if (mEarlyComplete) {
     CallCallback(mEarlyRv);
-    Skip();
     return;
   }
 
   // Store calling thread
   mOriginalEventTarget = GetCurrentThreadSerialEventTarget();
 
   // If we are running on a worker thread we must hold the worker
   // alive while we work on the thread pool.  Otherwise the worker
@@ -408,22 +407,16 @@ WebCryptoTask::Run()
     mRv = CalculateResult();
 
     // Back to the original thread, i.e. continue below.
     mOriginalEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
     return NS_OK;
   }
 
   // We're now back on the calling thread.
-
-  // Release NSS resources now, before calling CallCallback, so that
-  // WebCryptoTasks have consistent behavior regardless of whether NSS is shut
-  // down between CalculateResult being called and CallCallback being called.
-  virtualDestroyNSSReference();
-
   CallCallback(mRv);
 
   // Stop holding the worker thread alive now that the async work has
   // been completed.
   mWorkerHolder = nullptr;
 
   return NS_OK;
 }
@@ -2130,22 +2123,16 @@ protected:
   CryptoKey::KeyType mKeyType;
   bool mExtractable;
   nsString mAlg;
   nsTArray<nsString> mKeyUsages;
   CryptoBuffer mResult;
   JsonWebKey mJwk;
 
 private:
-  virtual void ReleaseNSSResources() override
-  {
-    mPrivateKey = nullptr;
-    mPublicKey = nullptr;
-  }
-
   virtual nsresult DoCrypto() override
   {
     if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_RAW)) {
       if (mPublicKey && mPublicKey->keyType == dhKey) {
         nsresult rv = CryptoKey::PublicDhKeyToRaw(mPublicKey.get(), mResult);
         if (NS_FAILED(rv)) {
           return NS_ERROR_DOM_OPERATION_ERR;
         }
@@ -2541,23 +2528,16 @@ GenerateAsymmetricKeyTask::GenerateAsymm
   // If no usages ended up being allowed, DataError
   if (!mKeyPair->mPublicKey.get()->HasAnyUsage() &&
       !mKeyPair->mPrivateKey.get()->HasAnyUsage()) {
     mEarlyRv = NS_ERROR_DOM_DATA_ERR;
     return;
   }
 }
 
-void
-GenerateAsymmetricKeyTask::ReleaseNSSResources()
-{
-  mPublicKey = nullptr;
-  mPrivateKey = nullptr;
-}
-
 nsresult
 GenerateAsymmetricKeyTask::DoCrypto()
 {
   MOZ_ASSERT(mKeyPair);
 
   UniquePK11SlotInfo slot(PK11_GetInternalSlot());
   MOZ_ASSERT(slot.get());
 
@@ -2910,43 +2890,37 @@ template<class DeriveBitsTask>
 class DeriveKeyTask : public DeriveBitsTask
 {
 public:
   DeriveKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
                 const ObjectOrString& aAlgorithm, CryptoKey& aBaseKey,
                 const ObjectOrString& aDerivedKeyType, bool aExtractable,
                 const Sequence<nsString>& aKeyUsages)
     : DeriveBitsTask(aCx, aAlgorithm, aBaseKey, aDerivedKeyType)
-    , mResolved(false)
   {
     if (NS_FAILED(this->mEarlyRv)) {
       return;
     }
 
     NS_NAMED_LITERAL_STRING(format, WEBCRYPTO_KEY_FORMAT_RAW);
     mTask = new ImportSymmetricKeyTask(aGlobal, aCx, format, aDerivedKeyType,
                                        aExtractable, aKeyUsages);
   }
 
 protected:
   RefPtr<ImportSymmetricKeyTask> mTask;
-  bool mResolved;
 
 private:
   virtual void Resolve() override {
     mTask->SetRawKeyData(this->mResult);
     mTask->DispatchWithPromise(this->mResultPromise);
-    mResolved = true;
   }
 
   virtual void Cleanup() override
   {
-    if (mTask && !mResolved) {
-      mTask->Skip();
-    }
     mTask = nullptr;
   }
 };
 
 class DeriveEcdhBitsTask : public ReturnArrayBufferViewTask
 {
 public:
   DeriveEcdhBitsTask(JSContext* aCx,
@@ -3158,28 +3132,26 @@ class WrapKeyTask : public ExportKeyTask
 {
 public:
   WrapKeyTask(JSContext* aCx,
               const nsAString& aFormat,
               CryptoKey& aKey,
               CryptoKey& aWrappingKey,
               const ObjectOrString& aWrapAlgorithm)
     : ExportKeyTask(aFormat, aKey)
-    , mResolved(false)
   {
     if (NS_FAILED(mEarlyRv)) {
       return;
     }
 
     mTask = new KeyEncryptTask(aCx, aWrapAlgorithm, aWrappingKey, true);
   }
 
 private:
   RefPtr<KeyEncryptTask> mTask;
-  bool mResolved;
 
   virtual nsresult AfterCrypto() override {
     // If wrapping JWK, stringify the JSON
     if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK)) {
       nsAutoString json;
       if (!mJwk.ToJSON(json)) {
         return NS_ERROR_DOM_OPERATION_ERR;
       }
@@ -3192,58 +3164,48 @@ private:
 
     return NS_OK;
   }
 
   virtual void Resolve() override
   {
     mTask->SetData(mResult);
     mTask->DispatchWithPromise(mResultPromise);
-    mResolved = true;
   }
 
   virtual void Cleanup() override
   {
-    if (mTask && !mResolved) {
-      mTask->Skip();
-    }
     mTask = nullptr;
   }
 };
 
 template<class KeyEncryptTask>
 class UnwrapKeyTask : public KeyEncryptTask
 {
 public:
   UnwrapKeyTask(JSContext* aCx,
                 const ArrayBufferViewOrArrayBuffer& aWrappedKey,
                 CryptoKey& aUnwrappingKey,
                 const ObjectOrString& aUnwrapAlgorithm,
                 ImportKeyTask* aTask)
     : KeyEncryptTask(aCx, aUnwrapAlgorithm, aUnwrappingKey, aWrappedKey, false)
     , mTask(aTask)
-    , mResolved(false)
   {}
 
 private:
   RefPtr<ImportKeyTask> mTask;
-  bool mResolved;
 
   virtual void Resolve() override
   {
     mTask->SetKeyDataMaybeParseJWK(KeyEncryptTask::mResult);
     mTask->DispatchWithPromise(KeyEncryptTask::mResultPromise);
-    mResolved = true;
   }
 
   virtual void Cleanup() override
   {
-    if (mTask && !mResolved) {
-      mTask->Skip();
-    }
     mTask = nullptr;
   }
 };
 
 // Task creation methods for WebCryptoTask
 
 // Note: We do not perform algorithm normalization as a monolithic process,
 // as described in the spec.  Instead:
@@ -3704,27 +3666,22 @@ WebCryptoTask::CreateUnwrapKeyTask(nsIGl
   return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
 }
 
 WebCryptoTask::WebCryptoTask()
   : CancelableRunnable("WebCryptoTask")
   , mEarlyRv(NS_OK)
   , mEarlyComplete(false)
   , mOriginalEventTarget(nullptr)
-  , mReleasedNSSResources(false)
   , mRv(NS_ERROR_NOT_INITIALIZED)
 {
 }
 
 WebCryptoTask::~WebCryptoTask()
 {
-  MOZ_ASSERT(mReleasedNSSResources);
-
-  shutdown(ShutdownCalledFrom::Object);
-
   if (mWorkerHolder) {
     NS_ProxyRelease(
       "WebCryptoTask::mWorkerHolder",
       mOriginalEventTarget, mWorkerHolder.forget());
   }
 }
 
 } // namespace dom
--- a/dom/crypto/WebCryptoTask.h
+++ b/dom/crypto/WebCryptoTask.h
@@ -49,31 +49,25 @@ so all NSS interactions should occur in 
 
 Cleanup should execute regardless of what else happens.
 
 */
 
 #define MAYBE_EARLY_FAIL(rv) \
 if (NS_FAILED(rv)) { \
   FailWithError(rv); \
-  Skip(); \
   return; \
 }
 
 class WebCryptoTask : public CancelableRunnable,
                       public nsNSSShutDownObject
 {
 public:
   virtual void DispatchWithPromise(Promise* aResultPromise);
 
-  void Skip()
-  {
-    virtualDestroyNSSReference();
-  }
-
 protected:
   static WebCryptoTask* CreateEncryptDecryptTask(JSContext* aCx,
                            const ObjectOrString& aAlgorithm,
                            CryptoKey& aKey,
                            const CryptoOperationData& aData,
                            bool aEncrypt);
 
   static WebCryptoTask* CreateSignVerifyTask(JSContext* aCx,
@@ -182,44 +176,28 @@ protected:
   virtual nsresult BeforeCrypto() { return NS_OK; }
   virtual nsresult DoCrypto() { return NS_OK; }
   virtual nsresult AfterCrypto() { return NS_OK; }
   virtual void Resolve() {}
   virtual void Cleanup() {}
 
   void FailWithError(nsresult aRv);
 
-  // Subclasses should override this method if they keep references to
-  // any NSS objects, e.g., SECKEYPrivateKey or PK11SymKey.
-  virtual void ReleaseNSSResources() {}
-
   virtual nsresult CalculateResult() final;
 
   virtual void CallCallback(nsresult rv) final;
 
 private:
   NS_IMETHOD Run() override final;
   nsresult Cancel() override final;
 
-  virtual void
-  virtualDestroyNSSReference() override final
-  {
-    MOZ_ASSERT(IsOnOriginalThread());
-
-    if (!mReleasedNSSResources) {
-      mReleasedNSSResources = true;
-      ReleaseNSSResources();
-    }
-  }
-
   class InternalWorkerHolder;
 
   nsCOMPtr<nsISerialEventTarget> mOriginalEventTarget;
   RefPtr<InternalWorkerHolder> mWorkerHolder;
-  bool mReleasedNSSResources;
   nsresult mRv;
 };
 
 // XXX This class is declared here (unlike others) to enable reuse by WebRTC.
 class GenerateAsymmetricKeyTask : public WebCryptoTask
 {
 public:
   GenerateAsymmetricKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
@@ -229,17 +207,16 @@ protected:
   UniquePLArenaPool mArena;
   UniquePtr<CryptoKeyPair> mKeyPair;
   nsString mAlgName;
   CK_MECHANISM_TYPE mMechanism;
   PK11RSAGenParams mRsaParams;
   SECKEYDHParams mDhParams;
   nsString mNamedCurve;
 
-  virtual void ReleaseNSSResources() override;
   virtual nsresult DoCrypto() override;
   virtual void Resolve() override;
   virtual void Cleanup() override;
 
 private:
   UniqueSECKEYPublicKey mPublicKey;
   UniqueSECKEYPrivateKey mPrivateKey;
 };
--- a/dom/media/webrtc/RTCCertificate.cpp
+++ b/dom/media/webrtc/RTCCertificate.cpp
@@ -301,22 +301,16 @@ RTCCertificate::RTCCertificate(nsIGlobal
     : mGlobal(aGlobal),
       mPrivateKey(aPrivateKey),
       mCertificate(aCertificate),
       mAuthType(aAuthType),
       mExpires(aExpires)
 {
 }
 
-RTCCertificate::~RTCCertificate()
-{
-  destructorSafeDestroyNSSReference();
-  shutdown(ShutdownCalledFrom::Object);
-}
-
 // This creates some interesting lifecycle consequences, since the DtlsIdentity
 // holds NSS objects, but does not implement nsNSSShutDownObject.
 
 // Unfortunately, the code that uses DtlsIdentity cannot always use that lock
 // due to external linkage requirements.  Therefore, the lock is held on this
 // object instead.  Consequently, the DtlsIdentity that this method returns must
 // have a lifetime that is strictly shorter than the RTCCertificate.
 //
@@ -336,29 +330,16 @@ RTCCertificate::CreateDtlsIdentity() con
 }
 
 JSObject*
 RTCCertificate::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return RTCCertificateBinding::Wrap(aCx, this, aGivenProto);
 }
 
-void
-RTCCertificate::virtualDestroyNSSReference()
-{
-  destructorSafeDestroyNSSReference();
-}
-
-void
-RTCCertificate::destructorSafeDestroyNSSReference()
-{
-  mPrivateKey.reset();
-  mCertificate.reset();
-}
-
 bool
 RTCCertificate::WritePrivateKey(JSStructuredCloneWriter* aWriter) const
 {
   JsonWebKey jwk;
   nsresult rv = CryptoKey::PrivateKeyToJwk(mPrivateKey.get(), jwk);
   if (NS_FAILED(rv)) {
     return false;
   }
--- a/dom/media/webrtc/RTCCertificate.h
+++ b/dom/media/webrtc/RTCCertificate.h
@@ -58,26 +58,22 @@ public:
   {
     return mExpires / PR_USEC_PER_MSEC;
   }
 
   // Accessors for use by PeerConnectionImpl.
   RefPtr<DtlsIdentity> CreateDtlsIdentity() const;
   const UniqueCERTCertificate& Certificate() const { return mCertificate; }
 
-  // For nsNSSShutDownObject
-  virtual void virtualDestroyNSSReference() override;
-  void destructorSafeDestroyNSSReference();
-
   // Structured clone methods
   bool WriteStructuredClone(JSStructuredCloneWriter* aWriter) const;
   bool ReadStructuredClone(JSStructuredCloneReader* aReader);
 
 private:
-  ~RTCCertificate();
+  ~RTCCertificate() {}
   void operator=(const RTCCertificate&) = delete;
   RTCCertificate(const RTCCertificate&) = delete;
 
   bool ReadCertificate(JSStructuredCloneReader* aReader);
   bool ReadPrivateKey(JSStructuredCloneReader* aReader);
   bool WriteCertificate(JSStructuredCloneWriter* aWriter) const;
   bool WritePrivateKey(JSStructuredCloneWriter* aWriter) const;
 
--- a/dom/webauthn/U2FSoftTokenManager.cpp
+++ b/dom/webauthn/U2FSoftTokenManager.cpp
@@ -63,34 +63,16 @@ enum SoftTokenHandle {
 
 }
 
 U2FSoftTokenManager::U2FSoftTokenManager(uint32_t aCounter)
   : mInitialized(false),
     mCounter(aCounter)
 {}
 
-U2FSoftTokenManager::~U2FSoftTokenManager()
-{
-  destructorSafeDestroyNSSReference();
-  shutdown(ShutdownCalledFrom::Object);
-}
-
-void
-U2FSoftTokenManager::virtualDestroyNSSReference()
-{
-  destructorSafeDestroyNSSReference();
-}
-
-void
-U2FSoftTokenManager::destructorSafeDestroyNSSReference()
-{
-  mWrappingKey = nullptr;
-}
-
 /**
  * Gets the first key with the given nickname from the given slot. Any other
  * keys found are not returned.
  * PK11_GetNextSymKey() should not be called on the returned key.
  *
  * @param aSlot Slot to search.
  * @param aNickname Nickname the key should have.
  * @return The first key found. nullptr if no key could be found.
--- a/dom/webauthn/U2FSoftTokenManager.h
+++ b/dom/webauthn/U2FSoftTokenManager.h
@@ -36,22 +36,18 @@ public:
   Sign(const nsTArray<WebAuthnScopedCredential>& aCredentials,
        const nsTArray<uint8_t>& aApplication,
        const nsTArray<uint8_t>& aChallenge,
        bool aRequireUserVerification,
        uint32_t aTimeoutMS) override;
 
   virtual void Cancel() override;
 
-  // For nsNSSShutDownObject
-  virtual void virtualDestroyNSSReference() override;
-  void destructorSafeDestroyNSSReference();
-
 private:
-  ~U2FSoftTokenManager();
+  ~U2FSoftTokenManager() {}
   nsresult Init();
 
   nsresult IsRegistered(const nsTArray<uint8_t>& aKeyHandle,
                         const nsTArray<uint8_t>& aAppParam,
                         bool& aResult);
 
   bool mInitialized;
   mozilla::UniquePK11SymKey mWrappingKey;
--- a/netwerk/base/BackgroundFileSaver.cpp
+++ b/netwerk/base/BackgroundFileSaver.cpp
@@ -113,30 +113,16 @@ BackgroundFileSaver::BackgroundFileSaver
 , mDigestContext(nullptr)
 {
   LOG(("Created BackgroundFileSaver [this = %p]", this));
 }
 
 BackgroundFileSaver::~BackgroundFileSaver()
 {
   LOG(("Destroying BackgroundFileSaver [this = %p]", this));
-  destructorSafeDestroyNSSReference();
-  shutdown(ShutdownCalledFrom::Object);
-}
-
-void
-BackgroundFileSaver::destructorSafeDestroyNSSReference()
-{
-  mDigestContext = nullptr;
-}
-
-void
-BackgroundFileSaver::virtualDestroyNSSReference()
-{
-  destructorSafeDestroyNSSReference();
 }
 
 // Called on the control thread.
 nsresult
 BackgroundFileSaver::Init()
 {
   MOZ_ASSERT(NS_IsMainThread(), "This should be called on the main thread");
 
@@ -1190,21 +1176,16 @@ DigestOutputStream::DigestOutputStream(n
                                        PK11Context* aContext) :
   mOutputStream(aStream)
   , mDigestContext(aContext)
 {
   MOZ_ASSERT(mDigestContext, "Can't have null digest context");
   MOZ_ASSERT(mOutputStream, "Can't have null output stream");
 }
 
-DigestOutputStream::~DigestOutputStream()
-{
-  shutdown(ShutdownCalledFrom::Object);
-}
-
 NS_IMETHODIMP
 DigestOutputStream::Close()
 {
   return mOutputStream->Close();
 }
 
 NS_IMETHODIMP
 DigestOutputStream::Flush()
--- a/netwerk/base/BackgroundFileSaver.h
+++ b/netwerk/base/BackgroundFileSaver.h
@@ -47,21 +47,16 @@ public:
    * Initializes the pipe and the worker thread on XPCOM construction.
    *
    * This is called automatically by the XPCOM infrastructure, and if this
    * fails, the factory will delete this object without returning a reference.
    */
   nsresult Init();
 
   /**
-   * Used by nsNSSShutDownList to manage nsNSSShutDownObjects.
-   */
-  void virtualDestroyNSSReference() override;
-
-  /**
    * Number of worker threads that are currently running.
    */
   static uint32_t sThreadCount;
 
   /**
    * Maximum number of worker threads reached during the current download session,
    * used for telemetry.
    *
@@ -70,21 +65,16 @@ public:
    */
   static uint32_t sTelemetryMaxThreadCount;
 
 
 protected:
   virtual ~BackgroundFileSaver();
 
   /**
-   * Helper function for managing NSS objects (mDigestContext).
-   */
-  void destructorSafeDestroyNSSReference();
-
-  /**
    * Thread that constructed this object.
    */
   nsCOMPtr<nsIEventTarget> mControlEventTarget;
 
   /**
    * Thread to which the actual input/output is delegated.
    */
   nsCOMPtr<nsIThread> mWorkerThread;
@@ -392,21 +382,18 @@ class DigestOutputStream : public nsNSSS
                            public nsIOutputStream
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIOUTPUTSTREAM
   // Constructor. Neither parameter may be null. The caller owns both.
   DigestOutputStream(nsIOutputStream* outputStream, PK11Context* aContext);
 
-  // We don't own any NSS objects here, so no need to clean up
-  void virtualDestroyNSSReference() override { }
-
 private:
-  ~DigestOutputStream();
+  ~DigestOutputStream() {}
 
   // Calls to write are passed to this stream.
   nsCOMPtr<nsIOutputStream> mOutputStream;
   // Digest context used to compute the hash, owned by the caller.
   PK11Context* mDigestContext;
 
   // Don't accidentally copy construct.
   DigestOutputStream(const DigestOutputStream& d);
--- a/security/apps/AppSignatureVerification.cpp
+++ b/security/apps/AppSignatureVerification.cpp
@@ -1411,20 +1411,16 @@ public:
 private:
   virtual nsresult CalculateResult() override
   {
     return OpenSignedAppFile(mTrustedRoot, mJarFile, mPolicy,
                              getter_AddRefs(mZipReader),
                              getter_AddRefs(mSignerCert));
   }
 
-  // nsNSSCertificate implements nsNSSShutdownObject, so there's nothing that
-  // needs to be released
-  virtual void ReleaseNSSResources() override { }
-
   virtual void CallCallback(nsresult rv) override
   {
     (void) mCallback->OpenSignedAppFileFinished(rv, mZipReader, mSignerCert);
   }
 
   const AppTrustedRoot mTrustedRoot;
   const nsCOMPtr<nsIFile> mJarFile;
   const SignaturePolicy mPolicy;
--- a/security/manager/ssl/ContentSignatureVerifier.cpp
+++ b/security/manager/ssl/ContentSignatureVerifier.cpp
@@ -37,22 +37,16 @@ using namespace mozilla::pkix;
 using namespace mozilla::psm;
 
 static LazyLogModule gCSVerifierPRLog("ContentSignatureVerifier");
 #define CSVerifier_LOG(args) MOZ_LOG(gCSVerifierPRLog, LogLevel::Debug, args)
 
 // Content-Signature prefix
 const nsLiteralCString kPREFIX = NS_LITERAL_CSTRING("Content-Signature:\x00");
 
-ContentSignatureVerifier::~ContentSignatureVerifier()
-{
-  destructorSafeDestroyNSSReference();
-  shutdown(ShutdownCalledFrom::Object);
-}
-
 NS_IMETHODIMP
 ContentSignatureVerifier::VerifyContentSignature(
   const nsACString& aData, const nsACString& aCSHeader,
   const nsACString& aCertChain, const nsACString& aName, bool* _retval)
 {
   NS_ENSURE_ARG(_retval);
   nsresult rv = CreateContext(aData, aCSHeader, aCertChain, aName);
   if (NS_FAILED(rv)) {
--- a/security/manager/ssl/ContentSignatureVerifier.h
+++ b/security/manager/ssl/ContentSignatureVerifier.h
@@ -37,37 +37,25 @@ public:
 
   ContentSignatureVerifier()
     : mCx(nullptr)
     , mInitialised(false)
     , mHasCertChain(false)
   {
   }
 
-  // nsNSSShutDownObject
-  virtual void virtualDestroyNSSReference() override
-  {
-    destructorSafeDestroyNSSReference();
-  }
-
 private:
-  ~ContentSignatureVerifier();
+  ~ContentSignatureVerifier() {}
 
   nsresult UpdateInternal(const nsACString& aData);
   nsresult DownloadCertChain();
   nsresult CreateContextInternal(const nsACString& aData,
                                  const nsACString& aCertChain,
                                  const nsACString& aName);
 
-  void destructorSafeDestroyNSSReference()
-  {
-    mCx = nullptr;
-    mKey = nullptr;
-  }
-
   nsresult ParseContentSignatureHeader(const nsACString& aContentSignatureHeader);
 
   // verifier context for incremental verifications
   mozilla::UniqueVFYContext mCx;
   bool mInitialised;
   // Indicates whether we hold a cert chain to verify the signature or not.
   // It's set by default in CreateContext or when the channel created in
   // DownloadCertChain finished. Update and End must only be called after
--- a/security/manager/ssl/CryptoTask.cpp
+++ b/security/manager/ssl/CryptoTask.cpp
@@ -4,23 +4,16 @@
  * 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/. */
 
 #include "CryptoTask.h"
 #include "nsNSSComponent.h"
 
 namespace mozilla {
 
-CryptoTask::~CryptoTask()
-{
-  MOZ_ASSERT(mReleasedNSSResources);
-
-  shutdown(ShutdownCalledFrom::Object);
-}
-
 nsresult
 CryptoTask::Dispatch(const nsACString& taskThreadName)
 {
   MOZ_ASSERT(taskThreadName.Length() <= 15);
 
   // Ensure that NSS is initialized, since presumably CalculateResult
   // will use NSS functions
   if (!EnsureNSSInitializedChromeOrContent()) {
@@ -43,24 +36,16 @@ NS_IMETHODIMP
 CryptoTask::Run()
 {
   if (!NS_IsMainThread()) {
     mRv = CalculateResult();
     NS_DispatchToMainThread(this);
   } else {
     // back on the main thread
 
-    // call ReleaseNSSResources now, before calling CallCallback, so that
-    // CryptoTasks have consistent behavior regardless of whether NSS is shut
-    // down between CalculateResult being called and CallCallback being called.
-    if (!mReleasedNSSResources) {
-      mReleasedNSSResources = true;
-      ReleaseNSSResources();
-    }
-
     CallCallback(mRv);
 
     // Not all uses of CryptoTask use a transient thread
     if (mThread) {
       // Don't leak threads!
       mThread->Shutdown(); // can't Shutdown from the thread itself, darn
       // Don't null out mThread!
       // See bug 999104.  We must hold a ref to the thread across Dispatch()
@@ -68,20 +53,9 @@ CryptoTask::Run()
       // the Dispatch(), and Dispatch/PutEvent itself doesn't hold a ref; it
       // assumes the caller does.
     }
   }
 
   return NS_OK;
 }
 
-void
-CryptoTask::virtualDestroyNSSReference()
-{
-  MOZ_ASSERT(NS_IsMainThread(),
-             "virtualDestroyNSSReference called off the main thread");
-  if (!mReleasedNSSResources) {
-    mReleasedNSSResources = true;
-    ReleaseNSSResources();
-  }
-}
-
 } // namespace mozilla
--- a/security/manager/ssl/CryptoTask.h
+++ b/security/manager/ssl/CryptoTask.h
@@ -14,93 +14,55 @@
 namespace mozilla {
 
 /**
  * Frequently we need to run a task on a background thread without blocking
  * the main thread, and then call a callback on the main thread with the
  * result. This class provides the framework for that. Subclasses must:
  *
  *   (1) Override CalculateResult for the off-the-main-thread computation.
- *       NSS functionality may only be accessed within CalculateResult.
- *   (2) Override ReleaseNSSResources to release references to all NSS
- *       resources (that do implement nsNSSShutDownObject themselves).
- *   (3) Override CallCallback() for the on-the-main-thread call of the
+ *   (2) Override CallCallback() for the on-the-main-thread call of the
  *       callback.
- *
- * CalculateResult, ReleaseNSSResources, and CallCallback are called in order,
- * except CalculateResult might be skipped if NSS is shut down before it can
- * be called; in that case ReleaseNSSResources will be called and then
- * CallCallback will be called with an error code.
- *
- * That sequence of events is what happens if you call Dispatch.  If for
- * some reason, you decide not to run the task (e.g., due to an error in the
- * constructor), you may call Skip, in which case the task is cleaned up and
- * not run.  In that case, only ReleaseNSSResources is called.  (So a
- * subclass must be prepared for ReleaseNSSResources to be run without
- * CalculateResult having been called first.)
- *
- * Once a CryptoTask is created, the calling code must call either
- * Dispatch or Skip.
- *
  */
 class CryptoTask : public Runnable,
                    public nsNSSShutDownObject
 {
 public:
   template <size_t LEN>
   nsresult Dispatch(const char (&taskThreadName)[LEN])
   {
     static_assert(LEN <= 15,
                   "Thread name must be no more than 15 characters");
     return Dispatch(nsDependentCString(taskThreadName, LEN - 1));
   }
 
   nsresult Dispatch(const nsACString& taskThreadName);
 
-  void Skip()
-  {
-    virtualDestroyNSSReference();
-  }
-
 protected:
   CryptoTask()
     : Runnable("CryptoTask")
     , mRv(NS_ERROR_NOT_INITIALIZED)
-    , mReleasedNSSResources(false)
   {
   }
 
-  virtual ~CryptoTask();
+  virtual ~CryptoTask() {}
 
   /**
-   * Called on a background thread (never the main thread). If CalculateResult
-   * is called, then its result will be passed to CallCallback on the main
-   * thread.
+   * Called on a background thread (never the main thread). Its result will be
+   * passed to CallCallback on the main thread.
    */
   virtual nsresult CalculateResult() = 0;
 
   /**
-   * Called on the main thread during NSS shutdown or just before CallCallback
-   * has been called. All NSS resources must be released. Usually, this just
-   * means assigning nullptr to the ScopedNSSType-based memory variables.
-   */
-  virtual void ReleaseNSSResources() = 0;
-
-  /**
-   * Called on the main thread with the result from CalculateResult() or
-   * with an error code if NSS was shut down before CalculateResult could
-   * be called.
+   * Called on the main thread with the result from CalculateResult().
    */
   virtual void CallCallback(nsresult rv) = 0;
 
 private:
   NS_IMETHOD Run() override final;
-  virtual void virtualDestroyNSSReference() override final;
 
   nsresult mRv;
-  bool mReleasedNSSResources;
-
   nsCOMPtr<nsIThread> mThread;
 };
 
 } // namespace mozilla
 
 #endif // mozilla__CryptoTask_h
--- a/security/manager/ssl/LocalCertService.cpp
+++ b/security/manager/ssl/LocalCertService.cpp
@@ -333,18 +333,16 @@ private:
     if (notBefore > now ||
         notAfter < (now - oneDay)) {
       return NS_ERROR_FAILURE;
     }
 
     return NS_OK;
   }
 
-  virtual void ReleaseNSSResources() override {}
-
   virtual void CallCallback(nsresult rv) override
   {
     (void) mCallback->HandleCert(mCert, rv);
   }
 
   nsMainThreadPtrHandle<nsILocalCertGetCallback> mCallback;
   nsCOMPtr<nsIX509Cert> mCert; // out
 };
@@ -361,18 +359,16 @@ public:
   }
 
 private:
   virtual nsresult CalculateResult() override
   {
     return RemoveExisting();
   }
 
-  virtual void ReleaseNSSResources() override {}
-
   virtual void CallCallback(nsresult rv) override
   {
     (void) mCallback->HandleResult(rv);
   }
 
   nsMainThreadPtrHandle<nsILocalCertCallback> mCallback;
 };
 
--- a/security/manager/ssl/PKCS11ModuleDB.cpp
+++ b/security/manager/ssl/PKCS11ModuleDB.cpp
@@ -14,25 +14,16 @@
 #include "nsNativeCharsetUtils.h"
 #include "nsPKCS11Slot.h"
 #include "nsServiceManagerUtils.h"
 
 namespace mozilla { namespace psm {
 
 NS_IMPL_ISUPPORTS(PKCS11ModuleDB, nsIPKCS11ModuleDB)
 
-PKCS11ModuleDB::PKCS11ModuleDB()
-{
-}
-
-PKCS11ModuleDB::~PKCS11ModuleDB()
-{
-  shutdown(ShutdownCalledFrom::Object);
-}
-
 // Delete a PKCS11 module from the user's profile.
 NS_IMETHODIMP
 PKCS11ModuleDB::DeleteModule(const nsAString& aModuleName)
 {
   if (aModuleName.IsEmpty()) {
     return NS_ERROR_INVALID_ARG;
   }
 
--- a/security/manager/ssl/PKCS11ModuleDB.h
+++ b/security/manager/ssl/PKCS11ModuleDB.h
@@ -16,26 +16,23 @@ namespace mozilla { namespace psm {
 #define NS_PKCS11MODULEDB_CID \
 { 0xff9fbcd7, 0x9517, 0x4334, \
   { 0xb9, 0x7a, 0xce, 0xed, 0x78, 0x90, 0x99, 0x74 }}
 
 class PKCS11ModuleDB : public nsIPKCS11ModuleDB
                      , public nsNSSShutDownObject
 {
 public:
-  PKCS11ModuleDB();
+  PKCS11ModuleDB() {}
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPKCS11MODULEDB
 
 protected:
-  virtual ~PKCS11ModuleDB();
-
-private:
-  virtual void virtualDestroyNSSReference() override {}
+  virtual ~PKCS11ModuleDB() {}
 };
 
 void GetModuleNameForTelemetry(/*in*/ const SECMODModule* module,
                                /*out*/nsString& result);
 
 } } // namespace mozilla::psm
 
 #endif // PKCS11ModuleDB_h
--- a/security/manager/ssl/SecretDecoderRing.cpp
+++ b/security/manager/ssl/SecretDecoderRing.cpp
@@ -55,25 +55,16 @@ void BackgroundSdrEncryptStrings(const n
                                aPromise->MaybeReject(rv);
                              } else {
                                aPromise->MaybeResolve(cipherTexts);
                              }
                            }));
   NS_DispatchToMainThread(runnable);
 }
 
-SecretDecoderRing::SecretDecoderRing()
-{
-}
-
-SecretDecoderRing::~SecretDecoderRing()
-{
-  shutdown(ShutdownCalledFrom::Object);
-}
-
 nsresult
 SecretDecoderRing::Encrypt(const nsACString& data, /*out*/ nsACString& result)
 {
   UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
   if (!slot) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
--- a/security/manager/ssl/SecretDecoderRing.h
+++ b/security/manager/ssl/SecretDecoderRing.h
@@ -18,22 +18,19 @@
 
 class SecretDecoderRing : public nsISecretDecoderRing
                         , public nsNSSShutDownObject
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSISECRETDECODERRING
 
-  SecretDecoderRing();
-
-  // Nothing to release.
-  virtual void virtualDestroyNSSReference() override {}
+  SecretDecoderRing() {}
 
 protected:
-  virtual ~SecretDecoderRing();
+  virtual ~SecretDecoderRing() {}
 
 private:
   nsresult Encrypt(const nsACString& data, /*out*/ nsACString& result);
   nsresult Decrypt(const nsACString& data, /*out*/ nsACString& result);
 };
 
 #endif // SecretDecoderRing_h
--- a/security/manager/ssl/TransportSecurityInfo.cpp
+++ b/security/manager/ssl/TransportSecurityInfo.cpp
@@ -43,26 +43,16 @@ TransportSecurityInfo::TransportSecurity
   , mSubRequestsBrokenSecurity(0)
   , mSubRequestsNoSecurity(0)
   , mErrorCode(0)
   , mErrorMessageType(SSLErrorMessageType::Plain)
   , mPort(0)
 {
 }
 
-TransportSecurityInfo::~TransportSecurityInfo()
-{
-  shutdown(ShutdownCalledFrom::Object);
-}
-
-void
-TransportSecurityInfo::virtualDestroyNSSReference()
-{
-}
-
 NS_IMPL_ISUPPORTS(TransportSecurityInfo,
                   nsITransportSecurityInfo,
                   nsIInterfaceRequestor,
                   nsISSLStatusProvider,
                   nsIAssociatedContentSecurity,
                   nsISerializable,
                   nsIClassInfo)
 
--- a/security/manager/ssl/TransportSecurityInfo.h
+++ b/security/manager/ssl/TransportSecurityInfo.h
@@ -34,17 +34,17 @@ class TransportSecurityInfo : public nsI
                             , public nsIInterfaceRequestor
                             , public nsISSLStatusProvider
                             , public nsIAssociatedContentSecurity
                             , public nsISerializable
                             , public nsIClassInfo
                             , public nsNSSShutDownObject
 {
 protected:
-  virtual ~TransportSecurityInfo();
+  virtual ~TransportSecurityInfo() {}
 public:
   TransportSecurityInfo();
 
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSITRANSPORTSECURITYINFO
   NS_DECL_NSIINTERFACEREQUESTOR
   NS_DECL_NSISSLSTATUSPROVIDER
   NS_DECL_NSIASSOCIATEDCONTENTSECURITY
@@ -103,19 +103,16 @@ private:
   nsCString mHostName;
   OriginAttributes mOriginAttributes;
 
   /* SSL Status */
   RefPtr<nsSSLStatus> mSSLStatus;
 
   /* Peer cert chain for failed connections (for error reporting) */
   nsCOMPtr<nsIX509CertList> mFailedCertChain;
-
-  virtual void virtualDestroyNSSReference() override;
-  void destructorSafeDestroyNSSReference();
 };
 
 class RememberCertErrorsTable
 {
 private:
   RememberCertErrorsTable();
 
   struct CertStateBits
--- a/security/manager/ssl/nsCryptoHash.cpp
+++ b/security/manager/ssl/nsCryptoHash.cpp
@@ -31,34 +31,16 @@ static const uint64_t STREAM_BUFFER_SIZE
 //---------------------------------------------
 
 nsCryptoHash::nsCryptoHash()
   : mHashContext(nullptr)
   , mInitialized(false)
 {
 }
 
-nsCryptoHash::~nsCryptoHash()
-{
-  destructorSafeDestroyNSSReference();
-  shutdown(ShutdownCalledFrom::Object);
-}
-
-void
-nsCryptoHash::virtualDestroyNSSReference()
-{
-  destructorSafeDestroyNSSReference();
-}
-
-void
-nsCryptoHash::destructorSafeDestroyNSSReference()
-{
-  mHashContext = nullptr;
-}
-
 NS_IMPL_ISUPPORTS(nsCryptoHash, nsICryptoHash)
 
 NS_IMETHODIMP
 nsCryptoHash::Init(uint32_t algorithm)
 {
   HASH_HashType hashType;
   switch (algorithm) {
     case nsICryptoHash::MD2:
@@ -215,34 +197,16 @@ nsCryptoHash::Finish(bool ascii, nsACStr
 
 NS_IMPL_ISUPPORTS(nsCryptoHMAC, nsICryptoHMAC)
 
 nsCryptoHMAC::nsCryptoHMAC()
   : mHMACContext(nullptr)
 {
 }
 
-nsCryptoHMAC::~nsCryptoHMAC()
-{
-  destructorSafeDestroyNSSReference();
-  shutdown(ShutdownCalledFrom::Object);
-}
-
-void
-nsCryptoHMAC::virtualDestroyNSSReference()
-{
-  destructorSafeDestroyNSSReference();
-}
-
-void
-nsCryptoHMAC::destructorSafeDestroyNSSReference()
-{
-  mHMACContext = nullptr;
-}
-
 NS_IMETHODIMP
 nsCryptoHMAC::Init(uint32_t aAlgorithm, nsIKeyObject *aKeyObject)
 {
   if (mHMACContext) {
     mHMACContext = nullptr;
   }
 
   CK_MECHANISM_TYPE mechType;
--- a/security/manager/ssl/nsCryptoHash.h
+++ b/security/manager/ssl/nsCryptoHash.h
@@ -23,34 +23,28 @@ class nsCryptoHash final : public nsICry
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSICRYPTOHASH
 
   nsCryptoHash();
 
 private:
-  ~nsCryptoHash();
+  ~nsCryptoHash() {}
 
   mozilla::UniqueHASHContext mHashContext;
   bool mInitialized;
-
-  virtual void virtualDestroyNSSReference() override;
-  void destructorSafeDestroyNSSReference();
 };
 
 class nsCryptoHMAC : public nsICryptoHMAC, public nsNSSShutDownObject
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSICRYPTOHMAC
 
   nsCryptoHMAC();
 
 private:
-  ~nsCryptoHMAC();
+  ~nsCryptoHMAC() {}
   mozilla::UniquePK11Context mHMACContext;
-
-  virtual void virtualDestroyNSSReference() override;
-  void destructorSafeDestroyNSSReference();
 };
 
 #endif // nsCryptoHash_h
--- a/security/manager/ssl/nsDataSignatureVerifier.cpp
+++ b/security/manager/ssl/nsDataSignatureVerifier.cpp
@@ -24,21 +24,16 @@ const SEC_ASN1Template CERT_SignatureDat
     { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
         offsetof(CERTSignedData,signatureAlgorithm),
         SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate), },
     { SEC_ASN1_BIT_STRING,
         offsetof(CERTSignedData,signature), },
     { 0, }
 };
 
-nsDataSignatureVerifier::~nsDataSignatureVerifier()
-{
-  shutdown(ShutdownCalledFrom::Object);
-}
-
 NS_IMETHODIMP
 nsDataSignatureVerifier::VerifyData(const nsACString& aData,
                                     const nsACString& aSignature,
                                     const nsACString& aPublicKey,
                                     bool* _retval)
 {
   NS_ENSURE_ARG_POINTER(_retval);
 
--- a/security/manager/ssl/nsDataSignatureVerifier.h
+++ b/security/manager/ssl/nsDataSignatureVerifier.h
@@ -16,20 +16,15 @@
 
 class nsDataSignatureVerifier final : public nsIDataSignatureVerifier
                                     , public nsNSSShutDownObject
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDATASIGNATUREVERIFIER
 
-  nsDataSignatureVerifier()
-  {
-  }
+  nsDataSignatureVerifier() {}
 
 private:
-  ~nsDataSignatureVerifier();
-
-  // Nothing to release.
-  virtual void virtualDestroyNSSReference() override {}
+  ~nsDataSignatureVerifier() {}
 };
 
 #endif // nsDataSignatureVerifier_h
--- a/security/manager/ssl/nsKeyModule.cpp
+++ b/security/manager/ssl/nsKeyModule.cpp
@@ -12,34 +12,16 @@ using namespace mozilla::psm;
 
 NS_IMPL_ISUPPORTS(nsKeyObject, nsIKeyObject)
 
 nsKeyObject::nsKeyObject()
   : mSymKey(nullptr)
 {
 }
 
-nsKeyObject::~nsKeyObject()
-{
-  destructorSafeDestroyNSSReference();
-  shutdown(ShutdownCalledFrom::Object);
-}
-
-void
-nsKeyObject::virtualDestroyNSSReference()
-{
-  destructorSafeDestroyNSSReference();
-}
-
-void
-nsKeyObject::destructorSafeDestroyNSSReference()
-{
-  mSymKey = nullptr;
-}
-
 //////////////////////////////////////////////////////////////////////////////
 // nsIKeyObject
 
 NS_IMETHODIMP
 nsKeyObject::InitKey(int16_t aAlgorithm, PK11SymKey* aKey)
 {
   if (!aKey || aAlgorithm != nsIKeyObject::HMAC) {
     return NS_ERROR_INVALID_ARG;
@@ -76,25 +58,16 @@ nsKeyObject::GetType(int16_t *_retval)
   return NS_OK;
 }
 
 //////////////////////////////////////////////////////////////////////////////
 // nsIKeyObjectFactory
 
 NS_IMPL_ISUPPORTS(nsKeyObjectFactory, nsIKeyObjectFactory)
 
-nsKeyObjectFactory::nsKeyObjectFactory()
-{
-}
-
-nsKeyObjectFactory::~nsKeyObjectFactory()
-{
-  shutdown(ShutdownCalledFrom::Object);
-}
-
 NS_IMETHODIMP
 nsKeyObjectFactory::KeyFromString(int16_t aAlgorithm, const nsACString& aKey,
                                   nsIKeyObject** _retval)
 {
   if (!_retval || aAlgorithm != nsIKeyObject::HMAC) {
     return NS_ERROR_INVALID_ARG;
   }
 
--- a/security/manager/ssl/nsKeyModule.h
+++ b/security/manager/ssl/nsKeyModule.h
@@ -24,40 +24,34 @@ class nsKeyObject final : public nsIKeyO
 {
 public:
   nsKeyObject();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIKEYOBJECT
 
 private:
-  ~nsKeyObject();
+  ~nsKeyObject() {}
 
   // Disallow copy constructor
   nsKeyObject(nsKeyObject&);
 
   UniquePK11SymKey mSymKey;
-
-  virtual void virtualDestroyNSSReference() override;
-  void destructorSafeDestroyNSSReference();
 };
 
 
 class nsKeyObjectFactory final : public nsIKeyObjectFactory
                                , public nsNSSShutDownObject
 {
 public:
-  nsKeyObjectFactory();
+  nsKeyObjectFactory() {}
 
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIKEYOBJECTFACTORY
 
 private:
-  ~nsKeyObjectFactory();
+  ~nsKeyObjectFactory() {}
 
   // Disallow copy constructor
   nsKeyObjectFactory(nsKeyObjectFactory&);
-
-  // No NSS resources to release.
-  virtual void virtualDestroyNSSReference() override {}
 };
 
 #endif // nsKeyModule_h
--- a/security/manager/ssl/nsKeygenHandler.cpp
+++ b/security/manager/ssl/nsKeygenHandler.cpp
@@ -215,21 +215,16 @@ DecodeECParams(const char* curve)
 
 NS_IMPL_ISUPPORTS(nsKeygenFormProcessor, nsIFormProcessor)
 
 nsKeygenFormProcessor::nsKeygenFormProcessor()
 {
    m_ctx = new PipUIContext();
 }
 
-nsKeygenFormProcessor::~nsKeygenFormProcessor()
-{
-  shutdown(ShutdownCalledFrom::Object);
-}
-
 nsresult
 nsKeygenFormProcessor::Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult)
 {
   if (GeckoProcessType_Content == XRE_GetProcessType()) {
     nsCOMPtr<nsISupports> contentProcessor = new nsKeygenFormProcessorContent();
     return contentProcessor->QueryInterface(aIID, aResult);
   }
 
--- a/security/manager/ssl/nsKeygenHandler.h
+++ b/security/manager/ssl/nsKeygenHandler.h
@@ -51,21 +51,18 @@ public:
 
   static nsresult Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult);
 
   static void ExtractParams(mozilla::dom::Element* aElement,
                             nsAString& challengeValue,
                             nsAString& keyTypeValue,
                             nsAString& keyParamsValue);
 
-  // Nothing to release.
-  virtual void virtualDestroyNSSReference() override {}
-
 protected:
-  virtual ~nsKeygenFormProcessor();
+  virtual ~nsKeygenFormProcessor() {}
 
   nsresult GetPublicKey(const nsAString& aValue, const nsAString& aChallenge,
                         const nsString& akeyType, nsAString& aOutPublicKey,
                         const nsAString& aPqg);
   nsresult GetSlot(uint32_t aMechanism, PK11SlotInfo** aSlot);
 private:
   nsCOMPtr<nsIInterfaceRequestor> m_ctx;
 
--- a/security/manager/ssl/nsNSSCallbacks.cpp
+++ b/security/manager/ssl/nsNSSCallbacks.cpp
@@ -734,33 +734,25 @@ class PK11PasswordPromptRunnable : publi
 public:
   PK11PasswordPromptRunnable(PK11SlotInfo* slot,
                              nsIInterfaceRequestor* ir)
     : mResult(nullptr),
       mSlot(slot),
       mIR(ir)
   {
   }
-  virtual ~PK11PasswordPromptRunnable();
+  virtual ~PK11PasswordPromptRunnable() = default;
 
-  // This doesn't own the PK11SlotInfo or any other NSS objects, so there's
-  // nothing to release.
-  virtual void virtualDestroyNSSReference() override {}
   char * mResult; // out
   virtual void RunOnTargetThread() override;
 private:
   PK11SlotInfo* const mSlot; // in
   nsIInterfaceRequestor* const mIR; // in
 };
 
-PK11PasswordPromptRunnable::~PK11PasswordPromptRunnable()
-{
-  shutdown(ShutdownCalledFrom::Object);
-}
-
 void
 PK11PasswordPromptRunnable::RunOnTargetThread()
 {
   nsresult rv;
   nsCOMPtr<nsIPrompt> prompt;
   if (!mIR) {
     rv = nsNSSComponent::GetNewPrompter(getter_AddRefs(prompt));
     if (NS_FAILED(rv)) {
--- a/security/manager/ssl/nsNSSCertValidity.cpp
+++ b/security/manager/ssl/nsNSSCertValidity.cpp
@@ -22,21 +22,16 @@ nsX509CertValidity::nsX509CertValidity(c
     return;
   }
 
   if (CERT_GetCertTimes(cert.get(), &mNotBefore, &mNotAfter) == SECSuccess) {
     mTimesInitialized = true;
   }
 }
 
-nsX509CertValidity::~nsX509CertValidity()
-{
-  shutdown(ShutdownCalledFrom::Object);
-}
-
 NS_IMETHODIMP
 nsX509CertValidity::GetNotBefore(PRTime* aNotBefore)
 {
   NS_ENSURE_ARG(aNotBefore);
 
   if (!mTimesInitialized) {
     return NS_ERROR_FAILURE;
   }
--- a/security/manager/ssl/nsNSSCertValidity.h
+++ b/security/manager/ssl/nsNSSCertValidity.h
@@ -15,20 +15,17 @@ class nsX509CertValidity : public nsIX50
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIX509CERTVALIDITY
 
   explicit nsX509CertValidity(const mozilla::UniqueCERTCertificate& cert);
 
 protected:
-  virtual ~nsX509CertValidity();
-
-  // Nothing to release.
-  virtual void virtualDestroyNSSReference() override {}
+  virtual ~nsX509CertValidity() {}
 
 private:
   nsresult FormatTime(const PRTime& aTime,
                       PRTimeParamFn aParamFn,
                       const nsTimeFormatSelector aTimeFormatSelector,
                       nsAString& aFormattedTimeDate);
 
   PRTime mNotBefore;
--- a/security/manager/ssl/nsNSSCertificate.cpp
+++ b/security/manager/ssl/nsNSSCertificate.cpp
@@ -121,40 +121,27 @@ nsNSSCertificate::nsNSSCertificate()
   : mCert(nullptr)
   , mPermDelete(false)
   , mCertType(CERT_TYPE_NOT_YET_INITIALIZED)
 {
 }
 
 nsNSSCertificate::~nsNSSCertificate()
 {
-  destructorSafeDestroyNSSReference();
-  shutdown(ShutdownCalledFrom::Object);
-}
-
-void nsNSSCertificate::virtualDestroyNSSReference()
-{
-  destructorSafeDestroyNSSReference();
-}
-
-void nsNSSCertificate::destructorSafeDestroyNSSReference()
-{
   if (mPermDelete) {
     if (mCertType == nsNSSCertificate::USER_CERT) {
       nsCOMPtr<nsIInterfaceRequestor> cxt = new PipUIContext();
       PK11_DeleteTokenCertAndKey(mCert.get(), cxt);
     } else if (mCert->slot && !PK11_IsReadOnly(mCert->slot)) {
       // If the list of built-ins does contain a non-removable
       // copy of this certificate, our call will not remove
       // the certificate permanently, but rather remove all trust.
       SEC_DeletePermCertificate(mCert.get());
     }
   }
-
-  mCert = nullptr;
 }
 
 nsresult
 nsNSSCertificate::GetCertType(uint32_t* aCertType)
 {
   if (mCertType == CERT_TYPE_NOT_YET_INITIALIZED) {
      // only determine cert type once and cache it
      mCertType = getCertType(mCert.get());
@@ -993,32 +980,16 @@ nsNSSCertList::nsNSSCertList(UniqueCERTC
   }
 }
 
 nsNSSCertList::nsNSSCertList()
 {
   mCertList = UniqueCERTCertList(CERT_NewCertList());
 }
 
-nsNSSCertList::~nsNSSCertList()
-{
-  destructorSafeDestroyNSSReference();
-  shutdown(ShutdownCalledFrom::Object);
-}
-
-void nsNSSCertList::virtualDestroyNSSReference()
-{
-  destructorSafeDestroyNSSReference();
-}
-
-void nsNSSCertList::destructorSafeDestroyNSSReference()
-{
-  mCertList = nullptr;
-}
-
 nsNSSCertList*
 nsNSSCertList::GetCertList()
 {
   return this;
 }
 
 NS_IMETHODIMP
 nsNSSCertList::AddCert(nsIX509Cert* aCert)
@@ -1308,32 +1279,16 @@ NS_IMPL_ISUPPORTS(nsNSSCertListEnumerato
 
 nsNSSCertListEnumerator::nsNSSCertListEnumerator(
   const UniqueCERTCertList& certList)
 {
   MOZ_ASSERT(certList);
   mCertList = nsNSSCertList::DupCertList(certList);
 }
 
-nsNSSCertListEnumerator::~nsNSSCertListEnumerator()
-{
-  destructorSafeDestroyNSSReference();
-  shutdown(ShutdownCalledFrom::Object);
-}
-
-void nsNSSCertListEnumerator::virtualDestroyNSSReference()
-{
-  destructorSafeDestroyNSSReference();
-}
-
-void nsNSSCertListEnumerator::destructorSafeDestroyNSSReference()
-{
-  mCertList = nullptr;
-}
-
 NS_IMETHODIMP
 nsNSSCertListEnumerator::HasMoreElements(bool* _retval)
 {
   NS_ENSURE_TRUE(mCertList, NS_ERROR_FAILURE);
 
   *_retval = !CERT_LIST_EMPTY(mCertList);
   return NS_OK;
 }
--- a/security/manager/ssl/nsNSSCertificate.h
+++ b/security/manager/ssl/nsNSSCertificate.h
@@ -51,18 +51,16 @@ private:
   virtual ~nsNSSCertificate();
 
   mozilla::UniqueCERTCertificate mCert;
   bool             mPermDelete;
   uint32_t         mCertType;
   nsresult CreateASN1Struct(nsIASN1Object** aRetVal);
   nsresult CreateTBSCertificateASN1Struct(nsIASN1Sequence** retSequence);
   nsresult GetSortableDate(PRTime aTime, nsAString& _aSortableDate);
-  virtual void virtualDestroyNSSReference() override;
-  void destructorSafeDestroyNSSReference();
   bool InitFromDER(char* certDER, int derLen);  // return false on failure
 
   nsresult GetCertificateHash(nsAString& aFingerprint, SECOidTag aHashAlg);
 };
 
 namespace mozilla {
 
 SECStatus ConstructCERTCertListFromReversedDERArray(
@@ -107,38 +105,34 @@ public:
   // Will return error if used on self-signed or empty chains.
   // This method requires that all arguments be empty, notably the list
   // `aIntermediates` must be empty.
   nsresult SegmentCertificateChain(/* out */ nsCOMPtr<nsIX509Cert>& aRoot,
                            /* out */ nsCOMPtr<nsIX509CertList>& aIntermediates,
                            /* out */ nsCOMPtr<nsIX509Cert>& aEndEntity);
 
 private:
-   virtual ~nsNSSCertList();
-   virtual void virtualDestroyNSSReference() override;
-   void destructorSafeDestroyNSSReference();
+   virtual ~nsNSSCertList() {}
 
    mozilla::UniqueCERTCertList mCertList;
 
    nsNSSCertList(const nsNSSCertList&) = delete;
    void operator=(const nsNSSCertList&) = delete;
 };
 
 class nsNSSCertListEnumerator: public nsISimpleEnumerator,
                                public nsNSSShutDownObject
 {
 public:
    NS_DECL_THREADSAFE_ISUPPORTS
    NS_DECL_NSISIMPLEENUMERATOR
 
    explicit nsNSSCertListEnumerator(const mozilla::UniqueCERTCertList& certList);
 private:
-   virtual ~nsNSSCertListEnumerator();
-   virtual void virtualDestroyNSSReference() override;
-   void destructorSafeDestroyNSSReference();
+   virtual ~nsNSSCertListEnumerator() {}
 
    mozilla::UniqueCERTCertList mCertList;
 
    nsNSSCertListEnumerator(const nsNSSCertListEnumerator&) = delete;
    void operator=(const nsNSSCertListEnumerator&) = delete;
 };
 
 #define NS_X509CERT_CID { /* 660a3226-915c-4ffb-bb20-8985a632df05 */   \
--- a/security/manager/ssl/nsNSSCertificateDB.cpp
+++ b/security/manager/ssl/nsNSSCertificateDB.cpp
@@ -52,21 +52,16 @@
 using namespace mozilla;
 using namespace mozilla::psm;
 using mozilla::psm::SharedSSLState;
 
 extern LazyLogModule gPIPNSSLog;
 
 NS_IMPL_ISUPPORTS(nsNSSCertificateDB, nsIX509CertDB)
 
-nsNSSCertificateDB::~nsNSSCertificateDB()
-{
-  shutdown(ShutdownCalledFrom::Object);
-}
-
 NS_IMETHODIMP
 nsNSSCertificateDB::FindCertByDBKey(const nsACString& aDBKey,
                             /*out*/ nsIX509Cert** _cert)
 {
   NS_ENSURE_ARG_POINTER(_cert);
   *_cert = nullptr;
 
   if (aDBKey.IsEmpty()) {
@@ -1367,19 +1362,16 @@ private:
     if (!certDB) {
       return NS_ERROR_FAILURE;
     }
     return certDB->VerifyCertAtTime(mCert, mUsage, mFlags, mHostname, mTime,
                                     getter_AddRefs(mVerifiedCertList),
                                     &mHasEVPolicy, &mPRErrorCode);
   }
 
-  // No NSS resources are directly held, so there is nothing to release.
-  virtual void ReleaseNSSResources() override { }
-
   virtual void CallCallback(nsresult rv) override
   {
     if (NS_FAILED(rv)) {
       Unused << mCallback->VerifyCertFinished(SEC_ERROR_LIBRARY_FAILURE,
                                               nullptr, false);
     } else {
       Unused << mCallback->VerifyCertFinished(mPRErrorCode, mVerifiedCertList,
                                               mHasEVPolicy);
--- a/security/manager/ssl/nsNSSCertificateDB.h
+++ b/security/manager/ssl/nsNSSCertificateDB.h
@@ -26,17 +26,17 @@ public:
   NS_DECL_NSIX509CERTDB
 
   // This is a separate static method so nsNSSComponent can use it during NSS
   // initialization. Other code should probably not use it.
   static nsresult
   FindCertByDBKey(const nsACString& aDBKey, mozilla::UniqueCERTCertificate& cert);
 
 protected:
-  virtual ~nsNSSCertificateDB();
+  virtual ~nsNSSCertificateDB() {}
 
 private:
   // Use this function to generate a default nickname for a user
   // certificate that is to be imported onto a token.
   static void
   get_default_nickname(CERTCertificate* cert, nsIInterfaceRequestor* ctx,
                        nsCString& nickname);
 
@@ -46,19 +46,16 @@ private:
   static void DisplayCertificateAlert(nsIInterfaceRequestor* ctx,
                                       const char* stringID,
                                       nsIX509Cert* certToShow);
 
   CERTDERCerts* getCertsFromPackage(const mozilla::UniquePLArenaPool& arena,
                                     uint8_t* data, uint32_t length);
   nsresult handleCACertDownload(mozilla::NotNull<nsIArray*> x509Certs,
                                 nsIInterfaceRequestor* ctx);
-
-  // We don't own any NSS objects here, so no need to clean up
-  virtual void virtualDestroyNSSReference() override { };
 };
 
 #define NS_X509CERTDB_CID { /* fb0bbc5c-452e-4783-b32c-80124693d871 */ \
     0xfb0bbc5c,                                                        \
     0x452e,                                                            \
     0x4783,                                                            \
     {0xb3, 0x2c, 0x80, 0x12, 0x46, 0x93, 0xd8, 0x71}                   \
   }
--- a/security/manager/ssl/nsNSSComponent.cpp
+++ b/security/manager/ssl/nsNSSComponent.cpp
@@ -978,34 +978,27 @@ class LoadLoadableRootsTask final : publ
 public:
   explicit LoadLoadableRootsTask(nsNSSComponent* nssComponent)
     : Runnable("LoadLoadableRootsTask")
     , mNSSComponent(nssComponent)
   {
     MOZ_ASSERT(nssComponent);
   }
 
-  ~LoadLoadableRootsTask();
+  ~LoadLoadableRootsTask() = default;
 
   nsresult Dispatch();
 
-  void virtualDestroyNSSReference() override {} // nothing to release
-
 private:
   NS_IMETHOD Run() override;
   nsresult LoadLoadableRoots();
   RefPtr<nsNSSComponent> mNSSComponent;
   nsCOMPtr<nsIThread> mThread;
 };
 
-LoadLoadableRootsTask::~LoadLoadableRootsTask()
-{
-  shutdown(ShutdownCalledFrom::Object);
-}
-
 nsresult
 LoadLoadableRootsTask::Dispatch()
 {
   // Can't add 'this' as the event to run, since mThread may not be set yet
   nsresult rv = NS_NewNamedThread("LoadRoots", getter_AddRefs(mThread),
                                   nullptr,
                                   nsIThreadManager::DEFAULT_STACK_SIZE);
   if (NS_FAILED(rv)) {
--- a/security/manager/ssl/nsNSSShutDown.h
+++ b/security/manager/ssl/nsNSSShutDown.h
@@ -8,24 +8,13 @@
 // This is the vestigial remains of the old NSS shutdown tracking
 // infrastructure. It will be removed entirely in bug 1421084 when we've
 // demonstrated that shutting down NSS only when all non-main-threads have been
 // joined is feasible (and beneficial).
 
 class nsNSSShutDownObject
 {
 public:
-  enum class ShutdownCalledFrom {
-    List,
-    Object,
-  };
-
   nsNSSShutDownObject() {}
-
   virtual ~nsNSSShutDownObject() {}
-
-  void shutdown(ShutdownCalledFrom) {}
-
-protected:
-  virtual void virtualDestroyNSSReference() = 0;
 };
 
 #endif // nsNSSShutDown_h
--- a/security/manager/ssl/nsPK11TokenDB.cpp
+++ b/security/manager/ssl/nsPK11TokenDB.cpp
@@ -73,34 +73,16 @@ nsPK11Token::refreshTokenInfo()
     mozilla::BitwiseCast<char*, CK_CHAR*>(tokInfo.serialNumber);
   mTokenSerialNum.Assign(ccSerial,
                          strnlen(ccSerial, sizeof(tokInfo.serialNumber)));
   mTokenSerialNum.Trim(" ", false, true);
 
   return NS_OK;
 }
 
-nsPK11Token::~nsPK11Token()
-{
-  destructorSafeDestroyNSSReference();
-  shutdown(ShutdownCalledFrom::Object);
-}
-
-void
-nsPK11Token::virtualDestroyNSSReference()
-{
-  destructorSafeDestroyNSSReference();
-}
-
-void
-nsPK11Token::destructorSafeDestroyNSSReference()
-{
-  mSlot = nullptr;
-}
-
 nsresult
 nsPK11Token::GetAttributeHelper(const nsACString& attribute,
                         /*out*/ nsACString& xpcomOutParam)
 {
   // Handle removals/insertions.
   if (PK11_GetSlotSeries(mSlot.get()) != mSeries) {
     nsresult rv = refreshTokenInfo();
     if (NS_FAILED(rv)) {
@@ -283,25 +265,16 @@ nsPK11Token::NeedsLogin(bool* _retval)
   *_retval = PK11_NeedLogin(mSlot.get());
   return NS_OK;
 }
 
 /*=========================================================*/
 
 NS_IMPL_ISUPPORTS(nsPK11TokenDB, nsIPK11TokenDB)
 
-nsPK11TokenDB::nsPK11TokenDB()
-{
-}
-
-nsPK11TokenDB::~nsPK11TokenDB()
-{
-  shutdown(ShutdownCalledFrom::Object);
-}
-
 NS_IMETHODIMP
 nsPK11TokenDB::GetInternalKeyToken(nsIPK11Token** _retval)
 {
   NS_ENSURE_ARG_POINTER(_retval);
   UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
   if (!slot) {
     return NS_ERROR_FAILURE;
   }
--- a/security/manager/ssl/nsPK11TokenDB.h
+++ b/security/manager/ssl/nsPK11TokenDB.h
@@ -22,50 +22,45 @@ class nsPK11Token : public nsIPK11Token,
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPK11TOKEN
 
   explicit nsPK11Token(PK11SlotInfo *slot);
 
 protected:
-  virtual ~nsPK11Token();
+  virtual ~nsPK11Token() {}
 
 private:
   friend class nsPK11TokenDB;
   nsresult refreshTokenInfo();
 
   nsCString mTokenName;
   nsCString mTokenLabel;
   nsCString mTokenManufacturerID;
   nsCString mTokenHWVersion;
   nsCString mTokenFWVersion;
   nsCString mTokenSerialNum;
   mozilla::UniquePK11SlotInfo mSlot;
   int mSeries;
   nsCOMPtr<nsIInterfaceRequestor> mUIContext;
-  virtual void virtualDestroyNSSReference() override;
-  void destructorSafeDestroyNSSReference();
   nsresult GetAttributeHelper(const nsACString& attribute,
                       /*out*/ nsACString& xpcomOutParam);
 };
 
 class nsPK11TokenDB : public nsIPK11TokenDB
                     , public nsNSSShutDownObject
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPK11TOKENDB
 
-  nsPK11TokenDB();
+  nsPK11TokenDB() {}
 
 protected:
-  virtual ~nsPK11TokenDB();
-
-  // Nothing to release.
-  virtual void virtualDestroyNSSReference() override {}
+  virtual ~nsPK11TokenDB() {}
 };
 
 #define NS_PK11TOKENDB_CID \
 { 0xb084a2ce, 0x1dd1, 0x11b2, \
   { 0xbf, 0x10, 0x83, 0x24, 0xf8, 0xe0, 0x65, 0xcc }}
 
 #endif // nsPK11TokenDB_h
--- a/security/manager/ssl/nsPKCS11Slot.cpp
+++ b/security/manager/ssl/nsPKCS11Slot.cpp
@@ -64,34 +64,16 @@ nsPKCS11Slot::refreshSlotInfo()
   mSlotFWVersion.Truncate();
   mSlotFWVersion.AppendInt(slotInfo.firmwareVersion.major);
   mSlotFWVersion.Append('.');
   mSlotFWVersion.AppendInt(slotInfo.firmwareVersion.minor);
 
   return NS_OK;
 }
 
-nsPKCS11Slot::~nsPKCS11Slot()
-{
-  destructorSafeDestroyNSSReference();
-  shutdown(ShutdownCalledFrom::Object);
-}
-
-void
-nsPKCS11Slot::virtualDestroyNSSReference()
-{
-  destructorSafeDestroyNSSReference();
-}
-
-void
-nsPKCS11Slot::destructorSafeDestroyNSSReference()
-{
-  mSlot = nullptr;
-}
-
 nsresult
 nsPKCS11Slot::GetAttributeHelper(const nsACString& attribute,
                          /*out*/ nsACString& xpcomOutParam)
 {
   if (PK11_GetSlotSeries(mSlot.get()) != mSeries) {
     nsresult rv = refreshSlotInfo();
     if (NS_FAILED(rv)) {
       return rv;
@@ -198,34 +180,16 @@ nsPKCS11Slot::GetStatus(uint32_t* _retva
 NS_IMPL_ISUPPORTS(nsPKCS11Module, nsIPKCS11Module)
 
 nsPKCS11Module::nsPKCS11Module(SECMODModule* module)
 {
   MOZ_ASSERT(module);
   mModule.reset(SECMOD_ReferenceModule(module));
 }
 
-nsPKCS11Module::~nsPKCS11Module()
-{
-  destructorSafeDestroyNSSReference();
-  shutdown(ShutdownCalledFrom::Object);
-}
-
-void
-nsPKCS11Module::virtualDestroyNSSReference()
-{
-  destructorSafeDestroyNSSReference();
-}
-
-void
-nsPKCS11Module::destructorSafeDestroyNSSReference()
-{
-  mModule = nullptr;
-}
-
 NS_IMETHODIMP
 nsPKCS11Module::GetName(/*out*/ nsACString& name)
 {
   name = mModule->commonName;
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/security/manager/ssl/nsPKCS11Slot.h
+++ b/security/manager/ssl/nsPKCS11Slot.h
@@ -20,45 +20,40 @@ class nsPKCS11Slot : public nsIPKCS11Slo
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPKCS11SLOT
 
   explicit nsPKCS11Slot(PK11SlotInfo* slot);
 
 protected:
-  virtual ~nsPKCS11Slot();
+  virtual ~nsPKCS11Slot() {}
 
 private:
   mozilla::UniquePK11SlotInfo mSlot;
   nsCString mSlotDesc;
   nsCString mSlotManufacturerID;
   nsCString mSlotHWVersion;
   nsCString mSlotFWVersion;
   int mSeries;
 
-  virtual void virtualDestroyNSSReference() override;
-  void destructorSafeDestroyNSSReference();
   nsresult refreshSlotInfo();
   nsresult GetAttributeHelper(const nsACString& attribute,
                       /*out*/ nsACString& xpcomOutParam);
 };
 
 class nsPKCS11Module : public nsIPKCS11Module,
                        public nsNSSShutDownObject
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPKCS11MODULE
 
   explicit nsPKCS11Module(SECMODModule* module);
 
 protected:
-  virtual ~nsPKCS11Module();
+  virtual ~nsPKCS11Module() {}
 
 private:
   mozilla::UniqueSECMODModule mModule;
-
-  virtual void virtualDestroyNSSReference() override;
-  void destructorSafeDestroyNSSReference();
 };
 
 #endif // nsPKCS11Slot_h
--- a/security/manager/ssl/nsPKCS12Blob.cpp
+++ b/security/manager/ssl/nsPKCS12Blob.cpp
@@ -34,22 +34,16 @@ extern LazyLogModule gPIPNSSLog;
 // constructor
 nsPKCS12Blob::nsPKCS12Blob()
   : mCertArray(nullptr)
   , mTmpFile(nullptr)
 {
   mUIContext = new PipUIContext();
 }
 
-// destructor
-nsPKCS12Blob::~nsPKCS12Blob()
-{
-  shutdown(ShutdownCalledFrom::Object);
-}
-
 // nsPKCS12Blob::ImportFromFile
 //
 // Given a file handle, read a PKCS#12 blob from that file, decode it, and
 // import the results into the internal database.
 nsresult
 nsPKCS12Blob::ImportFromFile(nsIFile *file)
 {
   nsresult rv = NS_OK;
--- a/security/manager/ssl/nsPKCS12Blob.h
+++ b/security/manager/ssl/nsPKCS12Blob.h
@@ -19,20 +19,17 @@ class nsIX509Cert;
 // nsPKCS12Blob
 //
 // Class for importing/exporting PKCS#12 blobs
 //
 class nsPKCS12Blob : public nsNSSShutDownObject
 {
 public:
   nsPKCS12Blob();
-  virtual ~nsPKCS12Blob();
-
-  // Nothing to release.
-  virtual void virtualDestroyNSSReference() override {}
+  virtual ~nsPKCS12Blob() {}
 
   // PKCS#12 Import
   nsresult ImportFromFile(nsIFile *file);
 
   // PKCS#12 Export
   nsresult ExportToFile(nsIFile *file, nsIX509Cert **certs, int numCerts);
 
 private:
--- a/security/manager/ssl/nsRandomGenerator.cpp
+++ b/security/manager/ssl/nsRandomGenerator.cpp
@@ -34,13 +34,8 @@ nsRandomGenerator::GenerateRandomBytes(u
     free(buf);
     return NS_ERROR_FAILURE;
   }
 
   *aBuffer = buf;
 
   return NS_OK;
 }
-
-nsRandomGenerator::~nsRandomGenerator()
-{
-  shutdown(ShutdownCalledFrom::Object);
-}
--- a/security/manager/ssl/nsRandomGenerator.h
+++ b/security/manager/ssl/nsRandomGenerator.h
@@ -18,13 +18,12 @@
 class nsRandomGenerator final : public nsIRandomGenerator
                               , public nsNSSShutDownObject
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRANDOMGENERATOR
 
 private:
-  ~nsRandomGenerator();
-  virtual void virtualDestroyNSSReference() override {}
+  ~nsRandomGenerator() {}
 };
 
 #endif // nsRandomGenerator_h
--- a/security/manager/ssl/nsSSLStatus.cpp
+++ b/security/manager/ssl/nsSSLStatus.cpp
@@ -9,22 +9,16 @@
 #include "nsSSLStatus.h"
 #include "nsIClassInfoImpl.h"
 #include "nsIObjectOutputStream.h"
 #include "nsIObjectInputStream.h"
 #include "nsNSSCertificate.h"
 #include "nsNSSShutDown.h"
 #include "ssl.h"
 
-
-void
-nsSSLStatus::virtualDestroyNSSReference()
-{
-}
-
 NS_IMETHODIMP
 nsSSLStatus::GetServerCert(nsIX509Cert** aServerCert)
 {
   NS_ENSURE_ARG_POINTER(aServerCert);
 
   nsCOMPtr<nsIX509Cert> cert = mServerCert;
   cert.forget(aServerCert);
   return NS_OK;
@@ -388,21 +382,16 @@ nsSSLStatus::nsSSLStatus()
 , mHasIsEVStatus(false)
 , mHaveCipherSuiteAndProtocol(false)
 , mHaveCertErrorBits(false)
 {
 }
 
 NS_IMPL_ISUPPORTS(nsSSLStatus, nsISSLStatus, nsISerializable, nsIClassInfo)
 
-nsSSLStatus::~nsSSLStatus()
-{
-  shutdown(ShutdownCalledFrom::Object);
-}
-
 void
 nsSSLStatus::SetServerCert(nsNSSCertificate* aServerCert, EVStatus aEVStatus)
 {
   MOZ_ASSERT(aServerCert);
 
   mServerCert = aServerCert;
   mIsEV = (aEVStatus == EVStatus::EV);
   mHasIsEVStatus = true;
--- a/security/manager/ssl/nsSSLStatus.h
+++ b/security/manager/ssl/nsSSLStatus.h
@@ -27,17 +27,17 @@ enum class EVStatus {
 
 class nsSSLStatus final
   : public nsISSLStatus
   , public nsISerializable
   , public nsIClassInfo
   , public nsNSSShutDownObject
 {
 protected:
-  virtual ~nsSSLStatus();
+  virtual ~nsSSLStatus() {}
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSISSLSTATUS
   NS_DECL_NSISERIALIZABLE
   NS_DECL_NSICLASSINFO
 
   nsSSLStatus();
 
@@ -48,18 +48,16 @@ public:
 
   bool HasServerCert() {
     return mServerCert != nullptr;
   }
 
   void SetCertificateTransparencyInfo(
     const mozilla::psm::CertificateTransparencyInfo& info);
 
-  virtual void virtualDestroyNSSReference() override;
-
   /* public for initilization in this file */
   uint16_t mCipherSuite;
   uint16_t mProtocolVersion;
   uint16_t mCertificateTransparencyStatus;
   nsCString mKeaGroup;
   nsCString mSignatureSchemeName;
 
   bool mIsDomainMismatch;
--- a/services/crypto/component/IdentityCryptoService.cpp
+++ b/services/crypto/component/IdentityCryptoService.cpp
@@ -54,31 +54,22 @@ public:
   NS_DECL_NSIIDENTITYKEYPAIR
 
   KeyPair(SECKEYPrivateKey* aPrivateKey, SECKEYPublicKey* aPublicKey,
           nsIEventTarget* aOperationThread);
 
 private:
   ~KeyPair() override
   {
-    destructorSafeDestroyNSSReference();
-    shutdown(ShutdownCalledFrom::Object);
-  }
-
-  void virtualDestroyNSSReference() override
-  {
-    destructorSafeDestroyNSSReference();
-  }
-
-  void destructorSafeDestroyNSSReference()
-  {
-    SECKEY_DestroyPrivateKey(mPrivateKey);
-    mPrivateKey = nullptr;
-    SECKEY_DestroyPublicKey(mPublicKey);
-    mPublicKey = nullptr;
+    if (mPrivateKey) {
+      SECKEY_DestroyPrivateKey(mPrivateKey);
+    }
+    if (mPublicKey) {
+      SECKEY_DestroyPublicKey(mPublicKey);
+    }
   }
 
   SECKEYPrivateKey * mPrivateKey;
   SECKEYPublicKey * mPublicKey;
   nsCOMPtr<nsIEventTarget> mThread;
 
   KeyPair(const KeyPair &) = delete;
   void operator=(const KeyPair &) = delete;
@@ -92,27 +83,16 @@ public:
   NS_DECL_NSIRUNNABLE
 
   KeyGenRunnable(KeyType keyType, nsIIdentityKeyGenCallback * aCallback,
                  nsIEventTarget* aOperationThread);
 
 private:
   ~KeyGenRunnable() override
   {
-    destructorSafeDestroyNSSReference();
-    shutdown(ShutdownCalledFrom::Object);
-  }
-
-  void virtualDestroyNSSReference() override
-  {
-    destructorSafeDestroyNSSReference();
-  }
-
-  void destructorSafeDestroyNSSReference()
-  {
   }
 
   const KeyType mKeyType; // in
   nsMainThreadPtrHandle<nsIIdentityKeyGenCallback> mCallback; // in
   nsresult mRv; // out
   nsCOMPtr<nsIIdentityKeyPair> mKeyPair; // out
   nsCOMPtr<nsIEventTarget> mThread;
 
@@ -126,29 +106,19 @@ public:
   NS_DECL_NSIRUNNABLE
 
   SignRunnable(const nsACString & textToSign, SECKEYPrivateKey * privateKey,
                nsIIdentitySignCallback * aCallback);
 
 private:
   ~SignRunnable() override
   {
-    destructorSafeDestroyNSSReference();
-    shutdown(ShutdownCalledFrom::Object);
-  }
-
-  void virtualDestroyNSSReference() override
-  {
-    destructorSafeDestroyNSSReference();
-  }
-
-  void destructorSafeDestroyNSSReference()
-  {
-    SECKEY_DestroyPrivateKey(mPrivateKey);
-    mPrivateKey = nullptr;
+    if (mPrivateKey) {
+      SECKEY_DestroyPrivateKey(mPrivateKey);
+    }
   }
 
   const nsCString mTextToSign; // in
   SECKEYPrivateKey* mPrivateKey; // in
   nsMainThreadPtrHandle<nsIIdentitySignCallback> mCallback; // in
   nsresult mRv; // out
   nsCString mSignature; // out