Bug 1042373 - Implement GMPDecryptor interface for use in GMPs. r=jesup

This commit is contained in:
Chris Pearce 2014-07-28 11:20:34 +12:00
parent 2de855d731
commit fe2c056b8e
18 changed files with 1459 additions and 3 deletions

View File

@ -6,6 +6,7 @@
#include "GMPChild.h"
#include "GMPVideoDecoderChild.h"
#include "GMPVideoEncoderChild.h"
#include "GMPDecryptorChild.h"
#include "GMPVideoHost.h"
#include "nsIFile.h"
#include "nsXULAppAPI.h"
@ -189,6 +190,19 @@ GMPChild::DeallocPGMPVideoDecoderChild(PGMPVideoDecoderChild* aActor)
return true;
}
PGMPDecryptorChild*
GMPChild::AllocPGMPDecryptorChild()
{
return new GMPDecryptorChild(this);
}
bool
GMPChild::DeallocPGMPDecryptorChild(PGMPDecryptorChild* aActor)
{
delete aActor;
return true;
}
PGMPVideoEncoderChild*
GMPChild::AllocPGMPVideoEncoderChild()
{
@ -234,5 +248,22 @@ GMPChild::RecvPGMPVideoEncoderConstructor(PGMPVideoEncoderChild* aActor)
return true;
}
bool
GMPChild::RecvPGMPDecryptorConstructor(PGMPDecryptorChild* aActor)
{
GMPDecryptorChild* child = static_cast<GMPDecryptorChild*>(aActor);
GMPDecryptorHost* host = static_cast<GMPDecryptorHost*>(child);
void* session = nullptr;
GMPErr err = mGetAPIFunc("eme-decrypt", host, &session);
if (err != GMPNoErr || !session) {
return false;
}
child->Init(static_cast<GMPDecryptor*>(session));
return true;
}
} // namespace gmp
} // namespace mozilla

View File

@ -29,12 +29,19 @@ public:
private:
virtual PCrashReporterChild* AllocPCrashReporterChild(const NativeThreadId& aThread) MOZ_OVERRIDE;
virtual bool DeallocPCrashReporterChild(PCrashReporterChild*) MOZ_OVERRIDE;
virtual PGMPVideoDecoderChild* AllocPGMPVideoDecoderChild() MOZ_OVERRIDE;
virtual bool DeallocPGMPVideoDecoderChild(PGMPVideoDecoderChild* aActor) MOZ_OVERRIDE;
virtual bool RecvPGMPVideoDecoderConstructor(PGMPVideoDecoderChild* aActor) MOZ_OVERRIDE;
virtual PGMPVideoEncoderChild* AllocPGMPVideoEncoderChild() MOZ_OVERRIDE;
virtual bool DeallocPGMPVideoEncoderChild(PGMPVideoEncoderChild* aActor) MOZ_OVERRIDE;
virtual bool RecvPGMPVideoDecoderConstructor(PGMPVideoDecoderChild* aActor) MOZ_OVERRIDE;
virtual bool RecvPGMPVideoEncoderConstructor(PGMPVideoEncoderChild* aActor) MOZ_OVERRIDE;
virtual PGMPDecryptorChild* AllocPGMPDecryptorChild() MOZ_OVERRIDE;
virtual bool DeallocPGMPDecryptorChild(PGMPDecryptorChild* aActor) MOZ_OVERRIDE;
virtual bool RecvPGMPDecryptorConstructor(PGMPDecryptorChild* aActor) MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual void ProcessingError(Result aWhat) MOZ_OVERRIDE;

View File

@ -0,0 +1,328 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "GMPDecryptorChild.h"
#include "GMPChild.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/unused.h"
#include <ctime>
namespace mozilla {
namespace gmp {
GMPDecryptorChild::GMPDecryptorChild(GMPChild* aPlugin)
: mPlugin(aPlugin)
, mSession(nullptr)
{
MOZ_ASSERT(mPlugin);
}
GMPDecryptorChild::~GMPDecryptorChild()
{
}
void
GMPDecryptorChild::Init(GMPDecryptor* aSession)
{
MOZ_ASSERT(aSession);
mSession = aSession;
}
void
GMPDecryptorChild::ResolveNewSessionPromise(uint32_t aPromiseId,
const char* aSessionId,
uint32_t aSessionIdLength)
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
nsAutoCString id(aSessionId, aSessionIdLength);
SendResolveNewSessionPromise(aPromiseId, id);
}
void
GMPDecryptorChild::ResolvePromise(uint32_t aPromiseId)
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
SendResolvePromise(aPromiseId);
}
void
GMPDecryptorChild::RejectPromise(uint32_t aPromiseId,
GMPDOMException aException,
const char* aMessage,
uint32_t aMessageLength)
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
nsAutoCString msg(aMessage, aMessageLength);
SendRejectPromise(aPromiseId, aException, msg);
}
void
GMPDecryptorChild::SessionMessage(const char* aSessionId,
uint32_t aSessionIdLength,
const uint8_t* aMessage,
uint32_t aMessageLength,
const char* aDestinationURL,
uint32_t aDestinationURLLength)
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
nsAutoCString id(aSessionId, aSessionIdLength);
nsTArray<uint8_t> msg;
msg.AppendElements(aMessage, aMessageLength);
nsAutoCString url(aDestinationURL, aDestinationURLLength);
SendSessionMessage(id, msg, url);
}
void
GMPDecryptorChild::ExpirationChange(const char* aSessionId,
uint32_t aSessionIdLength,
GMPTimestamp aExpiryTime)
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
nsAutoCString id(aSessionId, aSessionIdLength);
SendExpirationChange(id, aExpiryTime);
}
void
GMPDecryptorChild::SessionClosed(const char* aSessionId,
uint32_t aSessionIdLength)
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
nsAutoCString id(aSessionId, aSessionIdLength);
SendSessionClosed(id);
}
void
GMPDecryptorChild::SessionError(const char* aSessionId,
uint32_t aSessionIdLength,
GMPDOMException aException,
uint32_t aSystemCode,
const char* aMessage,
uint32_t aMessageLength)
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
nsAutoCString id(aSessionId, aSessionIdLength);
nsAutoCString msg(aMessage, aMessageLength);
SendSessionError(id, aException, aSystemCode, msg);
}
void
GMPDecryptorChild::KeyIdUsable(const char* aSessionId,
uint32_t aSessionIdLength,
const uint8_t* aKeyId,
uint32_t aKeyIdLength)
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
nsAutoCString sid(aSessionId, aSessionIdLength);
nsAutoTArray<uint8_t, 16> kid;
kid.AppendElements(aKeyId, aKeyIdLength);
SendKeyIdUsable(sid, kid);
}
void
GMPDecryptorChild::KeyIdNotUsable(const char* aSessionId,
uint32_t aSessionIdLength,
const uint8_t* aKeyId,
uint32_t aKeyIdLength)
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
nsAutoCString sid(aSessionId, aSessionIdLength);
nsAutoTArray<uint8_t, 16> kid;
kid.AppendElements(aKeyId, aKeyIdLength);
SendKeyIdNotUsable(sid, kid);
}
void
GMPDecryptorChild::Decrypted(GMPBuffer* aBuffer, GMPErr aResult)
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
auto buffer = static_cast<GMPBufferImpl*>(aBuffer);
SendDecrypted(buffer->mId, aResult, buffer->mData);
}
void
GMPDecryptorChild::SetCapabilities(uint64_t aCaps)
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
SendSetCaps(aCaps);
}
void
GMPDecryptorChild::GetNodeId(const char** aOutNodeId,
uint32_t* aOutNodeIdLength)
{
static const char* id = "placeholder_node_id";
*aOutNodeId = id;
*aOutNodeIdLength = strlen(id);
}
void
GMPDecryptorChild::GetSandboxVoucher(const uint8_t** aVoucher,
uint8_t* aVoucherLength)
{
const char* voucher = "placeholder_sandbox_voucher.";
*aVoucher = (uint8_t*)voucher;
*aVoucherLength = strlen(voucher);
}
void
GMPDecryptorChild::GetPluginVoucher(const uint8_t** aVoucher,
uint8_t* aVoucherLength)
{
const char* voucher = "placeholder_plugin_voucher.";
*aVoucher = (uint8_t*)voucher;
*aVoucherLength = strlen(voucher);
}
bool
GMPDecryptorChild::RecvInit()
{
if (!mSession) {
return false;
}
mSession->Init(this);
return true;
}
bool
GMPDecryptorChild::RecvCreateSession(const uint32_t& aPromiseId,
const nsCString& aInitDataType,
const nsTArray<uint8_t>& aInitData,
const GMPSessionType& aSessionType)
{
if (!mSession) {
return false;
}
mSession->CreateSession(aPromiseId,
aInitDataType.get(),
aInitDataType.Length(),
aInitData.Elements(),
aInitData.Length(),
aSessionType);
return true;
}
bool
GMPDecryptorChild::RecvLoadSession(const uint32_t& aPromiseId,
const nsCString& aSessionId)
{
if (!mSession) {
return false;
}
mSession->LoadSession(aPromiseId,
aSessionId.get(),
aSessionId.Length());
return true;
}
bool
GMPDecryptorChild::RecvUpdateSession(const uint32_t& aPromiseId,
const nsCString& aSessionId,
const nsTArray<uint8_t>& aResponse)
{
if (!mSession) {
return false;
}
mSession->UpdateSession(aPromiseId,
aSessionId.get(),
aSessionId.Length(),
aResponse.Elements(),
aResponse.Length());
return true;
}
bool
GMPDecryptorChild::RecvCloseSession(const uint32_t& aPromiseId,
const nsCString& aSessionId)
{
if (!mSession) {
return false;
}
mSession->CloseSession(aPromiseId,
aSessionId.get(),
aSessionId.Length());
return true;
}
bool
GMPDecryptorChild::RecvRemoveSession(const uint32_t& aPromiseId,
const nsCString& aSessionId)
{
if (!mSession) {
return false;
}
mSession->RemoveSession(aPromiseId,
aSessionId.get(),
aSessionId.Length());
return true;
}
bool
GMPDecryptorChild::RecvSetServerCertificate(const uint32_t& aPromiseId,
const nsTArray<uint8_t>& aServerCert)
{
if (!mSession) {
return false;
}
mSession->SetServerCertificate(aPromiseId,
aServerCert.Elements(),
aServerCert.Length());
return true;
}
bool
GMPDecryptorChild::RecvDecrypt(const uint32_t& aId,
const nsTArray<uint8_t>& aBuffer,
const GMPDecryptionData& aMetadata)
{
if (!mSession) {
return false;
}
GMPEncryptedBufferDataImpl metadata(aMetadata);
mSession->Decrypt(new GMPBufferImpl(aId, aBuffer), &metadata);
return true;
}
bool
GMPDecryptorChild::RecvDecryptingComplete()
{
if (!mSession) {
return false;
}
mSession->DecryptingComplete();
mSession = nullptr;
unused << Send__delete__(this);
return true;
}
} // namespace gmp
} // namespace mozilla

View File

@ -0,0 +1,127 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef GMPDecryptorChild_h_
#define GMPDecryptorChild_h_
#include "mozilla/gmp/PGMPDecryptorChild.h"
#include "gmp-decryption.h"
#include "mozilla/gmp/GMPTypes.h"
#include "GMPEncryptedBufferDataImpl.h"
namespace mozilla {
namespace gmp {
class GMPChild;
class GMPDecryptorChild : public GMPDecryptorCallback
, public GMPDecryptorHost
, public PGMPDecryptorChild
{
public:
GMPDecryptorChild(GMPChild* aPlugin);
~GMPDecryptorChild();
void Init(GMPDecryptor* aSession);
// GMPDecryptorCallback
virtual void ResolveNewSessionPromise(uint32_t aPromiseId,
const char* aSessionId,
uint32_t aSessionIdLength) MOZ_OVERRIDE;
virtual void ResolvePromise(uint32_t aPromiseId) MOZ_OVERRIDE;
virtual void RejectPromise(uint32_t aPromiseId,
GMPDOMException aException,
const char* aMessage,
uint32_t aMessageLength) MOZ_OVERRIDE;
virtual void SessionMessage(const char* aSessionId,
uint32_t aSessionIdLength,
const uint8_t* aMessage,
uint32_t aMessageLength,
const char* aDestinationURL,
uint32_t aDestinationURLLength) MOZ_OVERRIDE;
virtual void ExpirationChange(const char* aSessionId,
uint32_t aSessionIdLength,
GMPTimestamp aExpiryTime) MOZ_OVERRIDE;
virtual void SessionClosed(const char* aSessionId,
uint32_t aSessionIdLength) MOZ_OVERRIDE;
virtual void SessionError(const char* aSessionId,
uint32_t aSessionIdLength,
GMPDOMException aException,
uint32_t aSystemCode,
const char* aMessage,
uint32_t aMessageLength) MOZ_OVERRIDE;
virtual void KeyIdUsable(const char* aSessionId,
uint32_t aSessionIdLength,
const uint8_t* aKeyId,
uint32_t aKeyIdLength) MOZ_OVERRIDE;
virtual void KeyIdNotUsable(const char* aSessionId,
uint32_t aSessionIdLength,
const uint8_t* aKeyId,
uint32_t aKeyIdLength) MOZ_OVERRIDE;
virtual void SetCapabilities(uint64_t aCaps) MOZ_OVERRIDE;
virtual void Decrypted(GMPBuffer* aBuffer, GMPErr aResult) MOZ_OVERRIDE;
// GMPDecryptorHost
virtual void GetNodeId(const char** aOutNodeId,
uint32_t* aOutNodeIdLength) MOZ_OVERRIDE;
virtual void GetSandboxVoucher(const uint8_t** aVoucher,
uint8_t* aVoucherLength) MOZ_OVERRIDE;
virtual void GetPluginVoucher(const uint8_t** aVoucher,
uint8_t* aVoucherLength) MOZ_OVERRIDE;
private:
// GMPDecryptorChild
virtual bool RecvInit() MOZ_OVERRIDE;
virtual bool RecvCreateSession(const uint32_t& aPromiseId,
const nsCString& aInitDataType,
const nsTArray<uint8_t>& aInitData,
const GMPSessionType& aSessionType) MOZ_OVERRIDE;
virtual bool RecvLoadSession(const uint32_t& aPromiseId,
const nsCString& aSessionId) MOZ_OVERRIDE;
virtual bool RecvUpdateSession(const uint32_t& aPromiseId,
const nsCString& aSessionId,
const nsTArray<uint8_t>& aResponse) MOZ_OVERRIDE;
virtual bool RecvCloseSession(const uint32_t& aPromiseId,
const nsCString& aSessionId) MOZ_OVERRIDE;
virtual bool RecvRemoveSession(const uint32_t& aPromiseId,
const nsCString& aSessionId) MOZ_OVERRIDE;
virtual bool RecvDecrypt(const uint32_t& aId,
const nsTArray<uint8_t>& aBuffer,
const GMPDecryptionData& aMetadata);
// Resolve/reject promise on completion.
virtual bool RecvSetServerCertificate(const uint32_t& aPromiseId,
const nsTArray<uint8_t>& aServerCert) MOZ_OVERRIDE;
virtual bool RecvDecryptingComplete() MOZ_OVERRIDE;
GMPChild* mPlugin;
// GMP's GMPDecryptor implementation.
// Only call into this on the (GMP process) main thread.
GMPDecryptor* mSession;
};
} // namespace gmp
} // namespace mozilla
#endif // GMPDecryptorChild_h_

View File

@ -0,0 +1,358 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "GMPDecryptorParent.h"
#include "GMPParent.h"
#include "mp4_demuxer/DecoderData.h"
#include "mozilla/unused.h"
namespace mozilla {
namespace gmp {
GMPDecryptorParent::GMPDecryptorParent(GMPParent* aPlugin)
: mIsOpen(false)
, mPlugin(aPlugin)
, mCallback(nullptr)
{
MOZ_ASSERT(mPlugin);
}
GMPDecryptorParent::~GMPDecryptorParent()
{
}
nsresult
GMPDecryptorParent::Init(GMPDecryptorProxyCallback* aCallback)
{
if (mIsOpen) {
NS_WARNING("Trying to re-use an in-use GMP decrypter!");
return NS_ERROR_FAILURE;
}
mCallback = aCallback;
if (!SendInit()) {
return NS_ERROR_FAILURE;
}
mIsOpen = true;
return NS_OK;
}
void
GMPDecryptorParent::CreateSession(uint32_t aPromiseId,
const nsCString& aInitDataType,
const nsTArray<uint8_t>& aInitData,
GMPSessionType aSessionType)
{
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return;
}
// Caller should ensure parameters passed in from JS are valid.
MOZ_ASSERT(!aInitDataType.IsEmpty() && !aInitData.IsEmpty());
unused << SendCreateSession(aPromiseId, aInitDataType, aInitData, aSessionType);
}
void
GMPDecryptorParent::LoadSession(uint32_t aPromiseId,
const nsCString& aSessionId)
{
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return;
}
// Caller should ensure parameters passed in from JS are valid.
MOZ_ASSERT(!aSessionId.IsEmpty());
unused << SendLoadSession(aPromiseId, aSessionId);
}
void
GMPDecryptorParent::UpdateSession(uint32_t aPromiseId,
const nsCString& aSessionId,
const nsTArray<uint8_t>& aResponse)
{
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return;
}
// Caller should ensure parameters passed in from JS are valid.
MOZ_ASSERT(!aSessionId.IsEmpty() && !aResponse.IsEmpty());
unused << SendUpdateSession(aPromiseId, aSessionId, aResponse);
}
void
GMPDecryptorParent::CloseSession(uint32_t aPromiseId,
const nsCString& aSessionId)
{
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return;
}
// Caller should ensure parameters passed in from JS are valid.
MOZ_ASSERT(!aSessionId.IsEmpty());
unused << SendCloseSession(aPromiseId, aSessionId);
}
void
GMPDecryptorParent::RemoveSession(uint32_t aPromiseId,
const nsCString& aSessionId)
{
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return;
}
// Caller should ensure parameters passed in from JS are valid.
MOZ_ASSERT(!aSessionId.IsEmpty());
unused << SendRemoveSession(aPromiseId, aSessionId);
}
void
GMPDecryptorParent::SetServerCertificate(uint32_t aPromiseId,
const nsTArray<uint8_t>& aServerCert)
{
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return;
}
// Caller should ensure parameters passed in from JS are valid.
MOZ_ASSERT(!aServerCert.IsEmpty());
unused << SendSetServerCertificate(aPromiseId, aServerCert);
}
void
GMPDecryptorParent::Decrypt(uint32_t aId,
const mp4_demuxer::CryptoSample& aCrypto,
const nsTArray<uint8_t>& aBuffer)
{
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return;
}
// Caller should ensure parameters passed in are valid.
MOZ_ASSERT(!aBuffer.IsEmpty() && aCrypto.valid);
GMPDecryptionData data(aCrypto.key,
aCrypto.iv,
aCrypto.plain_sizes,
aCrypto.encrypted_sizes);
unused << SendDecrypt(aId, aBuffer, data);
}
bool
GMPDecryptorParent::RecvResolveNewSessionPromise(const uint32_t& aPromiseId,
const nsCString& aSessionId)
{
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return false;
}
mCallback->ResolveNewSessionPromise(aPromiseId, aSessionId);
return true;
}
bool
GMPDecryptorParent::RecvResolvePromise(const uint32_t& aPromiseId)
{
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return false;
}
mCallback->ResolvePromise(aPromiseId);
return true;
}
nsresult
GMPExToNsresult(GMPDOMException aDomException) {
switch (aDomException) {
case kGMPNoModificationAllowedError: return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
case kGMPNotFoundError: return NS_ERROR_DOM_NOT_FOUND_ERR;
case kGMPNotSupportedError: return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
case kGMPInvalidStateError: return NS_ERROR_DOM_INVALID_STATE_ERR;
case kGMPSyntaxError: return NS_ERROR_DOM_SYNTAX_ERR;
case kGMPInvalidModificationError: return NS_ERROR_DOM_INVALID_MODIFICATION_ERR;
case kGMPInvalidAccessError: return NS_ERROR_DOM_INVALID_ACCESS_ERR;
case kGMPSecurityError: return NS_ERROR_DOM_SECURITY_ERR;
case kGMPAbortError: return NS_ERROR_DOM_ABORT_ERR;
case kGMPQuotaExceededError: return NS_ERROR_DOM_QUOTA_EXCEEDED_ERR;
case kGMPTimeoutError: return NS_ERROR_DOM_TIMEOUT_ERR;
default: return NS_ERROR_DOM_UNKNOWN_ERR;
}
}
bool
GMPDecryptorParent::RecvRejectPromise(const uint32_t& aPromiseId,
const GMPDOMException& aException,
const nsCString& aMessage)
{
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return false;
}
mCallback->RejectPromise(aPromiseId, GMPExToNsresult(aException), aMessage);
return true;
}
bool
GMPDecryptorParent::RecvSessionMessage(const nsCString& aSessionId,
const nsTArray<uint8_t>& aMessage,
const nsCString& aDestinationURL)
{
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return false;
}
mCallback->SessionMessage(aSessionId, aMessage, aDestinationURL);
return true;
}
bool
GMPDecryptorParent::RecvExpirationChange(const nsCString& aSessionId,
const double& aExpiryTime)
{
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return false;
}
mCallback->ExpirationChange(aSessionId, aExpiryTime);
return true;
}
bool
GMPDecryptorParent::RecvSessionClosed(const nsCString& aSessionId)
{
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return false;
}
mCallback->SessionClosed(aSessionId);
return true;
}
bool
GMPDecryptorParent::RecvSessionError(const nsCString& aSessionId,
const GMPDOMException& aException,
const uint32_t& aSystemCode,
const nsCString& aMessage)
{
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return false;
}
mCallback->SessionError(aSessionId,
GMPExToNsresult(aException),
aSystemCode,
aMessage);
return true;
}
bool
GMPDecryptorParent::RecvKeyIdUsable(const nsCString& aSessionId,
const nsTArray<uint8_t>& aKeyId)
{
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return false;
}
mCallback->KeyIdUsable(aSessionId, aKeyId);
return true;
}
bool
GMPDecryptorParent::RecvKeyIdNotUsable(const nsCString& aSessionId,
const nsTArray<uint8_t>& aKeyId)
{
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return false;
}
mCallback->KeyIdNotUsable(aSessionId, aKeyId);
return true;
}
bool
GMPDecryptorParent::RecvSetCaps(const uint64_t& aCaps)
{
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return false;
}
mCallback->SetCaps(aCaps);
return true;
}
bool
GMPDecryptorParent::RecvDecrypted(const uint32_t& aId,
const GMPErr& aErr,
const nsTArray<uint8_t>& aBuffer)
{
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return false;
}
mCallback->Decrypted(aId, aErr, aBuffer);
return true;
}
// Note: may be called via Terminated()
void
GMPDecryptorParent::Close()
{
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
// Consumer is done with us; we can shut down. No more callbacks should
// be made to mCallback. Note: do this before Shutdown()!
mCallback = nullptr;
// Let Shutdown mark us as dead so it knows if we had been alive
// In case this is the last reference
nsRefPtr<GMPDecryptorParent> kungfudeathgrip(this);
NS_RELEASE(kungfudeathgrip);
Shutdown();
}
void
GMPDecryptorParent::Shutdown()
{
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
// Notify client we're gone! Won't occur after Close()
if (mCallback) {
mCallback->Terminated();
mCallback = nullptr;
}
if (mIsOpen) {
mIsOpen = false;
unused << SendDecryptingComplete();
}
}
// Note: Keep this sync'd up with Shutdown
void
GMPDecryptorParent::ActorDestroy(ActorDestroyReason aWhy)
{
mIsOpen = false;
if (mCallback) {
// May call Close() (and Shutdown()) immediately or with a delay
mCallback->Terminated();
mCallback = nullptr;
}
if (mPlugin) {
mPlugin->DecryptorDestroyed(this);
mPlugin = nullptr;
}
}
bool
GMPDecryptorParent::Recv__delete__()
{
if (mPlugin) {
mPlugin->DecryptorDestroyed(this);
mPlugin = nullptr;
}
return true;
}
} // namespace gmp
} // namespace mozilla

View File

@ -0,0 +1,113 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef GMPDecryptorParent_h_
#define GMPDecryptorParent_h_
#include "mozilla/gmp/PGMPDecryptorParent.h"
#include "mozilla/RefPtr.h"
#include "gmp-decryption.h"
#include "GMPDecryptorProxy.h"
namespace mp4_demuxer {
class CryptoSample;
}
namespace mozilla {
namespace gmp {
class GMPParent;
class GMPDecryptorParent MOZ_FINAL : public GMPDecryptorProxy
, public PGMPDecryptorParent
{
public:
NS_INLINE_DECL_REFCOUNTING(GMPDecryptorParent)
GMPDecryptorParent(GMPParent *aPlugin);
// GMPDecryptorProxy
virtual nsresult Init(GMPDecryptorProxyCallback* aCallback) MOZ_OVERRIDE;
virtual void CreateSession(uint32_t aPromiseId,
const nsCString& aInitDataType,
const nsTArray<uint8_t>& aInitData,
GMPSessionType aSessionType) MOZ_OVERRIDE;
virtual void LoadSession(uint32_t aPromiseId,
const nsCString& aSessionId) MOZ_OVERRIDE;
virtual void UpdateSession(uint32_t aPromiseId,
const nsCString& aSessionId,
const nsTArray<uint8_t>& aResponse) MOZ_OVERRIDE;
virtual void CloseSession(uint32_t aPromiseId,
const nsCString& aSessionId) MOZ_OVERRIDE;
virtual void RemoveSession(uint32_t aPromiseId,
const nsCString& aSessionId) MOZ_OVERRIDE;
virtual void SetServerCertificate(uint32_t aPromiseId,
const nsTArray<uint8_t>& aServerCert) MOZ_OVERRIDE;
virtual void Decrypt(uint32_t aId,
const mp4_demuxer::CryptoSample& aCrypto,
const nsTArray<uint8_t>& aBuffer) MOZ_OVERRIDE;
virtual void Close() MOZ_OVERRIDE;
void Shutdown();
private:
~GMPDecryptorParent();
// PGMPDecryptorParent
virtual bool RecvResolveNewSessionPromise(const uint32_t& aPromiseId,
const nsCString& aSessionId) MOZ_OVERRIDE;
virtual bool RecvResolvePromise(const uint32_t& aPromiseId) MOZ_OVERRIDE;
virtual bool RecvRejectPromise(const uint32_t& aPromiseId,
const GMPDOMException& aException,
const nsCString& aMessage) MOZ_OVERRIDE;
virtual bool RecvSessionMessage(const nsCString& aSessionId,
const nsTArray<uint8_t>& aMessage,
const nsCString& aDestinationURL) MOZ_OVERRIDE;
virtual bool RecvExpirationChange(const nsCString& aSessionId,
const double& aExpiryTime) MOZ_OVERRIDE;
virtual bool RecvSessionClosed(const nsCString& aSessionId) MOZ_OVERRIDE;
virtual bool RecvSessionError(const nsCString& aSessionId,
const GMPDOMException& aException,
const uint32_t& aSystemCode,
const nsCString& aMessage) MOZ_OVERRIDE;
virtual bool RecvKeyIdUsable(const nsCString& aSessionId,
const nsTArray<uint8_t>& aKeyId) MOZ_OVERRIDE;
virtual bool RecvKeyIdNotUsable(const nsCString& aSessionId,
const nsTArray<uint8_t>& aKeyId) MOZ_OVERRIDE;
virtual bool RecvDecrypted(const uint32_t& aId,
const GMPErr& aErr,
const nsTArray<uint8_t>& aBuffer) MOZ_OVERRIDE;
virtual bool RecvSetCaps(const uint64_t& aCaps) MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual bool Recv__delete__() MOZ_OVERRIDE;
bool mIsOpen;
nsRefPtr<GMPParent> mPlugin;
GMPDecryptorProxyCallback* mCallback;
};
} // namespace gmp
} // namespace mozilla
#endif // GMPDecryptorChild_h_

View File

@ -0,0 +1,89 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef GMPDecryptorProxy_h_
#define GMPDecryptorProxy_h_
#include "GMPCallbackBase.h"
namespace mp4_demuxer {
class CryptoSample;
}
class GMPDecryptorProxyCallback : public GMPCallbackBase {
public:
~GMPDecryptorProxyCallback() {}
virtual void ResolveNewSessionPromise(uint32_t aPromiseId,
const nsCString& aSessionId) = 0;
virtual void ResolvePromise(uint32_t aPromiseId) = 0;
virtual void RejectPromise(uint32_t aPromiseId,
nsresult aException,
const nsCString& aSessionId) = 0;
virtual void SessionMessage(const nsCString& aSessionId,
const nsTArray<uint8_t>& aMessage,
const nsCString& aDestinationURL) = 0;
virtual void ExpirationChange(const nsCString& aSessionId,
GMPTimestamp aExpiryTime) = 0;
virtual void SessionClosed(const nsCString& aSessionId) = 0;
virtual void SessionError(const nsCString& aSessionId,
nsresult aException,
uint32_t aSystemCode,
const nsCString& aMessage) = 0;
virtual void KeyIdUsable(const nsCString& aSessionId,
const nsTArray<uint8_t>& aKeyId) = 0;
virtual void KeyIdNotUsable(const nsCString& aSessionId,
const nsTArray<uint8_t>& aKeyId) = 0;
virtual void SetCaps(uint64_t aCaps) = 0;
virtual void Decrypted(uint32_t aId,
GMPErr aResult,
const nsTArray<uint8_t>& aDecryptedData) = 0;
};
class GMPDecryptorProxy {
public:
~GMPDecryptorProxy() {}
virtual nsresult Init(GMPDecryptorProxyCallback* aCallback) = 0;
virtual void CreateSession(uint32_t aPromiseId,
const nsCString& aInitDataType,
const nsTArray<uint8_t>& aInitData,
GMPSessionType aSessionType) = 0;
virtual void LoadSession(uint32_t aPromiseId,
const nsCString& aSessionId) = 0;
virtual void UpdateSession(uint32_t aPromiseId,
const nsCString& aSessionId,
const nsTArray<uint8_t>& aResponse) = 0;
virtual void CloseSession(uint32_t aPromiseId,
const nsCString& aSessionId) = 0;
virtual void RemoveSession(uint32_t aPromiseId,
const nsCString& aSessionId) = 0;
virtual void SetServerCertificate(uint32_t aPromiseId,
const nsTArray<uint8_t>& aServerCert) = 0;
virtual void Decrypt(uint32_t aId,
const mp4_demuxer::CryptoSample& aCrypto,
const nsTArray<uint8_t>& aBuffer) = 0;
virtual void Close() = 0;
};
#endif // GMPDecryptorProxy_h_

View File

@ -0,0 +1,84 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "GMPEncryptedBufferDataImpl.h"
#include "mozilla/gmp/GMPTypes.h"
namespace mozilla {
namespace gmp {
GMPEncryptedBufferDataImpl::GMPEncryptedBufferDataImpl(const CryptoSample& aCrypto)
: mKeyId(aCrypto.key)
, mIV(aCrypto.iv)
, mClearBytes(aCrypto.plain_sizes)
, mCipherBytes(aCrypto.encrypted_sizes)
{
}
GMPEncryptedBufferDataImpl::GMPEncryptedBufferDataImpl(const GMPDecryptionData& aData)
{
mKeyId = aData.mKeyId();
mIV = aData.mIV();
mClearBytes = aData.mClearBytes();
mCipherBytes = aData.mCipherBytes();
MOZ_ASSERT(mClearBytes.Length() == mCipherBytes.Length());
}
void
GMPEncryptedBufferDataImpl::RelinquishData(GMPDecryptionData& aData)
{
aData.mKeyId() = Move(mKeyId);
aData.mIV() = Move(mIV);
aData.mClearBytes() = Move(mClearBytes);
aData.mCipherBytes() = Move(mCipherBytes);
}
const uint8_t*
GMPEncryptedBufferDataImpl::KeyId() const
{
return mKeyId.Elements();
}
uint32_t
GMPEncryptedBufferDataImpl::KeyIdSize() const
{
return mKeyId.Length();
}
const uint8_t*
GMPEncryptedBufferDataImpl::IV() const
{
return mIV.Elements();
}
uint32_t
GMPEncryptedBufferDataImpl::IVSize() const
{
return mIV.Length();
}
const uint16_t*
GMPEncryptedBufferDataImpl::ClearBytes() const
{
return mClearBytes.Elements();
}
const uint32_t*
GMPEncryptedBufferDataImpl::CipherBytes() const
{
return mCipherBytes.Elements();
}
uint32_t
GMPEncryptedBufferDataImpl::NumSubsamples() const
{
MOZ_ASSERT(mClearBytes.Length() == mCipherBytes.Length());
// Return the min of the two, to ensure there's not chance of array index
// out-of-bounds shenanigans.
return std::min<uint32_t>(mClearBytes.Length(), mCipherBytes.Length());
}
} // namespace gmp
} // namespace mozilla

View File

@ -0,0 +1,68 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef GMPEncryptedBufferDataImpl_h_
#define GMPEncryptedBufferDataImpl_h_
#include "gmp-decryption.h"
#include "mp4_demuxer/DecoderData.h"
#include "nsTArray.h"
#include "mozilla/gmp/GMPTypes.h"
namespace mozilla {
namespace gmp {
class GMPEncryptedBufferDataImpl : public GMPEncryptedBufferMetadata {
private:
typedef mp4_demuxer::CryptoSample CryptoSample;
public:
GMPEncryptedBufferDataImpl(const CryptoSample& aCrypto);
GMPEncryptedBufferDataImpl(const GMPDecryptionData& aData);
void RelinquishData(GMPDecryptionData& aData);
virtual const uint8_t* KeyId() const MOZ_OVERRIDE;
virtual uint32_t KeyIdSize() const MOZ_OVERRIDE;
virtual const uint8_t* IV() const MOZ_OVERRIDE;
virtual uint32_t IVSize() const MOZ_OVERRIDE;
virtual uint32_t NumSubsamples() const MOZ_OVERRIDE;
virtual const uint16_t* ClearBytes() const MOZ_OVERRIDE;
virtual const uint32_t* CipherBytes() const MOZ_OVERRIDE;
private:
nsTArray<uint8_t> mKeyId;
nsTArray<uint8_t> mIV;
nsTArray<uint16_t> mClearBytes;
nsTArray<uint32_t> mCipherBytes;
};
class GMPBufferImpl : public GMPBuffer {
public:
GMPBufferImpl(uint32_t aId, const nsTArray<uint8_t>& aData)
: mId(aId)
, mData(aData)
{
}
virtual uint32_t Id() const {
return mId;
}
virtual uint8_t* Data() {
return mData.Elements();
}
virtual uint32_t Size() const {
return mData.Length();
}
virtual void Resize(uint32_t aSize) {
mData.SetLength(aSize);
}
uint32_t mId;
nsTArray<uint8_t> mData;
};
} // namespace gmp
} // namespace mozilla
#endif // GMPEncryptedBufferDataImpl_h_

View File

@ -8,6 +8,7 @@
#include "gmp-video-codec.h"
#include "gmp-video-frame-encoded.h"
#include "gmp-decryption.h"
namespace IPC {
@ -18,6 +19,27 @@ struct ParamTraits<GMPErr>
GMPLastErr>
{};
struct GMPDomExceptionValidator {
static bool IsLegalValue(GMPDOMException aValue) {
switch (aValue) {
case kGMPNoModificationAllowedError:
case kGMPNotFoundError:
case kGMPNotSupportedError:
case kGMPInvalidStateError:
case kGMPSyntaxError:
case kGMPInvalidModificationError:
case kGMPInvalidAccessError:
case kGMPSecurityError:
case kGMPAbortError:
case kGMPQuotaExceededError:
case kGMPTimeoutError:
return true;
default:
return false;
}
}
};
template <>
struct ParamTraits<GMPVideoFrameType>
: public ContiguousEnumSerializer<GMPVideoFrameType,
@ -25,6 +47,18 @@ struct ParamTraits<GMPVideoFrameType>
kGMPSkipFrame>
{};
template<>
struct ParamTraits<GMPDOMException>
: public EnumSerializer<GMPDOMException, GMPDomExceptionValidator>
{};
template <>
struct ParamTraits<GMPSessionType>
: public ContiguousEnumSerializer<GMPSessionType,
kGMPTemporySession,
kGMPPersistentSession>
{};
template <>
struct ParamTraits<GMPVideoCodecComplexity>
: public ContiguousEnumSerializer<GMPVideoCodecComplexity,

View File

@ -127,7 +127,8 @@ GMPParent::CloseIfUnused()
mState == GMPStateLoaded ||
mState == GMPStateUnloading) &&
mVideoDecoders.IsEmpty() &&
mVideoEncoders.IsEmpty()) {
mVideoEncoders.IsEmpty() &&
mDecryptors.IsEmpty()) {
Shutdown();
}
}
@ -153,6 +154,11 @@ GMPParent::CloseActive(bool aDieWhenUnloaded)
mVideoEncoders[i - 1]->Shutdown();
}
// Invalidate and remove any remaining API objects.
for (uint32_t i = mDecryptors.Length(); i > 0; i--) {
mDecryptors[i - 1]->Shutdown();
}
// Note: the shutdown of the codecs is async! don't kill
// the plugin-container until they're all safely shut down via
// CloseIfUnused();
@ -225,6 +231,44 @@ GMPParent::VideoEncoderDestroyed(GMPVideoEncoderParent* aEncoder)
}
}
void
GMPParent::DecryptorDestroyed(GMPDecryptorParent* aSession)
{
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
MOZ_ALWAYS_TRUE(mDecryptors.RemoveElement(aSession));
// Recv__delete__ is on the stack, don't potentially destroy the top-level actor
// until after this has completed.
if (mDecryptors.IsEmpty()) {
nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &GMPParent::CloseIfUnused);
NS_DispatchToCurrentThread(event);
}
}
nsresult
GMPParent::GetGMPDecryptor(GMPDecryptorParent** aGMPDP)
{
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
if (!EnsureProcessLoaded()) {
return NS_ERROR_FAILURE;
}
PGMPDecryptorParent* pdp = SendPGMPDecryptorConstructor();
if (!pdp) {
return NS_ERROR_FAILURE;
}
GMPDecryptorParent* dp = static_cast<GMPDecryptorParent*>(pdp);
// This addref corresponds to the Proxy pointer the consumer is returned.
// It's dropped by calling Close() on the interface.
NS_ADDREF(dp);
mDecryptors.AppendElement(dp);
*aGMPDP = dp;
return NS_OK;
}
GMPState
GMPParent::State() const
{
@ -461,6 +505,22 @@ GMPParent::DeallocPGMPVideoEncoderParent(PGMPVideoEncoderParent* aActor)
return true;
}
PGMPDecryptorParent*
GMPParent::AllocPGMPDecryptorParent()
{
GMPDecryptorParent* ksp = new GMPDecryptorParent(this);
NS_ADDREF(ksp);
return ksp;
}
bool
GMPParent::DeallocPGMPDecryptorParent(PGMPDecryptorParent* aActor)
{
GMPDecryptorParent* ksp = static_cast<GMPDecryptorParent*>(aActor);
NS_RELEASE(ksp);
return true;
}
nsresult
ParseNextRecord(nsILineInputStream* aLineInputStream,
const nsCString& aPrefix,

View File

@ -7,6 +7,7 @@
#define GMPParent_h_
#include "GMPProcessParent.h"
#include "GMPDecryptorParent.h"
#include "GMPVideoDecoderParent.h"
#include "GMPVideoEncoderParent.h"
#include "mozilla/gmp/PGMPParent.h"
@ -73,10 +74,16 @@ public:
void DeleteProcess();
bool SupportsAPI(const nsCString& aAPI, const nsCString& aTag);
nsresult GetGMPVideoDecoder(GMPVideoDecoderParent** aGMPVD);
void VideoDecoderDestroyed(GMPVideoDecoderParent* aDecoder);
nsresult GetGMPVideoEncoder(GMPVideoEncoderParent** aGMPVE);
void VideoEncoderDestroyed(GMPVideoEncoderParent* aEncoder);
nsresult GetGMPDecryptor(GMPDecryptorParent** aGMPKS);
void DecryptorDestroyed(GMPDecryptorParent* aSession);
GMPState State() const;
#ifdef DEBUG
nsIThread* GMPThread();
@ -119,11 +126,16 @@ private:
virtual PCrashReporterParent* AllocPCrashReporterParent(const NativeThreadId& aThread) MOZ_OVERRIDE;
virtual bool DeallocPCrashReporterParent(PCrashReporterParent* aCrashReporter) MOZ_OVERRIDE;
virtual PGMPVideoDecoderParent* AllocPGMPVideoDecoderParent() MOZ_OVERRIDE;
virtual bool DeallocPGMPVideoDecoderParent(PGMPVideoDecoderParent* aActor) MOZ_OVERRIDE;
virtual PGMPVideoEncoderParent* AllocPGMPVideoEncoderParent() MOZ_OVERRIDE;
virtual bool DeallocPGMPVideoEncoderParent(PGMPVideoEncoderParent* aActor) MOZ_OVERRIDE;
virtual PGMPDecryptorParent* AllocPGMPDecryptorParent() MOZ_OVERRIDE;
virtual bool DeallocPGMPDecryptorParent(PGMPDecryptorParent* aActor) MOZ_OVERRIDE;
GMPState mState;
nsCOMPtr<nsIFile> mDirectory; // plugin directory on disk
nsString mName; // base name of plugin on disk, UTF-16 because used for paths
@ -136,6 +148,7 @@ private:
nsTArray<nsRefPtr<GMPVideoDecoderParent>> mVideoDecoders;
nsTArray<nsRefPtr<GMPVideoEncoderParent>> mVideoEncoders;
nsTArray<nsRefPtr<GMPDecryptorParent>> mDecryptors;
#ifdef DEBUG
nsCOMPtr<nsIThread> mGMPThread;
#endif

View File

@ -16,6 +16,7 @@
#include "nsNativeCharsetUtils.h"
#include "nsIConsoleService.h"
#include "mozilla/unused.h"
#include "GMPDecryptorParent.h"
namespace mozilla {
@ -285,6 +286,37 @@ GeckoMediaPluginService::GetGMPVideoEncoder(nsTArray<nsCString>* aTags,
return NS_OK;
}
NS_IMETHODIMP
GeckoMediaPluginService::GetGMPDecryptor(nsTArray<nsCString>* aTags,
const nsAString& aOrigin,
GMPDecryptorProxy** aDecryptor)
{
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
NS_ENSURE_ARG(aTags && aTags->Length() > 0);
NS_ENSURE_ARG(aDecryptor);
if (mShuttingDownOnGMPThread) {
return NS_ERROR_FAILURE;
}
nsRefPtr<GMPParent> gmp = SelectPluginForAPI(aOrigin,
NS_LITERAL_CSTRING("eme-decrypt"),
*aTags);
if (!gmp) {
return NS_ERROR_FAILURE;
}
GMPDecryptorParent* ksp;
nsresult rv = gmp->GetGMPDecryptor(&ksp);
if (NS_FAILED(rv)) {
return rv;
}
*aDecryptor = static_cast<GMPDecryptorProxy*>(ksp);
return NS_OK;
}
void
GeckoMediaPluginService::UnloadPlugins()
{

View File

@ -8,6 +8,13 @@ using GMPBufferType from "gmp-video-codec.h";
namespace mozilla {
namespace gmp {
struct GMPDecryptionData {
uint8_t[] mKeyId;
uint8_t[] mIV;
uint16_t[] mClearBytes;
uint32_t[] mCipherBytes;
};
struct GMPVideoEncodedFrameData
{
uint32_t mEncodedWidth;
@ -19,6 +26,7 @@ struct GMPVideoEncodedFrameData
GMPBufferType mBufferType;
Shmem mBuffer;
bool mCompleteFrame;
GMPDecryptionData mDecryptionData;
};
struct GMPPlaneData

View File

@ -6,6 +6,7 @@
include protocol PGMPVideoDecoder;
include protocol PGMPVideoEncoder;
include protocol PCrashReporter;
include protocol PGMPDecryptor;
using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
@ -14,6 +15,7 @@ namespace gmp {
intr protocol PGMP
{
manages PGMPDecryptor;
manages PGMPVideoDecoder;
manages PGMPVideoEncoder;
manages PCrashReporter;
@ -22,6 +24,7 @@ parent:
async PCrashReporter(NativeThreadId tid);
child:
async PGMPDecryptor();
async PGMPVideoDecoder();
async PGMPVideoEncoder();
};

View File

@ -0,0 +1,85 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 protocol PGMP;
include GMPTypes;
using GMPSessionType from "gmp-decryption.h";
using GMPDOMException from "gmp-decryption.h";
using GMPErr from "gmp-errors.h";
namespace mozilla {
namespace gmp {
async protocol PGMPDecryptor
{
manager PGMP;
child:
Init();
CreateSession(uint32_t aPromiseId,
nsCString aInitDataType,
uint8_t[] aInitData,
GMPSessionType aSessionType);
LoadSession(uint32_t aPromiseId,
nsCString aSessionId);
UpdateSession(uint32_t aPromiseId,
nsCString aSessionId,
uint8_t[] aResponse);
CloseSession(uint32_t aPromiseId,
nsCString aSessionId);
RemoveSession(uint32_t aPromiseId,
nsCString aSessionId);
SetServerCertificate(uint32_t aPromiseId,
uint8_t[] aServerCert);
Decrypt(uint32_t aId,
uint8_t[] aBuffer,
GMPDecryptionData aMetadata);
DecryptingComplete();
parent:
__delete__();
ResolveNewSessionPromise(uint32_t aPromiseId,
nsCString aSessionId);
ResolvePromise(uint32_t aPromiseId);
RejectPromise(uint32_t aPromiseId,
GMPDOMException aDOMExceptionCode,
nsCString aMessage);
SessionMessage(nsCString aSessionId,
uint8_t[] aMessage,
nsCString aDestinationURL);
ExpirationChange(nsCString aSessionId, double aExpiryTime);
SessionClosed(nsCString aSessionId);
SessionError(nsCString aSessionId,
GMPDOMException aDOMExceptionCode,
uint32_t aSystemCode,
nsCString aMessage);
KeyIdUsable(nsCString aSessionId, uint8_t[] aKey);
SetCaps(uint64_t aCaps);
KeyIdNotUsable(nsCString aSessionId,uint8_t[] aKey);
Decrypted(uint32_t aId, GMPErr aResult, uint8_t[] aBuffer);
};
} // namespace gmp
} // namespace mozilla

View File

@ -31,6 +31,10 @@ EXPORTS += [
'gmp-api/gmp-video-plane.h',
'GMPCallbackBase.h',
'GMPChild.h',
'GMPDecryptorChild.h',
'GMPDecryptorParent.h',
'GMPDecryptorProxy.h',
'GMPEncryptedBufferDataImpl.h',
'GMPMessageUtils.h',
'GMPParent.h',
'GMPPlatform.h',
@ -52,6 +56,9 @@ EXPORTS += [
UNIFIED_SOURCES += [
'GMPChild.cpp',
'GMPDecryptorChild.cpp',
'GMPDecryptorParent.cpp',
'GMPEncryptedBufferDataImpl.cpp',
'GMPParent.cpp',
'GMPPlatform.cpp',
'GMPProcessChild.cpp',
@ -71,6 +78,7 @@ UNIFIED_SOURCES += [
IPDL_SOURCES += [
'GMPTypes.ipdlh',
'PGMP.ipdl',
'PGMPDecryptor.ipdl',
'PGMPVideoDecoder.ipdl',
'PGMPVideoEncoder.ipdl',
]

View File

@ -10,6 +10,7 @@
%{C++
#include "nsTArray.h"
#include "nsStringGlue.h"
class GMPDecryptorProxy;
class GMPVideoDecoderProxy;
class GMPVideoEncoderProxy;
class GMPVideoHost;
@ -20,8 +21,9 @@ class GMPVideoHost;
[ptr] native GMPVideoHost(GMPVideoHost);
[ptr] native MessageLoop(MessageLoop);
[ptr] native TagArray(nsTArray<nsCString>);
[ptr] native GMPDecryptorProxy(GMPDecryptorProxy);
[scriptable, uuid(a9b826da-725a-4b81-814f-b715445188f2)]
[scriptable, uuid(b301ea8b-8a1e-4839-a13c-9dd32b2d684b)]
interface mozIGeckoMediaPluginService : nsISupports
{
/**
@ -60,6 +62,12 @@ interface mozIGeckoMediaPluginService : nsISupports
[optional] in AString origin,
out GMPVideoHost outVideoHost);
// Returns a decryption session manager that supports the specified tags.
// The array of tags should at least contain a key system tag, and optionally
// other tags.
// Callable only on GMP thread.
GMPDecryptorProxy getGMPDecryptor(in TagArray tags, in AString origin);
/**
* Add a directory to scan for gecko media plugins.
* @note Main-thread API.