tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 6b239e496c39cf1a59732096921c963dadbfcfa9
parent 89594220989894d98fc5489c5e393e16aea8e522
Author: Andrew Osmond <aosmond@gmail.com>
Date:   Thu,  8 Jan 2026 15:52:08 +0000

Bug 2008385 - Remote encoders/decoders should always check if manager thread has shutdown. r=media-playback-reviewers,padenot

Differential Revision: https://phabricator.services.mozilla.com/D278230

Diffstat:
Mdom/media/ipc/MFCDMChild.h | 4++--
Mdom/media/ipc/MFMediaEngineChild.h | 2+-
Mdom/media/ipc/RemoteDecoderChild.cpp | 9+++++----
Mdom/media/ipc/RemoteMediaDataDecoder.cpp | 90++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Mdom/media/ipc/RemoteMediaManagerChild.cpp | 12+++++++++---
Mdom/media/ipc/RemoteMediaManagerChild.h | 2+-
6 files changed, 80 insertions(+), 39 deletions(-)

diff --git a/dom/media/ipc/MFCDMChild.h b/dom/media/ipc/MFCDMChild.h @@ -85,7 +85,7 @@ class MFCDMChild final : public PMFCDMChild { void EnsureRemote(); void Shutdown(); - nsISerialEventTarget* ManagerThread() { return mManagerThread; } + nsISerialEventTarget* ManagerThread() const { return mManagerThread; } void AssertOnManagerThread() const { MOZ_ASSERT(mManagerThread->IsOnCurrentThread()); } @@ -97,7 +97,7 @@ class MFCDMChild final : public PMFCDMChild { const nsString mKeySystem; - const RefPtr<nsISerialEventTarget> mManagerThread; + const nsCOMPtr<nsISerialEventTarget> mManagerThread; RefPtr<MFCDMChild> mIPDLSelfRef; using RemotePromise = GenericNonExclusivePromise; diff --git a/dom/media/ipc/MFMediaEngineChild.h b/dom/media/ipc/MFMediaEngineChild.h @@ -46,7 +46,7 @@ class MFMediaEngineChild final : public PMFMediaEngineChild { mozilla::ipc::IPCResult RecvUpdateStatisticData(const StatisticData& aData); mozilla::ipc::IPCResult RecvNotifyResizing(uint32_t aWidth, uint32_t aHeight); - nsISerialEventTarget* ManagerThread() { return mManagerThread; } + nsISerialEventTarget* ManagerThread() const { return mManagerThread; } void AssertOnManagerThread() const { MOZ_ASSERT(mManagerThread->IsOnCurrentThread()); } diff --git a/dom/media/ipc/RemoteDecoderChild.cpp b/dom/media/ipc/RemoteDecoderChild.cpp @@ -14,10 +14,11 @@ RemoteDecoderChild::RemoteDecoderChild(RemoteMediaIn aLocation) : ShmemRecycleAllocator(this), mLocation(aLocation), mThread(GetCurrentSerialEventTarget()) { - MOZ_DIAGNOSTIC_ASSERT( - RemoteMediaManagerChild::GetManagerThread() && - RemoteMediaManagerChild::GetManagerThread()->IsOnCurrentThread(), - "Must be created on the manager thread"); +#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED + auto managerThread = RemoteMediaManagerChild::GetManagerThread(); + MOZ_DIAGNOSTIC_ASSERT(managerThread); + MOZ_DIAGNOSTIC_ASSERT(managerThread->IsOnCurrentThread()); +#endif } RemoteDecoderChild::~RemoteDecoderChild() = default; diff --git a/dom/media/ipc/RemoteMediaDataDecoder.cpp b/dom/media/ipc/RemoteMediaDataDecoder.cpp @@ -48,11 +48,15 @@ RemoteMediaDataDecoder::~RemoteMediaDataDecoder() { } RefPtr<MediaDataDecoder::InitPromise> RemoteMediaDataDecoder::Init() { + auto managerThread = RemoteMediaManagerChild::GetManagerThread(); + if (!managerThread) { + return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED, __func__); + } RefPtr<RemoteMediaDataDecoder> self = this; - return InvokeAsync(RemoteMediaManagerChild::GetManagerThread(), __func__, + return InvokeAsync(managerThread, __func__, [self]() { return self->mChild->Init(); }) ->Then( - RemoteMediaManagerChild::GetManagerThread(), __func__, + managerThread, __func__, [self, this](TrackType aTrack) { MutexAutoLock lock(mMutex); // If shutdown has started in the meantime shutdown promise may @@ -83,55 +87,81 @@ RefPtr<MediaDataDecoder::InitPromise> RemoteMediaDataDecoder::Init() { RefPtr<MediaDataDecoder::DecodePromise> RemoteMediaDataDecoder::Decode( MediaRawData* aSample) { + auto managerThread = RemoteMediaManagerChild::GetManagerThread(); + if (!managerThread) { + return DecodePromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED, + __func__); + } RefPtr<RemoteMediaDataDecoder> self = this; RefPtr<MediaRawData> sample = aSample; - return InvokeAsync( - RemoteMediaManagerChild::GetManagerThread(), __func__, [self, sample]() { - return self->mChild->Decode(nsTArray<RefPtr<MediaRawData>>{sample}); - }); + return InvokeAsync(managerThread, __func__, [self, sample]() { + return self->mChild->Decode(nsTArray<RefPtr<MediaRawData>>{sample}); + }); } RefPtr<MediaDataDecoder::DecodePromise> RemoteMediaDataDecoder::DecodeBatch( nsTArray<RefPtr<MediaRawData>>&& aSamples) { + auto managerThread = RemoteMediaManagerChild::GetManagerThread(); + if (!managerThread) { + return DecodePromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED, + __func__); + } RefPtr<RemoteMediaDataDecoder> self = this; - return InvokeAsync(RemoteMediaManagerChild::GetManagerThread(), __func__, + return InvokeAsync(managerThread, __func__, [self, samples = std::move(aSamples)]() { return self->mChild->Decode(samples); }); } RefPtr<MediaDataDecoder::FlushPromise> RemoteMediaDataDecoder::Flush() { + auto managerThread = RemoteMediaManagerChild::GetManagerThread(); + if (!managerThread) { + return FlushPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED, __func__); + } RefPtr<RemoteMediaDataDecoder> self = this; - return InvokeAsync(RemoteMediaManagerChild::GetManagerThread(), __func__, + return InvokeAsync(managerThread, __func__, [self]() { return self->mChild->Flush(); }); } RefPtr<MediaDataDecoder::DecodePromise> RemoteMediaDataDecoder::Drain() { + auto managerThread = RemoteMediaManagerChild::GetManagerThread(); + if (!managerThread) { + return DecodePromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED, + __func__); + } RefPtr<RemoteMediaDataDecoder> self = this; - return InvokeAsync(RemoteMediaManagerChild::GetManagerThread(), __func__, + return InvokeAsync(managerThread, __func__, [self]() { return self->mChild->Drain(); }); } RefPtr<ShutdownPromise> RemoteMediaDataDecoder::Shutdown() { + auto managerThread = RemoteMediaManagerChild::GetManagerThread(); + if (!managerThread) { + return ShutdownPromise::CreateAndResolve(true, __func__); + } RefPtr<RemoteMediaDataDecoder> self = this; - return InvokeAsync( - RemoteMediaManagerChild::GetManagerThread(), __func__, [self]() { - RefPtr<ShutdownPromise> p = self->mChild->Shutdown(); - - // We're about to be destroyed and drop our ref to - // *DecoderChild. Make sure we put a ref into the - // task queue for the *DecoderChild thread to keep - // it alive until we send the delete message. - p->Then(RemoteMediaManagerChild::GetManagerThread(), __func__, - [child = std::move(self->mChild)]( - const ShutdownPromise::ResolveOrRejectValue& aValue) { - MOZ_ASSERT(aValue.IsResolve()); - child->DestroyIPDL(); - return ShutdownPromise::CreateAndResolveOrReject(aValue, - __func__); - }); - return p; - }); + return InvokeAsync(managerThread, __func__, [self]() { + auto managerThread = RemoteMediaManagerChild::GetManagerThread(); + if (!managerThread) { + return ShutdownPromise::CreateAndResolve(true, __func__); + } + + RefPtr<ShutdownPromise> p = self->mChild->Shutdown(); + + // We're about to be destroyed and drop our ref to + // *DecoderChild. Make sure we put a ref into the + // task queue for the *DecoderChild thread to keep + // it alive until we send the delete message. + p->Then(managerThread, __func__, + [child = std::move(self->mChild)]( + const ShutdownPromise::ResolveOrRejectValue& aValue) { + MOZ_ASSERT(aValue.IsResolve()); + child->DestroyIPDL(); + return ShutdownPromise::CreateAndResolveOrReject(aValue, + __func__); + }); + return p; + }); } bool RemoteMediaDataDecoder::IsHardwareAccelerated( @@ -142,9 +172,13 @@ bool RemoteMediaDataDecoder::IsHardwareAccelerated( } void RemoteMediaDataDecoder::SetSeekThreshold(const media::TimeUnit& aTime) { + auto managerThread = RemoteMediaManagerChild::GetManagerThread(); + if (!managerThread) { + return; + } RefPtr<RemoteMediaDataDecoder> self = this; media::TimeUnit time = aTime; - RemoteMediaManagerChild::GetManagerThread()->Dispatch( + managerThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaDataDecoder::SetSeekThreshold", [=]() { MOZ_ASSERT(self->mChild); diff --git a/dom/media/ipc/RemoteMediaManagerChild.cpp b/dom/media/ipc/RemoteMediaManagerChild.cpp @@ -231,9 +231,9 @@ RemoteMediaManagerChild* RemoteMediaManagerChild::GetSingleton( } /* static */ -nsISerialEventTarget* RemoteMediaManagerChild::GetManagerThread() { +nsCOMPtr<nsISerialEventTarget> RemoteMediaManagerChild::GetManagerThread() { auto remoteDecoderManagerThread = sRemoteMediaManagerChildThread.Lock(); - return *remoteDecoderManagerThread; + return nsCOMPtr<nsISerialEventTarget>(*remoteDecoderManagerThread); } /* static */ @@ -639,6 +639,13 @@ RemoteMediaManagerChild::InitializeEncoder( __func__); } + auto managerThread = aEncoder->GetManagerThread(); + if (!managerThread) { + return PlatformEncoderModule::CreateEncoderPromise::CreateAndReject( + MediaResult(NS_ERROR_DOM_MEDIA_CANCELED, "Thread shutdown"_ns), + __func__); + } + MOZ_ASSERT(location != RemoteMediaIn::Unspecified); RefPtr<GenericNonExclusivePromise> p; @@ -658,7 +665,6 @@ RemoteMediaManagerChild::InitializeEncoder( aConfig.IsAudio() ? "audio" : "video", static_cast<int>(aConfig.mCodec), RemoteMediaInToStr(location)); - auto* managerThread = aEncoder->GetManagerThread(); return p->Then( managerThread, __func__, [encoder = std::move(aEncoder), aConfig](bool) { diff --git a/dom/media/ipc/RemoteMediaManagerChild.h b/dom/media/ipc/RemoteMediaManagerChild.h @@ -85,7 +85,7 @@ class RemoteMediaManagerChild final const EncoderConfig& aConfig); // Can be called from any thread. - static nsISerialEventTarget* GetManagerThread(); + static nsCOMPtr<nsISerialEventTarget> GetManagerThread(); // Return the track support information based on the location of the remote // process. Thread-safe.