GMPErr ChromiumCDMAdapter::GMPInit(const GMPPlatformAPI* aPlatformAPI) { GMP_LOG("ChromiumCDMAdapter::GMPInit"); sPlatform = aPlatformAPI; if (!mLib) { return GMPGenericErr; } #ifdef MOZILLA_OFFICIAL // Note: we must call the VerifyCdmHost_0 function if it's present before // we call the initialize function. auto verify = reinterpret_cast<decltype(::VerifyCdmHost_0)*>( PR_FindFunctionSymbol(mLib, STRINGIFY(VerifyCdmHost_0))); if (verify) { nsTArray<cdm::HostFile> files; for (HostFileData& hostFile : mHostFiles) { files.AppendElement(TakeToCDMHostFile(hostFile)); } bool result = verify(files.Elements(), files.Length()); GMP_LOG("%s VerifyCdmHost_0 returned %d", __func__, result); } #endif auto init = reinterpret_cast<decltype(::INITIALIZE_CDM_MODULE)*>( PR_FindFunctionSymbol(mLib, STRINGIFY(INITIALIZE_CDM_MODULE))); if (!init) { return GMPGenericErr; } GMP_LOG(STRINGIFY(INITIALIZE_CDM_MODULE) "()"); init(); return GMPNoErr; }
void ChromiumCDMAdapter::GMPShutdown() { GMP_LOG("ChromiumCDMAdapter::GMPShutdown()"); decltype(::DeinitializeCdmModule)* deinit; deinit = (decltype(deinit))(PR_FindFunctionSymbol(mLib, "DeinitializeCdmModule")); if (deinit) { GMP_LOG("DeinitializeCdmModule()"); deinit(); } }
GMPErr ChromiumCDMAdapter::GMPGetAPI(const char* aAPIName, void* aHostAPI, void** aPluginAPI, uint32_t aDecryptorId) { GMP_LOG("ChromiumCDMAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p", aAPIName, aHostAPI, aPluginAPI, aDecryptorId, this); bool isCDM9 = !strcmp(aAPIName, CHROMIUM_CDM_API); bool isCDM8 = !strcmp(aAPIName, CHROMIUM_CDM_API_BACKWARD_COMPAT); if (isCDM8 || isCDM9) { auto create = reinterpret_cast<decltype(::CreateCdmInstance)*>( PR_FindFunctionSymbol(mLib, "CreateCdmInstance")); if (!create) { GMP_LOG("ChromiumCDMAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p " "FAILED to find CreateCdmInstance", aAPIName, aHostAPI, aPluginAPI, aDecryptorId, this); return GMPGenericErr; } int version = isCDM8 ? cdm::ContentDecryptionModule_8::kVersion : cdm::ContentDecryptionModule_9::kVersion; void* cdm = create(version, kEMEKeySystemWidevine.get(), kEMEKeySystemWidevine.Length(), &ChromiumCdmHost, aHostAPI); if (!cdm) { GMP_LOG("ChromiumCDMAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p " "FAILED to create cdm version %d", aAPIName, aHostAPI, aPluginAPI, aDecryptorId, this, version); return GMPGenericErr; } GMP_LOG("cdm: 0x%p, version: %d", cdm, version); *aPluginAPI = cdm; } return *aPluginAPI ? GMPNoErr : GMPNotImplementedErr; }
PGMPVideoDecoderParent* GMPContentParent::AllocPGMPVideoDecoderParent( const uint32_t& aDecryptorId) { GMP_LOG("GMPContentParent::AllocPGMPVideoDecoderParent(this=%p)", this); GMPVideoDecoderParent* vdp = new GMPVideoDecoderParent(this); NS_ADDREF(vdp); return vdp; }
void GMPContentParent::ActorDestroy(ActorDestroyReason aWhy) { GMP_LOG("GMPContentParent::ActorDestroy(this=%p, aWhy=%d)", this, static_cast<int>(aWhy)); MOZ_ASSERT(mVideoDecoders.IsEmpty() && mVideoEncoders.IsEmpty() && mChromiumCDMs.IsEmpty()); NS_DispatchToCurrentThread(new ReleaseGMPContentParent(this)); }
void GMPContentParent::AddCloseBlocker() { MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread()); ++mCloseBlockerCount; GMP_LOG( "GMPContentParent::AddCloseBlocker(this=%p) mCloseBlockerCount=%" PRIu32, this, mCloseBlockerCount); }
bool GMPContentParent::DeallocPChromiumCDMParent(PChromiumCDMParent* aActor) { GMP_LOG("GMPContentParent::DeallocPChromiumCDMParent(this=%p, aActor=%p)", this, aActor); ChromiumCDMParent* parent = static_cast<ChromiumCDMParent*>(aActor); NS_RELEASE(parent); return true; }
bool GMPContentParent::DeallocPGMPVideoEncoderParent( PGMPVideoEncoderParent* aActor) { GMP_LOG("GMPContentParent::DeallocPGMPVideoEncoderParent(this=%p, aActor=%p)", this, aActor); GMPVideoEncoderParent* vep = static_cast<GMPVideoEncoderParent*>(aActor); NS_RELEASE(vep); return true; }
void GMPContentParent::ChromiumCDMDestroyed(ChromiumCDMParent* aCDM) { GMP_LOG("GMPContentParent::ChromiumCDMDestroyed(this=%p, aCDM=%p)", this, aCDM); MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread()); MOZ_ALWAYS_TRUE(mChromiumCDMs.RemoveElement(aCDM)); CloseIfUnused(); }
void GMPContentParent::RemoveCloseBlocker() { MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread()); --mCloseBlockerCount; GMP_LOG( "GMPContentParent::RemoveCloseBlocker(this=%p) " "mCloseBlockerCount=%" PRIu32, this, mCloseBlockerCount); CloseIfUnused(); }
void GMPContentParent::VideoEncoderDestroyed(GMPVideoEncoderParent* aEncoder) { GMP_LOG("GMPContentParent::VideoEncoderDestroyed(this=%p, aEncoder=%p)", this, aEncoder); MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread()); // If the constructor fails, we'll get called before it's added Unused << NS_WARN_IF(!mVideoEncoders.RemoveElement(aEncoder)); CloseIfUnused(); }
GMPContentParent::~GMPContentParent() { GMP_LOG( "GMPContentParent::~GMPContentParent(this=%p) mVideoDecoders.IsEmpty=%s, " "mVideoEncoders.IsEmpty=%s, mChromiumCDMs.IsEmpty=%s, " "mCloseBlockerCount=%" PRIu32, this, GetBoolString(mVideoDecoders.IsEmpty()), GetBoolString(mVideoEncoders.IsEmpty()), GetBoolString(mChromiumCDMs.IsEmpty()), mCloseBlockerCount); }
GMPContentParent::GMPContentParent(GMPParent* aParent) : mParent(aParent), mPluginId(0) { GMP_LOG("GMPContentParent::GMPContentParent(this=%p), aParent=%p", this, aParent); if (mParent) { SetDisplayName(mParent->GetDisplayName()); SetPluginId(mParent->GetPluginId()); } }
void* ChromiumCdmHost(int aHostInterfaceVersion, void* aUserData) { GMP_LOG("ChromiumCdmHostFunc(%d, %p)", aHostInterfaceVersion, aUserData); if (aHostInterfaceVersion != cdm::Host_8::kVersion && aHostInterfaceVersion != cdm::Host_9::kVersion) { return nullptr; } return aUserData; }
already_AddRefed<ChromiumCDMParent> GMPContentParent::GetChromiumCDM() { GMP_LOG("GMPContentParent::GetChromiumCDM(this=%p)", this); PChromiumCDMParent* actor = SendPChromiumCDMConstructor(); if (!actor) { return nullptr; } RefPtr<ChromiumCDMParent> parent = static_cast<ChromiumCDMParent*>(actor); // TODO: Remove parent from mChromiumCDMs in ChromiumCDMParent::Destroy(). mChromiumCDMs.AppendElement(parent); return parent.forget(); }
nsresult GMPContentParent::GetGMPVideoEncoder(GMPVideoEncoderParent** aGMPVE) { GMP_LOG("GMPContentParent::GetGMPVideoEncoder(this=%p)", this); // returned with one anonymous AddRef that locks it until Destroy PGMPVideoEncoderParent* pvep = SendPGMPVideoEncoderConstructor(); if (!pvep) { return NS_ERROR_FAILURE; } GMPVideoEncoderParent* vep = static_cast<GMPVideoEncoderParent*>(pvep); // This addref corresponds to the Proxy pointer the consumer is returned. // It's dropped by calling Close() on the interface. NS_ADDREF(vep); *aGMPVE = vep; mVideoEncoders.AppendElement(vep); return NS_OK; }
DWORD WINAPI QueryDosDeviceWHook(LPCWSTR lpDeviceName, LPWSTR lpTargetPath, DWORD ucchMax) { if (!sDeviceNames) { return 0; } std::wstring name = std::wstring(lpDeviceName); auto iter = sDeviceNames->find(name); if (iter == sDeviceNames->end()) { return 0; } const std::wstring& device = iter->second; if (device.size() + 1 > ucchMax) { return 0; } PodCopy(lpTargetPath, device.c_str(), device.size()); lpTargetPath[device.size()] = 0; GMP_LOG("QueryDosDeviceWHook %S -> %S", lpDeviceName, lpTargetPath); return name.size(); }
nsCOMPtr<nsISerialEventTarget> GMPContentParent::GMPEventTarget() { if (!mGMPEventTarget) { GMP_LOG("GMPContentParent::GMPEventTarget(this=%p)", this); nsCOMPtr<mozIGeckoMediaPluginService> mps = do_GetService("@mozilla.org/gecko-media-plugin-service;1"); MOZ_ASSERT(mps); if (!mps) { return nullptr; } // Not really safe if we just grab to the mGMPEventTarget, as we don't know // what thread we're running on and other threads may be trying to // access this without locks! However, debug only, and primary failure // mode outside of compiler-helped TSAN is a leak. But better would be // to use swap() under a lock. nsCOMPtr<nsIThread> gmpThread; mps->GetThread(getter_AddRefs(gmpThread)); MOZ_ASSERT(gmpThread); mGMPEventTarget = gmpThread->SerialEventTarget(); } return mGMPEventTarget; }
void GMPContentParent::CloseIfUnused() { GMP_LOG( "GMPContentParent::CloseIfUnused(this=%p) mVideoDecoders.IsEmpty=%s, " "mVideoEncoders.IsEmpty=%s, mChromiumCDMs.IsEmpty=%s, " "mCloseBlockerCount=%" PRIu32, this, GetBoolString(mVideoDecoders.IsEmpty()), GetBoolString(mVideoEncoders.IsEmpty()), GetBoolString(mChromiumCDMs.IsEmpty()), mCloseBlockerCount); if (mVideoDecoders.IsEmpty() && mVideoEncoders.IsEmpty() && mChromiumCDMs.IsEmpty() && mCloseBlockerCount == 0) { RefPtr<GMPContentParent> toClose; if (mParent) { toClose = mParent->ForgetGMPContentParent(); } else { toClose = this; RefPtr<GeckoMediaPluginServiceChild> gmp( GeckoMediaPluginServiceChild::GetSingleton()); gmp->RemoveGMPContentParent(toClose); } NS_DispatchToCurrentThread(NewRunnableMethod( "gmp::GMPContentParent::Close", toClose, &GMPContentParent::Close)); } }
PChromiumCDMParent* GMPContentParent::AllocPChromiumCDMParent() { GMP_LOG("GMPContentParent::AllocPChromiumCDMParent(this=%p)", this); ChromiumCDMParent* parent = new ChromiumCDMParent(this, GetPluginId()); NS_ADDREF(parent); return parent; }
PGMPVideoEncoderParent* GMPContentParent::AllocPGMPVideoEncoderParent() { GMP_LOG("GMPContentParent::AllocPGMPVideoEncoderParent(this=%p)", this); GMPVideoEncoderParent* vep = new GMPVideoEncoderParent(this); NS_ADDREF(vep); return vep; }