Merge mozilla-central to mozilla-inbound
authorEd Morley <emorley@mozilla.com>
Fri, 14 Dec 2012 19:03:57 +0000
changeset 125203 ba8c91f1d468724d44065727d771e50baf4386a9
parent 125202 dc4887f61d2e2042b1af209927d23686fd68302c (current diff)
parent 125162 2798371f16505dddc042e659a2c691f37317cc97 (diff)
child 125204 7b9ffa4e1e64753b5ca65dbcd967815ae15cfac8
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone20.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
Merge mozilla-central to mozilla-inbound
security/manager/ssl/src/nsNSSCertificateDB.cpp
--- a/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
+++ b/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
@@ -434,21 +434,16 @@ PrivateBrowsingService.prototype = {
             this.privateBrowsingEnabled = true;
         }
         this._obs.removeObserver(this, "profile-after-change");
         break;
       case "quit-application-granted":
         this._unload();
         break;
       case "private-browsing":
-        // clear all auth tokens
-        let sdr = Cc["@mozilla.org/security/sdr;1"].
-                  getService(Ci.nsISecretDecoderRing);
-        sdr.logoutAndTeardown();
-    
         if (!this._inPrivateBrowsing) {
           // Clear the error console
           let consoleService = Cc["@mozilla.org/consoleservice;1"].
                                getService(Ci.nsIConsoleService);
           consoleService.logStringMessage(null); // trigger the listeners
           consoleService.reset();
         }
         break;
--- a/browser/confvars.sh
+++ b/browser/confvars.sh
@@ -68,8 +68,9 @@ MOZ_SERVICES_SYNC=1
 MOZ_APP_VERSION=$FIREFOX_VERSION
 MOZ_EXTENSIONS_DEFAULT=" gio"
 MOZ_APP_ID={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
 MOZ_PROFILE_MIGRATOR=1
 MOZ_EXTENSION_MANAGER=1
 MOZ_APP_STATIC_INI=1
 MOZ_WEBAPP_RUNTIME=1
 MOZ_MEDIA_NAVIGATOR=1
+MOZ_PER_WINDOW_PRIVATE_BROWSING=1
--- a/browser/devtools/debugger/test/Makefile.in
+++ b/browser/devtools/debugger/test/Makefile.in
@@ -83,17 +83,17 @@ MOCHITEST_BROWSER_TESTS = \
 	browser_dbg_displayName.js \
 	browser_dbg_iframes.js \
 	browser_dbg_pause-exceptions.js \
 	browser_dbg_multiple-windows.js \
 	browser_dbg_bfcache.js \
 	browser_dbg_breakpoint-new-script.js \
 	browser_dbg_bug737803_editor_actual_location.js \
 	browser_dbg_progress-listener-bug.js \
-	browser_dbg_chrome-debugging.js \
+	$(filter disabled-for-intermittent-crashes--bug-821701, browser_dbg_chrome-debugging.js) \
 	$(filter disabled-for-intermittent-failures--bug-753225, browser_dbg_createRemote.js) \
 	head.js \
 	$(NULL)
 
 MOCHITEST_BROWSER_PAGES = \
 	browser_dbg_tab1.html \
 	browser_dbg_tab2.html \
 	browser_dbg_debuggerstatement.html \
--- a/netwerk/base/public/nsASocketHandler.h
+++ b/netwerk/base/public/nsASocketHandler.h
@@ -10,16 +10,17 @@
 
 class nsASocketHandler : public nsISupports
 {
 public:
     nsASocketHandler()
         : mCondition(NS_OK)
         , mPollFlags(0)
         , mPollTimeout(UINT16_MAX)
+        , mIsPrivate(false)
         {}
 
     //
     // this condition variable will be checked to determine if the socket
     // handler should be detached.  it must only be accessed on the socket
     // thread.
     //
     nsresult mCondition;
@@ -37,16 +38,18 @@ public:
     // then OnSocketReady will be called with outFlags = -1.
     //
     // the default value for this member is UINT16_MAX, which disables the
     // timeout error checking.  (i.e., a timeout value of UINT16_MAX is
     // never reached.)
     //
     uint16_t mPollTimeout;
 
+    bool mIsPrivate;
+
     //
     // called to service a socket
     // 
     // params:
     //   socketRef - socket identifier
     //   fd        - socket file descriptor
     //   outFlags  - value of PR_PollDesc::out_flags after PR_Poll returns
     //               or -1 if a timeout occurred
--- a/netwerk/base/src/nsSocketTransport2.cpp
+++ b/netwerk/base/src/nsSocketTransport2.cpp
@@ -2201,16 +2201,17 @@ nsSocketTransport::GetConnectionFlags(ui
     *value = mConnectionFlags;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSocketTransport::SetConnectionFlags(uint32_t value)
 {
     mConnectionFlags = value;
+    mIsPrivate = value & nsISocketTransport::NO_PERMANENT_STORAGE;
     return NS_OK;
 }
 
 
 #ifdef ENABLE_SOCKET_TRACING
 
 #include <stdio.h>
 #include <ctype.h>
--- a/netwerk/base/src/nsSocketTransportService2.cpp
+++ b/netwerk/base/src/nsSocketTransportService2.cpp
@@ -18,25 +18,17 @@
 #include "nsIPrefBranch.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIOService.h"
 #include "NetworkActivityMonitor.h"
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Likely.h"
-
-
-// XXX: There is no good header file to put these in. :(
-namespace mozilla { namespace psm {
-
-void InitializeSSLServerCertVerificationThreads();
-void StopSSLServerCertVerificationThreads();
-
-} } // namespace mozilla::psm
+#include "mozilla/PublicSSL.h"
 
 using namespace mozilla;
 using namespace mozilla::net;
 
 #if defined(PR_LOGGING)
 PRLogModuleInfo *gSocketTransportLog = nullptr;
 #endif
 
@@ -465,16 +457,17 @@ nsSocketTransportService::Init()
     if (tmpPrefService) {
         tmpPrefService->AddObserver(SEND_BUFFER_PREF, this, false);
     }
     UpdatePrefs();
 
     nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
     if (obsSvc) {
         obsSvc->AddObserver(this, "profile-initial-state", false);
+        obsSvc->AddObserver(this, "last-pb-context-exited", false);
     }
 
     mInitialized = true;
     return NS_OK;
 }
 
 // called from main thread only
 NS_IMETHODIMP
@@ -512,16 +505,17 @@ nsSocketTransportService::Shutdown()
 
     nsCOMPtr<nsIPrefBranch> tmpPrefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
     if (tmpPrefService) 
         tmpPrefService->RemoveObserver(SEND_BUFFER_PREF, this);
 
     nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
     if (obsSvc) {
         obsSvc->RemoveObserver(this, "profile-initial-state");
+        obsSvc->RemoveObserver(this, "last-pb-context-exited");
     }
 
     mozilla::net::NetworkActivityMonitor::Shutdown();
 
     mInitialized = false;
     mShuttingDown = false;
 
     return NS_OK;
@@ -879,19 +873,52 @@ nsSocketTransportService::Observe(nsISup
     if (!strcmp(topic, "profile-initial-state")) {
         int32_t blipInterval = Preferences::GetInt(BLIP_INTERVAL_PREF, 0);
         if (blipInterval <= 0) {
             return NS_OK;
         }
 
         return net::NetworkActivityMonitor::Init(blipInterval);
     }
+
+    if (!strcmp(topic, "last-pb-context-exited")) {
+        nsCOMPtr<nsIRunnable> ev =
+          NS_NewRunnableMethod(this,
+                               &nsSocketTransportService::ClosePrivateConnections);
+        nsresult rv = Dispatch(ev, nsIEventTarget::DISPATCH_NORMAL);
+        NS_ENSURE_SUCCESS(rv, rv);
+    }
+
     return NS_OK;
 }
 
+void
+nsSocketTransportService::ClosePrivateConnections()
+{
+    // Must be called on the socket thread.
+#ifdef DEBUG
+    bool onSTSThread;
+    IsOnCurrentThread(&onSTSThread);
+    MOZ_ASSERT(onSTSThread);
+#endif
+
+    for (int32_t i = mActiveCount - 1; i >= 0; --i) {
+        if (mActiveList[i].mHandler->mIsPrivate) {
+            DetachSocket(mActiveList, &mActiveList[i]);
+        }
+    }
+    for (int32_t i = mIdleCount - 1; i >= 0; --i) {
+        if (mIdleList[i].mHandler->mIsPrivate) {
+            DetachSocket(mIdleList, &mIdleList[i]);
+        }
+    }
+
+    mozilla::ClearPrivateSSLState();
+}
+
 NS_IMETHODIMP
 nsSocketTransportService::GetSendBufferSize(int32_t *value)
 {
     *value = mSendBufferSize;
     return NS_OK;
 }
 
 
--- a/netwerk/base/src/nsSocketTransportService2.h
+++ b/netwerk/base/src/nsSocketTransportService2.h
@@ -185,14 +185,16 @@ private:
     // Socket thread only for dynamically adjusting max socket size
 #if defined(XP_WIN)
     void ProbeMaxCount();
 #endif
     bool mProbedMaxCount;
 
     void AnalyzeConnection(nsTArray<mozilla::net::SocketInfo> *data,
                            SocketContext *context, bool aActive);
+
+    void ClosePrivateConnections();
 };
 
 extern nsSocketTransportService *gSocketTransportService;
 extern PRThread                 *gSocketThread;
 
 #endif // !nsSocketTransportService_h__
--- a/security/manager/pki/resources/content/exceptionDialog.js
+++ b/security/manager/pki/resources/content/exceptionDialog.js
@@ -83,18 +83,21 @@ function initExceptionDialog() {
     // Set out parameter to false by default
     args[0].exceptionAdded = false; 
   }
 }
 
 // returns true if found and global status could be set
 function findRecentBadCert(uri) {
   try {
-    var recentCertsSvc = Components.classes["@mozilla.org/security/recentbadcerts;1"]
-                         .getService(Components.interfaces.nsIRecentBadCertsService);
+    var certDB = Components.classes["@mozilla.org/security/x509certdb;1"]
+                           .getService(Components.interfaces.nsIX509CertDB);
+    if (!certDB)
+      return false;
+    var recentCertsSvc = certDB.getRecentBadCertsService(inPrivateBrowsingMode());
     if (!recentCertsSvc)
       return false;
 
     var hostWithPort = uri.host + ":" + uri.port;
     gSSLStatus = recentCertsSvc.getRecentBadCert(hostWithPort);
     if (!gSSLStatus)
       return false;
 
--- a/security/manager/ssl/public/nsIRecentBadCertsService.idl
+++ b/security/manager/ssl/public/nsIRecentBadCertsService.idl
@@ -15,19 +15,18 @@ interface nsISSLStatus;
 %}
 
 /**
  * This represents a global list of recently seen bad ssl status
  * including the bad cert.
  * The implementation will decide how many entries it will hold,
  * the number is expected to be small.
  */
-[scriptable, uuid(a5ae8b05-a76e-408f-b0ba-02a831265749)]
-interface nsIRecentBadCertsService : nsISupports {
-
+[scriptable, uuid(0fed7784-d152-44d6-95a7-67a59024de0f)]
+interface nsIRecentBadCerts : nsISupports {
   /**
    *  Retrieve the recently seen bad ssl status for the given hostname:port.
    *  If no SSL cert was recently seen for the given hostname:port, return null.
    *  If a good cert was seen for the given hostname:port, return null.
    *
    *  @param aHostNameWithPort The host:port whose entry should be tested
    *  @return null or a recently seen bad ssl status with cert
    */
@@ -38,9 +37,14 @@ interface nsIRecentBadCertsService : nsI
    *  Will be added as the most recently seen cert.
    *  The service may forget older entries to make room for the new one.
    *
    *  @param aHostNameWithPort The host:port whose entry should be tested
    *  @param aCert The bad ssl status with certificate
    */
   void addBadCert(in AString aHostNameWithPort,
                   in nsISSLStatus aStatus);
+
+  /**
+   * Clear all stored cert data.
+   */
+  void resetStoredCerts();
 };
--- a/security/manager/ssl/public/nsIX509CertDB.idl
+++ b/security/manager/ssl/public/nsIX509CertDB.idl
@@ -7,16 +7,17 @@
 #include "nsISupports.idl"
 
 interface nsIArray;
 interface nsIX509Cert;
 interface nsIX509Cert3;
 interface nsIFile;
 interface nsIInterfaceRequestor;
 interface nsIZipReader;
+interface nsIRecentBadCerts;
 
 %{C++
 #define NS_X509CERTDB_CONTRACTID "@mozilla.org/security/x509certdb;1"
 %}
 
 [scriptable, function, uuid(48411e2d-85a9-4b16-bec8-e30cde801f9e)]
 interface nsIOpenSignedJARFileCallback : nsISupports
 {
@@ -24,17 +25,17 @@ interface nsIOpenSignedJARFileCallback :
                                  in nsIZipReader aZipReader,
                                  in nsIX509Cert3 aSignerCert);
 };
 
 /**
  * This represents a service to access and manipulate 
  * X.509 certificates stored in a database.
  */
-[scriptable, uuid(735d0363-e219-4387-b5c6-72e800c3ea0b)]
+[scriptable, uuid(a18df2a5-84a9-46cd-9140-3fdb3879d9ff)]
 interface nsIX509CertDB : nsISupports {
 
   /**
    *  Constants that define which usages a certificate
    *  is trusted for.
    */
   const unsigned long UNTRUSTED       =      0;
   const unsigned long TRUSTED_SSL     = 1 << 0;
@@ -259,16 +260,26 @@ interface nsIX509CertDB : nsISupports {
    *  Decode a raw data presentation and instantiate an object in memory.
    *
    *  @param base64 The raw representation of a certificate,
    *                encoded as Base 64.
    *  @return The new certificate object.
    */
   nsIX509Cert constructX509FromBase64(in string base64);
 
+  /*
+   *  Obtain a reference to the appropriate service for recent
+   *  bad certificates. May only be called on the main thread.
+   *
+   *  @param isPrivate True if the service for certs for private connections
+   *                   is desired, false otherwise.
+   *  @return The requested service.
+   */
+  nsIRecentBadCerts getRecentBadCerts(in boolean isPrivate);
+
   /**
    *  Verifies the signature on the given JAR file to verify that it has a
    *  valid signature.  To be considered valid, there must be exactly one
    *  signature on the JAR file and that signature must have signed every
    *  entry. Further, the signature must come from a certificate that
    *  is trusted for code signing.
    *
    *  On success, NS_OK, a nsIZipReader, and the trusted certificate that
--- a/security/manager/ssl/src/Makefile.in
+++ b/security/manager/ssl/src/Makefile.in
@@ -69,33 +69,39 @@ CPPSRCS = 				\
   nsIdentityChecking.cpp \
   nsDataSignatureVerifier.cpp \
   nsRandomGenerator.cpp \
   NSSErrorsService.cpp \
   nsNSSCertificateFakeTransport.cpp \
   PSMRunnable.cpp \
   nsNSSVersion.cpp \
   nsCertificatePrincipal.cpp \
+  SharedSSLState.cpp \
   $(NULL)
 
 ifdef MOZ_XUL
 CPPSRCS += nsCertTree.cpp
 endif
 
 CSRCS += md4.c
 
-
 EXTRA_DEPS = $(NSS_DEP_LIBS)
 
 DEFINES += \
   -DNSS_ENABLE_ECC \
   -DDLL_PREFIX=\"$(DLL_PREFIX)\" \
   -DDLL_SUFFIX=\"$(DLL_SUFFIX)\" \
   $(NULL)
 
 EXPORTS += \
   CryptoTask.h \
   nsNSSShutDown.h \
   ScopedNSSTypes.h \
   $(NULL)
 
+EXPORTS_NAMESPACES = mozilla
+
+EXPORTS_mozilla += \
+  PublicSSL.h \
+  $(NULL)
+
 include $(topsrcdir)/config/rules.mk
 
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/src/PublicSSL.h
@@ -0,0 +1,23 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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 mozilla_SSL_h
+#define mozilla_SSL_h
+
+namespace mozilla {
+
+void ClearPrivateSSLState();
+
+namespace psm {
+
+void InitializeSSLServerCertVerificationThreads();
+void StopSSLServerCertVerificationThreads();
+
+} //namespace psm
+} // namespace mozilla
+
+#endif
+
--- a/security/manager/ssl/src/SSLServerCertVerification.cpp
+++ b/security/manager/ssl/src/SSLServerCertVerification.cpp
@@ -107,16 +107,17 @@
 #include "mozilla/Assertions.h"
 #include "nsIThreadPool.h"
 #include "nsXPCOMCIDInternal.h"
 #include "nsComponentManagerUtils.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIConsoleService.h"
 #include "PSMRunnable.h"
 #include "ScopedNSSTypes.h"
+#include "SharedSSLState.h"
 
 #include "ssl.h"
 #include "secerr.h"
 #include "secport.h"
 #include "sslerr.h"
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gPIPNSSLog;
@@ -233,39 +234,42 @@ class CertErrorRunnable : public SyncRun
  public:
   CertErrorRunnable(const void * fdForLogging,
                     nsIX509Cert * cert,
                     TransportSecurityInfo * infoObject,
                     PRErrorCode defaultErrorCodeToReport,
                     uint32_t collectedErrors,
                     PRErrorCode errorCodeTrust,
                     PRErrorCode errorCodeMismatch,
-                    PRErrorCode errorCodeExpired)
+                    PRErrorCode errorCodeExpired,
+                    uint32_t providerFlags)
     : mFdForLogging(fdForLogging), mCert(cert), mInfoObject(infoObject),
       mDefaultErrorCodeToReport(defaultErrorCodeToReport),
       mCollectedErrors(collectedErrors),
       mErrorCodeTrust(errorCodeTrust),
       mErrorCodeMismatch(errorCodeMismatch),
-      mErrorCodeExpired(errorCodeExpired)
+      mErrorCodeExpired(errorCodeExpired),
+      mProviderFlags(providerFlags)
   {
   }
 
   virtual void RunOnTargetThread();
   RefPtr<SSLServerCertVerificationResult> mResult; // out
 private:
   SSLServerCertVerificationResult *CheckCertOverrides();
   
   const void * const mFdForLogging; // may become an invalid pointer; do not dereference
   const nsCOMPtr<nsIX509Cert> mCert;
   const RefPtr<TransportSecurityInfo> mInfoObject;
   const PRErrorCode mDefaultErrorCodeToReport;
   const uint32_t mCollectedErrors;
   const PRErrorCode mErrorCodeTrust;
   const PRErrorCode mErrorCodeMismatch;
   const PRErrorCode mErrorCodeExpired;
+  const uint32_t mProviderFlags;
 };
 
 SSLServerCertVerificationResult *
 CertErrorRunnable::CheckCertOverrides()
 {
   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("[%p][%p] top of CheckCertOverrides\n",
                                     mFdForLogging, this));
 
@@ -291,22 +295,18 @@ CertErrorRunnable::CheckCertOverrides()
   // connections must be dropped when there are any certificate errors
   // (STS Spec section 7.3).
   bool strictTransportSecurityEnabled = false;
   nsCOMPtr<nsIStrictTransportSecurityService> stss
     = do_GetService(NS_STSSERVICE_CONTRACTID, &nsrv);
   if (NS_SUCCEEDED(nsrv)) {
     nsCOMPtr<nsISSLSocketControl> sslSocketControl = do_QueryInterface(
       NS_ISUPPORTS_CAST(nsITransportSecurityInfo*, mInfoObject));
-    uint32_t flags = 0;
-    if (sslSocketControl) {
-      sslSocketControl->GetProviderFlags(&flags);
-    }
     nsrv = stss->IsStsHost(mInfoObject->GetHostName(),
-                           flags,
+                           mProviderFlags,
                            &strictTransportSecurityEnabled);
   }
   if (NS_FAILED(nsrv)) {
     return new SSLServerCertVerificationResult(mInfoObject,
                                                mDefaultErrorCodeToReport);
   }
 
   if (!strictTransportSecurityEnabled) {
@@ -366,18 +366,22 @@ CertErrorRunnable::CheckCertOverrides()
           = static_cast<nsIInterfaceRequestor*>(mInfoObject);
         bool suppressMessage = false; // obsolete, ignored
         nsrv = bcl->NotifyCertProblem(csi, mInfoObject->SSLStatus(),
                                       hostWithPortString, &suppressMessage);
       }
     }
   }
 
-  nsCOMPtr<nsIRecentBadCertsService> recentBadCertsService = 
-    do_GetService(NS_RECENTBADCERTS_CONTRACTID);
+  nsCOMPtr<nsIX509CertDB> certdb = do_GetService(NS_X509CERTDB_CONTRACTID);
+  nsCOMPtr<nsIRecentBadCerts> recentBadCertsService;
+  if (certdb) {
+    bool isPrivate = mProviderFlags & nsISocketProvider::NO_PERMANENT_STORAGE;
+    certdb->GetRecentBadCerts(isPrivate, getter_AddRefs(recentBadCertsService));
+  }
  
   if (recentBadCertsService) {
     NS_ConvertUTF8toUTF16 hostWithPortStringUTF16(hostWithPortString);
     recentBadCertsService->AddBadCert(hostWithPortStringUTF16,
                                       mInfoObject->SSLStatus());
   }
 
   // pick the error code to report by priority
@@ -413,17 +417,18 @@ CertErrorRunnable::RunOnTargetThread()
 }
 
 // Returns null with the error code (PR_GetError()) set if it does not create
 // the CertErrorRunnable.
 CertErrorRunnable *
 CreateCertErrorRunnable(PRErrorCode defaultErrorCodeToReport,
                         TransportSecurityInfo * infoObject,
                         CERTCertificate * cert,
-                        const void * fdForLogging)
+                        const void * fdForLogging,
+                        uint32_t providerFlags)
 {
   MOZ_ASSERT(infoObject);
   MOZ_ASSERT(cert);
   
   // cert was revoked, don't do anything else
   if (defaultErrorCodeToReport == SEC_ERROR_REVOKED_CERTIFICATE) {
     PR_SetError(SEC_ERROR_REVOKED_CERTIFICATE, 0);
     return nullptr;
@@ -562,17 +567,18 @@ CreateCertErrorRunnable(PRErrorCode defa
   }
 
   infoObject->SetStatusErrorBits(*nssCert, collected_errors);
 
   return new CertErrorRunnable(fdForLogging, 
                                static_cast<nsIX509Cert*>(nssCert.get()),
                                infoObject, defaultErrorCodeToReport, 
                                collected_errors, errorCodeTrust, 
-                               errorCodeMismatch, errorCodeExpired);
+                               errorCodeMismatch, errorCodeExpired,
+                               providerFlags);
 }
 
 // When doing async cert processing, we dispatch one of these runnables to the
 // socket transport service thread, which blocks the socket transport
 // service thread while it waits for the inner CertErrorRunnable to execute
 // CheckCertOverrides on the main thread. CheckCertOverrides must block events
 // on both of these threads because it calls TransportSecurityInfo::GetInterface(), 
 // which may call nsHttpConnection::GetInterface() through
@@ -602,35 +608,39 @@ private:
 };
 
 class SSLServerCertVerificationJob : public nsRunnable
 {
 public:
   // Must be called only on the socket transport thread
   static SECStatus Dispatch(const void * fdForLogging,
                             TransportSecurityInfo * infoObject,
-                            CERTCertificate * serverCert);
+                            CERTCertificate * serverCert,
+                            uint32_t providerFlags);
 private:
   NS_DECL_NSIRUNNABLE
 
   // Must be called only on the socket transport thread
   SSLServerCertVerificationJob(const void * fdForLogging,
                                TransportSecurityInfo * infoObject, 
-                               CERTCertificate * cert);
+                               CERTCertificate * cert,
+                               uint32_t providerFlags);
   const void * const mFdForLogging;
   const RefPtr<TransportSecurityInfo> mInfoObject;
   const ScopedCERTCertificate mCert;
+  const uint32_t mProviderFlags;
 };
 
 SSLServerCertVerificationJob::SSLServerCertVerificationJob(
     const void * fdForLogging, TransportSecurityInfo * infoObject,
-    CERTCertificate * cert)
+    CERTCertificate * cert, uint32_t providerFlags)
   : mFdForLogging(fdForLogging)
   , mInfoObject(infoObject)
   , mCert(CERT_DupCertificate(cert))
+  , mProviderFlags(providerFlags)
 {
 }
 
 SECStatus
 PSM_SSL_PKIX_AuthCertificate(CERTCertificate *peerCert, void * pinarg,
                              const char * hostname)
 {
     SECStatus          rv;
@@ -820,17 +830,18 @@ BlockServerCertChangeForSpdy(nsNSSSocket
   // Report an error - changed cert is confirmed
   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
          ("SPDY Refused to allow new cert during renegotiation\n"));
   PR_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED, 0);
   return SECFailure;
 }
 
 SECStatus
-AuthCertificate(TransportSecurityInfo * infoObject, CERTCertificate * cert)
+AuthCertificate(TransportSecurityInfo * infoObject, CERTCertificate * cert,
+                uint32_t providerFlags)
 {
   if (cert->serialNumber.data &&
       cert->issuerName &&
       !strcmp(cert->issuerName, 
         "CN=UTN-USERFirst-Hardware,OU=http://www.usertrust.com,O=The USERTRUST Network,L=Salt Lake City,ST=UT,C=US")) {
 
     unsigned char *server_cert_comparison_start = cert->serialNumber.data;
     unsigned int server_cert_comparison_len = cert->serialNumber.len;
@@ -906,47 +917,51 @@ AuthCertificate(TransportSecurityInfo * 
 
   if (rv == SECSuccess) {
     if (nsc) {
       bool dummyIsEV;
       nsc->GetIsExtendedValidation(&dummyIsEV); // the nsc object will cache the status
     }
     
     nsCOMPtr<nsINSSComponent> nssComponent;
-      
-    for (CERTCertListNode *node = CERT_LIST_HEAD(certList);
-         !CERT_LIST_END(node, certList);
-         node = CERT_LIST_NEXT(node)) {
+
+    // We want to avoid storing any intermediate cert information when browsing
+    // in private, transient contexts.
+    if (!(providerFlags & nsISocketProvider::NO_PERMANENT_STORAGE)) {
+      for (CERTCertListNode *node = CERT_LIST_HEAD(certList);
+           !CERT_LIST_END(node, certList);
+           node = CERT_LIST_NEXT(node)) {
+
+        if (node->cert->slot) {
+          // This cert was found on a token, no need to remember it in the temp db.
+          continue;
+        }
 
-      if (node->cert->slot) {
-        // This cert was found on a token, no need to remember it in the temp db.
-        continue;
-      }
+        if (node->cert->isperm) {
+          // We don't need to remember certs already stored in perm db.
+          continue;
+        }
+
+        if (node->cert == cert) {
+          // We don't want to remember the server cert, 
+          // the code that cares for displaying page info does this already.
+          continue;
+        }
 
-      if (node->cert->isperm) {
-        // We don't need to remember certs already stored in perm db.
-        continue;
+        // We have found a signer cert that we want to remember.
+        char* nickname = nsNSSCertificate::defaultServerNickname(node->cert);
+        if (nickname && *nickname) {
+          ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
+          if (slot) {
+            PK11_ImportCert(slot, node->cert, CK_INVALID_HANDLE, 
+                            nickname, false);
+          }
+        }
+        PR_FREEIF(nickname);
       }
-        
-      if (node->cert == cert) {
-        // We don't want to remember the server cert, 
-        // the code that cares for displaying page info does this already.
-        continue;
-      }
-
-      // We have found a signer cert that we want to remember.
-      char* nickname = nsNSSCertificate::defaultServerNickname(node->cert);
-      if (nickname && *nickname) {
-        ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
-        if (slot) {
-          PK11_ImportCert(slot, node->cert, CK_INVALID_HANDLE, 
-                          nickname, false);
-        }
-      }
-      PR_FREEIF(nickname);
     }
 
     // The connection may get terminated, for example, if the server requires
     // a client cert. Let's provide a minimal SSLStatus
     // to the caller that contains at least the cert and its status.
     if (!status) {
       status = new nsSSLStatus();
       infoObject->SetSSLStatus(status);
@@ -972,27 +987,29 @@ AuthCertificate(TransportSecurityInfo * 
   }
 
   return rv;
 }
 
 /*static*/ SECStatus
 SSLServerCertVerificationJob::Dispatch(const void * fdForLogging,
                                        TransportSecurityInfo * infoObject,
-                                       CERTCertificate * serverCert)
+                                       CERTCertificate * serverCert,
+                                       uint32_t providerFlags)
 {
   // Runs on the socket transport thread
   if (!infoObject || !serverCert) {
     NS_ERROR("Invalid parameters for SSL server cert validation");
     PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
     return SECFailure;
   }
   
   RefPtr<SSLServerCertVerificationJob> job(
-    new SSLServerCertVerificationJob(fdForLogging, infoObject, serverCert));
+    new SSLServerCertVerificationJob(fdForLogging, infoObject, serverCert,
+                                     providerFlags));
 
   nsresult nrv;
   if (!gCertVerificationThreadPool) {
     nrv = NS_ERROR_NOT_INITIALIZED;
   } else {
     nrv = gCertVerificationThreadPool->Dispatch(job, NS_DISPATCH_NORMAL);
   }
   if (NS_FAILED(nrv)) {
@@ -1026,28 +1043,28 @@ SSLServerCertVerificationJob::Run()
 
   nsNSSShutDownPreventionLock nssShutdownPrevention;
   if (mInfoObject->isAlreadyShutDown()) {
     error = SEC_ERROR_USER_CANCELLED;
   } else {
     // Reset the error code here so we can detect if AuthCertificate fails to
     // set the error code if/when it fails.
     PR_SetError(0, 0); 
-    SECStatus rv = AuthCertificate(mInfoObject, mCert);
+    SECStatus rv = AuthCertificate(mInfoObject, mCert, mProviderFlags);
     if (rv == SECSuccess) {
       RefPtr<SSLServerCertVerificationResult> restart(
         new SSLServerCertVerificationResult(mInfoObject, 0));
       restart->Dispatch();
       return NS_OK;
     }
 
     error = PR_GetError();
     if (error != 0) {
       RefPtr<CertErrorRunnable> runnable(CreateCertErrorRunnable(
-        error, mInfoObject, mCert, mFdForLogging));
+        error, mInfoObject, mCert, mFdForLogging, mProviderFlags));
       if (!runnable) {
         // CreateCertErrorRunnable set a new error code
         error = PR_GetError(); 
       } else {
         // We must block the the socket transport service thread while the
         // main thread executes the CertErrorRunnable. The CertErrorRunnable
         // will dispatch the result asynchronously, so we don't have to block
         // this thread waiting for it.
@@ -1130,42 +1147,47 @@ AuthCertificateHook(void *arg, PRFileDes
     nrv = sts->IsOnCurrentThread(&onSTSThread);
   }
 
   if (NS_FAILED(nrv)) {
     NS_ERROR("Could not get STS service or IsOnCurrentThread failed");
     PR_SetError(PR_UNKNOWN_ERROR, 0);
     return SECFailure;
   }
-  
+
+  uint32_t providerFlags = 0;
+  socketInfo->GetProviderFlags(&providerFlags);
+
   if (onSTSThread) {
+
     // We *must* do certificate verification on a background thread because
     // we need the socket transport thread to be free for our OCSP requests,
     // and we *want* to do certificate verification on a background thread
     // because of the performance benefits of doing so.
     socketInfo->SetCertVerificationWaiting();
     SECStatus rv = SSLServerCertVerificationJob::Dispatch(
-                        static_cast<const void *>(fd), socketInfo, serverCert);
+                           static_cast<const void *>(fd), socketInfo, serverCert,
+                           providerFlags);
     return rv;
   }
   
   // We can't do certificate verification on a background thread, because the
   // thread doing the network I/O may not interrupt its network I/O on receipt
   // of our SSLServerCertVerificationResult event, and/or it might not even be
   // a non-blocking socket.
-  SECStatus rv = AuthCertificate(socketInfo, serverCert);
+  SECStatus rv = AuthCertificate(socketInfo, serverCert, providerFlags);
   if (rv == SECSuccess) {
     return SECSuccess;
   }
 
   PRErrorCode error = PR_GetError();
   if (error != 0) {
     RefPtr<CertErrorRunnable> runnable(CreateCertErrorRunnable(
                     error, socketInfo, serverCert,
-                    static_cast<const void *>(fd)));
+                    static_cast<const void *>(fd), providerFlags));
     if (!runnable) {
       // CreateCertErrorRunnable sets a new error code when it fails
       error = PR_GetError();
     } else {
       // We have to return SECSuccess or SECFailure based on the result of the
       // override processing, so we must block this thread waiting for it. The
       // CertErrorRunnable will NOT dispatch the result at all, since we passed
       // false for CreateCertErrorRunnable's async parameter
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/src/SharedSSLState.cpp
@@ -0,0 +1,230 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#include "SharedSSLState.h"
+#include "nsClientAuthRemember.h"
+#include "nsComponentManagerUtils.h"
+#include "nsICertOverrideService.h"
+#include "nsIObserverService.h"
+#include "mozilla/Services.h"
+#include "nsThreadUtils.h"
+#include "nsCRT.h"
+#include "nsServiceManagerUtils.h"
+#include "nsRecentBadCerts.h"
+#include "PSMRunnable.h"
+#include "PublicSSL.h"
+#include "ssl.h"
+#include "nsNetCID.h"
+#include "mozilla/unused.h"
+
+using mozilla::psm::SyncRunnableBase;
+using mozilla::unused;
+
+namespace {
+
+static PRInt32 sCertOverrideSvcExists = 0;
+static PRInt32 sCertDBExists = 0;
+
+class MainThreadClearer : public SyncRunnableBase
+{
+public:
+  MainThreadClearer() : mShouldClearSessionCache(false) {}
+
+  void RunOnTargetThread() {
+    // In some cases it's possible to cause PSM/NSS to initialize while XPCOM shutdown
+    // is in progress. We want to avoid this, since they do not handle the situation well,
+    // hence the flags to avoid instantiating the services if they don't already exist.
+
+    bool certOverrideSvcExists = (bool)PR_ATOMIC_SET(&sCertOverrideSvcExists, 0);
+    if (certOverrideSvcExists) {
+      unused << PR_ATOMIC_SET(&sCertOverrideSvcExists, 1);
+      nsCOMPtr<nsICertOverrideService> icos = do_GetService(NS_CERTOVERRIDE_CONTRACTID);
+      if (icos) {
+        icos->ClearValidityOverride(
+          NS_LITERAL_CSTRING("all:temporary-certificates"),
+          0);
+      }
+    }
+
+    bool certDBExists = (bool)PR_ATOMIC_SET(&sCertDBExists, 0);
+    if (certDBExists) {
+      unused << PR_ATOMIC_SET(&sCertDBExists, 1);
+      nsCOMPtr<nsIX509CertDB> certdb = do_GetService(NS_X509CERTDB_CONTRACTID);
+      if (certdb) {
+        nsCOMPtr<nsIRecentBadCerts> badCerts;
+        certdb->GetRecentBadCerts(true, getter_AddRefs(badCerts));
+        if (badCerts) {
+          badCerts->ResetStoredCerts();
+        }
+      }
+    }
+
+    // This needs to be checked on the main thread to avoid racing with NSS
+    // initialization.
+    mShouldClearSessionCache = mozilla::psm::PrivateSSLState() &&
+                               mozilla::psm::PrivateSSLState()->SocketCreated();
+  }
+  bool mShouldClearSessionCache;
+};
+
+} // anonymous namespace
+
+namespace mozilla {
+
+void ClearPrivateSSLState()
+{
+  // This only works if it is called on the socket transport
+  // service thread immediately after closing all private SSL
+  // connections.
+#ifdef DEBUG
+  nsresult rv;
+  nsCOMPtr<nsIEventTarget> sts
+    = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
+  MOZ_ASSERT(NS_SUCCEEDED(rv));
+  bool onSTSThread;
+  rv = sts->IsOnCurrentThread(&onSTSThread);
+  MOZ_ASSERT(NS_SUCCEEDED(rv) && onSTSThread);
+#endif
+
+  RefPtr<MainThreadClearer> runnable = new MainThreadClearer;
+  runnable->DispatchToMainThreadAndWait();
+
+  // If NSS isn't initialized, this throws an assertion. We guard it by checking if
+  // the session cache might even have anything worth clearing.
+  if (runnable->mShouldClearSessionCache) {
+    SSL_ClearSessionCache();
+  }
+}
+
+namespace psm {
+
+namespace {
+class PrivateBrowsingObserver : public nsIObserver {
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIOBSERVER
+  PrivateBrowsingObserver(SharedSSLState* aOwner) : mOwner(aOwner) {}
+  virtual ~PrivateBrowsingObserver() {}
+private:
+  SharedSSLState* mOwner;
+};
+
+SharedSSLState* gPublicState;
+SharedSSLState* gPrivateState;
+} // anonymous namespace
+
+NS_IMPL_ISUPPORTS1(PrivateBrowsingObserver, nsIObserver)
+
+NS_IMETHODIMP
+PrivateBrowsingObserver::Observe(nsISupports     *aSubject,
+                                 const char      *aTopic,
+                                 const PRUnichar *aData)
+{
+  if (!nsCRT::strcmp(aTopic, "last-pb-context-exited")) {
+    mOwner->ResetStoredData();
+  }
+  return NS_OK;
+}
+
+SharedSSLState::SharedSSLState()
+: mClientAuthRemember(new nsClientAuthRememberService)
+, mMutex("SharedSSLState::mMutex")
+, mSocketCreated(false)
+{
+  mIOLayerHelpers.Init();
+  mClientAuthRemember->Init();
+}
+
+SharedSSLState::~SharedSSLState()
+{
+}
+
+void
+SharedSSLState::NotePrivateBrowsingStatus()
+{
+  MOZ_ASSERT(NS_IsMainThread(), "Not on main thread");
+  mObserver = new PrivateBrowsingObserver(this);
+  nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
+  obsSvc->AddObserver(mObserver, "last-pb-context-exited", false);
+}
+
+void
+SharedSSLState::ResetStoredData()
+{
+  MOZ_ASSERT(NS_IsMainThread(), "Not on main thread");
+  mClientAuthRemember->ClearRememberedDecisions();
+  mIOLayerHelpers.clearStoredData();
+}
+
+void
+SharedSSLState::NoteSocketCreated()
+{
+  MutexAutoLock lock(mMutex);
+  mSocketCreated = true;
+}
+
+bool
+SharedSSLState::SocketCreated()
+{
+  MutexAutoLock lock(mMutex);
+  return mSocketCreated;
+}
+
+/*static*/ void
+SharedSSLState::GlobalInit()
+{
+  MOZ_ASSERT(NS_IsMainThread(), "Not on main thread");
+  gPublicState = new SharedSSLState();
+  gPrivateState = new SharedSSLState();
+  gPrivateState->NotePrivateBrowsingStatus();
+}
+
+/*static*/ void
+SharedSSLState::GlobalCleanup()
+{
+  MOZ_ASSERT(NS_IsMainThread(), "Not on main thread");
+
+  gPrivateState->Cleanup();
+  delete gPrivateState;
+  gPrivateState = nullptr;
+
+  gPublicState->Cleanup();
+  delete gPublicState;
+  gPublicState = nullptr;
+}
+
+/*static*/ void
+SharedSSLState::NoteCertOverrideServiceInstantiated()
+{
+  unused << PR_ATOMIC_SET(&sCertOverrideSvcExists, 1);
+}
+
+/*static*/ void
+SharedSSLState::NoteCertDBServiceInstantiated()
+{
+  unused << PR_ATOMIC_SET(&sCertDBExists, 1);
+}
+
+void
+SharedSSLState::Cleanup()
+{
+  mIOLayerHelpers.Cleanup();
+}
+
+SharedSSLState*
+PublicSSLState()
+{
+  return gPublicState;
+}
+
+SharedSSLState*
+PrivateSSLState()
+{
+  return gPrivateState;
+}
+
+} // namespace psm
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/src/SharedSSLState.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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 SharedSSLState_h
+#define SharedSSLState_h
+
+#include "mozilla/RefPtr.h"
+#include "nsNSSIOLayer.h"
+
+class nsClientAuthRememberService;
+class nsIObserver;
+
+namespace mozilla {
+namespace psm {
+
+class SharedSSLState {
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedSSLState)
+  SharedSSLState();
+  ~SharedSSLState();
+
+  static void GlobalInit();
+  static void GlobalCleanup();
+
+  nsClientAuthRememberService* GetClientAuthRememberService() {
+    return mClientAuthRemember;
+  }
+
+  nsSSLIOLayerHelpers& IOLayerHelpers() {
+    return mIOLayerHelpers;
+  }
+
+  // Main-thread only
+  void ResetStoredData();
+  void NotePrivateBrowsingStatus();
+
+  // The following methods may be called from any thread
+  bool SocketCreated();
+  void NoteSocketCreated();
+  static void NoteCertOverrideServiceInstantiated();
+  static void NoteCertDBServiceInstantiated();
+
+private:
+  void Cleanup();
+
+  nsCOMPtr<nsIObserver> mObserver;
+  RefPtr<nsClientAuthRememberService> mClientAuthRemember;
+  nsSSLIOLayerHelpers mIOLayerHelpers;
+
+  // True if any sockets have been created that use this shared data.
+  // Requires synchronization between the socket and main threads for
+  // reading/writing.
+  Mutex mMutex;
+  bool mSocketCreated;
+};
+
+SharedSSLState* PublicSSLState();
+SharedSSLState* PrivateSSLState();
+
+} // namespace psm
+} // namespace mozilla
+
+#endif
--- a/security/manager/ssl/src/nsCertOverrideService.cpp
+++ b/security/manager/ssl/src/nsCertOverrideService.cpp
@@ -14,24 +14,26 @@
 #include "nsILineInputStream.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
 #include "nsISupportsPrimitives.h"
 #include "nsPromiseFlatString.h"
 #include "nsThreadUtils.h"
 #include "nsStringBuffer.h"
 #include "ScopedNSSTypes.h"
+#include "SharedSSLState.h"
 
 #include "nspr.h"
 #include "pk11pub.h"
 #include "certdb.h"
 #include "sechash.h"
 #include "ssl.h" // For SSL_ClearSessionCache
 
 using namespace mozilla;
+using mozilla::psm::SharedSSLState;
 
 static const char kCertOverrideFileName[] = "cert_override.txt";
 
 void
 nsCertOverride::convertBitsToString(OverrideBits ob, nsACString &str)
 {
   str.Truncate();
 
@@ -123,16 +125,17 @@ nsCertOverrideService::Init()
   // reading/writing the wrong settings file after a profile change.
   if (observerService) {
     observerService->AddObserver(this, "profile-before-change", true);
     observerService->AddObserver(this, "profile-do-change", true);
     // simulate a profile change so we read the current profile's settings file
     Observe(nullptr, "profile-do-change", nullptr);
   }
 
+  SharedSSLState::NoteCertOverrideServiceInstantiated();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCertOverrideService::Observe(nsISupports     *,
                                const char      *aTopic,
                                const PRUnichar *aData)
 {
--- a/security/manager/ssl/src/nsClientAuthRemember.cpp
+++ b/security/manager/ssl/src/nsClientAuthRemember.cpp
@@ -16,18 +16,20 @@
 #include "nsPromiseFlatString.h"
 #include "nsThreadUtils.h"
 #include "nsStringBuffer.h"
 #include "cert.h"
 #include "nspr.h"
 #include "pk11pub.h"
 #include "certdb.h"
 #include "sechash.h"
+#include "SharedSSLState.h"
 
 using namespace mozilla;
+using namespace mozilla::psm;
 
 NS_IMPL_THREADSAFE_ISUPPORTS2(nsClientAuthRememberService, 
                               nsIObserver,
                               nsISupportsWeakReference)
 
 nsClientAuthRememberService::nsClientAuthRememberService()
   : monitor("nsClientAuthRememberService.monitor")
 {
@@ -75,16 +77,26 @@ nsClientAuthRememberService::Observe(nsI
 }
 
 void nsClientAuthRememberService::ClearRememberedDecisions()
 {
   ReentrantMonitorAutoEnter lock(monitor);
   RemoveAllFromMemory();
 }
 
+void nsClientAuthRememberService::ClearAllRememberedDecisions()
+{
+  RefPtr<nsClientAuthRememberService> svc =
+    PublicSSLState()->GetClientAuthRememberService();
+  svc->ClearRememberedDecisions();
+
+  svc = PrivateSSLState()->GetClientAuthRememberService();
+  svc->ClearRememberedDecisions();
+}
+
 void
 nsClientAuthRememberService::RemoveAllFromMemory()
 {
   mSettingsTable.Clear();
 }
 
 static nsresult
 GetCertFingerprintByOidTag(CERTCertificate* nsscert,
--- a/security/manager/ssl/src/nsClientAuthRemember.h
+++ b/security/manager/ssl/src/nsClientAuthRemember.h
@@ -123,16 +123,17 @@ public:
 
   nsresult RememberDecision(const nsACString & aHostName, 
                             CERTCertificate *aServerCert, CERTCertificate *aClientCert);
   nsresult HasRememberedDecision(const nsACString & aHostName, 
                                  CERTCertificate *aServerCert, 
                                  nsACString & aCertDBKey, bool *_retval);
 
   void ClearRememberedDecisions();
+  static void ClearAllRememberedDecisions();
 
 protected:
     mozilla::ReentrantMonitor monitor;
     nsTHashtable<nsClientAuthRememberEntry> mSettingsTable;
 
     void RemoveAllFromMemory();
     nsresult AddEntryToList(const nsACString &host, 
                             const nsACString &server_fingerprint,
--- a/security/manager/ssl/src/nsNSSCallbacks.cpp
+++ b/security/manager/ssl/src/nsNSSCallbacks.cpp
@@ -18,16 +18,17 @@
 #include "nsThreadUtils.h"
 #include "nsIPrompt.h"
 #include "nsProxyRelease.h"
 #include "PSMRunnable.h"
 #include "ScopedNSSTypes.h"
 #include "nsIConsoleService.h"
 #include "nsIHttpChannelInternal.h"
 #include "nsCRT.h"
+#include "SharedSSLState.h"
 
 #include "ssl.h"
 #include "sslproto.h"
 #include "ocsp.h"
 #include "nssb64.h"
 
 using namespace mozilla;
 using namespace mozilla::psm;
@@ -836,17 +837,18 @@ void HandshakeCallback(PRFileDesc* fd, v
 
   if (infoObject) {
     // This is the first callback on resumption handshakes
     infoObject->SetFirstServerHelloReceived();
   }
 
   // If the handshake completed, then we know the site is TLS tolerant (if this
   // was a TLS connection).
-  nsSSLIOLayerHelpers::rememberTolerantSite(infoObject);
+  nsSSLIOLayerHelpers& ioLayerHelpers = infoObject->SharedState().IOLayerHelpers();
+  ioLayerHelpers.rememberTolerantSite(infoObject);
 
   if (SECSuccess != SSL_SecurityStatus(fd, &sslStatus, &cipherName, &keyLength,
                                        &encryptBits, &signer, nullptr)) {
     return;
   }
 
   int32_t secStatus;
   if (sslStatus == SSL_SECURITY_STATUS_OFF)
@@ -854,33 +856,33 @@ void HandshakeCallback(PRFileDesc* fd, v
   else
     secStatus = nsIWebProgressListener::STATE_IS_SECURE
               | nsIWebProgressListener::STATE_SECURE_HIGH;
 
   PRBool siteSupportsSafeRenego;
   if (SSL_HandshakeNegotiatedExtension(fd, ssl_renegotiation_info_xtn, &siteSupportsSafeRenego) != SECSuccess
       || !siteSupportsSafeRenego) {
 
-    bool wantWarning = (nsSSLIOLayerHelpers::getWarnLevelMissingRFC5746() > 0);
+    bool wantWarning = (ioLayerHelpers.getWarnLevelMissingRFC5746() > 0);
 
     nsCOMPtr<nsIConsoleService> console;
     if (infoObject && wantWarning) {
       console = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
       if (console) {
         nsXPIDLCString hostName;
         infoObject->GetHostName(getter_Copies(hostName));
 
         nsAutoString msg;
         msg.Append(NS_ConvertASCIItoUTF16(hostName));
         msg.Append(NS_LITERAL_STRING(" : server does not support RFC 5746, see CVE-2009-3555"));
 
         console->LogStringMessage(msg.get());
       }
     }
-    if (nsSSLIOLayerHelpers::treatUnsafeNegotiationAsBroken()) {
+    if (ioLayerHelpers.treatUnsafeNegotiationAsBroken()) {
       secStatus = nsIWebProgressListener::STATE_IS_BROKEN;
     }
   }
 
 
   ScopedCERTCertificate serverCert(SSL_PeerCertificate(fd));
   const char* caName = nullptr; // caName is a pointer only, no ownership
   char* certOrgName = CERT_GetOrgName(&serverCert->issuer);
--- a/security/manager/ssl/src/nsNSSCertificateDB.cpp
+++ b/security/manager/ssl/src/nsNSSCertificateDB.cpp
@@ -26,40 +26,46 @@
 #include "nsArrayUtils.h"
 #include "nsNSSShutDown.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIPrompt.h"
 #include "nsThreadUtils.h"
 #include "ScopedNSSTypes.h"
+#include "nsIObserverService.h"
+#include "nsRecentBadCerts.h"
+#include "SharedSSLState.h"
 
 #include "nspr.h"
 #include "certdb.h"
 #include "secerr.h"
 #include "nssb64.h"
 #include "secasn1.h"
 #include "secder.h"
 #include "ssl.h"
 #include "ocsp.h"
 #include "plbase64.h"
 
 using namespace mozilla;
+using mozilla::psm::SharedSSLState;
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gPIPNSSLog;
 #endif
 
 static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
 
 
 NS_IMPL_THREADSAFE_ISUPPORTS2(nsNSSCertificateDB, nsIX509CertDB, nsIX509CertDB2)
 
 nsNSSCertificateDB::nsNSSCertificateDB()
+: mBadCertsLock("nsNSSCertificateDB::mBadCertsLock")
 {
+  SharedSSLState::NoteCertDBServiceInstantiated();
 }
 
 nsNSSCertificateDB::~nsNSSCertificateDB()
 {
 }
 
 NS_IMETHODIMP
 nsNSSCertificateDB::FindCertByNickname(nsISupports *aToken,
@@ -1638,8 +1644,26 @@ nsNSSCertificateDB::GetCerts(nsIX509Cert
   // nsNSSCertList 1) adopts certList, and 2) handles the nullptr case fine.
   // (returns an empty list) 
   nssCertList = new nsNSSCertList(certList, true);
 
   *_retval = nssCertList;
   NS_ADDREF(*_retval);
   return NS_OK;
 }
+
+NS_IMETHODIMP
+nsNSSCertificateDB::GetRecentBadCerts(bool isPrivate, nsIRecentBadCerts** result)
+{
+  MutexAutoLock lock(mBadCertsLock);
+  if (isPrivate) {
+    if (!mPrivateRecentBadCerts) {
+      mPrivateRecentBadCerts = new nsRecentBadCerts;
+    }
+    NS_ADDREF(*result = mPrivateRecentBadCerts);
+  } else {
+    if (!mPublicRecentBadCerts) {
+      mPublicRecentBadCerts = new nsRecentBadCerts;
+    }
+    NS_ADDREF(*result = mPublicRecentBadCerts);
+  }
+  return NS_OK;
+}
--- a/security/manager/ssl/src/nsNSSCertificateDB.h
+++ b/security/manager/ssl/src/nsNSSCertificateDB.h
@@ -2,20 +2,23 @@
  * 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 __NSNSSCERTIFICATEDB_H__
 #define __NSNSSCERTIFICATEDB_H__
 
 #include "nsIX509CertDB.h"
 #include "nsIX509CertDB2.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/Mutex.h"
 #include "certt.h"
 
 class nsCString;
 class nsIArray;
+class nsRecentBadCerts;
 
 class nsNSSCertificateDB : public nsIX509CertDB, public nsIX509CertDB2
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIX509CERTDB
   NS_DECL_NSIX509CERTDB2
 
@@ -43,16 +46,20 @@ private:
                     uint32_t      type, 
                     uint32_t     *_count,
                     PRUnichar  ***_certNameList);
 
   CERTDERCerts *getCertsFromPackage(PLArenaPool *arena, uint8_t *data, 
                                     uint32_t length);
   nsresult handleCACertDownload(nsIArray *x509Certs, 
                                 nsIInterfaceRequestor *ctx);
+
+  mozilla::Mutex mBadCertsLock;
+  mozilla::RefPtr<nsRecentBadCerts> mPublicRecentBadCerts;
+  mozilla::RefPtr<nsRecentBadCerts> mPrivateRecentBadCerts;
 };
 
 #define NS_X509CERTDB_CID { /* fb0bbc5c-452e-4783-b32c-80124693d871 */ \
     0xfb0bbc5c,                                                        \
     0x452e,                                                            \
     0x4783,                                                            \
     {0xb3, 0x2c, 0x80, 0x12, 0x46, 0x93, 0xd8, 0x71}                   \
   }
--- a/security/manager/ssl/src/nsNSSComponent.cpp
+++ b/security/manager/ssl/src/nsNSSComponent.cpp
@@ -55,16 +55,17 @@
 #include "nsIServiceManager.h"
 #include "nsIFile.h"
 #include "nsITokenPasswordDialogs.h"
 #include "nsICRLManager.h"
 #include "nsNSSShutDown.h"
 #include "nsSmartCardEvent.h"
 #include "nsIKeyModule.h"
 #include "ScopedNSSTypes.h"
+#include "SharedSSLState.h"
 
 #include "nss.h"
 #include "pk11func.h"
 #include "ssl.h"
 #include "sslproto.h"
 #include "secmod.h"
 #include "sechash.h"
 #include "secmime.h"
@@ -395,17 +396,17 @@ nsNSSComponent::~nsNSSComponent()
     }
 
     mUpdateTimerInitialized = false;
   }
 
   // All cleanup code requiring services needs to happen in xpcom_shutdown
 
   ShutdownNSS();
-  nsSSLIOLayerHelpers::Cleanup();
+  SharedSSLState::GlobalCleanup();
   RememberCertErrorsTable::Cleanup();
   --mInstanceCount;
   delete mShutdownObjectList;
 
   // We are being freed, drop the haveLoaded flag to re-enable
   // potential nss initialization later.
   EnsureNSSInitialized(nssShutdown);
 
@@ -1855,19 +1856,16 @@ nsNSSComponent::ShutdownNSS()
     UnregisterMyOCSPAIAInfoCallback();
 
     if (mPrefBranch) {
       mPrefBranch->RemoveObserver("security.", this);
     }
 
     ShutdownSmartCardThreads();
     SSL_ClearSessionCache();
-    if (mClientAuthRememberService) {
-      mClientAuthRememberService->ClearRememberedDecisions();
-    }
     UnloadLoadableRoots();
     CleanupIdentityInfo();
     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("evaporating psm resources\n"));
     mShutdownObjectList->evaporateAllNSSResources();
     EnsureNSSInitialized(nssShutdown);
     if (SECSuccess != ::NSS_Shutdown()) {
       PR_LOG(gPIPNSSLog, PR_LOG_ALWAYS, ("NSS SHUTDOWN FAILURE\n"));
       rv = NS_ERROR_FAILURE;
@@ -1928,37 +1926,18 @@ nsNSSComponent::Init()
     PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to Initialize NSS.\n"));
 
     DeregisterObservers();
     mPIPNSSBundle = nullptr;
     return rv;
   }
 
   RememberCertErrorsTable::Init();
-  nsSSLIOLayerHelpers::Init();
-  char *unrestricted_hosts=nullptr;
-  mPrefBranch->GetCharPref("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts);
-  if (unrestricted_hosts) {
-    nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(nsDependentCString(unrestricted_hosts));
-    nsMemory::Free(unrestricted_hosts);
-    unrestricted_hosts=nullptr;
-  }
-
-  bool enabled = false;
-  mPrefBranch->GetBoolPref("security.ssl.treat_unsafe_negotiation_as_broken", &enabled);
-  nsSSLIOLayerHelpers::setTreatUnsafeNegotiationAsBroken(enabled);
-
-  int32_t warnLevel = 1;
-  mPrefBranch->GetIntPref("security.ssl.warn_missing_rfc5746", &warnLevel);
-  nsSSLIOLayerHelpers::setWarnLevelMissingRFC5746(warnLevel);
+  SharedSSLState::GlobalInit();
   
-  mClientAuthRememberService = new nsClientAuthRememberService;
-  if (mClientAuthRememberService)
-    mClientAuthRememberService->Init();
-
   createBackgroundThreads();
   if (!mCertVerificationThread)
   {
     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS init, could not create threads\n"));
 
     DeregisterObservers();
     mPIPNSSBundle = nullptr;
     return NS_ERROR_OUT_OF_MEMORY;
@@ -2266,30 +2245,16 @@ nsNSSComponent::Observe(nsISupports *aSu
       SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, enabled);
     } else if (prefName.Equals("security.ssl.require_safe_negotiation")) {
       mPrefBranch->GetBoolPref("security.ssl.require_safe_negotiation", &enabled);
       SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, enabled);
     } else if (prefName.Equals("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref")) {
       mPrefBranch->GetBoolPref("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref", &enabled);
       SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION, 
         enabled ? SSL_RENEGOTIATE_UNRESTRICTED : SSL_RENEGOTIATE_REQUIRES_XTN);
-    } else if (prefName.Equals("security.ssl.renego_unrestricted_hosts")) {
-      char *unrestricted_hosts=nullptr;
-      mPrefBranch->GetCharPref("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts);
-      if (unrestricted_hosts) {
-        nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(nsDependentCString(unrestricted_hosts));
-        nsMemory::Free(unrestricted_hosts);
-      }
-    } else if (prefName.Equals("security.ssl.treat_unsafe_negotiation_as_broken")) {
-      mPrefBranch->GetBoolPref("security.ssl.treat_unsafe_negotiation_as_broken", &enabled);
-      nsSSLIOLayerHelpers::setTreatUnsafeNegotiationAsBroken(enabled);
-    } else if (prefName.Equals("security.ssl.warn_missing_rfc5746")) {
-      int32_t warnLevel = 1;
-      mPrefBranch->GetIntPref("security.ssl.warn_missing_rfc5746", &warnLevel);
-      nsSSLIOLayerHelpers::setWarnLevelMissingRFC5746(warnLevel);
 #ifdef SSL_ENABLE_FALSE_START // Requires NSS 3.12.8
     } else if (prefName.Equals("security.ssl.enable_false_start")) {
       mPrefBranch->GetBoolPref("security.ssl.enable_false_start", &enabled);
       SSL_OptionSetDefault(SSL_ENABLE_FALSE_START, enabled);
 #endif
     } else if (prefName.Equals("security.OCSP.enabled")
                || prefName.Equals("security.CRL_download.enabled")
                || prefName.Equals("security.fresh_revocation_info.require")
@@ -2382,19 +2347,17 @@ nsresult nsNSSComponent::LogoutAuthentic
   nsCOMPtr<nsICertOverrideService> icos =
     do_GetService("@mozilla.org/security/certoverride;1");
   if (icos) {
     icos->ClearValidityOverride(
             NS_LITERAL_CSTRING("all:temporary-certificates"),
             0);
   }
 
-  if (mClientAuthRememberService) {
-    mClientAuthRememberService->ClearRememberedDecisions();
-  }
+  nsClientAuthRememberService::ClearAllRememberedDecisions();
 
   return mShutdownObjectList->doPK11Logout();
 }
 
 nsresult
 nsNSSComponent::RegisterObservers()
 {
   // Happens once during init only, no mutex protection.
@@ -2564,24 +2527,16 @@ nsNSSComponent::DoProfileChangeNetRestor
 {
   /* XXX this doesn't work well, since nothing expects null pointers */
   deleteBackgroundThreads();
   createBackgroundThreads();
   mIsNetworkDown = false;
 }
 
 NS_IMETHODIMP
-nsNSSComponent::GetClientAuthRememberService(nsClientAuthRememberService **cars)
-{
-  NS_ENSURE_ARG_POINTER(cars);
-  NS_IF_ADDREF(*cars = mClientAuthRememberService);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsNSSComponent::IsNSSInitialized(bool *initialized)
 {
   MutexAutoLock lock(mutex);
   *initialized = mNSSInitialized;
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/security/manager/ssl/src/nsNSSComponent.h
+++ b/security/manager/ssl/src/nsNSSComponent.h
@@ -149,18 +149,16 @@ class NS_NO_VTABLE nsINSSComponent : pub
   NS_IMETHOD LaunchSmartCardThread(SECMODModule *module) = 0;
 
   NS_IMETHOD ShutdownSmartCardThread(SECMODModule *module) = 0;
 
   NS_IMETHOD PostEvent(const nsAString &eventType, const nsAString &token) = 0;
 
   NS_IMETHOD DispatchEvent(const nsAString &eventType, const nsAString &token) = 0;
   
-  NS_IMETHOD GetClientAuthRememberService(nsClientAuthRememberService **cars) = 0;
-
   NS_IMETHOD EnsureIdentityInfoLoaded() = 0;
 
   NS_IMETHOD IsNSSInitialized(bool *initialized) = 0;
 
   NS_IMETHOD GetDefaultCERTValInParam(
                   mozilla::RefPtr<nsCERTValInParamWrapper> &out) = 0;
   NS_IMETHOD GetDefaultCERTValInParamLocalOnly(
                   mozilla::RefPtr<nsCERTValInParamWrapper> &out) = 0;
@@ -254,17 +252,16 @@ public:
   NS_IMETHOD LogoutAuthenticatedPK11();
   NS_IMETHOD DownloadCRLDirectly(nsAutoString, nsAutoString);
   NS_IMETHOD RememberCert(CERTCertificate *cert);
 
   NS_IMETHOD LaunchSmartCardThread(SECMODModule *module);
   NS_IMETHOD ShutdownSmartCardThread(SECMODModule *module);
   NS_IMETHOD PostEvent(const nsAString &eventType, const nsAString &token);
   NS_IMETHOD DispatchEvent(const nsAString &eventType, const nsAString &token);
-  NS_IMETHOD GetClientAuthRememberService(nsClientAuthRememberService **cars);
   NS_IMETHOD EnsureIdentityInfoLoaded();
   NS_IMETHOD IsNSSInitialized(bool *initialized);
 
   NS_IMETHOD GetDefaultCERTValInParam(
                   mozilla::RefPtr<nsCERTValInParamWrapper> &out);
   NS_IMETHOD GetDefaultCERTValInParamLocalOnly(
                   mozilla::RefPtr<nsCERTValInParamWrapper> &out);
 private:
@@ -322,17 +319,16 @@ private:
   SmartCardThreadList *mThreadList;
   bool mIsNetworkDown;
 
   void deleteBackgroundThreads();
   void createBackgroundThreads();
   nsCertVerificationThread *mCertVerificationThread;
 
   nsNSSHttpInterface mHttpForNSS;
-  mozilla::RefPtr<nsClientAuthRememberService> mClientAuthRememberService;
   mozilla::RefPtr<nsCERTValInParamWrapper> mDefaultCERTValInParam;
   mozilla::RefPtr<nsCERTValInParamWrapper> mDefaultCERTValInParamLocalOnly;
 
   static PRStatus IdentityInfoInit(void);
   PRCallOnceType mIdentityInfoCallOnce;
 
 public:
   static bool globalConstFlagUsePKIXVerification;
--- a/security/manager/ssl/src/nsNSSIOLayer.cpp
+++ b/security/manager/ssl/src/nsNSSIOLayer.cpp
@@ -23,16 +23,18 @@
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsISecureBrowserUI.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsIConsoleService.h"
 #include "PSMRunnable.h"
 #include "ScopedNSSTypes.h"
+#include "SharedSSLState.h"
+#include "mozilla/Preferences.h"
 
 #include "ssl.h"
 #include "secerr.h"
 #include "sslerr.h"
 #include "secder.h"
 #include "keyhi.h"
 
 using namespace mozilla;
@@ -58,19 +60,20 @@ static NS_DEFINE_CID(kNSSComponentCID, N
 typedef enum {ASK, AUTO} SSM_UserCertChoice;
 
 } // unnamed namespace
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gPIPNSSLog;
 #endif
 
-nsNSSSocketInfo::nsNSSSocketInfo(uint32_t providerFlags)
+nsNSSSocketInfo::nsNSSSocketInfo(SharedSSLState& aState, uint32_t providerFlags)
   : mFd(nullptr),
     mCertVerificationState(before_cert_verification),
+    mSharedState(aState),
     mForSTARTTLS(false),
     mSSL3Enabled(false),
     mTLSEnabled(false),
     mHandshakePending(true),
     mHasCleartextPhase(false),
     mHandshakeInProgress(false),
     mAllowTLSIntoleranceTimeout(true),
     mRememberClientAuthCertificate(false),
@@ -452,16 +455,21 @@ void nsNSSSocketInfo::SetHandshakeInProg
   }
 }
 
 void nsNSSSocketInfo::SetAllowTLSIntoleranceTimeout(bool aAllow)
 {
   mAllowTLSIntoleranceTimeout = aAllow;
 }
 
+SharedSSLState& nsNSSSocketInfo::SharedState()
+{
+  return mSharedState;
+}
+
 bool nsNSSSocketInfo::HandshakeTimeout()
 {
   if (!mAllowTLSIntoleranceTimeout)
     return false;
 
   if (!mHandshakeInProgress)
     return false; // have not even sent client hello yet
 
@@ -909,17 +917,18 @@ int32_t checkHandshake(int32_t bytesTran
       if (PR_WOULD_BLOCK_ERROR == err) {
         socketInfo->SetHandshakeInProgress(true);
         return bytesTransfered;
       }
 
       if (!wantRetry // no decision yet
           && isTLSIntoleranceError(err, socketInfo->GetHasCleartextPhase()))
       {
-        wantRetry = nsSSLIOLayerHelpers::rememberPossibleTLSProblemSite(socketInfo);
+        nsSSLIOLayerHelpers& helpers = socketInfo->SharedState().IOLayerHelpers();
+        wantRetry = helpers.rememberPossibleTLSProblemSite(socketInfo);
       }
     }
     
     // This is the common place where we trigger non-cert-errors on a SSL
     // socket. This might be reached at any time of the connection.
     //
     // The socketInfo->GetErrorCode() check is here to ensure we don't try to
     // do the synchronous dispatch to the main thread unnecessarily after we've
@@ -937,18 +946,18 @@ int32_t checkHandshake(int32_t bytesTran
   }
   else if (wasReading && 0 == bytesTransfered) // zero bytes on reading, socket closed
   {
     if (handleHandshakeResultNow)
     {
       if (!wantRetry // no decision yet
           && !socketInfo->GetHasCleartextPhase()) // mirror PR_CONNECT_RESET_ERROR treament
       {
-        wantRetry = 
-          nsSSLIOLayerHelpers::rememberPossibleTLSProblemSite(socketInfo);
+        nsSSLIOLayerHelpers& helpers = socketInfo->SharedState().IOLayerHelpers();
+        wantRetry = helpers.rememberPossibleTLSProblemSite(socketInfo);
       }
     }
   }
 
   if (wantRetry) {
     // We want to cause the network layer to retry the connection.
     PR_SetError(PR_CONNECT_RESET_ERROR, 0);
     if (wasReading)
@@ -1026,22 +1035,26 @@ nsSSLIOLayerPoll(PRFileDesc * fd, int16_
   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("[%p] poll SSL socket returned %d\n",
                                     (void*)fd, (int) result));
   return result;
 }
 
 bool nsSSLIOLayerHelpers::nsSSLIOLayerInitialized = false;
 PRDescIdentity nsSSLIOLayerHelpers::nsSSLIOLayerIdentity;
 PRIOMethods nsSSLIOLayerHelpers::nsSSLIOLayerMethods;
-Mutex *nsSSLIOLayerHelpers::mutex = nullptr;
-nsTHashtable<nsCStringHashKey> *nsSSLIOLayerHelpers::mTLSIntolerantSites = nullptr;
-nsTHashtable<nsCStringHashKey> *nsSSLIOLayerHelpers::mTLSTolerantSites = nullptr;
-nsTHashtable<nsCStringHashKey> *nsSSLIOLayerHelpers::mRenegoUnrestrictedSites = nullptr;
-bool nsSSLIOLayerHelpers::mTreatUnsafeNegotiationAsBroken = false;
-int32_t nsSSLIOLayerHelpers::mWarnLevelMissingRFC5746 = 1;
+
+nsSSLIOLayerHelpers::nsSSLIOLayerHelpers()
+: mutex(nullptr)
+, mTLSIntolerantSites(nullptr)
+, mTLSTolerantSites(nullptr)
+, mRenegoUnrestrictedSites(nullptr)
+, mTreatUnsafeNegotiationAsBroken(false)
+, mWarnLevelMissingRFC5746(1)
+{
+}
 
 static int _PSM_InvalidInt(void)
 {
     PR_ASSERT(!"I/O method is invalid");
     PR_SetError(PR_INVALID_METHOD_ERROR, 0);
     return -1;
 }
 
@@ -1185,16 +1198,63 @@ static int PSMAvailable(void)
 
 static int64_t PSMAvailable64(void)
 {
   // This is called through PR_Available(), but is not implemented in PSM
   PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
   return -1;
 }
 
+namespace {
+class PrefObserver : public nsIObserver {
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIOBSERVER
+  PrefObserver(nsSSLIOLayerHelpers* aOwner) : mOwner(aOwner) {}
+  virtual ~PrefObserver() {}
+private:
+  nsSSLIOLayerHelpers* mOwner;
+};
+} // namespace anonymous
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(PrefObserver, nsIObserver)
+
+NS_IMETHODIMP
+PrefObserver::Observe(nsISupports *aSubject, const char *aTopic, 
+                      const PRUnichar *someData)
+{
+  if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
+    NS_ConvertUTF16toUTF8 prefName(someData);
+
+    if (prefName.Equals("security.ssl.renego_unrestricted_hosts")) {
+      nsCString unrestricted_hosts;
+      Preferences::GetCString("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts);
+      if (!unrestricted_hosts.IsEmpty()) {
+        mOwner->setRenegoUnrestrictedSites(unrestricted_hosts);
+      }
+    } else if (prefName.Equals("security.ssl.treat_unsafe_negotiation_as_broken")) {
+      bool enabled;
+      Preferences::GetBool("security.ssl.treat_unsafe_negotiation_as_broken", &enabled);
+      mOwner->setTreatUnsafeNegotiationAsBroken(enabled);
+    } else if (prefName.Equals("security.ssl.warn_missing_rfc5746")) {
+      int32_t warnLevel = 1;
+      Preferences::GetInt("security.ssl.warn_missing_rfc5746", &warnLevel);
+      mOwner->setWarnLevelMissingRFC5746(warnLevel);
+    }
+  }
+  return NS_OK;
+}
+
+nsSSLIOLayerHelpers::~nsSSLIOLayerHelpers()
+{
+  Preferences::RemoveObserver(mPrefObserver, "security.ssl.renego_unrestricted_hosts");
+  Preferences::RemoveObserver(mPrefObserver, "security.ssl.treat_unsafe_negotiation_as_broken");
+  Preferences::RemoveObserver(mPrefObserver, "security.ssl.warn_missing_rfc5746");
+}
+
 nsresult nsSSLIOLayerHelpers::Init()
 {
   if (!nsSSLIOLayerInitialized) {
     nsSSLIOLayerInitialized = true;
     nsSSLIOLayerIdentity = PR_GetUniqueIdentity("NSS layer");
     nsSSLIOLayerMethods  = *PR_GetDefaultIOMethods();
 
     nsSSLIOLayerMethods.available = (PRAvailableFN)PSMAvailable;
@@ -1239,33 +1299,60 @@ nsresult nsSSLIOLayerHelpers::Init()
   // Initialize the tolerant site hashtable to 16 items at the start seems
   // reasonable as most servers are TLS tolerant. We just want to lower 
   // the rate of hashtable array reallocation.
   mTLSTolerantSites->Init(16);
 
   mRenegoUnrestrictedSites = new nsTHashtable<nsCStringHashKey>();
   mRenegoUnrestrictedSites->Init(1);
 
-  mTreatUnsafeNegotiationAsBroken = false;
-  
+  nsCString unrestricted_hosts;
+  Preferences::GetCString("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts);
+  if (!unrestricted_hosts.IsEmpty()) {
+    setRenegoUnrestrictedSites(unrestricted_hosts);
+  }
+
+  bool enabled = false;
+  Preferences::GetBool("security.ssl.treat_unsafe_negotiation_as_broken", &enabled);
+  setTreatUnsafeNegotiationAsBroken(enabled);
+
+  int32_t warnLevel = 1;
+  Preferences::GetInt("security.ssl.warn_missing_rfc5746", &warnLevel);
+  setWarnLevelMissingRFC5746(warnLevel);
+
+  mPrefObserver = new PrefObserver(this);
+  Preferences::AddStrongObserver(mPrefObserver,
+                                 "security.ssl.renego_unrestricted_hosts");
+  Preferences::AddStrongObserver(mPrefObserver,
+                                 "security.ssl.treat_unsafe_negotiation_as_broken");
+  Preferences::AddStrongObserver(mPrefObserver,
+                                 "security.ssl.warn_missing_rfc5746");
+
   return NS_OK;
 }
 
+void nsSSLIOLayerHelpers::clearStoredData()
+{
+  mRenegoUnrestrictedSites->Clear();
+  mTLSTolerantSites->Clear();
+  mTLSIntolerantSites->Clear();
+}
+
 void nsSSLIOLayerHelpers::addIntolerantSite(const nsCString &str)
 {
   MutexAutoLock lock(*mutex);
   // Remember intolerant site only if it is not known as tolerant
   if (!mTLSTolerantSites->Contains(str))
-    nsSSLIOLayerHelpers::mTLSIntolerantSites->PutEntry(str);
+    mTLSIntolerantSites->PutEntry(str);
 }
 
 void nsSSLIOLayerHelpers::removeIntolerantSite(const nsCString &str)
 {
   MutexAutoLock lock(*mutex);
-  nsSSLIOLayerHelpers::mTLSIntolerantSites->RemoveEntry(str);
+  mTLSIntolerantSites->RemoveEntry(str);
 }
 
 bool nsSSLIOLayerHelpers::isKnownAsIntolerantSite(const nsCString &str)
 {
   MutexAutoLock lock(*mutex);
   return mTLSIntolerantSites->Contains(str);
 }
 
@@ -1918,16 +2005,17 @@ void ClientAuthDataRunnable::RunOnTarget
   ScopedCERTCertList certList;
   CERTCertListNode* node;
   ScopedCERTCertNicknames nicknames;
   char* extracted = nullptr;
   int keyError = 0; /* used for private key retrieval error */
   SSM_UserCertChoice certChoice;
   int32_t NumberOfCerts = 0;
   void * wincx = mSocketInfo;
+  nsresult rv;
 
   /* create caNameStrings */
   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   if (!arena) {
     goto loser;
   }
 
   caNameStrings = (char**)PORT_ArenaAlloc(arena, 
@@ -2019,29 +2107,24 @@ void ClientAuthDataRunnable::RunOnTarget
     }
   }
   else { // Not Auto => ask
     /* Get the SSL Certificate */
 
     nsXPIDLCString hostname;
     mSocketInfo->GetHostName(getter_Copies(hostname));
 
-    nsresult rv;
-    NS_DEFINE_CID(nssComponentCID, NS_NSSCOMPONENT_CID);
-    nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(nssComponentCID, &rv));
-    RefPtr<nsClientAuthRememberService> cars;
-    if (nssComponent) {
-      nssComponent->GetClientAuthRememberService(byRef(cars));
-    }
+    RefPtr<nsClientAuthRememberService> cars =
+        mSocketInfo->SharedState().GetClientAuthRememberService();
 
     bool hasRemembered = false;
     nsCString rememberedDBKey;
     if (cars) {
       bool found;
-      nsresult rv = cars->HasRememberedDecision(hostname, mServerCert,
+      rv = cars->HasRememberedDecision(hostname, mServerCert,
                                                 rememberedDBKey, &found);
       if (NS_SUCCEEDED(rv) && found) {
         hasRemembered = true;
       }
     }
 
     bool canceled = false;
 
@@ -2214,19 +2297,19 @@ if (!hasRemembered)
         nsMemory::Free(certNicknameList[CertsToUse]);
         continue;
       }
 
       ++CertsToUse;
     }
 
     /* Throw up the client auth dialog and get back the index of the selected cert */
-    rv = getNSSDialogs((void**)&dialogs, 
-                       NS_GET_IID(nsIClientAuthDialogs),
-                       NS_CLIENTAUTHDIALOGS_CONTRACTID);
+    nsresult rv = getNSSDialogs((void**)&dialogs, 
+                                NS_GET_IID(nsIClientAuthDialogs),
+                                NS_CLIENTAUTHDIALOGS_CONTRACTID);
 
     if (NS_FAILED(rv)) {
       NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(CertsToUse, certNicknameList);
       NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(CertsToUse, certDetailsList);
       goto loser;
     }
 
     {
@@ -2360,32 +2443,32 @@ loser:
     PR_Close(sslSock);
   }
   return nullptr;
 }
 
 static nsresult
 nsSSLIOLayerSetOptions(PRFileDesc *fd, bool forSTARTTLS, 
                        const char *proxyHost, const char *host, int32_t port,
-                       bool anonymousLoad, nsNSSSocketInfo *infoObject)
+                       nsNSSSocketInfo *infoObject)
 {
   nsNSSShutDownPreventionLock locker;
   if (forSTARTTLS || proxyHost) {
     if (SECSuccess != SSL_OptionSet(fd, SSL_SECURITY, false)) {
       return NS_ERROR_FAILURE;
     }
     infoObject->SetHasCleartextPhase(true);
   }
 
   // Let's see if we're trying to connect to a site we know is
   // TLS intolerant.
   nsAutoCString key;
   key = nsDependentCString(host) + NS_LITERAL_CSTRING(":") + nsPrintfCString("%d", port);
 
-  if (nsSSLIOLayerHelpers::isKnownAsIntolerantSite(key)) {
+  if (infoObject->SharedState().IOLayerHelpers().isKnownAsIntolerantSite(key)) {
     if (SECSuccess != SSL_OptionSet(fd, SSL_ENABLE_TLS, false))
       return NS_ERROR_FAILURE;
 
     infoObject->SetAllowTLSIntoleranceTimeout(false);
       
     // We assume that protocols that use the STARTTLS mechanism should support
     // modern hellos. For other protocols, if we suspect a site 
     // does not support TLS, let's also use V2 hellos.
@@ -2402,40 +2485,44 @@ nsSSLIOLayerSetOptions(PRFileDesc *fd, b
   if (SECSuccess != SSL_OptionGet(fd, SSL_ENABLE_TLS, &enabled)) {
     return NS_ERROR_FAILURE;
   }
   infoObject->SetTLSEnabled(enabled);
 
   if (SECSuccess != SSL_OptionSet(fd, SSL_HANDSHAKE_AS_CLIENT, true)) {
     return NS_ERROR_FAILURE;
   }
-  
-  if (nsSSLIOLayerHelpers::isRenegoUnrestrictedSite(nsDependentCString(host))) {
+
+  nsSSLIOLayerHelpers& ioHelpers = infoObject->SharedState().IOLayerHelpers();
+  if (ioHelpers.isRenegoUnrestrictedSite(nsDependentCString(host))) {
     if (SECSuccess != SSL_OptionSet(fd, SSL_REQUIRE_SAFE_NEGOTIATION, false)) {
       return NS_ERROR_FAILURE;
     }
     if (SECSuccess != SSL_OptionSet(fd, SSL_ENABLE_RENEGOTIATION, SSL_RENEGOTIATE_UNRESTRICTED)) {
       return NS_ERROR_FAILURE;
     }
   }
 
-  // Set the Peer ID so that SSL proxy connections work properly.
-  char *peerId;
-  if (anonymousLoad) {  // See bug #466080. Separate the caches.
-      peerId = PR_smprintf("anon:%s:%d", host, port);
-  } else {
-      peerId = PR_smprintf("%s:%d", host, port);
+  // Set the Peer ID so that SSL proxy connections work properly and to
+  // separate anonymous and/or private browsing connections.
+  uint32_t flags = infoObject->GetProviderFlags();
+  nsAutoCString peerId;
+  if (flags & nsISocketProvider::ANONYMOUS_CONNECT) { // See bug 466080
+    peerId.Append("anon:");
   }
-  
-  if (SECSuccess != SSL_SetSockPeerID(fd, peerId)) {
-    PR_smprintf_free(peerId);
+  if (flags & nsISocketProvider::NO_PERMANENT_STORAGE) {
+    peerId.Append("private:");
+  }
+  peerId.Append(host);
+  peerId.Append(':');
+  peerId.AppendInt(port);
+  if (SECSuccess != SSL_SetSockPeerID(fd, peerId.get())) {
     return NS_ERROR_FAILURE;
   }
 
-  PR_smprintf_free(peerId);
   return NS_OK;
 }
 
 nsresult
 nsSSLIOLayerAddToSocket(int32_t family,
                         const char* host,
                         int32_t port,
                         const char* proxyHost,
@@ -2445,35 +2532,35 @@ nsSSLIOLayerAddToSocket(int32_t family,
                         bool forSTARTTLS,
                         uint32_t providerFlags)
 {
   nsNSSShutDownPreventionLock locker;
   PRFileDesc* layer = nullptr;
   nsresult rv;
   PRStatus stat;
 
-  nsNSSSocketInfo* infoObject = new nsNSSSocketInfo(providerFlags);
+  SharedSSLState* sharedState =
+    providerFlags & nsISocketProvider::NO_PERMANENT_STORAGE ? PrivateSSLState() : PublicSSLState();
+  nsNSSSocketInfo* infoObject = new nsNSSSocketInfo(*sharedState, providerFlags);
   if (!infoObject) return NS_ERROR_FAILURE;
   
   NS_ADDREF(infoObject);
   infoObject->SetForSTARTTLS(forSTARTTLS);
   infoObject->SetHostName(host);
   infoObject->SetPort(port);
 
-  bool anonymousLoad = providerFlags & nsISocketProvider::ANONYMOUS_CONNECT;
   PRFileDesc *sslSock = nsSSLIOLayerImportFD(fd, infoObject, host);
   if (!sslSock) {
     NS_ASSERTION(false, "NSS: Error importing socket");
     goto loser;
   }
 
   infoObject->SetFileDescPtr(sslSock);
 
-  rv = nsSSLIOLayerSetOptions(sslSock,
-                              forSTARTTLS, proxyHost, host, port, anonymousLoad,
+  rv = nsSSLIOLayerSetOptions(sslSock, forSTARTTLS, proxyHost, host, port,
                               infoObject);
 
   if (NS_FAILED(rv))
     goto loser;
 
   /* Now, layer ourselves on top of the SSL socket... */
   layer = PR_CreateIOLayerStub(nsSSLIOLayerHelpers::nsSSLIOLayerIdentity,
                                &nsSSLIOLayerHelpers::nsSSLIOLayerMethods);
@@ -2492,16 +2579,18 @@ nsSSLIOLayerAddToSocket(int32_t family,
   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("[%p] Socket set up\n", (void*)sslSock));
   infoObject->QueryInterface(NS_GET_IID(nsISupports), (void**) (info));
 
   // We are going use a clear connection first //
   if (forSTARTTLS || proxyHost) {
     infoObject->SetHandshakePending(false);
   }
 
+  infoObject->SharedState().NoteSocketCreated();
+
   return NS_OK;
  loser:
   NS_IF_RELEASE(infoObject);
   if (layer) {
     layer->dtor(layer);
   }
   return NS_ERROR_FAILURE;
 }
--- a/security/manager/ssl/src/nsNSSIOLayer.h
+++ b/security/manager/ssl/src/nsNSSIOLayer.h
@@ -10,22 +10,30 @@
 #include "TransportSecurityInfo.h"
 #include "nsISSLSocketControl.h"
 #include "nsIClientAuthDialogs.h"
 #include "nsNSSCertificate.h"
 #include "nsDataHashtable.h"
 #include "nsTHashtable.h"
 #include "mozilla/TimeStamp.h"
 
+namespace mozilla {
+namespace psm {
+class SharedSSLState;
+}
+}
+
+class nsIObserver;
+
 class nsNSSSocketInfo : public mozilla::psm::TransportSecurityInfo,
                         public nsISSLSocketControl,
                         public nsIClientAuthUserDecision
 {
 public:
-  nsNSSSocketInfo(uint32_t providerFlags);
+  nsNSSSocketInfo(mozilla::psm::SharedSSLState& aState, uint32_t providerFlags);
   
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSISSLSOCKETCONTROL
   NS_DECL_NSICLIENTAUTHUSERDECISION
  
   nsresult SetForSTARTTLS(bool aForSTARTTLS);
   nsresult GetForSTARTTLS(bool *aForSTARTTLS);
 
@@ -50,17 +58,21 @@ public:
   PRStatus CloseSocketAndDestroy(
                 const nsNSSShutDownPreventionLock & proofOfLock);
   
   void SetNegotiatedNPN(const char *value, uint32_t length);
   void SetHandshakeCompleted();
 
   bool GetJoined() { return mJoined; }
   void SetSentClientCert() { mSentClientCert = true; }
-  
+
+  uint32_t GetProviderFlags() const { return mProviderFlags; }
+
+  mozilla::psm::SharedSSLState& SharedState();
+
   // XXX: These are only used on for diagnostic purposes
   enum CertVerificationState {
     before_cert_verification,
     waiting_for_cert_verification,
     after_cert_verification
   };
   void SetCertVerificationWaiting();
   // Use errorCode == 0 to indicate success; in that case, errorMessageType is
@@ -78,16 +90,17 @@ public:
   void SetSSL3Enabled(bool enabled) { mSSL3Enabled = enabled; }
   bool IsTLSEnabled() const { return mTLSEnabled; }
   void SetTLSEnabled(bool enabled) { mTLSEnabled = enabled; }
 private:
   PRFileDesc* mFd;
 
   CertVerificationState mCertVerificationState;
 
+  mozilla::psm::SharedSSLState& mSharedState;
   bool mForSTARTTLS;
   bool mSSL3Enabled;
   bool mTLSEnabled;
   bool mHandshakePending;
   bool mHasCleartextPhase;
   bool mHandshakeInProgress;
   bool mAllowTLSIntoleranceTimeout;
   bool mRememberClientAuthCertificate;
@@ -104,47 +117,54 @@ private:
 
   uint32_t mProviderFlags;
   mozilla::TimeStamp mSocketCreationTimestamp;
 };
 
 class nsSSLIOLayerHelpers
 {
 public:
-  static nsresult Init();
-  static void Cleanup();
+  nsSSLIOLayerHelpers();
+  ~nsSSLIOLayerHelpers();
+
+  nsresult Init();
+  void Cleanup();
 
   static bool nsSSLIOLayerInitialized;
   static PRDescIdentity nsSSLIOLayerIdentity;
   static PRIOMethods nsSSLIOLayerMethods;
 
-  static mozilla::Mutex *mutex;
-  static nsTHashtable<nsCStringHashKey> *mTLSIntolerantSites;
-  static nsTHashtable<nsCStringHashKey> *mTLSTolerantSites;
+  mozilla::Mutex *mutex;
+  nsTHashtable<nsCStringHashKey> *mTLSIntolerantSites;
+  nsTHashtable<nsCStringHashKey> *mTLSTolerantSites;
 
-  static nsTHashtable<nsCStringHashKey> *mRenegoUnrestrictedSites;
-  static bool mTreatUnsafeNegotiationAsBroken;
-  static int32_t mWarnLevelMissingRFC5746;
+  nsTHashtable<nsCStringHashKey> *mRenegoUnrestrictedSites;
+  bool mTreatUnsafeNegotiationAsBroken;
+  int32_t mWarnLevelMissingRFC5746;
 
-  static void setTreatUnsafeNegotiationAsBroken(bool broken);
-  static bool treatUnsafeNegotiationAsBroken();
+  void setTreatUnsafeNegotiationAsBroken(bool broken);
+  bool treatUnsafeNegotiationAsBroken();
 
-  static void setWarnLevelMissingRFC5746(int32_t level);
-  static int32_t getWarnLevelMissingRFC5746();
+  void setWarnLevelMissingRFC5746(int32_t level);
+  int32_t getWarnLevelMissingRFC5746();
 
   static void getSiteKey(nsNSSSocketInfo *socketInfo, nsCSubstring &key);
-  static bool rememberPossibleTLSProblemSite(nsNSSSocketInfo *socketInfo);
-  static void rememberTolerantSite(nsNSSSocketInfo *socketInfo);
+  bool rememberPossibleTLSProblemSite(nsNSSSocketInfo *socketInfo);
+  void rememberTolerantSite(nsNSSSocketInfo *socketInfo);
+
+  void addIntolerantSite(const nsCString &str);
+  void removeIntolerantSite(const nsCString &str);
+  bool isKnownAsIntolerantSite(const nsCString &str);
 
-  static void addIntolerantSite(const nsCString &str);
-  static void removeIntolerantSite(const nsCString &str);
-  static bool isKnownAsIntolerantSite(const nsCString &str);
+  void setRenegoUnrestrictedSites(const nsCString &str);
+  bool isRenegoUnrestrictedSite(const nsCString &str);
 
-  static void setRenegoUnrestrictedSites(const nsCString &str);
-  static bool isRenegoUnrestrictedSite(const nsCString &str);
+  void clearStoredData();
+private:
+  nsCOMPtr<nsIObserver> mPrefObserver;
 };
 
 nsresult nsSSLIOLayerNewSocket(int32_t family,
                                const char *host,
                                int32_t port,
                                const char *proxyHost,
                                int32_t proxyPort,
                                PRFileDesc **fd,
--- a/security/manager/ssl/src/nsNSSModule.cpp
+++ b/security/manager/ssl/src/nsNSSModule.cpp
@@ -33,17 +33,16 @@
 #include "nsICategoryManager.h"
 #include "nsCRLManager.h"
 #include "nsNTLMAuthModule.h"
 #include "nsStreamCipher.h"
 #include "nsKeyModule.h"
 #include "nsDataSignatureVerifier.h"
 #include "nsCertOverrideService.h"
 #include "nsRandomGenerator.h"
-#include "nsRecentBadCerts.h"
 #include "nsSSLStatus.h"
 #include "TransportSecurityInfo.h"
 #include "NSSErrorsService.h"
 #include "nsNSSVersion.h"
 
 #include "nsXULAppAPI.h"
 #define NS_IS_PROCESS_DEFAULT                                                 \
     (GeckoProcessType_Default == XRE_GetProcessType())
@@ -199,17 +198,16 @@ NS_NSS_GENERIC_FACTORY_CONSTRUCTOR_INIT(
 NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsCryptoHash)
 NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsCryptoHMAC)
 NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsStreamCipher)
 NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsKeyObject)
 NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsKeyObjectFactory)
 NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsDataSignatureVerifier)
 NS_NSS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nssEnsure, nsCertOverrideService, Init)
 NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsRandomGenerator)
-NS_NSS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nssEnsure, nsRecentBadCertsService, Init)
 NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureOnChromeOnly, nsSSLStatus)
 NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureOnChromeOnly, TransportSecurityInfo)
 
 typedef mozilla::psm::NSSErrorsService NSSErrorsService;
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(NSSErrorsService, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsNSSVersion)
 
 NS_DEFINE_NAMED_CID(NS_NSSCOMPONENT_CID);
@@ -238,17 +236,16 @@ NS_DEFINE_NAMED_CID(NS_CERT_PICKER_CID);
 NS_DEFINE_NAMED_CID(NS_CRLMANAGER_CID);
 NS_DEFINE_NAMED_CID(NS_NTLMAUTHMODULE_CID);
 NS_DEFINE_NAMED_CID(NS_STREAMCIPHER_CID);
 NS_DEFINE_NAMED_CID(NS_KEYMODULEOBJECT_CID);
 NS_DEFINE_NAMED_CID(NS_KEYMODULEOBJECTFACTORY_CID);
 NS_DEFINE_NAMED_CID(NS_DATASIGNATUREVERIFIER_CID);
 NS_DEFINE_NAMED_CID(NS_CERTOVERRIDE_CID);
 NS_DEFINE_NAMED_CID(NS_RANDOMGENERATOR_CID);
-NS_DEFINE_NAMED_CID(NS_RECENTBADCERTS_CID);
 NS_DEFINE_NAMED_CID(NS_SSLSTATUS_CID);
 NS_DEFINE_NAMED_CID(TRANSPORTSECURITYINFO_CID);
 NS_DEFINE_NAMED_CID(NS_NSSERRORSSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_NSSVERSION_CID);
 
 static const mozilla::Module::CIDEntry kNSSCIDs[] = {
   { &kNS_NSSCOMPONENT_CID, false, nullptr, nsNSSComponentConstructor },
   { &kNS_SSLSOCKETPROVIDER_CID, false, nullptr, nsSSLSocketProviderConstructor },
@@ -276,17 +273,16 @@ static const mozilla::Module::CIDEntry k
   { &kNS_CRLMANAGER_CID, false, nullptr, nsCRLManagerConstructor },
   { &kNS_NTLMAUTHMODULE_CID, false, nullptr, nsNTLMAuthModuleConstructor },
   { &kNS_STREAMCIPHER_CID, false, nullptr, nsStreamCipherConstructor },
   { &kNS_KEYMODULEOBJECT_CID, false, nullptr, nsKeyObjectConstructor },
   { &kNS_KEYMODULEOBJECTFACTORY_CID, false, nullptr, nsKeyObjectFactoryConstructor },
   { &kNS_DATASIGNATUREVERIFIER_CID, false, nullptr, nsDataSignatureVerifierConstructor },
   { &kNS_CERTOVERRIDE_CID, false, nullptr, nsCertOverrideServiceConstructor },
   { &kNS_RANDOMGENERATOR_CID, false, nullptr, nsRandomGeneratorConstructor },
-  { &kNS_RECENTBADCERTS_CID, false, nullptr, nsRecentBadCertsServiceConstructor },
   { &kNS_SSLSTATUS_CID, false, nullptr, nsSSLStatusConstructor },
   { &kTRANSPORTSECURITYINFO_CID, false, nullptr, TransportSecurityInfoConstructor },
   { &kNS_NSSERRORSSERVICE_CID, false, nullptr, NSSErrorsServiceConstructor },
   { &kNS_NSSVERSION_CID, false, nullptr, nsNSSVersionConstructor },
   { nullptr }
 };
 
 static const mozilla::Module::ContractIDEntry kNSSContracts[] = {
@@ -319,17 +315,16 @@ static const mozilla::Module::ContractID
   { NS_CRYPTO_FIPSINFO_SERVICE_CONTRACTID, &kNS_PKCS11MODULEDB_CID },
   { NS_NTLMAUTHMODULE_CONTRACTID, &kNS_NTLMAUTHMODULE_CID },
   { NS_STREAMCIPHER_CONTRACTID, &kNS_STREAMCIPHER_CID },
   { NS_KEYMODULEOBJECT_CONTRACTID, &kNS_KEYMODULEOBJECT_CID },
   { NS_KEYMODULEOBJECTFACTORY_CONTRACTID, &kNS_KEYMODULEOBJECTFACTORY_CID },
   { NS_DATASIGNATUREVERIFIER_CONTRACTID, &kNS_DATASIGNATUREVERIFIER_CID },
   { NS_CERTOVERRIDE_CONTRACTID, &kNS_CERTOVERRIDE_CID },
   { NS_RANDOMGENERATOR_CONTRACTID, &kNS_RANDOMGENERATOR_CID },
-  { NS_RECENTBADCERTS_CONTRACTID, &kNS_RECENTBADCERTS_CID },
   { nullptr }
 };
 
 static const mozilla::Module::CategoryEntry kNSSCategories[] = {
   { NS_CONTENT_LISTENER_CATEGORYMANAGER_ENTRY, "application/x-x509-ca-cert", "@mozilla.org/uriloader/psm-external-content-listener;1" },
   { NS_CONTENT_LISTENER_CATEGORYMANAGER_ENTRY, "application/x-x509-server-cert", "@mozilla.org/uriloader/psm-external-content-listener;1" },
   { NS_CONTENT_LISTENER_CATEGORYMANAGER_ENTRY, "application/x-x509-user-cert", "@mozilla.org/uriloader/psm-external-content-listener;1" },
   { NS_CONTENT_LISTENER_CATEGORYMANAGER_ENTRY, "application/x-x509-email-cert", "@mozilla.org/uriloader/psm-external-content-listener;1" },
--- a/security/manager/ssl/src/nsRecentBadCerts.cpp
+++ b/security/manager/ssl/src/nsRecentBadCerts.cpp
@@ -1,52 +1,48 @@
 /* -*- 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/. */
 
 #include "nsRecentBadCerts.h"
 #include "nsIX509Cert.h"
+#include "nsIObserverService.h"
 #include "mozilla/RefPtr.h"
+#include "mozilla/Services.h"
 #include "nsSSLStatus.h"
 #include "nsCOMPtr.h"
 #include "nsNSSCertificate.h"
 #include "nsCRT.h"
 #include "nsPromiseFlatString.h"
 #include "nsStringBuffer.h"
 #include "nspr.h"
 #include "pk11pub.h"
 #include "certdb.h"
 #include "sechash.h"
 
 using namespace mozilla;
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsRecentBadCertsService, 
-                              nsIRecentBadCertsService)
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsRecentBadCerts,
+                              nsIRecentBadCerts)
 
-nsRecentBadCertsService::nsRecentBadCertsService()
-:monitor("nsRecentBadCertsService.monitor")
+nsRecentBadCerts::nsRecentBadCerts()
+:monitor("nsRecentBadCerts.monitor")
 ,mNextStorePosition(0)
 {
 }
 
-nsRecentBadCertsService::~nsRecentBadCertsService()
+nsRecentBadCerts::~nsRecentBadCerts()
 {
 }
 
-nsresult
-nsRecentBadCertsService::Init()
-{
-  return NS_OK;
-}
-
 NS_IMETHODIMP
-nsRecentBadCertsService::GetRecentBadCert(const nsAString & aHostNameWithPort, 
-                                          nsISSLStatus **aStatus)
+nsRecentBadCerts::GetRecentBadCert(const nsAString & aHostNameWithPort, 
+                                   nsISSLStatus **aStatus)
 {
   NS_ENSURE_ARG_POINTER(aStatus);
   if (!aHostNameWithPort.Length())
     return NS_ERROR_INVALID_ARG;
 
   *aStatus = nullptr;
   RefPtr<nsSSLStatus> status(new nsSSLStatus());
 
@@ -96,17 +92,17 @@ nsRecentBadCertsService::GetRecentBadCer
     *aStatus = status;
     NS_IF_ADDREF(*aStatus);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsRecentBadCertsService::AddBadCert(const nsAString &hostWithPort, 
+nsRecentBadCerts::AddBadCert(const nsAString &hostWithPort, 
                                     nsISSLStatus *aStatus)
 {
   NS_ENSURE_ARG(aStatus);
 
   nsCOMPtr<nsIX509Cert> cert;
   nsresult rv;
   rv = aStatus->GetServerCert(getter_AddRefs(cert));
   NS_ENSURE_SUCCESS(rv, rv);
@@ -141,8 +137,18 @@ nsRecentBadCertsService::AddBadCert(cons
     updatedEntry.mDERCert = tempItem; // consume
     updatedEntry.isDomainMismatch = isDomainMismatch;
     updatedEntry.isNotValidAtThisTime = isNotValidAtThisTime;
     updatedEntry.isUntrusted = isUntrusted;
   }
 
   return NS_OK;
 }
+
+NS_IMETHODIMP
+nsRecentBadCerts::ResetStoredCerts()
+{
+  for (size_t i = 0; i < const_recently_seen_list_size; ++i) {
+    RecentBadCert &entry = mCerts[i];
+    entry.Clear();
+  }
+  return NS_OK;
+}
--- a/security/manager/ssl/src/nsRecentBadCerts.h
+++ b/security/manager/ssl/src/nsRecentBadCerts.h
@@ -49,26 +49,24 @@ public:
   bool isNotValidAtThisTime;
   bool isUntrusted;
 
 private:
   RecentBadCert(const RecentBadCert &other) MOZ_DELETE;
   RecentBadCert &operator=(const RecentBadCert &other) MOZ_DELETE;
 };
 
-class nsRecentBadCertsService MOZ_FINAL : public nsIRecentBadCertsService
+class nsRecentBadCerts MOZ_FINAL : public nsIRecentBadCerts
 {
 public:
   NS_DECL_ISUPPORTS
-  NS_DECL_NSIRECENTBADCERTSSERVICE
+  NS_DECL_NSIRECENTBADCERTS
 
-  nsRecentBadCertsService();
-  ~nsRecentBadCertsService();
-
-  nsresult Init();
+  nsRecentBadCerts();
+  ~nsRecentBadCerts();
 
 protected:
     mozilla::ReentrantMonitor monitor;
 
     enum {const_recently_seen_list_size = 5};
     RecentBadCert mCerts[const_recently_seen_list_size];
 
     // will be in the range of 0 to list_size-1