зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1491889 - Update chromium CDM interface to accommodate async init. r=cpearce
Starting at the Widevine CDM10 interface, the CDM is expected to make a callback to an `OnInititalized` function to signal initialization has taken place. Prior to this, it was sufficient to call the init function on the CDM, with no waiting for a callback. This changeset puts in place the IPDL to support async init, as well as the handling for the ChromiumCDMParent and ChromiumCDMProxy. The code is not fully updated to handle CDM10, so CDM9 is the only compatible CDM. Because CDM9 does not perform the init callback, we immediately call our IPDL to signal init has taken place. This also accommodates the clearkey case, which uses the CDM9 interface. Further changesets will put in place more elaborate handling to accommodate the possible failure of init, as well as implementing the handling `OnInitialized` function explicitly. Differential Revision: https://phabricator.services.mozilla.com/D6061 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
03ab113d02
Коммит
2fe058b38b
|
@ -454,7 +454,8 @@ ChromiumCDMChild::RecvPurgeShmems()
|
|||
|
||||
mozilla::ipc::IPCResult
|
||||
ChromiumCDMChild::RecvInit(const bool& aAllowDistinctiveIdentifier,
|
||||
const bool& aAllowPersistentState)
|
||||
const bool& aAllowPersistentState,
|
||||
InitResolver&& aResolver)
|
||||
{
|
||||
MOZ_ASSERT(IsOnMessageLoopThread());
|
||||
GMP_LOG("ChromiumCDMChild::RecvInit(distinctiveId=%s, persistentState=%s)",
|
||||
|
@ -467,6 +468,7 @@ ChromiumCDMChild::RecvInit(const bool& aAllowDistinctiveIdentifier,
|
|||
// We do not yet support hardware secure codecs
|
||||
false);
|
||||
}
|
||||
aResolver(true /* unused */);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
|
|
@ -89,7 +89,8 @@ protected:
|
|||
ipc::IPCResult RecvPurgeShmems() override;
|
||||
void PurgeShmems();
|
||||
ipc::IPCResult RecvInit(const bool& aAllowDistinctiveIdentifier,
|
||||
const bool& aAllowPersistentState) override;
|
||||
const bool& aAllowPersistentState,
|
||||
InitResolver&& aResolver) override;
|
||||
ipc::IPCResult RecvSetServerCertificate(
|
||||
const uint32_t& aPromiseId,
|
||||
nsTArray<uint8_t>&& aServerCert) override;
|
||||
|
|
|
@ -41,47 +41,75 @@ ChromiumCDMParent::ChromiumCDMParent(GMPContentParent* aContentParent,
|
|||
aPluginId);
|
||||
}
|
||||
|
||||
bool
|
||||
RefPtr<ChromiumCDMParent::InitPromise>
|
||||
ChromiumCDMParent::Init(ChromiumCDMCallback* aCDMCallback,
|
||||
bool aAllowDistinctiveIdentifier,
|
||||
bool aAllowPersistentState,
|
||||
nsIEventTarget* aMainThread,
|
||||
nsCString& aOutFailureReason)
|
||||
nsIEventTarget* aMainThread)
|
||||
{
|
||||
GMP_LOG("ChromiumCDMParent::Init(this=%p) shutdown=%d abormalShutdown=%d "
|
||||
"actorDestroyed=%d",
|
||||
GMP_LOG("ChromiumCDMParent::Init(this=%p) shutdown=%s abormalShutdown=%s "
|
||||
"actorDestroyed=%s",
|
||||
this,
|
||||
mIsShutdown,
|
||||
mAbnormalShutdown,
|
||||
mActorDestroyed);
|
||||
mIsShutdown ? "true" : "false",
|
||||
mAbnormalShutdown ? "true" : "false",
|
||||
mActorDestroyed ? "true" : "false");
|
||||
if (!aCDMCallback || !aMainThread) {
|
||||
aOutFailureReason = nsPrintfCString("ChromiumCDMParent::Init() failed "
|
||||
"nullCallback=%d nullMainThread=%d",
|
||||
!aCDMCallback,
|
||||
!aMainThread);
|
||||
GMP_LOG("ChromiumCDMParent::Init(this=%p) failure since aCDMCallback(%p) or"
|
||||
" aMainThread(%p) is nullptr", this, aCDMCallback, aMainThread);
|
||||
return false;
|
||||
GMP_LOG("ChromiumCDMParent::Init(this=%p) failed "
|
||||
"nullCallback=%s nullMainThread=%s",
|
||||
this,
|
||||
!aCDMCallback ? "true" : "false",
|
||||
!aMainThread ? "true" : "false");
|
||||
|
||||
return ChromiumCDMParent::InitPromise::CreateAndReject(
|
||||
MediaResult(NS_ERROR_FAILURE,
|
||||
nsPrintfCString("ChromiumCDMParent::Init() failed "
|
||||
"nullCallback=%s nullMainThread=%s",
|
||||
!aCDMCallback ? "true" : "false",
|
||||
!aMainThread ? "true" : "false")),
|
||||
__func__);
|
||||
}
|
||||
mCDMCallback = aCDMCallback;
|
||||
mMainThread = aMainThread;
|
||||
|
||||
if (SendInit(aAllowDistinctiveIdentifier,
|
||||
aAllowPersistentState)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
RefPtr<gmp::GeckoMediaPluginService> service =
|
||||
gmp::GeckoMediaPluginService::GetGeckoMediaPluginService();
|
||||
bool xpcomWillShutdown = service && service->XPCOMWillShutdownReceived();
|
||||
aOutFailureReason = nsPrintfCString(
|
||||
"ChromiumCDMParent::Init() failed "
|
||||
"shutdown=%d cdmCrash=%d actorDestroyed=%d browserShutdown=%d",
|
||||
mIsShutdown,
|
||||
mAbnormalShutdown,
|
||||
mActorDestroyed,
|
||||
xpcomWillShutdown);
|
||||
return false;
|
||||
RefPtr<ChromiumCDMParent::InitPromise> promise =
|
||||
mInitPromise.Ensure(__func__);
|
||||
RefPtr<ChromiumCDMParent> self = this;
|
||||
SendInit(aAllowDistinctiveIdentifier, aAllowPersistentState)
|
||||
->Then(AbstractThread::GetCurrent(),
|
||||
__func__,
|
||||
[self](bool /* unused */) {
|
||||
GMP_LOG(
|
||||
"ChromiumCDMParent::Init() succeeded with callback from child");
|
||||
self->mInitPromise.ResolveIfExists(true /* unused */, __func__);
|
||||
},
|
||||
[self](ResponseRejectReason aReason) {
|
||||
RefPtr<gmp::GeckoMediaPluginService> service =
|
||||
gmp::GeckoMediaPluginService::GetGeckoMediaPluginService();
|
||||
bool xpcomWillShutdown =
|
||||
service && service->XPCOMWillShutdownReceived();
|
||||
GMP_LOG("ChromiumCDMParent::Init(this=%p) failed "
|
||||
"shutdown=%s cdmCrash=%s actorDestroyed=%s "
|
||||
"browserShutdown=%s promiseRejectReason=%d",
|
||||
self.get(),
|
||||
self->mIsShutdown ? "true" : "false",
|
||||
self->mAbnormalShutdown ? "true" : "false",
|
||||
self->mActorDestroyed ? "true" : "false",
|
||||
xpcomWillShutdown ? "true" : "false",
|
||||
static_cast<int>(aReason));
|
||||
self->mInitPromise.RejectIfExists(
|
||||
MediaResult(
|
||||
NS_ERROR_FAILURE,
|
||||
nsPrintfCString("ChromiumCDMParent::Init() failed "
|
||||
"shutdown=%s cdmCrash=%s actorDestroyed=%s "
|
||||
"browserShutdown=%s promiseRejectReason=%d",
|
||||
self->mIsShutdown ? "true" : "false",
|
||||
self->mAbnormalShutdown ? "true" : "false",
|
||||
self->mActorDestroyed ? "true" : "false",
|
||||
xpcomWillShutdown ? "true" : "false",
|
||||
static_cast<int>(aReason))),
|
||||
__func__);
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1139,6 +1167,11 @@ ChromiumCDMParent::Shutdown()
|
|||
// Note: MediaKeys rejects all outstanding promises when it initiates shutdown.
|
||||
mPromiseToCreateSessionToken.Clear();
|
||||
|
||||
mInitPromise.RejectIfExists(
|
||||
MediaResult(NS_ERROR_DOM_ABORT_ERR,
|
||||
RESULT_DETAIL("ChromiumCDMParent is shutdown")),
|
||||
__func__);
|
||||
|
||||
mInitVideoDecoderPromise.RejectIfExists(
|
||||
MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
|
||||
RESULT_DETAIL("ChromiumCDMParent is shutdown")),
|
||||
|
|
|
@ -34,17 +34,18 @@ class ChromiumCDMParent final
|
|||
, public GMPCrashHelperHolder
|
||||
{
|
||||
public:
|
||||
typedef MozPromise<bool, MediaResult, /* IsExclusive = */ true> InitPromise;
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ChromiumCDMParent)
|
||||
|
||||
ChromiumCDMParent(GMPContentParent* aContentParent, uint32_t aPluginId);
|
||||
|
||||
uint32_t PluginId() const { return mPluginId; }
|
||||
|
||||
bool Init(ChromiumCDMCallback* aCDMCallback,
|
||||
bool aAllowDistinctiveIdentifier,
|
||||
bool aAllowPersistentState,
|
||||
nsIEventTarget* aMainThread,
|
||||
nsCString& aOutFailureReason);
|
||||
RefPtr<InitPromise> Init(ChromiumCDMCallback* aCDMCallback,
|
||||
bool aAllowDistinctiveIdentifier,
|
||||
bool aAllowPersistentState,
|
||||
nsIEventTarget* aMainThread);
|
||||
|
||||
void CreateSession(uint32_t aCreateSessionToken,
|
||||
uint32_t aSessionType,
|
||||
|
@ -159,6 +160,8 @@ protected:
|
|||
nsDataHashtable<nsUint32HashKey, uint32_t> mPromiseToCreateSessionToken;
|
||||
nsTArray<RefPtr<DecryptJob>> mDecrypts;
|
||||
|
||||
MozPromiseHolder<InitPromise> mInitPromise;
|
||||
|
||||
MozPromiseHolder<MediaDataDecoder::InitPromise> mInitVideoDecoderPromise;
|
||||
MozPromiseHolder<MediaDataDecoder::DecodePromise> mDecodePromise;
|
||||
|
||||
|
|
|
@ -98,25 +98,33 @@ ChromiumCDMProxy::Init(PromiseId aPromiseId,
|
|||
promise->Then(
|
||||
thread,
|
||||
__func__,
|
||||
[self, aPromiseId](RefPtr<gmp::ChromiumCDMParent> cdm) {
|
||||
[self, aPromiseId, thread](RefPtr<gmp::ChromiumCDMParent> cdm) {
|
||||
// service->GetCDM succeeded
|
||||
self->mCallback =
|
||||
MakeUnique<ChromiumCDMCallbackProxy>(self, self->mMainThread);
|
||||
nsCString failureReason;
|
||||
if (!cdm->Init(self->mCallback.get(),
|
||||
self->mDistinctiveIdentifierRequired,
|
||||
self->mPersistentStateRequired,
|
||||
self->mMainThread,
|
||||
failureReason)) {
|
||||
self->RejectPromise(aPromiseId, NS_ERROR_FAILURE, failureReason);
|
||||
return;
|
||||
}
|
||||
{
|
||||
MutexAutoLock lock(self->mCDMMutex);
|
||||
self->mCDM = cdm;
|
||||
}
|
||||
self->OnCDMCreated(aPromiseId);
|
||||
cdm
|
||||
->Init(self->mCallback.get(),
|
||||
self->mDistinctiveIdentifierRequired,
|
||||
self->mPersistentStateRequired,
|
||||
self->mMainThread)
|
||||
->Then(thread,
|
||||
__func__,
|
||||
[self, aPromiseId, cdm](bool /* unused */) {
|
||||
// CDM init succeeded
|
||||
{
|
||||
MutexAutoLock lock(self->mCDMMutex);
|
||||
self->mCDM = cdm;
|
||||
}
|
||||
self->OnCDMCreated(aPromiseId);
|
||||
},
|
||||
[self, aPromiseId](MediaResult aResult) {
|
||||
// CDM init failed
|
||||
self->RejectPromise(
|
||||
aPromiseId, aResult.Code(), aResult.Message());
|
||||
});
|
||||
},
|
||||
[self, aPromiseId](MediaResult rv) {
|
||||
// service->GetCDM failed
|
||||
self->RejectPromise(
|
||||
aPromiseId, rv.Code(), rv.Description());
|
||||
});
|
||||
|
|
|
@ -16,7 +16,7 @@ child:
|
|||
|
||||
// cdm::ContentDecryptionModule9+10
|
||||
async Init(bool aAllowDistinctiveIdentifier,
|
||||
bool aAllowPersistentState);
|
||||
bool aAllowPersistentState) returns (bool unused);
|
||||
|
||||
async GetStatusForPolicy(uint32_t aPromiseId,
|
||||
nsCString aMinHdcpVersion);
|
||||
|
|
|
@ -448,24 +448,27 @@ class CDMStorageTest
|
|||
RefPtr<gmp::GetCDMParentPromise> promise =
|
||||
service->GetCDM(aNodeId, std::move(tags), nullptr);
|
||||
auto thread = GetAbstractGMPThread();
|
||||
promise->Then(thread,
|
||||
__func__,
|
||||
[self, aUpdates](RefPtr<gmp::ChromiumCDMParent> cdm) {
|
||||
self->mCDM = cdm;
|
||||
EXPECT_TRUE(!!self->mCDM);
|
||||
self->mCallback.reset(new CallbackProxy(self));
|
||||
nsCString failureReason;
|
||||
self->mCDM->Init(self->mCallback.get(),
|
||||
false,
|
||||
true,
|
||||
GetMainThreadEventTarget(),
|
||||
failureReason);
|
||||
promise->Then(
|
||||
thread,
|
||||
__func__,
|
||||
[self, aUpdates, thread](RefPtr<gmp::ChromiumCDMParent> cdm) {
|
||||
self->mCDM = cdm;
|
||||
EXPECT_TRUE(!!self->mCDM);
|
||||
self->mCallback.reset(new CallbackProxy(self));
|
||||
nsCString failureReason;
|
||||
self->mCDM
|
||||
->Init(self->mCallback.get(), false, true, GetMainThreadEventTarget())
|
||||
->Then(thread,
|
||||
__func__,
|
||||
[self, aUpdates] {
|
||||
for (auto& update : aUpdates) {
|
||||
self->Update(update);
|
||||
}
|
||||
},
|
||||
[](MediaResult rv) { EXPECT_TRUE(false); });
|
||||
|
||||
for (auto& update : aUpdates) {
|
||||
self->Update(update);
|
||||
}
|
||||
},
|
||||
[](MediaResult rv) { EXPECT_TRUE(false); });
|
||||
},
|
||||
[](MediaResult rv) { EXPECT_TRUE(false); });
|
||||
}
|
||||
|
||||
void TestBasicStorage() {
|
||||
|
|
Загрузка…
Ссылка в новой задаче