Bug 1267918 - Split LoadGMP message into select and load messages. r=gerald draft
authorChris Pearce <cpearce@mozilla.com>
Wed, 29 Jun 2016 11:41:52 +1200
changeset 383035 e67160643c724bf1f90cd62843cbb76de65a989f
parent 383034 ffa1bfaf23398aee04d8d46848f4576893c5dd95
child 383036 4eee756f6abf7a6212b6a3ce31dcb8182f12999b
push id21909
push usercpearce@mozilla.com
push dateFri, 01 Jul 2016 03:07:19 +0000
reviewersgerald
bugs1267918
milestone50.0a1
Bug 1267918 - Split LoadGMP message into select and load messages. r=gerald This will allow us to attach a crash handler to a GMP process after deciding which GMP to load but before actually loading it. MozReview-Commit-ID: HwBZU2Q4TX6
dom/media/gmp/GMPServiceChild.cpp
dom/media/gmp/GMPServiceParent.cpp
dom/media/gmp/GMPServiceParent.h
dom/media/gmp/PGMPService.ipdl
--- a/dom/media/gmp/GMPServiceChild.cpp
+++ b/dom/media/gmp/GMPServiceChild.cpp
@@ -62,26 +62,31 @@ public:
 
   void Done(GMPServiceChild* aGMPServiceChild) override
   {
     if (!aGMPServiceChild) {
       mCallback->Done(nullptr);
       return;
     }
 
+    uint32_t pluginId;
+    nsresult rv;
+    bool ok = aGMPServiceChild->SendSelectGMP(mNodeId, mAPI, mTags, &pluginId, &rv);
+    if (!ok || rv == NS_ERROR_ILLEGAL_DURING_SHUTDOWN) {
+      mCallback->Done(nullptr);
+      return;
+    }
+
     nsTArray<base::ProcessId> alreadyBridgedTo;
     aGMPServiceChild->GetAlreadyBridgedTo(alreadyBridgedTo);
 
     base::ProcessId otherProcess;
     nsCString displayName;
-    uint32_t pluginId;
-    nsresult rv;
-    bool ok = aGMPServiceChild->SendLoadGMP(mNodeId, mAPI, mTags,
-                                            alreadyBridgedTo, &otherProcess,
-                                            &displayName, &pluginId, &rv);
+    ok = aGMPServiceChild->SendLaunchGMP(pluginId, alreadyBridgedTo, &otherProcess,
+                                         &displayName, &rv);
     if (!ok || rv == NS_ERROR_ILLEGAL_DURING_SHUTDOWN) {
       mCallback->Done(nullptr);
       return;
     }
 
     RefPtr<GMPContentParent> parent;
     aGMPServiceChild->GetBridgedGMPContentParent(otherProcess,
                                                  getter_AddRefs(parent));
--- a/dom/media/gmp/GMPServiceParent.cpp
+++ b/dom/media/gmp/GMPServiceParent.cpp
@@ -1813,51 +1813,86 @@ GeckoMediaPluginServiceParent::ClearStor
   }
 
   // Clear private-browsing storage.
   mTempGMPStorage.Clear();
 
   NS_DispatchToMainThread(new NotifyObserversTask("gmp-clear-storage-complete"), NS_DISPATCH_NORMAL);
 }
 
+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()
 {
   RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(GetTransport());
   XRE_GetIOMessageLoop()->PostTask(task.forget());
 }
 
 bool
-GMPServiceParent::RecvLoadGMP(const nsCString& aNodeId,
-                              const nsCString& aAPI,
-                              nsTArray<nsCString>&& aTags,
-                              nsTArray<ProcessId>&& aAlreadyBridgedTo,
-                              ProcessId* aId,
-                              nsCString* aDisplayName,
-                              uint32_t* aPluginId,
-                              nsresult* aRv)
+GMPServiceParent::RecvSelectGMP(const nsCString& aNodeId,
+                                const nsCString& aAPI,
+                                nsTArray<nsCString>&& aTags,
+                                uint32_t* aOutPluginId,
+                                nsresult* aOutRv)
 {
-  *aRv = NS_OK;
   if (mService->IsShuttingDown()) {
-    *aRv = NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
+    *aOutRv = NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
     return true;
   }
 
   RefPtr<GMPParent> gmp = mService->SelectPluginForAPI(aNodeId, aAPI, aTags);
+  if (gmp) {
+    *aOutPluginId = gmp->GetPluginId();
+    *aOutRv = NS_OK;
+  } else {
+    *aOutRv = NS_ERROR_FAILURE;
+  }
 
   nsCString api = aTags[0];
   LOGD(("%s: %p returning %p for api %s", __FUNCTION__, (void *)this, (void *)gmp, api.get()));
 
-  if (!gmp || !gmp->EnsureProcessLoaded(aId)) {
+  return true;
+}
+
+bool
+GMPServiceParent::RecvLaunchGMP(const uint32_t& aPluginId,
+                                nsTArray<ProcessId>&& aAlreadyBridgedTo,
+                                ProcessId* aOutProcessId,
+                                nsCString* aOutDisplayName,
+                                nsresult* aOutRv)
+{
+  *aOutRv = NS_OK;
+  if (mService->IsShuttingDown()) {
+    *aOutRv = NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
+    return true;
+  }
+
+  RefPtr<GMPParent> gmp(mService->GetById(aPluginId));
+  if (!gmp) {
+    *aOutRv = NS_ERROR_FAILURE;
+    return true;
+  }
+
+  if (!gmp->EnsureProcessLoaded(aOutProcessId)) {
     return false;
   }
 
-  *aDisplayName = gmp->GetDisplayName();
-  *aPluginId = gmp->GetPluginId();
+  *aOutDisplayName = gmp->GetDisplayName();
 
-  return aAlreadyBridgedTo.Contains(*aId) || gmp->Bridge(this);
+  return aAlreadyBridgedTo.Contains(*aOutProcessId) || gmp->Bridge(this);
 }
 
 bool
 GMPServiceParent::RecvGetGMPNodeId(const nsString& aOrigin,
                                    const nsString& aTopLevelOrigin,
                                    const nsString& aGMPName,
                                    const bool& aInPrivateBrowsing,
                                    nsCString* aID)
--- a/dom/media/gmp/GMPServiceParent.h
+++ b/dom/media/gmp/GMPServiceParent.h
@@ -101,16 +101,18 @@ private:
     ~DirectoryFilter() {}
   };
   void ClearNodeIdAndPlugin(DirectoryFilter& aFilter);
   void ClearNodeIdAndPlugin(nsIFile* aPluginStorageDir,
                             DirectoryFilter& aFilter);
   void ForgetThisSiteOnGMPThread(const nsACString& aOrigin);
   void ClearRecentHistoryOnGMPThread(PRTime aSince);
 
+  already_AddRefed<GMPParent> GetById(uint32_t aPluginId);
+
 protected:
   friend class GMPParent;
   void ReAddOnGMPThread(const RefPtr<GMPParent>& aOld);
   void PluginTerminated(const RefPtr<GMPParent>& aOld);
   void InitializePlugins(AbstractThread* aAbstractGMPThread) override;
   RefPtr<GenericPromise::AllPromiseType> LoadFromEnvironment();
   RefPtr<GenericPromise> AddOnGMPThread(nsString aDirectory);
   bool GetContentParentFrom(const nsACString& aNodeId,
@@ -220,37 +222,41 @@ class GMPServiceParent final : public PG
 {
 public:
   explicit GMPServiceParent(GeckoMediaPluginServiceParent* aService)
     : mService(aService)
   {
   }
   virtual ~GMPServiceParent();
 
-  bool RecvLoadGMP(const nsCString& aNodeId,
-                   const nsCString& aApi,
-                   nsTArray<nsCString>&& aTags,
-                   nsTArray<ProcessId>&& aAlreadyBridgedTo,
-                   base::ProcessId* aID,
-                   nsCString* aDisplayName,
-                   uint32_t* aPluginId,
-                   nsresult* aRv) override;
   bool RecvGetGMPNodeId(const nsString& aOrigin,
                         const nsString& aTopLevelOrigin,
                         const nsString& aGMPName,
                         const bool& aInPrivateBrowsing,
                         nsCString* aID) override;
   static bool RecvGetGMPPluginVersionForAPI(const nsCString& aAPI,
                                             nsTArray<nsCString>&& aTags,
                                             bool* aHasPlugin,
                                             nsCString* aVersion);
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
   static PGMPServiceParent* Create(Transport* aTransport, ProcessId aOtherPid);
 
+  bool RecvSelectGMP(const nsCString& aNodeId,
+                     const nsCString& aAPI,
+                     nsTArray<nsCString>&& aTags,
+                     uint32_t* aOutPluginId,
+                     nsresult* aOutRv) override;
+
+  bool RecvLaunchGMP(const uint32_t& aPluginId,
+                     nsTArray<ProcessId>&& aAlreadyBridgedTo,
+                     ProcessId* aOutID,
+                     nsCString* aOutDisplayName,
+                     nsresult* aOutRv) override;
+
 private:
   RefPtr<GeckoMediaPluginServiceParent> mService;
 };
 
 } // namespace gmp
 } // namespace mozilla
 
 #endif // GMPServiceParent_h_
--- a/dom/media/gmp/PGMPService.ipdl
+++ b/dom/media/gmp/PGMPService.ipdl
@@ -10,20 +10,23 @@ using base::ProcessId from "base/process
 namespace mozilla {
 namespace gmp {
 
 sync protocol PGMPService
 {
   parent spawns PGMP as child;
 
 parent:
-  sync LoadGMP(nsCString nodeId, nsCString api, nsCString[] tags,
-               ProcessId[] alreadyBridgedTo)
-    returns (ProcessId id, nsCString displayName, uint32_t pluginId,
-             nsresult aResult);
+
+  sync SelectGMP(nsCString nodeId, nsCString api, nsCString[] tags)
+    returns (uint32_t pluginId, nsresult aResult);
+
+  sync LaunchGMP(uint32_t pluginId, ProcessId[] alreadyBridgedTo)
+    returns (ProcessId id, nsCString displayName, nsresult aResult);
+
   sync GetGMPNodeId(nsString origin, nsString topLevelOrigin,
                     nsString gmpName,
                     bool inPrivateBrowsing)
     returns (nsCString id);
 };
 
 } // namespace gmp
 } // namespace mozilla