Bug 1346678 - Label runnables in dom/media/gmp/GMPParent.cpp and its friends. r?cpearce draft
authorJW Wang <jwwang@mozilla.com>
Thu, 09 Mar 2017 15:31:11 +0800
changeset 497254 05b1855db21c755192ead612edce6ae66a861880
parent 497253 ad313d8ae219f1618431e82471834b12c19c5e02
child 497255 6a1ba18bca51b18ba08957ebbef87c0ac2df01ac
push id48848
push userjwwang@mozilla.com
push dateMon, 13 Mar 2017 03:58:36 +0000
reviewerscpearce
bugs1346678
milestone55.0a1
Bug 1346678 - Label runnables in dom/media/gmp/GMPParent.cpp and its friends. r?cpearce MozReview-Commit-ID: DWYx30T7gCJ
dom/media/gmp/GMPCrashHelper.cpp
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/GMPServiceParent.h
--- a/dom/media/gmp/GMPCrashHelper.cpp
+++ b/dom/media/gmp/GMPCrashHelper.cpp
@@ -14,13 +14,15 @@ NS_IMPL_RELEASE_WITH_DESTROY(GMPCrashHel
 
 void
 GMPCrashHelper::Destroy()
 {
   if (NS_IsMainThread()) {
     delete this;
   } else {
     // Don't addref, as then we'd end up releasing after the detele runs!
-    NS_DispatchToMainThread(mozilla::NewNonOwningRunnableMethod(this, &GMPCrashHelper::Destroy));
+    SystemGroup::Dispatch(
+      "GMPCrashHelper::Destroy", TaskCategory::Other,
+      NewNonOwningRunnableMethod(this, &GMPCrashHelper::Destroy));
   }
 }
 
 } // namespace mozilla
--- a/dom/media/gmp/GMPParent.cpp
+++ b/dom/media/gmp/GMPParent.cpp
@@ -55,26 +55,27 @@ extern LogModule* GetGMPLog();
 
 #ifdef __CLASS__
 #undef __CLASS__
 #endif
 #define __CLASS__ "GMPParent"
 
 namespace gmp {
 
-GMPParent::GMPParent()
+GMPParent::GMPParent(AbstractThread* aMainThread)
   : mState(GMPStateNotLoaded)
   , mProcess(nullptr)
   , mDeleteProcessOnlyOnUnload(false)
   , mAbnormalShutdownInProgress(false)
   , mIsBlockingDeletion(false)
   , mCanDecrypt(false)
   , mGMPContentChildCount(0)
   , mChildPid(0)
   , mHoldingSelfRef(false)
+  , mMainThread(aMainThread)
 {
   mPluginId = GeckoChildProcessHost::GetUniqueID();
   LOGD("GMPParent ctor id=%u", mPluginId);
 }
 
 GMPParent::~GMPParent()
 {
   LOGD("GMPParent dtor id=%u", mPluginId);
@@ -297,17 +298,18 @@ GMPParent::Shutdown()
     mService->ReAddOnGMPThread(self);
   } // else we've been asked to die and stay dead
   MOZ_ASSERT(mState == GMPStateNotLoaded);
 }
 
 class NotifyGMPShutdownTask : public Runnable {
 public:
   explicit NotifyGMPShutdownTask(const nsAString& aNodeId)
-    : mNodeId(aNodeId)
+    : Runnable("NotifyGMPShutdownTask")
+    , mNodeId(aNodeId)
   {
   }
   NS_IMETHOD Run() override {
     MOZ_ASSERT(NS_IsMainThread());
     nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService();
     MOZ_ASSERT(obsService);
     if (obsService) {
       obsService->NotifyObservers(nullptr, "gmp-shutdown", mNodeId.get());
@@ -349,19 +351,19 @@ GMPParent::DeleteProcess()
     mState = GMPStateClosing;
     Close();
   }
   mProcess->Delete(NewRunnableMethod(this, &GMPParent::ChildTerminated));
   LOGD("%s: Shut down process", __FUNCTION__);
   mProcess = nullptr;
   mState = GMPStateNotLoaded;
 
-  NS_DispatchToMainThread(
-    new NotifyGMPShutdownTask(NS_ConvertUTF8toUTF16(mNodeId)),
-    NS_DISPATCH_NORMAL);
+  nsCOMPtr<nsIRunnable> r
+    = new NotifyGMPShutdownTask(NS_ConvertUTF8toUTF16(mNodeId));
+  mMainThread->Dispatch(r.forget());
 
   if (mHoldingSelfRef) {
     Release();
     mHoldingSelfRef = false;
   }
 }
 
 GMPState
@@ -512,19 +514,19 @@ GMPParent::ActorDestroy(ActorDestroyReas
     if (!GetCrashID(dumpID)) {
       NS_WARNING("GMP crash without crash report");
       dumpID = mName;
       dumpID += '-';
       AppendUTF8toUTF16(mVersion, dumpID);
     }
 
     // NotifyObservers is mainthread-only
-    NS_DispatchToMainThread(WrapRunnableNM(&GMPNotifyObservers,
-                                           mPluginId, mDisplayName, dumpID),
-                            NS_DISPATCH_NORMAL);
+    nsCOMPtr<nsIRunnable> r = WrapRunnableNM(
+      &GMPNotifyObservers, mPluginId, mDisplayName, dumpID);
+    mMainThread->Dispatch(r.forget());
   }
 #endif
   // warn us off trying to close again
   mState = GMPStateClosing;
   mAbnormalShutdownInProgress = true;
   CloseActive(false);
 
   // Normal Shutdown() will delete the process on unwind.
@@ -723,18 +725,17 @@ GMPParent::ReadChromiumManifestFile(nsIF
 {
   nsAutoCString json;
   if (!ReadIntoString(aFile, json, 5 * 1024)) {
     return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
   }
 
   // DOM JSON parsing needs to run on the main thread.
   return InvokeAsync<nsString&&>(
-    // Non DocGroup-version of AbstractThread::MainThread for the task in parent.
-    AbstractThread::MainThread(), this, __func__,
+    mMainThread, this, __func__,
     &GMPParent::ParseChromiumManifest, NS_ConvertUTF8toUTF16(json));
 }
 
 RefPtr<GenericPromise>
 GMPParent::ParseChromiumManifest(const nsAString& aJSON)
 {
   LOGD("%s: for '%s'", __FUNCTION__, NS_LossyConvertUTF16toASCII(aJSON).get());
 
--- a/dom/media/gmp/GMPParent.h
+++ b/dom/media/gmp/GMPParent.h
@@ -68,17 +68,17 @@ enum GMPState {
 
 class GMPContentParent;
 
 class GMPParent final : public PGMPParent
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPParent)
 
-  GMPParent();
+  explicit GMPParent(AbstractThread* aMainThread);
 
   RefPtr<GenericPromise> Init(GeckoMediaPluginServiceParent* aService, nsIFile* aPluginDir);
   nsresult CloneFrom(const GMPParent* aOther);
 
   void Crash();
 
   nsresult LoadProcess();
 
@@ -223,14 +223,16 @@ private:
   // This ensures that if the GMPService tries to shut us down and drops
   // its reference to us, we stay alive long enough for the child process
   // to terminate gracefully.
   bool mHoldingSelfRef;
 
 #ifdef MOZ_CRASHREPORTER
   UniquePtr<ipc::CrashReporterHost> mCrashReporter;
 #endif
+
+  const RefPtr<AbstractThread> mMainThread;
 };
 
 } // namespace gmp
 } // namespace mozilla
 
 #endif // GMPParent_h_
--- a/dom/media/gmp/GMPService.cpp
+++ b/dom/media/gmp/GMPService.cpp
@@ -74,31 +74,31 @@ public:
   static already_AddRefed<GeckoMediaPluginService>
   GetOrCreate()
   {
     RefPtr<GeckoMediaPluginService> service;
 
     if (NS_IsMainThread()) {
       service = GetOrCreateOnMainThread();
     } else {
-      nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
-      MOZ_ASSERT(mainThread);
-
       RefPtr<GMPServiceCreateHelper> createHelper = new GMPServiceCreateHelper();
 
-      mozilla::SyncRunnable::DispatchToThread(mainThread, createHelper, true);
+      mozilla::SyncRunnable::DispatchToThread(
+        SystemGroup::EventTargetFor(mozilla::TaskCategory::Other),
+        createHelper, true);
 
       service = createHelper->mService.forget();
     }
 
     return service.forget();
   }
 
 private:
   GMPServiceCreateHelper()
+    : Runnable("GMPServiceCreateHelper")
   {
   }
 
   ~GMPServiceCreateHelper()
   {
     MOZ_ASSERT(!mService);
   }
 
--- a/dom/media/gmp/GMPServiceChild.cpp
+++ b/dom/media/gmp/GMPServiceChild.cpp
@@ -300,18 +300,19 @@ GeckoMediaPluginServiceChild::GetService
   if (!mServiceChild) {
     dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
     if (!contentChild) {
       return GetServiceChildPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
     }
     MozPromiseHolder<GetServiceChildPromise>* holder = mGetServiceChildPromises.AppendElement();
     RefPtr<GetServiceChildPromise> promise = holder->Ensure(__func__);
     if (mGetServiceChildPromises.Length() == 1) {
-        NS_DispatchToMainThread(WrapRunnable(contentChild,
-                                             &dom::ContentChild::SendCreateGMPService));
+      nsCOMPtr<nsIRunnable> r = WrapRunnable(
+        contentChild, &dom::ContentChild::SendCreateGMPService);
+      SystemGroup::Dispatch("SendCreateGMPService", TaskCategory::Other, r.forget());
     }
     return promise;
   }
   return GetServiceChildPromise::CreateAndResolve(mServiceChild.get(), __func__);
 }
 
 void
 GeckoMediaPluginServiceChild::SetServiceChild(UniquePtr<GMPServiceChild>&& aServiceChild)
--- a/dom/media/gmp/GMPServiceParent.cpp
+++ b/dom/media/gmp/GMPServiceParent.cpp
@@ -89,16 +89,17 @@ NS_IMPL_ISUPPORTS_INHERITED(GeckoMediaPl
 
 GeckoMediaPluginServiceParent::GeckoMediaPluginServiceParent()
   : mShuttingDown(false)
   , mScannedPluginOnDisk(false)
   , mWaitingForPluginsSyncShutdown(false)
   , mInitPromiseMonitor("GeckoMediaPluginServiceParent::mInitPromiseMonitor")
   , mLoadPluginsFromDiskComplete(false)
   , mServiceUserCount(0)
+  , mMainThread(SystemGroup::AbstractMainThreadFor(TaskCategory::Other))
 {
   MOZ_ASSERT(NS_IsMainThread());
   mInitPromise.SetMonitor(&mInitPromiseMonitor);
 }
 
 GeckoMediaPluginServiceParent::~GeckoMediaPluginServiceParent()
 {
   MOZ_ASSERT(mPlugins.IsEmpty());
@@ -457,19 +458,20 @@ GeckoMediaPluginServiceParent::UnloadPlu
   }
 #endif
   // Note: CloseActive may be async; it could actually finish
   // shutting down when all the plugins have unloaded.
   for (const auto& plugin : plugins) {
     plugin->CloseActive(true);
   }
 
-  nsCOMPtr<nsIRunnable> task(NewRunnableMethod(
-    this, &GeckoMediaPluginServiceParent::NotifySyncShutdownComplete));
-  NS_DispatchToMainThread(task);
+  nsCOMPtr<nsIRunnable> task = NewRunnableMethod(
+    "GeckoMediaPluginServiceParent::NotifySyncShutdownComplete",
+    this, &GeckoMediaPluginServiceParent::NotifySyncShutdownComplete);
+  mMainThread->Dispatch(task.forget());
 }
 
 void
 GeckoMediaPluginServiceParent::CrashPlugins()
 {
   LOGD(("%s::%s", __CLASS__, __FUNCTION__));
   MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
 
@@ -515,17 +517,18 @@ GeckoMediaPluginServiceParent::LoadFromE
 
   mScannedPluginOnDisk = true;
   return GenericPromise::All(thread, promises);
 }
 
 class NotifyObserversTask final : public mozilla::Runnable {
 public:
   explicit NotifyObserversTask(const char* aTopic, nsString aData = EmptyString())
-    : mTopic(aTopic)
+    : Runnable(aTopic)
+    , mTopic(aTopic)
     , mData(aData)
   {}
   NS_IMETHOD Run() override {
     MOZ_ASSERT(NS_IsMainThread());
     nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService();
     MOZ_ASSERT(obsService);
     if (obsService) {
       obsService->NotifyObservers(nullptr, mTopic, mData.get());
@@ -548,19 +551,20 @@ GeckoMediaPluginServiceParent::PathRunna
   mService->UpdateContentProcessGMPCapabilities();
   return NS_OK;
 }
 
 void
 GeckoMediaPluginServiceParent::UpdateContentProcessGMPCapabilities()
 {
   if (!NS_IsMainThread()) {
-    nsCOMPtr<nsIRunnable> task =
-      NewRunnableMethod(this, &GeckoMediaPluginServiceParent::UpdateContentProcessGMPCapabilities);
-    NS_DispatchToMainThread(task);
+    nsCOMPtr<nsIRunnable> task = NewRunnableMethod(
+      "GeckoMediaPluginServiceParent::UpdateContentProcessGMPCapabilities",
+      this, &GeckoMediaPluginServiceParent::UpdateContentProcessGMPCapabilities);
+    mMainThread->Dispatch(task.forget());
     return;
   }
 
   typedef mozilla::dom::GMPCapabilityData GMPCapabilityData;
   typedef mozilla::dom::GMPAPITags GMPAPITags;
   typedef mozilla::dom::ContentParent ContentParent;
 
   nsTArray<GMPCapabilityData> caps;
@@ -612,17 +616,17 @@ GeckoMediaPluginServiceParent::AsyncAddP
   }
 
   nsString dir(aDirectory);
   RefPtr<GeckoMediaPluginServiceParent> self = this;
   return InvokeAsync<nsString&&>(
            thread, this, __func__,
            &GeckoMediaPluginServiceParent::AddOnGMPThread, dir)
     ->Then(
-      AbstractThread::MainThread(), // Non DocGroup-version for the task in parent.
+      mMainThread,
       __func__,
       [dir, self]() -> void {
         LOGD(("GeckoMediaPluginServiceParent::AsyncAddPluginDirectory %s succeeded",
               NS_ConvertUTF16toUTF8(dir).get()));
         MOZ_ASSERT(NS_IsMainThread());
         self->UpdateContentProcessGMPCapabilities();
       },
       [dir]() -> void {
@@ -774,36 +778,36 @@ GeckoMediaPluginServiceParent::SelectPlu
     }
     return clone.forget();
   }
 
   return nullptr;
 }
 
 RefPtr<GMPParent>
-CreateGMPParent()
+CreateGMPParent(AbstractThread* aMainThread)
 {
 #if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
   if (!SandboxInfo::Get().CanSandboxMedia()) {
     if (!MediaPrefs::GMPAllowInsecure()) {
       NS_WARNING("Denying media plugin load due to lack of sandboxing.");
       return nullptr;
     }
     NS_WARNING("Loading media plugin despite lack of sandboxing.");
   }
 #endif
-  return new GMPParent();
+  return new GMPParent(aMainThread);
 }
 
 already_AddRefed<GMPParent>
 GeckoMediaPluginServiceParent::ClonePlugin(const GMPParent* aOriginal)
 {
   MOZ_ASSERT(aOriginal);
 
-  RefPtr<GMPParent> gmp = CreateGMPParent();
+  RefPtr<GMPParent> gmp = CreateGMPParent(mMainThread);
   nsresult rv = gmp ? gmp->CloneFrom(aOriginal) : NS_ERROR_NOT_AVAILABLE;
 
   if (NS_FAILED(rv)) {
     NS_WARNING("Can't Create GMPParent");
     return nullptr;
   }
 
   return gmp.forget();
@@ -832,17 +836,17 @@ GeckoMediaPluginServiceParent::AddOnGMPT
   nsCOMPtr<nsIFile> directory;
   nsresult rv = NS_NewLocalFile(aDirectory, false, getter_AddRefs(directory));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     LOGD(("%s::%s: failed to create nsIFile for dir=%s rv=%" PRIx32,
           __CLASS__, __FUNCTION__, dir.get(), static_cast<uint32_t>(rv)));
     return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
   }
 
-  RefPtr<GMPParent> gmp = CreateGMPParent();
+  RefPtr<GMPParent> gmp = CreateGMPParent(mMainThread);
   if (!gmp) {
     NS_WARNING("Can't Create GMPParent");
     return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
   }
 
   RefPtr<GeckoMediaPluginServiceParent> self(this);
   return gmp->Init(this, directory)->Then(thread, __func__,
     [gmp, self, dir]() -> void {
@@ -915,19 +919,19 @@ GeckoMediaPluginServiceParent::RemoveOnG
     // permission to delete them.
     directory->SetPermissions(0700);
     DirectoryEnumerator iter(directory, DirectoryEnumerator::FilesAndDirs);
     for (nsCOMPtr<nsIFile> dirEntry; (dirEntry = iter.Next()) != nullptr;) {
       dirEntry->SetPermissions(0700);
     }
     if (NS_SUCCEEDED(directory->Remove(true))) {
       mPluginsWaitingForDeletion.RemoveElement(aDirectory);
-      NS_DispatchToMainThread(new NotifyObserversTask("gmp-directory-deleted",
-                                                      nsString(aDirectory)),
-                              NS_DISPATCH_NORMAL);
+      nsCOMPtr<nsIRunnable> task = new NotifyObserversTask(
+        "gmp-directory-deleted", nsString(aDirectory));
+      mMainThread->Dispatch(task.forget());
     }
   }
 }
 
 // May remove when Bug 1043671 is fixed
 static void Dummy(RefPtr<GMPParent>& aOnDeathsDoor)
 {
   // exists solely to do nothing and let the Runnable kill the GMPParent
@@ -1532,17 +1536,19 @@ GeckoMediaPluginServiceParent::ClearRece
       return NS_SUCCEEDED(temp->AppendNative(salt)) && IsModifiedAfter(temp);
     }
   private:
     const PRTime mSince;
   } filter(aSince);
 
   ClearNodeIdAndPlugin(filter);
 
-  NS_DispatchToMainThread(new NotifyObserversTask("gmp-clear-storage-complete"), NS_DISPATCH_NORMAL);
+  nsCOMPtr<nsIRunnable> task
+    = new NotifyObserversTask("gmp-clear-storage-complete");
+  mMainThread->Dispatch(task.forget());
 }
 
 NS_IMETHODIMP
 GeckoMediaPluginServiceParent::ForgetThisSite(const nsAString& aSite,
                                               const nsAString& aPattern)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
@@ -1642,36 +1648,39 @@ GeckoMediaPluginServiceParent::ClearStor
 
   if (NS_FAILED(DeleteDir(path))) {
     NS_WARNING("Failed to delete GMP storage directory");
   }
 
   // Clear private-browsing storage.
   mTempGMPStorage.Clear();
 
-  NS_DispatchToMainThread(new NotifyObserversTask("gmp-clear-storage-complete"), NS_DISPATCH_NORMAL);
+  nsCOMPtr<nsIRunnable> task
+    = new NotifyObserversTask("gmp-clear-storage-complete");
+  mMainThread->Dispatch(task.forget());
 }
 
 already_AddRefed<GMPParent>
 GeckoMediaPluginServiceParent::GetById(uint32_t aPluginId)
 {
   MutexAutoLock lock(mMutex);
   for (const RefPtr<GMPParent>& gmp : mPlugins) {
     if (gmp->GetPluginId() == aPluginId) {
       return do_AddRef(gmp);
     }
   }
   return nullptr;
 }
 
 GMPServiceParent::~GMPServiceParent()
 {
-  NS_DispatchToMainThread(
-    NewRunnableMethod(mService.get(),
-                      &GeckoMediaPluginServiceParent::ServiceUserDestroyed));
+  nsCOMPtr<nsIRunnable> task = NewRunnableMethod(
+    "GeckoMediaPluginServiceParent::ServiceUserDestroyed",
+    mService.get(), &GeckoMediaPluginServiceParent::ServiceUserDestroyed);
+  mService->MainThread()->Dispatch(task.forget());
 }
 
 mozilla::ipc::IPCResult
 GMPServiceParent::RecvLaunchGMP(const nsCString& aNodeId,
                                 const nsCString& aAPI,
                                 nsTArray<nsCString>&& aTags,
                                 nsTArray<ProcessId>&& aAlreadyBridgedTo,
                                 uint32_t* aOutPluginId,
--- a/dom/media/gmp/GMPServiceParent.h
+++ b/dom/media/gmp/GMPServiceParent.h
@@ -60,16 +60,18 @@ public:
                                 const mozilla::OriginAttributesPattern& aPattern);
 
   // Notifies that some user of this class is created/destroyed.
   void ServiceUserCreated();
   void ServiceUserDestroyed();
 
   void UpdateContentProcessGMPCapabilities();
 
+  AbstractThread* MainThread() const { return mMainThread; }
+
 private:
   friend class GMPServiceParent;
 
   virtual ~GeckoMediaPluginServiceParent();
 
   void ClearStorage();
 
   already_AddRefed<GMPParent> SelectPluginForAPI(const nsACString& aNodeId,
@@ -197,16 +199,18 @@ private:
   bool mLoadPluginsFromDiskComplete;
 
   // Hashes nodeId to the hashtable of storage for that nodeId.
   nsRefPtrHashtable<nsCStringHashKey, GMPStorage> mTempGMPStorage;
 
   // Tracks how many users are running (on the GMP thread). Only when this count
   // drops to 0 can we safely shut down the thread.
   MainThreadOnly<int32_t> mServiceUserCount;
+
+  const RefPtr<AbstractThread> mMainThread;
 };
 
 nsresult ReadSalt(nsIFile* aPath, nsACString& aOutData);
 bool MatchOrigin(nsIFile* aPath,
                  const nsACString& aSite,
                  const mozilla::OriginAttributesPattern& aPattern);
 
 class GMPServiceParent final : public PGMPServiceParent