Bug 1348454 - Use a single thread for IdentityCryptoService. r=jesup, a=lizzard
authorNathan Froyd <froydnj@mozilla.com>
Mon, 03 Apr 2017 15:41:54 -0400
changeset 379422 62e7b123b0e1a6bc970d8506e778cd47dc2f5cff
parent 379421 4f97cc13beb2334f14e6cf4f73eaab5e45f07491
child 379423 168d76e8a965a90b966679db03a86e677af87cdc
push id1419
push userjlund@mozilla.com
push dateMon, 10 Apr 2017 20:44:07 +0000
treeherdermozilla-release@5e6801b73ef6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup, lizzard
bugs1348454
milestone53.0
Bug 1348454 - Use a single thread for IdentityCryptoService. r=jesup, a=lizzard Rather than starting a single thread for every key generation and key signing operation started by IdentityCryptoService, and then leaking those threads, we can at least start a single thread to be used by all operations and leak that instead.
toolkit/identity/IdentityCryptoService.cpp
--- a/toolkit/identity/IdentityCryptoService.cpp
+++ b/toolkit/identity/IdentityCryptoService.cpp
@@ -48,17 +48,18 @@ HexEncode(const SECItem * it, nsACString
 #define RSA_KEY_TYPE_STRING (NS_LITERAL_CSTRING("RS256"))
 
 class KeyPair : public nsIIdentityKeyPair, public nsNSSShutDownObject
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIIDENTITYKEYPAIR
 
-  KeyPair(SECKEYPrivateKey* aPrivateKey, SECKEYPublicKey* aPublicKey);
+  KeyPair(SECKEYPrivateKey* aPrivateKey, SECKEYPublicKey* aPublicKey,
+          nsIEventTarget* aOperationThread);
 
 private:
   ~KeyPair() override
   {
     nsNSSShutDownPreventionLock locker;
     if (isAlreadyShutDown()) {
       return;
     }
@@ -76,29 +77,31 @@ private:
     SECKEY_DestroyPrivateKey(mPrivateKey);
     mPrivateKey = nullptr;
     SECKEY_DestroyPublicKey(mPublicKey);
     mPublicKey = nullptr;
   }
 
   SECKEYPrivateKey * mPrivateKey;
   SECKEYPublicKey * mPublicKey;
+  nsCOMPtr<nsIEventTarget> mThread;
 
   KeyPair(const KeyPair &) = delete;
   void operator=(const KeyPair &) = delete;
 };
 
 NS_IMPL_ISUPPORTS(KeyPair, nsIIdentityKeyPair)
 
 class KeyGenRunnable : public Runnable, public nsNSSShutDownObject
 {
 public:
   NS_DECL_NSIRUNNABLE
 
-  KeyGenRunnable(KeyType keyType, nsIIdentityKeyGenCallback * aCallback);
+  KeyGenRunnable(KeyType keyType, nsIIdentityKeyGenCallback * aCallback,
+                 nsIEventTarget* aOperationThread);
 
 private:
   ~KeyGenRunnable() override
   {
     nsNSSShutDownPreventionLock locker;
     if (isAlreadyShutDown()) {
       return;
     }
@@ -114,16 +117,17 @@ private:
   void destructorSafeDestroyNSSReference()
   {
   }
 
   const KeyType mKeyType; // in
   nsMainThreadPtrHandle<nsIIdentityKeyGenCallback> mCallback; // in
   nsresult mRv; // out
   nsCOMPtr<nsIIdentityKeyPair> mKeyPair; // out
+  nsCOMPtr<nsIEventTarget> mThread;
 
   KeyGenRunnable(const KeyGenRunnable &) = delete;
   void operator=(const KeyGenRunnable &) = delete;
 };
 
 class SignRunnable : public Runnable, public nsNSSShutDownObject
 {
 public:
@@ -174,23 +178,31 @@ public:
   IdentityCryptoService() = default;
   nsresult Init()
   {
     nsresult rv;
     nsCOMPtr<nsISupports> dummyUsedToEnsureNSSIsInitialized
       = do_GetService("@mozilla.org/psm;1", &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
+    nsCOMPtr<nsIThread> thread;
+    rv = NS_NewNamedThread("IdentityCrypto", getter_AddRefs(thread));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    mThread = thread.forget();
+
     return NS_OK;
   }
 
 private:
   ~IdentityCryptoService() = default;
   IdentityCryptoService(const KeyPair &) = delete;
   void operator=(const IdentityCryptoService &) = delete;
+
+  nsCOMPtr<nsIEventTarget> mThread;
 };
 
 NS_IMPL_ISUPPORTS(IdentityCryptoService, nsIIdentityCryptoService)
 
 NS_IMETHODIMP
 IdentityCryptoService::GenerateKeyPair(
   const nsACString & keyTypeString, nsIIdentityKeyGenCallback * callback)
 {
@@ -198,37 +210,37 @@ IdentityCryptoService::GenerateKeyPair(
   if (keyTypeString.Equals(RSA_KEY_TYPE_STRING)) {
     keyType = rsaKey;
   } else if (keyTypeString.Equals(DSA_KEY_TYPE_STRING)) {
     keyType = dsaKey;
   } else {
     return NS_ERROR_UNEXPECTED;
   }
 
-  nsCOMPtr<nsIRunnable> r = new KeyGenRunnable(keyType, callback);
-  nsCOMPtr<nsIThread> thread;
-  nsresult rv = NS_NewNamedThread("GenerateKeyPair", getter_AddRefs(thread),
-                                  r);
+  nsCOMPtr<nsIRunnable> r = new KeyGenRunnable(keyType, callback, mThread);
+  nsresult rv = mThread->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 IdentityCryptoService::Base64UrlEncode(const nsACString & utf8Input,
                                        nsACString & result)
 {
   return Base64URLEncode(utf8Input.Length(),
     reinterpret_cast<const uint8_t*>(utf8Input.BeginReading()),
     Base64URLEncodePaddingPolicy::Include, result);
 }
 
-KeyPair::KeyPair(SECKEYPrivateKey * privateKey, SECKEYPublicKey * publicKey)
+KeyPair::KeyPair(SECKEYPrivateKey * privateKey, SECKEYPublicKey * publicKey,
+                 nsIEventTarget* operationThread)
   : mPrivateKey(privateKey)
   , mPublicKey(publicKey)
+  , mThread(operationThread)
 {
   MOZ_ASSERT(!NS_IsMainThread());
 }
 
 NS_IMETHODIMP
 KeyPair::GetHexRSAPublicKeyExponent(nsACString & result)
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -304,26 +316,26 @@ KeyPair::GetKeyType(nsACString & result)
 NS_IMETHODIMP
 KeyPair::Sign(const nsACString & textToSign,
               nsIIdentitySignCallback* callback)
 {
   MOZ_ASSERT(NS_IsMainThread());
   nsCOMPtr<nsIRunnable> r = new SignRunnable(textToSign, mPrivateKey,
                                              callback);
 
-  nsCOMPtr<nsIThread> thread;
-  nsresult rv = NS_NewNamedThread("KeyPair Sign", getter_AddRefs(thread), r);
-  return rv;
+  return mThread->Dispatch(r, NS_DISPATCH_NORMAL);
 }
 
 KeyGenRunnable::KeyGenRunnable(KeyType keyType,
-                               nsIIdentityKeyGenCallback * callback)
+                               nsIIdentityKeyGenCallback * callback,
+                               nsIEventTarget* operationThread)
   : mKeyType(keyType)
   , mCallback(new nsMainThreadPtrHolder<nsIIdentityKeyGenCallback>(callback))
   , mRv(NS_ERROR_NOT_INITIALIZED)
+  , mThread(operationThread)
 {
 }
 
 MOZ_MUST_USE nsresult
 GenerateKeyPair(PK11SlotInfo * slot,
                 SECKEYPrivateKey ** privateKey,
                 SECKEYPublicKey ** publicKey,
                 CK_MECHANISM_TYPE mechanism,
@@ -452,17 +464,17 @@ KeyGenRunnable::Run()
         }
 
         PK11_FreeSlot(slot);
 
         if (NS_SUCCEEDED(mRv)) {
           MOZ_ASSERT(privk);
           MOZ_ASSERT(pubk);
 		  // mKeyPair will take over ownership of privk and pubk
-          mKeyPair = new KeyPair(privk, pubk);
+          mKeyPair = new KeyPair(privk, pubk, mThread);
         }
       }
     }
 
     NS_DispatchToMainThread(this);
   } else {
     // Back on Main Thread
     (void) mCallback->GenerateKeyPairFinished(mRv, mKeyPair);