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

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "GMPDecryptorChild.h"
       7             : #include "GMPContentChild.h"
       8             : #include "GMPChild.h"
       9             : #include "base/task.h"
      10             : #include "mozilla/TimeStamp.h"
      11             : #include "mozilla/Unused.h"
      12             : #include "runnable_utils.h"
      13             : #include <ctime>
      14             : 
      15             : #define ON_GMP_THREAD() (mPlugin->GMPMessageLoop() == MessageLoop::current())
      16             : 
      17             : #define CALL_ON_GMP_THREAD(_func, ...) \
      18             :   CallOnGMPThread(&GMPDecryptorChild::_func, __VA_ARGS__)
      19             : 
      20             : namespace mozilla {
      21             : namespace gmp {
      22             : 
      23             : static uint32_t sDecryptorCount = 1;
      24             : 
      25           0 : GMPDecryptorChild::GMPDecryptorChild(GMPContentChild* aPlugin)
      26             :   : mSession(nullptr)
      27             :   , mPlugin(aPlugin)
      28           0 :   , mDecryptorId(sDecryptorCount++)
      29             : {
      30           0 :   MOZ_ASSERT(mPlugin);
      31           0 : }
      32             : 
      33           0 : GMPDecryptorChild::~GMPDecryptorChild()
      34             : {
      35           0 : }
      36             : 
      37             : template <typename MethodType, typename... ParamType>
      38             : void
      39           0 : GMPDecryptorChild::CallMethod(MethodType aMethod, ParamType&&... aParams)
      40             : {
      41           0 :   MOZ_ASSERT(ON_GMP_THREAD());
      42             :   // Don't send IPC messages after tear-down.
      43           0 :   if (mSession) {
      44           0 :     (this->*aMethod)(Forward<ParamType>(aParams)...);
      45             :   }
      46           0 : }
      47             : 
      48             : template<typename T>
      49             : struct AddConstReference {
      50             :   typedef const typename RemoveReference<T>::Type& Type;
      51             : };
      52             : 
      53             : template<typename MethodType, typename... ParamType>
      54             : void
      55           0 : GMPDecryptorChild::CallOnGMPThread(MethodType aMethod, ParamType&&... aParams)
      56             : {
      57           0 :   if (ON_GMP_THREAD()) {
      58             :     // Use forwarding reference when we can.
      59           0 :     CallMethod(aMethod, Forward<ParamType>(aParams)...);
      60             :   } else {
      61             :     // Use const reference when we have to.
      62           0 :     auto m = &GMPDecryptorChild::CallMethod<
      63             :         decltype(aMethod), typename AddConstReference<ParamType>::Type...>;
      64             :     RefPtr<mozilla::Runnable> t =
      65           0 :       dont_add_new_uses_of_this::NewRunnableMethod(this, m, aMethod, Forward<ParamType>(aParams)...);
      66           0 :     mPlugin->GMPMessageLoop()->PostTask(t.forget());
      67             :   }
      68           0 : }
      69             : 
      70             : void
      71           0 : GMPDecryptorChild::Init(GMPDecryptor* aSession)
      72             : {
      73           0 :   MOZ_ASSERT(aSession);
      74           0 :   mSession = aSession;
      75             :   // The ID of this decryptor is the IPDL actor ID. Note it's unique inside
      76             :   // the child process, but not necessarily across all gecko processes. However,
      77             :   // since GMPDecryptors are segregated by node ID/origin, we shouldn't end up
      78             :   // with clashes in the content process.
      79           0 :   SendSetDecryptorId(DecryptorId());
      80           0 : }
      81             : 
      82             : void
      83           0 : GMPDecryptorChild::SetSessionId(uint32_t aCreateSessionToken,
      84             :                                 const char* aSessionId,
      85             :                                 uint32_t aSessionIdLength)
      86             : {
      87           0 :   CALL_ON_GMP_THREAD(SendSetSessionId,
      88           0 :                      aCreateSessionToken, nsCString(aSessionId, aSessionIdLength));
      89           0 : }
      90             : 
      91             : void
      92           0 : GMPDecryptorChild::ResolveLoadSessionPromise(uint32_t aPromiseId,
      93             :                                              bool aSuccess)
      94             : {
      95           0 :   CALL_ON_GMP_THREAD(SendResolveLoadSessionPromise, aPromiseId, aSuccess);
      96           0 : }
      97             : 
      98             : void
      99           0 : GMPDecryptorChild::ResolvePromise(uint32_t aPromiseId)
     100             : {
     101           0 :   CALL_ON_GMP_THREAD(SendResolvePromise, aPromiseId);
     102           0 : }
     103             : 
     104             : void
     105           0 : GMPDecryptorChild::RejectPromise(uint32_t aPromiseId,
     106             :                                  GMPDOMException aException,
     107             :                                  const char* aMessage,
     108             :                                  uint32_t aMessageLength)
     109             : {
     110           0 :   CALL_ON_GMP_THREAD(SendRejectPromise,
     111           0 :                      aPromiseId, aException, nsCString(aMessage, aMessageLength));
     112           0 : }
     113             : 
     114             : void
     115           0 : GMPDecryptorChild::SessionMessage(const char* aSessionId,
     116             :                                   uint32_t aSessionIdLength,
     117             :                                   GMPSessionMessageType aMessageType,
     118             :                                   const uint8_t* aMessage,
     119             :                                   uint32_t aMessageLength)
     120             : {
     121           0 :   nsTArray<uint8_t> msg;
     122           0 :   msg.AppendElements(aMessage, aMessageLength);
     123           0 :   CALL_ON_GMP_THREAD(SendSessionMessage,
     124             :                      nsCString(aSessionId, aSessionIdLength),
     125           0 :                      aMessageType, Move(msg));
     126           0 : }
     127             : 
     128             : void
     129           0 : GMPDecryptorChild::ExpirationChange(const char* aSessionId,
     130             :                                     uint32_t aSessionIdLength,
     131             :                                     GMPTimestamp aExpiryTime)
     132             : {
     133           0 :   CALL_ON_GMP_THREAD(SendExpirationChange,
     134           0 :                      nsCString(aSessionId, aSessionIdLength), aExpiryTime);
     135           0 : }
     136             : 
     137             : void
     138           0 : GMPDecryptorChild::SessionClosed(const char* aSessionId,
     139             :                                  uint32_t aSessionIdLength)
     140             : {
     141           0 :   CALL_ON_GMP_THREAD(SendSessionClosed,
     142           0 :                      nsCString(aSessionId, aSessionIdLength));
     143           0 : }
     144             : 
     145             : void
     146           0 : GMPDecryptorChild::SessionError(const char* aSessionId,
     147             :                                 uint32_t aSessionIdLength,
     148             :                                 GMPDOMException aException,
     149             :                                 uint32_t aSystemCode,
     150             :                                 const char* aMessage,
     151             :                                 uint32_t aMessageLength)
     152             : {
     153           0 :   CALL_ON_GMP_THREAD(SendSessionError,
     154             :                      nsCString(aSessionId, aSessionIdLength),
     155             :                      aException, aSystemCode,
     156           0 :                      nsCString(aMessage, aMessageLength));
     157           0 : }
     158             : 
     159             : void
     160           0 : GMPDecryptorChild::KeyStatusChanged(const char* aSessionId,
     161             :                                     uint32_t aSessionIdLength,
     162             :                                     const uint8_t* aKeyId,
     163             :                                     uint32_t aKeyIdLength,
     164             :                                     GMPMediaKeyStatus aStatus)
     165             : {
     166           0 :   AutoTArray<uint8_t, 16> kid;
     167           0 :   kid.AppendElements(aKeyId, aKeyIdLength);
     168             : 
     169           0 :   nsTArray<GMPKeyInformation> keyInfos;
     170           0 :   keyInfos.AppendElement(GMPKeyInformation(kid, aStatus));
     171           0 :   CALL_ON_GMP_THREAD(SendBatchedKeyStatusChanged,
     172             :                      nsCString(aSessionId, aSessionIdLength),
     173           0 :                      keyInfos);
     174           0 : }
     175             : 
     176             : void
     177           0 : GMPDecryptorChild::BatchedKeyStatusChanged(const char* aSessionId,
     178             :                                            uint32_t aSessionIdLength,
     179             :                                            const GMPMediaKeyInfo* aKeyInfos,
     180             :                                            uint32_t aKeyInfosLength)
     181             : {
     182           0 :   nsTArray<GMPKeyInformation> keyInfos;
     183           0 :   for (uint32_t i = 0; i < aKeyInfosLength; i++) {
     184           0 :     nsTArray<uint8_t> keyId;
     185           0 :     keyId.AppendElements(aKeyInfos[i].keyid, aKeyInfos[i].keyid_size);
     186           0 :     keyInfos.AppendElement(GMPKeyInformation(keyId, aKeyInfos[i].status));
     187             :   }
     188           0 :   CALL_ON_GMP_THREAD(SendBatchedKeyStatusChanged,
     189             :                      nsCString(aSessionId, aSessionIdLength),
     190           0 :                      keyInfos);
     191           0 : }
     192             : 
     193             : void
     194           0 : GMPDecryptorChild::Decrypted(GMPBuffer* aBuffer, GMPErr aResult)
     195             : {
     196           0 :   if (!ON_GMP_THREAD()) {
     197             :     // We should run this whole method on the GMP thread since the buffer needs
     198             :     // to be deleted after the SendDecrypted call.
     199           0 :     mPlugin->GMPMessageLoop()->PostTask(
     200           0 :       NewRunnableMethod<GMPBuffer*, GMPErr>("gmp::GMPDecryptorChild::Decrypted",
     201             :                                             this,
     202             :                                             &GMPDecryptorChild::Decrypted,
     203             :                                             aBuffer,
     204           0 :                                             aResult));
     205           0 :     return;
     206             :   }
     207             : 
     208           0 :   if (!aBuffer) {
     209           0 :     NS_WARNING("GMPDecryptorCallback passed bull GMPBuffer");
     210           0 :     return;
     211             :   }
     212             : 
     213           0 :   auto buffer = static_cast<GMPBufferImpl*>(aBuffer);
     214           0 :   if (mSession) {
     215           0 :     SendDecrypted(buffer->mId, aResult, buffer->mData);
     216             :   }
     217           0 :   delete buffer;
     218             : }
     219             : 
     220             : void
     221           0 : GMPDecryptorChild::SetCapabilities(uint64_t aCaps)
     222             : {
     223             :   // Deprecated.
     224           0 : }
     225             : 
     226             : mozilla::ipc::IPCResult
     227           0 : GMPDecryptorChild::RecvInit(const bool& aDistinctiveIdentifierRequired,
     228             :                             const bool& aPersistentStateRequired)
     229             : {
     230           0 :   if (!mSession) {
     231           0 :     return IPC_FAIL_NO_REASON(this);
     232             :   }
     233           0 :   mSession->Init(this, aDistinctiveIdentifierRequired, aPersistentStateRequired);
     234           0 :   return IPC_OK();
     235             : }
     236             : 
     237             : mozilla::ipc::IPCResult
     238           0 : GMPDecryptorChild::RecvCreateSession(const uint32_t& aCreateSessionToken,
     239             :                                      const uint32_t& aPromiseId,
     240             :                                      const nsCString& aInitDataType,
     241             :                                      InfallibleTArray<uint8_t>&& aInitData,
     242             :                                      const GMPSessionType& aSessionType)
     243             : {
     244           0 :   if (!mSession) {
     245           0 :     return IPC_FAIL_NO_REASON(this);
     246             :   }
     247             : 
     248           0 :   mSession->CreateSession(aCreateSessionToken,
     249             :                           aPromiseId,
     250             :                           aInitDataType.get(),
     251             :                           aInitDataType.Length(),
     252           0 :                           aInitData.Elements(),
     253           0 :                           aInitData.Length(),
     254           0 :                           aSessionType);
     255             : 
     256           0 :   return IPC_OK();
     257             : }
     258             : 
     259             : mozilla::ipc::IPCResult
     260           0 : GMPDecryptorChild::RecvLoadSession(const uint32_t& aPromiseId,
     261             :                                    const nsCString& aSessionId)
     262             : {
     263           0 :   if (!mSession) {
     264           0 :     return IPC_FAIL_NO_REASON(this);
     265             :   }
     266             : 
     267           0 :   mSession->LoadSession(aPromiseId,
     268             :                         aSessionId.get(),
     269           0 :                         aSessionId.Length());
     270             : 
     271           0 :   return IPC_OK();
     272             : }
     273             : 
     274             : mozilla::ipc::IPCResult
     275           0 : GMPDecryptorChild::RecvUpdateSession(const uint32_t& aPromiseId,
     276             :                                      const nsCString& aSessionId,
     277             :                                      InfallibleTArray<uint8_t>&& aResponse)
     278             : {
     279           0 :   if (!mSession) {
     280           0 :     return IPC_FAIL_NO_REASON(this);
     281             :   }
     282             : 
     283           0 :   mSession->UpdateSession(aPromiseId,
     284             :                           aSessionId.get(),
     285             :                           aSessionId.Length(),
     286           0 :                           aResponse.Elements(),
     287           0 :                           aResponse.Length());
     288             : 
     289           0 :   return IPC_OK();
     290             : }
     291             : 
     292             : mozilla::ipc::IPCResult
     293           0 : GMPDecryptorChild::RecvCloseSession(const uint32_t& aPromiseId,
     294             :                                     const nsCString& aSessionId)
     295             : {
     296           0 :   if (!mSession) {
     297           0 :     return IPC_FAIL_NO_REASON(this);
     298             :   }
     299             : 
     300           0 :   mSession->CloseSession(aPromiseId,
     301             :                          aSessionId.get(),
     302           0 :                          aSessionId.Length());
     303             : 
     304           0 :   return IPC_OK();
     305             : }
     306             : 
     307             : mozilla::ipc::IPCResult
     308           0 : GMPDecryptorChild::RecvRemoveSession(const uint32_t& aPromiseId,
     309             :                                      const nsCString& aSessionId)
     310             : {
     311           0 :   if (!mSession) {
     312           0 :     return IPC_FAIL_NO_REASON(this);
     313             :   }
     314             : 
     315           0 :   mSession->RemoveSession(aPromiseId,
     316             :                           aSessionId.get(),
     317           0 :                           aSessionId.Length());
     318             : 
     319           0 :   return IPC_OK();
     320             : }
     321             : 
     322             : mozilla::ipc::IPCResult
     323           0 : GMPDecryptorChild::RecvSetServerCertificate(const uint32_t& aPromiseId,
     324             :                                             InfallibleTArray<uint8_t>&& aServerCert)
     325             : {
     326           0 :   if (!mSession) {
     327           0 :     return IPC_FAIL_NO_REASON(this);
     328             :   }
     329             : 
     330           0 :   mSession->SetServerCertificate(aPromiseId,
     331           0 :                                  aServerCert.Elements(),
     332           0 :                                  aServerCert.Length());
     333             : 
     334           0 :   return IPC_OK();
     335             : }
     336             : 
     337             : mozilla::ipc::IPCResult
     338           0 : GMPDecryptorChild::RecvDecrypt(const uint32_t& aId,
     339             :                                InfallibleTArray<uint8_t>&& aBuffer,
     340             :                                const GMPDecryptionData& aMetadata)
     341             : {
     342           0 :   if (!mSession) {
     343           0 :     return IPC_FAIL_NO_REASON(this);
     344             :   }
     345             : 
     346             :   // Note: the GMPBufferImpl created here is deleted when the GMP passes
     347             :   // it back in the Decrypted() callback above.
     348           0 :   GMPBufferImpl* buffer = new GMPBufferImpl(aId, aBuffer);
     349             : 
     350             :   // |metadata| lifetime is managed by |buffer|.
     351           0 :   GMPEncryptedBufferDataImpl* metadata = new GMPEncryptedBufferDataImpl(aMetadata);
     352           0 :   buffer->SetMetadata(metadata);
     353             : 
     354           0 :   mSession->Decrypt(buffer, metadata);
     355           0 :   return IPC_OK();
     356             : }
     357             : 
     358             : mozilla::ipc::IPCResult
     359           0 : GMPDecryptorChild::RecvDecryptingComplete()
     360             : {
     361             :   // Reset |mSession| before calling DecryptingComplete(). We should not send
     362             :   // any IPC messages during tear-down.
     363           0 :   auto session = mSession;
     364           0 :   mSession = nullptr;
     365             : 
     366           0 :   if (!session) {
     367           0 :     return IPC_FAIL_NO_REASON(this);
     368             :   }
     369             : 
     370           0 :   session->DecryptingComplete();
     371             : 
     372           0 :   Unused << Send__delete__(this);
     373             : 
     374           0 :   return IPC_OK();
     375             : }
     376             : 
     377             : } // namespace gmp
     378             : } // namespace mozilla
     379             : 
     380             : // avoid redefined macro in unified build
     381             : #undef ON_GMP_THREAD
     382             : #undef CALL_ON_GMP_THREAD

Generated by: LCOV version 1.13