Bug 1315850 - Add GMPService::GetCDM. r=gerald draft
authorChris Pearce <cpearce@mozilla.com>
Wed, 22 Feb 2017 09:26:47 +1300
changeset 504154 c725a958c507b7f93ce9cfccc475f259ae9ccbc2
parent 504153 c7f5c395a719b9f3f13d398f8ca976b09f25ce49
child 504155 c76f1f5f88f53abc4929d21abf6fabf1e47e6056
push id50748
push userbmo:cpearce@mozilla.com
push dateFri, 24 Mar 2017 01:10:17 +0000
reviewersgerald
bugs1315850
milestone55.0a1
Bug 1315850 - Add GMPService::GetCDM. r=gerald Infrastructure necessary to create an instance of the CDM process. MozReview-Commit-ID: 7oQ86x6BNWj
dom/media/gmp/GMPParent.cpp
dom/media/gmp/GMPService.cpp
dom/media/gmp/GMPService.h
dom/media/gmp/GMPUtils.h
dom/media/gmp/moz.build
--- a/dom/media/gmp/GMPParent.cpp
+++ b/dom/media/gmp/GMPParent.cpp
@@ -781,17 +781,17 @@ GMPParent::ParseChromiumManifest(const n
     kEMEKeySystem = kEMEKeySystemWidevine;
 #if XP_WIN
     mLibs = NS_LITERAL_CSTRING("dxva2.dll");
 #endif
   } else {
     return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
   }
 
-  GMPCapability video(NS_LITERAL_CSTRING(GMP_API_VIDEO_DECODER));
+  GMPCapability video;
 
   nsCString codecsString = NS_ConvertUTF16toUTF8(m.mX_cdm_codecs);
   nsTArray<nsCString> codecs;
   SplitAt(",", codecsString, codecs);
 
   for (const nsCString& chromiumCodec : codecs) {
     nsCString codec;
     if (chromiumCodec.EqualsASCII("vp8")) {
@@ -803,24 +803,29 @@ GMPParent::ParseChromiumManifest(const n
     } else {
       return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
     }
 
     video.mAPITags.AppendElement(codec);
   }
 
   video.mAPITags.AppendElement(kEMEKeySystem);
-  mCapabilities.AppendElement(Move(video));
-
-  GMPCapability decrypt(NS_LITERAL_CSTRING(GMP_API_DECRYPTOR));
 
-  decrypt.mAPITags.AppendElement(kEMEKeySystem);
-  mCapabilities.AppendElement(Move(decrypt));
+  if (MediaPrefs::EMEChromiumAPIEnabled()) {
+    video.mAPIName = NS_LITERAL_CSTRING(CHROMIUM_CDM_API);
+    mAdapter = NS_LITERAL_STRING("chromium");
+  } else {
+    video.mAPIName = NS_LITERAL_CSTRING(GMP_API_VIDEO_DECODER);
+    mAdapter = NS_LITERAL_STRING("widevine");
 
-  mAdapter = NS_LITERAL_STRING("widevine");
+    GMPCapability decrypt(NS_LITERAL_CSTRING(GMP_API_DECRYPTOR));
+    decrypt.mAPITags.AppendElement(kEMEKeySystem);
+    mCapabilities.AppendElement(Move(decrypt));
+  }
+  mCapabilities.AppendElement(Move(video));
 
   return GenericPromise::CreateAndResolve(true, __func__);
 }
 
 bool
 GMPParent::CanBeSharedCrossNodeIds() const
 {
   return mNodeId.IsEmpty() &&
--- a/dom/media/gmp/GMPService.cpp
+++ b/dom/media/gmp/GMPService.cpp
@@ -224,16 +224,57 @@ GeckoMediaPluginService::Init()
   MOZ_ASSERT(obsService);
   MOZ_ALWAYS_SUCCEEDS(obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false));
 
   // Kick off scanning for plugins
   nsCOMPtr<nsIThread> thread;
   return GetThread(getter_AddRefs(thread));
 }
 
+RefPtr<GetCDMParentPromise>
+GeckoMediaPluginService::GetCDM(const NodeId& aNodeId,
+                                nsTArray<nsCString> aTags,
+                                GMPCrashHelper* aHelper)
+{
+  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
+
+  if (mShuttingDownOnGMPThread || aTags.IsEmpty()) {
+    return GetCDMParentPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
+  }
+
+  typedef MozPromiseHolder<GetCDMParentPromise> PromiseHolder;
+  PromiseHolder* rawHolder(new PromiseHolder());
+  RefPtr<GetCDMParentPromise> promise = rawHolder->Ensure(__func__);
+  RefPtr<AbstractThread> thread(GetAbstractGMPThread());
+  RefPtr<GMPCrashHelper> helper(aHelper);
+  GetContentParent(
+    aHelper, aNodeId, NS_LITERAL_CSTRING(CHROMIUM_CDM_API), aTags)
+    ->Then(thread,
+           __func__,
+           [rawHolder, helper](RefPtr<GMPContentParent::CloseBlocker> wrapper) {
+             RefPtr<GMPContentParent> parent = wrapper->mParent;
+             UniquePtr<PromiseHolder> holder(rawHolder);
+             RefPtr<ChromiumCDMParent> cdm = parent->GetChromiumCDM();
+             if (!parent) {
+               holder->Reject(NS_ERROR_FAILURE, __func__);
+               return;
+             }
+             if (helper) {
+               cdm->SetCrashHelper(helper);
+             }
+             holder->Resolve(cdm, __func__);
+           },
+           [rawHolder] {
+             UniquePtr<PromiseHolder> holder(rawHolder);
+             holder->Reject(NS_ERROR_FAILURE, __func__);
+           });
+
+  return promise;
+}
+
 void
 GeckoMediaPluginService::ShutdownGMPThread()
 {
   LOGD(("%s::%s", __CLASS__, __FUNCTION__));
   nsCOMPtr<nsIThread> gmpThread;
   {
     MutexAutoLock lock(mMutex);
     mGMPThreadShutdown = true;
--- a/dom/media/gmp/GMPService.h
+++ b/dom/media/gmp/GMPService.h
@@ -19,46 +19,66 @@
 #include "nsIDocument.h"
 #include "nsIWeakReference.h"
 #include "mozilla/AbstractThread.h"
 #include "nsClassHashtable.h"
 #include "nsISupportsImpl.h"
 #include "mozilla/MozPromise.h"
 #include "GMPContentParent.h"
 #include "GMPCrashHelper.h"
+#include "ChromiumCDMParent.h"
 
 template <class> struct already_AddRefed;
 
 namespace mozilla {
 
 class GMPCrashHelper;
 
 extern LogModule* GetGMPLog();
 
 namespace gmp {
 
 struct NodeId
 {
+  NodeId(const nsAString& aOrigin,
+         const nsAString& aTopLevelOrigin,
+         const nsAString& aGMPName)
+    : mOrigin(aOrigin)
+    , mTopLevelOrigin(aTopLevelOrigin)
+    , mGMPName(aGMPName)
+  {
+  }
   nsString mOrigin;
   nsString mTopLevelOrigin;
   nsString mGMPName;
 };
 
-typedef MozPromise<RefPtr<GMPContentParent::CloseBlocker>, nsresult, /* IsExclusive = */ true> GetGMPContentParentPromise;
+typedef MozPromise<RefPtr<GMPContentParent::CloseBlocker>,
+                   nsresult,
+                   /* IsExclusive = */ true>
+  GetGMPContentParentPromise;
+typedef MozPromise<RefPtr<ChromiumCDMParent>,
+                   nsresult,
+                   /* IsExclusive = */ true>
+  GetCDMParentPromise;
 
 class GeckoMediaPluginService : public mozIGeckoMediaPluginService
                               , public nsIObserver
 {
 public:
   static already_AddRefed<GeckoMediaPluginService> GetGeckoMediaPluginService();
 
   virtual nsresult Init();
 
   NS_DECL_THREADSAFE_ISUPPORTS
 
+  RefPtr<GetCDMParentPromise> GetCDM(const NodeId& aNodeId,
+                                     nsTArray<nsCString> aTags,
+                                     GMPCrashHelper* aHelper);
+
   // mozIGeckoMediaPluginService
   NS_IMETHOD GetThread(nsIThread** aThread) override;
   NS_IMETHOD GetDecryptingGMPVideoDecoder(GMPCrashHelper* aHelper,
                                           nsTArray<nsCString>* aTags,
                                           const nsACString& aNodeId,
                                           UniquePtr<GetGMPVideoDecoderCallback>&& aCallback,
                                           uint32_t aDecryptorId)
     override;
--- a/dom/media/gmp/GMPUtils.h
+++ b/dom/media/gmp/GMPUtils.h
@@ -6,16 +6,18 @@
 #ifndef GMPUtils_h_
 #define GMPUtils_h_
 
 #include "mozilla/UniquePtr.h"
 #include "nsTArray.h"
 #include "nsCOMPtr.h"
 #include "nsClassHashtable.h"
 
+#define CHROMIUM_CDM_API "chromium-cdm8-host4"
+
 class nsIFile;
 class nsCString;
 class nsISimpleEnumerator;
 
 namespace mozilla {
 
 template<typename T>
 struct DestroyPolicy
--- a/dom/media/gmp/moz.build
+++ b/dom/media/gmp/moz.build
@@ -7,16 +7,17 @@
 XPIDL_MODULE = 'content_geckomediaplugins'
 
 XPIDL_SOURCES += [
     'mozIGeckoMediaPluginChromeService.idl',
     'mozIGeckoMediaPluginService.idl',
 ]
 
 EXPORTS += [
+    'ChromiumCDMParent.h',
     'DecryptJob.h',
     'gmp-api/gmp-decryption.h',
     'gmp-api/gmp-entrypoints.h',
     'gmp-api/gmp-errors.h',
     'gmp-api/gmp-platform.h',
     'gmp-api/gmp-storage.h',
     'gmp-api/gmp-video-codec.h',
     'gmp-api/gmp-video-decode.h',