Bug 566478 - Invalid SSL cert error is not mobile-friendly [r=kaie a=blocking-fennecb2]
authorHonza Bambas <honzab.moz@firemni.cz>
Wed, 27 Oct 2010 14:35:00 -0400
changeset 56645 c3886efa7e57b1b44cc4f002ce09402da4a4e944
parent 56644 66b7220a7c35e55c7ce91472c34cdc25ac9c4af2
child 56646 bcfefd30c2a68e8f33d3606f83f76509b504965a
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskaie, blocking-fennecb2
bugs566478
milestone2.0b8pre
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 566478 - Invalid SSL cert error is not mobile-friendly [r=kaie a=blocking-fennecb2]
netwerk/protocol/http/HttpChannelParentListener.cpp
security/manager/ssl/src/Makefile.in
security/manager/ssl/src/NSSErrorsService.cpp
security/manager/ssl/src/NSSErrorsService.h
security/manager/ssl/src/nsNSSComponent.cpp
security/manager/ssl/src/nsNSSComponent.h
security/manager/ssl/src/nsNSSIOLayer.cpp
security/manager/ssl/src/nsNSSModule.cpp
--- a/netwerk/protocol/http/HttpChannelParentListener.cpp
+++ b/netwerk/protocol/http/HttpChannelParentListener.cpp
@@ -138,16 +138,22 @@ NS_IMETHODIMP
 HttpChannelParentListener::GetInterface(const nsIID& aIID, void **result)
 {
   if (aIID.Equals(NS_GET_IID(nsIAuthPromptProvider))) {
     if (!mActiveChannel || !mActiveChannel->mTabParent)
       return NS_NOINTERFACE;
     return mActiveChannel->mTabParent->QueryInterface(aIID, result);
   }
 
+  if (aIID.Equals(NS_GET_IID(nsISecureBrowserUI))) {
+    if (!mActiveChannel && !mActiveChannel->mTabParent)
+      return NS_NOINTERFACE;
+    return mActiveChannel->mTabParent->QueryInterface(aIID, result);
+  }
+
   if (aIID.Equals(NS_GET_IID(nsIProgressEventSink))) {
     if (!mActiveChannel)
       return NS_NOINTERFACE;
     return mActiveChannel->QueryInterface(aIID, result);
   }
 
   // TODO: 575494: once we're confident we're handling all needed interfaces,
   // remove all code below and simply "return QueryInterface(aIID, result)"
--- a/security/manager/ssl/src/Makefile.in
+++ b/security/manager/ssl/src/Makefile.in
@@ -97,16 +97,17 @@ CPPSRCS = 				\
   nsNTLMAuthModule.cpp \
   nsSmartCardMonitor.cpp \
   nsSmartCardEvent.cpp \
   nsStreamCipher.cpp \
   nsKeyModule.cpp \
   nsIdentityChecking.cpp \
   nsDataSignatureVerifier.cpp \
   nsRandomGenerator.cpp \
+  NSSErrorsService.cpp \
   $(NULL)
 
 ifdef MOZ_XUL
 CPPSRCS += nsCertTree.cpp
 endif
 
 ifdef MOZ_IPC
 CPPSRCS += nsNSSCertificateFakeTransport.cpp
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/src/NSSErrorsService.cpp
@@ -0,0 +1,189 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Personal Security Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Hubbie Shaw
+ *   Doug Turner <dougt@netscape.com>
+ *   Mitch Stoltz <mstoltz@netscape.com>
+ *   Brian Ryner <bryner@brianryner.com>
+ *   Kai Engert <kaie@netscape.com>
+ *   Vipul Gupta <vipul.gupta@sun.com>
+ *   Douglas Stebila <douglas@stebila.ca>
+ *   Kai Engert <kengert@redhat.com>
+ *   honzab.moz@firemni.cz
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "NSSErrorsService.h"
+
+#include "nsNSSComponent.h"
+#include "nsServiceManagerUtils.h"
+#include "secerr.h"
+#include "sslerr.h"
+
+#define PIPNSS_STRBUNDLE_URL "chrome://pipnss/locale/pipnss.properties"
+#define NSSERR_STRBUNDLE_URL "chrome://pipnss/locale/nsserrors.properties"
+
+namespace mozilla {
+namespace psm {
+
+NS_IMPL_ISUPPORTS1(NSSErrorsService, nsINSSErrorsService)
+
+nsresult
+NSSErrorsService::Init()
+{
+  nsresult rv;
+  nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
+  if (NS_FAILED(rv) || !bundleService) 
+    return NS_ERROR_FAILURE;
+  
+  bundleService->CreateBundle(PIPNSS_STRBUNDLE_URL,
+                              getter_AddRefs(mPIPNSSBundle));
+  if (!mPIPNSSBundle)
+    rv = NS_ERROR_FAILURE;
+
+  bundleService->CreateBundle(NSSERR_STRBUNDLE_URL,
+                              getter_AddRefs(mNSSErrorsBundle));
+  if (!mNSSErrorsBundle)
+    rv = NS_ERROR_FAILURE;
+
+  return rv;
+}
+
+#define EXPECTED_SEC_ERROR_BASE (-0x2000)
+#define EXPECTED_SSL_ERROR_BASE (-0x3000)
+
+#if SEC_ERROR_BASE != EXPECTED_SEC_ERROR_BASE || SSL_ERROR_BASE != EXPECTED_SSL_ERROR_BASE
+#error "Unexpected change of error code numbers in lib NSS, please adjust the mapping code"
+/*
+ * Please ensure the NSS error codes are mapped into the positive range 0x1000 to 0xf000
+ * Search for NS_ERROR_MODULE_SECURITY to ensure there are no conflicts.
+ * The current code also assumes that NSS library error codes are negative.
+ */
+#endif
+
+NS_IMETHODIMP
+NSSErrorsService::IsNSSErrorCode(PRInt32 aNSPRCode, PRBool *_retval)
+{
+  if (!_retval)
+    return NS_ERROR_FAILURE;
+
+  *_retval = IS_SEC_ERROR(aNSPRCode) || IS_SSL_ERROR(aNSPRCode);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+NSSErrorsService::GetXPCOMFromNSSError(PRInt32 aNSPRCode, nsresult *aXPCOMErrorCode)
+{
+  if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode))
+    return NS_ERROR_FAILURE;
+
+  if (!aXPCOMErrorCode)
+    return NS_ERROR_INVALID_ARG;
+
+  // The error codes within each module may be a 16 bit value.
+  // For simplicity let's use the positive value of the NSS code.
+
+  *aXPCOMErrorCode =
+    NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY,
+                              -1 * aNSPRCode);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+NSSErrorsService::GetErrorClass(nsresult aXPCOMErrorCode, PRUint32 *aErrorClass)
+{
+  NS_ENSURE_ARG(aErrorClass);
+
+  if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY
+      || NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR)
+    return NS_ERROR_FAILURE;
+  
+  PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode);
+
+  if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode))
+    return NS_ERROR_FAILURE;
+
+  switch (aNSPRCode)
+  {
+    case SEC_ERROR_UNKNOWN_ISSUER:
+    case SEC_ERROR_CA_CERT_INVALID:
+    case SEC_ERROR_UNTRUSTED_ISSUER:
+    case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
+    case SEC_ERROR_UNTRUSTED_CERT:
+    case SEC_ERROR_INADEQUATE_KEY_USAGE:
+    case SSL_ERROR_BAD_CERT_DOMAIN:
+    case SEC_ERROR_EXPIRED_CERTIFICATE:
+      *aErrorClass = ERROR_CLASS_BAD_CERT;
+      break;
+    default:
+      *aErrorClass = ERROR_CLASS_SSL_PROTOCOL;
+      break;
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+NSSErrorsService::GetErrorMessage(nsresult aXPCOMErrorCode, nsAString &aErrorMessage)
+{
+  if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY
+      || NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR)
+    return NS_ERROR_FAILURE;
+  
+  PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode);
+
+  if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode))
+    return NS_ERROR_FAILURE;
+
+  nsCOMPtr<nsIStringBundle> theBundle = mPIPNSSBundle;
+  const char *id_str = nsNSSErrors::getOverrideErrorStringName(aNSPRCode);
+
+  if (!id_str) {
+    id_str = nsNSSErrors::getDefaultErrorStringName(aNSPRCode);
+    theBundle = mNSSErrorsBundle;
+  }
+
+  if (!id_str || !theBundle)
+    return NS_ERROR_FAILURE;
+
+  nsAutoString msg;
+  nsresult rv =
+    theBundle->GetStringFromName(NS_ConvertASCIItoUTF16(id_str).get(),
+                                 getter_Copies(msg));
+  if (NS_SUCCEEDED(rv)) {
+    aErrorMessage = msg;
+  }
+  return rv;
+}
+
+} // psm
+} // mozilla
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/src/NSSErrorsService.h
@@ -0,0 +1,68 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Personal Security Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Hubbie Shaw
+ *   Doug Turner <dougt@netscape.com>
+ *   Brian Ryner <bryner@brianryner.com>
+ *   Kai Engert <kaie@netscape.com>
+ *   Kai Engert <kengert@redhat.com>
+ *   honzab.moz@firemni.cz
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsINSSErrorsService.h"
+
+#include "nsIStringBundle.h"
+#include "nsCOMPtr.h"
+
+namespace mozilla {
+namespace psm {
+
+class NSSErrorsService : public nsINSSErrorsService
+{
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSINSSERRORSSERVICE
+
+public:
+  nsresult Init();
+
+private:
+  nsCOMPtr<nsIStringBundle> mPIPNSSBundle;
+  nsCOMPtr<nsIStringBundle> mNSSErrorsBundle;
+};
+
+} // psm
+} // mozilla
+
+#define NS_NSSERRORSSERVICE_CID \
+  { 0x9ef18451, 0xa157, 0x4d17, { 0x81, 0x32, 0x47, 0xaf, 0xef, 0x21, 0x36, 0x89 } }
--- a/security/manager/ssl/src/nsNSSComponent.cpp
+++ b/security/manager/ssl/src/nsNSSComponent.cpp
@@ -1948,24 +1948,23 @@ nsNSSComponent::Init()
   if (bec) {
     bec->ForwardTo(this);
   }
 
   return rv;
 }
 
 /* nsISupports Implementation for the class */
-NS_IMPL_THREADSAFE_ISUPPORTS7(nsNSSComponent,
+NS_IMPL_THREADSAFE_ISUPPORTS6(nsNSSComponent,
                               nsISignatureVerifier,
                               nsIEntropyCollector,
                               nsINSSComponent,
                               nsIObserver,
                               nsISupportsWeakReference,
-                              nsITimerCallback,
-                              nsINSSErrorsService)
+                              nsITimerCallback)
 
 
 /* Callback functions for decoder. For now, use empty/default functions. */
 static void ContentCallback(void *arg, 
                                            const char *buf,
                                            unsigned long len)
 {
 }
@@ -2448,122 +2447,16 @@ nsNSSComponent::RememberCert(CERTCertifi
   
   if (!PL_HashTableAdd(hashTableCerts, (void*)&myDupCert->certKey, myDupCert)) {
     CERT_DestroyCertificate(myDupCert);
   }
   
   return NS_OK;
 }
 
-#define EXPECTED_SEC_ERROR_BASE (-0x2000)
-#define EXPECTED_SSL_ERROR_BASE (-0x3000)
-
-#if SEC_ERROR_BASE != EXPECTED_SEC_ERROR_BASE || SSL_ERROR_BASE != EXPECTED_SSL_ERROR_BASE
-#error "Unexpected change of error code numbers in lib NSS, please adjust the mapping code"
-/*
- * Please ensure the NSS error codes are mapped into the positive range 0x1000 to 0xf000
- * Search for NS_ERROR_MODULE_SECURITY to ensure there are no conflicts.
- * The current code also assumes that NSS library error codes are negative.
- */
-#endif
-
-NS_IMETHODIMP
-nsNSSComponent::IsNSSErrorCode(PRInt32 aNSPRCode, PRBool *_retval)
-{
-  if (!_retval)
-    return NS_ERROR_FAILURE;
-
-  *_retval = IS_SEC_ERROR(aNSPRCode) || IS_SSL_ERROR(aNSPRCode);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsNSSComponent::GetXPCOMFromNSSError(PRInt32 aNSPRCode, nsresult *aXPCOMErrorCode)
-{
-  if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode))
-    return NS_ERROR_FAILURE;
-
-  if (!aXPCOMErrorCode)
-    return NS_ERROR_INVALID_ARG;
-
-  // The error codes within each module may be a 16 bit value.
-  // For simplicity let's use the positive value of the NSS code.
-
-  *aXPCOMErrorCode =
-    NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY,
-                              -1 * aNSPRCode);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsNSSComponent::GetErrorClass(nsresult aXPCOMErrorCode, PRUint32 *aErrorClass)
-{
-  NS_ENSURE_ARG(aErrorClass);
-
-  if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY
-      || NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR)
-    return NS_ERROR_FAILURE;
-  
-  PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode);
-
-  if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode))
-    return NS_ERROR_FAILURE;
-
-  switch (aNSPRCode)
-  {
-    case SEC_ERROR_UNKNOWN_ISSUER:
-    case SEC_ERROR_CA_CERT_INVALID:
-    case SEC_ERROR_UNTRUSTED_ISSUER:
-    case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
-    case SEC_ERROR_UNTRUSTED_CERT:
-    case SEC_ERROR_INADEQUATE_KEY_USAGE:
-    case SSL_ERROR_BAD_CERT_DOMAIN:
-    case SEC_ERROR_EXPIRED_CERTIFICATE:
-      *aErrorClass = ERROR_CLASS_BAD_CERT;
-      break;
-    default:
-      *aErrorClass = ERROR_CLASS_SSL_PROTOCOL;
-      break;
-  }
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsNSSComponent::GetErrorMessage(nsresult aXPCOMErrorCode, nsAString &aErrorMessage)
-{
-  if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY
-      || NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR)
-    return NS_ERROR_FAILURE;
-  
-  PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode);
-
-  if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode))
-    return NS_ERROR_FAILURE;
-
-  nsCOMPtr<nsIStringBundle> theBundle = mPIPNSSBundle;
-  const char *id_str = nsNSSErrors::getOverrideErrorStringName(aNSPRCode);
-
-  if (!id_str) {
-    id_str = nsNSSErrors::getDefaultErrorStringName(aNSPRCode);
-    theBundle = mNSSErrorsBundle;
-  }
-
-  if (!id_str || !theBundle)
-    return NS_ERROR_FAILURE;
-
-  nsAutoString msg;
-  nsresult rv =
-    theBundle->GetStringFromName(NS_ConvertASCIItoUTF16(id_str).get(),
-                                 getter_Copies(msg));
-  if (NS_SUCCEEDED(rv)) {
-    aErrorMessage = msg;
-  }
-  return rv;
-}
-
 void
 nsNSSComponent::DoProfileApproveChange(nsISupports* aSubject)
 {
   if (mShutdownObjectList->isUIActive()) {
     ShowAlert(ai_crypto_ui_active);
     nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
     if (status) {
       status->VetoChange();
--- a/security/manager/ssl/src/nsNSSComponent.h
+++ b/security/manager/ssl/src/nsNSSComponent.h
@@ -234,31 +234,29 @@ class nsSSLThread;
 class nsCertVerificationThread;
 
 // Implementation of the PSM component interface.
 class nsNSSComponent : public nsISignatureVerifier,
                        public nsIEntropyCollector,
                        public nsINSSComponent,
                        public nsIObserver,
                        public nsSupportsWeakReference,
-                       public nsITimerCallback,
-                       public nsINSSErrorsService
+                       public nsITimerCallback
 {
 public:
   NS_DEFINE_STATIC_CID_ACCESSOR( NS_NSSCOMPONENT_CID )
 
   nsNSSComponent();
   virtual ~nsNSSComponent();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSISIGNATUREVERIFIER
   NS_DECL_NSIENTROPYCOLLECTOR
   NS_DECL_NSIOBSERVER
   NS_DECL_NSITIMERCALLBACK
-  NS_DECL_NSINSSERRORSSERVICE
 
   NS_METHOD Init();
 
   NS_IMETHOD GetPIPNSSBundleString(const char *name,
                                    nsAString &outString);
   NS_IMETHOD PIPBundleFormatStringFromName(const char *name,
                                            const PRUnichar **params,
                                            PRUint32 numParams,
--- a/security/manager/ssl/src/nsNSSIOLayer.cpp
+++ b/security/manager/ssl/src/nsNSSIOLayer.cpp
@@ -374,64 +374,73 @@ nsNSSSocketInfo::EnsureDocShellDependent
   // We'll look at the presence of a security UI object inside docshell.
   // If the docshell wants the lock icon, you'll get the ssl error pages, too.
   // This is helpful to distinguish from all other contexts, like mail windows,
   // or any other SSL connections running in the background.
   // We must query it now and remember, because fatal SSL errors will come 
   // with a socket close, and the socket transport might detach the callbacks 
   // instance prior to our error reporting.
 
-  nsCOMPtr<nsIDocShell> docshell;
-
-  nsCOMPtr<nsIDocShellTreeItem> item(do_GetInterface(proxiedCallbacks));
-  if (item)
-  {
-    nsCOMPtr<nsIDocShellTreeItem> proxiedItem;
-    nsCOMPtr<nsIDocShellTreeItem> rootItem;
-    NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
-                         NS_GET_IID(nsIDocShellTreeItem),
-                         item.get(),
-                         NS_PROXY_SYNC,
-                         getter_AddRefs(proxiedItem));
-
-    proxiedItem->GetSameTypeRootTreeItem(getter_AddRefs(rootItem));
-    docshell = do_QueryInterface(rootItem);
-    NS_ASSERTION(docshell, "rootItem do_QI is null");
-  }
-
-  if (docshell)
+  nsISecureBrowserUI* secureUI = nsnull;
+#ifdef MOZ_IPC
+  CallGetInterface(proxiedCallbacks.get(), &secureUI);
+#endif
+
+  if (!secureUI)
   {
-    nsCOMPtr<nsIDocShell> proxiedDocShell;
-    NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
-                         NS_GET_IID(nsIDocShell),
-                         docshell.get(),
-                         NS_PROXY_SYNC,
-                         getter_AddRefs(proxiedDocShell));
-    nsISecureBrowserUI* secureUI = nsnull;
-    if (proxiedDocShell)
-      proxiedDocShell->GetSecurityUI(&secureUI);
-    if (secureUI)
+    nsCOMPtr<nsIDocShell> docshell;
+
+    nsCOMPtr<nsIDocShellTreeItem> item(do_GetInterface(proxiedCallbacks));
+    if (item)
+    {
+      nsCOMPtr<nsIDocShellTreeItem> proxiedItem;
+      nsCOMPtr<nsIDocShellTreeItem> rootItem;
+      NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
+                           NS_GET_IID(nsIDocShellTreeItem),
+                           item.get(),
+                           NS_PROXY_SYNC,
+                           getter_AddRefs(proxiedItem));
+
+      proxiedItem->GetSameTypeRootTreeItem(getter_AddRefs(rootItem));
+      docshell = do_QueryInterface(rootItem);
+      NS_ASSERTION(docshell, "rootItem do_QI is null");
+    }
+
+    if (docshell)
     {
-      nsCOMPtr<nsIThread> mainThread(do_GetMainThread());
-      NS_ProxyRelease(mainThread, secureUI, PR_FALSE);
-      mExternalErrorReporting = PR_TRUE;
-
-      // If this socket is associated to a docshell, let's try to remember
-      // the currently used cert. If this socket gets a notification from NSS
-      // having the same raw socket, we can keep the PSM wrapper object
-      // and all the data it has cached (like verification results).
-      nsCOMPtr<nsISSLStatusProvider> statprov = do_QueryInterface(secureUI);
-      if (statprov) {
-        nsCOMPtr<nsISupports> isup_stat;
-        statprov->GetSSLStatus(getter_AddRefs(isup_stat));
-        if (isup_stat) {
-          nsCOMPtr<nsISSLStatus> sslstat = do_QueryInterface(isup_stat);
-          if (sslstat) {
-            sslstat->GetServerCert(getter_AddRefs(mPreviousCert));
-          }
+      nsCOMPtr<nsIDocShell> proxiedDocShell;
+      NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
+                           NS_GET_IID(nsIDocShell),
+                           docshell.get(),
+                           NS_PROXY_SYNC,
+                           getter_AddRefs(proxiedDocShell));
+      nsISecureBrowserUI* secureUI = nsnull;
+      if (proxiedDocShell)
+        proxiedDocShell->GetSecurityUI(&secureUI);
+    }
+  }
+
+  if (secureUI)
+  {
+    nsCOMPtr<nsIThread> mainThread(do_GetMainThread());
+    NS_ProxyRelease(mainThread, secureUI, PR_FALSE);
+    mExternalErrorReporting = PR_TRUE;
+
+    // If this socket is associated to a docshell, let's try to remember
+    // the currently used cert. If this socket gets a notification from NSS
+    // having the same raw socket, we can keep the PSM wrapper object
+    // and all the data it has cached (like verification results).
+    nsCOMPtr<nsISSLStatusProvider> statprov = do_QueryInterface(secureUI);
+    if (statprov) {
+      nsCOMPtr<nsISupports> isup_stat;
+      statprov->GetSSLStatus(getter_AddRefs(isup_stat));
+      if (isup_stat) {
+        nsCOMPtr<nsISSLStatus> sslstat = do_QueryInterface(isup_stat);
+        if (sslstat) {
+          sslstat->GetServerCert(getter_AddRefs(mPreviousCert));
         }
       }
     }
   }
 
   return NS_OK;
 }
 
--- a/security/manager/ssl/src/nsNSSModule.cpp
+++ b/security/manager/ssl/src/nsNSSModule.cpp
@@ -73,16 +73,17 @@
 #include "nsStreamCipher.h"
 #include "nsKeyModule.h"
 #include "nsDataSignatureVerifier.h"
 #include "nsCertOverrideService.h"
 #include "nsRandomGenerator.h"
 #include "nsRecentBadCerts.h"
 #include "nsSSLStatus.h"
 #include "nsNSSIOLayer.h"
+#include "NSSErrorsService.h"
 
 #ifdef MOZ_IPC
 #include "nsXULAppAPI.h"
 #define NS_IS_PROCESS_DEFAULT                                                 \
     (GeckoProcessType_Default == XRE_GetProcessType())
 #else
 #define NS_IS_PROCESS_DEFAULT                                                 \
     (true)
@@ -256,16 +257,19 @@ NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEn
 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, nsNSSSocketInfo)
 
+typedef mozilla::psm::NSSErrorsService NSSErrorsService;
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(NSSErrorsService, Init)
+
 NS_DEFINE_NAMED_CID(NS_NSSCOMPONENT_CID);
 NS_DEFINE_NAMED_CID(NS_SSLSOCKETPROVIDER_CID);
 NS_DEFINE_NAMED_CID(NS_STARTTLSSOCKETPROVIDER_CID);
 NS_DEFINE_NAMED_CID(NS_SDR_CID);
 NS_DEFINE_NAMED_CID(NS_PK11TOKENDB_CID);
 NS_DEFINE_NAMED_CID(NS_PKCS11MODULEDB_CID);
 NS_DEFINE_NAMED_CID(NS_PSMCONTENTLISTEN_CID);
 NS_DEFINE_NAMED_CID(NS_X509CERT_CID);
@@ -291,16 +295,17 @@ 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(NS_NSSSOCKETINFO_CID);
+NS_DEFINE_NAMED_CID(NS_NSSERRORSSERVICE_CID);
 
 
 static const mozilla::Module::CIDEntry kNSSCIDs[] = {
   { &kNS_NSSCOMPONENT_CID, false, NULL, nsNSSComponentConstructor },
   { &kNS_SSLSOCKETPROVIDER_CID, false, NULL, nsSSLSocketProviderConstructor },
   { &kNS_STARTTLSSOCKETPROVIDER_CID, false, NULL, nsTLSSocketProviderConstructor },
   { &kNS_SDR_CID, false, NULL, nsSecretDecoderRingConstructor },
   { &kNS_PK11TOKENDB_CID, false, NULL, nsPK11TokenDBConstructor },
@@ -329,22 +334,23 @@ static const mozilla::Module::CIDEntry k
   { &kNS_KEYMODULEOBJECT_CID, false, NULL, nsKeyObjectConstructor },
   { &kNS_KEYMODULEOBJECTFACTORY_CID, false, NULL, nsKeyObjectFactoryConstructor },
   { &kNS_DATASIGNATUREVERIFIER_CID, false, NULL, nsDataSignatureVerifierConstructor },
   { &kNS_CERTOVERRIDE_CID, false, NULL, nsCertOverrideServiceConstructor },
   { &kNS_RANDOMGENERATOR_CID, false, NULL, nsRandomGeneratorConstructor },
   { &kNS_RECENTBADCERTS_CID, false, NULL, nsRecentBadCertsServiceConstructor },
   { &kNS_SSLSTATUS_CID, false, NULL, nsSSLStatusConstructor },
   { &kNS_NSSSOCKETINFO_CID, false, NULL, nsNSSSocketInfoConstructor },
+  { &kNS_NSSERRORSSERVICE_CID, false, NULL, NSSErrorsServiceConstructor },
   { NULL }
 };
 
 static const mozilla::Module::ContractIDEntry kNSSContracts[] = {
   { PSM_COMPONENT_CONTRACTID, &kNS_NSSCOMPONENT_CID },
-  { NS_NSS_ERRORS_SERVICE_CONTRACTID, &kNS_NSSCOMPONENT_CID },
+  { NS_NSS_ERRORS_SERVICE_CONTRACTID, &kNS_NSSERRORSSERVICE_CID },
   { NS_SSLSOCKETPROVIDER_CONTRACTID, &kNS_SSLSOCKETPROVIDER_CID },
   { NS_STARTTLSSOCKETPROVIDER_CONTRACTID, &kNS_STARTTLSSOCKETPROVIDER_CID },
   { NS_SDR_CONTRACTID, &kNS_SDR_CID },
   { NS_PK11TOKENDB_CONTRACTID, &kNS_PK11TOKENDB_CID },
   { NS_PKCS11MODULEDB_CONTRACTID, &kNS_PKCS11MODULEDB_CID },
   { NS_PSMCONTENTLISTEN_CONTRACTID, &kNS_PSMCONTENTLISTEN_CID },
   { NS_X509CERTDB_CONTRACTID, &kNS_X509CERTDB_CID },
   { NS_NSSCERTCACHE_CONTRACTID, &kNS_NSSCERTCACHE_CID },