Bug 1315850 - Connect MediaKeys.createSession to Chromium CDM. r=gerald draft
authorChris Pearce <cpearce@mozilla.com>
Wed, 30 Nov 2016 14:51:18 +1300
changeset 504164 cf303b0d792dfd86f1056529eb4c081d84fc2e82
parent 504163 0931d65116bf0c499933efc58cae97b275b0ba85
child 504165 b7de793c7676ace43d34a9556ef803e1bd3df239
push id50748
push userbmo:cpearce@mozilla.com
push dateFri, 24 Mar 2017 01:10:17 +0000
reviewersgerald
bugs1315850
milestone55.0a1
Bug 1315850 - Connect MediaKeys.createSession to Chromium CDM. r=gerald MozReview-Commit-ID: AzvypvetoOL
dom/media/gmp/ChromiumCDMParent.cpp
dom/media/gmp/ChromiumCDMParent.h
dom/media/gmp/ChromiumCDMProxy.cpp
--- a/dom/media/gmp/ChromiumCDMParent.cpp
+++ b/dom/media/gmp/ChromiumCDMParent.cpp
@@ -26,16 +26,34 @@ ChromiumCDMParent::Init(ChromiumCDMProxy
                         bool aAllowDistinctiveIdentifier,
                         bool aAllowPersistentState)
 {
   mProxy = aProxy;
   return SendInit(aAllowDistinctiveIdentifier, aAllowPersistentState);
 }
 
 void
+ChromiumCDMParent::CreateSession(uint32_t aCreateSessionToken,
+                                 uint32_t aSessionType,
+                                 uint32_t aInitDataType,
+                                 uint32_t aPromiseId,
+                                 const nsTArray<uint8_t>& aInitData)
+{
+  if (!SendCreateSessionAndGenerateRequest(
+        aPromiseId, aSessionType, aInitDataType, aInitData)) {
+    RejectPromise(
+      aPromiseId,
+      NS_ERROR_DOM_INVALID_STATE_ERR,
+      NS_LITERAL_CSTRING("Failed to send generateRequest to CDM process."));
+    return;
+  }
+  mPromiseToCreateSessionToken.Put(aPromiseId, aCreateSessionToken);
+}
+
+void
 ChromiumCDMParent::SetServerCertificate(uint32_t aPromiseId,
                                         const nsTArray<uint8_t>& aCert)
 {
   if (!SendSetServerCertificate(aPromiseId, aCert)) {
     RejectPromise(
       aPromiseId,
       NS_ERROR_DOM_INVALID_STATE_ERR,
       NS_LITERAL_CSTRING("Failed to send setServerCertificate to CDM process"));
@@ -84,27 +102,54 @@ ChromiumCDMParent::Recv__delete__()
 {
   return IPC_OK();
 }
 
 ipc::IPCResult
 ChromiumCDMParent::RecvOnResolveNewSessionPromise(const uint32_t& aPromiseId,
                                                   const nsCString& aSessionId)
 {
+  if (!mProxy) {
+    return IPC_OK();
+  }
+
+  Maybe<uint32_t> token = mPromiseToCreateSessionToken.GetAndRemove(aPromiseId);
+  if (token.isNothing()) {
+    RejectPromise(aPromiseId,
+                  NS_ERROR_DOM_INVALID_STATE_ERR,
+                  NS_LITERAL_CSTRING("Lost session token for new session."));
+    return IPC_OK();
+  }
+
+  RefPtr<Runnable> task =
+    NewRunnableMethod<uint32_t, nsString>(mProxy,
+                                          &ChromiumCDMProxy::OnSetSessionId,
+                                          token.value(),
+                                          NS_ConvertUTF8toUTF16(aSessionId));
+  NS_DispatchToMainThread(task);
+
+  ResolvePromise(aPromiseId);
+
   return IPC_OK();
 }
 
+void
+ChromiumCDMParent::ResolvePromise(uint32_t aPromiseId)
+{
+  if (!mProxy) {
+    return;
+  }
+  NS_DispatchToMainThread(NewRunnableMethod<uint32_t>(
+    mProxy, &ChromiumCDMProxy::ResolvePromise, aPromiseId));
+}
+
 ipc::IPCResult
 ChromiumCDMParent::RecvOnResolvePromise(const uint32_t& aPromiseId)
 {
-  if (!mProxy) {
-    return IPC_OK();
-  }
-  NS_DispatchToMainThread(NewRunnableMethod<uint32_t>(
-    mProxy, &ChromiumCDMProxy::ResolvePromise, aPromiseId));
+  ResolvePromise(aPromiseId);
   return IPC_OK();
 }
 
 static nsresult
 ToNsresult(uint32_t aError)
 {
   switch (static_cast<cdm::Error>(aError)) {
     case cdm::kNotSupportedError:
--- a/dom/media/gmp/ChromiumCDMParent.h
+++ b/dom/media/gmp/ChromiumCDMParent.h
@@ -6,16 +6,17 @@
 #ifndef ChromiumCDMParent_h_
 #define ChromiumCDMParent_h_
 
 #include "GMPCrashHelper.h"
 #include "GMPCrashHelperHolder.h"
 #include "GMPMessageUtils.h"
 #include "mozilla/gmp/PChromiumCDMParent.h"
 #include "mozilla/RefPtr.h"
+#include "nsDataHashtable.h"
 
 namespace mozilla {
 
 class ChromiumCDMProxy;
 
 namespace gmp {
 
 class GMPContentParent;
@@ -30,27 +31,34 @@ public:
   ChromiumCDMParent(GMPContentParent* aContentParent, uint32_t aPluginId);
 
   uint32_t PluginId() const { return mPluginId; }
 
   bool Init(ChromiumCDMProxy* aProxy,
             bool aAllowDistinctiveIdentifier,
             bool aAllowPersistentState);
 
+  void CreateSession(uint32_t aCreateSessionToken,
+                     uint32_t aSessionType,
+                     uint32_t aInitDataType,
+                     uint32_t aPromiseId,
+                     const nsTArray<uint8_t>& aInitData);
+
   void SetServerCertificate(uint32_t aPromiseId,
                             const nsTArray<uint8_t>& aCert);
 
   void UpdateSession(const nsCString& aSessionId,
                      uint32_t aPromiseId,
                      const nsTArray<uint8_t>& aResponse);
 
   void CloseSession(const nsCString& aSessionId, uint32_t aPromiseId);
 
   void RemoveSession(const nsCString& aSessionId, uint32_t aPromiseId);
 
+  // TODO: Add functions for clients to send data to CDM, and
   // a Close() function.
 
 protected:
   ~ChromiumCDMParent() {}
 
   ipc::IPCResult Recv__delete__() override;
   ipc::IPCResult RecvOnResolveNewSessionPromise(
     const uint32_t& aPromiseId,
@@ -80,20 +88,23 @@ protected:
   ipc::IPCResult RecvDecodeFailed(const uint32_t& aStatus) override;
   ipc::IPCResult RecvShutdown() override;
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
   void RejectPromise(uint32_t aPromiseId,
                      nsresult aError,
                      const nsCString& aErrorMessage);
 
+  void ResolvePromise(uint32_t aPromiseId);
+
   const uint32_t mPluginId;
   GMPContentParent* mContentParent;
   // Note: this pointer is a weak reference because otherwise it would cause
   // a cycle, as ChromiumCDMProxy has a strong reference to the
   // ChromiumCDMParent.
   ChromiumCDMProxy* mProxy = nullptr;
+  nsDataHashtable<nsUint32HashKey, uint32_t> mPromiseToCreateSessionToken;
 };
 
 } // namespace gmp
 } // namespace mozilla
 
 #endif // ChromiumCDMParent_h_
--- a/dom/media/gmp/ChromiumCDMProxy.cpp
+++ b/dom/media/gmp/ChromiumCDMProxy.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ChromiumCDMProxy.h"
+#include "mozilla/dom/MediaKeySession.h"
 #include "GMPUtils.h"
 #include "nsPrintfCString.h"
 #include "GMPService.h"
 #include "mozilla/dom/MediaKeySession.h"
 
 namespace mozilla {
 
 ChromiumCDMProxy::ChromiumCDMProxy(dom::MediaKeys* aKeys,
@@ -136,23 +137,68 @@ ChromiumCDMProxy::OnCDMCreated(uint32_t 
 #ifdef DEBUG
 bool
 ChromiumCDMProxy::IsOnOwnerThread()
 {
   return mGMPThread->IsCurrentThreadIn();
 }
 #endif
 
+static uint32_t
+ToCDMSessionType(dom::MediaKeySessionType aSessionType)
+{
+  switch (aSessionType) {
+    case dom::MediaKeySessionType::Temporary:
+      return static_cast<uint32_t>(cdm::kTemporary);
+    case dom::MediaKeySessionType::Persistent_license:
+      return static_cast<uint32_t>(cdm::kPersistentLicense);
+    default:
+      return static_cast<uint32_t>(cdm::kTemporary);
+  };
+};
+
+static uint32_t
+ToCDMInitDataType(const nsAString& aInitDataType)
+{
+  if (aInitDataType.EqualsLiteral("cenc")) {
+    return static_cast<uint32_t>(cdm::kCenc);
+  }
+  if (aInitDataType.EqualsLiteral("webm")) {
+    return static_cast<uint32_t>(cdm::kWebM);
+  }
+  if (aInitDataType.EqualsLiteral("keyids")) {
+    return static_cast<uint32_t>(cdm::kKeyIds);
+  }
+  return static_cast<uint32_t>(cdm::kCenc);
+}
+
 void
 ChromiumCDMProxy::CreateSession(uint32_t aCreateSessionToken,
                                 dom::MediaKeySessionType aSessionType,
                                 PromiseId aPromiseId,
                                 const nsAString& aInitDataType,
                                 nsTArray<uint8_t>& aInitData)
 {
+  MOZ_ASSERT(NS_IsMainThread());
+
+  uint32_t sessionType = ToCDMSessionType(aSessionType);
+  uint32_t initDataType = ToCDMInitDataType(aInitDataType);
+
+  mGMPThread->Dispatch(
+    NewRunnableMethod<uint32_t,
+                      uint32_t,
+                      uint32_t,
+                      uint32_t,
+                      nsTArray<uint8_t>>(mCDM,
+                                         &gmp::ChromiumCDMParent::CreateSession,
+                                         aCreateSessionToken,
+                                         sessionType,
+                                         initDataType,
+                                         aPromiseId,
+                                         Move(aInitData)));
 }
 
 void
 ChromiumCDMProxy::LoadSession(PromiseId aPromiseId, const nsAString& aSessionId)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   RejectPromise(aPromiseId,
@@ -255,16 +301,25 @@ ChromiumCDMProxy::GetNodeId() const
 {
   return mNodeId;
 }
 
 void
 ChromiumCDMProxy::OnSetSessionId(uint32_t aCreateSessionToken,
                                  const nsAString& aSessionId)
 {
+  MOZ_ASSERT(NS_IsMainThread());
+  if (mKeys.IsNull()) {
+    return;
+  }
+  RefPtr<dom::MediaKeySession> session(
+    mKeys->GetPendingSession(aCreateSessionToken));
+  if (session) {
+    session->SetSessionId(aSessionId);
+  }
 }
 
 void
 ChromiumCDMProxy::OnResolveLoadSessionPromise(uint32_t aPromiseId,
                                               bool aSuccess)
 {
 }