Bug 995385 - Ensure that NSS is initialzed for CryptoTasks. r=dkeeler
authorRichard Barnes <rbarnes@mozilla.com>
Fri, 16 May 2014 15:47:00 -0400
changeset 184204 43114cb9948066b7fbcde652e331edf2fe365fee
parent 184203 7ea38414bb31b01471b1beebf149c3cb99023fb7
child 184205 739a582c405c67c1b1a176708eb542af8cd144f8
push id26814
push userryanvm@gmail.com
push dateWed, 21 May 2014 19:50:12 +0000
treeherdermozilla-central@7aee2fa0f655 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdkeeler
bugs995385
milestone32.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 995385 - Ensure that NSS is initialzed for CryptoTasks. r=dkeeler
security/manager/ssl/src/CryptoTask.cpp
security/manager/ssl/src/CryptoTask.h
security/manager/ssl/src/nsNSSComponent.cpp
security/manager/ssl/src/nsNSSComponent.h
--- a/security/manager/ssl/src/CryptoTask.cpp
+++ b/security/manager/ssl/src/CryptoTask.cpp
@@ -1,28 +1,52 @@
 /* -*- Mode: C++; tab-width: 8; 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 "CryptoTask.h"
+#include "nsNSSComponent.h"
 
 namespace mozilla {
 
 CryptoTask::~CryptoTask()
 {
   MOZ_ASSERT(mReleasedNSSResources);
 
   nsNSSShutDownPreventionLock lock;
   if (!isAlreadyShutDown()) {
     shutdown(calledFromObject);
   }
 }
 
+nsresult
+CryptoTask::Dispatch(const nsACString& taskThreadName)
+{
+  MOZ_ASSERT(taskThreadName.Length() <= 15);
+
+  // Ensure that NSS is initialized, since presumably CalculateResult
+  // will use NSS functions
+  if (!EnsureNSSInitializedChromeOrContent()) {
+    return NS_ERROR_FAILURE;
+  }
+
+  // Can't add 'this' as the event to run, since mThread may not be set yet
+  nsresult rv = NS_NewThread(getter_AddRefs(mThread), nullptr,
+                             nsIThreadManager::DEFAULT_STACK_SIZE);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  NS_SetThreadName(mThread, taskThreadName);
+  // Note: event must not null out mThread!
+  return mThread->Dispatch(this, NS_DISPATCH_NORMAL);
+}
+
 NS_IMETHODIMP
 CryptoTask::Run()
 {
   if (!NS_IsMainThread()) {
     nsNSSShutDownPreventionLock locker;
     if (isAlreadyShutDown()) {
       mRv = NS_ERROR_NOT_AVAILABLE;
     } else {
--- a/security/manager/ssl/src/CryptoTask.h
+++ b/security/manager/ssl/src/CryptoTask.h
@@ -45,25 +45,21 @@ class CryptoTask : public nsRunnable,
                    public nsNSSShutDownObject
 {
 public:
   template <size_t LEN>
   nsresult Dispatch(const char (&taskThreadName)[LEN])
   {
     static_assert(LEN <= 15,
                   "Thread name must be no more than 15 characters");
-    // Can't add 'this' as the event to run, since mThread may not be set yet
-    nsresult rv = NS_NewNamedThread(taskThreadName, getter_AddRefs(mThread));
-    if (NS_SUCCEEDED(rv)) {
-      // Note: event must not null out mThread!
-      rv = mThread->Dispatch(this, NS_DISPATCH_NORMAL);
-    }
-    return rv;
+    return Dispatch(NS_LITERAL_CSTRING(taskThreadName));
   }
 
+  nsresult Dispatch(const nsACString& taskThreadName);
+
   void Skip()
   {
     virtualDestroyNSSReference();
   }
 
 protected:
   CryptoTask()
     : mRv(NS_ERROR_NOT_INITIALIZED),
--- a/security/manager/ssl/src/nsNSSComponent.cpp
+++ b/security/manager/ssl/src/nsNSSComponent.cpp
@@ -122,16 +122,50 @@ nsTokenEventRunnable::Run()
     return rv;
 
   return nssComponent->DispatchEvent(mType, mTokenName);
 }
 #endif // MOZ_DISABLE_CRYPTOLEGACY
 
 bool nsPSMInitPanic::isPanic = false;
 
+// This function can be called from chrome or content processes
+// to ensure that NSS is initialized.
+bool EnsureNSSInitializedChromeOrContent()
+{
+  nsresult rv;
+  if (XRE_GetProcessType() == GeckoProcessType_Default) {
+    nsCOMPtr<nsISupports> nss = do_GetService(PSM_COMPONENT_CONTRACTID, &rv);
+    if (NS_FAILED(rv)) {
+      return false;
+    }
+
+    return true;
+  }
+
+  if (!NS_IsMainThread()) {
+    return false;
+  }
+
+  if (NSS_IsInitialized()) {
+    return true;
+  }
+
+  if (NSS_NoDB_Init(nullptr) != SECSuccess) {
+    return false;
+  }
+
+  if (NS_FAILED(mozilla::psm::InitializeCipherSuite())) {
+    return false;
+  }
+
+  mozilla::psm::DisableMD5();
+  return true;
+}
+
 // We must ensure that the nsNSSComponent has been loaded before
 // creating any other components.
 bool EnsureNSSInitialized(EnsureNSSOperator op)
 {
   if (nsPSMInitPanic::GetPanic())
     return false;
 
   if (GeckoProcessType_Default != XRE_GetProcessType())
--- a/security/manager/ssl/src/nsNSSComponent.h
+++ b/security/manager/ssl/src/nsNSSComponent.h
@@ -56,16 +56,18 @@ enum EnsureNSSOperator
   nssLoadingComponent = 0,
   nssInitSucceeded = 1,
   nssInitFailed = 2,
   nssShutdown = 3,
   nssEnsure = 100,
   nssEnsureOnChromeOnly = 101
 };
 
+extern bool EnsureNSSInitializedChromeOrContent();
+
 extern bool EnsureNSSInitialized(EnsureNSSOperator op);
 
 class nsNSSComponent;
 
 class NS_NO_VTABLE nsINSSComponent : public nsISupports {
  public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_INSSCOMPONENT_IID)