Bug 1365098 - Convert NS_GetCurrentThread uses in dom/media (r=cpearce)
authorBill McCloskey <billm@mozilla.com>
Thu, 01 Jun 2017 13:41:18 -0700
changeset 412322 54f926563d9d
parent 412321 a2e617b58eba
child 412323 351a4d47496e
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs1365098
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 1365098 - Convert NS_GetCurrentThread uses in dom/media (r=cpearce) MozReview-Commit-ID: DUPt6xj49zz
dom/media/AbstractMediaDecoder.h
dom/media/GraphDriver.cpp
dom/media/GraphDriver.h
dom/media/MediaManager.cpp
dom/media/MediaRecorder.cpp
dom/media/TextTrackList.cpp
dom/media/VideoUtils.cpp
dom/media/VideoUtils.h
dom/media/gmp/GMPCDMProxy.cpp
dom/media/gmp/GMPContentParent.cpp
dom/media/gmp/GMPContentParent.h
dom/media/gmp/GMPDecryptorParent.cpp
dom/media/gmp/GMPDecryptorParent.h
dom/media/gmp/GMPParent.cpp
dom/media/gmp/GMPParent.h
dom/media/gmp/GMPService.cpp
dom/media/gmp/GMPServiceChild.cpp
dom/media/gmp/GMPServiceParent.cpp
dom/media/gmp/GMPTimerParent.cpp
dom/media/gmp/GMPTimerParent.h
dom/media/gmp/GMPVideoDecoderParent.cpp
dom/media/gmp/GMPVideoEncoderParent.cpp
dom/media/platforms/PDMFactory.cpp
dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp
dom/media/systemservices/CamerasParent.cpp
dom/media/systemservices/CamerasParent.h
dom/media/webaudio/blink/HRTFDatabaseLoader.cpp
dom/media/webspeech/recognition/SpeechStreamListener.cpp
--- a/dom/media/AbstractMediaDecoder.h
+++ b/dom/media/AbstractMediaDecoder.h
@@ -29,21 +29,16 @@ class MediaResource;
 class ReentrantMonitor;
 class VideoFrameContainer;
 class MediaDecoderOwner;
 class CDMProxy;
 class GMPCrashHelper;
 
 typedef nsDataHashtable<nsCStringHashKey, nsCString> MetadataTags;
 
-static inline bool IsCurrentThread(nsIThread* aThread)
-{
-  return NS_GetCurrentThread() == aThread;
-}
-
 /**
  * The AbstractMediaDecoder class describes the public interface for a media decoder
  * and is used by the MediaReader classes.
  */
 class AbstractMediaDecoder : public nsIObserver
 {
 public:
   // Get the current MediaResource being used. Its URI will be returned
--- a/dom/media/GraphDriver.cpp
+++ b/dom/media/GraphDriver.cpp
@@ -219,17 +219,17 @@ ThreadedDriver::Start()
   LOG(LogLevel::Debug,
       ("Starting thread for a SystemClockDriver  %p", mGraphImpl));
   Unused << NS_WARN_IF(mThread);
   if (!mThread) { // Ensure we haven't already started it
     nsCOMPtr<nsIRunnable> event = new MediaStreamGraphInitThreadRunnable(this);
     // Note: mThread may be null during event->Run() if we pass to NewNamedThread!  See AudioInitTask
     nsresult rv = NS_NewNamedThread("MediaStreamGrph", getter_AddRefs(mThread));
     if (NS_SUCCEEDED(rv)) {
-      mThread->Dispatch(event, NS_DISPATCH_NORMAL);
+      mThread->EventTarget()->Dispatch(event.forget(), NS_DISPATCH_NORMAL);
     }
   }
 }
 
 void
 ThreadedDriver::Resume()
 {
   Start();
@@ -245,17 +245,17 @@ ThreadedDriver::Revive()
   // loop again.
   MonitorAutoLock mon(mGraphImpl->GetMonitor());
   if (NextDriver()) {
     NextDriver()->SetGraphTime(this, mIterationStart, mIterationEnd);
     mGraphImpl->SetCurrentDriver(NextDriver());
     NextDriver()->Start();
   } else {
     nsCOMPtr<nsIRunnable> event = new MediaStreamGraphInitThreadRunnable(this);
-    mThread->Dispatch(event, NS_DISPATCH_NORMAL);
+    mThread->EventTarget()->Dispatch(event.forget(), NS_DISPATCH_NORMAL);
   }
 }
 
 void
 ThreadedDriver::RemoveCallback()
 {
 }
 
--- a/dom/media/GraphDriver.h
+++ b/dom/media/GraphDriver.h
@@ -273,17 +273,17 @@ public:
    * of this runs for the entire lifetime of the graph thread.
    */
   void RunThread();
   friend class MediaStreamGraphInitThreadRunnable;
   uint32_t IterationDuration() override {
     return MEDIA_GRAPH_TARGET_PERIOD_MS;
   }
 
-  bool OnThread() override { return !mThread || NS_GetCurrentThread() == mThread; }
+  bool OnThread() override { return !mThread || mThread->EventTarget()->IsOnCurrentThread(); }
 
   /* When the graph wakes up to do an iteration, implementations return the
    * range of time that will be processed.  This is called only once per
    * iteration; it may determine the interval from state in a previous
    * call. */
   virtual MediaTime GetIntervalForIteration() = 0;
 protected:
   nsCOMPtr<nsIThread> mThread;
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -3669,42 +3669,41 @@ SourceListener::NotifyPull(MediaStreamGr
                                           aDesiredTime, mPrincipalHandle);
   }
 }
 
 void
 SourceListener::NotifyEvent(MediaStreamGraph* aGraph,
                             MediaStreamGraphEvent aEvent)
 {
-  nsresult rv;
-  nsCOMPtr<nsIThread> thread;
+  nsCOMPtr<nsIEventTarget> target;
 
   switch (aEvent) {
     case MediaStreamGraphEvent::EVENT_FINISHED:
-      rv = NS_GetMainThread(getter_AddRefs(thread));
-      if (NS_WARN_IF(NS_FAILED(rv))) {
+      target = GetMainThreadEventTarget();
+      if (NS_WARN_IF(!target)) {
         NS_ASSERTION(false, "Mainthread not available; running on current thread");
         // Ensure this really *was* MainThread (NS_GetCurrentThread won't work)
         MOZ_RELEASE_ASSERT(mMainThreadCheck == PR_GetCurrentThread());
         NotifyFinished();
         return;
       }
-      thread->Dispatch(NewRunnableMethod(this, &SourceListener::NotifyFinished),
+      target->Dispatch(NewRunnableMethod(this, &SourceListener::NotifyFinished),
                        NS_DISPATCH_NORMAL);
       break;
     case MediaStreamGraphEvent::EVENT_REMOVED:
-      rv = NS_GetMainThread(getter_AddRefs(thread));
-      if (NS_WARN_IF(NS_FAILED(rv))) {
+      target = GetMainThreadEventTarget();
+      if (NS_WARN_IF(!target)) {
         NS_ASSERTION(false, "Mainthread not available; running on current thread");
         // Ensure this really *was* MainThread (NS_GetCurrentThread won't work)
         MOZ_RELEASE_ASSERT(mMainThreadCheck == PR_GetCurrentThread());
         NotifyRemoved();
         return;
       }
-      thread->Dispatch(NewRunnableMethod(this, &SourceListener::NotifyRemoved),
+      target->Dispatch(NewRunnableMethod(this, &SourceListener::NotifyRemoved),
                        NS_DISPATCH_NORMAL);
       break;
     case MediaStreamGraphEvent::EVENT_HAS_DIRECT_LISTENERS:
       NotifyDirectListeners(aGraph, true);
       break;
     case MediaStreamGraphEvent::EVENT_HAS_NO_DIRECT_LISTENERS:
       NotifyDirectListeners(aGraph, false);
       break;
--- a/dom/media/MediaRecorder.cpp
+++ b/dom/media/MediaRecorder.cpp
@@ -266,17 +266,17 @@ class MediaRecorder::Session: public nsI
     explicit ExtractRunnable(Session* aSession)
       : mSession(aSession) {}
 
     ~ExtractRunnable()
     {}
 
     NS_IMETHOD Run() override
     {
-      MOZ_ASSERT(NS_GetCurrentThread() == mSession->mReadThread);
+      MOZ_ASSERT(mSession->mReadThread->EventTarget()->IsOnCurrentThread());
 
       LOG(LogLevel::Debug, ("Session.ExtractRunnable shutdown = %d", mSession->mEncoder->IsShutdown()));
       if (!mSession->mEncoder->IsShutdown()) {
         mSession->Extract(false);
         if (NS_FAILED(NS_DispatchToCurrentThread(this))) {
           NS_WARNING("Failed to dispatch ExtractRunnable to encoder thread");
         }
       } else {
@@ -604,17 +604,17 @@ private:
     }
   }
   // Pull encoded media data from MediaEncoder and put into EncodedBufferCache.
   // Destroy this session object in the end of this function.
   // If the bool aForceFlush is true, we will force to dispatch a
   // PushBlobRunnable to main thread.
   void Extract(bool aForceFlush)
   {
-    MOZ_ASSERT(NS_GetCurrentThread() == mReadThread);
+    MOZ_ASSERT(mReadThread->EventTarget()->IsOnCurrentThread());
     LOG(LogLevel::Debug, ("Session.Extract %p", this));
 
     PROFILER_LABEL("MediaRecorder", "Session Extract",
       js::ProfileEntry::Category::OTHER);
 
     // Pull encoded media data from MediaEncoder
     nsTArray<nsTArray<uint8_t> > encodedBuf;
     mEncoder->GetEncodedData(&encodedBuf, mMimeType);
@@ -776,17 +776,17 @@ private:
       }
     }
 
     // In case source media stream does not notify track end, receive
     // shutdown notification and stop Read Thread.
     nsContentUtils::RegisterShutdownObserver(this);
 
     nsCOMPtr<nsIRunnable> event = new ExtractRunnable(this);
-    if (NS_FAILED(mReadThread->Dispatch(event, NS_DISPATCH_NORMAL))) {
+    if (NS_FAILED(mReadThread->EventTarget()->Dispatch(event.forget(), NS_DISPATCH_NORMAL))) {
       NS_WARNING("Failed to dispatch ExtractRunnable at beginning");
       LOG(LogLevel::Debug, ("Session.InitEncoder !ReadThread->Dispatch %p", this));
       DoSessionEndTask(NS_ERROR_ABORT);
     }
     // Set mNeedSessionEndTask to false because the
     // ExtractRunnable/DestroyRunnable will take the response to
     // end the session.
     mNeedSessionEndTask = false;
--- a/dom/media/TextTrackList.cpp
+++ b/dom/media/TextTrackList.cpp
@@ -1,14 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/TextTrackList.h"
+
+#include "mozilla/DebugOnly.h"
 #include "mozilla/dom/TextTrackListBinding.h"
 #include "mozilla/dom/TrackEvent.h"
 #include "nsThreadUtils.h"
 #include "nsGlobalWindow.h"
 #include "mozilla/dom/TextTrackCue.h"
 #include "mozilla/dom/TextTrackManager.h"
 
 namespace mozilla {
@@ -195,30 +197,30 @@ TextTrackList::CreateAndDispatchChangeEv
       eventRunner.forget());
   }
 }
 
 void
 TextTrackList::CreateAndDispatchTrackEventRunner(TextTrack* aTrack,
                                                  const nsAString& aEventName)
 {
-  nsCOMPtr<nsIThread> thread;
-  nsresult rv = NS_GetMainThread(getter_AddRefs(thread));
-  if (NS_FAILED(rv)) {
+  DebugOnly<nsresult> rv;
+  nsCOMPtr<nsIEventTarget> target = GetMainThreadEventTarget();
+  if (!target) {
     // If we are not able to get the main-thread object we are shutting down.
     return;
   }
 
   TrackEventInit eventInit;
   eventInit.mTrack.SetValue().SetAsTextTrack() = aTrack;
   RefPtr<TrackEvent> event =
     TrackEvent::Constructor(this, aEventName, eventInit);
 
   // Dispatch the TrackEvent asynchronously.
-  rv = thread->Dispatch(do_AddRef(new TrackEventRunner(this, event)),
+  rv = target->Dispatch(do_AddRef(new TrackEventRunner(this, event)),
                         NS_DISPATCH_NORMAL);
 
   // If we are shutting down this can file but it's still ok.
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Dispatch failed");
 }
 
 HTMLMediaElement*
 TextTrackList::GetMediaElement()
--- a/dom/media/VideoUtils.cpp
+++ b/dom/media/VideoUtils.cpp
@@ -317,18 +317,19 @@ CreateMediaDecodeTaskQueue(const char* a
 }
 
 void
 SimpleTimer::Cancel() {
   if (mTimer) {
 #ifdef DEBUG
     nsCOMPtr<nsIEventTarget> target;
     mTimer->GetTarget(getter_AddRefs(target));
-    nsCOMPtr<nsIThread> thread(do_QueryInterface(target));
-    MOZ_ASSERT(NS_GetCurrentThread() == thread);
+    bool onCurrent;
+    nsresult rv = target->IsOnCurrentThread(&onCurrent);
+    MOZ_ASSERT(NS_SUCCEEDED(rv) && onCurrent);
 #endif
     mTimer->Cancel();
     mTimer = nullptr;
   }
   mTask = nullptr;
 }
 
 NS_IMETHODIMP
@@ -337,38 +338,38 @@ SimpleTimer::Notify(nsITimer *timer) {
   if (mTask) {
     mTask->Run();
     mTask = nullptr;
   }
   return NS_OK;
 }
 
 nsresult
-SimpleTimer::Init(nsIRunnable* aTask, uint32_t aTimeoutMs, nsIThread* aTarget)
+SimpleTimer::Init(nsIRunnable* aTask, uint32_t aTimeoutMs, nsIEventTarget* aTarget)
 {
   nsresult rv;
 
   // Get target thread first, so we don't have to cancel the timer if it fails.
-  nsCOMPtr<nsIThread> target;
+  nsCOMPtr<nsIEventTarget> target;
   if (aTarget) {
     target = aTarget;
   } else {
-    rv = NS_GetMainThread(getter_AddRefs(target));
-    if (NS_FAILED(rv)) {
-      return rv;
+    target = GetMainThreadEventTarget();
+    if (!target) {
+      return NS_ERROR_NOT_AVAILABLE;
     }
   }
 
   nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
   if (NS_FAILED(rv)) {
     return rv;
   }
   // Note: set target before InitWithCallback in case the timer fires before
   // we change the event target.
-  rv = timer->SetTarget(aTarget);
+  rv = timer->SetTarget(target);
   if (NS_FAILED(rv)) {
     timer->Cancel();
     return rv;
   }
   rv = timer->InitWithCallback(this, aTimeoutMs, nsITimer::TYPE_ONE_SHOT);
   if (NS_FAILED(rv)) {
     return rv;
   }
@@ -376,17 +377,17 @@ SimpleTimer::Init(nsIRunnable* aTask, ui
   mTimer = timer.forget();
   mTask = aTask;
   return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS(SimpleTimer, nsITimerCallback)
 
 already_AddRefed<SimpleTimer>
-SimpleTimer::Create(nsIRunnable* aTask, uint32_t aTimeoutMs, nsIThread* aTarget)
+SimpleTimer::Create(nsIRunnable* aTask, uint32_t aTimeoutMs, nsIEventTarget* aTarget)
 {
   RefPtr<SimpleTimer> t(new SimpleTimer());
   if (NS_FAILED(t->Init(aTask, aTimeoutMs, aTarget))) {
     return nullptr;
   }
   return t.forget();
 }
 
--- a/dom/media/VideoUtils.h
+++ b/dom/media/VideoUtils.h
@@ -282,24 +282,24 @@ class SimpleTimer : public nsITimerCallb
 {
 public:
   NS_DECL_ISUPPORTS
 
   // Create a new timer to run aTask after aTimeoutMs milliseconds
   // on thread aTarget. If aTarget is null, task is run on the main thread.
   static already_AddRefed<SimpleTimer> Create(nsIRunnable* aTask,
                                               uint32_t aTimeoutMs,
-                                              nsIThread* aTarget = nullptr);
+                                              nsIEventTarget* aTarget = nullptr);
   void Cancel();
 
   NS_IMETHOD Notify(nsITimer *timer) override;
 
 private:
   virtual ~SimpleTimer() {}
-  nsresult Init(nsIRunnable* aTask, uint32_t aTimeoutMs, nsIThread* aTarget);
+  nsresult Init(nsIRunnable* aTask, uint32_t aTimeoutMs, nsIEventTarget* aTarget);
 
   RefPtr<nsIRunnable> mTask;
   nsCOMPtr<nsITimer> mTimer;
 };
 
 void
 LogToBrowserConsole(const nsAString& aMsg);
 
--- a/dom/media/gmp/GMPCDMProxy.cpp
+++ b/dom/media/gmp/GMPCDMProxy.cpp
@@ -5,17 +5,16 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "GMPCDMProxy.h"
 #include "mozilla/EMEUtils.h"
 #include "mozilla/PodOperations.h"
 
 #include "mozilla/dom/MediaKeys.h"
 #include "mozilla/dom/MediaKeySession.h"
-
 #include "mozIGeckoMediaPluginService.h"
 #include "nsPrintfCString.h"
 #include "nsString.h"
 #include "prenv.h"
 #include "GMPCDMCallbackProxy.h"
 #include "GMPService.h"
 #include "MainThreadUtils.h"
 #include "MediaData.h"
@@ -91,24 +90,24 @@ GMPCDMProxy::Init(PromiseId aPromiseId,
   data->mOrigin = aOrigin;
   data->mTopLevelOrigin = aTopLevelOrigin;
   data->mGMPName = aGMPName;
   data->mCrashHelper = mCrashHelper;
   nsCOMPtr<nsIRunnable> task(
     NewRunnableMethod<UniquePtr<InitData>&&>(this,
                                              &GMPCDMProxy::gmp_Init,
                                              Move(data)));
-  mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
+  mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
 }
 
 #ifdef DEBUG
 bool
 GMPCDMProxy::IsOnOwnerThread()
 {
-  return NS_GetCurrentThread() == mOwnerThread;
+  return mOwnerThread->IsOnCurrentThread();
 }
 #endif
 
 void
 GMPCDMProxy::gmp_InitDone(GMPDecryptorProxy* aCDM, UniquePtr<InitData>&& aData)
 {
   EME_LOG("GMPCDMProxy::gmp_InitDone");
   if (mShutdownCalled) {
@@ -293,17 +292,17 @@ GMPCDMProxy::CreateSession(uint32_t aCre
   data->mPromiseId = aPromiseId;
   data->mInitDataType = NS_ConvertUTF16toUTF8(aInitDataType);
   data->mInitData = Move(aInitData);
 
   nsCOMPtr<nsIRunnable> task(
     NewRunnableMethod<UniquePtr<CreateSessionData>&&>(this,
                                                       &GMPCDMProxy::gmp_CreateSession,
                                                       Move(data)));
-  mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
+  mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
 }
 
 GMPSessionType
 ToGMPSessionType(dom::MediaKeySessionType aSessionType) {
   switch (aSessionType) {
     case dom::MediaKeySessionType::Temporary: return kGMPTemporySession;
     case dom::MediaKeySessionType::Persistent_license: return kGMPPersistentSession;
     default: return kGMPTemporySession;
@@ -336,17 +335,17 @@ GMPCDMProxy::LoadSession(PromiseId aProm
 
   UniquePtr<SessionOpData> data(new SessionOpData());
   data->mPromiseId = aPromiseId;
   data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
   nsCOMPtr<nsIRunnable> task(
     NewRunnableMethod<UniquePtr<SessionOpData>&&>(this,
                                                   &GMPCDMProxy::gmp_LoadSession,
                                                   Move(data)));
-  mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
+  mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
 }
 
 void
 GMPCDMProxy::gmp_LoadSession(UniquePtr<SessionOpData>&& aData)
 {
   MOZ_ASSERT(IsOnOwnerThread());
 
   if (!mCDM) {
@@ -366,17 +365,17 @@ GMPCDMProxy::SetServerCertificate(Promis
 
   UniquePtr<SetServerCertificateData> data(new SetServerCertificateData());
   data->mPromiseId = aPromiseId;
   data->mCert = Move(aCert);
   nsCOMPtr<nsIRunnable> task(
     NewRunnableMethod<UniquePtr<SetServerCertificateData>&&>(this,
                                                              &GMPCDMProxy::gmp_SetServerCertificate,
                                                              Move(data)));
-  mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
+  mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
 }
 
 void
 GMPCDMProxy::gmp_SetServerCertificate(UniquePtr<SetServerCertificateData>&& aData)
 {
   MOZ_ASSERT(IsOnOwnerThread());
   if (!mCDM) {
     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
@@ -398,17 +397,17 @@ GMPCDMProxy::UpdateSession(const nsAStri
   UniquePtr<UpdateSessionData> data(new UpdateSessionData());
   data->mPromiseId = aPromiseId;
   data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
   data->mResponse = Move(aResponse);
   nsCOMPtr<nsIRunnable> task(
     NewRunnableMethod<UniquePtr<UpdateSessionData>&&>(this,
                                                       &GMPCDMProxy::gmp_UpdateSession,
                                                       Move(data)));
-  mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
+  mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
 }
 
 void
 GMPCDMProxy::gmp_UpdateSession(UniquePtr<UpdateSessionData>&& aData)
 {
   MOZ_ASSERT(IsOnOwnerThread());
   if (!mCDM) {
     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
@@ -429,17 +428,17 @@ GMPCDMProxy::CloseSession(const nsAStrin
 
   UniquePtr<SessionOpData> data(new SessionOpData());
   data->mPromiseId = aPromiseId;
   data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
   nsCOMPtr<nsIRunnable> task(
     NewRunnableMethod<UniquePtr<SessionOpData>&&>(this,
                                                   &GMPCDMProxy::gmp_CloseSession,
                                                   Move(data)));
-  mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
+  mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
 }
 
 void
 GMPCDMProxy::gmp_CloseSession(UniquePtr<SessionOpData>&& aData)
 {
   MOZ_ASSERT(IsOnOwnerThread());
   if (!mCDM) {
     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
@@ -458,17 +457,17 @@ GMPCDMProxy::RemoveSession(const nsAStri
 
   UniquePtr<SessionOpData> data(new SessionOpData());
   data->mPromiseId = aPromiseId;
   data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
   nsCOMPtr<nsIRunnable> task(
     NewRunnableMethod<UniquePtr<SessionOpData>&&>(this,
                                                   &GMPCDMProxy::gmp_RemoveSession,
                                                   Move(data)));
-  mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
+  mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
 }
 
 void
 GMPCDMProxy::gmp_RemoveSession(UniquePtr<SessionOpData>&& aData)
 {
   MOZ_ASSERT(IsOnOwnerThread());
   if (!mCDM) {
     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
@@ -481,17 +480,17 @@ GMPCDMProxy::gmp_RemoveSession(UniquePtr
 void
 GMPCDMProxy::Shutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
   mKeys.Clear();
   // Note: This may end up being the last owning reference to the GMPCDMProxy.
   nsCOMPtr<nsIRunnable> task(NewRunnableMethod(this, &GMPCDMProxy::gmp_Shutdown));
   if (mOwnerThread) {
-    mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
+    mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
   }
 }
 
 void
 GMPCDMProxy::gmp_Shutdown()
 {
   MOZ_ASSERT(IsOnOwnerThread());
 
@@ -681,17 +680,17 @@ GMPCDMProxy::Capabilites() {
 RefPtr<DecryptPromise>
 GMPCDMProxy::Decrypt(MediaRawData* aSample)
 {
   RefPtr<DecryptJob> job(new DecryptJob(aSample));
   RefPtr<DecryptPromise> promise(job->Ensure());
 
   nsCOMPtr<nsIRunnable> task(
     NewRunnableMethod<RefPtr<DecryptJob>>(this, &GMPCDMProxy::gmp_Decrypt, job));
-  mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
+  mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
   return promise;
 }
 
 void
 GMPCDMProxy::gmp_Decrypt(RefPtr<DecryptJob> aJob)
 {
   MOZ_ASSERT(IsOnOwnerThread());
 
--- a/dom/media/gmp/GMPContentParent.cpp
+++ b/dom/media/gmp/GMPContentParent.cpp
@@ -69,68 +69,68 @@ GMPContentParent::ActorDestroy(ActorDest
   MOZ_ASSERT(mDecryptors.IsEmpty() && mVideoDecoders.IsEmpty() &&
              mVideoEncoders.IsEmpty() && mChromiumCDMs.IsEmpty());
   NS_DispatchToCurrentThread(new ReleaseGMPContentParent(this));
 }
 
 void
 GMPContentParent::CheckThread()
 {
-  MOZ_ASSERT(mGMPThread == NS_GetCurrentThread());
+  MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
 }
 
 void
 GMPContentParent::ChromiumCDMDestroyed(ChromiumCDMParent* aDecoder)
 {
-  MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
 
   MOZ_ALWAYS_TRUE(mChromiumCDMs.RemoveElement(aDecoder));
   CloseIfUnused();
 }
 
 void
 GMPContentParent::VideoDecoderDestroyed(GMPVideoDecoderParent* aDecoder)
 {
-  MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
 
   // If the constructor fails, we'll get called before it's added
   Unused << NS_WARN_IF(!mVideoDecoders.RemoveElement(aDecoder));
   CloseIfUnused();
 }
 
 void
 GMPContentParent::VideoEncoderDestroyed(GMPVideoEncoderParent* aEncoder)
 {
-  MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
 
   // If the constructor fails, we'll get called before it's added
   Unused << NS_WARN_IF(!mVideoEncoders.RemoveElement(aEncoder));
   CloseIfUnused();
 }
 
 void
 GMPContentParent::DecryptorDestroyed(GMPDecryptorParent* aSession)
 {
-  MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
 
   MOZ_ALWAYS_TRUE(mDecryptors.RemoveElement(aSession));
   CloseIfUnused();
 }
 
 void
 GMPContentParent::AddCloseBlocker()
 {
-  MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
   ++mCloseBlockerCount;
 }
 
 void
 GMPContentParent::RemoveCloseBlocker()
 {
-  MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
   --mCloseBlockerCount;
   CloseIfUnused();
 }
 
 void
 GMPContentParent::CloseIfUnused()
 {
   if (mDecryptors.IsEmpty() && mVideoDecoders.IsEmpty() &&
@@ -162,35 +162,38 @@ GMPContentParent::GetGMPDecryptor(GMPDec
   // It's dropped by calling Close() on the interface.
   NS_ADDREF(dp);
   mDecryptors.AppendElement(dp);
   *aGMPDP = dp;
 
   return NS_OK;
 }
 
-nsCOMPtr<nsIThread>
-GMPContentParent::GMPThread()
+nsCOMPtr<nsISerialEventTarget>
+GMPContentParent::GMPEventTarget()
 {
-  if (!mGMPThread) {
+  if (!mGMPEventTarget) {
     nsCOMPtr<mozIGeckoMediaPluginService> mps = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
     MOZ_ASSERT(mps);
     if (!mps) {
       return nullptr;
     }
-    // Not really safe if we just grab to the mGMPThread, as we don't know
+    // Not really safe if we just grab to the mGMPEventTarget, as we don't know
     // what thread we're running on and other threads may be trying to
     // access this without locks!  However, debug only, and primary failure
     // mode outside of compiler-helped TSAN is a leak.  But better would be
     // to use swap() under a lock.
-    mps->GetThread(getter_AddRefs(mGMPThread));
-    MOZ_ASSERT(mGMPThread);
+    nsCOMPtr<nsIThread> gmpThread;
+    mps->GetThread(getter_AddRefs(gmpThread));
+    MOZ_ASSERT(gmpThread);
+
+    mGMPEventTarget = gmpThread->SerialEventTarget();
   }
 
-  return mGMPThread;
+  return mGMPEventTarget;
 }
 
 already_AddRefed<ChromiumCDMParent>
 GMPContentParent::GetChromiumCDM()
 {
   PChromiumCDMParent* actor = SendPChromiumCDMConstructor();
   if (!actor) {
     return nullptr;
--- a/dom/media/gmp/GMPContentParent.h
+++ b/dom/media/gmp/GMPContentParent.h
@@ -35,17 +35,17 @@ public:
   void VideoEncoderDestroyed(GMPVideoEncoderParent* aEncoder);
 
   nsresult GetGMPDecryptor(GMPDecryptorParent** aGMPKS);
   void DecryptorDestroyed(GMPDecryptorParent* aSession);
 
   already_AddRefed<ChromiumCDMParent> GetChromiumCDM();
   void ChromiumCDMDestroyed(ChromiumCDMParent* aCDM);
 
-  nsCOMPtr<nsIThread> GMPThread();
+  nsCOMPtr<nsISerialEventTarget> GMPEventTarget();
 
   // GMPSharedMem
   void CheckThread() override;
 
   void SetDisplayName(const nsCString& aDisplayName)
   {
     mDisplayName = aDisplayName;
   }
@@ -106,17 +106,17 @@ private:
   {
     PGMPContentParent::Close();
   }
 
   nsTArray<RefPtr<GMPVideoDecoderParent>> mVideoDecoders;
   nsTArray<RefPtr<GMPVideoEncoderParent>> mVideoEncoders;
   nsTArray<RefPtr<GMPDecryptorParent>> mDecryptors;
   nsTArray<RefPtr<ChromiumCDMParent>> mChromiumCDMs;
-  nsCOMPtr<nsIThread> mGMPThread;
+  nsCOMPtr<nsISerialEventTarget> mGMPEventTarget;
   RefPtr<GMPParent> mParent;
   nsCString mDisplayName;
   uint32_t mPluginId;
   uint32_t mCloseBlockerCount = 0;
 };
 
 } // namespace gmp
 } // namespace mozilla
--- a/dom/media/gmp/GMPDecryptorParent.cpp
+++ b/dom/media/gmp/GMPDecryptorParent.cpp
@@ -26,20 +26,20 @@ namespace gmp {
 GMPDecryptorParent::GMPDecryptorParent(GMPContentParent* aPlugin)
   : mIsOpen(false)
   , mShuttingDown(false)
   , mActorDestroyed(false)
   , mPlugin(aPlugin)
   , mPluginId(aPlugin->GetPluginId())
   , mCallback(nullptr)
 #ifdef DEBUG
-  , mGMPThread(aPlugin->GMPThread())
+  , mGMPEventTarget(aPlugin->GMPEventTarget())
 #endif
 {
-  MOZ_ASSERT(mPlugin && mGMPThread);
+  MOZ_ASSERT(mPlugin && mGMPEventTarget);
 }
 
 GMPDecryptorParent::~GMPDecryptorParent()
 {
 }
 
 mozilla::ipc::IPCResult
 GMPDecryptorParent::RecvSetDecryptorId(const uint32_t& aId)
@@ -432,34 +432,34 @@ GMPDecryptorParent::RecvShutdown()
   return IPC_OK();
 }
 
 // Note: may be called via Terminated()
 void
 GMPDecryptorParent::Close()
 {
   LOGD(("GMPDecryptorParent[%p]::Close()", this));
-  MOZ_ASSERT(mGMPThread == NS_GetCurrentThread());
+  MOZ_ASSERT(mGMPEventTarget->IsOnCurrentThread());
 
   // Consumer is done with us; we can shut down.  No more callbacks should
   // be made to mCallback. Note: do this before Shutdown()!
   mCallback = nullptr;
   // Let Shutdown mark us as dead so it knows if we had been alive
 
   // In case this is the last reference
   RefPtr<GMPDecryptorParent> kungfudeathgrip(this);
   this->Release();
   Shutdown();
 }
 
 void
 GMPDecryptorParent::Shutdown()
 {
   LOGD(("GMPDecryptorParent[%p]::Shutdown()", this));
-  MOZ_ASSERT(mGMPThread == NS_GetCurrentThread());
+  MOZ_ASSERT(mGMPEventTarget->IsOnCurrentThread());
 
   if (mShuttingDown) {
     return;
   }
   mShuttingDown = true;
 
   // Notify client we're gone!  Won't occur after Close()
   if (mCallback) {
--- a/dom/media/gmp/GMPDecryptorParent.h
+++ b/dom/media/gmp/GMPDecryptorParent.h
@@ -114,16 +114,16 @@ private:
 
   bool mIsOpen;
   bool mShuttingDown;
   bool mActorDestroyed;
   RefPtr<GMPContentParent> mPlugin;
   uint32_t mPluginId;
   GMPDecryptorProxyCallback* mCallback;
 #ifdef DEBUG
-  nsCOMPtr<nsIThread> const mGMPThread;
+  nsCOMPtr<nsISerialEventTarget> const mGMPEventTarget;
 #endif
 };
 
 } // namespace gmp
 } // namespace mozilla
 
 #endif // GMPDecryptorChild_h_
--- a/dom/media/gmp/GMPParent.cpp
+++ b/dom/media/gmp/GMPParent.cpp
@@ -81,17 +81,17 @@ GMPParent::~GMPParent()
 {
   LOGD("GMPParent dtor id=%u", mPluginId);
   MOZ_ASSERT(!mProcess);
 }
 
 nsresult
 GMPParent::CloneFrom(const GMPParent* aOther)
 {
-  MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
   MOZ_ASSERT(aOther->mDirectory && aOther->mService, "null plugin directory");
 
   mService = aOther->mService;
   mDirectory = aOther->mDirectory;
   mName = aOther->mName;
   mVersion = aOther->mVersion;
   mDescription = aOther->mDescription;
   mDisplayName = aOther->mDisplayName;
@@ -105,17 +105,17 @@ GMPParent::CloneFrom(const GMPParent* aO
   return NS_OK;
 }
 
 RefPtr<GenericPromise>
 GMPParent::Init(GeckoMediaPluginServiceParent* aService, nsIFile* aPluginDir)
 {
   MOZ_ASSERT(aPluginDir);
   MOZ_ASSERT(aService);
-  MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
 
   mService = aService;
   mDirectory = aPluginDir;
 
   // aPluginDir is <profile-dir>/<gmp-plugin-id>/<version>
   // where <gmp-plugin-id> should be gmp-gmpopenh264
   nsCOMPtr<nsIFile> parent;
   nsresult rv = aPluginDir->GetParent(getter_AddRefs(parent));
@@ -142,17 +142,17 @@ GMPParent::Crash()
     Unused << SendCrashPluginNow();
   }
 }
 
 nsresult
 GMPParent::LoadProcess()
 {
   MOZ_ASSERT(mDirectory, "Plugin directory cannot be NULL!");
-  MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
   MOZ_ASSERT(mState == GMPStateNotLoaded);
 
   nsAutoString path;
   if (NS_FAILED(mDirectory->GetPath(path))) {
     return NS_ERROR_FAILURE;
   }
   LOGD("%s: for %s", __FUNCTION__, NS_ConvertUTF16toUTF8(path).get());
 
@@ -217,17 +217,17 @@ GMPParent::RecvPGMPContentChildDestroyed
     CloseIfUnused();
   }
   return IPC_OK();
 }
 
 void
 GMPParent::CloseIfUnused()
 {
-  MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
   LOGD("%s", __FUNCTION__);
 
   if ((mDeleteProcessOnlyOnUnload ||
        mState == GMPStateLoaded ||
        mState == GMPStateUnloading) &&
       !IsUsed()) {
     // Ensure all timers are killed.
     for (uint32_t i = mTimers.Length(); i > 0; i--) {
@@ -242,17 +242,17 @@ GMPParent::CloseIfUnused()
     Shutdown();
   }
 }
 
 void
 GMPParent::CloseActive(bool aDieWhenUnloaded)
 {
   LOGD("%s: state %d", __FUNCTION__, mState);
-  MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
 
   if (aDieWhenUnloaded) {
     mDeleteProcessOnlyOnUnload = true; // don't allow this to go back...
   }
   if (mState == GMPStateLoaded) {
     mState = GMPStateUnloading;
   }
   if (mState != GMPStateNotLoaded && IsUsed()) {
@@ -273,17 +273,17 @@ GMPParent::IsMarkedForDeletion()
 {
   return mIsBlockingDeletion;
 }
 
 void
 GMPParent::Shutdown()
 {
   LOGD("%s", __FUNCTION__);
-  MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
 
   if (mAbnormalShutdownInProgress) {
     return;
   }
 
   MOZ_ASSERT(!IsUsed());
   if (mState == GMPStateNotLoaded || mState == GMPStateClosing) {
     return;
@@ -319,30 +319,30 @@ public:
   }
   nsString mNodeId;
 };
 
 void
 GMPParent::ChildTerminated()
 {
   RefPtr<GMPParent> self(this);
-  nsCOMPtr<nsIThread> gmpThread = GMPThread();
+  nsCOMPtr<nsISerialEventTarget> gmpEventTarget = GMPEventTarget();
 
-  if (!gmpThread) {
+  if (!gmpEventTarget) {
     // Bug 1163239 - this can happen on shutdown.
     // PluginTerminated removes the GMP from the GMPService.
     // On shutdown we can have this case where it is already been
     // removed so there is no harm in not trying to remove it again.
-    LOGD("%s::%s: GMPThread() returned nullptr.", __CLASS__, __FUNCTION__);
+    LOGD("%s::%s: GMPEventTarget() returned nullptr.", __CLASS__, __FUNCTION__);
   } else {
-    gmpThread->Dispatch(NewRunnableMethod<RefPtr<GMPParent>>(
-                         mService,
-                         &GeckoMediaPluginServiceParent::PluginTerminated,
-                         self),
-                         NS_DISPATCH_NORMAL);
+    gmpEventTarget->Dispatch(NewRunnableMethod<RefPtr<GMPParent>>(
+                               mService,
+                               &GeckoMediaPluginServiceParent::PluginTerminated,
+                               self),
+                             NS_DISPATCH_NORMAL);
   }
 }
 
 void
 GMPParent::DeleteProcess()
 {
   LOGD("%s", __FUNCTION__);
 
@@ -368,30 +368,30 @@ GMPParent::DeleteProcess()
 }
 
 GMPState
 GMPParent::State() const
 {
   return mState;
 }
 
-nsCOMPtr<nsIThread>
-GMPParent::GMPThread()
+nsCOMPtr<nsISerialEventTarget>
+GMPParent::GMPEventTarget()
 {
   nsCOMPtr<mozIGeckoMediaPluginService> mps =
     do_GetService("@mozilla.org/gecko-media-plugin-service;1");
   MOZ_ASSERT(mps);
   if (!mps) {
     return nullptr;
   }
   // Note: GeckoMediaPluginService::GetThread() is threadsafe, and returns
   // nullptr if the GeckoMediaPluginService has started shutdown.
   nsCOMPtr<nsIThread> gmpThread;
   mps->GetThread(getter_AddRefs(gmpThread));
-  return gmpThread;
+  return gmpThread ? gmpThread->SerialEventTarget() : nullptr;
 }
 
 /* static */
 bool
 GMPCapability::Supports(const nsTArray<GMPCapability>& aCapabilities,
                         const nsCString& aAPI,
                         const nsTArray<nsCString>& aTags)
 {
@@ -579,18 +579,18 @@ mozilla::ipc::IPCResult
 GMPParent::RecvPGMPTimerConstructor(PGMPTimerParent* actor)
 {
   return IPC_OK();
 }
 
 PGMPTimerParent*
 GMPParent::AllocPGMPTimerParent()
 {
-  nsCOMPtr<nsIThread> thread = GMPThread();
-  GMPTimerParent* p = new GMPTimerParent(thread);
+  nsCOMPtr<nsISerialEventTarget> target = GMPEventTarget();
+  GMPTimerParent* p = new GMPTimerParent(target);
   mTimers.AppendElement(p); // Released in DeallocPGMPTimerParent, or on shutdown.
   return p;
 }
 
 bool
 GMPParent::DeallocPGMPTimerParent(PGMPTimerParent* aActor)
 {
   GMPTimerParent* p = static_cast<GMPTimerParent*>(aActor);
@@ -886,17 +886,17 @@ GMPParent::ResolveGetContentParentPromis
   for (auto& holder : promises) {
     holder->Resolve(blocker, __func__);
   }
 }
 
 bool
 GMPParent::OpenPGMPContent()
 {
-  MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
   MOZ_ASSERT(!mGMPContentParent);
 
   Endpoint<PGMPContentParent> parent;
   Endpoint<PGMPContentChild> child;
   if (NS_FAILED(PGMPContent::CreateEndpoints(base::GetCurrentProcId(),
                                              OtherPid(), &parent, &child))) {
     return false;
   }
@@ -926,17 +926,17 @@ GMPParent::RejectGetContentParentPromise
     holder->Reject(NS_ERROR_FAILURE, __func__);
   }
 }
 
 void
 GMPParent::GetGMPContentParent(UniquePtr<MozPromiseHolder<GetGMPContentParentPromise>>&& aPromiseHolder)
 {
   LOGD("%s %p", __FUNCTION__, this);
-  MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
 
   if (mGMPContentParent) {
     RefPtr<GMPContentParent::CloseBlocker> blocker(new GMPContentParent::CloseBlocker(mGMPContentParent));
     aPromiseHolder->Resolve(blocker, __func__);
   } else {
     mGetContentParentPromises.AppendElement(Move(aPromiseHolder));
     // If we don't have a GMPContentParent and we try to get one for the first
     // time (mGetContentParentPromises.Length() == 1) then call PGMPContent::Open. If more
--- a/dom/media/gmp/GMPParent.h
+++ b/dom/media/gmp/GMPParent.h
@@ -17,18 +17,16 @@
 #include "nsCOMPtr.h"
 #include "nscore.h"
 #include "nsISupports.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsIFile.h"
 #include "mozilla/MozPromise.h"
 
-class nsIThread;
-
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #endif
 
 namespace mozilla {
 namespace ipc {
 class CrashReporterHost;
 } // namespace ipc
@@ -95,17 +93,17 @@ public:
 
   // Called by the GMPService to forcibly close active de/encoders at shutdown
   void Shutdown();
 
   // This must not be called while we're in the middle of abnormal ActorDestroy
   void DeleteProcess();
 
   GMPState State() const;
-  nsCOMPtr<nsIThread> GMPThread();
+  nsCOMPtr<nsISerialEventTarget> GMPEventTarget();
 
   // A GMP can either be a single instance shared across all NodeIds (like
   // in the OpenH264 case), or we can require a new plugin instance for every
   // NodeIds running the plugin (as in the EME plugin case).
   //
   // A NodeId is a hash of the ($urlBarOrigin, $ownerDocOrigin) pair.
   //
   // Plugins are associated with an NodeIds by calling SetNodeId() before
--- a/dom/media/gmp/GMPService.cpp
+++ b/dom/media/gmp/GMPService.cpp
@@ -229,17 +229,17 @@ GeckoMediaPluginService::Init()
   return GetThread(getter_AddRefs(thread));
 }
 
 RefPtr<GetCDMParentPromise>
 GeckoMediaPluginService::GetCDM(const NodeId& aNodeId,
                                 nsTArray<nsCString> aTags,
                                 GMPCrashHelper* aHelper)
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
 
   if (mShuttingDownOnGMPThread || aTags.IsEmpty()) {
     return GetCDMParentPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
   }
 
   typedef MozPromiseHolder<GetCDMParentPromise> PromiseHolder;
   PromiseHolder* rawHolder(new PromiseHolder());
   RefPtr<GetCDMParentPromise> promise = rawHolder->Ensure(__func__);
@@ -349,17 +349,17 @@ GeckoMediaPluginService::GetAbstractGMPT
 
 NS_IMETHODIMP
 GeckoMediaPluginService::GetDecryptingGMPVideoDecoder(GMPCrashHelper* aHelper,
                                                       nsTArray<nsCString>* aTags,
                                                       const nsACString& aNodeId,
                                                       UniquePtr<GetGMPVideoDecoderCallback>&& aCallback,
                                                       uint32_t aDecryptorId)
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
   NS_ENSURE_ARG(aTags && aTags->Length() > 0);
   NS_ENSURE_ARG(aCallback);
 
   if (mShuttingDownOnGMPThread) {
     return NS_ERROR_FAILURE;
   }
 
   GetGMPVideoDecoderCallback* rawCallback = aCallback.release();
@@ -387,17 +387,17 @@ GeckoMediaPluginService::GetDecryptingGM
 }
 
 NS_IMETHODIMP
 GeckoMediaPluginService::GetGMPVideoEncoder(GMPCrashHelper* aHelper,
                                             nsTArray<nsCString>* aTags,
                                             const nsACString& aNodeId,
                                             UniquePtr<GetGMPVideoEncoderCallback>&& aCallback)
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
   NS_ENSURE_ARG(aTags && aTags->Length() > 0);
   NS_ENSURE_ARG(aCallback);
 
   if (mShuttingDownOnGMPThread) {
     return NS_ERROR_FAILURE;
   }
 
   GetGMPVideoEncoderCallback* rawCallback = aCallback.release();
@@ -433,17 +433,17 @@ GeckoMediaPluginService::GetGMPDecryptor
 #if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
   if (!SandboxInfo::Get().CanSandboxMedia()) {
     NS_WARNING("GeckoMediaPluginService::GetGMPDecryptor: "
                "EME decryption not available without sandboxing support.");
     return NS_ERROR_NOT_AVAILABLE;
   }
 #endif
 
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
   NS_ENSURE_ARG(aTags && aTags->Length() > 0);
   NS_ENSURE_ARG(aCallback);
 
   if (mShuttingDownOnGMPThread) {
     return NS_ERROR_FAILURE;
   }
 
   GetGMPDecryptorCallback* rawCallback = aCallback.release();
--- a/dom/media/gmp/GMPServiceChild.cpp
+++ b/dom/media/gmp/GMPServiceChild.cpp
@@ -53,17 +53,17 @@ GeckoMediaPluginServiceChild::GetSinglet
 }
 
 RefPtr<GetGMPContentParentPromise>
 GeckoMediaPluginServiceChild::GetContentParent(GMPCrashHelper* aHelper,
                                                const nsACString& aNodeIdString,
                                                const nsCString& aAPI,
                                                const nsTArray<nsCString>& aTags)
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
 
   MozPromiseHolder<GetGMPContentParentPromise>* rawHolder = new MozPromiseHolder<GetGMPContentParentPromise>();
   RefPtr<GetGMPContentParentPromise> promise = rawHolder->Ensure(__func__);
   RefPtr<AbstractThread> thread(GetAbstractGMPThread());
 
   nsCString nodeIdString(aNodeIdString);
   nsCString api(aAPI);
   nsTArray<nsCString> tags(aTags);
@@ -128,17 +128,17 @@ GeckoMediaPluginServiceChild::GetContent
 }
 
 RefPtr<GetGMPContentParentPromise>
 GeckoMediaPluginServiceChild::GetContentParent(GMPCrashHelper* aHelper,
                                                const NodeId& aNodeId,
                                                const nsCString& aAPI,
                                                const nsTArray<nsCString>& aTags)
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
 
   MozPromiseHolder<GetGMPContentParentPromise>* rawHolder =
     new MozPromiseHolder<GetGMPContentParentPromise>();
   RefPtr<GetGMPContentParentPromise> promise = rawHolder->Ensure(__func__);
   RefPtr<AbstractThread> thread(GetAbstractGMPThread());
 
   NodeIdData nodeId(aNodeId.mOrigin, aNodeId.mTopLevelOrigin, aNodeId.mGMPName);
   nsCString api(aAPI);
@@ -291,17 +291,17 @@ GeckoMediaPluginServiceChild::UpdateGMPC
   if (obsService) {
     obsService->NotifyObservers(nullptr, "gmp-changed", nullptr);
   }
 }
 
 void
 GeckoMediaPluginServiceChild::BeginShutdown()
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
   mShuttingDownOnGMPThread = true;
 }
 
 NS_IMETHODIMP
 GeckoMediaPluginServiceChild::HasPluginForAPI(const nsACString& aAPI,
                                               nsTArray<nsCString>* aTags,
                                               bool* aHasPlugin)
 {
@@ -324,17 +324,17 @@ GeckoMediaPluginServiceChild::HasPluginF
 }
 
 NS_IMETHODIMP
 GeckoMediaPluginServiceChild::GetNodeId(const nsAString& aOrigin,
                                         const nsAString& aTopLevelOrigin,
                                         const nsAString& aGMPName,
                                         UniquePtr<GetNodeIdCallback>&& aCallback)
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
 
   GetNodeIdCallback* rawCallback = aCallback.release();
   RefPtr<AbstractThread> thread(GetAbstractGMPThread());
   nsString origin(aOrigin);
   nsString topLevelOrigin(aTopLevelOrigin);
   nsString gmpName(aGMPName);
   GetServiceChild()->Then(thread, __func__,
     [rawCallback, origin, topLevelOrigin, gmpName](GMPServiceChild* child) {
@@ -373,17 +373,17 @@ GeckoMediaPluginServiceChild::Observe(ns
   }
 
   return NS_OK;
 }
 
 RefPtr<GeckoMediaPluginServiceChild::GetServiceChildPromise>
 GeckoMediaPluginServiceChild::GetServiceChild()
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
 
   if (!mServiceChild) {
     if (mShuttingDownOnGMPThread) {
       // We have begun shutdown. Don't allow a new connection to the main
       // process to be instantiated. This also prevents new plugins being
       // instantiated.
       return GetServiceChildPromise::CreateAndReject(NS_ERROR_FAILURE,
                                                      __func__);
@@ -402,31 +402,31 @@ GeckoMediaPluginServiceChild::GetService
     return promise;
   }
   return GetServiceChildPromise::CreateAndResolve(mServiceChild.get(), __func__);
 }
 
 void
 GeckoMediaPluginServiceChild::SetServiceChild(UniquePtr<GMPServiceChild>&& aServiceChild)
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
 
   mServiceChild = Move(aServiceChild);
 
   nsTArray<MozPromiseHolder<GetServiceChildPromise>> holders;
   holders.SwapElements(mGetServiceChildPromises);
   for (MozPromiseHolder<GetServiceChildPromise>& holder : holders) {
     holder.Resolve(mServiceChild.get(), __func__);
   }
 }
 
 void
 GeckoMediaPluginServiceChild::RemoveGMPContentParent(GMPContentParent* aGMPContentParent)
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
 
   if (mServiceChild) {
     mServiceChild->RemoveGMPContentParent(aGMPContentParent);
     if (mShuttingDownOnGMPThread && !mServiceChild->HaveContentParents()) {
       mServiceChild->Close();
       mServiceChild = nullptr;
     }
   }
--- a/dom/media/gmp/GMPServiceParent.cpp
+++ b/dom/media/gmp/GMPServiceParent.cpp
@@ -398,17 +398,17 @@ GeckoMediaPluginServiceParent::GetConten
 
 RefPtr<GetGMPContentParentPromise>
 GeckoMediaPluginServiceParent::GetContentParent(
   GMPCrashHelper* aHelper,
   const NodeId& aNodeId,
   const nsCString& aAPI,
   const nsTArray<nsCString>& aTags)
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
 
   nsCString nodeIdString;
   nsresult rv = GetNodeId(
     aNodeId.mOrigin, aNodeId.mTopLevelOrigin, aNodeId.mGMPName, nodeIdString);
   if (NS_FAILED(rv)) {
     return GetGMPContentParentPromise::CreateAndReject(NS_ERROR_FAILURE,
                                                        __func__);
   }
@@ -447,24 +447,24 @@ GeckoMediaPluginServiceParent::NotifySyn
 {
   MOZ_ASSERT(NS_IsMainThread());
   mWaitingForPluginsSyncShutdown = false;
 }
 
 bool
 GeckoMediaPluginServiceParent::IsShuttingDown()
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
   return mShuttingDownOnGMPThread;
 }
 
 void
 GeckoMediaPluginServiceParent::UnloadPlugins()
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
   MOZ_ASSERT(!mShuttingDownOnGMPThread);
   mShuttingDownOnGMPThread = true;
 
   nsTArray<RefPtr<GMPParent>> plugins;
   {
     MutexAutoLock lock(mMutex);
     // Move all plugins references to a local array. This way mMutex won't be
     // locked when calling CloseActive (to avoid inter-locking).
@@ -494,28 +494,28 @@ GeckoMediaPluginServiceParent::UnloadPlu
     this, &GeckoMediaPluginServiceParent::NotifySyncShutdownComplete);
   mMainThread->Dispatch(task.forget());
 }
 
 void
 GeckoMediaPluginServiceParent::CrashPlugins()
 {
   LOGD(("%s::%s", __CLASS__, __FUNCTION__));
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
 
   MutexAutoLock lock(mMutex);
   for (size_t i = 0; i < mPlugins.Length(); i++) {
     mPlugins[i]->Crash();
   }
 }
 
 RefPtr<GenericPromise::AllPromiseType>
 GeckoMediaPluginServiceParent::LoadFromEnvironment()
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
   RefPtr<AbstractThread> thread(GetAbstractGMPThread());
   if (!thread) {
     return GenericPromise::AllPromiseType::CreateAndReject(NS_ERROR_FAILURE, __func__);
   }
 
   const char* env = PR_GetEnv("MOZ_GMP_PATH");
   if (!env || !*env) {
     return GenericPromise::AllPromiseType::CreateAndResolve(true, __func__);
@@ -755,17 +755,17 @@ GeckoMediaPluginServiceParent::FindPlugi
   return nullptr;
 }
 
 already_AddRefed<GMPParent>
 GeckoMediaPluginServiceParent::SelectPluginForAPI(const nsACString& aNodeId,
                                                   const nsCString& aAPI,
                                                   const nsTArray<nsCString>& aTags)
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread,
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread(),
              "Can't clone GMP plugins on non-GMP threads.");
 
   GMPParent* gmpToClone = nullptr;
   {
     MutexAutoLock lock(mMutex);
     size_t index = 0;
     RefPtr<GMPParent> gmp;
     while ((gmp = FindPluginForAPIFrom(index, aAPI, aTags, &index))) {
@@ -847,17 +847,17 @@ GeckoMediaPluginServiceParent::AddOnGMPT
 #ifdef XP_WIN
   // On Windows our various test harnesses often pass paths with UNIX dir
   // separators, or a mix of dir separators. NS_NewLocalFile() can't handle
   // that, so fixup to match the platform's expected format. This makes us
   // more robust in the face of bad input and test harnesses changing...
   std::replace(aDirectory.BeginWriting(), aDirectory.EndWriting(), '/', '\\');
 #endif
 
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
   nsCString dir = NS_ConvertUTF16toUTF8(aDirectory);
   RefPtr<AbstractThread> thread(GetAbstractGMPThread());
   if (!thread) {
     LOGD(("%s::%s: %s No GMP Thread", __CLASS__, __FUNCTION__, dir.get()));
     return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
   }
   LOGD(("%s::%s: %s", __CLASS__, __FUNCTION__, dir.get()));
 
@@ -891,17 +891,17 @@ GeckoMediaPluginServiceParent::AddOnGMPT
     });
 }
 
 void
 GeckoMediaPluginServiceParent::RemoveOnGMPThread(const nsAString& aDirectory,
                                                  const bool aDeleteFromDisk,
                                                  const bool aCanDefer)
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
   LOGD(("%s::%s: %s", __CLASS__, __FUNCTION__, NS_LossyConvertUTF16toASCII(aDirectory).get()));
 
   nsCOMPtr<nsIFile> directory;
   nsresult rv = NS_NewLocalFile(aDirectory, false, getter_AddRefs(directory));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
@@ -966,17 +966,17 @@ static void Dummy(RefPtr<GMPParent>& aOn
 {
   // exists solely to do nothing and let the Runnable kill the GMPParent
   // when done.
 }
 
 void
 GeckoMediaPluginServiceParent::PluginTerminated(const RefPtr<GMPParent>& aPlugin)
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
 
   if (aPlugin->IsMarkedForDeletion()) {
     nsCString path8;
     RefPtr<nsIFile> dir = aPlugin->GetDirectory();
     nsresult rv = dir->GetNativePath(path8);
     NS_ENSURE_SUCCESS_VOID(rv);
 
     nsString path = NS_ConvertUTF8toUTF16(path8);
@@ -984,17 +984,17 @@ GeckoMediaPluginServiceParent::PluginTer
       RemoveOnGMPThread(path, true /* delete */, true /* can defer */);
     }
   }
 }
 
 void
 GeckoMediaPluginServiceParent::ReAddOnGMPThread(const RefPtr<GMPParent>& aOld)
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
   LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, (void*) aOld));
 
   RefPtr<GMPParent> gmp;
   if (!mShuttingDownOnGMPThread) {
     // We're not shutting down, so replace the old plugin in the list with a
     // clone which is in a pristine state. Note: We place the plugin in
     // the same slot in the array as a hack to ensure if we re-request with
     // the same capabilities we get an instance of the same plugin.
@@ -1112,33 +1112,33 @@ GeckoMediaPluginServiceParent::GetMemory
   }
   return s.forget();
 }
 
 NS_IMETHODIMP
 GeckoMediaPluginServiceParent::IsPersistentStorageAllowed(const nsACString& aNodeId,
                                                           bool* aOutAllowed)
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
   NS_ENSURE_ARG(aOutAllowed);
   // We disallow persistent storage for the NodeId used for shared GMP
   // decoding, to prevent GMP decoding being used to track what a user
   // watches somehow.
   *aOutAllowed = !aNodeId.Equals(SHARED_GMP_DECODING_NODE_ID) &&
                  mPersistentStorageAllowed.Get(aNodeId);
   return NS_OK;
 }
 
 nsresult
 GeckoMediaPluginServiceParent::GetNodeId(const nsAString& aOrigin,
                                          const nsAString& aTopLevelOrigin,
                                          const nsAString& aGMPName,
                                          nsACString& aOutId)
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
   LOGD(("%s::%s: (%s, %s)", __CLASS__, __FUNCTION__,
        NS_ConvertUTF16toUTF8(aOrigin).get(),
        NS_ConvertUTF16toUTF8(aTopLevelOrigin).get()));
 
   nsresult rv;
 
   if (aOrigin.EqualsLiteral("null") ||
       aOrigin.IsEmpty() ||
@@ -1485,17 +1485,17 @@ GeckoMediaPluginServiceParent::ClearNode
     }
   }
 }
 
 void
 GeckoMediaPluginServiceParent::ForgetThisSiteOnGMPThread(const nsACString& aSite,
                                                          const mozilla::OriginAttributesPattern& aPattern)
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
   LOGD(("%s::%s: origin=%s", __CLASS__, __FUNCTION__, aSite.Data()));
 
   struct OriginFilter : public DirectoryFilter {
     explicit OriginFilter(const nsACString& aSite,
                           const mozilla::OriginAttributesPattern& aPattern)
     : mSite(aSite)
     , mPattern(aPattern)
     { }
@@ -1508,17 +1508,17 @@ GeckoMediaPluginServiceParent::ForgetThi
   } filter(aSite, aPattern);
 
   ClearNodeIdAndPlugin(filter);
 }
 
 void
 GeckoMediaPluginServiceParent::ClearRecentHistoryOnGMPThread(PRTime aSince)
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
   LOGD(("%s::%s: since=%" PRId64, __CLASS__, __FUNCTION__, (int64_t)aSince));
 
   struct MTimeFilter : public DirectoryFilter {
     explicit MTimeFilter(PRTime aSince)
       : mSince(aSince) {}
 
     // Return true if any files under aPath is modified after |mSince|.
     bool IsModifiedAfter(nsIFile* aPath) {
@@ -1668,17 +1668,17 @@ GeckoMediaPluginServiceParent::ServiceUs
     nsresult rv = GetShutdownBarrier()->RemoveBlocker(this);
     MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
   }
 }
 
 void
 GeckoMediaPluginServiceParent::ClearStorage()
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
   LOGD(("%s::%s", __CLASS__, __FUNCTION__));
 
   // Kill plugins with valid nodeIDs.
   KillPlugins(mPlugins, mMutex, &IsNodeIdValid);
 
   nsCOMPtr<nsIFile> path; // $profileDir/gmp/$platform/
   nsresult rv = GetStorageDir(getter_AddRefs(path));
   if (NS_WARN_IF(NS_FAILED(rv))) {
--- a/dom/media/gmp/GMPTimerParent.cpp
+++ b/dom/media/gmp/GMPTimerParent.cpp
@@ -21,41 +21,41 @@ extern LogModule* GetGMPLog();
 
 #ifdef __CLASS__
 #undef __CLASS__
 #endif
 #define __CLASS__ "GMPParent"
 
 namespace gmp {
 
-GMPTimerParent::GMPTimerParent(nsIThread* aGMPThread)
-  : mGMPThread(aGMPThread)
+GMPTimerParent::GMPTimerParent(nsISerialEventTarget* aGMPEventTarget)
+  : mGMPEventTarget(aGMPEventTarget)
   , mIsOpen(true)
 {
 }
 
 mozilla::ipc::IPCResult
 GMPTimerParent::RecvSetTimer(const uint32_t& aTimerId,
                              const uint32_t& aTimeoutMs)
 {
   LOGD(("%s::%s: %p mIsOpen=%d", __CLASS__, __FUNCTION__, this, mIsOpen));
 
-  MOZ_ASSERT(mGMPThread == NS_GetCurrentThread());
+  MOZ_ASSERT(mGMPEventTarget->IsOnCurrentThread());
 
   if (!mIsOpen) {
     return IPC_OK();
   }
 
   nsresult rv;
   nsAutoPtr<Context> ctx(new Context());
   ctx->mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
   NS_ENSURE_SUCCESS(rv, IPC_OK());
 
   ctx->mId = aTimerId;
-  rv = ctx->mTimer->SetTarget(mGMPThread);
+  rv = ctx->mTimer->SetTarget(mGMPEventTarget);
   NS_ENSURE_SUCCESS(rv, IPC_OK());
   ctx->mParent = this;
 
   rv = ctx->mTimer->InitWithFuncCallback(&GMPTimerParent::GMPTimerExpired,
                                           ctx,
                                           aTimeoutMs,
                                           nsITimer::TYPE_ONE_SHOT);
   NS_ENSURE_SUCCESS(rv, IPC_OK());
@@ -65,17 +65,17 @@ GMPTimerParent::RecvSetTimer(const uint3
   return IPC_OK();
 }
 
 void
 GMPTimerParent::Shutdown()
 {
   LOGD(("%s::%s: %p mIsOpen=%d", __CLASS__, __FUNCTION__, this, mIsOpen));
 
-  MOZ_ASSERT(mGMPThread == NS_GetCurrentThread());
+  MOZ_ASSERT(mGMPEventTarget->IsOnCurrentThread());
 
   for (auto iter = mTimers.Iter(); !iter.Done(); iter.Next()) {
     Context* context = iter.Get()->GetKey();
     context->mTimer->Cancel();
     delete context;
   }
 
   mTimers.Clear();
@@ -101,17 +101,17 @@ GMPTimerParent::GMPTimerExpired(nsITimer
     ctx->mParent->TimerExpired(ctx);
   }
 }
 
 void
 GMPTimerParent::TimerExpired(Context* aContext)
 {
   LOGD(("%s::%s: %p mIsOpen=%d", __CLASS__, __FUNCTION__, this, mIsOpen));
-  MOZ_ASSERT(mGMPThread == NS_GetCurrentThread());
+  MOZ_ASSERT(mGMPEventTarget->IsOnCurrentThread());
 
   if (!mIsOpen) {
     return;
   }
 
   uint32_t id = aContext->mId;
   mTimers.RemoveEntry(aContext);
   if (id) {
--- a/dom/media/gmp/GMPTimerParent.h
+++ b/dom/media/gmp/GMPTimerParent.h
@@ -15,17 +15,17 @@
 #include "nsIThread.h"
 
 namespace mozilla {
 namespace gmp {
 
 class GMPTimerParent : public PGMPTimerParent {
 public:
   NS_INLINE_DECL_REFCOUNTING(GMPTimerParent)
-  explicit GMPTimerParent(nsIThread* aGMPThread);
+  explicit GMPTimerParent(nsISerialEventTarget* aGMPEventTarget);
 
   void Shutdown();
 
 protected:
   mozilla::ipc::IPCResult RecvSetTimer(const uint32_t& aTimerId,
                                        const uint32_t& aTimeoutMs) override;
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
@@ -45,17 +45,17 @@ private:
     RefPtr<GMPTimerParent> mParent; // Note: live timers keep the GMPTimerParent alive.
     uint32_t mId;
   };
 
   void TimerExpired(Context* aContext);
 
   nsTHashtable<nsPtrHashKey<Context>> mTimers;
 
-  nsCOMPtr<nsIThread> mGMPThread;
+  nsCOMPtr<nsISerialEventTarget> mGMPEventTarget;
 
   bool mIsOpen;
 };
 
 } // namespace gmp
 } // namespace mozilla
 
 #endif // GMPTimerParent_h_
--- a/dom/media/gmp/GMPVideoDecoderParent.cpp
+++ b/dom/media/gmp/GMPVideoDecoderParent.cpp
@@ -68,17 +68,17 @@ GMPVideoDecoderParent::Host()
   return mVideoHost;
 }
 
 // Note: may be called via Terminated()
 void
 GMPVideoDecoderParent::Close()
 {
   LOGD(("GMPVideoDecoderParent[%p]::Close()", this));
-  MOZ_ASSERT(!mPlugin || mPlugin->GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(!mPlugin || mPlugin->GMPEventTarget()->IsOnCurrentThread());
 
   // Ensure if we've received a Close while waiting for a ResetComplete
   // or DrainComplete notification, we'll unblock the caller before processing
   // the close. This seems unlikely to happen, but better to be careful.
   UnblockResetAndDrain();
 
   // Consumer is done with us; we can shut down.  No more callbacks should
   // be made to mCallback.  Note: do this before Shutdown()!
@@ -103,17 +103,17 @@ GMPVideoDecoderParent::InitDecode(const 
     NS_WARNING("Trying to use a destroyed GMP video decoder!");
     return NS_ERROR_FAILURE;
   }
   if (mIsOpen) {
     NS_WARNING("Trying to re-init an in-use GMP video decoder!");
     return NS_ERROR_FAILURE;
   }
 
-  MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(mPlugin->GMPEventTarget()->IsOnCurrentThread());
 
   if (!aCallback) {
     return NS_ERROR_FAILURE;
   }
   mCallback = aCallback;
 
   if (!SendInitDecode(aCodecSettings, aCodecSpecific, aCoreCount)) {
     return NS_ERROR_FAILURE;
@@ -147,17 +147,17 @@ GMPVideoDecoderParent::Decode(GMPUniqueP
         CryptoInfo(aInputFrame).get()));
 
   if (!mIsOpen) {
     LOGE(("GMPVideoDecoderParent[%p]::Decode() ERROR; dead GMPVideoDecoder", this));
     NS_WARNING("Trying to use an dead GMP video decoder");
     return NS_ERROR_FAILURE;
   }
 
-  MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(mPlugin->GMPEventTarget()->IsOnCurrentThread());
 
   GMPUniquePtr<GMPVideoEncodedFrameImpl> inputFrameImpl(
     static_cast<GMPVideoEncodedFrameImpl*>(aInputFrame.release()));
 
   // Very rough kill-switch if the plugin stops processing.  If it's merely
   // hung and continues, we'll come back to life eventually.
   // 3* is because we're using 3 buffers per frame for i420 data for now.
   if ((NumInUse(GMPSharedMem::kGMPFrameData) > 3*GMPSharedMem::kGMPBufLimit) ||
@@ -188,34 +188,34 @@ GMPVideoDecoderParent::Reset()
 {
   LOGD(("GMPVideoDecoderParent[%p]::Reset()", this));
 
   if (!mIsOpen) {
     NS_WARNING("Trying to use an dead GMP video decoder");
     return NS_ERROR_FAILURE;
   }
 
-  MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(mPlugin->GMPEventTarget()->IsOnCurrentThread());
 
   if (!SendReset()) {
     return NS_ERROR_FAILURE;
   }
 
   mIsAwaitingResetComplete = true;
 
   RefPtr<GMPVideoDecoderParent> self(this);
   nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction([self]() -> void
   {
     LOGD(("GMPVideoDecoderParent[%p]::ResetCompleteTimeout() timed out waiting for ResetComplete", self.get()));
     self->mResetCompleteTimeout = nullptr;
     LogToBrowserConsole(NS_LITERAL_STRING("GMPVideoDecoderParent timed out waiting for ResetComplete()"));
   });
   CancelResetCompleteTimeout();
-  nsCOMPtr<nsIThread> thread = mPlugin->GMPThread();
-  mResetCompleteTimeout = SimpleTimer::Create(task, 5000, thread);
+  nsCOMPtr<nsISerialEventTarget> target = mPlugin->GMPEventTarget();
+  mResetCompleteTimeout = SimpleTimer::Create(task, 5000, target);
 
   // Async IPC, we don't have access to a return value.
   return NS_OK;
 }
 
 void
 GMPVideoDecoderParent::CancelResetCompleteTimeout()
 {
@@ -230,17 +230,17 @@ GMPVideoDecoderParent::Drain()
 {
   LOGD(("GMPVideoDecoderParent[%p]::Drain() frameCount=%d", this, mFrameCount));
 
   if (!mIsOpen) {
     NS_WARNING("Trying to use an dead GMP video decoder");
     return NS_ERROR_FAILURE;
   }
 
-  MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(mPlugin->GMPEventTarget()->IsOnCurrentThread());
 
   if (!SendDrain()) {
     return NS_ERROR_FAILURE;
   }
 
   mIsAwaitingDrainComplete = true;
 
   // Async IPC, we don't have access to a return value.
@@ -249,27 +249,27 @@ GMPVideoDecoderParent::Drain()
 
 const nsCString&
 GMPVideoDecoderParent::GetDisplayName() const
 {
   if (!mIsOpen) {
     NS_WARNING("Trying to use an dead GMP video decoder");
   }
 
-  MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(mPlugin->GMPEventTarget()->IsOnCurrentThread());
 
   return mPlugin->GetDisplayName();
 }
 
 // Note: Consider keeping ActorDestroy sync'd up when making changes here.
 nsresult
 GMPVideoDecoderParent::Shutdown()
 {
   LOGD(("GMPVideoDecoderParent[%p]::Shutdown()", this));
-  MOZ_ASSERT(!mPlugin || mPlugin->GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(!mPlugin || mPlugin->GMPEventTarget()->IsOnCurrentThread());
 
   if (mShuttingDown) {
     return NS_OK;
   }
   mShuttingDown = true;
 
   // Ensure if we've received a shutdown while waiting for a ResetComplete
   // or DrainComplete notification, we'll unblock the caller before processing
--- a/dom/media/gmp/GMPVideoEncoderParent.cpp
+++ b/dom/media/gmp/GMPVideoEncoderParent.cpp
@@ -78,17 +78,17 @@ GMPVideoEncoderParent::Host()
   return mVideoHost;
 }
 
 // Note: may be called via Terminated()
 void
 GMPVideoEncoderParent::Close()
 {
   LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, this));
-  MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(mPlugin->GMPEventTarget()->IsOnCurrentThread());
   // Consumer is done with us; we can shut down.  No more callbacks should
   // be made to mCallback.  Note: do this before Shutdown()!
   mCallback = nullptr;
   // Let Shutdown mark us as dead so it knows if we had been alive
 
   // In case this is the last reference
   RefPtr<GMPVideoEncoderParent> kungfudeathgrip(this);
   Release();
@@ -103,17 +103,17 @@ GMPVideoEncoderParent::InitEncode(const 
                                   uint32_t aMaxPayloadSize)
 {
   LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, this));
   if (mIsOpen) {
     NS_WARNING("Trying to re-init an in-use GMP video encoder!");
     return GMPGenericErr;;
   }
 
-  MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(mPlugin->GMPEventTarget()->IsOnCurrentThread());
 
   if (!aCallback) {
     return GMPGenericErr;
   }
   mCallback = aCallback;
 
   if (!SendInitEncode(aCodecSettings, aCodecSpecific, aNumberOfCores, aMaxPayloadSize)) {
     return GMPGenericErr;
@@ -129,17 +129,17 @@ GMPVideoEncoderParent::Encode(GMPUniqueP
                               const nsTArray<uint8_t>& aCodecSpecificInfo,
                               const nsTArray<GMPVideoFrameType>& aFrameTypes)
 {
   if (!mIsOpen) {
     NS_WARNING("Trying to use an dead GMP video encoder");
     return GMPGenericErr;
   }
 
-  MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(mPlugin->GMPEventTarget()->IsOnCurrentThread());
 
   GMPUniquePtr<GMPVideoi420FrameImpl> inputFrameImpl(
     static_cast<GMPVideoi420FrameImpl*>(aInputFrame.release()));
 
   // Very rough kill-switch if the plugin stops processing.  If it's merely
   // hung and continues, we'll come back to life eventually.
   // 3* is because we're using 3 buffers per frame for i420 data for now.
   if ((NumInUse(GMPSharedMem::kGMPFrameData) > 3*GMPSharedMem::kGMPBufLimit) ||
@@ -163,17 +163,17 @@ GMPVideoEncoderParent::Encode(GMPUniqueP
 GMPErr
 GMPVideoEncoderParent::SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT)
 {
   if (!mIsOpen) {
     NS_WARNING("Trying to use an invalid GMP video encoder!");
     return GMPGenericErr;
   }
 
-  MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(mPlugin->GMPEventTarget()->IsOnCurrentThread());
 
   if (!SendSetChannelParameters(aPacketLoss, aRTT)) {
     return GMPGenericErr;
   }
 
   // Async IPC, we don't have access to a return value.
   return GMPNoErr;
 }
@@ -181,17 +181,17 @@ GMPVideoEncoderParent::SetChannelParamet
 GMPErr
 GMPVideoEncoderParent::SetRates(uint32_t aNewBitRate, uint32_t aFrameRate)
 {
   if (!mIsOpen) {
     NS_WARNING("Trying to use an dead GMP video decoder");
     return GMPGenericErr;
   }
 
-  MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(mPlugin->GMPEventTarget()->IsOnCurrentThread());
 
   if (!SendSetRates(aNewBitRate, aFrameRate)) {
     return GMPGenericErr;
   }
 
   // Async IPC, we don't have access to a return value.
   return GMPNoErr;
 }
@@ -199,32 +199,32 @@ GMPVideoEncoderParent::SetRates(uint32_t
 GMPErr
 GMPVideoEncoderParent::SetPeriodicKeyFrames(bool aEnable)
 {
   if (!mIsOpen) {
     NS_WARNING("Trying to use an invalid GMP video encoder!");
     return GMPGenericErr;
   }
 
-  MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(mPlugin->GMPEventTarget()->IsOnCurrentThread());
 
   if (!SendSetPeriodicKeyFrames(aEnable)) {
     return GMPGenericErr;
   }
 
   // Async IPC, we don't have access to a return value.
   return GMPNoErr;
 }
 
 // Note: Consider keeping ActorDestroy sync'd up when making changes here.
 void
 GMPVideoEncoderParent::Shutdown()
 {
   LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, this));
-  MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
+  MOZ_ASSERT(mPlugin->GMPEventTarget()->IsOnCurrentThread());
 
   if (mShuttingDown) {
     return;
   }
   mShuttingDown = true;
 
   // Notify client we're gone!  Won't occur after Close()
   if (mCallback) {
--- a/dom/media/platforms/PDMFactory.cpp
+++ b/dom/media/platforms/PDMFactory.cpp
@@ -184,26 +184,26 @@ PDMFactory::EnsureInit() const
       // On the main thread and holding the lock -> Create instance.
       sInstance = new PDMFactoryImpl();
       ClearOnShutdown(&sInstance);
       return;
     }
   }
 
   // Not on the main thread -> Sync-dispatch creation to main thread.
-  nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
+  nsCOMPtr<nsIEventTarget> mainTarget = GetMainThreadEventTarget();
   nsCOMPtr<nsIRunnable> runnable =
     NS_NewRunnableFunction([]() {
       StaticMutexAutoLock mon(sMonitor);
       if (!sInstance) {
         sInstance = new PDMFactoryImpl();
         ClearOnShutdown(&sInstance);
       }
     });
-  SyncRunnable::DispatchToThread(mainThread, runnable);
+  SyncRunnable::DispatchToThread(mainTarget, runnable);
 }
 
 already_AddRefed<MediaDataDecoder>
 PDMFactory::CreateDecoder(const CreateDecoderParams& aParams)
 {
   if (aParams.mUseNullDecoder) {
     MOZ_ASSERT(mNullPDM);
     return CreateDecoderWithPDM(mNullPDM, aParams);
--- a/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp
+++ b/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp
@@ -20,17 +20,17 @@ static bool IsOnGMPThread()
 {
   nsCOMPtr<mozIGeckoMediaPluginService> mps =
     do_GetService("@mozilla.org/gecko-media-plugin-service;1");
   MOZ_ASSERT(mps);
 
   nsCOMPtr<nsIThread> gmpThread;
   nsresult rv = mps->GetThread(getter_AddRefs(gmpThread));
   MOZ_ASSERT(NS_SUCCEEDED(rv) && gmpThread);
-  return NS_GetCurrentThread() == gmpThread;
+  return gmpThread->EventTarget()->IsOnCurrentThread();
 }
 #endif
 
 GMPVideoDecoderParams::GMPVideoDecoderParams(const CreateDecoderParams& aParams)
   : mConfig(aParams.VideoConfig())
   , mTaskQueue(aParams.mTaskQueue)
   , mImageContainer(aParams.mImageContainer)
   , mLayersBackend(aParams.GetLayersBackend())
--- a/dom/media/systemservices/CamerasParent.cpp
+++ b/dom/media/systemservices/CamerasParent.cpp
@@ -58,19 +58,19 @@ void InputObserver::OnDeviceChange() {
     media::NewRunnableFrom([self]() -> nsresult {
       if (self->mParent->IsShuttingDown()) {
         return NS_ERROR_FAILURE;
       }
       Unused << self->mParent->SendDeviceChange();
       return NS_OK;
     });
 
-  nsIThread* thread = mParent->GetBackgroundThread();
-  MOZ_ASSERT(thread != nullptr);
-  thread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
+  nsIEventTarget* target = mParent->GetBackgroundEventTarget();
+  MOZ_ASSERT(target != nullptr);
+  target->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
 };
 
 class DeliverFrameRunnable : public ::mozilla::Runnable {
 public:
   DeliverFrameRunnable(CamerasParent *aParent, CaptureEngine aEngine,
       uint32_t aStreamId, const webrtc::VideoFrame& aFrame,
       const VideoFrameProperties& aProperties)
       : mParent(aParent), mCapEngine(aEngine), mStreamId(aStreamId),
@@ -276,19 +276,19 @@ CallbackHelper::RenderFrame(uint32_t aSt
     runnable = new DeliverFrameRunnable(mParent, mCapEngine, mStreamId,
                                         Move(shMemBuffer), properties);
   }
   if (!runnable.get()) {
     runnable = new DeliverFrameRunnable(mParent, mCapEngine, mStreamId,
                                         aVideoFrame, properties);
   }
   MOZ_ASSERT(mParent);
-  nsIThread* thread = mParent->GetBackgroundThread();
-  MOZ_ASSERT(thread != nullptr);
-  thread->Dispatch(runnable, NS_DISPATCH_NORMAL);
+  nsIEventTarget* target = mParent->GetBackgroundEventTarget();
+  MOZ_ASSERT(target != nullptr);
+  target->Dispatch(runnable, NS_DISPATCH_NORMAL);
   return 0;
 }
 
 void
 CallbackHelper::OnIncomingCapturedFrame(const int32_t id, const webrtc::VideoFrame& aVideoFrame)
 {
  LOG_VERBOSE((__PRETTY_FUNCTION__));
  RenderFrame(id,aVideoFrame);
@@ -452,17 +452,17 @@ CamerasParent::RecvNumberOfCaptureDevice
             Unused << self->SendReplyFailure();
             return NS_ERROR_FAILURE;
           } else {
             LOG(("RecvNumberOfCaptureDevices: %d", num));
             Unused << self->SendReplyNumberOfCaptureDevices(num);
             return NS_OK;
           }
         });
-        self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
+        self->mPBackgroundEventTarget->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
       return NS_OK;
     });
   DispatchToVideoCaptureThread(webrtc_runnable);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 CamerasParent::RecvEnsureInitialized(const CaptureEngine& aCapEngine)
@@ -484,17 +484,17 @@ CamerasParent::RecvEnsureInitialized(con
             Unused << self->SendReplyFailure();
             return NS_ERROR_FAILURE;
           } else {
             LOG(("RecvEnsureInitialized succeeded"));
             Unused << self->SendReplySuccess();
             return NS_OK;
           }
         });
-        self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
+        self->mPBackgroundEventTarget->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
       return NS_OK;
     });
   DispatchToVideoCaptureThread(webrtc_runnable);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 CamerasParent::RecvNumberOfCapabilities(const CaptureEngine& aCapEngine,
@@ -522,17 +522,17 @@ CamerasParent::RecvNumberOfCapabilities(
             Unused << self->SendReplyFailure();
             return NS_ERROR_FAILURE;
           } else {
             LOG(("RecvNumberOfCapabilities: %d", num));
           }
           Unused << self->SendReplyNumberOfCapabilities(num);
           return NS_OK;
         });
-      self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
+      self->mPBackgroundEventTarget->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
       return NS_OK;
     });
   DispatchToVideoCaptureThread(webrtc_runnable);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 CamerasParent::RecvGetCaptureCapability(const CaptureEngine& aCapEngine,
@@ -573,17 +573,17 @@ CamerasParent::RecvGetCaptureCapability(
                webrtcCaps.codecType));
           if (error) {
             Unused << self->SendReplyFailure();
             return NS_ERROR_FAILURE;
           }
           Unused << self->SendReplyGetCaptureCapability(capCap);
           return NS_OK;
         });
-      self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
+      self->mPBackgroundEventTarget->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
       return NS_OK;
     });
   DispatchToVideoCaptureThread(webrtc_runnable);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 CamerasParent::RecvGetCaptureDevice(const CaptureEngine& aCapEngine,
@@ -624,17 +624,17 @@ CamerasParent::RecvGetCaptureDevice(cons
           }
           bool scary = (devicePid == getpid());
 
           LOG(("Returning %s name %s id (pid = %d)%s", name.get(),
                uniqueId.get(), devicePid, (scary? " (scary)" : "")));
           Unused << self->SendReplyGetCaptureDevice(name, uniqueId, scary);
           return NS_OK;
         });
-      self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
+      self->mPBackgroundEventTarget->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
       return NS_OK;
     });
   DispatchToVideoCaptureThread(webrtc_runnable);
   return IPC_OK();
 }
 
 // Find out whether the given principal has permission to use the
 // camera. If the permission is not persistent, we'll make it
@@ -735,17 +735,17 @@ CamerasParent::RecvAllocateCaptureDevice
               Unused << self->SendReplyFailure();
               return NS_ERROR_FAILURE;
             } else {
               LOG(("Allocated device nr %d", numdev));
               Unused << self->SendReplyAllocateCaptureDevice(numdev);
               return NS_OK;
             }
           });
-        self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
+        self->mPBackgroundEventTarget->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
         return NS_OK;
         });
       self->DispatchToVideoCaptureThread(webrtc_runnable);
       return NS_OK;
     });
   NS_DispatchToMainThread(mainthread_runnable);
   return IPC_OK();
 }
@@ -783,17 +783,17 @@ CamerasParent::RecvReleaseCaptureDevice(
             LOG(("Failed to free device nr %d", numdev));
             return NS_ERROR_FAILURE;
           } else {
             Unused << self->SendReplySuccess();
             LOG(("Freed device nr %d", numdev));
             return NS_OK;
           }
         });
-      self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
+      self->mPBackgroundEventTarget->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
       return NS_OK;
     });
   DispatchToVideoCaptureThread(webrtc_runnable);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 CamerasParent::RecvStartCapture(const CaptureEngine& aCapEngine,
@@ -849,17 +849,17 @@ CamerasParent::RecvStartCapture(const Ca
           if (!error) {
             Unused << self->SendReplySuccess();
             return NS_OK;
           } else {
             Unused << self->SendReplyFailure();
             return NS_ERROR_FAILURE;
           }
         });
-      self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
+      self->mPBackgroundEventTarget->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
       return NS_OK;
     });
   DispatchToVideoCaptureThread(webrtc_runnable);
   return IPC_OK();
 }
 
 void
 CamerasParent::StopCapture(const CaptureEngine& aCapEngine,
@@ -961,18 +961,19 @@ CamerasParent::CamerasParent()
     mThreadMonitor("CamerasParent::mThreadMonitor"),
     mVideoCaptureThread(nullptr),
     mChildIsAlive(true),
     mDestroyed(false),
     mWebRTCAlive(true)
 {
   LOG(("CamerasParent: %p", this));
 
-  mPBackgroundThread = NS_GetCurrentThread();
-  MOZ_ASSERT(mPBackgroundThread != nullptr, "GetCurrentThread failed");
+  mPBackgroundEventTarget = GetCurrentThreadSerialEventTarget();
+  MOZ_ASSERT(mPBackgroundEventTarget != nullptr,
+             "GetCurrentThreadEventTarget failed");
 
   LOG(("Spinning up WebRTC Cameras Thread"));
 
   RefPtr<CamerasParent> self(this);
   RefPtr<Runnable> threadStart =
     media::NewRunnableFrom([self]() -> nsresult {
       // Register thread shutdown observer
       nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
--- a/dom/media/systemservices/CamerasParent.h
+++ b/dom/media/systemservices/CamerasParent.h
@@ -108,17 +108,17 @@ public:
   virtual mozilla::ipc::IPCResult RecvStartCapture(const CaptureEngine&, const int&,
                                                    const VideoCaptureCapability&) override;
   virtual mozilla::ipc::IPCResult RecvStopCapture(const CaptureEngine&, const int&) override;
   virtual mozilla::ipc::IPCResult RecvReleaseFrame(mozilla::ipc::Shmem&&) override;
   virtual mozilla::ipc::IPCResult RecvAllDone() override;
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
   virtual mozilla::ipc::IPCResult RecvEnsureInitialized(const CaptureEngine&) override;
 
-  nsIThread* GetBackgroundThread() { return mPBackgroundThread; };
+  nsIEventTarget* GetBackgroundEventTarget() { return mPBackgroundEventTarget; };
   bool IsShuttingDown() { return !mChildIsAlive
                               ||  mDestroyed
                               || !mWebRTCAlive; };
   ShmemBuffer GetBuffer(size_t aSize);
 
   // helper to forward to the PBackground thread
   int DeliverFrameOverIPC(CaptureEngine capEng,
                           uint32_t aStreamId,
@@ -146,17 +146,17 @@ protected:
 
   RefPtr<VideoEngine> mEngines[CaptureEngine::MaxEngine];
   nsTArray<CallbackHelper*> mCallbacks;
 
   // image buffers
   mozilla::ShmemPool mShmemPool;
 
   // PBackground parent thread
-  nsCOMPtr<nsIThread> mPBackgroundThread;
+  nsCOMPtr<nsISerialEventTarget> mPBackgroundEventTarget;
 
   // Monitors creation of the thread below
   Monitor mThreadMonitor;
 
   // video processing thread - where webrtc.org capturer code runs
   base::Thread* mVideoCaptureThread;
 
   // Shutdown handling
--- a/dom/media/webaudio/blink/HRTFDatabaseLoader.cpp
+++ b/dom/media/webaudio/blink/HRTFDatabaseLoader.cpp
@@ -118,21 +118,21 @@ public:
         return NS_OK;
     }
 private:
     HRTFDatabaseLoader* mLoader;
 };
 
 void HRTFDatabaseLoader::ProxyRelease()
 {
-    nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
-    if (MOZ_LIKELY(mainThread)) {
+    nsCOMPtr<nsIEventTarget> mainTarget = GetMainThreadEventTarget();
+    if (MOZ_LIKELY(mainTarget)) {
         RefPtr<ProxyReleaseEvent> event = new ProxyReleaseEvent(this);
         DebugOnly<nsresult> rv =
-            mainThread->Dispatch(event, NS_DISPATCH_NORMAL);
+            mainTarget->Dispatch(event, NS_DISPATCH_NORMAL);
         MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed to dispatch release event");
     } else {
         // Should be in XPCOM shutdown.
         MOZ_ASSERT(NS_IsMainThread(),
                    "Main thread is not available for dispatch.");
         MainThreadRelease();
     }
 }
--- a/dom/media/webspeech/recognition/SpeechStreamListener.cpp
+++ b/dom/media/webspeech/recognition/SpeechStreamListener.cpp
@@ -14,20 +14,17 @@ namespace dom {
 
 SpeechStreamListener::SpeechStreamListener(SpeechRecognition* aRecognition)
   : mRecognition(aRecognition)
 {
 }
 
 SpeechStreamListener::~SpeechStreamListener()
 {
-  nsCOMPtr<nsIThread> mainThread;
-  NS_GetMainThread(getter_AddRefs(mainThread));
-
-  NS_ProxyRelease(mainThread, mRecognition.forget());
+  NS_ReleaseOnMainThread(mRecognition.forget());
 }
 
 void
 SpeechStreamListener::NotifyQueuedAudioData(MediaStreamGraph* aGraph, TrackID aID,
                                             StreamTime aTrackOffset,
                                             const AudioSegment& aQueuedMedia,
                                             MediaStream* aInputStream,
                                             TrackID aInputTrackID)