/* -*- 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 "GMPContentChild.h" #include "GMPChild.h" #include "GMPAudioDecoderChild.h" #include "GMPDecryptorChild.h" #include "GMPVideoDecoderChild.h" #include "GMPVideoEncoderChild.h" namespace mozilla { namespace gmp { GMPContentChild::GMPContentChild(GMPChild* aChild) : mGMPChild(aChild) { MOZ_COUNT_CTOR(GMPContentChild); } GMPContentChild::~GMPContentChild() { MOZ_COUNT_DTOR(GMPContentChild); XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new DeleteTask(GetTransport())); } MessageLoop* GMPContentChild::GMPMessageLoop() { return mGMPChild->GMPMessageLoop(); } void GMPContentChild::CheckThread() { MOZ_ASSERT(mGMPChild->mGMPMessageLoop == MessageLoop::current()); } void GMPContentChild::ActorDestroy(ActorDestroyReason aWhy) { mGMPChild->GMPContentChildActorDestroy(this); } void GMPContentChild::ProcessingError(Result aCode, const char* aReason) { mGMPChild->ProcessingError(aCode, aReason); } PGMPAudioDecoderChild* GMPContentChild::AllocPGMPAudioDecoderChild() { return new GMPAudioDecoderChild(this); } bool GMPContentChild::DeallocPGMPAudioDecoderChild(PGMPAudioDecoderChild* aActor) { delete aActor; return true; } PGMPDecryptorChild* GMPContentChild::AllocPGMPDecryptorChild() { GMPDecryptorChild* actor = new GMPDecryptorChild(this, mGMPChild->mPluginVoucher, mGMPChild->mSandboxVoucher); actor->AddRef(); return actor; } bool GMPContentChild::DeallocPGMPDecryptorChild(PGMPDecryptorChild* aActor) { static_cast(aActor)->Release(); return true; } PGMPVideoDecoderChild* GMPContentChild::AllocPGMPVideoDecoderChild() { GMPVideoDecoderChild* actor = new GMPVideoDecoderChild(this); actor->AddRef(); return actor; } bool GMPContentChild::DeallocPGMPVideoDecoderChild(PGMPVideoDecoderChild* aActor) { static_cast(aActor)->Release(); return true; } PGMPVideoEncoderChild* GMPContentChild::AllocPGMPVideoEncoderChild() { GMPVideoEncoderChild* actor = new GMPVideoEncoderChild(this); actor->AddRef(); return actor; } bool GMPContentChild::DeallocPGMPVideoEncoderChild(PGMPVideoEncoderChild* aActor) { static_cast(aActor)->Release(); return true; } bool GMPContentChild::RecvPGMPDecryptorConstructor(PGMPDecryptorChild* aActor) { GMPDecryptorChild* child = static_cast(aActor); GMPDecryptorHost* host = static_cast(child); void* session = nullptr; GMPErr err = mGMPChild->GetAPI(GMP_API_DECRYPTOR, host, &session); if (err != GMPNoErr || !session) { // We Adapt the previous GMPDecryptor version to the current, so that // Gecko thinks it's only talking to the current version. Helpfully, // v7 is ABI compatible with v8, it only has different enumerations. // If the GMP uses a v8-only enum value in an IPDL message, the IPC // layer will terminate, so we rev'd the API version to signal to the // GMP that it's safe to use the new enum values. err = mGMPChild->GetAPI(GMP_API_DECRYPTOR_BACKWARDS_COMPAT, host, &session); if (err != GMPNoErr || !session) { return false; } } child->Init(static_cast(session)); return true; } bool GMPContentChild::RecvPGMPAudioDecoderConstructor(PGMPAudioDecoderChild* aActor) { auto vdc = static_cast(aActor); void* vd = nullptr; GMPErr err = mGMPChild->GetAPI(GMP_API_AUDIO_DECODER, &vdc->Host(), &vd); if (err != GMPNoErr || !vd) { return false; } vdc->Init(static_cast(vd)); return true; } bool GMPContentChild::RecvPGMPVideoDecoderConstructor(PGMPVideoDecoderChild* aActor) { auto vdc = static_cast(aActor); void* vd = nullptr; GMPErr err = mGMPChild->GetAPI(GMP_API_VIDEO_DECODER, &vdc->Host(), &vd); if (err != GMPNoErr || !vd) { NS_WARNING("GMPGetAPI call failed trying to construct decoder."); return false; } vdc->Init(static_cast(vd)); return true; } bool GMPContentChild::RecvPGMPVideoEncoderConstructor(PGMPVideoEncoderChild* aActor) { auto vec = static_cast(aActor); void* ve = nullptr; GMPErr err = mGMPChild->GetAPI(GMP_API_VIDEO_ENCODER, &vec->Host(), &ve); if (err != GMPNoErr || !ve) { NS_WARNING("GMPGetAPI call failed trying to construct encoder."); return false; } vec->Init(static_cast(ve)); return true; } void GMPContentChild::CloseActive() { // Invalidate and remove any remaining API objects. const ManagedContainer& audioDecoders = ManagedPGMPAudioDecoderChild(); for (auto iter = audioDecoders.ConstIter(); !iter.Done(); iter.Next()) { iter.Get()->GetKey()->SendShutdown(); } const ManagedContainer& decryptors = ManagedPGMPDecryptorChild(); for (auto iter = decryptors.ConstIter(); !iter.Done(); iter.Next()) { iter.Get()->GetKey()->SendShutdown(); } const ManagedContainer& videoDecoders = ManagedPGMPVideoDecoderChild(); for (auto iter = videoDecoders.ConstIter(); !iter.Done(); iter.Next()) { iter.Get()->GetKey()->SendShutdown(); } const ManagedContainer& videoEncoders = ManagedPGMPVideoEncoderChild(); for (auto iter = videoEncoders.ConstIter(); !iter.Done(); iter.Next()) { iter.Get()->GetKey()->SendShutdown(); } } bool GMPContentChild::IsUsed() { return !ManagedPGMPAudioDecoderChild().IsEmpty() || !ManagedPGMPDecryptorChild().IsEmpty() || !ManagedPGMPVideoDecoderChild().IsEmpty() || !ManagedPGMPVideoEncoderChild().IsEmpty(); } } // namespace gmp } // namespace mozilla