LCOV - code coverage report
Current view: top level - dom/media/gmp - GMPCDMProxy.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 386 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 53 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
       5             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "GMPCDMProxy.h"
       8             : #include "mozilla/EMEUtils.h"
       9             : #include "mozilla/PodOperations.h"
      10             : 
      11             : #include "mozilla/dom/MediaKeys.h"
      12             : #include "mozilla/dom/MediaKeySession.h"
      13             : #include "mozIGeckoMediaPluginService.h"
      14             : #include "nsPrintfCString.h"
      15             : #include "nsString.h"
      16             : #include "prenv.h"
      17             : #include "GMPCDMCallbackProxy.h"
      18             : #include "GMPService.h"
      19             : #include "MainThreadUtils.h"
      20             : #include "MediaData.h"
      21             : #include "DecryptJob.h"
      22             : #include "GMPUtils.h"
      23             : 
      24             : namespace mozilla {
      25             : 
      26           0 : GMPCDMProxy::GMPCDMProxy(dom::MediaKeys* aKeys,
      27             :                          const nsAString& aKeySystem,
      28             :                          GMPCrashHelper* aCrashHelper,
      29             :                          bool aDistinctiveIdentifierRequired,
      30             :                          bool aPersistentStateRequired,
      31           0 :                          nsIEventTarget* aMainThread)
      32             :   : CDMProxy(aKeys,
      33             :              aKeySystem,
      34             :              aDistinctiveIdentifierRequired,
      35             :              aPersistentStateRequired,
      36             :              aMainThread)
      37             :   , mCrashHelper(aCrashHelper)
      38             :   , mCDM(nullptr)
      39             :   , mShutdownCalled(false)
      40             :   , mDecryptorId(0)
      41           0 :   , mCreatePromiseId(0)
      42             : {
      43           0 :   MOZ_ASSERT(NS_IsMainThread());
      44           0 :   MOZ_COUNT_CTOR(GMPCDMProxy);
      45           0 : }
      46             : 
      47           0 : GMPCDMProxy::~GMPCDMProxy()
      48             : {
      49           0 :   MOZ_COUNT_DTOR(GMPCDMProxy);
      50           0 : }
      51             : 
      52             : void
      53           0 : GMPCDMProxy::Init(PromiseId aPromiseId,
      54             :                   const nsAString& aOrigin,
      55             :                   const nsAString& aTopLevelOrigin,
      56             :                   const nsAString& aGMPName)
      57             : {
      58           0 :   MOZ_ASSERT(NS_IsMainThread());
      59           0 :   NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
      60             : 
      61           0 :   EME_LOG("GMPCDMProxy::Init (%s, %s)",
      62             :           NS_ConvertUTF16toUTF8(aOrigin).get(),
      63             :           NS_ConvertUTF16toUTF8(aTopLevelOrigin).get());
      64             : 
      65           0 :   nsCString pluginVersion;
      66           0 :   if (!mOwnerThread) {
      67             :     nsCOMPtr<mozIGeckoMediaPluginService> mps =
      68           0 :       do_GetService("@mozilla.org/gecko-media-plugin-service;1");
      69           0 :     if (!mps) {
      70           0 :       RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
      71           0 :                     NS_LITERAL_CSTRING("Couldn't get MediaPluginService in GMPCDMProxy::Init"));
      72           0 :       return;
      73             :     }
      74           0 :     mps->GetThread(getter_AddRefs(mOwnerThread));
      75           0 :     if (!mOwnerThread) {
      76           0 :       RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
      77           0 :                     NS_LITERAL_CSTRING("Couldn't get GMP thread GMPCDMProxy::Init"));
      78           0 :       return;
      79             :     }
      80             :   }
      81             : 
      82           0 :   if (aGMPName.IsEmpty()) {
      83             :     RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
      84           0 :       nsPrintfCString("Unknown GMP for keysystem '%s'", NS_ConvertUTF16toUTF8(mKeySystem).get()));
      85           0 :     return;
      86             :   }
      87             : 
      88           0 :   UniquePtr<InitData> data(new InitData());
      89           0 :   data->mPromiseId = aPromiseId;
      90           0 :   data->mOrigin = aOrigin;
      91           0 :   data->mTopLevelOrigin = aTopLevelOrigin;
      92           0 :   data->mGMPName = aGMPName;
      93           0 :   data->mCrashHelper = mCrashHelper;
      94             :   nsCOMPtr<nsIRunnable> task(
      95           0 :     NewRunnableMethod<UniquePtr<InitData>&&>("GMPCDMProxy::gmp_Init",
      96             :                                              this,
      97             :                                              &GMPCDMProxy::gmp_Init,
      98           0 :                                              Move(data)));
      99           0 :   mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
     100             : }
     101             : 
     102             : #ifdef DEBUG
     103             : bool
     104           0 : GMPCDMProxy::IsOnOwnerThread()
     105             : {
     106           0 :   return mOwnerThread->IsOnCurrentThread();
     107             : }
     108             : #endif
     109             : 
     110             : void
     111           0 : GMPCDMProxy::gmp_InitDone(GMPDecryptorProxy* aCDM, UniquePtr<InitData>&& aData)
     112             : {
     113           0 :   EME_LOG("GMPCDMProxy::gmp_InitDone");
     114           0 :   if (mShutdownCalled) {
     115           0 :     if (aCDM) {
     116           0 :       aCDM->Close();
     117             :     }
     118           0 :     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
     119           0 :                   NS_LITERAL_CSTRING("GMPCDMProxy was shut down before init could complete"));
     120           0 :     return;
     121             :   }
     122           0 :   if (!aCDM) {
     123           0 :     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
     124           0 :                   NS_LITERAL_CSTRING("GetGMPDecryptor failed to return a CDM"));
     125           0 :     return;
     126             :   }
     127             : 
     128           0 :   mCDM = aCDM;
     129           0 :   mCallback.reset(new GMPCDMCallbackProxy(this, mMainThread));
     130           0 :   mCDM->Init(mCallback.get(),
     131           0 :              mDistinctiveIdentifierRequired,
     132           0 :              mPersistentStateRequired);
     133             : 
     134             :   // Await the OnSetDecryptorId callback.
     135           0 :   mCreatePromiseId = aData->mPromiseId;
     136             : }
     137             : 
     138           0 : void GMPCDMProxy::OnSetDecryptorId(uint32_t aId)
     139             : {
     140           0 :   MOZ_ASSERT(mCreatePromiseId);
     141           0 :   mDecryptorId = aId;
     142             :   nsCOMPtr<nsIRunnable> task(
     143           0 :     NewRunnableMethod<uint32_t>("GMPCDMProxy::OnCDMCreated",
     144             :                                 this,
     145             :                                 &GMPCDMProxy::OnCDMCreated,
     146           0 :                                 mCreatePromiseId));
     147           0 :   mMainThread->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
     148           0 : }
     149             : 
     150           0 : class gmp_InitDoneCallback : public GetGMPDecryptorCallback
     151             : {
     152             : public:
     153           0 :   gmp_InitDoneCallback(GMPCDMProxy* aGMPCDMProxy,
     154             :                        UniquePtr<GMPCDMProxy::InitData>&& aData)
     155           0 :     : mGMPCDMProxy(aGMPCDMProxy),
     156           0 :       mData(Move(aData))
     157             :   {
     158           0 :   }
     159             : 
     160           0 :   void Done(GMPDecryptorProxy* aCDM)
     161             :   {
     162           0 :     mGMPCDMProxy->gmp_InitDone(aCDM, Move(mData));
     163           0 :   }
     164             : 
     165             : private:
     166             :   RefPtr<GMPCDMProxy> mGMPCDMProxy;
     167             :   UniquePtr<GMPCDMProxy::InitData> mData;
     168             : };
     169             : 
     170           0 : class gmp_InitGetGMPDecryptorCallback : public GetNodeIdCallback
     171             : {
     172             : public:
     173           0 :   gmp_InitGetGMPDecryptorCallback(GMPCDMProxy* aGMPCDMProxy,
     174             :                                   UniquePtr<GMPCDMProxy::InitData>&& aData)
     175           0 :     : mGMPCDMProxy(aGMPCDMProxy),
     176           0 :       mData(Move(aData))
     177             :   {
     178           0 :   }
     179             : 
     180           0 :   void Done(nsresult aResult, const nsACString& aNodeId)
     181             :   {
     182           0 :     mGMPCDMProxy->gmp_InitGetGMPDecryptor(aResult, aNodeId, Move(mData));
     183           0 :   }
     184             : 
     185             : private:
     186             :   RefPtr<GMPCDMProxy> mGMPCDMProxy;
     187             :   UniquePtr<GMPCDMProxy::InitData> mData;
     188             : };
     189             : 
     190             : void
     191           0 : GMPCDMProxy::gmp_Init(UniquePtr<InitData>&& aData)
     192             : {
     193           0 :   MOZ_ASSERT(IsOnOwnerThread());
     194             : 
     195             :   nsCOMPtr<mozIGeckoMediaPluginService> mps =
     196           0 :     do_GetService("@mozilla.org/gecko-media-plugin-service;1");
     197           0 :   if (!mps) {
     198           0 :     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
     199           0 :                   NS_LITERAL_CSTRING("Couldn't get MediaPluginService in GMPCDMProxy::gmp_Init"));
     200           0 :     return;
     201             :   }
     202             : 
     203             :   // Make a copy before we transfer ownership of aData to the
     204             :   // gmp_InitGetGMPDecryptorCallback.
     205           0 :   InitData data(*aData);
     206             :   UniquePtr<GetNodeIdCallback> callback(
     207           0 :     new gmp_InitGetGMPDecryptorCallback(this, Move(aData)));
     208           0 :   nsresult rv = mps->GetNodeId(data.mOrigin,
     209             :                                data.mTopLevelOrigin,
     210             :                                data.mGMPName,
     211           0 :                                Move(callback));
     212           0 :   if (NS_FAILED(rv)) {
     213           0 :     RejectPromise(data.mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
     214           0 :                   NS_LITERAL_CSTRING("Call to GetNodeId() failed early"));
     215             :   }
     216             : }
     217             : 
     218             : void
     219           0 : GMPCDMProxy::gmp_InitGetGMPDecryptor(nsresult aResult,
     220             :                                      const nsACString& aNodeId,
     221             :                                      UniquePtr<InitData>&& aData)
     222             : {
     223           0 :   uint32_t promiseID = aData->mPromiseId;
     224           0 :   if (NS_FAILED(aResult)) {
     225           0 :     RejectPromise(promiseID, NS_ERROR_DOM_INVALID_STATE_ERR,
     226           0 :                   NS_LITERAL_CSTRING("GetNodeId() called back, but with a failure result"));
     227           0 :     return;
     228             :   }
     229             : 
     230           0 :   mNodeId = aNodeId;
     231           0 :   MOZ_ASSERT(!GetNodeId().IsEmpty());
     232             : 
     233             :   nsCOMPtr<mozIGeckoMediaPluginService> mps =
     234           0 :     do_GetService("@mozilla.org/gecko-media-plugin-service;1");
     235           0 :   if (!mps) {
     236           0 :     RejectPromise(promiseID, NS_ERROR_DOM_INVALID_STATE_ERR,
     237           0 :                   NS_LITERAL_CSTRING("Couldn't get MediaPluginService in GMPCDMProxy::gmp_InitGetGMPDecryptor"));
     238           0 :     return;
     239             :   }
     240             : 
     241           0 :   EME_LOG("GMPCDMProxy::gmp_Init (%s, %s) NodeId=%s",
     242             :           NS_ConvertUTF16toUTF8(aData->mOrigin).get(),
     243             :           NS_ConvertUTF16toUTF8(aData->mTopLevelOrigin).get(),
     244             :           GetNodeId().get());
     245             : 
     246           0 :   nsTArray<nsCString> tags;
     247           0 :   tags.AppendElement(NS_ConvertUTF16toUTF8(mKeySystem));
     248             : 
     249             :   // Note: must capture helper refptr here, before the Move()
     250             :   // when we create the GetGMPDecryptorCallback below.
     251           0 :   RefPtr<GMPCrashHelper> crashHelper = Move(aData->mCrashHelper);
     252             :   UniquePtr<GetGMPDecryptorCallback> callback(new gmp_InitDoneCallback(this,
     253           0 :                                                                        Move(aData)));
     254           0 :   nsresult rv = mps->GetGMPDecryptor(crashHelper,
     255             :                                      &tags,
     256           0 :                                      GetNodeId(),
     257           0 :                                      Move(callback));
     258           0 :   if (NS_FAILED(rv)) {
     259           0 :     RejectPromise(promiseID, NS_ERROR_DOM_INVALID_STATE_ERR,
     260           0 :                   NS_LITERAL_CSTRING("Call to GetGMPDecryptor() failed early"));
     261             :   }
     262             : }
     263             : 
     264             : void
     265           0 : GMPCDMProxy::OnCDMCreated(uint32_t aPromiseId)
     266             : {
     267           0 :   MOZ_ASSERT(NS_IsMainThread());
     268           0 :   if (mKeys.IsNull()) {
     269           0 :     return;
     270             :   }
     271           0 :   MOZ_ASSERT(!GetNodeId().IsEmpty());
     272           0 :   if (mCDM) {
     273           0 :     mKeys->OnCDMCreated(aPromiseId, mCDM->GetPluginId());
     274             :   } else {
     275             :     // No CDM? Just reject the promise.
     276           0 :     mKeys->RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
     277           0 :                          NS_LITERAL_CSTRING("Null CDM in OnCDMCreated()"));
     278             :   }
     279             : }
     280             : 
     281             : void
     282           0 : GMPCDMProxy::CreateSession(uint32_t aCreateSessionToken,
     283             :                            dom::MediaKeySessionType aSessionType,
     284             :                            PromiseId aPromiseId,
     285             :                            const nsAString& aInitDataType,
     286             :                            nsTArray<uint8_t>& aInitData)
     287             : {
     288           0 :   MOZ_ASSERT(NS_IsMainThread());
     289           0 :   MOZ_ASSERT(mOwnerThread);
     290             : 
     291           0 :   UniquePtr<CreateSessionData> data(new CreateSessionData());
     292           0 :   data->mSessionType = aSessionType;
     293           0 :   data->mCreateSessionToken = aCreateSessionToken;
     294           0 :   data->mPromiseId = aPromiseId;
     295           0 :   data->mInitDataType = NS_ConvertUTF16toUTF8(aInitDataType);
     296           0 :   data->mInitData = Move(aInitData);
     297             : 
     298             :   nsCOMPtr<nsIRunnable> task(
     299           0 :     NewRunnableMethod<UniquePtr<CreateSessionData>&&>("GMPCDMProxy::gmp_CreateSession",
     300             :                                                       this,
     301             :                                                       &GMPCDMProxy::gmp_CreateSession,
     302           0 :                                                       Move(data)));
     303           0 :   mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
     304           0 : }
     305             : 
     306             : GMPSessionType
     307           0 : ToGMPSessionType(dom::MediaKeySessionType aSessionType) {
     308           0 :   switch (aSessionType) {
     309           0 :     case dom::MediaKeySessionType::Temporary: return kGMPTemporySession;
     310           0 :     case dom::MediaKeySessionType::Persistent_license: return kGMPPersistentSession;
     311           0 :     default: return kGMPTemporySession;
     312             :   };
     313             : };
     314             : 
     315             : void
     316           0 : GMPCDMProxy::gmp_CreateSession(UniquePtr<CreateSessionData>&& aData)
     317             : {
     318           0 :   MOZ_ASSERT(IsOnOwnerThread());
     319           0 :   if (!mCDM) {
     320           0 :     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
     321           0 :                   NS_LITERAL_CSTRING("Null CDM in gmp_CreateSession"));
     322           0 :     return;
     323             :   }
     324           0 :   mCDM->CreateSession(aData->mCreateSessionToken,
     325           0 :                       aData->mPromiseId,
     326           0 :                       aData->mInitDataType,
     327           0 :                       aData->mInitData,
     328           0 :                       ToGMPSessionType(aData->mSessionType));
     329             : }
     330             : 
     331             : void
     332           0 : GMPCDMProxy::LoadSession(PromiseId aPromiseId,
     333             :                          dom::MediaKeySessionType aSessionType,
     334             :                          const nsAString& aSessionId)
     335             : {
     336           0 :   MOZ_ASSERT(NS_IsMainThread());
     337           0 :   MOZ_ASSERT(mOwnerThread);
     338             : 
     339           0 :   UniquePtr<SessionOpData> data(new SessionOpData());
     340           0 :   data->mPromiseId = aPromiseId;
     341           0 :   data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
     342             :   nsCOMPtr<nsIRunnable> task(
     343           0 :     NewRunnableMethod<UniquePtr<SessionOpData>&&>("GMPCDMProxy::gmp_LoadSession",
     344             :                                                   this,
     345             :                                                   &GMPCDMProxy::gmp_LoadSession,
     346           0 :                                                   Move(data)));
     347           0 :   mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
     348           0 : }
     349             : 
     350             : void
     351           0 : GMPCDMProxy::gmp_LoadSession(UniquePtr<SessionOpData>&& aData)
     352             : {
     353           0 :   MOZ_ASSERT(IsOnOwnerThread());
     354             : 
     355           0 :   if (!mCDM) {
     356           0 :     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
     357           0 :                   NS_LITERAL_CSTRING("Null CDM in gmp_LoadSession"));
     358           0 :     return;
     359             :   }
     360           0 :   mCDM->LoadSession(aData->mPromiseId, aData->mSessionId);
     361             : }
     362             : 
     363             : void
     364           0 : GMPCDMProxy::SetServerCertificate(PromiseId aPromiseId,
     365             :                                   nsTArray<uint8_t>& aCert)
     366             : {
     367           0 :   MOZ_ASSERT(NS_IsMainThread());
     368           0 :   MOZ_ASSERT(mOwnerThread);
     369             : 
     370           0 :   UniquePtr<SetServerCertificateData> data(new SetServerCertificateData());
     371           0 :   data->mPromiseId = aPromiseId;
     372           0 :   data->mCert = Move(aCert);
     373             :   nsCOMPtr<nsIRunnable> task(
     374           0 :     NewRunnableMethod<UniquePtr<SetServerCertificateData>&&>("GMPCDMProxy::gmp_SetServerCertificate",
     375             :                                                              this,
     376             :                                                              &GMPCDMProxy::gmp_SetServerCertificate,
     377           0 :                                                              Move(data)));
     378           0 :   mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
     379           0 : }
     380             : 
     381             : void
     382           0 : GMPCDMProxy::gmp_SetServerCertificate(UniquePtr<SetServerCertificateData>&& aData)
     383             : {
     384           0 :   MOZ_ASSERT(IsOnOwnerThread());
     385           0 :   if (!mCDM) {
     386           0 :     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
     387           0 :                   NS_LITERAL_CSTRING("Null CDM in gmp_SetServerCertificate"));
     388           0 :     return;
     389             :   }
     390           0 :   mCDM->SetServerCertificate(aData->mPromiseId, aData->mCert);
     391             : }
     392             : 
     393             : void
     394           0 : GMPCDMProxy::UpdateSession(const nsAString& aSessionId,
     395             :                            PromiseId aPromiseId,
     396             :                            nsTArray<uint8_t>& aResponse)
     397             : {
     398           0 :   MOZ_ASSERT(NS_IsMainThread());
     399           0 :   MOZ_ASSERT(mOwnerThread);
     400           0 :   NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
     401             : 
     402           0 :   UniquePtr<UpdateSessionData> data(new UpdateSessionData());
     403           0 :   data->mPromiseId = aPromiseId;
     404           0 :   data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
     405           0 :   data->mResponse = Move(aResponse);
     406             :   nsCOMPtr<nsIRunnable> task(
     407           0 :     NewRunnableMethod<UniquePtr<UpdateSessionData>&&>("GMPCDMProxy::gmp_UpdateSession",
     408             :                                                       this,
     409             :                                                       &GMPCDMProxy::gmp_UpdateSession,
     410           0 :                                                       Move(data)));
     411           0 :   mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
     412             : }
     413             : 
     414             : void
     415           0 : GMPCDMProxy::gmp_UpdateSession(UniquePtr<UpdateSessionData>&& aData)
     416             : {
     417           0 :   MOZ_ASSERT(IsOnOwnerThread());
     418           0 :   if (!mCDM) {
     419           0 :     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
     420           0 :                   NS_LITERAL_CSTRING("Null CDM in gmp_UpdateSession"));
     421           0 :     return;
     422             :   }
     423           0 :   mCDM->UpdateSession(aData->mPromiseId,
     424           0 :                       aData->mSessionId,
     425           0 :                       aData->mResponse);
     426             : }
     427             : 
     428             : void
     429           0 : GMPCDMProxy::CloseSession(const nsAString& aSessionId,
     430             :                           PromiseId aPromiseId)
     431             : {
     432           0 :   MOZ_ASSERT(NS_IsMainThread());
     433           0 :   NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
     434             : 
     435           0 :   UniquePtr<SessionOpData> data(new SessionOpData());
     436           0 :   data->mPromiseId = aPromiseId;
     437           0 :   data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
     438             :   nsCOMPtr<nsIRunnable> task(
     439           0 :     NewRunnableMethod<UniquePtr<SessionOpData>&&>("GMPCDMProxy::gmp_CloseSession",
     440             :                                                   this,
     441             :                                                   &GMPCDMProxy::gmp_CloseSession,
     442           0 :                                                   Move(data)));
     443           0 :   mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
     444             : }
     445             : 
     446             : void
     447           0 : GMPCDMProxy::gmp_CloseSession(UniquePtr<SessionOpData>&& aData)
     448             : {
     449           0 :   MOZ_ASSERT(IsOnOwnerThread());
     450           0 :   if (!mCDM) {
     451           0 :     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
     452           0 :                   NS_LITERAL_CSTRING("Null CDM in gmp_CloseSession"));
     453           0 :     return;
     454             :   }
     455           0 :   mCDM->CloseSession(aData->mPromiseId, aData->mSessionId);
     456             : }
     457             : 
     458             : void
     459           0 : GMPCDMProxy::RemoveSession(const nsAString& aSessionId,
     460             :                            PromiseId aPromiseId)
     461             : {
     462           0 :   MOZ_ASSERT(NS_IsMainThread());
     463           0 :   NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
     464             : 
     465           0 :   UniquePtr<SessionOpData> data(new SessionOpData());
     466           0 :   data->mPromiseId = aPromiseId;
     467           0 :   data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
     468             :   nsCOMPtr<nsIRunnable> task(
     469           0 :     NewRunnableMethod<UniquePtr<SessionOpData>&&>("GMPCDMProxy::gmp_RemoveSession",
     470             :                                                   this,
     471             :                                                   &GMPCDMProxy::gmp_RemoveSession,
     472           0 :                                                   Move(data)));
     473           0 :   mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
     474             : }
     475             : 
     476             : void
     477           0 : GMPCDMProxy::gmp_RemoveSession(UniquePtr<SessionOpData>&& aData)
     478             : {
     479           0 :   MOZ_ASSERT(IsOnOwnerThread());
     480           0 :   if (!mCDM) {
     481           0 :     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
     482           0 :                   NS_LITERAL_CSTRING("Null CDM in gmp_RemoveSession"));
     483           0 :     return;
     484             :   }
     485           0 :   mCDM->RemoveSession(aData->mPromiseId, aData->mSessionId);
     486             : }
     487             : 
     488             : void
     489           0 : GMPCDMProxy::Shutdown()
     490             : {
     491           0 :   MOZ_ASSERT(NS_IsMainThread());
     492           0 :   mKeys.Clear();
     493             :   // Note: This may end up being the last owning reference to the GMPCDMProxy.
     494           0 :   nsCOMPtr<nsIRunnable> task(NewRunnableMethod(
     495           0 :     "GMPCDMProxy::gmp_Shutdown", this, &GMPCDMProxy::gmp_Shutdown));
     496           0 :   if (mOwnerThread) {
     497           0 :     mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
     498             :   }
     499           0 : }
     500             : 
     501             : void
     502           0 : GMPCDMProxy::gmp_Shutdown()
     503             : {
     504           0 :   MOZ_ASSERT(IsOnOwnerThread());
     505             : 
     506           0 :   mShutdownCalled = true;
     507             : 
     508             :   // Abort any pending decrypt jobs, to awaken any clients waiting on a job.
     509           0 :   for (size_t i = 0; i < mDecryptionJobs.Length(); i++) {
     510           0 :     DecryptJob* job = mDecryptionJobs[i];
     511           0 :     job->PostResult(eme::AbortedErr);
     512             :   }
     513           0 :   mDecryptionJobs.Clear();
     514             : 
     515           0 :   if (mCDM) {
     516           0 :     mCDM->Close();
     517           0 :     mCDM = nullptr;
     518             :   }
     519           0 : }
     520             : 
     521             : void
     522           0 : GMPCDMProxy::RejectPromise(PromiseId aId, nsresult aCode,
     523             :                            const nsCString& aReason)
     524             : {
     525           0 :   if (NS_IsMainThread()) {
     526           0 :     if (!mKeys.IsNull()) {
     527           0 :       mKeys->RejectPromise(aId, aCode, aReason);
     528             :     }
     529             :   } else {
     530             :     nsCOMPtr<nsIRunnable> task(new RejectPromiseTask(this, aId, aCode,
     531           0 :                                                      aReason));
     532           0 :     mMainThread->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
     533             :   }
     534           0 : }
     535             : 
     536             : void
     537           0 : GMPCDMProxy::ResolvePromise(PromiseId aId)
     538             : {
     539           0 :   if (NS_IsMainThread()) {
     540           0 :     if (!mKeys.IsNull()) {
     541           0 :       mKeys->ResolvePromise(aId);
     542             :     } else {
     543           0 :       NS_WARNING("GMPCDMProxy unable to resolve promise!");
     544             :     }
     545             :   } else {
     546           0 :     nsCOMPtr<nsIRunnable> task;
     547           0 :     task = NewRunnableMethod<PromiseId>(
     548           0 :       "GMPCDMProxy::ResolvePromise", this, &GMPCDMProxy::ResolvePromise, aId);
     549           0 :     mMainThread->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
     550             :   }
     551           0 : }
     552             : 
     553             : const nsCString&
     554           0 : GMPCDMProxy::GetNodeId() const
     555             : {
     556           0 :   return mNodeId;
     557             : }
     558             : 
     559             : void
     560           0 : GMPCDMProxy::OnSetSessionId(uint32_t aCreateSessionToken,
     561             :                             const nsAString& aSessionId)
     562             : {
     563           0 :   MOZ_ASSERT(NS_IsMainThread());
     564           0 :   if (mKeys.IsNull()) {
     565           0 :     return;
     566             :   }
     567             : 
     568           0 :   RefPtr<dom::MediaKeySession> session(mKeys->GetPendingSession(aCreateSessionToken));
     569           0 :   if (session) {
     570           0 :     session->SetSessionId(aSessionId);
     571             :   }
     572             : }
     573             : 
     574             : void
     575           0 : GMPCDMProxy::OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess)
     576             : {
     577           0 :   MOZ_ASSERT(NS_IsMainThread());
     578           0 :   if (mKeys.IsNull()) {
     579           0 :     return;
     580             :   }
     581           0 :   mKeys->OnSessionLoaded(aPromiseId, aSuccess);
     582             : }
     583             : 
     584             : void
     585           0 : GMPCDMProxy::OnSessionMessage(const nsAString& aSessionId,
     586             :                               dom::MediaKeyMessageType aMessageType,
     587             :                               nsTArray<uint8_t>& aMessage)
     588             : {
     589           0 :   MOZ_ASSERT(NS_IsMainThread());
     590           0 :   if (mKeys.IsNull()) {
     591           0 :     return;
     592             :   }
     593           0 :   RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
     594           0 :   if (session) {
     595           0 :     session->DispatchKeyMessage(aMessageType, aMessage);
     596             :   }
     597             : }
     598             : 
     599             : void
     600           0 : GMPCDMProxy::OnKeyStatusesChange(const nsAString& aSessionId)
     601             : {
     602           0 :   MOZ_ASSERT(NS_IsMainThread());
     603           0 :   if (mKeys.IsNull()) {
     604           0 :     return;
     605             :   }
     606           0 :   RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
     607           0 :   if (session) {
     608           0 :     session->DispatchKeyStatusesChange();
     609             :   }
     610             : }
     611             : 
     612             : void
     613           0 : GMPCDMProxy::OnExpirationChange(const nsAString& aSessionId,
     614             :                                 GMPTimestamp aExpiryTime)
     615             : {
     616           0 :   MOZ_ASSERT(NS_IsMainThread());
     617           0 :   if (mKeys.IsNull()) {
     618           0 :     return;
     619             :   }
     620           0 :   RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
     621           0 :   if (session) {
     622             :     // Expiry of 0 is interpreted as "never expire". See bug 1345341.
     623           0 :     double t = (aExpiryTime == 0) ? std::numeric_limits<double>::quiet_NaN()
     624           0 :                                   : static_cast<double>(aExpiryTime);
     625           0 :     session->SetExpiration(t);
     626             :   }
     627             : }
     628             : 
     629             : void
     630           0 : GMPCDMProxy::OnSessionClosed(const nsAString& aSessionId)
     631             : {
     632           0 :   MOZ_ASSERT(NS_IsMainThread());
     633           0 :   if (mKeys.IsNull()) {
     634           0 :     return;
     635             :   }
     636           0 :   RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
     637           0 :   if (session) {
     638           0 :     session->OnClosed();
     639             :   }
     640             : }
     641             : 
     642             : void
     643           0 : GMPCDMProxy::OnDecrypted(uint32_t aId,
     644             :                          DecryptStatus aResult,
     645             :                          const nsTArray<uint8_t>& aDecryptedData)
     646             : {
     647           0 :   MOZ_ASSERT(IsOnOwnerThread());
     648           0 :   gmp_Decrypted(aId, aResult, aDecryptedData);
     649           0 : }
     650             : 
     651             : void
     652           0 : GMPCDMProxy::OnSessionError(const nsAString& aSessionId,
     653             :                          nsresult aException,
     654             :                          uint32_t aSystemCode,
     655             :                          const nsAString& aMsg)
     656             : {
     657           0 :   MOZ_ASSERT(NS_IsMainThread());
     658           0 :   if (mKeys.IsNull()) {
     659           0 :     return;
     660             :   }
     661           0 :   RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
     662           0 :   if (session) {
     663           0 :     session->DispatchKeyError(aSystemCode);
     664             :   }
     665           0 :   LogToConsole(aMsg);
     666             : }
     667             : 
     668             : void
     669           0 : GMPCDMProxy::OnRejectPromise(uint32_t aPromiseId,
     670             :                           nsresult aDOMException,
     671             :                           const nsCString& aMsg)
     672             : {
     673           0 :   MOZ_ASSERT(NS_IsMainThread());
     674           0 :   RejectPromise(aPromiseId, aDOMException, aMsg);
     675           0 : }
     676             : 
     677             : const nsString&
     678           0 : GMPCDMProxy::KeySystem() const
     679             : {
     680           0 :   return mKeySystem;
     681             : }
     682             : 
     683             : CDMCaps&
     684           0 : GMPCDMProxy::Capabilites() {
     685           0 :   return mCapabilites;
     686             : }
     687             : 
     688             : RefPtr<DecryptPromise>
     689           0 : GMPCDMProxy::Decrypt(MediaRawData* aSample)
     690             : {
     691           0 :   RefPtr<DecryptJob> job(new DecryptJob(aSample));
     692           0 :   RefPtr<DecryptPromise> promise(job->Ensure());
     693             : 
     694             :   nsCOMPtr<nsIRunnable> task(
     695           0 :     NewRunnableMethod<RefPtr<DecryptJob>>("GMPCDMProxy::gmp_Decrypt",
     696           0 :                                           this, &GMPCDMProxy::gmp_Decrypt, job));
     697           0 :   mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
     698           0 :   return promise;
     699             : }
     700             : 
     701             : void
     702           0 : GMPCDMProxy::gmp_Decrypt(RefPtr<DecryptJob> aJob)
     703             : {
     704           0 :   MOZ_ASSERT(IsOnOwnerThread());
     705             : 
     706           0 :   if (!mCDM) {
     707           0 :     aJob->PostResult(eme::AbortedErr);
     708           0 :     return;
     709             :   }
     710             : 
     711           0 :   nsTArray<uint8_t> data;
     712           0 :   data.AppendElements(aJob->mSample->Data(), aJob->mSample->Size());
     713           0 :   mCDM->Decrypt(aJob->mId, aJob->mSample->mCrypto, data);
     714           0 :   mDecryptionJobs.AppendElement(aJob.forget());
     715             : }
     716             : 
     717             : void
     718           0 : GMPCDMProxy::gmp_Decrypted(uint32_t aId,
     719             :                            DecryptStatus aResult,
     720             :                            const nsTArray<uint8_t>& aDecryptedData)
     721             : {
     722           0 :   MOZ_ASSERT(IsOnOwnerThread());
     723             : #ifdef DEBUG
     724           0 :   bool jobIdFound = false;
     725             : #endif
     726           0 :   for (size_t i = 0; i < mDecryptionJobs.Length(); i++) {
     727           0 :     DecryptJob* job = mDecryptionJobs[i];
     728           0 :     if (job->mId == aId) {
     729             : #ifdef DEBUG
     730           0 :       jobIdFound = true;
     731             : #endif
     732           0 :       job->PostResult(aResult, aDecryptedData);
     733           0 :       mDecryptionJobs.RemoveElementAt(i);
     734             :     }
     735             :   }
     736             : #ifdef DEBUG
     737           0 :   if (!jobIdFound) {
     738           0 :     NS_WARNING("GMPDecryptorChild returned incorrect job ID");
     739             :   }
     740             : #endif
     741           0 : }
     742             : 
     743             : void
     744           0 : GMPCDMProxy::GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId,
     745             :                                    nsTArray<nsCString>& aSessionIds)
     746             : {
     747           0 :   CDMCaps::AutoLock caps(Capabilites());
     748           0 :   caps.GetSessionIdsForKeyId(aKeyId, aSessionIds);
     749           0 : }
     750             : 
     751             : void
     752           0 : GMPCDMProxy::Terminated()
     753             : {
     754           0 :   MOZ_ASSERT(NS_IsMainThread());
     755           0 :   NS_WARNING("CDM terminated");
     756           0 :   if (mCreatePromiseId) {
     757           0 :     RejectPromise(mCreatePromiseId,
     758             :                   NS_ERROR_DOM_MEDIA_FATAL_ERR,
     759           0 :                   NS_LITERAL_CSTRING("Crashed waiting for CDM to initialize"));
     760           0 :     mCreatePromiseId = 0;
     761             :   }
     762           0 :   if (!mKeys.IsNull()) {
     763           0 :     mKeys->Terminated();
     764             :   }
     765           0 : }
     766             : 
     767             : uint32_t
     768           0 : GMPCDMProxy::GetDecryptorId()
     769             : {
     770           0 :   return mDecryptorId;
     771             : }
     772             : 
     773             : } // namespace mozilla

Generated by: LCOV version 1.13