Bug 1420836 - Part2 - Pass the storage id from content process to GMP process then provide it to CDM. draft
authorJames Cheng <jacheng@mozilla.com>
Wed, 03 Jan 2018 15:37:07 +0800
changeset 720769 27d9efe3e8c32d3121da10452bbaaa7ac7391d24
parent 720763 4d3ed4d2663109158d3abbab5bec1acfb918c4fe
child 720801 4225d1c5c3475898c14599f53b50da3325ed8c56
push id95633
push userbmo:jacheng@mozilla.com
push dateTue, 16 Jan 2018 07:58:54 +0000
bugs1420836
milestone59.0a1
Bug 1420836 - Part2 - Pass the storage id from content process to GMP process then provide it to CDM. MozReview-Commit-ID: 2VFNHaL5p73
dom/media/gmp/ChromiumCDMChild.cpp
dom/media/gmp/ChromiumCDMChild.h
dom/media/gmp/GMPChild.cpp
dom/media/gmp/GMPChild.h
dom/media/gmp/GMPContentChild.cpp
dom/media/gmp/GMPParent.cpp
dom/media/gmp/PGMP.ipdl
--- a/dom/media/gmp/ChromiumCDMChild.cpp
+++ b/dom/media/gmp/ChromiumCDMChild.cpp
@@ -10,33 +10,35 @@
 #include "WidevineVideoFrame.h"
 #include "GMPLog.h"
 #include "GMPPlatform.h"
 #include "mozilla/Unused.h"
 #include "nsPrintfCString.h"
 #include "base/time.h"
 #include "GMPUtils.h"
 #include "mozilla/ScopeExit.h"
+#include "CDMStorageIdProvider.h"
 
 namespace mozilla {
 namespace gmp {
 
 ChromiumCDMChild::ChromiumCDMChild(GMPContentChild* aPlugin)
   : mPlugin(aPlugin)
 {
   MOZ_ASSERT(IsOnMessageLoopThread());
   GMP_LOG("ChromiumCDMChild:: ctor this=%p", this);
 }
 
 void
-ChromiumCDMChild::Init(cdm::ContentDecryptionModule_9* aCDM)
+ChromiumCDMChild::Init(cdm::ContentDecryptionModule_9* aCDM, const nsCString& aStorageId)
 {
   MOZ_ASSERT(IsOnMessageLoopThread());
   mCDM = aCDM;
   MOZ_ASSERT(mCDM);
+  mStorageId = aStorageId;
 }
 
 void
 ChromiumCDMChild::TimerExpired(void* aContext)
 {
   MOZ_ASSERT(IsOnMessageLoopThread());
   GMP_LOG("ChromiumCDMChild::TimerExpired(context=0x%p)", aContext);
   if (mCDM) {
@@ -471,16 +473,38 @@ ChromiumCDMChild::CreateFileIO(cdm::File
   MOZ_ASSERT(IsOnMessageLoopThread());
   GMP_LOG("ChromiumCDMChild::CreateFileIO()");
   if (!mPersistentStateAllowed) {
     return nullptr;
   }
   return new WidevineFileIO(aClient);
 }
 
+void
+ChromiumCDMChild::RequestStorageId(uint32_t aVersion)
+{
+  MOZ_ASSERT(IsOnMessageLoopThread());
+  GMP_LOG("ChromiumCDMChild::RequestStorageId() aVersion = %u", aVersion);
+  // aVersion >= 0x80000000 are reserved.
+  if (aVersion >= 0x80000000) {
+    mCDM->OnStorageId(aVersion, nullptr, 0);
+    return;
+  }
+  if (aVersion > CDMStorageIdProvider::kCurrentVersion) {
+    mCDM->OnStorageId(aVersion, nullptr, 0);
+    return;
+  }
+
+  mCDM->OnStorageId(CDMStorageIdProvider::kCurrentVersion,
+                    !mStorageId.IsEmpty()
+                      ? reinterpret_cast<const uint8_t*>(mStorageId.get())
+                      : nullptr,
+                    mStorageId.Length());
+}
+
 ChromiumCDMChild::~ChromiumCDMChild()
 {
   GMP_LOG("ChromiumCDMChild:: dtor this=%p", this);
 }
 
 bool
 ChromiumCDMChild::IsOnMessageLoopThread()
 {
--- a/dom/media/gmp/ChromiumCDMChild.h
+++ b/dom/media/gmp/ChromiumCDMChild.h
@@ -20,17 +20,17 @@ class ChromiumCDMChild : public PChromiu
                        , public cdm::Host_8
                        , public cdm::Host_9
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ChromiumCDMChild);
 
   explicit ChromiumCDMChild(GMPContentChild* aPlugin);
 
-  void Init(cdm::ContentDecryptionModule_9* aCDM);
+  void Init(cdm::ContentDecryptionModule_9* aCDM, const nsCString& aStorageId);
 
   void TimerExpired(void* aContext);
 
   // cdm::Host_9 implementation
   cdm::Buffer* Allocate(uint32_t aCapacity) override;
   void SetTimer(int64_t aDelayMs, void* aContext) override;
   cdm::Time GetCurrentWallTime() override;
   // cdm::Host_9 interface
@@ -66,17 +66,17 @@ public:
                              uint32_t aServiceIdSize,
                              const char* aChallenge,
                              uint32_t aChallengeSize) override {}
   void EnableOutputProtection(uint32_t aDesiredProtectionMask) override {}
   void QueryOutputProtectionStatus() override {}
   void OnDeferredInitializationDone(cdm::StreamType aStreamType,
                                     cdm::Status aDecoderStatus) override {}
   // cdm::Host_9 interface
-  void RequestStorageId(uint32_t aVersion) override {}
+  void RequestStorageId(uint32_t aVersion) override;
   cdm::FileIO* CreateFileIO(cdm::FileIOClient* aClient) override;
 
   // cdm::Host_8 implementation
   void OnSessionMessage(const char* aSessionId,
                         uint32_t aSessionIdSize,
                         cdm::MessageType aMessageType,
                         const char* aMessage,
                         uint32_t aMessageSize,
@@ -157,14 +157,15 @@ protected:
   nsTArray<uint32_t> mLoadSessionPromiseIds;
 
   cdm::Size mCodedSize;
   nsTArray<ipc::Shmem> mBuffers;
 
   bool mDecoderInitialized = false;
   bool mPersistentStateAllowed = false;
   bool mDestroyed = false;
+  nsCString mStorageId;
 };
 
 } // namespace gmp
 } // namespace mozilla
 
 #endif // ChromiumCDMChild_h_
--- a/dom/media/gmp/GMPChild.cpp
+++ b/dom/media/gmp/GMPChild.cpp
@@ -249,16 +249,24 @@ GMPChild::Init(const nsAString& aPluginP
 
   CrashReporterClient::InitSingleton(this);
 
   mPluginPath = aPluginPath;
 
   return true;
 }
 
+mozilla::ipc::IPCResult
+GMPChild::RecvProvideStorageId(const nsCString& aStorageId)
+{
+  LOGD("%s", __FUNCTION__);
+  mStorageId = aStorageId;
+  return IPC_OK();
+}
+
 GMPErr
 GMPChild::GetAPI(const char* aAPIName,
                  void* aHostAPI,
                  void** aPluginAPI,
                  uint32_t aDecryptorId)
 {
   if (!mGMPLoader) {
     return GMPGenericErr;
--- a/dom/media/gmp/GMPChild.h
+++ b/dom/media/gmp/GMPChild.h
@@ -41,16 +41,18 @@ public:
 
 private:
   friend class GMPContentChild;
 
   bool ResolveLinks(nsCOMPtr<nsIFile>& aPath);
 
   bool GetUTF8LibPath(nsACString& aOutLibPath);
 
+  mozilla::ipc::IPCResult RecvProvideStorageId(const nsCString& aStorageId) override;
+
   mozilla::ipc::IPCResult AnswerStartPlugin(const nsString& aAdapter) override;
   mozilla::ipc::IPCResult RecvPreloadLibs(const nsCString& aLibs) override;
 
   PGMPTimerChild* AllocPGMPTimerChild() override;
   bool DeallocPGMPTimerChild(PGMPTimerChild* aActor) override;
 
   PGMPStorageChild* AllocPGMPStorageChild() override;
   bool DeallocPGMPStorageChild(PGMPStorageChild* aActor) override;
@@ -71,15 +73,16 @@ private:
 
   nsTArray<UniquePtr<GMPContentChild>> mGMPContentChildren;
 
   RefPtr<GMPTimerChild> mTimerChild;
   RefPtr<GMPStorageChild> mStorage;
 
   MessageLoop* mGMPMessageLoop;
   nsString mPluginPath;
+  nsCString mStorageId;
   UniquePtr<GMPLoader> mGMPLoader;
 };
 
 } // namespace gmp
 } // namespace mozilla
 
 #endif // GMPChild_h_
--- a/dom/media/gmp/GMPContentChild.cpp
+++ b/dom/media/gmp/GMPContentChild.cpp
@@ -300,17 +300,18 @@ GMPContentChild::RecvPChromiumCDMConstru
       return IPC_FAIL_NO_REASON(this);
     }
     cdm =
       new ChromiumCDM8BackwardsCompat(
         host9,
         static_cast<cdm::ContentDecryptionModule_8*>(cdm));
   }
 
-  child->Init(static_cast<cdm::ContentDecryptionModule_9*>(cdm));
+  child->Init(static_cast<cdm::ContentDecryptionModule_9*>(cdm),
+              mGMPChild->mStorageId);
 
   return IPC_OK();
 }
 
 void
 GMPContentChild::CloseActive()
 {
   // Invalidate and remove any remaining API objects.
--- a/dom/media/gmp/GMPParent.cpp
+++ b/dom/media/gmp/GMPParent.cpp
@@ -19,16 +19,17 @@
 #include "mozilla/SyncRunnable.h"
 #include "mozilla/Unused.h"
 #include "nsIObserverService.h"
 #include "GMPTimerParent.h"
 #include "runnable_utils.h"
 #if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
 #include "mozilla/SandboxInfo.h"
 #endif
+#include "CDMStorageIdProvider.h"
 #include "GMPContentParent.h"
 #include "MediaPrefs.h"
 #include "VideoUtils.h"
 
 using mozilla::ipc::GeckoChildProcessHost;
 
 using CrashReporter::AnnotationTable;
 using CrashReporter::GetIDFromMinidump;
@@ -170,16 +171,26 @@ GMPParent::LoadProcess()
     if (!opened) {
       LOGD("%s: Failed to open channel to new child process", __FUNCTION__);
       mProcess->Delete();
       mProcess = nullptr;
       return NS_ERROR_FAILURE;
     }
     LOGD("%s: Opened channel to new child process", __FUNCTION__);
 
+    // ComputeStorageId may return empty string, we leave the error handling to CDM.
+    // The CDM will reject the promise once we provide a empty string of storage id.
+    bool ok = SendProvideStorageId(
+      CDMStorageIdProvider::ComputeStorageId(mNodeId));
+    if (!ok) {
+      LOGD("%s: Failed to send storage id to child process", __FUNCTION__);
+      return NS_ERROR_FAILURE;
+    }
+    LOGD("%s: Sent storage id to child process", __FUNCTION__);
+
 #ifdef XP_WIN
     if (!mLibs.IsEmpty()) {
       bool ok = SendPreloadLibs(mLibs);
       if (!ok) {
         LOGD("%s: Failed to send preload-libs to child process", __FUNCTION__);
         return NS_ERROR_FAILURE;
       }
       LOGD("%s: Sent preload-libs ('%s') to child process", __FUNCTION__, mLibs.get());
--- a/dom/media/gmp/PGMP.ipdl
+++ b/dom/media/gmp/PGMP.ipdl
@@ -22,15 +22,16 @@ parent:
   async PGMPTimer();
   async PGMPStorage();
 
   async PGMPContentChildDestroyed();
 
 child:
   async CrashPluginNow();
   intr StartPlugin(nsString adapter);
+  async ProvideStorageId(nsCString storageId);
   async PreloadLibs(nsCString libs);
   async CloseActive();
   async InitGMPContentChild(Endpoint<PGMPContentChild> endpoint);
 };
 
 } // namespace gmp
 } // namespace mozilla