Bug 1724751 - Plumb key system arg to CDM creation. r=alwu

This enables us to use CDMs that support multiple key systems. E.g. if we have a
CDM that supports keySystem1 and keySystem2, and it needs to know which key
system we want, this lets us tell it which.

This exact case can be used to let us have a more flexible and configurable
clearkey CDM with differently behaved key systems for specific tests.

Differential Revision: https://phabricator.services.mozilla.com/D122137
This commit is contained in:
Bryce Seager van Dyk 2021-08-10 14:54:02 +00:00
Родитель 260bbe6069
Коммит ffe6a8ce4d
12 изменённых файлов: 48 добавлений и 30 удалений

Просмотреть файл

@ -101,9 +101,14 @@ GMPErr ChromiumCDMAdapter::GMPInit(const GMPPlatformAPI* aPlatformAPI) {
}
GMPErr ChromiumCDMAdapter::GMPGetAPI(const char* aAPIName, void* aHostAPI,
void** aPluginAPI) {
GMP_LOG_DEBUG("ChromiumCDMAdapter::GMPGetAPI(%s, 0x%p, 0x%p) this=0x%p",
aAPIName, aHostAPI, aPluginAPI, this);
void** aPluginAPI,
const nsCString& aKeySystem) {
MOZ_ASSERT(aKeySystem.EqualsLiteral(EME_KEY_SYSTEM_WIDEVINE) ||
aKeySystem.EqualsLiteral(EME_KEY_SYSTEM_CLEARKEY),
"Should not get an unrecognized key system. Why didn't it get "
"blocked by MediaKeySystemAccess?");
GMP_LOG_DEBUG("ChromiumCDMAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %s) this=0x%p",
aAPIName, aHostAPI, aPluginAPI, aKeySystem.get(), this);
bool isCdm10 = !strcmp(aAPIName, CHROMIUM_CDM_API);
if (!isCdm10) {
@ -125,8 +130,7 @@ GMPErr ChromiumCDMAdapter::GMPGetAPI(const char* aAPIName, void* aHostAPI,
}
const int version = cdm::ContentDecryptionModule_10::kVersion;
void* cdm = create(version, EME_KEY_SYSTEM_WIDEVINE,
mozilla::ArrayLength(EME_KEY_SYSTEM_WIDEVINE) - 1,
void* cdm = create(version, aKeySystem.get(), aKeySystem.Length(),
&ChromiumCdmHost, aHostAPI);
if (!cdm) {
GMP_LOG_DEBUG(

Просмотреть файл

@ -61,8 +61,8 @@ class ChromiumCDMAdapter : public gmp::GMPAdapter {
// These are called in place of the corresponding GMP API functions.
GMPErr GMPInit(const GMPPlatformAPI* aPlatformAPI) override;
GMPErr GMPGetAPI(const char* aAPIName, void* aHostAPI,
void** aPluginAPI) override;
GMPErr GMPGetAPI(const char* aAPIName, void* aHostAPI, void** aPluginAPI,
const nsCString& aKeySystem) override;
void GMPShutdown() override;
static bool Supports(int32_t aModuleVersion, int32_t aInterfaceVersion,

Просмотреть файл

@ -188,12 +188,12 @@ mozilla::ipc::IPCResult GMPChild::RecvProvideStorageId(
return IPC_OK();
}
GMPErr GMPChild::GetAPI(const char* aAPIName, void* aHostAPI,
void** aPluginAPI) {
GMPErr GMPChild::GetAPI(const char* aAPIName, void* aHostAPI, void** aPluginAPI,
const nsCString aKeySystem) {
if (!mGMPLoader) {
return GMPGenericErr;
}
return mGMPLoader->GetAPI(aAPIName, aHostAPI, aPluginAPI);
return mGMPLoader->GetAPI(aAPIName, aHostAPI, aPluginAPI, aKeySystem);
}
mozilla::ipc::IPCResult GMPChild::RecvPreloadLibs(const nsCString& aLibs) {

Просмотреть файл

@ -64,7 +64,8 @@ class GMPChild : public PGMPChild {
void ActorDestroy(ActorDestroyReason aWhy) override;
void ProcessingError(Result aCode, const char* aReason) override;
GMPErr GetAPI(const char* aAPIName, void* aHostAPI, void** aPluginAPI);
GMPErr GetAPI(const char* aAPIName, void* aHostAPI, void** aPluginAPI,
const nsCString aKeySystem = ""_ns);
nsTArray<std::pair<nsCString, nsCString>> MakeCDMHostVerificationPaths();

Просмотреть файл

@ -50,7 +50,8 @@ GMPContentChild::AllocPGMPVideoEncoderChild() {
return MakeAndAddRef<GMPVideoEncoderChild>(this);
}
already_AddRefed<PChromiumCDMChild> GMPContentChild::AllocPChromiumCDMChild() {
already_AddRefed<PChromiumCDMChild> GMPContentChild::AllocPChromiumCDMChild(
const nsCString& aKeySystem) {
return MakeAndAddRef<ChromiumCDMChild>(this);
}
@ -87,12 +88,12 @@ mozilla::ipc::IPCResult GMPContentChild::RecvPGMPVideoEncoderConstructor(
}
mozilla::ipc::IPCResult GMPContentChild::RecvPChromiumCDMConstructor(
PChromiumCDMChild* aActor) {
PChromiumCDMChild* aActor, const nsCString& aKeySystem) {
ChromiumCDMChild* child = static_cast<ChromiumCDMChild*>(aActor);
cdm::Host_10* host10 = child;
void* cdm = nullptr;
GMPErr err = mGMPChild->GetAPI(CHROMIUM_CDM_API, host10, &cdm);
GMPErr err = mGMPChild->GetAPI(CHROMIUM_CDM_API, host10, &cdm, aKeySystem);
if (err != GMPNoErr || !cdm) {
NS_WARNING("GMPGetAPI call failed trying to get CDM.");
return IPC_FAIL_NO_REASON(this);

Просмотреть файл

@ -33,13 +33,14 @@ class GMPContentChild : public PGMPContentChild, public GMPSharedMem {
mozilla::ipc::IPCResult RecvPGMPVideoEncoderConstructor(
PGMPVideoEncoderChild* aActor) override;
mozilla::ipc::IPCResult RecvPChromiumCDMConstructor(
PChromiumCDMChild* aActor) override;
PChromiumCDMChild* aActor, const nsCString& aKeySystem) override;
already_AddRefed<PGMPVideoDecoderChild> AllocPGMPVideoDecoderChild();
already_AddRefed<PGMPVideoEncoderChild> AllocPGMPVideoEncoderChild();
already_AddRefed<PChromiumCDMChild> AllocPChromiumCDMChild();
already_AddRefed<PChromiumCDMChild> AllocPChromiumCDMChild(
const nsCString& aKeySystem);
#if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
mozilla::ipc::IPCResult RecvInitSandboxTesting(

Просмотреть файл

@ -148,11 +148,13 @@ nsCOMPtr<nsISerialEventTarget> GMPContentParent::GMPEventTarget() {
return mGMPEventTarget;
}
already_AddRefed<ChromiumCDMParent> GMPContentParent::GetChromiumCDM() {
GMP_LOG_DEBUG("GMPContentParent::GetChromiumCDM(this=%p)", this);
already_AddRefed<ChromiumCDMParent> GMPContentParent::GetChromiumCDM(
const nsCString& aKeySystem) {
GMP_LOG_DEBUG("GMPContentParent::GetChromiumCDM(this=%p aKeySystem=%s)", this,
aKeySystem.get());
RefPtr<ChromiumCDMParent> parent = new ChromiumCDMParent(this, GetPluginId());
if (!SendPChromiumCDMConstructor(parent)) {
if (!SendPChromiumCDMConstructor(parent, aKeySystem)) {
return nullptr;
}

Просмотреть файл

@ -34,7 +34,8 @@ class GMPContentParent final : public PGMPContentParent, public GMPSharedMem {
nsresult GetGMPVideoEncoder(GMPVideoEncoderParent** aGMPVE);
void VideoEncoderDestroyed(GMPVideoEncoderParent* aEncoder);
already_AddRefed<ChromiumCDMParent> GetChromiumCDM();
already_AddRefed<ChromiumCDMParent> GetChromiumCDM(
const nsCString& aKeySystem);
void ChromiumCDMDestroyed(ChromiumCDMParent* aCDM);
nsCOMPtr<nsISerialEventTarget> GMPEventTarget();

Просмотреть файл

@ -49,8 +49,8 @@ class PassThroughGMPAdapter : public GMPAdapter {
return initFunc(aPlatformAPI);
}
GMPErr GMPGetAPI(const char* aAPIName, void* aHostAPI,
void** aPluginAPI) override {
GMPErr GMPGetAPI(const char* aAPIName, void* aHostAPI, void** aPluginAPI,
const nsCString& /* aKeySystem */) override {
if (!mLib) {
return GMPGenericErr;
}
@ -121,8 +121,8 @@ bool GMPLoader::Load(const char* aUTF8LibPath, uint32_t aUTF8LibPathLen,
}
GMPErr GMPLoader::GetAPI(const char* aAPIName, void* aHostAPI,
void** aPluginAPI) {
return mAdapter->GMPGetAPI(aAPIName, aHostAPI, aPluginAPI);
void** aPluginAPI, const nsCString& aKeySystem) {
return mAdapter->GMPGetAPI(aAPIName, aHostAPI, aPluginAPI, aKeySystem);
}
void GMPLoader::Shutdown() {

Просмотреть файл

@ -11,6 +11,7 @@
#include "prlink.h"
#include "gmp-entrypoints.h"
#include "mozilla/UniquePtr.h"
#include "nsString.h"
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
# include "mozilla/Sandbox.h"
@ -36,8 +37,11 @@ class GMPAdapter {
// These are called in place of the corresponding GMP API functions.
virtual GMPErr GMPInit(const GMPPlatformAPI* aPlatformAPI) = 0;
// The `aKeySystem` arg is used to specify the key system when loading CDMs,
// and will be ignored by non-CDM GMPs. It is not part of the public GMP API
// Gecko exposes.
virtual GMPErr GMPGetAPI(const char* aAPIName, void* aHostAPI,
void** aPluginAPI) = 0;
void** aPluginAPI, const nsCString& aKeySystem) = 0;
virtual void GMPShutdown() = 0;
};
@ -55,8 +59,11 @@ class GMPLoader {
bool Load(const char* aUTF8LibPath, uint32_t aLibPathLen,
const GMPPlatformAPI* aPlatformAPI, GMPAdapter* aAdapter = nullptr);
// Retrieves an interface pointer from the GMP.
GMPErr GetAPI(const char* aAPIName, void* aHostAPI, void** aPluginAPI);
// Retrieves an interface pointer from the GMP. If the GMP is loading a CDM,
// aKeySystem is passed to the CDM to allow for key system specific
// configuration by the CDM.
GMPErr GetAPI(const char* aAPIName, void* aHostAPI, void** aPluginAPI,
const nsCString& aKeySystem);
// Calls the GMPShutdown function exported by the GMP lib, and unloads the
// plugin library.

Просмотреть файл

@ -232,13 +232,14 @@ RefPtr<GetCDMParentPromise> GeckoMediaPluginService::GetCDM(
nsLiteralCString(CHROMIUM_CDM_API), tags)
->Then(
thread, __func__,
[rawHolder, helper](RefPtr<GMPContentParent::CloseBlocker> wrapper) {
[rawHolder, helper, keySystem = nsCString{aKeySystem}](
RefPtr<GMPContentParent::CloseBlocker> wrapper) {
RefPtr<GMPContentParent> parent = wrapper->mParent;
MOZ_ASSERT(
parent,
"Wrapper should wrap a valid parent if we're in this path.");
UniquePtr<PromiseHolder> holder(rawHolder);
RefPtr<ChromiumCDMParent> cdm = parent->GetChromiumCDM();
RefPtr<ChromiumCDMParent> cdm = parent->GetChromiumCDM(keySystem);
if (!cdm) {
nsPrintfCString reason(
"%s::%s failed since GetChromiumCDM returns nullptr.",

Просмотреть файл

@ -23,7 +23,7 @@ namespace gmp {
child:
async PGMPVideoDecoder();
async PGMPVideoEncoder();
async PChromiumCDM();
async PChromiumCDM(nsCString aKeySystem);
#if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
async InitSandboxTesting(Endpoint<PSandboxTestingChild> aEndpoint);