Bug 1228215 - Add a 'gmpName' parameter to GMPService::GetNodeId(), so each GMP can see a different nodeId for the same origin. r=jwwang
authorChris Pearce <cpearce@mozilla.com>
Fri, 27 Nov 2015 10:53:31 +1300
changeset 308541 eabac8a5315b3d319089cfbce6cf09f18ce8f02c
parent 308540 11ede1cca0069fb3bfb8164ec3ada4a54fb4e7a4
child 308542 584678105c1476f5276f8723681604ecea06d583
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwwang
bugs1228215
milestone45.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 1228215 - Add a 'gmpName' parameter to GMPService::GetNodeId(), so each GMP can see a different nodeId for the same origin. r=jwwang
dom/media/eme/CDMProxy.cpp
dom/media/eme/CDMProxy.h
dom/media/eme/EMEUtils.cpp
dom/media/eme/EMEUtils.h
dom/media/eme/MediaKeys.cpp
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
@@ -13,16 +13,17 @@
 #include "nsServiceManagerUtils.h"
 #include "MainThreadUtils.h"
 #include "mozilla/EMEUtils.h"
 #include "nsIConsoleService.h"
 #include "prenv.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/CDMCallbackProxy.h"
 #include "MediaData.h"
+#include "nsPrintfCString.h"
 
 namespace mozilla {
 
 CDMProxy::CDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem)
   : mKeys(aKeys)
   , mKeySystem(aKeySystem)
   , mCDM(nullptr)
   , mDecryptionJobCount(0)
@@ -36,16 +37,17 @@ CDMProxy::~CDMProxy()
 {
   MOZ_COUNT_DTOR(CDMProxy);
 }
 
 void
 CDMProxy::Init(PromiseId aPromiseId,
                const nsAString& aOrigin,
                const nsAString& aTopLevelOrigin,
+               const nsAString& aGMPName,
                bool aInPrivateBrowsing)
 {
   MOZ_ASSERT(NS_IsMainThread());
   NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
 
   EME_LOG("CDMProxy::Init (%s, %s) %s",
           NS_ConvertUTF16toUTF8(aOrigin).get(),
           NS_ConvertUTF16toUTF8(aTopLevelOrigin).get(),
@@ -63,20 +65,27 @@ CDMProxy::Init(PromiseId aPromiseId,
     mps->GetThread(getter_AddRefs(mGMPThread));
     if (!mGMPThread) {
       RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
                     NS_LITERAL_CSTRING("Couldn't get GMP thread CDMProxy::Init"));
       return;
     }
   }
 
+  if (aGMPName.IsEmpty()) {
+    RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
+      nsPrintfCString("Unknown GMP for keysystem '%s'", NS_ConvertUTF16toUTF8(mKeySystem).get()));
+    return;
+  }
+
   nsAutoPtr<InitData> data(new InitData());
   data->mPromiseId = aPromiseId;
   data->mOrigin = aOrigin;
   data->mTopLevelOrigin = aTopLevelOrigin;
+  data->mGMPName = aGMPName;
   data->mInPrivateBrowsing = aInPrivateBrowsing;
   nsCOMPtr<nsIRunnable> task(
     NS_NewRunnableMethodWithArg<nsAutoPtr<InitData>>(this,
                                                      &CDMProxy::gmp_Init,
                                                      Move(data)));
   mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
 }
 
@@ -171,16 +180,17 @@ 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.mGMPName,
                                data.mInPrivateBrowsing,
                                Move(callback));
   if (NS_FAILED(rv)) {
     RejectPromise(data.mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
                   NS_LITERAL_CSTRING("Call to GetNodeId() failed early"));
   }
 }
 
--- a/dom/media/eme/CDMProxy.h
+++ b/dom/media/eme/CDMProxy.h
@@ -52,16 +52,17 @@ public:
   CDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem);
 
   // Main thread only.
   // Loads the CDM corresponding to mKeySystem.
   // Calls MediaKeys::OnCDMCreated() when the CDM is created.
   void Init(PromiseId aPromiseId,
             const nsAString& aOrigin,
             const nsAString& aTopLevelOrigin,
+            const nsAString& aGMPName,
             bool aInPrivateBrowsing);
 
   // Main thread only.
   // Uses the CDM to create a key session.
   // Calls MediaKeys::OnSessionActivated() when session is created.
   // Assumes ownership of (Move()s) aInitData's contents.
   void CreateSession(uint32_t aCreateSessionToken,
                      dom::SessionType aSessionType,
@@ -181,16 +182,17 @@ public:
 private:
   friend class gmp_InitDoneCallback;
   friend class gmp_InitGetGMPDecryptorCallback;
 
   struct InitData {
     uint32_t mPromiseId;
     nsAutoString mOrigin;
     nsAutoString mTopLevelOrigin;
+    nsString mGMPName;
     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/eme/EMEUtils.cpp
+++ b/dom/media/eme/EMEUtils.cpp
@@ -136,9 +136,22 @@ CopyArrayBufferViewOrArrayBufferData(con
   ArrayData data = GetArrayBufferViewOrArrayBufferData(aBufferOrView);
   aOutData.Clear();
   if (!data.IsValid()) {
     return;
   }
   aOutData.AppendElements(data.mData, data.mLength);
 }
 
+nsString
+KeySystemToGMPName(const nsAString& aKeySystem)
+{
+  if (aKeySystem.EqualsLiteral("com.adobe.primetime")) {
+    return NS_LITERAL_STRING("gmp-eme-adobe");
+  }
+  if (aKeySystem.EqualsLiteral("org.w3.clearkey")) {
+    return NS_LITERAL_STRING("gmp-clearkey");
+  }
+  MOZ_ASSERT(false, "We should only call this for known GMPs");
+  return EmptyString();
+}
+
 } // namespace mozilla
--- a/dom/media/eme/EMEUtils.h
+++ b/dom/media/eme/EMEUtils.h
@@ -99,11 +99,14 @@ struct ArrayData {
 // while the ArrayData is live, as then all bets about the data not changing
 // are off! No calls into JS, no calls into JS-implemented WebIDL or XPIDL,
 // nothing. Beware!
 //
 // Only call this on a properly initialized ArrayBufferViewOrArrayBuffer.
 ArrayData
 GetArrayBufferViewOrArrayBufferData(const dom::ArrayBufferViewOrArrayBuffer& aBufferOrView);
 
+nsString
+KeySystemToGMPName(const nsAString& aKeySystem);
+
 } // namespace mozilla
 
 #endif // EME_LOG_H_
--- a/dom/media/eme/MediaKeys.cpp
+++ b/dom/media/eme/MediaKeys.cpp
@@ -363,16 +363,17 @@ MediaKeys::Init(ErrorResult& aRv)
   // here, and hold a self-reference until that promise is resolved or
   // rejected.
   MOZ_ASSERT(!mCreatePromiseId, "Should only be created once!");
   mCreatePromiseId = StorePromise(promise);
   AddRef();
   mProxy->Init(mCreatePromiseId,
                origin,
                topLevelOrigin,
+               KeySystemToGMPName(mKeySystem),
                inPrivateBrowsing);
 
   return promise.forget();
 }
 
 void
 MediaKeys::OnCDMCreated(PromiseId aId, const nsACString& aNodeId, const uint32_t aPluginId)
 {
--- a/dom/media/gmp/GMPServiceChild.cpp
+++ b/dom/media/gmp/GMPServiceChild.cpp
@@ -132,56 +132,61 @@ GeckoMediaPluginServiceChild::GetPluginV
   aOutVersion = version;
   return ok ? NS_OK : NS_ERROR_FAILURE;
 }
 
 class GetNodeIdDone : public GetServiceChildCallback
 {
 public:
   GetNodeIdDone(const nsAString& aOrigin, const nsAString& aTopLevelOrigin,
+                const nsAString& aGMPName,
                 bool aInPrivateBrowsing, UniquePtr<GetNodeIdCallback>&& aCallback)
     : mOrigin(aOrigin),
       mTopLevelOrigin(aTopLevelOrigin),
+      mGMPName(aGMPName),
       mInPrivateBrowsing(aInPrivateBrowsing),
       mCallback(Move(aCallback))
   {
   }
 
   virtual void Done(GMPServiceChild* aGMPServiceChild)
   {
     if (!aGMPServiceChild) {
       mCallback->Done(NS_ERROR_FAILURE, EmptyCString());
       return;
     }
 
     nsCString outId;
     if (!aGMPServiceChild->SendGetGMPNodeId(mOrigin, mTopLevelOrigin,
+                                            mGMPName,
                                             mInPrivateBrowsing, &outId)) {
       mCallback->Done(NS_ERROR_FAILURE, EmptyCString());
       return;
     }
 
     mCallback->Done(NS_OK, outId);
   }
 
 private:
   nsString mOrigin;
   nsString mTopLevelOrigin;
+  nsString mGMPName;
   bool mInPrivateBrowsing;
   UniquePtr<GetNodeIdCallback> mCallback;
 };
 
 NS_IMETHODIMP
 GeckoMediaPluginServiceChild::GetNodeId(const nsAString& aOrigin,
                                         const nsAString& aTopLevelOrigin,
+                                        const nsAString& aGMPName,
                                         bool aInPrivateBrowsing,
                                         UniquePtr<GetNodeIdCallback>&& aCallback)
 {
   UniquePtr<GetServiceChildCallback> callback(
-    new GetNodeIdDone(aOrigin, aTopLevelOrigin, aInPrivateBrowsing, Move(aCallback)));
+    new GetNodeIdDone(aOrigin, aTopLevelOrigin, aGMPName, aInPrivateBrowsing, Move(aCallback)));
   GetServiceChild(Move(callback));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 GeckoMediaPluginServiceChild::UpdateTrialCreateState(const nsAString& aKeySystem,
                                                      uint32_t aState)
 {
--- a/dom/media/gmp/GMPServiceChild.h
+++ b/dom/media/gmp/GMPServiceChild.h
@@ -42,16 +42,17 @@ public:
   static already_AddRefed<GeckoMediaPluginServiceChild> GetSingleton();
 
   NS_IMETHOD GetPluginVersionForAPI(const nsACString& aAPI,
                                     nsTArray<nsCString>* aTags,
                                     bool* aHasPlugin,
                                     nsACString& aOutVersion) override;
   NS_IMETHOD GetNodeId(const nsAString& aOrigin,
                        const nsAString& aTopLevelOrigin,
+                       const nsAString& aGMPName,
                        bool aInPrivateBrowsingMode,
                        UniquePtr<GetNodeIdCallback>&& aCallback) override;
   NS_IMETHOD UpdateTrialCreateState(const nsAString& aKeySystem,
                                     uint32_t aState) override;
 
   NS_DECL_NSIOBSERVER
 
   void SetServiceChild(UniquePtr<GMPServiceChild>&& aServiceChild);
--- a/dom/media/gmp/GMPServiceParent.cpp
+++ b/dom/media/gmp/GMPServiceParent.cpp
@@ -1207,16 +1207,17 @@ GeckoMediaPluginServiceParent::IsPersist
   NS_ENSURE_ARG(aOutAllowed);
   *aOutAllowed = mPersistentStorageAllowed.Get(aNodeId);
   return NS_OK;
 }
 
 nsresult
 GeckoMediaPluginServiceParent::GetNodeId(const nsAString& aOrigin,
                                          const nsAString& aTopLevelOrigin,
+                                         const nsAString& aGMPName,
                                          bool aInPrivateBrowsing,
                                          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")));
@@ -1355,21 +1356,22 @@ GeckoMediaPluginServiceParent::GetNodeId
   mPersistentStorageAllowed.Put(salt, true);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 GeckoMediaPluginServiceParent::GetNodeId(const nsAString& aOrigin,
                                          const nsAString& aTopLevelOrigin,
+                                         const nsAString& aGMPName,
                                          bool aInPrivateBrowsing,
                                          UniquePtr<GetNodeIdCallback>&& aCallback)
 {
   nsCString nodeId;
-  nsresult rv = GetNodeId(aOrigin, aTopLevelOrigin, aInPrivateBrowsing, nodeId);
+  nsresult rv = GetNodeId(aOrigin, aTopLevelOrigin, aGMPName, aInPrivateBrowsing, nodeId);
   aCallback->Done(rv, nodeId);
   return rv;
 }
 
 NS_IMETHODIMP
 GeckoMediaPluginServiceParent::UpdateTrialCreateState(const nsAString& aKeySystem,
                                                       uint32_t aState)
 {
@@ -1697,20 +1699,21 @@ GMPServiceParent::RecvLoadGMP(const nsCS
   *aPluginId = gmp->GetPluginId();
 
   return aAlreadyBridgedTo.Contains(*aId) || gmp->Bridge(this);
 }
 
 bool
 GMPServiceParent::RecvGetGMPNodeId(const nsString& aOrigin,
                                    const nsString& aTopLevelOrigin,
+                                   const nsString& aGMPName,
                                    const bool& aInPrivateBrowsing,
                                    nsCString* aID)
 {
-  nsresult rv = mService->GetNodeId(aOrigin, aTopLevelOrigin,
+  nsresult rv = mService->GetNodeId(aOrigin, aTopLevelOrigin, aGMPName,
                                     aInPrivateBrowsing, *aID);
   return NS_SUCCEEDED(rv);
 }
 
 bool
 GMPServiceParent::RecvUpdateGMPTrialCreateState(const nsString& aKeySystem,
                                                 const uint32_t& aState)
 {
--- a/dom/media/gmp/GMPServiceParent.h
+++ b/dom/media/gmp/GMPServiceParent.h
@@ -36,16 +36,17 @@ 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,
+                       const nsAString& aGMPName,
                        bool aInPrivateBrowsingMode,
                        UniquePtr<GetNodeIdCallback>&& aCallback) override;
   NS_IMETHOD UpdateTrialCreateState(const nsAString& aKeySystem,
                                     uint32_t aState) override;
 
   NS_DECL_MOZIGECKOMEDIAPLUGINCHROMESERVICE
   NS_DECL_NSIOBSERVER
 
@@ -68,16 +69,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,
+                     const nsAString& aGMPName,
                      bool aInPrivateBrowsing, nsACString& aOutId);
 
   void UnloadPlugins();
   void CrashPlugins();
   void NotifySyncShutdownComplete();
   void NotifyAsyncShutdownComplete();
 
   void LoadFromEnvironment();
@@ -210,16 +212,17 @@ public:
                            const nsCString& aApi,
                            nsTArray<nsCString>&& aTags,
                            nsTArray<ProcessId>&& aAlreadyBridgedTo,
                            base::ProcessId* aID,
                            nsCString* aDisplayName,
                            uint32_t* aPluginId) override;
   virtual 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);
   virtual bool RecvUpdateGMPTrialCreateState(const nsString& aKeySystem,
                                              const uint32_t& aState) override;
--- a/dom/media/gmp/PGMPService.ipdl
+++ b/dom/media/gmp/PGMPService.ipdl
@@ -14,16 +14,17 @@ 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);
   sync GetGMPNodeId(nsString origin, nsString topLevelOrigin,
+                    nsString gmpName,
                     bool inPrivateBrowsing)
     returns (nsCString id);
 
   async UpdateGMPTrialCreateState(nsString keySystem, uint32_t status);
 };
 
 } // 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(661492d6-726b-4ba0-8e6e-14bfaf2b62e4)]
+[scriptable, uuid(b5492915-2f0e-4973-9f91-a6fe61ac4749)]
 interface mozIGeckoMediaPluginService : nsISupports
 {
 
   /**
    * The GMP thread. Callable from any thread.
    */
   readonly attribute nsIThread thread;
 
@@ -140,16 +140,17 @@ interface mozIGeckoMediaPluginService : 
                        in GetGMPDecryptorCallback callback);
 
   /**
    * Gets the NodeId for a (origin, urlbarOrigin, isInprivateBrowsing) tuple.
    */
   [noscript]
   void getNodeId(in AString origin,
                  in AString topLevelOrigin,
+                 in AString gmpName,
                  in bool inPrivateBrowsingMode,
                  in GetNodeIdCallback callback);
 
   /**
    * Stores the result of trying to create a decoder for the given keysystem.
    */
   [noscript]
   void updateTrialCreateState(in AString keySystem, in uint32_t status);
--- a/dom/media/gtest/TestGMPCrossOrigin.cpp
+++ b/dom/media/gtest/TestGMPCrossOrigin.cpp
@@ -464,16 +464,17 @@ GetNodeId(const nsAString& aOrigin,
   nsCString nodeId;
   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,
+                                   NS_LITERAL_STRING("gmp-fake"),
                                    aInPBMode,
                                    Move(callback));
   EXPECT_TRUE(NS_SUCCEEDED(rv) && NS_SUCCEEDED(result));
   return nodeId;
 }
 
 static bool
 IsGMPStorageIsEmpty()