From 2ba9c2d2638b04bac89e416d7880017abedf7584 Mon Sep 17 00:00:00 2001 From: James Cheng Date: Mon, 11 Sep 2017 12:17:36 +0800 Subject: [PATCH] Bug 1397123 - [Part2] Decouple ChromiumCDMProxy from ChromiumCDMParent. r=cpearce 1. Pass ChromiumCDMCallback interface to ChromiumCDMParent instead of ChromiumCDMProxy directly. 2. Wrap dispatching to main thread function to clean up the redundant code. MozReview-Commit-ID: 5HxS9Fc1yr --- dom/media/gmp/ChromiumCDMCallback.h | 52 +++++ dom/media/gmp/ChromiumCDMCallbackProxy.cpp | 188 ++++++++++++++++++ dom/media/gmp/ChromiumCDMCallbackProxy.h | 68 +++++++ dom/media/gmp/ChromiumCDMParent.cpp | 215 +++++---------------- dom/media/gmp/ChromiumCDMParent.h | 13 +- dom/media/gmp/ChromiumCDMProxy.cpp | 7 +- dom/media/gmp/ChromiumCDMProxy.h | 3 +- dom/media/gmp/moz.build | 2 + 8 files changed, 373 insertions(+), 175 deletions(-) create mode 100644 dom/media/gmp/ChromiumCDMCallback.h create mode 100644 dom/media/gmp/ChromiumCDMCallbackProxy.cpp create mode 100644 dom/media/gmp/ChromiumCDMCallbackProxy.h diff --git a/dom/media/gmp/ChromiumCDMCallback.h b/dom/media/gmp/ChromiumCDMCallback.h new file mode 100644 index 000000000000..1558eebf9f9c --- /dev/null +++ b/dom/media/gmp/ChromiumCDMCallback.h @@ -0,0 +1,52 @@ +/* -*- 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/. */ + +#ifndef ChromiumCDMCallback_h_ +#define ChromiumCDMCallback_h_ + +#include "mozilla/CDMProxy.h" +#include "mozilla/dom/MediaKeyStatusMapBinding.h" // For MediaKeyStatus +#include "mozilla/dom/MediaKeyMessageEventBinding.h" // For MediaKeyMessageType +#include "mozilla/gmp/GMPTypes.h" // For CDMKeyInformation + +class ChromiumCDMCallback { +public: + + virtual ~ChromiumCDMCallback() {} + + virtual void SetSessionId(uint32_t aPromiseId, + const nsCString& aSessionId) = 0; + + virtual void ResolveLoadSessionPromise(uint32_t aPromiseId, + bool aSuccessful) = 0; + + virtual void ResolvePromise(uint32_t aPromiseId) = 0; + + virtual void RejectPromise(uint32_t aPromiseId, + nsresult aError, + const nsCString& aErrorMessage) = 0; + + virtual void SessionMessage(const nsACString& aSessionId, + uint32_t aMessageType, + nsTArray&& aMessage) = 0; + + virtual void SessionKeysChange(const nsCString& aSessionId, + nsTArray&& aKeysInfo) = 0; + + virtual void ExpirationChange(const nsCString& aSessionId, + double aSecondsSinceEpoch) = 0; + + virtual void SessionClosed(const nsCString& aSessionId) = 0; + + virtual void LegacySessionError(const nsCString& aSessionId, + nsresult aError, + uint32_t aSystemCode, + const nsCString& aMessage) = 0; + virtual void Terminated() = 0; + + virtual void Shutdown() = 0; +}; + +#endif diff --git a/dom/media/gmp/ChromiumCDMCallbackProxy.cpp b/dom/media/gmp/ChromiumCDMCallbackProxy.cpp new file mode 100644 index 000000000000..38b6001e1f35 --- /dev/null +++ b/dom/media/gmp/ChromiumCDMCallbackProxy.cpp @@ -0,0 +1,188 @@ +/* -*- 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 "ChromiumCDMCallbackProxy.h" + +#include "ChromiumCDMProxy.h" +#include "content_decryption_module.h" + +namespace mozilla { + +template +void ChromiumCDMCallbackProxy::DispatchToMainThread(const char* const aLabel, + Func aFunc, + Args&&... aArgs) +{ + mMainThread->Dispatch( + // Use Decay to ensure all the types are passed by value not by reference. + NewRunnableMethod::Type...>( + aLabel, + mProxy, + aFunc, + Forward(aArgs)...), + NS_DISPATCH_NORMAL); +} + +void +ChromiumCDMCallbackProxy::SetSessionId(uint32_t aPromiseId, + const nsCString& aSessionId) +{ + DispatchToMainThread("ChromiumCDMProxy::OnSetSessionId", + &ChromiumCDMProxy::OnSetSessionId, + aPromiseId, + NS_ConvertUTF8toUTF16(aSessionId)); +} + +void +ChromiumCDMCallbackProxy::ResolveLoadSessionPromise(uint32_t aPromiseId, + bool aSuccessful) +{ + DispatchToMainThread("ChromiumCDMProxy::OnResolveLoadSessionPromise", + &ChromiumCDMProxy::OnResolveLoadSessionPromise, + aPromiseId, + aSuccessful); +} + +void +ChromiumCDMCallbackProxy::ResolvePromise(uint32_t aPromiseId) +{ + DispatchToMainThread("ChromiumCDMProxy::ResolvePromise", + &ChromiumCDMProxy::ResolvePromise, + aPromiseId); +} + +void +ChromiumCDMCallbackProxy::RejectPromise(uint32_t aPromiseId, + nsresult aError, + const nsCString& aErrorMessage) +{ + DispatchToMainThread("ChromiumCDMProxy::RejectPromise", + &ChromiumCDMProxy::RejectPromise, + aPromiseId, + aError, + aErrorMessage); +} + + +static dom::MediaKeyMessageType +ToDOMMessageType(uint32_t aMessageType) +{ + switch (static_cast(aMessageType)) { + case cdm::kLicenseRequest: + return dom::MediaKeyMessageType::License_request; + case cdm::kLicenseRenewal: + return dom::MediaKeyMessageType::License_renewal; + case cdm::kLicenseRelease: + return dom::MediaKeyMessageType::License_release; + } + MOZ_ASSERT_UNREACHABLE("Invalid cdm::MessageType enum value."); + return dom::MediaKeyMessageType::License_request; +} + +void +ChromiumCDMCallbackProxy::SessionMessage(const nsACString& aSessionId, + uint32_t aMessageType, + nsTArray&& aMessage) +{ + DispatchToMainThread("ChromiumCDMProxy::OnSessionMessage", + &ChromiumCDMProxy::OnSessionMessage, + NS_ConvertUTF8toUTF16(aSessionId), + ToDOMMessageType(aMessageType), + Move(aMessage)); +} + +static dom::MediaKeyStatus +ToDOMMediaKeyStatus(uint32_t aStatus) +{ + switch (static_cast(aStatus)) { + case cdm::kUsable: + return dom::MediaKeyStatus::Usable; + case cdm::kInternalError: + return dom::MediaKeyStatus::Internal_error; + case cdm::kExpired: + return dom::MediaKeyStatus::Expired; + case cdm::kOutputRestricted: + return dom::MediaKeyStatus::Output_restricted; + case cdm::kOutputDownscaled: + return dom::MediaKeyStatus::Output_downscaled; + case cdm::kStatusPending: + return dom::MediaKeyStatus::Status_pending; + case cdm::kReleased: + return dom::MediaKeyStatus::Released; + } + MOZ_ASSERT_UNREACHABLE("Invalid cdm::KeyStatus enum value."); + return dom::MediaKeyStatus::Internal_error; +} + +void +ChromiumCDMCallbackProxy::SessionKeysChange(const nsCString& aSessionId, + nsTArray && aKeysInfo) +{ + bool keyStatusesChange = false; + { + CDMCaps::AutoLock caps(mProxy->Capabilites()); + for (const auto& keyInfo : aKeysInfo) { + keyStatusesChange |= + caps.SetKeyStatus(keyInfo.mKeyId(), + NS_ConvertUTF8toUTF16(aSessionId), + dom::Optional( + ToDOMMediaKeyStatus(keyInfo.mStatus()))); + } + } + if (keyStatusesChange) { + DispatchToMainThread("ChromiumCDMProxy::OnKeyStatusesChange", + &ChromiumCDMProxy::OnKeyStatusesChange, + NS_ConvertUTF8toUTF16(aSessionId)); + } +} + +void +ChromiumCDMCallbackProxy::ExpirationChange(const nsCString& aSessionId, + double aSecondsSinceEpoch) +{ + DispatchToMainThread("ChromiumCDMProxy::OnExpirationChange", + &ChromiumCDMProxy::OnExpirationChange, + NS_ConvertUTF8toUTF16(aSessionId), + UnixTime(aSecondsSinceEpoch * 1000)); + +} + +void +ChromiumCDMCallbackProxy::SessionClosed(const nsCString& aSessionId) +{ + DispatchToMainThread("ChromiumCDMProxy::OnSessionClosed", + &ChromiumCDMProxy::OnSessionClosed , + NS_ConvertUTF8toUTF16(aSessionId)); +} + +void +ChromiumCDMCallbackProxy::LegacySessionError(const nsCString& aSessionId, + nsresult aError, + uint32_t aSystemCode, + const nsCString& aMessage) +{ + DispatchToMainThread("ChromiumCDMProxy::OnSessionError", + &ChromiumCDMProxy::OnSessionError , + NS_ConvertUTF8toUTF16(aSessionId), + aError, + aSystemCode, + NS_ConvertUTF8toUTF16(aMessage)); +} + +void +ChromiumCDMCallbackProxy::Terminated() +{ + DispatchToMainThread("ChromiumCDMProxy::Terminated", + &ChromiumCDMProxy::Terminated); +} + +void +ChromiumCDMCallbackProxy::Shutdown() +{ + DispatchToMainThread("ChromiumCDMProxy::Shutdown", + &ChromiumCDMProxy::Shutdown); +} + +} //namespace mozilla diff --git a/dom/media/gmp/ChromiumCDMCallbackProxy.h b/dom/media/gmp/ChromiumCDMCallbackProxy.h new file mode 100644 index 000000000000..15fd97738a29 --- /dev/null +++ b/dom/media/gmp/ChromiumCDMCallbackProxy.h @@ -0,0 +1,68 @@ +/* -*- 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/. */ + +#ifndef ChromiumCDMCallbackProxy_h_ +#define ChromiumCDMCallbackProxy_h_ + +#include "ChromiumCDMCallback.h" +#include "ChromiumCDMProxy.h" +#include "nsThreadUtils.h" + +namespace mozilla { + +class ChromiumCDMCallbackProxy : public ChromiumCDMCallback { +public: + + ChromiumCDMCallbackProxy(ChromiumCDMProxy* aProxy, + nsIEventTarget* aMainThread) + : mProxy(aProxy), mMainThread(aMainThread) + { + } + + void SetSessionId(uint32_t aPromiseId, + const nsCString& aSessionId) override; + + void ResolveLoadSessionPromise(uint32_t aPromiseId, + bool aSuccessful) override; + + void ResolvePromise(uint32_t aPromiseId) override; + + void RejectPromise(uint32_t aPromiseId, + nsresult aError, + const nsCString& aErrorMessage) override; + + void SessionMessage(const nsACString& aSessionId, + uint32_t aMessageType, + nsTArray&& aMessage) override; + + void SessionKeysChange(const nsCString& aSessionId, + nsTArray&& aKeysInfo) override; + + void ExpirationChange(const nsCString& aSessionId, + double aSecondsSinceEpoch) override; + + void SessionClosed(const nsCString& aSessionId) override; + + void LegacySessionError(const nsCString& aSessionId, + nsresult aError, + uint32_t aSystemCode, + const nsCString& aMessage) override; + void Terminated() override; + + void Shutdown() override; + +private: + template + void DispatchToMainThread(const char* const aLabel, + Func aFunc, + Args&&... aArgs); + // Warning: Weak ref. + ChromiumCDMProxy* mProxy; + const nsCOMPtr mMainThread; + +}; + +} //namespace mozilla +#endif diff --git a/dom/media/gmp/ChromiumCDMParent.cpp b/dom/media/gmp/ChromiumCDMParent.cpp index aa7908ec2fbb..16a5347655d7 100644 --- a/dom/media/gmp/ChromiumCDMParent.cpp +++ b/dom/media/gmp/ChromiumCDMParent.cpp @@ -5,6 +5,8 @@ #include "ChromiumCDMParent.h" +#include "ChromiumCDMCallback.h" +#include "ChromiumCDMCallbackProxy.h" #include "ChromiumCDMProxy.h" #include "content_decryption_module.h" #include "GMPContentChild.h" @@ -40,16 +42,16 @@ ChromiumCDMParent::ChromiumCDMParent(GMPContentParent* aContentParent, } bool -ChromiumCDMParent::Init(ChromiumCDMProxy* aProxy, +ChromiumCDMParent::Init(ChromiumCDMCallback* aCDMCallback, bool aAllowDistinctiveIdentifier, bool aAllowPersistentState, nsIEventTarget* aMainThread) { GMP_LOG("ChromiumCDMParent::Init(this=%p)", this); - if (!aProxy || !aMainThread) { + if (!aCDMCallback || !aMainThread) { return false; } - mProxy = aProxy; + mCDMCallback = aCDMCallback; mMainThread = aMainThread; return SendInit(aAllowDistinctiveIdentifier, aAllowPersistentState); } @@ -279,7 +281,7 @@ ChromiumCDMParent::RecvOnResolveNewSessionPromise(const uint32_t& aPromiseId, this, aPromiseId, aSessionId.get()); - if (!mProxy || mIsShutdown) { + if (!mCDMCallback || mIsShutdown) { return IPC_OK(); } @@ -291,13 +293,7 @@ ChromiumCDMParent::RecvOnResolveNewSessionPromise(const uint32_t& aPromiseId, return IPC_OK(); } - mMainThread->Dispatch( - NewRunnableMethod("ChromiumCDMProxy::OnSetSessionId", - mProxy, - &ChromiumCDMProxy::OnSetSessionId, - token.value(), - NS_ConvertUTF8toUTF16(aSessionId)), - NS_DISPATCH_NORMAL); + mCDMCallback->SetSessionId(token.value(), aSessionId); ResolvePromise(aPromiseId); @@ -313,21 +309,15 @@ ChromiumCDMParent::RecvResolveLoadSessionPromise(const uint32_t& aPromiseId, this, aPromiseId, aSuccessful); - if (!mProxy || mIsShutdown) { + if (!mCDMCallback || mIsShutdown) { return IPC_OK(); } - mMainThread->Dispatch( - NewRunnableMethod( - "ChromiumCDMProxy::OnResolveLoadSessionPromise", - mProxy, - &ChromiumCDMProxy::OnResolveLoadSessionPromise, - aPromiseId, - aSuccessful), - NS_DISPATCH_NORMAL); + mCDMCallback->ResolveLoadSessionPromise(aPromiseId, aSuccessful); return IPC_OK(); } + void ChromiumCDMParent::ResolvePromise(uint32_t aPromiseId) { @@ -336,16 +326,11 @@ ChromiumCDMParent::ResolvePromise(uint32_t aPromiseId) // Note: The MediaKeys rejects all pending DOM promises when it // initiates shutdown. - if (!mProxy || mIsShutdown) { + if (!mCDMCallback || mIsShutdown) { return; } - mMainThread->Dispatch( - NewRunnableMethod("ChromiumCDMProxy::ResolvePromise", - mProxy, - &ChromiumCDMProxy::ResolvePromise, - aPromiseId), - NS_DISPATCH_NORMAL); + mCDMCallback->ResolvePromise(aPromiseId); } ipc::IPCResult @@ -355,6 +340,22 @@ ChromiumCDMParent::RecvOnResolvePromise(const uint32_t& aPromiseId) return IPC_OK(); } +void +ChromiumCDMParent::RejectPromise(uint32_t aPromiseId, + nsresult aError, + const nsCString& aErrorMessage) +{ + GMP_LOG( + "ChromiumCDMParent::RejectPromise(this=%p, pid=%u)", this, aPromiseId); + // Note: The MediaKeys rejects all pending DOM promises when it + // initiates shutdown. + if (!mCDMCallback || mIsShutdown) { + return; + } + + mCDMCallback->RejectPromise(aPromiseId, aError, aErrorMessage); +} + static nsresult ToNsresult(uint32_t aError) { @@ -382,30 +383,6 @@ ToNsresult(uint32_t aError) return NS_ERROR_DOM_TIMEOUT_ERR; // Note: Unique placeholder. } -void -ChromiumCDMParent::RejectPromise(uint32_t aPromiseId, - nsresult aError, - const nsCString& aErrorMessage) -{ - GMP_LOG( - "ChromiumCDMParent::RejectPromise(this=%p, pid=%u)", this, aPromiseId); - // Note: The MediaKeys rejects all pending DOM promises when it - // initiates shutdown. - if (!mProxy || mIsShutdown) { - return; - } - - mMainThread->Dispatch( - NewRunnableMethod( - "ChromiumCDMProxy::RejectPromise", - mProxy, - &ChromiumCDMProxy::RejectPromise, - aPromiseId, - aError, - aErrorMessage), - NS_DISPATCH_NORMAL); -} - ipc::IPCResult ChromiumCDMParent::RecvOnRejectPromise(const uint32_t& aPromiseId, const uint32_t& aError, @@ -416,21 +393,6 @@ ChromiumCDMParent::RecvOnRejectPromise(const uint32_t& aPromiseId, return IPC_OK(); } -static dom::MediaKeyMessageType -ToDOMMessageType(uint32_t aMessageType) -{ - switch (static_cast(aMessageType)) { - case cdm::kLicenseRequest: - return dom::MediaKeyMessageType::License_request; - case cdm::kLicenseRenewal: - return dom::MediaKeyMessageType::License_renewal; - case cdm::kLicenseRelease: - return dom::MediaKeyMessageType::License_release; - } - MOZ_ASSERT_UNREACHABLE("Invalid cdm::MessageType enum value."); - return dom::MediaKeyMessageType::License_request; -} - ipc::IPCResult ChromiumCDMParent::RecvOnSessionMessage(const nsCString& aSessionId, const uint32_t& aMessageType, @@ -439,44 +401,12 @@ ChromiumCDMParent::RecvOnSessionMessage(const nsCString& aSessionId, GMP_LOG("ChromiumCDMParent::RecvOnSessionMessage(this=%p, sid=%s)", this, aSessionId.get()); - if (!mProxy || mIsShutdown) { + if (!mCDMCallback || mIsShutdown) { return IPC_OK(); } - RefPtr proxy = mProxy; - nsString sid = NS_ConvertUTF8toUTF16(aSessionId); - dom::MediaKeyMessageType messageType = ToDOMMessageType(aMessageType); - nsTArray msg(Move(aMessage)); - - mMainThread->Dispatch( - NS_NewRunnableFunction("gmp::ChromiumCDMParent::RecvOnSessionMessage", - [proxy, sid, messageType, msg]() mutable { - proxy->OnSessionMessage(sid, messageType, msg); - }), - NS_DISPATCH_NORMAL); - return IPC_OK(); -} -static dom::MediaKeyStatus -ToDOMMediaKeyStatus(uint32_t aStatus) -{ - switch (static_cast(aStatus)) { - case cdm::kUsable: - return dom::MediaKeyStatus::Usable; - case cdm::kInternalError: - return dom::MediaKeyStatus::Internal_error; - case cdm::kExpired: - return dom::MediaKeyStatus::Expired; - case cdm::kOutputRestricted: - return dom::MediaKeyStatus::Output_restricted; - case cdm::kOutputDownscaled: - return dom::MediaKeyStatus::Output_downscaled; - case cdm::kStatusPending: - return dom::MediaKeyStatus::Status_pending; - case cdm::kReleased: - return dom::MediaKeyStatus::Released; - } - MOZ_ASSERT_UNREACHABLE("Invalid cdm::KeyStatus enum value."); - return dom::MediaKeyStatus::Internal_error; + mCDMCallback->SessionMessage(aSessionId, aMessageType, Move(aMessage)); + return IPC_OK(); } ipc::IPCResult @@ -485,28 +415,11 @@ ChromiumCDMParent::RecvOnSessionKeysChange( nsTArray&& aKeysInfo) { GMP_LOG("ChromiumCDMParent::RecvOnSessionKeysChange(this=%p)", this); - if (!mProxy || mIsShutdown) { + if (!mCDMCallback || mIsShutdown) { return IPC_OK(); } - bool keyStatusesChange = false; - { - CDMCaps::AutoLock caps(mProxy->Capabilites()); - for (size_t i = 0; i < aKeysInfo.Length(); i++) { - keyStatusesChange |= - caps.SetKeyStatus(aKeysInfo[i].mKeyId(), - NS_ConvertUTF8toUTF16(aSessionId), - dom::Optional( - ToDOMMediaKeyStatus(aKeysInfo[i].mStatus()))); - } - } - if (keyStatusesChange) { - mMainThread->Dispatch( - NewRunnableMethod("ChromiumCDMProxy::OnKeyStatusesChange", - mProxy, - &ChromiumCDMProxy::OnKeyStatusesChange, - NS_ConvertUTF8toUTF16(aSessionId)), - NS_DISPATCH_NORMAL); - } + + mCDMCallback->SessionKeysChange(aSessionId, Move(aKeysInfo)); return IPC_OK(); } @@ -517,18 +430,11 @@ ChromiumCDMParent::RecvOnExpirationChange(const nsCString& aSessionId, GMP_LOG("ChromiumCDMParent::RecvOnExpirationChange(this=%p) time=%lf", this, aSecondsSinceEpoch); - if (!mProxy || mIsShutdown) { + if (!mCDMCallback || mIsShutdown) { return IPC_OK(); } - mMainThread->Dispatch( - NewRunnableMethod( - "ChromiumCDMProxy::OnExpirationChange", - mProxy, - &ChromiumCDMProxy::OnExpirationChange, - NS_ConvertUTF8toUTF16(aSessionId), - GMPTimestamp(aSecondsSinceEpoch * 1000)), - NS_DISPATCH_NORMAL); + mCDMCallback->ExpirationChange(aSessionId, aSecondsSinceEpoch); return IPC_OK(); } @@ -536,16 +442,11 @@ ipc::IPCResult ChromiumCDMParent::RecvOnSessionClosed(const nsCString& aSessionId) { GMP_LOG("ChromiumCDMParent::RecvOnSessionClosed(this=%p)", this); - if (!mProxy || mIsShutdown) { + if (!mCDMCallback || mIsShutdown) { return IPC_OK(); } - mMainThread->Dispatch( - NewRunnableMethod("ChromiumCDMProxy::OnSessionClosed", - mProxy, - &ChromiumCDMProxy::OnSessionClosed, - NS_ConvertUTF8toUTF16(aSessionId)), - NS_DISPATCH_NORMAL); + mCDMCallback->SessionClosed(aSessionId); return IPC_OK(); } @@ -556,20 +457,12 @@ ChromiumCDMParent::RecvOnLegacySessionError(const nsCString& aSessionId, const nsCString& aMessage) { GMP_LOG("ChromiumCDMParent::RecvOnLegacySessionError(this=%p)", this); - if (!mProxy || mIsShutdown) { + if (!mCDMCallback || mIsShutdown) { return IPC_OK(); } - mMainThread->Dispatch( - NewRunnableMethod( - "ChromiumCDMProxy::OnSessionError", - mProxy, - &ChromiumCDMProxy::OnSessionError, - NS_ConvertUTF8toUTF16(aSessionId), - ToNsresult(aError), - aSystemCode, - NS_ConvertUTF8toUTF16(aMessage)), - NS_DISPATCH_NORMAL); + mCDMCallback->LegacySessionError( + aSessionId, ToNsresult(aError), aSystemCode, aMessage); return IPC_OK(); } @@ -934,8 +827,8 @@ ChromiumCDMParent::ActorDestroy(ActorDestroyReason aWhy) GMP_LOG("ChromiumCDMParent::ActorDestroy(this=%p, reason=%d)", this, aWhy); MOZ_ASSERT(!mActorDestroyed); mActorDestroyed = true; - // Shutdown() will clear mProxy, so let's keep a reference for later use. - RefPtr proxy = mProxy; + // Shutdown() will clear mCDMCallback, so let's keep a reference for later use. + auto callback = mCDMCallback; if (!mIsShutdown) { // Plugin crash. MOZ_ASSERT(aWhy == AbnormalShutdown); @@ -948,13 +841,8 @@ ChromiumCDMParent::ActorDestroy(ActorDestroyReason aWhy) mContentParent = nullptr; } bool abnormalShutdown = (aWhy == AbnormalShutdown); - if (abnormalShutdown && proxy) { - mMainThread->Dispatch( - NewRunnableMethod( - "ChromiumCDMProxy::Terminated", - proxy, - &ChromiumCDMProxy::Terminated), - NS_DISPATCH_NORMAL); + if (abnormalShutdown && callback) { + callback->Terminated(); } MaybeDisconnect(abnormalShutdown); } @@ -1190,19 +1078,14 @@ ChromiumCDMParent::Shutdown() // proxy will shutdown when the owning MediaKeys is destroyed during cycle // collection, and that will not shut down cleanly as the GMP thread will be // shutdown by then. - if (mProxy) { - mMainThread->Dispatch( - NewRunnableMethod( - "ChromiumCDMProxy::Shutdown", - mProxy, - &ChromiumCDMProxy::Shutdown), - NS_DISPATCH_NORMAL); + if (mCDMCallback) { + mCDMCallback->Shutdown(); } - // We may be called from a task holding the last reference to the proxy, so + // We may be called from a task holding the last reference to the CDM callback, so // let's clear our local weak pointer to ensure it will not be used afterward // (including from an already-queued task, e.g.: ActorDestroy). - mProxy = nullptr; + mCDMCallback = nullptr; mReorderQueue.Clear(); diff --git a/dom/media/gmp/ChromiumCDMParent.h b/dom/media/gmp/ChromiumCDMParent.h index 8bd23fc3515a..f5aabeda4b6b 100644 --- a/dom/media/gmp/ChromiumCDMParent.h +++ b/dom/media/gmp/ChromiumCDMParent.h @@ -18,6 +18,8 @@ #include "mozilla/Span.h" #include "ReorderQueue.h" +class ChromiumCDMCallback; + namespace mozilla { class MediaRawData; @@ -38,7 +40,7 @@ class ChromiumCDMParent final uint32_t PluginId() const { return mPluginId; } - bool Init(ChromiumCDMProxy* aProxy, + bool Init(ChromiumCDMCallback* aCDMCallback, bool aAllowDistinctiveIdentifier, bool aAllowPersistentState, nsIEventTarget* aMainThread); @@ -148,10 +150,9 @@ class ChromiumCDMParent final const uint32_t mPluginId; GMPContentParent* mContentParent; - // Note: this pointer is a weak reference because otherwise it would cause - // a cycle, as ChromiumCDMProxy has a strong reference to the - // ChromiumCDMParent. - ChromiumCDMProxy* mProxy = nullptr; + // Note: this pointer is a weak reference as ChromiumCDMProxy has a strong reference to the + // ChromiumCDMCallback. + ChromiumCDMCallback* mCDMCallback = nullptr; nsDataHashtable mPromiseToCreateSessionToken; nsTArray> mDecrypts; @@ -188,7 +189,7 @@ class ChromiumCDMParent final ReorderQueue mReorderQueue; // The main thread associated with the root document. Must be set in Init(). - nsCOMPtr mMainThread; + nsCOMPtr mMainThread; }; } // namespace gmp diff --git a/dom/media/gmp/ChromiumCDMProxy.cpp b/dom/media/gmp/ChromiumCDMProxy.cpp index 081a3f752e7d..860f72e79fdf 100644 --- a/dom/media/gmp/ChromiumCDMProxy.cpp +++ b/dom/media/gmp/ChromiumCDMProxy.cpp @@ -5,6 +5,7 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ChromiumCDMProxy.h" +#include "ChromiumCDMCallbackProxy.h" #include "mozilla/dom/MediaKeySession.h" #include "GMPUtils.h" #include "nsPrintfCString.h" @@ -97,7 +98,9 @@ ChromiumCDMProxy::Init(PromiseId aPromiseId, thread, __func__, [self, aPromiseId](RefPtr cdm) { - if (!cdm->Init(self, + self->mCallback = + MakeUnique(self, self->mMainThread); + if (!cdm->Init(self->mCallback.get(), self->mDistinctiveIdentifierRequired, self->mPersistentStateRequired, self->mMainThread)) { @@ -464,7 +467,7 @@ ChromiumCDMProxy::OnResolveLoadSessionPromise(uint32_t aPromiseId, void ChromiumCDMProxy::OnSessionMessage(const nsAString& aSessionId, dom::MediaKeyMessageType aMessageType, - nsTArray& aMessage) + const nsTArray& aMessage) { MOZ_ASSERT(NS_IsMainThread()); if (mKeys.IsNull()) { diff --git a/dom/media/gmp/ChromiumCDMProxy.h b/dom/media/gmp/ChromiumCDMProxy.h index b9e31a50bd44..8419e8c97aba 100644 --- a/dom/media/gmp/ChromiumCDMProxy.h +++ b/dom/media/gmp/ChromiumCDMProxy.h @@ -15,7 +15,7 @@ namespace mozilla { class MediaRawData; class DecryptJob; - +class ChromiumCDMCallbackProxy; class ChromiumCDMProxy : public CDMProxy { public: @@ -125,6 +125,7 @@ class ChromiumCDMProxy : public CDMProxy Mutex mCDMMutex; RefPtr mCDM; RefPtr mGMPThread; + UniquePtr mCallback; }; } // namespace mozilla diff --git a/dom/media/gmp/moz.build b/dom/media/gmp/moz.build index 3b0a62652e9d..de7db3244126 100644 --- a/dom/media/gmp/moz.build +++ b/dom/media/gmp/moz.build @@ -12,6 +12,7 @@ XPIDL_SOURCES += [ ] EXPORTS += [ + 'ChromiumCDMCallback.h', 'ChromiumCDMParent.h', 'ChromiumCDMProxy.h', 'DecryptJob.h', @@ -72,6 +73,7 @@ EXPORTS += [ UNIFIED_SOURCES += [ 'ChromiumCDMAdapter.cpp', + 'ChromiumCDMCallbackProxy.cpp', 'ChromiumCDMChild.cpp', 'ChromiumCDMParent.cpp', 'ChromiumCDMProxy.cpp',