Bug 1372736 - Avoid using AbstractThread for non-media MozPromises (r=bkelly)
authorBill McCloskey <billm@mozilla.com>
Fri, 09 Jun 2017 21:24:46 -0700
changeset 364233 871e57ecd232a8aeb1feb47e6aff647ae867588a
parent 364232 8408c88a471ca55dc914098ded86e9ffaacff7a3
child 364234 b4f50a8eb778910abcc62ea62cee5f3b3b29bc1f
push id91508
push userwmccloskey@mozilla.com
push dateFri, 16 Jun 2017 03:16:34 +0000
treeherdermozilla-inbound@871e57ecd232 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbkelly
bugs1372736
milestone56.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 1372736 - Avoid using AbstractThread for non-media MozPromises (r=bkelly) MozReview-Commit-ID: BBi0pK4DXxf
dom/flyweb/FlyWebPublishedServer.cpp
dom/flyweb/HttpServer.cpp
dom/flyweb/HttpServer.h
dom/script/ScriptLoader.cpp
dom/u2f/U2F.cpp
dom/u2f/U2F.h
dom/webauthn/U2FSoftTokenManager.cpp
dom/webauthn/WebAuthnManager.cpp
dom/workers/ServiceWorkerUpdaterChild.cpp
editor/composer/nsEditorSpellCheck.cpp
netwerk/protocol/http/HttpChannelParent.cpp
tools/profiler/gecko/nsProfiler.cpp
xpcom/threads/AbstractThread.h
--- a/dom/flyweb/FlyWebPublishedServer.cpp
+++ b/dom/flyweb/FlyWebPublishedServer.cpp
@@ -11,17 +11,16 @@
 #include "mozilla/dom/Request.h"
 #include "mozilla/dom/FlyWebServerEvents.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/InternalResponse.h"
 #include "mozilla/ipc/IPCStreamUtils.h"
 #include "mozilla/net/NeckoParent.h"
 #include "mozilla/net/IPCTransportProvider.h"
-#include "mozilla/AbstractThread.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Unused.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsGlobalWindow.h"
 #include "WebSocketChannel.h"
 
 namespace mozilla {
@@ -167,18 +166,18 @@ FlyWebPublishedServer::OnWebSocketAccept
 NS_IMPL_ISUPPORTS_INHERITED0(FlyWebPublishedServerImpl, mozilla::DOMEventTargetHelper)
 
 FlyWebPublishedServerImpl::FlyWebPublishedServerImpl(nsPIDOMWindowInner* aOwner,
                                                      const nsAString& aName,
                                                      const FlyWebPublishOptions& aOptions)
   : FlyWebPublishedServer(aOwner, aName, aOptions)
   , mHttpServer(
       new HttpServer(aOwner ?
-        aOwner->GetDocGroup()->AbstractMainThreadFor(TaskCategory::Other) :
-        AbstractThread::MainThread()))
+        aOwner->GetDocGroup()->EventTargetFor(TaskCategory::Other) :
+        GetMainThreadSerialEventTarget()))
 {
   LOG_I("FlyWebPublishedServerImpl::FlyWebPublishedServerImpl(%p)", this);
 }
 
 void
 FlyWebPublishedServerImpl::PermissionGranted(bool aGranted)
 {
   LOG_I("FlyWebPublishedServerImpl::PermissionGranted(%d)", aGranted);
@@ -486,18 +485,18 @@ FlyWebPublishedServerParent::FlyWebPubli
   if (!mozPromise) {
     Unused << SendServerReady(NS_ERROR_FAILURE);
     return;
   }
 
   RefPtr<FlyWebPublishedServerParent> self = this;
 
   mozPromise->Then(
-    // Non DocGroup-version of AbstractThread::MainThread() for the task in parent.
-    AbstractThread::MainThread(),
+    // Non DocGroup-version for the task in parent.
+    GetMainThreadSerialEventTarget(),
     __func__,
     [this, self] (FlyWebPublishedServer* aServer) {
       mPublishedServer = static_cast<FlyWebPublishedServerImpl*>(aServer);
       if (mActorDestroyed) {
         mPublishedServer->Close();
         return;
       }
 
--- a/dom/flyweb/HttpServer.cpp
+++ b/dom/flyweb/HttpServer.cpp
@@ -31,20 +31,20 @@ static LazyLogModule gHttpServerLog("Htt
 #undef LOG_E
 #define LOG_E(...) MOZ_LOG(gHttpServerLog, mozilla::LogLevel::Error, (__VA_ARGS__))
 
 
 NS_IMPL_ISUPPORTS(HttpServer,
                   nsIServerSocketListener,
                   nsILocalCertGetCallback)
 
-HttpServer::HttpServer(AbstractThread* aMainThread)
+HttpServer::HttpServer(nsISerialEventTarget* aEventTarget)
   : mPort()
   , mHttps()
-  , mAbstractMainThread(aMainThread)
+  , mEventTarget(aEventTarget)
 {
 }
 
 HttpServer::~HttpServer()
 {
 }
 
 void
@@ -1251,17 +1251,17 @@ HttpServer::Connection::OnOutputStreamRe
       mOutputCopy =
         StreamCopier::Copy(mOutputBuffers[0].mStream,
                            mOutput,
                            mOutputBuffers[0].mChunked);
 
       RefPtr<Connection> self = this;
 
       mOutputCopy->
-        Then(mServer->mAbstractMainThread,
+        Then(mServer->mEventTarget,
              __func__,
              [self, this] (nsresult aStatus) {
                MOZ_ASSERT(mOutputBuffers[0].mStream);
                LOG_V("HttpServer::Connection::OnOutputStreamReady(%p) - "
                      "Sent body. Status 0x%" PRIx32,
                      this, static_cast<uint32_t>(aStatus));
 
                mOutputBuffers.RemoveElementAt(0);
--- a/dom/flyweb/HttpServer.h
+++ b/dom/flyweb/HttpServer.h
@@ -15,20 +15,19 @@
 #include "mozilla/Variant.h"
 #include "nsIRequestObserver.h"
 #include "mozilla/MozPromise.h"
 #include "nsITransportProvider.h"
 #include "nsILocalCertService.h"
 
 class nsIX509Cert;
 
-namespace mozilla {
+class nsISerialEventTarget;
 
-class AbstractThread;
-
+namespace mozilla {
 namespace dom {
 
 extern bool
 ContainsToken(const nsCString& aList, const nsCString& aToken);
 
 class InternalRequest;
 class InternalResponse;
 
@@ -42,17 +41,17 @@ public:
   virtual void OnWebSocket(InternalRequest* aConnectRequest) = 0;
   virtual void OnServerClose() = 0;
 };
 
 class HttpServer final : public nsIServerSocketListener,
                          public nsILocalCertGetCallback
 {
 public:
-  explicit HttpServer(AbstractThread* aMainThread);
+  explicit HttpServer(nsISerialEventTarget* aEventTarget);
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSISERVERSOCKETLISTENER
   NS_DECL_NSILOCALCERTGETCALLBACK
 
   void Init(int32_t aPort, bool aHttps, HttpServerListener* aListener);
 
   void SendResponse(InternalRequest* aRequest, InternalResponse* aResponse);
@@ -182,15 +181,15 @@ private:
   nsCOMPtr<nsIServerSocket> mServerSocket;
   nsCOMPtr<nsIX509Cert> mCert;
 
   nsTArray<RefPtr<Connection>> mConnections;
 
   int32_t mPort;
   bool mHttps;
 
-  const RefPtr<AbstractThread> mAbstractMainThread;
+  const nsCOMPtr<nsISerialEventTarget> mEventTarget;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HttpServer_h
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -52,17 +52,16 @@
 #include "nsContentCreatorFunctions.h"
 #include "nsProxyRelease.h"
 #include "nsSandboxFlags.h"
 #include "nsContentTypeParser.h"
 #include "nsINetworkPredictor.h"
 #include "mozilla/dom/EncodingUtils.h"
 #include "mozilla/ConsoleReportCollector.h"
 
-#include "mozilla/AbstractThread.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Unused.h"
 #include "nsIScriptError.h"
 #include "nsIOutputStream.h"
 
@@ -626,18 +625,18 @@ ScriptLoader::StartFetchingModuleDepende
   for (size_t i = 0; i < urls.Length(); i++) {
     RefPtr<GenericPromise> childReady =
       StartFetchingModuleAndDependencies(aRequest, urls[i]);
     importsReady.AppendElement(childReady);
   }
 
   // Wait for all imports to become ready.
   RefPtr<GenericPromise::AllPromiseType> allReady =
-    GenericPromise::All(AbstractThread::MainThread(), importsReady);
-  allReady->Then(AbstractThread::MainThread(), __func__, aRequest,
+    GenericPromise::All(GetMainThreadSerialEventTarget(), importsReady);
+  allReady->Then(GetMainThreadSerialEventTarget(), __func__, aRequest,
                  &ModuleLoadRequest::DependenciesLoaded,
                  &ModuleLoadRequest::LoadFailed);
 }
 
 RefPtr<GenericPromise>
 ScriptLoader::StartFetchingModuleAndDependencies(ModuleLoadRequest* aRequest,
                                                  nsIURI* aURI)
 {
@@ -835,17 +834,17 @@ ScriptLoader::StartLoad(ScriptLoadReques
   }
 
   if (aRequest->IsModuleRequest()) {
     // Check whether the module has been fetched or is currently being fetched,
     // and if so wait for it.
     ModuleLoadRequest* request = aRequest->AsModuleRequest();
     if (ModuleMapContainsModule(request)) {
       WaitForModuleFetch(request)
-        ->Then(AbstractThread::MainThread(), __func__, request,
+        ->Then(GetMainThreadSerialEventTarget(), __func__, request,
                &ModuleLoadRequest::ModuleLoaded,
                &ModuleLoadRequest::LoadFailed);
       return NS_OK;
     }
 
     // Otherwise put the URL in the module map and mark it as fetching.
     SetModuleFetchStarted(request);
   }
--- a/dom/u2f/U2F.cpp
+++ b/dom/u2f/U2F.cpp
@@ -1,28 +1,28 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 "hasht.h"
-#include "mozilla/AbstractThread.h"
 #include "mozilla/dom/CallbackFunction.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/CryptoBuffer.h"
 #include "mozilla/dom/NSSU2FTokenRemote.h"
 #include "mozilla/dom/U2F.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "mozilla/SizePrintfMacros.h"
 #include "nsContentUtils.h"
 #include "nsINSSU2FToken.h"
 #include "nsNetCID.h"
 #include "nsNSSComponent.h"
+#include "nsThreadUtils.h"
 #include "nsURLParsers.h"
 #include "nsXPCOMCIDInternal.h"
 #include "pk11pub.h"
 
 using mozilla::dom::ContentChild;
 
 namespace mozilla {
 namespace dom {
@@ -160,66 +160,66 @@ U2FStatus::GetResponse()
 {
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   MOZ_ASSERT(mIsStopped);
   return mResponse;
 }
 
 U2FTask::U2FTask(const nsAString& aOrigin, const nsAString& aAppId,
                  const Authenticator& aAuthenticator,
-                 AbstractThread* aMainThread)
+                 nsISerialEventTarget* aEventTarget)
   : mOrigin(aOrigin)
   , mAppId(aAppId)
   , mAuthenticator(aAuthenticator)
-  , mAbstractMainThread(aMainThread)
+  , mEventTarget(aEventTarget)
 {}
 
 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.
-  mAbstractMainThread->Dispatch(r.forget());
+  mEventTarget->Dispatch(r.forget());
   return p;
 }
 
 U2FPrepTask::U2FPrepTask(const Authenticator& aAuthenticator,
-                         AbstractThread* aMainThread)
+                         nsISerialEventTarget* aEventTarget)
   : mAuthenticator(aAuthenticator)
-  , mAbstractMainThread(aMainThread)
+  , mEventTarget(aEventTarget)
 {}
 
 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.
-  mAbstractMainThread->Dispatch(r.forget());
+  mEventTarget->Dispatch(r.forget());
   return p;
 }
 
 U2FIsRegisteredTask::U2FIsRegisteredTask(const Authenticator& aAuthenticator,
                                          const LocalRegisteredKey& aRegisteredKey,
                                          const CryptoBuffer& aAppParam,
-                                         AbstractThread* aMainThread)
-  : U2FPrepTask(aAuthenticator, aMainThread)
+                                         nsISerialEventTarget* aEventTarget)
+  : U2FPrepTask(aAuthenticator, aEventTarget)
   , mRegisteredKey(aRegisteredKey)
   , mAppParam(aAppParam)
 {}
 
 U2FIsRegisteredTask::~U2FIsRegisteredTask()
 {}
 
 NS_IMETHODIMP
@@ -268,18 +268,18 @@ U2FIsRegisteredTask::Run()
 }
 
 U2FRegisterTask::U2FRegisterTask(const nsAString& aOrigin,
                                  const nsAString& aAppId,
                                  const Authenticator& aAuthenticator,
                                  const CryptoBuffer& aAppParam,
                                  const CryptoBuffer& aChallengeParam,
                                  const LocalRegisterRequest& aRegisterEntry,
-                                 AbstractThread* aMainThread)
-  : U2FTask(aOrigin, aAppId, aAuthenticator, aMainThread)
+                                 nsISerialEventTarget* aEventTarget)
+  : U2FTask(aOrigin, aAppId, aAuthenticator, aEventTarget)
   , mAppParam(aAppParam)
   , mChallengeParam(aChallengeParam)
   , mRegisterEntry(aRegisterEntry)
 {}
 
 U2FRegisterTask::~U2FRegisterTask()
 {}
 
@@ -348,18 +348,18 @@ 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,
-                         AbstractThread* aMainThread)
-  : U2FTask(aOrigin, aAppId, aAuthenticator, aMainThread)
+                         nsISerialEventTarget* aEventTarget)
+  : U2FTask(aOrigin, aAppId, aAuthenticator, aEventTarget)
   , mVersion(aVersion)
   , mAppParam(aAppParam)
   , mChallengeParam(aChallengeParam)
   , mClientData(aClientData)
   , mKeyHandle(aKeyHandle)
 {}
 
 U2FSignTask::~U2FSignTask()
@@ -438,20 +438,20 @@ U2FSignTask::Run()
   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,
-                         AbstractThread* aMainThread)
+                         nsISerialEventTarget* aEventTarget)
   : mOrigin(aOrigin)
   , mAppId(aAppId)
-  , mAbstractMainThread(aMainThread)
+  , mEventTarget(aEventTarget)
 {}
 
 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
@@ -524,18 +524,18 @@ U2FRunnable::EvaluateAppID()
 }
 
 U2FRegisterRunnable::U2FRegisterRunnable(const nsAString& aOrigin,
                                          const nsAString& aAppId,
                                          const Sequence<RegisterRequest>& aRegisterRequests,
                                          const Sequence<RegisteredKey>& aRegisteredKeys,
                                          const Sequence<Authenticator>& aAuthenticators,
                                          U2FRegisterCallback* aCallback,
-                                         AbstractThread* aMainThread)
-  : U2FRunnable(aOrigin, aAppId, aMainThread)
+                                         nsISerialEventTarget* aEventTarget)
+  : U2FRunnable(aOrigin, aAppId, aEventTarget)
   , 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
@@ -641,25 +641,25 @@ 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 (const Authenticator& token : mAuthenticators) {
       RefPtr<U2FIsRegisteredTask> compTask =
-        new U2FIsRegisteredTask(token, key, appParam, mAbstractMainThread);
+        new U2FIsRegisteredTask(token, key, appParam, mEventTarget);
       prepPromiseList.AppendElement(compTask->Execute());
     }
 
     // Treat each call to Promise::All as a work unit, as it completes together
     status->WaitGroupAdd();
 
-    U2FPrepPromise::All(mAbstractMainThread, prepPromiseList)
-    ->Then(mAbstractMainThread, __func__,
+    U2FPrepPromise::All(mEventTarget, prepPromiseList)
+    ->Then(mEventTarget, __func__,
       [&status] (const nsTArray<Authenticator>& aTokens) {
         MOZ_LOG(gU2FLog, LogLevel::Debug,
                 ("ALL: None of the RegisteredKeys were recognized. n=%" PRIuSIZE,
                  aTokens.Length()));
 
         status->WaitGroupDone();
       },
       [&status] (ErrorCode aErrorCode) {
@@ -670,17 +670,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();
-    mAbstractMainThread->Dispatch(NS_NewRunnableFunction(
+    mEventTarget->Dispatch(NS_NewRunnableFunction(
       [&status, this] () {
         RegisterResponse response;
         response.mErrorCode.Construct(
             static_cast<uint32_t>(status->GetErrorCode()));
         SendResponse(response);
         status->WaitGroupDone();
       }
     ));
@@ -704,20 +704,20 @@ U2FRegisterRunnable::Run()
       continue;
     }
 
     for (const Authenticator& token : mAuthenticators) {
       RefPtr<U2FRegisterTask> registerTask = new U2FRegisterTask(mOrigin, mAppId,
                                                                  token, appParam,
                                                                  challengeParam,
                                                                  req,
-                                                                 mAbstractMainThread);
+                                                                 mEventTarget);
       status->WaitGroupAdd();
 
-      registerTask->Execute()->Then(mAbstractMainThread, __func__,
+      registerTask->Execute()->Then(mEventTarget, __func__,
         [&status] (nsString aResponse) {
           if (!status->IsStopped()) {
             status->Stop(ErrorCode::OK, aResponse);
           }
           status->WaitGroupDone();
         },
         [&status] (ErrorCode aErrorCode) {
           // Ignore the failing error code, as we only want the first success.
@@ -733,17 +733,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();
-  mAbstractMainThread->Dispatch(NS_NewRunnableFunction(
+  mEventTarget->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()));
       }
@@ -758,18 +758,18 @@ U2FRegisterRunnable::Run()
 }
 
 U2FSignRunnable::U2FSignRunnable(const nsAString& aOrigin,
                                  const nsAString& aAppId,
                                  const nsAString& aChallenge,
                                  const Sequence<RegisteredKey>& aRegisteredKeys,
                                  const Sequence<Authenticator>& aAuthenticators,
                                  U2FSignCallback* aCallback,
-                                 AbstractThread* aMainThread)
-  : U2FRunnable(aOrigin, aAppId, aMainThread)
+                                 nsISerialEventTarget* aEventTarget)
+  : U2FRunnable(aOrigin, aAppId, aEventTarget)
   , 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
@@ -886,20 +886,20 @@ U2FSignRunnable::Run()
     // We ignore mTransports, as it is intended to be used for sorting the
     // available devices by preference, but is not an exclusion factor.
 
     for (const Authenticator& token : mAuthenticators) {
       RefPtr<U2FSignTask> signTask = new U2FSignTask(mOrigin, mAppId,
                                                      key.mVersion, token,
                                                      appParam, challengeParam,
                                                      mClientData, keyHandle,
-                                                     mAbstractMainThread);
+                                                     mEventTarget);
       status->WaitGroupAdd();
 
-      signTask->Execute()->Then(mAbstractMainThread, __func__,
+      signTask->Execute()->Then(mEventTarget, __func__,
         [&status] (nsString aResponse) {
           if (!status->IsStopped()) {
             status->Stop(ErrorCode::OK, aResponse);
           }
           status->WaitGroupDone();
         },
         [&status] (ErrorCode aErrorCode) {
           // Ignore the failing error code, as we only want the first success.
@@ -915,17 +915,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();
-  mAbstractMainThread->Dispatch(NS_NewRunnableFunction(
+  mEventTarget->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()));
       }
@@ -1002,17 +1002,17 @@ 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);
+  mEventTarget = doc->EventTargetFor(TaskCategory::Other);
 
   mInitialized = true;
 }
 
 void
 U2F::Register(const nsAString& aAppId,
               const Sequence<RegisterRequest>& aRegisterRequests,
               const Sequence<RegisteredKey>& aRegisteredKeys,
@@ -1028,17 +1028,17 @@ U2F::Register(const nsAString& aAppId,
   }
 
   RefPtr<SharedThreadPool> pool = SharedThreadPool::Get(kPoolName);
   RefPtr<U2FRegisterRunnable> task = new U2FRegisterRunnable(mOrigin, aAppId,
                                                              aRegisterRequests,
                                                              aRegisteredKeys,
                                                              mAuthenticators,
                                                              &aCallback,
-                                                             mAbstractMainThread);
+                                                             mEventTarget);
   pool->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
 }
 
 void
 U2F::Sign(const nsAString& aAppId,
           const nsAString& aChallenge,
           const Sequence<RegisteredKey>& aRegisteredKeys,
           U2FSignCallback& aCallback,
@@ -1051,14 +1051,14 @@ U2F::Sign(const nsAString& aAppId,
     aRv.Throw(NS_ERROR_NOT_AVAILABLE);
     return;
   }
 
   RefPtr<SharedThreadPool> pool = SharedThreadPool::Get(kPoolName);
   RefPtr<U2FSignRunnable> task = new U2FSignRunnable(mOrigin, aAppId, aChallenge,
                                                      aRegisteredKeys,
                                                      mAuthenticators, &aCallback,
-                                                     mAbstractMainThread);
+                                                     mEventTarget);
   pool->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/u2f/U2F.h
+++ b/dom/u2f/U2F.h
@@ -21,20 +21,19 @@
 #include "nsIU2FToken.h"
 #include "nsNSSShutDown.h"
 #include "nsPIDOMWindow.h"
 #include "nsProxyRelease.h"
 #include "nsWrapperCache.h"
 
 #include "U2FAuthenticator.h"
 
-namespace mozilla {
+class nsISerialEventTarget;
 
-class AbstractThread;
-
+namespace mozilla {
 namespace dom {
 
 class U2FRegisterCallback;
 class U2FSignCallback;
 
 // Defined in U2FBinding.h by the U2F.webidl; their use requires a JSContext.
 struct RegisterRequest;
 struct RegisteredKey;
@@ -62,60 +61,60 @@ typedef MozPromise<Authenticator, ErrorC
 
 // 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,
-                       AbstractThread* aMainThread);
+                       nsISerialEventTarget* aEventTarget);
 
   RefPtr<U2FPrepPromise> Execute();
 
 protected:
   virtual ~U2FPrepTask();
 
   Authenticator mAuthenticator;
   MozPromiseHolder<U2FPrepPromise> mPromise;
-  const RefPtr<AbstractThread> mAbstractMainThread;
+  const nsCOMPtr<nsISerialEventTarget> mEventTarget;
 };
 
 // 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 CryptoBuffer& aAppParam,
-                      AbstractThread* aMainThread);
+                      nsISerialEventTarget* aEventTarget);
 
   NS_DECL_NSIRUNNABLE
 private:
   ~U2FIsRegisteredTask();
 
   LocalRegisteredKey mRegisteredKey;
   CryptoBuffer mAppParam;
 };
 
 class U2FTask : public Runnable
 {
 public:
   U2FTask(const nsAString& aOrigin,
           const nsAString& aAppId,
           const Authenticator& aAuthenticator,
-          AbstractThread* aMainThread);
+          nsISerialEventTarget* aEventTarget);
 
   RefPtr<U2FPromise> Execute();
 
   nsString mOrigin;
   nsString mAppId;
   Authenticator mAuthenticator;
-  const RefPtr<AbstractThread> mAbstractMainThread;
+  const nsCOMPtr<nsISerialEventTarget> mEventTarget;
 
 protected:
   virtual ~U2FTask();
 
   MozPromiseHolder<U2FPromise> mPromise;
 };
 
 // Use the provided Authenticator to Register a new scoped credential
@@ -124,17 +123,17 @@ class U2FRegisterTask final : public U2F
 {
 public:
   U2FRegisterTask(const nsAString& aOrigin,
                   const nsAString& aAppId,
                   const Authenticator& aAuthenticator,
                   const CryptoBuffer& aAppParam,
                   const CryptoBuffer& aChallengeParam,
                   const LocalRegisterRequest& aRegisterEntry,
-                  AbstractThread* aMainThread);
+                  nsISerialEventTarget* aEventTarget);
 
   NS_DECL_NSIRUNNABLE
 private:
   ~U2FRegisterTask();
 
   CryptoBuffer mAppParam;
   CryptoBuffer mChallengeParam;
   LocalRegisterRequest mRegisterEntry;
@@ -148,17 +147,17 @@ 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,
-              AbstractThread* aMainThread);
+              nsISerialEventTarget* aEventTarget);
 
   NS_DECL_NSIRUNNABLE
 private:
   ~U2FSignTask();
 
   nsString mVersion;
   CryptoBuffer mAppParam;
   CryptoBuffer mChallengeParam;
@@ -198,43 +197,43 @@ 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,
-              AbstractThread* aMainThread);
+              nsISerialEventTarget* aEventTarget);
 
   // No NSS resources to release.
   virtual
   void virtualDestroyNSSReference() override {};
 
 protected:
   virtual ~U2FRunnable();
   ErrorCode EvaluateAppID();
 
   nsString mOrigin;
   nsString mAppId;
-  const RefPtr<AbstractThread> mAbstractMainThread;
+  const nsCOMPtr<nsISerialEventTarget> mEventTarget;
 };
 
 // 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,
-                      AbstractThread* aMainThread);
+                      nsISerialEventTarget* aEventTarget);
 
   void SendResponse(const RegisterResponse& aResponse);
   void SetTimeout(const int32_t aTimeoutMillis);
 
   NS_DECL_NSIRUNNABLE
 
 private:
   ~U2FRegisterRunnable();
@@ -251,17 +250,17 @@ class U2FSignRunnable : public U2FRunnab
 {
 public:
   U2FSignRunnable(const nsAString& aOrigin,
                   const nsAString& aAppId,
                   const nsAString& aChallenge,
                   const Sequence<RegisteredKey>& aRegisteredKeys,
                   const Sequence<Authenticator>& aAuthenticators,
                   U2FSignCallback* aCallback,
-                  AbstractThread* aMainThread);
+                  nsISerialEventTarget* aEventTarget);
 
   void SendResponse(const SignResponse& aResponse);
   void SetTimeout(const int32_t aTimeoutMillis);
 
   NS_DECL_NSIRUNNABLE
 
 private:
   ~U2FSignRunnable();
@@ -317,17 +316,17 @@ public:
   virtual
   void virtualDestroyNSSReference() override {};
 
 private:
   nsCOMPtr<nsPIDOMWindowInner> mParent;
   nsString mOrigin;
   Sequence<Authenticator> mAuthenticators;
   bool mInitialized;
-  RefPtr<AbstractThread> mAbstractMainThread;
+  nsCOMPtr<nsISerialEventTarget> mEventTarget;
 
   ~U2F();
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_U2F_h
--- a/dom/webauthn/U2FSoftTokenManager.cpp
+++ b/dom/webauthn/U2FSoftTokenManager.cpp
@@ -1,20 +1,20 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 "mozilla/dom/U2FSoftTokenManager.h"
 #include "CryptoBuffer.h"
-#include "mozilla/AbstractThread.h"
 #include "mozilla/Base64.h"
 #include "mozilla/Casting.h"
 #include "nsNSSComponent.h"
+#include "nsThreadUtils.h"
 #include "pk11pub.h"
 #include "prerror.h"
 #include "secerr.h"
 #include "WebCryptoCommon.h"
 
 #define PREF_U2F_NSSTOKEN_COUNTER "security.webauth.softtoken_counter"
 
 namespace mozilla {
@@ -228,17 +228,17 @@ U2FSoftTokenManager::GetOrCreateWrapping
     MOZ_LOG(gNSSTokenLog, LogLevel::Warning,
             ("Failed to set nickname, NSS error #%d", PORT_GetError()));
     return NS_ERROR_FAILURE;
   }
 
   MOZ_LOG(gNSSTokenLog, LogLevel::Debug,
           ("Key stored, nickname set to %s.", mSecretNickname.get()));
 
-  AbstractThread::MainThread()->Dispatch(NS_NewRunnableFunction(
+  GetMainThreadEventTarget()->Dispatch(NS_NewRunnableFunction(
                                            [] () {
                                              MOZ_ASSERT(NS_IsMainThread());
                                              Preferences::SetUint(PREF_U2F_NSSTOKEN_COUNTER, 0);
                                            }));
 
   return NS_OK;
 }
 
@@ -791,17 +791,17 @@ U2FSoftTokenManager::Sign(const nsTArray
   // Increment the counter and turn it into a SECItem
   mCounter += 1;
   ScopedAutoSECItem counterItem(4);
   counterItem.data[0] = (mCounter >> 24) & 0xFF;
   counterItem.data[1] = (mCounter >> 16) & 0xFF;
   counterItem.data[2] = (mCounter >>  8) & 0xFF;
   counterItem.data[3] = (mCounter >>  0) & 0xFF;
   uint32_t counter = mCounter;
-  AbstractThread::MainThread()->Dispatch(NS_NewRunnableFunction(
+  GetMainThreadEventTarget()->Dispatch(NS_NewRunnableFunction(
                                            [counter] () {
                                              MOZ_ASSERT(NS_IsMainThread());
                                              Preferences::SetUint(PREF_U2F_NSSTOKEN_COUNTER, counter);
                                            }));
 
   // Compute the signature
   mozilla::dom::CryptoBuffer signedDataBuf;
   if (NS_WARN_IF(!signedDataBuf.SetCapacity(1 + 4 + (2 * kParamLen), mozilla::fallible))) {
--- a/dom/webauthn/WebAuthnManager.cpp
+++ b/dom/webauthn/WebAuthnManager.cpp
@@ -2,27 +2,27 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 "hasht.h"
 #include "nsNetCID.h"
 #include "nsICryptoHash.h"
-#include "mozilla/AbstractThread.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/dom/AuthenticatorAttestationResponse.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/WebAuthnManager.h"
 #include "mozilla/dom/WebAuthnUtil.h"
 #include "mozilla/dom/PWebAuthnTransaction.h"
 #include "mozilla/dom/WebAuthnTransactionChild.h"
 #include "mozilla/dom/WebCryptoCommon.h"
 #include "mozilla/ipc/PBackgroundChild.h"
 #include "mozilla/ipc/BackgroundChild.h"
+#include "nsThreadUtils.h"
 
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace dom {
 
 /***********************************************************************
  * Statics
@@ -417,17 +417,17 @@ WebAuthnManager::MakeCredential(nsPIDOMW
   nsTArray<WebAuthnExtension> extensions;
 
   WebAuthnTransactionInfo info(rpIdHash,
                                clientDataHash,
                                adjustedTimeout,
                                excludeList,
                                extensions);
   RefPtr<MozPromise<nsresult, nsresult, false>> p = GetOrCreateBackgroundActor();
-  p->Then(AbstractThread::MainThread(), __func__,
+  p->Then(GetMainThreadSerialEventTarget(), __func__,
           []() {
             WebAuthnManager* mgr = WebAuthnManager::Get();
             if (!mgr) {
               return;
             }
             mgr->StartRegister();
           },
           []() {
@@ -583,17 +583,17 @@ WebAuthnManager::GetAssertion(nsPIDOMWin
   nsTArray<WebAuthnExtension> extensions;
 
   WebAuthnTransactionInfo info(rpIdHash,
                                clientDataHash,
                                adjustedTimeout,
                                allowList,
                                extensions);
   RefPtr<MozPromise<nsresult, nsresult, false>> p = GetOrCreateBackgroundActor();
-  p->Then(AbstractThread::MainThread(), __func__,
+  p->Then(GetMainThreadSerialEventTarget(), __func__,
           []() {
             WebAuthnManager* mgr = WebAuthnManager::Get();
             if (!mgr) {
               return;
             }
             mgr->StartSign();
           },
           []() {
--- a/dom/workers/ServiceWorkerUpdaterChild.cpp
+++ b/dom/workers/ServiceWorkerUpdaterChild.cpp
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=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 "ServiceWorkerUpdaterChild.h"
-#include "mozilla/AbstractThread.h"
+#include "nsThreadUtils.h"
 
 namespace mozilla {
 namespace dom {
 namespace workers {
 
 ServiceWorkerUpdaterChild::ServiceWorkerUpdaterChild(GenericPromise* aPromise,
                                                      CancelableRunnable* aSuccessRunnable,
                                                      CancelableRunnable* aFailureRunnable)
@@ -19,17 +19,17 @@ ServiceWorkerUpdaterChild::ServiceWorker
 {
   // TODO: remove the main thread restriction after fixing bug 1364821.
   MOZ_ASSERT(NS_IsMainThread());
 
   MOZ_ASSERT(aPromise);
   MOZ_ASSERT(aSuccessRunnable);
   MOZ_ASSERT(aFailureRunnable);
 
-  aPromise->Then(AbstractThread::MainThread(), __func__,
+  aPromise->Then(GetMainThreadSerialEventTarget(), __func__,
     [this]() {
       mPromiseHolder.Complete();
       Unused << Send__delete__(this);
   }).Track(mPromiseHolder);
 }
 
 mozilla::ipc::IPCResult
 ServiceWorkerUpdaterChild::RecvProceed(const bool& aAllowed)
--- a/editor/composer/nsEditorSpellCheck.cpp
+++ b/editor/composer/nsEditorSpellCheck.cpp
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 sts=2 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 <stdlib.h>                     // for getenv
 
-#include "mozilla/AbstractThread.h"     // for AbstractThread
 #include "mozilla/Attributes.h"         // for final
 #include "mozilla/Preferences.h"        // for Preferences
 #include "mozilla/dom/Element.h"        // for Element
 #include "mozilla/dom/Selection.h"
 #include "mozilla/intl/LocaleService.h" // for retrieving app locale
 #include "mozilla/mozalloc.h"           // for operator delete, etc
 #include "nsAString.h"                  // for nsAString::IsEmpty, etc
 #include "nsComponentManagerUtils.h"    // for do_CreateInstance
@@ -30,16 +29,17 @@
 #include "nsILoadContext.h"
 #include "nsISelection.h"               // for nsISelection
 #include "nsISpellChecker.h"            // for nsISpellChecker, etc
 #include "nsISupportsBase.h"            // for nsISupports
 #include "nsISupportsUtils.h"           // for NS_ADDREF
 #include "nsITextServicesDocument.h"    // for nsITextServicesDocument
 #include "nsITextServicesFilter.h"      // for nsITextServicesFilter
 #include "nsIURI.h"                     // for nsIURI
+#include "nsThreadUtils.h"              // for GetMainThreadSerialEventTarget
 #include "nsVariant.h"                  // for nsIWritableVariant, etc
 #include "nsLiteralString.h"            // for NS_LITERAL_STRING, etc
 #include "nsMemory.h"                   // for nsMemory
 #include "nsRange.h"
 #include "nsReadableUtils.h"            // for ToNewUnicode, EmptyString, etc
 #include "nsServiceManagerUtils.h"      // for do_GetService
 #include "nsString.h"                   // for nsAutoString, nsString, etc
 #include "nsStringFwd.h"                // for nsAFlatString
@@ -837,17 +837,17 @@ nsEditorSpellCheck::DictionaryFetched(Di
     dictName.Assign(aFetcher->mDictionary);
     if (!dictName.IsEmpty()) {
       AutoTArray<nsString, 1> tryDictList;
       BuildDictionaryList(dictName, dictList, DICT_NORMAL_COMPARE, tryDictList);
 
       RefPtr<nsEditorSpellCheck> self = this;
       RefPtr<DictionaryFetcher> fetcher = aFetcher;
       mSpellChecker->SetCurrentDictionaryFromList(tryDictList)->Then(
-        AbstractThread::MainThread(),
+        GetMainThreadSerialEventTarget(),
         __func__,
         [self, fetcher]() {
 #ifdef DEBUG_DICT
           printf("***** Assigned from content preferences |%s|\n",
                  NS_ConvertUTF16toUTF8(dictName).get());
 #endif
           // We take an early exit here, so let's not forget to clear the word
           // list.
@@ -1020,17 +1020,17 @@ nsEditorSpellCheck::SetFallbackDictionar
     printf("***** Trying first of list |%s|\n",
            NS_ConvertUTF16toUTF8(dictList[0]).get());
 #endif
   }
 
   RefPtr<nsEditorSpellCheck> self = this;
   RefPtr<DictionaryFetcher> fetcher = aFetcher;
   mSpellChecker->SetCurrentDictionaryFromList(tryDictList)->Then(
-    AbstractThread::MainThread(),
+    GetMainThreadSerialEventTarget(),
     __func__,
     [self, fetcher]() {
       // If an error was thrown while setting the dictionary, just
       // fail silently so that the spellchecker dialog is allowed to come
       // up. The user can manually reset the language to their choice on
       // the dialog if it is wrong.
       self->DeleteSuggestedWordList();
       self->EndUpdateDictionary();
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -2,17 +2,16 @@
 /* vim: set sw=2 ts=8 et 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/. */
 
 // HttpLog.h should generally be included first
 #include "HttpLog.h"
 
-#include "mozilla/AbstractThread.h"
 #include "mozilla/ipc/FileDescriptorSetParent.h"
 #include "mozilla/ipc/IPCStreamUtils.h"
 #include "mozilla/net/HttpChannelParent.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/net/NeckoParent.h"
 #include "mozilla/IntegerPrintfMacros.h"
@@ -45,16 +44,17 @@
 #include "nsIIPCSerializableInputStream.h"
 #include "nsIPrompt.h"
 #include "nsIRedirectChannelRegistrar.h"
 #include "nsIWindowWatcher.h"
 #include "nsIDocument.h"
 #include "nsStreamUtils.h"
 #include "nsStringStream.h"
 #include "nsIStorageStream.h"
+#include "nsThreadUtils.h"
 #include "nsQueryObject.h"
 #include "nsIURIClassifier.h"
 
 using mozilla::BasePrincipal;
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
 
 namespace mozilla {
@@ -735,17 +735,17 @@ HttpChannelParent::DoAsyncOpen(  const U
   mSuspendAfterSynthesizeResponse = aSuspendAfterSynthesizeResponse;
 
   MOZ_ASSERT(!mBgParent);
   MOZ_ASSERT(mPromise.IsEmpty());
   // Wait for HttpBackgrounChannel to continue the async open procedure.
   ++mAsyncOpenBarrier;
   RefPtr<GenericPromise> promise = WaitForBgParent();
   RefPtr<HttpChannelParent> self = this;
-  promise->Then(AbstractThread::MainThread(), __func__,
+  promise->Then(GetMainThreadSerialEventTarget(), __func__,
                 [self]() {
                   self->mRequest.Complete();
                   self->TryInvokeAsyncOpen(NS_OK);
                 },
                 [self](nsresult aStatus) {
                   self->mRequest.Complete();
                   self->TryInvokeAsyncOpen(aStatus);
                 })
@@ -817,17 +817,17 @@ HttpChannelParent::ConnectChannel(const 
     }
   }
 
   MOZ_ASSERT(!mBgParent);
   MOZ_ASSERT(mPromise.IsEmpty());
   // Waiting for background channel
   RefPtr<GenericPromise> promise = WaitForBgParent();
   RefPtr<HttpChannelParent> self = this;
-  promise->Then(AbstractThread::MainThread(), __func__,
+  promise->Then(GetMainThreadSerialEventTarget(), __func__,
                 [self]() {
                   self->mRequest.Complete();
                 },
                 [self](const nsresult& aResult) {
                   NS_ERROR("failed to establish the background channel");
                   self->mRequest.Complete();
                 })
          ->Track(mRequest);
@@ -1039,17 +1039,17 @@ HttpChannelParent::ContinueVerification(
   }
 
   // ConnectChannel must be received before Redirect2Verify.
   MOZ_ASSERT(!mPromise.IsEmpty());
 
   // Otherwise, wait for the background channel.
   RefPtr<GenericPromise> promise = WaitForBgParent();
   nsCOMPtr<nsIAsyncVerifyRedirectReadyCallback> callback = aCallback;
-  promise->Then(AbstractThread::MainThread(), __func__,
+  promise->Then(GetMainThreadSerialEventTarget(), __func__,
                 [callback]() {
                   callback->ReadyToVerify(NS_OK);
                 },
                 [callback](const nsresult& aResult) {
                   NS_ERROR("failed to establish the background channel");
                   callback->ReadyToVerify(aResult);
                 });
   return NS_OK;
--- a/tools/profiler/gecko/nsProfiler.cpp
+++ b/tools/profiler/gecko/nsProfiler.cpp
@@ -15,21 +15,21 @@
 #include "mozilla/Services.h"
 #include "nsIObserverService.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsILoadContext.h"
 #include "nsIWebNavigation.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "shared-libraries.h"
 #include "js/Value.h"
-#include "mozilla/AbstractThread.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/TypedArray.h"
 #include "nsLocalFile.h"
+#include "nsThreadUtils.h"
 #include "ProfilerParent.h"
 #include "platform.h"
 
 using namespace mozilla;
 
 using dom::AutoJSAPI;
 using dom::Promise;
 using std::string;
@@ -270,17 +270,17 @@ nsProfiler::GetProfileDataAsync(double a
 
   ErrorResult result;
   RefPtr<Promise> promise = Promise::Create(globalObject, result);
   if (NS_WARN_IF(result.Failed())) {
     return result.StealNSResult();
   }
 
   StartGathering(aSinceTime)->Then(
-    AbstractThread::MainThread(), __func__,
+    GetMainThreadSerialEventTarget(), __func__,
     [promise](nsCString aResult) {
       AutoJSAPI jsapi;
       if (NS_WARN_IF(!jsapi.Init(promise->GlobalJSObject()))) {
         // We're really hosed if we can't get a JS context for some reason.
         promise->MaybeReject(NS_ERROR_DOM_UNKNOWN_ERR);
         return;
       }
 
@@ -338,17 +338,17 @@ nsProfiler::GetProfileDataAsArrayBuffer(
 
   ErrorResult result;
   RefPtr<Promise> promise = Promise::Create(globalObject, result);
   if (NS_WARN_IF(result.Failed())) {
     return result.StealNSResult();
   }
 
   StartGathering(aSinceTime)->Then(
-    AbstractThread::MainThread(), __func__,
+    GetMainThreadSerialEventTarget(), __func__,
     [promise](nsCString aResult) {
       AutoJSAPI jsapi;
       if (NS_WARN_IF(!jsapi.Init(promise->GlobalJSObject()))) {
         // We're really hosed if we can't get a JS context for some reason.
         promise->MaybeReject(NS_ERROR_DOM_UNKNOWN_ERR);
         return;
       }
 
@@ -379,17 +379,17 @@ nsProfiler::DumpProfileToFileAsync(const
 
   if (!profiler_is_active()) {
     return NS_ERROR_FAILURE;
   }
 
   nsCString filename(aFilename);
 
   StartGathering(aSinceTime)->Then(
-    AbstractThread::MainThread(), __func__,
+    GetMainThreadSerialEventTarget(), __func__,
     [filename](const nsCString& aResult) {
       nsCOMPtr<nsIFile> file = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
       nsresult rv = file->InitWithNativePath(filename);
       if (NS_FAILED(rv)) {
         MOZ_CRASH();
       }
       nsCOMPtr<nsIFileOutputStream> of =
         do_CreateInstance("@mozilla.org/network/file-output-stream;1");
@@ -600,17 +600,17 @@ nsProfiler::StartGathering(double aSince
   // Keep the array property "processes" and the root object in mWriter open
   // until FinishGathering() is called. As profiles from the other processes
   // come in, they will be inserted and end up in the right spot.
   // FinishGathering() will close the array and the root object.
 
   mPendingProfiles = profiles.Length();
   RefPtr<nsProfiler> self = this;
   for (auto profile : profiles) {
-    profile->Then(AbstractThread::MainThread(), __func__,
+    profile->Then(GetMainThreadSerialEventTarget(), __func__,
       [self](const nsCString& aResult) {
         self->GatheredOOPProfile(aResult);
       },
       [self](ipc::PromiseRejectReason aReason) {
         self->GatheredOOPProfile(NS_LITERAL_CSTRING(""));
       });
   }
   if (!mPendingProfiles) {
--- a/xpcom/threads/AbstractThread.h
+++ b/xpcom/threads/AbstractThread.h
@@ -16,16 +16,21 @@
 #include "nsIThread.h"
 
 namespace mozilla {
 
 class TaskQueue;
 class TaskDispatcher;
 
 /*
+ * NOTE: PLEASE AVOID USE OF AbstractThread OUTSIDE MEDIA CODE WHEN POSSIBLE.
+ * The nsISerialEventTarget interface should be preferred. AbstractThread
+ * has unusual "tail dispatch" semantics that usually are not needed outside
+ * of media code.
+ *
  * We often want to run tasks on a target that guarantees that events will never
  * run in parallel. There are various target types that achieve this - namely
  * nsIThread and TaskQueue. Note that nsIThreadPool (which implements
  * nsIEventTarget) does not have this property, so we do not want to use
  * nsIEventTarget for this purpose. This class encapsulates the specifics of
  * the structures we might use here and provides a consistent interface.
  *
  * At present, the supported AbstractThread implementations are TaskQueue,