Bug 1263951 - Avoid trying to initialize new GMP instances once the browser enters shutdown. r=cpearce a=lizzard
authorJim Mathies <jmathies@mozilla.com>
Tue, 26 Apr 2016 12:11:26 -0500
changeset 332748 61a1435b8d611a196110354410e05c6c2171c661
parent 332747 f5c86d60a78970259891ca29ae1a4d0adbf24e56
child 332749 ab4a17a4d9d6c9fae18446c6292acf12c9fb6865
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce, lizzard
bugs1263951
milestone48.0a2
Bug 1263951 - Avoid trying to initialize new GMP instances once the browser enters shutdown. r=cpearce a=lizzard MozReview-Commit-ID: G6ND2LyT0tp
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
@@ -67,20 +67,21 @@ public:
     }
 
     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);
-    if (!ok) {
+                                            &displayName, &pluginId, &rv);
+    if (!ok && rv == NS_ERROR_ILLEGAL_DURING_SHUTDOWN) {
       mCallback->Done(nullptr);
       return;
     }
 
     RefPtr<GMPContentParent> parent;
     aGMPServiceChild->GetBridgedGMPContentParent(otherProcess,
                                                  getter_AddRefs(parent));
     if (!alreadyBridgedTo.Contains(otherProcess)) {
--- a/dom/media/gmp/GMPServiceParent.cpp
+++ b/dom/media/gmp/GMPServiceParent.cpp
@@ -680,16 +680,23 @@ GeckoMediaPluginServiceParent::NotifyAsy
 
 void
 GeckoMediaPluginServiceParent::NotifySyncShutdownComplete()
 {
   MOZ_ASSERT(NS_IsMainThread());
   mWaitingForPluginsSyncShutdown = false;
 }
 
+bool
+GeckoMediaPluginServiceParent::IsShuttingDown()
+{
+  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+  return mShuttingDownOnGMPThread;
+}
+
 void
 GeckoMediaPluginServiceParent::UnloadPlugins()
 {
   MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
   MOZ_ASSERT(!mShuttingDownOnGMPThread);
   mShuttingDownOnGMPThread = true;
 #ifdef MOZ_CRASHREPORTER
       SetAsyncShutdownPluginState(nullptr, '2',
@@ -1785,18 +1792,25 @@ GMPServiceParent::~GMPServiceParent()
 
 bool
 GMPServiceParent::RecvLoadGMP(const nsCString& aNodeId,
                               const nsCString& aAPI,
                               nsTArray<nsCString>&& aTags,
                               nsTArray<ProcessId>&& aAlreadyBridgedTo,
                               ProcessId* aId,
                               nsCString* aDisplayName,
-                              uint32_t* aPluginId)
+                              uint32_t* aPluginId,
+                              nsresult* aRv)
 {
+  *aRv = NS_OK;
+  if (mService->IsShuttingDown()) {
+    *aRv = NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
+    return true;
+  }
+
   RefPtr<GMPParent> gmp = mService->SelectPluginForAPI(aNodeId, aAPI, aTags);
 
   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 false;
   }
--- a/dom/media/gmp/GMPServiceParent.h
+++ b/dom/media/gmp/GMPServiceParent.h
@@ -54,16 +54,19 @@ public:
 
   int32_t AsyncShutdownTimeoutMs();
 #ifdef MOZ_CRASHREPORTER
   void SetAsyncShutdownPluginState(GMPParent* aGMPParent, char aId, const nsCString& aState);
 #endif // MOZ_CRASHREPORTER
   RefPtr<GenericPromise> EnsureInitialized();
   RefPtr<GenericPromise> AsyncAddPluginDirectory(const nsAString& aDirectory);
 
+  // GMP thread access only
+  bool IsShuttingDown();
+
 private:
   friend class GMPServiceParent;
 
   virtual ~GeckoMediaPluginServiceParent();
 
   void ClearStorage();
 
   GMPParent* SelectPluginForAPI(const nsACString& aNodeId,
@@ -216,17 +219,18 @@ public:
   virtual ~GMPServiceParent();
 
   bool RecvLoadGMP(const nsCString& aNodeId,
                    const nsCString& aApi,
                    nsTArray<nsCString>&& aTags,
                    nsTArray<ProcessId>&& aAlreadyBridgedTo,
                    base::ProcessId* aID,
                    nsCString* aDisplayName,
-                   uint32_t* aPluginId) override;
+                   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,
--- a/dom/media/gmp/PGMPService.ipdl
+++ b/dom/media/gmp/PGMPService.ipdl
@@ -12,17 +12,18 @@ 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);
+    returns (ProcessId id, nsCString displayName, uint32_t pluginId,
+             nsresult aResult);
   sync GetGMPNodeId(nsString origin, nsString topLevelOrigin,
                     nsString gmpName,
                     bool inPrivateBrowsing)
     returns (nsCString id);
 };
 
 } // namespace gmp
 } // namespace mozilla