Bug 1156560 - Prefer old CDMs on update if they are in use - r=cpearce
authorEdwin Flores <eflores@mozilla.com>
Wed, 22 Apr 2015 10:22:23 +1200
changeset 240412 cefce495a0bf20e2a0304dc62bc762ec2ee39166
parent 240411 ec68bf489da0c0ed640cce5f38c40513cc0b3c31
child 240413 c30371e57ddf4a5d8f0b62abaa11f0431756cacc
push id28636
push userkwierso@gmail.com
push dateThu, 23 Apr 2015 00:16:12 +0000
treeherdermozilla-central@a5af73b32ac8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs1156560
milestone40.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 1156560 - Prefer old CDMs on update if they are in use - r=cpearce
dom/media/eme/CDMProxy.cpp
dom/media/eme/CDMProxy.h
dom/media/gmp/GMPServiceChild.cpp
dom/media/gmp/GMPServiceChild.h
dom/media/gmp/GMPServiceParent.cpp
dom/media/gmp/GMPServiceParent.h
dom/media/gmp/PGMPService.ipdl
dom/media/gmp/mozIGeckoMediaPluginService.idl
dom/media/gtest/TestGMPCrossOrigin.cpp
--- a/dom/media/eme/CDMProxy.cpp
+++ b/dom/media/eme/CDMProxy.cpp
@@ -59,29 +59,22 @@ CDMProxy::Init(PromiseId aPromiseId,
       RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
       return;
     }
     mps->GetThread(getter_AddRefs(mGMPThread));
     if (!mGMPThread) {
       RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
       return;
     }
-    bool hasPlugin;
-    nsTArray<nsCString> tags;
-    tags.AppendElement(NS_ConvertUTF16toUTF8(mKeySystem));
-    nsresult rv = mps->GetPluginVersionForAPI(NS_LITERAL_CSTRING(GMP_API_DECRYPTOR),
-                                              &tags, &hasPlugin, pluginVersion);
-    NS_ENSURE_SUCCESS_VOID(rv);
   }
 
   nsAutoPtr<InitData> data(new InitData());
   data->mPromiseId = aPromiseId;
   data->mOrigin = aOrigin;
   data->mTopLevelOrigin = aTopLevelOrigin;
-  data->mPluginVersion = pluginVersion;
   data->mInPrivateBrowsing = aInPrivateBrowsing;
   nsCOMPtr<nsIRunnable> task(
     NS_NewRunnableMethodWithArg<nsAutoPtr<InitData>>(this,
                                                      &CDMProxy::gmp_Init,
                                                      Move(data)));
   mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
 }
 
@@ -170,17 +163,16 @@ CDMProxy::gmp_Init(nsAutoPtr<InitData>&&
   // Make a copy before we transfer ownership of aData to the
   // gmp_InitGetGMPDecryptorCallback.
   InitData data(*aData);
   UniquePtr<GetNodeIdCallback> callback(
     new gmp_InitGetGMPDecryptorCallback(this, Move(aData)));
   nsresult rv = mps->GetNodeId(data.mOrigin,
                                data.mTopLevelOrigin,
                                data.mInPrivateBrowsing,
-                               data.mPluginVersion,
                                Move(callback));
   if (NS_FAILED(rv)) {
     RejectPromise(data.mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
   }
 }
 
 void
 CDMProxy::gmp_InitGetGMPDecryptor(nsresult aResult,
--- a/dom/media/eme/CDMProxy.h
+++ b/dom/media/eme/CDMProxy.h
@@ -176,17 +176,16 @@ public:
 private:
   friend class gmp_InitDoneCallback;
   friend class gmp_InitGetGMPDecryptorCallback;
 
   struct InitData {
     uint32_t mPromiseId;
     nsAutoString mOrigin;
     nsAutoString mTopLevelOrigin;
-    nsAutoCString mPluginVersion;
     bool mInPrivateBrowsing;
   };
 
   // GMP thread only.
   void gmp_Init(nsAutoPtr<InitData>&& aData);
   void gmp_InitDone(GMPDecryptorProxy* aCDM, nsAutoPtr<InitData>&& aData);
   void gmp_InitGetGMPDecryptor(nsresult aResult,
                                const nsACString& aNodeId,
--- a/dom/media/gmp/GMPServiceChild.cpp
+++ b/dom/media/gmp/GMPServiceChild.cpp
@@ -143,62 +143,56 @@ GeckoMediaPluginServiceChild::GetPluginV
   aOutVersion = version;
   return ok ? NS_OK : NS_ERROR_FAILURE;
 }
 
 class GetNodeIdDone : public GetServiceChildCallback
 {
 public:
   GetNodeIdDone(const nsAString& aOrigin, const nsAString& aTopLevelOrigin,
-                bool aInPrivateBrowsing, const nsACString& aVersion,
-                UniquePtr<GetNodeIdCallback>&& aCallback)
+                bool aInPrivateBrowsing, UniquePtr<GetNodeIdCallback>&& aCallback)
     : mOrigin(aOrigin),
       mTopLevelOrigin(aTopLevelOrigin),
       mInPrivateBrowsing(aInPrivateBrowsing),
-      mVersion(aVersion),
       mCallback(Move(aCallback))
   {
   }
 
   virtual void Done(GMPServiceChild* aGMPServiceChild)
   {
     if (!aGMPServiceChild) {
       mCallback->Done(NS_ERROR_FAILURE, EmptyCString());
       return;
     }
 
     nsCString outId;
     if (!aGMPServiceChild->SendGetGMPNodeId(mOrigin, mTopLevelOrigin,
-                                            mInPrivateBrowsing, mVersion,
-                                            &outId)) {
+                                            mInPrivateBrowsing, &outId)) {
       mCallback->Done(NS_ERROR_FAILURE, EmptyCString());
       return;
     }
 
     mCallback->Done(NS_OK, outId);
   }
 
 private:
   nsString mOrigin;
   nsString mTopLevelOrigin;
   bool mInPrivateBrowsing;
-  nsCString mVersion;
   UniquePtr<GetNodeIdCallback> mCallback;
 };
 
 NS_IMETHODIMP
 GeckoMediaPluginServiceChild::GetNodeId(const nsAString& aOrigin,
                                         const nsAString& aTopLevelOrigin,
                                         bool aInPrivateBrowsing,
-                                        const nsACString& aVersion,
                                         UniquePtr<GetNodeIdCallback>&& aCallback)
 {
   UniquePtr<GetServiceChildCallback> callback(
-    new GetNodeIdDone(aOrigin, aTopLevelOrigin, aInPrivateBrowsing, aVersion,
-                      Move(aCallback)));
+    new GetNodeIdDone(aOrigin, aTopLevelOrigin, aInPrivateBrowsing, Move(aCallback)));
   GetServiceChild(Move(callback));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 GeckoMediaPluginServiceChild::Observe(nsISupports* aSubject,
                                       const char* aTopic,
                                       const char16_t* aSomeData)
--- a/dom/media/gmp/GMPServiceChild.h
+++ b/dom/media/gmp/GMPServiceChild.h
@@ -29,17 +29,16 @@ public:
 
   NS_IMETHOD GetPluginVersionForAPI(const nsACString& aAPI,
                                     nsTArray<nsCString>* aTags,
                                     bool* aHasPlugin,
                                     nsACString& aOutVersion) override;
   NS_IMETHOD GetNodeId(const nsAString& aOrigin,
                        const nsAString& aTopLevelOrigin,
                        bool aInPrivateBrowsingMode,
-                       const nsACString& aVersion,
                        UniquePtr<GetNodeIdCallback>&& aCallback) override;
 
   NS_DECL_NSIOBSERVER
 
   void SetServiceChild(UniquePtr<GMPServiceChild>&& aServiceChild);
 
   void RemoveGMPContentParent(GMPContentParent* aGMPContentParent);
 
--- a/dom/media/gmp/GMPServiceParent.cpp
+++ b/dom/media/gmp/GMPServiceParent.cpp
@@ -579,19 +579,27 @@ GeckoMediaPluginServiceParent::SelectPlu
           return gmp;
         }
       } else if (gmp->CanBeUsedFrom(aNodeId)) {
         MOZ_ASSERT(!aNodeId.IsEmpty());
         gmp->SetNodeId(aNodeId);
         return gmp;
       }
 
-      // This GMP has the correct type but has the wrong nodeId; hold on to it
-      // in case we need to clone it.
-      gmpToClone = gmp;
+      if (!gmpToClone ||
+          (gmpToClone->IsMarkedForDeletion() && !gmp->IsMarkedForDeletion())) {
+        // This GMP has the correct type but has the wrong nodeId; hold on to it
+        // in case we need to clone it.
+        // Prefer GMPs in-use for the case where an upgraded plugin version is
+        // waiting for the old one to die. If the old plugin is in use, we
+        // should continue using it so that any persistent state remains
+        // consistent. Otherwise, just check that the plugin isn't scheduled
+        // for deletion.
+        gmpToClone = gmp;
+      }
       // Loop around and try the next plugin; it may be usable from aNodeId.
       index++;
     }
   }
 
   // Plugin exists, but we can't use it due to cross-origin separation. Create a
   // new one.
   if (gmpToClone) {
@@ -907,17 +915,16 @@ GeckoMediaPluginServiceParent::IsPersist
   *aOutAllowed = mPersistentStorageAllowed.Get(aNodeId);
   return NS_OK;
 }
 
 nsresult
 GeckoMediaPluginServiceParent::GetNodeId(const nsAString& aOrigin,
                                          const nsAString& aTopLevelOrigin,
                                          bool aInPrivateBrowsing,
-                                         const nsACString& aVersion,
                                          nsACString& aOutId)
 {
   MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
   LOGD(("%s::%s: (%s, %s), %s", __CLASS__, __FUNCTION__,
        NS_ConvertUTF16toUTF8(aOrigin).get(),
        NS_ConvertUTF16toUTF8(aTopLevelOrigin).get(),
        (aInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing")));
 
@@ -936,18 +943,17 @@ GeckoMediaPluginServiceParent::GetNodeId
       return rv;
     }
     aOutId = salt;
     mPersistentStorageAllowed.Put(salt, false);
     return NS_OK;
   }
 
   const uint32_t hash = AddToHash(HashString(aOrigin),
-                                  HashString(aTopLevelOrigin),
-                                  HashString(aVersion));
+                                  HashString(aTopLevelOrigin));
 
   if (aInPrivateBrowsing) {
     // For PB mode, we store the node id, indexed by the origin pair,
     // so that if the same origin pair is opened in this session, it gets
     // the same node id.
     nsCString* salt = nullptr;
     if (!(salt = mTempNodeIds.Get(hash))) {
       // No salt stored, generate and temporarily store some for this id.
@@ -1057,21 +1063,20 @@ GeckoMediaPluginServiceParent::GetNodeId
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 GeckoMediaPluginServiceParent::GetNodeId(const nsAString& aOrigin,
                                          const nsAString& aTopLevelOrigin,
                                          bool aInPrivateBrowsing,
-                                         const nsACString& aVersion,
                                          UniquePtr<GetNodeIdCallback>&& aCallback)
 {
   nsCString nodeId;
-  nsresult rv = GetNodeId(aOrigin, aTopLevelOrigin, aInPrivateBrowsing, aVersion, nodeId);
+  nsresult rv = GetNodeId(aOrigin, aTopLevelOrigin, aInPrivateBrowsing, nodeId);
   aCallback->Done(rv, nodeId);
   return rv;
 }
 
 static bool
 ExtractHostName(const nsACString& aOrigin, nsACString& aOutData)
 {
   nsCString str;
@@ -1430,21 +1435,20 @@ GMPServiceParent::RecvLoadGMP(const nsCS
 
   return aAlreadyBridgedTo.Contains(*aId) || gmp->Bridge(this);
 }
 
 bool
 GMPServiceParent::RecvGetGMPNodeId(const nsString& aOrigin,
                                    const nsString& aTopLevelOrigin,
                                    const bool& aInPrivateBrowsing,
-                                   const nsCString& aVersion,
                                    nsCString* aID)
 {
   nsresult rv = mService->GetNodeId(aOrigin, aTopLevelOrigin,
-                                    aInPrivateBrowsing, aVersion, *aID);
+                                    aInPrivateBrowsing, *aID);
   return NS_SUCCEEDED(rv);
 }
 
 /* static */
 bool
 GMPServiceParent::RecvGetGMPPluginVersionForAPI(const nsCString& aAPI,
                                                 nsTArray<nsCString>&& aTags,
                                                 bool* aHasPlugin,
--- a/dom/media/gmp/GMPServiceParent.h
+++ b/dom/media/gmp/GMPServiceParent.h
@@ -37,17 +37,16 @@ public:
   // mozIGeckoMediaPluginService
   NS_IMETHOD GetPluginVersionForAPI(const nsACString& aAPI,
                                     nsTArray<nsCString>* aTags,
                                     bool* aHasPlugin,
                                     nsACString& aOutVersion) override;
   NS_IMETHOD GetNodeId(const nsAString& aOrigin,
                        const nsAString& aTopLevelOrigin,
                        bool aInPrivateBrowsingMode,
-                       const nsACString& aVersion,
                        UniquePtr<GetNodeIdCallback>&& aCallback) override;
 
   NS_DECL_MOZIGECKOMEDIAPLUGINCHROMESERVICE
   NS_DECL_NSIOBSERVER
 
   void AsyncShutdownNeeded(GMPParent* aParent);
   void AsyncShutdownComplete(GMPParent* aParent);
   void AbortAsyncShutdown();
@@ -65,18 +64,17 @@ private:
                                 const nsCString& aAPI,
                                 const nsTArray<nsCString>& aTags);
   GMPParent* FindPluginForAPIFrom(size_t aSearchStartIndex,
                                   const nsCString& aAPI,
                                   const nsTArray<nsCString>& aTags,
                                   size_t* aOutPluginIndex);
 
   nsresult GetNodeId(const nsAString& aOrigin, const nsAString& aTopLevelOrigin,
-                     bool aInPrivateBrowsing, const nsACString& aVersion,
-                     nsACString& aOutId);
+                     bool aInPrivateBrowsing, nsACString& aOutId);
 
   void UnloadPlugins();
   void CrashPlugins();
   void SetAsyncShutdownComplete();
 
   void LoadFromEnvironment();
   void ProcessPossiblePlugin(nsIFile* aDir);
 
@@ -194,17 +192,16 @@ public:
                            nsTArray<nsCString>&& aTags,
                            nsTArray<ProcessId>&& aAlreadyBridgedTo,
                            base::ProcessId* aID,
                            nsCString* aDisplayName,
                            nsCString* aPluginId) override;
   virtual bool RecvGetGMPNodeId(const nsString& aOrigin,
                                 const nsString& aTopLevelOrigin,
                                 const bool& aInPrivateBrowsing,
-                                const nsCString& aVersion,
                                 nsCString* aID) override;
   static bool RecvGetGMPPluginVersionForAPI(const nsCString& aAPI,
                                             nsTArray<nsCString>&& aTags,
                                             bool* aHasPlugin,
                                             nsCString* aVersion);
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
--- a/dom/media/gmp/PGMPService.ipdl
+++ b/dom/media/gmp/PGMPService.ipdl
@@ -14,14 +14,14 @@ sync protocol PGMPService
 {
   parent spawns PGMP as child;
 
 parent:
   sync LoadGMP(nsCString nodeId, nsCString api, nsCString[] tags,
                ProcessId[] alreadyBridgedTo)
     returns (ProcessId id, nsCString displayName, nsCString pluginId);
   sync GetGMPNodeId(nsString origin, nsString topLevelOrigin,
-                    bool inPrivateBrowsing, nsCString version)
+                    bool inPrivateBrowsing)
     returns (nsCString id);
 };
 
 } // namespace gmp
 } // namespace mozilla
--- a/dom/media/gmp/mozIGeckoMediaPluginService.idl
+++ b/dom/media/gmp/mozIGeckoMediaPluginService.idl
@@ -47,17 +47,17 @@ public:
 
 [ptr] native TagArray(nsTArray<nsCString>);
 native GetGMPDecryptorCallback(mozilla::UniquePtr<GetGMPDecryptorCallback>&&);
 native GetGMPAudioDecoderCallback(mozilla::UniquePtr<GetGMPAudioDecoderCallback>&&);
 native GetGMPVideoDecoderCallback(mozilla::UniquePtr<GetGMPVideoDecoderCallback>&&);
 native GetGMPVideoEncoderCallback(mozilla::UniquePtr<GetGMPVideoEncoderCallback>&&);
 native GetNodeIdCallback(mozilla::UniquePtr<GetNodeIdCallback>&&);
 
-[scriptable, uuid(6e3023f4-d9a2-46b4-8f50-70d4c918471d)]
+[scriptable, uuid(787cf744-eea8-48c8-b692-376e0485ef97)]
 interface mozIGeckoMediaPluginService : nsISupports
 {
 
   /**
    * The GMP thread. Callable from any thread.
    */
   readonly attribute nsIThread thread;
 
@@ -141,11 +141,10 @@ interface mozIGeckoMediaPluginService : 
 
   /**
    * Gets the NodeId for a (origin, urlbarOrigin, isInprivateBrowsing) tuple.
    */
   [noscript]
   void getNodeId(in AString origin,
                  in AString topLevelOrigin,
                  in bool inPrivateBrowsingMode,
-                 in ACString version,
                  in GetNodeIdCallback callback);
 };
--- a/dom/media/gtest/TestGMPCrossOrigin.cpp
+++ b/dom/media/gtest/TestGMPCrossOrigin.cpp
@@ -492,17 +492,16 @@ GetNodeId(const nsAString& aOrigin,
   nsresult result;
   UniquePtr<GetNodeIdCallback> callback(new TestGetNodeIdCallback(nodeId,
                                                                   result));
   // We rely on the fact that the GetNodeId implementation for
   // GeckoMediaPluginServiceParent is synchronous.
   nsresult rv = service->GetNodeId(aOrigin,
                                    aTopLevelOrigin,
                                    aInPBMode,
-                                   NS_LITERAL_CSTRING(""),
                                    Move(callback));
   EXPECT_TRUE(NS_SUCCEEDED(rv) && NS_SUCCEEDED(result));
   return nodeId;
 }
 
 static bool
 IsGMPStorageIsEmpty()
 {