Bug 1314833 - Part 4: Factor out AbstractThread::MainThread() used in U2F. r=billm
authorBevis Tseng <btseng@mozilla.com>
Tue, 22 Nov 2016 14:19:06 +0800
changeset 375620 66e7178c31542d5cc6f893c3998ad17bf6845075
parent 375619 d3cfaafedb4339897fcede34a67125a4d16a7b98
child 375621 38db7f01d45d75547b026fbc9d739fe90e93675c
child 377326 586d65b40b24824331a16be1fe94f74e2e113a15
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1314833
milestone53.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 1314833 - Part 4: Factor out AbstractThread::MainThread() used in U2F. r=billm MozReview-Commit-ID: 7TcbTE9wab0
dom/u2f/U2F.cpp
dom/u2f/U2F.h
dom/webauthn/WebAuthentication.cpp
--- a/dom/u2f/U2F.cpp
+++ b/dom/u2f/U2F.cpp
@@ -157,61 +157,66 @@ nsString
 U2FStatus::GetResponse()
 {
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   MOZ_ASSERT(mIsStopped);
   return mResponse;
 }
 
 U2FTask::U2FTask(const nsAString& aOrigin, const nsAString& aAppId,
-                 const Authenticator& aAuthenticator)
+                 const Authenticator& aAuthenticator,
+                 AbstractThread* aMainThread)
   : mOrigin(aOrigin)
   , mAppId(aAppId)
   , mAuthenticator(aAuthenticator)
+  , mAbstractMainThread(aMainThread)
 {}
 
 U2FTask::~U2FTask()
 {}
 
 RefPtr<U2FPromise>
 U2FTask::Execute()
 {
   RefPtr<U2FPromise> p = mPromise.Ensure(__func__);
 
   nsCOMPtr<nsIRunnable> r(this);
 
   // TODO: Use a thread pool here, but we have to solve the PContentChild issues
   // of being in a worker thread.
-  AbstractThread::MainThread()->Dispatch(r.forget());
+  mAbstractMainThread->Dispatch(r.forget());
   return p;
 }
 
-U2FPrepTask::U2FPrepTask(const Authenticator& aAuthenticator)
+U2FPrepTask::U2FPrepTask(const Authenticator& aAuthenticator,
+                         AbstractThread* aMainThread)
   : mAuthenticator(aAuthenticator)
+  , mAbstractMainThread(aMainThread)
 {}
 
 U2FPrepTask::~U2FPrepTask()
 {}
 
 RefPtr<U2FPrepPromise>
 U2FPrepTask::Execute()
 {
   RefPtr<U2FPrepPromise> p = mPromise.Ensure(__func__);
 
   nsCOMPtr<nsIRunnable> r(this);
 
   // TODO: Use a thread pool here, but we have to solve the PContentChild issues
   // of being in a worker thread.
-  AbstractThread::MainThread()->Dispatch(r.forget());
+  mAbstractMainThread->Dispatch(r.forget());
   return p;
 }
 
 U2FIsRegisteredTask::U2FIsRegisteredTask(const Authenticator& aAuthenticator,
-                                         const LocalRegisteredKey& aRegisteredKey)
-  : U2FPrepTask(aAuthenticator)
+                                         const LocalRegisteredKey& aRegisteredKey,
+                                         AbstractThread* aMainThread)
+  : U2FPrepTask(aAuthenticator, aMainThread)
   , mRegisteredKey(aRegisteredKey)
 {}
 
 U2FIsRegisteredTask::~U2FIsRegisteredTask()
 {}
 
 NS_IMETHODIMP
 U2FIsRegisteredTask::Run()
@@ -257,18 +262,19 @@ U2FIsRegisteredTask::Run()
   return NS_OK;
 }
 
 U2FRegisterTask::U2FRegisterTask(const nsAString& aOrigin,
                                  const nsAString& aAppId,
                                  const Authenticator& aAuthenticator,
                                  const CryptoBuffer& aAppParam,
                                  const CryptoBuffer& aChallengeParam,
-                                 const LocalRegisterRequest& aRegisterEntry)
-  : U2FTask(aOrigin, aAppId, aAuthenticator)
+                                 const LocalRegisterRequest& aRegisterEntry,
+                                 AbstractThread* aMainThread)
+  : U2FTask(aOrigin, aAppId, aAuthenticator, aMainThread)
   , mAppParam(aAppParam)
   , mChallengeParam(aChallengeParam)
   , mRegisterEntry(aRegisterEntry)
 {}
 
 U2FRegisterTask::~U2FRegisterTask()
 {}
 
@@ -336,18 +342,19 @@ U2FRegisterTask::Run()
 
 U2FSignTask::U2FSignTask(const nsAString& aOrigin,
                          const nsAString& aAppId,
                          const nsAString& aVersion,
                          const Authenticator& aAuthenticator,
                          const CryptoBuffer& aAppParam,
                          const CryptoBuffer& aChallengeParam,
                          const CryptoBuffer& aClientData,
-                         const CryptoBuffer& aKeyHandle)
-  : U2FTask(aOrigin, aAppId, aAuthenticator)
+                         const CryptoBuffer& aKeyHandle,
+                         AbstractThread* aMainThread)
+  : U2FTask(aOrigin, aAppId, aAuthenticator, aMainThread)
   , mVersion(aVersion)
   , mAppParam(aAppParam)
   , mChallengeParam(aChallengeParam)
   , mClientData(aClientData)
   , mKeyHandle(aKeyHandle)
 {}
 
 U2FSignTask::~U2FSignTask()
@@ -424,19 +431,21 @@ U2FSignTask::Run()
   nsString responseStr;
   if (NS_WARN_IF(!response.ToJSON(responseStr))) {
     return NS_ERROR_FAILURE;
   }
   mPromise.Resolve(responseStr, __func__);
   return NS_OK;
 }
 
-U2FRunnable::U2FRunnable(const nsAString& aOrigin, const nsAString& aAppId)
+U2FRunnable::U2FRunnable(const nsAString& aOrigin, const nsAString& aAppId,
+                         AbstractThread* aMainThread)
   : mOrigin(aOrigin)
   , mAppId(aAppId)
+  , mAbstractMainThread(aMainThread)
 {}
 
 U2FRunnable::~U2FRunnable()
 {}
 
 // EvaluateAppIDAndRunTask determines whether the supplied FIDO AppID is valid for
 // the current FacetID, e.g., the current origin.
 // See https://fidoalliance.org/specs/fido-u2f-v1.0-nfc-bt-amendment-20150514/fido-appid-and-facets.html
@@ -508,18 +517,19 @@ U2FRunnable::EvaluateAppID()
   return ErrorCode::BAD_REQUEST;
 }
 
 U2FRegisterRunnable::U2FRegisterRunnable(const nsAString& aOrigin,
                                          const nsAString& aAppId,
                                          const Sequence<RegisterRequest>& aRegisterRequests,
                                          const Sequence<RegisteredKey>& aRegisteredKeys,
                                          const Sequence<Authenticator>& aAuthenticators,
-                                         U2FRegisterCallback* aCallback)
-  : U2FRunnable(aOrigin, aAppId)
+                                         U2FRegisterCallback* aCallback,
+                                         AbstractThread* aMainThread)
+  : U2FRunnable(aOrigin, aAppId, aMainThread)
   , mAuthenticators(aAuthenticators)
   // U2FRegisterCallback does not support threadsafe refcounting, and must be
   // used and destroyed on main.
   , mCallback(new nsMainThreadPtrHolder<U2FRegisterCallback>(aCallback))
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // The WebIDL dictionary types RegisterRequest and RegisteredKey cannot
@@ -612,25 +622,26 @@ U2FRegisterRunnable::Run()
   }
 
   // First, we must determine if any of the RegisteredKeys are already
   // registered, e.g., in the whitelist.
   for (LocalRegisteredKey key: mRegisteredKeys) {
     nsTArray<RefPtr<U2FPrepPromise>> prepPromiseList;
     for (size_t a = 0; a < mAuthenticators.Length(); ++a) {
       Authenticator token(mAuthenticators[a]);
-      RefPtr<U2FIsRegisteredTask> compTask = new U2FIsRegisteredTask(token, key);
+      RefPtr<U2FIsRegisteredTask> compTask =
+        new U2FIsRegisteredTask(token, key, mAbstractMainThread);
       prepPromiseList.AppendElement(compTask->Execute());
     }
 
     // Treat each call to Promise::All as a work unit, as it completes together
     status->WaitGroupAdd();
 
-    U2FPrepPromise::All(AbstractThread::MainThread(), prepPromiseList)
-    ->Then(AbstractThread::MainThread(), __func__,
+    U2FPrepPromise::All(mAbstractMainThread, prepPromiseList)
+    ->Then(mAbstractMainThread, __func__,
       [status] (const nsTArray<Authenticator>& aTokens) {
         MOZ_LOG(gU2FLog, LogLevel::Debug,
                 ("ALL: None of the RegisteredKeys were recognized. n=%d",
                  aTokens.Length()));
 
         status->WaitGroupDone();
       },
       [status] (ErrorCode aErrorCode) {
@@ -641,17 +652,17 @@ U2FRegisterRunnable::Run()
 
   // Wait for all the IsRegistered tasks to complete
   status->WaitGroupWait();
 
   // Check to see whether we're supposed to stop, because one of the keys was
   // recognized.
   if (status->IsStopped()) {
     status->WaitGroupAdd();
-    AbstractThread::MainThread()->Dispatch(NS_NewRunnableFunction(
+    mAbstractMainThread->Dispatch(NS_NewRunnableFunction(
       [status, this] () {
         RegisterResponse response;
         response.mErrorCode.Construct(
             static_cast<uint32_t>(status->GetErrorCode()));
         SendResponse(response);
         status->WaitGroupDone();
       }
     ));
@@ -692,20 +703,21 @@ U2FRegisterRunnable::Run()
       continue;
     }
 
     for (size_t a = 0; a < mAuthenticators.Length(); ++a) {
       Authenticator token(mAuthenticators[a]);
       RefPtr<U2FRegisterTask> registerTask = new U2FRegisterTask(mOrigin, mAppId,
                                                                  token, appParam,
                                                                  challengeParam,
-                                                                 req);
+                                                                 req,
+                                                                 mAbstractMainThread);
       status->WaitGroupAdd();
 
-      registerTask->Execute()->Then(AbstractThread::MainThread(), __func__,
+      registerTask->Execute()->Then(mAbstractMainThread, __func__,
         [status, this] (nsString aResponse) {
           if (status->IsStopped()) {
             return;
           }
           status->Stop(ErrorCode::OK, aResponse);
           status->WaitGroupDone();
         },
         [status, this] (ErrorCode aErrorCode) {
@@ -723,17 +735,17 @@ U2FRegisterRunnable::Run()
 
   // If none of the tasks completed, then nothing could satisfy.
   if (!status->IsStopped()) {
     status->Stop(ErrorCode::BAD_REQUEST);
   }
 
   // Transmit back to the JS engine from the Main Thread
   status->WaitGroupAdd();
-  AbstractThread::MainThread()->Dispatch(NS_NewRunnableFunction(
+  mAbstractMainThread->Dispatch(NS_NewRunnableFunction(
     [status, this] () {
       RegisterResponse response;
       if (status->GetErrorCode() == ErrorCode::OK) {
         response.Init(status->GetResponse());
       } else {
         response.mErrorCode.Construct(
             static_cast<uint32_t>(status->GetErrorCode()));
       }
@@ -747,18 +759,19 @@ U2FRegisterRunnable::Run()
   return NS_OK;
 }
 
 U2FSignRunnable::U2FSignRunnable(const nsAString& aOrigin,
                                  const nsAString& aAppId,
                                  const nsAString& aChallenge,
                                  const Sequence<RegisteredKey>& aRegisteredKeys,
                                  const Sequence<Authenticator>& aAuthenticators,
-                                 U2FSignCallback* aCallback)
-  : U2FRunnable(aOrigin, aAppId)
+                                 U2FSignCallback* aCallback,
+                                 AbstractThread* aMainThread)
+  : U2FRunnable(aOrigin, aAppId, aMainThread)
   , mAuthenticators(aAuthenticators)
   // U2FSignCallback does not support threadsafe refcounting, and must be used
   // and destroyed on main.
   , mCallback(new nsMainThreadPtrHolder<U2FSignCallback>(aCallback))
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // Convert WebIDL objects to generic structs to pass between threads
@@ -878,20 +891,21 @@ U2FSignRunnable::Run()
     // available devices by preference, but is not an exclusion factor.
 
     for (size_t a = 0; a < mAuthenticators.Length() ; ++a) {
       Authenticator token(mAuthenticators[a]);
 
       RefPtr<U2FSignTask> signTask = new U2FSignTask(mOrigin, mAppId,
                                                      key.mVersion, token,
                                                      appParam, challengeParam,
-                                                     mClientData, keyHandle);
+                                                     mClientData, keyHandle,
+                                                     mAbstractMainThread);
       status->WaitGroupAdd();
 
-      signTask->Execute()->Then(AbstractThread::MainThread(), __func__,
+      signTask->Execute()->Then(mAbstractMainThread, __func__,
         [status, this] (nsString aResponse) {
           if (status->IsStopped()) {
             return;
           }
           status->Stop(ErrorCode::OK, aResponse);
           status->WaitGroupDone();
         },
         [status, this] (ErrorCode aErrorCode) {
@@ -909,17 +923,17 @@ U2FSignRunnable::Run()
 
   // If none of the tasks completed, then nothing could satisfy.
   if (!status->IsStopped()) {
     status->Stop(ErrorCode::DEVICE_INELIGIBLE);
   }
 
   // Transmit back to the JS engine from the Main Thread
   status->WaitGroupAdd();
-  AbstractThread::MainThread()->Dispatch(NS_NewRunnableFunction(
+  mAbstractMainThread->Dispatch(NS_NewRunnableFunction(
     [status, this] () {
       SignResponse response;
       if (status->GetErrorCode() == ErrorCode::OK) {
         response.Init(status->GetResponse());
       } else {
         response.mErrorCode.Construct(
           static_cast<uint32_t>(status->GetErrorCode()));
       }
@@ -996,16 +1010,18 @@ U2F::Init(nsPIDOMWindowInner* aParent, E
   if (Preferences::GetBool(PREF_U2F_SOFTTOKEN_ENABLED)) {
     if (!mAuthenticators.AppendElement(new NSSU2FTokenRemote(),
                                        mozilla::fallible)) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
   }
 
+  mAbstractMainThread = doc->AbstractMainThreadFor(TaskCategory::Other);
+
   mInitialized = true;
 }
 
 void
 U2F::Register(const nsAString& aAppId,
               const Sequence<RegisterRequest>& aRegisterRequests,
               const Sequence<RegisteredKey>& aRegisteredKeys,
               U2FRegisterCallback& aCallback,
@@ -1019,17 +1035,18 @@ U2F::Register(const nsAString& aAppId,
     return;
   }
 
   RefPtr<SharedThreadPool> pool = SharedThreadPool::Get(kPoolName);
   RefPtr<U2FRegisterRunnable> task = new U2FRegisterRunnable(mOrigin, aAppId,
                                                              aRegisterRequests,
                                                              aRegisteredKeys,
                                                              mAuthenticators,
-                                                             &aCallback);
+                                                             &aCallback,
+                                                             mAbstractMainThread);
   pool->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
 }
 
 void
 U2F::Sign(const nsAString& aAppId,
           const nsAString& aChallenge,
           const Sequence<RegisteredKey>& aRegisteredKeys,
           U2FSignCallback& aCallback,
@@ -1041,14 +1058,15 @@ U2F::Sign(const nsAString& aAppId,
   if (!mInitialized) {
     aRv.Throw(NS_ERROR_NOT_AVAILABLE);
     return;
   }
 
   RefPtr<SharedThreadPool> pool = SharedThreadPool::Get(kPoolName);
   RefPtr<U2FSignRunnable> task = new U2FSignRunnable(mOrigin, aAppId, aChallenge,
                                                      aRegisteredKeys,
-                                                     mAuthenticators, &aCallback);
+                                                     mAuthenticators, &aCallback,
+                                                     mAbstractMainThread);
   pool->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/u2f/U2F.h
+++ b/dom/u2f/U2F.h
@@ -22,16 +22,19 @@
 #include "nsNSSShutDown.h"
 #include "nsPIDOMWindow.h"
 #include "nsProxyRelease.h"
 #include "nsWrapperCache.h"
 
 #include "U2FAuthenticator.h"
 
 namespace mozilla {
+
+class AbstractThread;
+
 namespace dom {
 
 class U2FRegisterCallback;
 class U2FSignCallback;
 
 // Defined in U2FBinding.h by the U2F.webidl; their use requires a JSContext.
 struct RegisterRequest;
 struct RegisteredKey;
@@ -58,54 +61,59 @@ typedef MozPromise<nsString, ErrorCode, 
 typedef MozPromise<Authenticator, ErrorCode, false> U2FPrepPromise;
 
 // U2FPrepTasks return lists of Authenticators that are OK to
 // proceed; they're useful for culling incompatible Authenticators.
 // Currently, only IsRegistered is supported.
 class U2FPrepTask : public Runnable
 {
 public:
-  explicit U2FPrepTask(const Authenticator& aAuthenticator);
+  explicit U2FPrepTask(const Authenticator& aAuthenticator,
+                       AbstractThread* aMainThread);
 
   RefPtr<U2FPrepPromise> Execute();
 
 protected:
   virtual ~U2FPrepTask();
 
   Authenticator mAuthenticator;
   MozPromiseHolder<U2FPrepPromise> mPromise;
+  const RefPtr<AbstractThread> mAbstractMainThread;
 };
 
 // Determine whether the provided Authenticator already knows
 // of the provided Registered Key.
 class U2FIsRegisteredTask final : public U2FPrepTask
 {
 public:
   U2FIsRegisteredTask(const Authenticator& aAuthenticator,
-                      const LocalRegisteredKey& aRegisteredKey);
+                      const LocalRegisteredKey& aRegisteredKey,
+                      AbstractThread* aMainThread);
 
   NS_DECL_NSIRUNNABLE
 private:
   ~U2FIsRegisteredTask();
 
   LocalRegisteredKey mRegisteredKey;
 };
 
 class U2FTask : public Runnable
 {
 public:
   U2FTask(const nsAString& aOrigin,
           const nsAString& aAppId,
-          const Authenticator& aAuthenticator);
+          const Authenticator& aAuthenticator,
+          AbstractThread* aMainThread);
 
   RefPtr<U2FPromise> Execute();
 
   nsString mOrigin;
   nsString mAppId;
   Authenticator mAuthenticator;
+  const RefPtr<AbstractThread> mAbstractMainThread;
 
 protected:
   virtual ~U2FTask();
 
   MozPromiseHolder<U2FPromise> mPromise;
 };
 
 // Use the provided Authenticator to Register a new scoped credential
@@ -113,17 +121,18 @@ protected:
 class U2FRegisterTask final : public U2FTask
 {
 public:
   U2FRegisterTask(const nsAString& aOrigin,
                   const nsAString& aAppId,
                   const Authenticator& aAuthenticator,
                   const CryptoBuffer& aAppParam,
                   const CryptoBuffer& aChallengeParam,
-                  const LocalRegisterRequest& aRegisterEntry);
+                  const LocalRegisterRequest& aRegisterEntry,
+                  AbstractThread* aMainThread);
 
   NS_DECL_NSIRUNNABLE
 private:
   ~U2FRegisterTask();
 
   CryptoBuffer mAppParam;
   CryptoBuffer mChallengeParam;
   LocalRegisterRequest mRegisterEntry;
@@ -136,17 +145,18 @@ class U2FSignTask final : public U2FTask
 public:
   U2FSignTask(const nsAString& aOrigin,
               const nsAString& aAppId,
               const nsAString& aVersion,
               const Authenticator& aAuthenticator,
               const CryptoBuffer& aAppParam,
               const CryptoBuffer& aChallengeParam,
               const CryptoBuffer& aClientData,
-              const CryptoBuffer& aKeyHandle);
+              const CryptoBuffer& aKeyHandle,
+              AbstractThread* aMainThread);
 
   NS_DECL_NSIRUNNABLE
 private:
   ~U2FSignTask();
 
   nsString mVersion;
   CryptoBuffer mAppParam;
   CryptoBuffer mChallengeParam;
@@ -184,41 +194,44 @@ private:
 };
 
 // U2FRunnables run to completion, performing a single U2F operation such as
 // registering, or signing.
 class U2FRunnable : public Runnable
                   , public nsNSSShutDownObject
 {
 public:
-  U2FRunnable(const nsAString& aOrigin, const nsAString& aAppId);
+  U2FRunnable(const nsAString& aOrigin, const nsAString& aAppId,
+              AbstractThread* aMainThread);
 
   // No NSS resources to release.
   virtual
   void virtualDestroyNSSReference() override {};
 
 protected:
   virtual ~U2FRunnable();
   ErrorCode EvaluateAppID();
 
   nsString mOrigin;
   nsString mAppId;
+  const RefPtr<AbstractThread> mAbstractMainThread;
 };
 
 // This U2FRunnable completes a single application-requested U2F Register
 // operation.
 class U2FRegisterRunnable : public U2FRunnable
 {
 public:
   U2FRegisterRunnable(const nsAString& aOrigin,
                       const nsAString& aAppId,
                       const Sequence<RegisterRequest>& aRegisterRequests,
                       const Sequence<RegisteredKey>& aRegisteredKeys,
                       const Sequence<Authenticator>& aAuthenticators,
-                      U2FRegisterCallback* aCallback);
+                      U2FRegisterCallback* aCallback,
+                      AbstractThread* aMainThread);
 
   void SendResponse(const RegisterResponse& aResponse);
   void SetTimeout(const int32_t aTimeoutMillis);
 
   NS_DECL_NSIRUNNABLE
 
 private:
   ~U2FRegisterRunnable();
@@ -234,17 +247,18 @@ private:
 class U2FSignRunnable : public U2FRunnable
 {
 public:
   U2FSignRunnable(const nsAString& aOrigin,
                   const nsAString& aAppId,
                   const nsAString& aChallenge,
                   const Sequence<RegisteredKey>& aRegisteredKeys,
                   const Sequence<Authenticator>& aAuthenticators,
-                  U2FSignCallback* aCallback);
+                  U2FSignCallback* aCallback,
+                  AbstractThread* aMainThread);
 
   void SendResponse(const SignResponse& aResponse);
   void SetTimeout(const int32_t aTimeoutMillis);
 
   NS_DECL_NSIRUNNABLE
 
 private:
   ~U2FSignRunnable();
@@ -300,16 +314,17 @@ public:
   virtual
   void virtualDestroyNSSReference() override {};
 
 private:
   nsCOMPtr<nsPIDOMWindowInner> mParent;
   nsString mOrigin;
   Sequence<Authenticator> mAuthenticators;
   bool mInitialized;
+  RefPtr<AbstractThread> mAbstractMainThread;
 
   ~U2F();
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_U2F_h
--- a/dom/webauthn/WebAuthentication.cpp
+++ b/dom/webauthn/WebAuthentication.cpp
@@ -847,17 +847,18 @@ WebAuthentication::MakeCredential(JSCont
     // the existence of C.
     U2FAuthMakeCredential(requestMonitor, u2ftoken, rpIdHash, clientDataJSON,
                           clientDataHash, aAccount, normalizedParams,
                           aOptions.mExcludeList, aOptions.mExtensions);
   }
 
   requestMonitor->CompleteTask();
 
-  monitorPromise->Then(AbstractThread::MainThread(), __func__,
+  monitorPromise->Then(
+    global->AbstractMainThreadFor(TaskCategory::Other), __func__,
     [promise] (CredentialPtr aInfo) {
       promise->MaybeResolve(aInfo);
     },
     [promise] (nsresult aErrorCode) {
       promise->MaybeReject(aErrorCode);
   });
 
   return promise.forget();
@@ -1037,17 +1038,18 @@ WebAuthentication::GetAssertion(const Ar
     // on this authenticator with rpIdHash, clientDataHash, credentialList, and
     // clientExtensions as parameters.
     U2FAuthGetAssertion(requestMonitor, u2ftoken, rpIdHash, clientDataJSON,
                         clientDataHash, credentialList, aOptions.mExtensions);
   }
 
   requestMonitor->CompleteTask();
 
-  monitorPromise->Then(AbstractThread::MainThread(), __func__,
+  monitorPromise->Then(
+    global->AbstractMainThreadFor(TaskCategory::Other), __func__,
     [promise] (AssertionPtr aAssertion) {
       promise->MaybeResolve(aAssertion);
     },
     [promise] (nsresult aErrorCode) {
       promise->MaybeReject(aErrorCode);
   });
 
   return promise.forget();