diff --git a/dom/media/ipc/RDDProcessManager.cpp b/dom/media/ipc/RDDProcessManager.cpp index 89dc004471f5..35cebbaaa72b 100644 --- a/dom/media/ipc/RDDProcessManager.cpp +++ b/dom/media/ipc/RDDProcessManager.cpp @@ -99,44 +99,49 @@ void RDDProcessManager::OnPreferenceChange(const char16_t* aData) { } } -bool RDDProcessManager::EnsureRDDProcessAndCreateBridge( - base::ProcessId aOtherProcess, - mozilla::ipc::Endpoint* - aOutRemoteDecoderManager) { - bool success = false; +auto RDDProcessManager::EnsureRDDProcessAndCreateBridge( + base::ProcessId aOtherProcess) -> RefPtr { + return InvokeAsync(GetMainThreadSerialEventTarget(), __func__, + [aOtherProcess, this]() -> RefPtr { + if (!Get()) { + // Shutdown? + return EnsureRDDPromise::CreateAndReject( + NS_ERROR_NOT_AVAILABLE, __func__); + } + if (mProcess) { + ipc::Endpoint endpoint; + if (!CreateContentBridge(aOtherProcess, &endpoint)) { + return EnsureRDDPromise::CreateAndReject( + NS_ERROR_NOT_AVAILABLE, __func__); + } + return EnsureRDDPromise::CreateAndResolve( + std::move(endpoint), __func__); + } - RefPtr task = - NS_NewRunnableFunction("RDDProcessManager::RDDProcessManager", [&]() { - if (mProcess) { - success = - CreateContentBridge(aOtherProcess, aOutRemoteDecoderManager); - return; - } + mNumProcessAttempts++; - mNumProcessAttempts++; + std::vector extraArgs; + nsCString parentBuildID(mozilla::PlatformBuildID()); + extraArgs.push_back("-parentBuildID"); + extraArgs.push_back(parentBuildID.get()); - std::vector extraArgs; - nsCString parentBuildID(mozilla::PlatformBuildID()); - extraArgs.push_back("-parentBuildID"); - extraArgs.push_back(parentBuildID.get()); - - // The subprocess is launched asynchronously, so we wait for a callback - // to acquire the IPDL actor. - mProcess = new RDDProcessHost(this); - if (!mProcess->Launch(extraArgs)) { - DestroyProcess(); - return; - } - if (!EnsureRDDReady()) { - return; - } - - success = CreateVideoBridge() && - CreateContentBridge(aOtherProcess, aOutRemoteDecoderManager); - }); - SyncRunnable::DispatchToThread(GetMainThreadSerialEventTarget(), task); - - return success; + // The subprocess is launched asynchronously, so we wait + // for a callback to acquire the IPDL actor. + mProcess = new RDDProcessHost(this); + if (!mProcess->Launch(extraArgs)) { + DestroyProcess(); + return EnsureRDDPromise::CreateAndReject( + NS_ERROR_NOT_AVAILABLE, __func__); + } + ipc::Endpoint endpoint; + if (!EnsureRDDReady() || !CreateVideoBridge() || + !CreateContentBridge(aOtherProcess, &endpoint)) { + return EnsureRDDPromise::CreateAndReject( + NS_ERROR_NOT_AVAILABLE, __func__); + } + return EnsureRDDPromise::CreateAndResolve( + std::move(endpoint), __func__); + }); } bool RDDProcessManager::IsRDDProcessLaunching() { @@ -237,27 +242,23 @@ void RDDProcessManager::DestroyProcess() { bool RDDProcessManager::CreateContentBridge( base::ProcessId aOtherProcess, ipc::Endpoint* aOutRemoteDecoderManager) { - bool success = false; - RefPtr task = - NS_NewRunnableFunction("RDDProcessManager::RDDProcessManager", [&]() { - ipc::Endpoint parentPipe; - ipc::Endpoint childPipe; + MOZ_ASSERT(NS_IsMainThread()); - nsresult rv = PRemoteDecoderManager::CreateEndpoints( - mRDDChild->OtherPid(), aOtherProcess, &parentPipe, &childPipe); - if (NS_FAILED(rv)) { - MOZ_LOG(sPDMLog, LogLevel::Debug, - ("Could not create content remote decoder: %d", int(rv))); - return; - } + ipc::Endpoint parentPipe; + ipc::Endpoint childPipe; - mRDDChild->SendNewContentRemoteDecoderManager(std::move(parentPipe)); + nsresult rv = PRemoteDecoderManager::CreateEndpoints( + mRDDChild->OtherPid(), aOtherProcess, &parentPipe, &childPipe); + if (NS_FAILED(rv)) { + MOZ_LOG(sPDMLog, LogLevel::Debug, + ("Could not create content remote decoder: %d", int(rv))); + return false; + } - *aOutRemoteDecoderManager = std::move(childPipe); - success = true; - }); - SyncRunnable::DispatchToThread(GetMainThreadSerialEventTarget(), task); - return success; + mRDDChild->SendNewContentRemoteDecoderManager(std::move(parentPipe)); + + *aOutRemoteDecoderManager = std::move(childPipe); + return true; } bool RDDProcessManager::CreateVideoBridge() { diff --git a/dom/media/ipc/RDDProcessManager.h b/dom/media/ipc/RDDProcessManager.h index e00ed5e53296..ab0db1a9d5ee 100644 --- a/dom/media/ipc/RDDProcessManager.h +++ b/dom/media/ipc/RDDProcessManager.h @@ -5,13 +5,14 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef _include_dom_media_ipc_RDDProcessManager_h_ #define _include_dom_media_ipc_RDDProcessManager_h_ +#include "mozilla/MozPromise.h" +#include "mozilla/PRemoteDecoderManagerChild.h" #include "mozilla/RDDProcessHost.h" #include "mozilla/ipc/TaskFactory.h" namespace mozilla { class MemoryReportingProcess; -class PRemoteDecoderManagerChild; class RDDChild; // The RDDProcessManager is a singleton responsible for creating RDD-bound @@ -27,18 +28,12 @@ class RDDProcessManager final : public RDDProcessHost::Listener { ~RDDProcessManager(); + using EnsureRDDPromise = + MozPromise, nsresult, true>; // If not using a RDD process, launch a new RDD process asynchronously and // create a RemoteDecoderManager bridge - bool EnsureRDDProcessAndCreateBridge( - base::ProcessId aOtherProcess, - mozilla::ipc::Endpoint* - aOutRemoteDecoderManager); - bool IsRDDProcessLaunching(); - - // Ensure that RDD-bound methods can be used. If no RDD process is being - // used, or one is launched and ready, this function returns immediately. - // Otherwise it blocks until the RDD process has finished launching. - bool EnsureRDDReady(); + RefPtr EnsureRDDProcessAndCreateBridge( + base::ProcessId aOtherProcess); void OnProcessLaunchComplete(RDDProcessHost* aHost) override; void OnProcessUnexpectedShutdown(RDDProcessHost* aHost) override; @@ -67,6 +62,11 @@ class RDDProcessManager final : public RDDProcessHost::Listener { RDDProcessHost* Process() { return mProcess; } private: + bool IsRDDProcessLaunching(); + // Ensure that RDD-bound methods can be used. If no RDD process is being + // used, or one is launched and ready, this function returns immediately. + // Otherwise it blocks until the RDD process has finished launching. + bool EnsureRDDReady(); bool CreateVideoBridge(); // Called from our xpcom-shutdown observer. @@ -94,13 +94,12 @@ class RDDProcessManager final : public RDDProcessHost::Listener { }; friend class Observer; - private: - bool CreateContentBridge(base::ProcessId aOtherProcess, - mozilla::ipc::Endpoint* - aOutRemoteDecoderManager); + bool CreateContentBridge( + base::ProcessId aOtherProcess, + ipc::Endpoint* aOutRemoteDecoderManager); const RefPtr mObserver; - mozilla::ipc::TaskFactory mTaskFactory; + ipc::TaskFactory mTaskFactory; uint32_t mNumProcessAttempts = 0; // Fields that are associated with the current RDD process. @@ -110,7 +109,7 @@ class RDDProcessManager final : public RDDProcessHost::Listener { // Collects any pref changes that occur during process launch (after // the initial map is passed in command-line arguments) to be sent // when the process can receive IPC messages. - nsTArray mQueuedPrefs; + nsTArray mQueuedPrefs; }; } // namespace mozilla diff --git a/ipc/glue/BackgroundParentImpl.cpp b/ipc/glue/BackgroundParentImpl.cpp index 3e86d9dc4663..05462759a462 100644 --- a/ipc/glue/BackgroundParentImpl.cpp +++ b/ipc/glue/BackgroundParentImpl.cpp @@ -761,7 +761,7 @@ bool BackgroundParentImpl::DeallocPCamerasParent( } auto BackgroundParentImpl::AllocPUDPSocketParent( - const Maybe& /* unused */, const nsCString & /* unused */) + const Maybe& /* unused */, const nsCString& /* unused */) -> PUDPSocketParent* { RefPtr p = new UDPSocketParent(this); @@ -1316,15 +1316,25 @@ mozilla::ipc::IPCResult BackgroundParentImpl::RecvEnsureRDDProcessAndCreateBridge( EnsureRDDProcessAndCreateBridgeResolver&& aResolver) { RDDProcessManager* rdd = RDDProcessManager::Get(); - Endpoint endpoint; - nsresult rv = - rdd && rdd->EnsureRDDProcessAndCreateBridge(OtherPid(), &endpoint) - ? NS_OK - : NS_ERROR_NOT_AVAILABLE; - aResolver( - Tuple&&>( - rv, std::move(endpoint))); - + using Type = + Tuple&&>; + if (!rdd) { + aResolver( + Type(NS_ERROR_NOT_AVAILABLE, Endpoint())); + } else { + rdd->EnsureRDDProcessAndCreateBridge(OtherPid()) + ->Then(GetCurrentSerialEventTarget(), __func__, + [resolver = std::move(aResolver)]( + mozilla::RDDProcessManager::EnsureRDDPromise:: + ResolveOrRejectValue&& aValue) mutable { + if (aValue.IsReject()) { + resolver(Type(aValue.RejectValue(), + Endpoint())); + return; + } + resolver(Type(NS_OK, std::move(aValue.ResolveValue()))); + }); + } return IPC_OK(); }