Bug 1390739 - Dispatch the task to main thread if the callback of CDM does not on main thread. r=cpearce

MozReview-Commit-ID: E5sjEKR4bRQ

--HG--
extra : rebase_source : dccaa55c721f6da82e1cb9f6702f8099f3f4c0a3
This commit is contained in:
James Cheng 2017-08-16 13:36:08 +08:00
parent 003f12df93
commit 3bef82d85a
2 changed files with 97 additions and 37 deletions

View File

@ -189,17 +189,45 @@ ChromiumCDMChild::GetCurrentWallTime()
return base::Time::Now().ToDoubleT();
}
template <typename MethodType, typename... ParamType>
void
ChromiumCDMChild::OnResolveNewSessionPromise(uint32_t aPromiseId,
const char* aSessionId,
uint32_t aSessionIdSize)
ChromiumCDMChild::CallMethod(MethodType aMethod, ParamType&&... aParams)
{
MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::OnResolveNewSessionPromise(pid=%" PRIu32
", sid=%s)",
aPromiseId,
aSessionId);
// Avoid calling member function after destroy.
if (!mDestroyed) {
Unused << (this->*aMethod)(Forward<ParamType>(aParams)...);
}
}
template<typename MethodType, typename... ParamType>
void
ChromiumCDMChild::CallOnMessageLoopThread(const char* const aName,
MethodType aMethod,
ParamType&&... aParams)
{
if (IsOnMessageLoopThread()) {
CallMethod(aMethod, Forward<ParamType>(aParams)...);
} else {
auto m = &ChromiumCDMChild::CallMethod<
decltype(aMethod), const typename RemoveReference<ParamType>::Type&...>;
RefPtr<mozilla::Runnable> t =
NewRunnableMethod<decltype(aMethod),
const typename RemoveReference<ParamType>::Type...>(
aName,
this,
m,
aMethod,
Forward<ParamType>(aParams)...);
mPlugin->GMPMessageLoop()->PostTask(t.forget());
}
}
bool
ChromiumCDMChild::OnResolveNewSessionPromiseInternal(uint32_t aPromiseId,
const nsCString& aSessionId)
{
MOZ_ASSERT(IsOnMessageLoopThread());
if (mLoadSessionPromiseIds.Contains(aPromiseId)) {
// As laid out in the Chromium CDM API, if the CDM fails to load
// a session it calls OnResolveNewSessionPromise with nullptr as the sessionId.
@ -209,22 +237,37 @@ ChromiumCDMChild::OnResolveNewSessionPromise(uint32_t aPromiseId,
GMP_LOG("ChromiumCDMChild::OnResolveNewSessionPromise(pid=%u, sid=%s) "
"resolving %s load session ",
aPromiseId,
aSessionId,
aSessionId.get(),
(loadSuccessful ? "successful" : "failed"));
Unused << SendResolveLoadSessionPromise(aPromiseId, loadSuccessful);
mLoadSessionPromiseIds.RemoveElement(aPromiseId);
return;
return SendResolveLoadSessionPromise(aPromiseId, loadSuccessful);
}
Unused << SendOnResolveNewSessionPromise(aPromiseId,
nsCString(aSessionId, aSessionIdSize));
return SendOnResolveNewSessionPromise(aPromiseId,
aSessionId);
}
void
ChromiumCDMChild::OnResolveNewSessionPromise(uint32_t aPromiseId,
const char* aSessionId,
uint32_t aSessionIdSize)
{
GMP_LOG("ChromiumCDMChild::OnResolveNewSessionPromise(pid=%" PRIu32
", sid=%s)",
aPromiseId,
aSessionId);
CallOnMessageLoopThread("gmp::ChromiumCDMChild::OnResolveNewSessionPromise",
&ChromiumCDMChild::OnResolveNewSessionPromiseInternal,
aPromiseId,
nsCString(aSessionId, aSessionIdSize));
}
void ChromiumCDMChild::OnResolvePromise(uint32_t aPromiseId)
{
MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::OnResolvePromise(pid=%" PRIu32 ")", aPromiseId);
Unused << SendOnResolvePromise(aPromiseId);
CallOnMessageLoopThread("gmp::ChromiumCDMChild::OnResolvePromise",
&ChromiumCDMChild::SendOnResolvePromise,
aPromiseId);
}
void
@ -234,17 +277,18 @@ ChromiumCDMChild::OnRejectPromise(uint32_t aPromiseId,
const char* aErrorMessage,
uint32_t aErrorMessageSize)
{
MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::OnRejectPromise(pid=%" PRIu32 ", err=%" PRIu32
" code=%" PRIu32 ", msg='%s')",
aPromiseId,
aError,
aSystemCode,
aErrorMessage);
Unused << SendOnRejectPromise(aPromiseId,
static_cast<uint32_t>(aError),
aSystemCode,
nsCString(aErrorMessage, aErrorMessageSize));
CallOnMessageLoopThread("gmp::ChromiumCDMChild::OnRejectPromise",
&ChromiumCDMChild::SendOnRejectPromise,
aPromiseId,
static_cast<uint32_t>(aError),
aSystemCode,
nsCString(aErrorMessage, aErrorMessageSize));
}
void
@ -256,7 +300,6 @@ ChromiumCDMChild::OnSessionMessage(const char* aSessionId,
const char* aLegacyDestinationUrl,
uint32_t aLegacyDestinationUrlLength)
{
MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::OnSessionMessage(sid=%s, type=%" PRIu32
" size=%" PRIu32 ")",
aSessionId,
@ -264,9 +307,11 @@ ChromiumCDMChild::OnSessionMessage(const char* aSessionId,
aMessageSize);
nsTArray<uint8_t> message;
message.AppendElements(aMessage, aMessageSize);
Unused << SendOnSessionMessage(nsCString(aSessionId, aSessionIdSize),
static_cast<uint32_t>(aMessageType),
message);
CallOnMessageLoopThread("gmp::ChromiumCDMChild::OnSessionMessage",
&ChromiumCDMChild::SendOnSessionMessage,
nsCString(aSessionId, aSessionIdSize),
static_cast<uint32_t>(aMessageType),
message);
}
static nsCString
@ -292,7 +337,6 @@ ChromiumCDMChild::OnSessionKeysChange(const char *aSessionId,
const cdm::KeyInformation* aKeysInfo,
uint32_t aKeysInfoCount)
{
MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::OnSessionKeysChange(sid=%s) keys={%s}",
aSessionId,
ToString(aKeysInfo, aKeysInfoCount).get());
@ -305,8 +349,11 @@ ChromiumCDMChild::OnSessionKeysChange(const char *aSessionId,
kid.AppendElements(key.key_id, key.key_id_size);
keys.AppendElement(CDMKeyInformation(kid, key.status, key.system_code));
}
Unused << SendOnSessionKeysChange(nsCString(aSessionId, aSessionIdSize),
keys);
CallOnMessageLoopThread("gmp::ChromiumCDMChild::OnSessionMessage",
&ChromiumCDMChild::SendOnSessionKeysChange,
nsCString(aSessionId, aSessionIdSize),
keys);
}
void
@ -314,21 +361,23 @@ ChromiumCDMChild::OnExpirationChange(const char* aSessionId,
uint32_t aSessionIdSize,
cdm::Time aNewExpiryTime)
{
MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::OnExpirationChange(sid=%s, time=%lf)",
aSessionId,
aNewExpiryTime);
Unused << SendOnExpirationChange(nsCString(aSessionId, aSessionIdSize),
aNewExpiryTime);
CallOnMessageLoopThread("gmp::ChromiumCDMChild::OnExpirationChange",
&ChromiumCDMChild::SendOnExpirationChange,
nsCString(aSessionId, aSessionIdSize),
aNewExpiryTime);
}
void
ChromiumCDMChild::OnSessionClosed(const char* aSessionId,
uint32_t aSessionIdSize)
{
MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::OnSessionClosed(sid=%s)", aSessionId);
Unused << SendOnSessionClosed(nsCString(aSessionId, aSessionIdSize));
CallOnMessageLoopThread("gmp::ChromiumCDMChild::OnSessionClosed",
&ChromiumCDMChild::SendOnSessionClosed,
nsCString(aSessionId, aSessionIdSize));
}
void
@ -339,17 +388,17 @@ ChromiumCDMChild::OnLegacySessionError(const char* aSessionId,
const char* aErrorMessage,
uint32_t aErrorMessageLength)
{
MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::OnLegacySessionError(sid=%s, error=%" PRIu32
" msg='%s')",
aSessionId,
aError,
aErrorMessage);
Unused << SendOnLegacySessionError(
nsCString(aSessionId, aSessionIdLength),
static_cast<uint32_t>(aError),
aSystemCode,
nsCString(aErrorMessage, aErrorMessageLength));
CallOnMessageLoopThread("gmp::ChromiumCDMChild::OnLegacySessionError",
&ChromiumCDMChild::SendOnLegacySessionError,
nsCString(aSessionId, aSessionIdLength),
static_cast<uint32_t>(aError),
aSystemCode,
nsCString(aErrorMessage, aErrorMessageLength));
}
cdm::FileIO*
@ -800,6 +849,7 @@ ChromiumCDMChild::RecvDestroy()
mCDM->Destroy();
mCDM = nullptr;
}
mDestroyed = true;
Unused << Send__delete__(this);

View File

@ -79,6 +79,9 @@ public:
protected:
~ChromiumCDMChild();
bool OnResolveNewSessionPromiseInternal(uint32_t aPromiseId,
const nsCString& aSessionId);
bool IsOnMessageLoopThread();
ipc::IPCResult RecvGiveBuffer(ipc::Shmem&& aShmem) override;
@ -118,6 +121,12 @@ protected:
void ReturnOutput(WidevineVideoFrame& aFrame);
bool HasShmemOfSize(size_t aSize) const;
template <typename MethodType, typename... ParamType>
void CallMethod(MethodType, ParamType&&...);
template<typename MethodType, typename... ParamType>
void CallOnMessageLoopThread(const char* const, MethodType, ParamType&&...);
GMPContentChild* mPlugin = nullptr;
cdm::ContentDecryptionModule_8* mCDM = nullptr;
@ -130,6 +139,7 @@ protected:
bool mDecoderInitialized = false;
bool mPersistentStateAllowed = false;
bool mDestroyed = false;
};
} // namespace gmp