author | Chris Pearce <cpearce@mozilla.com> |
Wed, 09 Nov 2016 15:52:22 +1300 | |
changeset 324013 | cb29571e849184f019cf7343afb0ac6d36fa0e11 |
parent 324012 | 3a60967cd9ed58bf2ec9573b0185e3537a42518c |
child 324014 | 4be3169b9d0257f3e0182dd1ad5d60a9a98eef48 |
push id | 30988 |
push user | cbook@mozilla.com |
push date | Thu, 24 Nov 2016 15:35:58 +0000 |
treeherder | mozilla-central@9aef92f7911d [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | gerald |
bugs | 1316215 |
milestone | 53.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/media/gmp/GMPParent.cpp +++ b/dom/media/gmp/GMPParent.cpp @@ -1048,94 +1048,85 @@ GMPParent::RecvAsyncShutdownComplete() mService->SetAsyncShutdownPluginState(this, 'L', NS_LITERAL_CSTRING("Received AsyncShutdownComplete")); } #endif AbortAsyncShutdown(); return IPC_OK(); } -class RunCreateContentParentCallbacks : public Runnable +void +GMPParent::ResolveGetContentParentPromises() { -public: - explicit RunCreateContentParentCallbacks(GMPContentParent* aGMPContentParent) - : mGMPContentParent(aGMPContentParent) - { - } - - void TakeCallbacks(nsTArray<UniquePtr<GetGMPContentParentCallback>>& aCallbacks) - { - mCallbacks.SwapElements(aCallbacks); + nsTArray<UniquePtr<MozPromiseHolder<GetGMPContentParentPromise>>> promises; + promises.SwapElements(mGetContentParentPromises); + MOZ_ASSERT(mGetContentParentPromises.IsEmpty()); + for (auto& holder : promises) { + holder->Resolve(mGMPContentParent, __func__); } - - NS_IMETHOD - Run() override - { - for (uint32_t i = 0, length = mCallbacks.Length(); i < length; ++i) { - mCallbacks[i]->Done(mGMPContentParent); - } - return NS_OK; - } - -private: - RefPtr<GMPContentParent> mGMPContentParent; - nsTArray<UniquePtr<GetGMPContentParentCallback>> mCallbacks; -}; +} PGMPContentParent* GMPParent::AllocPGMPContentParent(Transport* aTransport, ProcessId aOtherPid) { MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); MOZ_ASSERT(!mGMPContentParent); mGMPContentParent = new GMPContentParent(this); mGMPContentParent->Open(aTransport, aOtherPid, XRE_GetIOMessageLoop(), ipc::ParentSide); - RefPtr<RunCreateContentParentCallbacks> runCallbacks = - new RunCreateContentParentCallbacks(mGMPContentParent); - runCallbacks->TakeCallbacks(mCallbacks); - NS_DispatchToCurrentThread(runCallbacks); - MOZ_ASSERT(mCallbacks.IsEmpty()); + ResolveGetContentParentPromises(); return mGMPContentParent; } -bool -GMPParent::GetGMPContentParent(UniquePtr<GetGMPContentParentCallback>&& aCallback) +void +GMPParent::RejectGetContentParentPromises() +{ + nsTArray<UniquePtr<MozPromiseHolder<GetGMPContentParentPromise>>> promises; + promises.SwapElements(mGetContentParentPromises); + MOZ_ASSERT(mGetContentParentPromises.IsEmpty()); + for (auto& holder : promises) { + holder->Reject(NS_ERROR_FAILURE, __func__); + } +} + +void +GMPParent::GetGMPContentParent(UniquePtr<MozPromiseHolder<GetGMPContentParentPromise>>&& aPromiseHolder) { LOGD("%s %p", __FUNCTION__, this); MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); if (mGMPContentParent) { - aCallback->Done(mGMPContentParent); + aPromiseHolder->Resolve(mGMPContentParent, __func__); } else { - mCallbacks.AppendElement(Move(aCallback)); + mGetContentParentPromises.AppendElement(Move(aPromiseHolder)); // If we don't have a GMPContentParent and we try to get one for the first - // time (mCallbacks.Length() == 1) then call PGMPContent::Open. If more + // time (mGetContentParentPromises.Length() == 1) then call PGMPContent::Open. If more // calls to GetGMPContentParent happen before mGMPContentParent has been // set then we should just store them, so that they get called when we set // mGMPContentParent as a result of the PGMPContent::Open call. - if (mCallbacks.Length() == 1) { + if (mGetContentParentPromises.Length() == 1) { if (!EnsureProcessLoaded() || !PGMPContent::Open(this)) { - return false; + RejectGetContentParentPromises(); + return; } // We want to increment this as soon as possible, to avoid that we'd try // to shut down the GMP process while we're still trying to get a // PGMPContentParent actor. ++mGMPContentChildCount; } } - return true; } already_AddRefed<GMPContentParent> GMPParent::ForgetGMPContentParent() { - MOZ_ASSERT(mCallbacks.IsEmpty()); + MOZ_ASSERT(mGetContentParentPromises.IsEmpty()); return Move(mGMPContentParent.forget()); } bool GMPParent::EnsureProcessLoaded(base::ProcessId* aID) { if (!EnsureProcessLoaded()) { return false;
--- a/dom/media/gmp/GMPParent.h +++ b/dom/media/gmp/GMPParent.h @@ -68,30 +68,16 @@ enum GMPState { GMPStateNotLoaded, GMPStateLoaded, GMPStateUnloading, GMPStateClosing }; class GMPContentParent; -class GetGMPContentParentCallback -{ -public: - GetGMPContentParentCallback() - { - MOZ_COUNT_CTOR(GetGMPContentParentCallback); - }; - virtual ~GetGMPContentParentCallback() - { - MOZ_COUNT_DTOR(GetGMPContentParentCallback); - }; - virtual void Done(GMPContentParent* aGMPContentParent) = 0; -}; - class GMPParent final : public PGMPParent { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPParent) GMPParent(); RefPtr<GenericPromise> Init(GeckoMediaPluginServiceParent* aService, nsIFile* aPluginDir); @@ -154,17 +140,17 @@ public: return nsCOMPtr<nsIFile>(mDirectory).forget(); } void AbortAsyncShutdown(); // Called when the child process has died. void ChildTerminated(); - bool GetGMPContentParent(UniquePtr<GetGMPContentParentCallback>&& aCallback); + void GetGMPContentParent(UniquePtr<MozPromiseHolder<GetGMPContentParentPromise>>&& aPromiseHolder); already_AddRefed<GMPContentParent> ForgetGMPContentParent(); bool EnsureProcessLoaded(base::ProcessId* aID); bool Bridge(GMPServiceParent* aGMPServiceParent); const nsTArray<GMPCapability>& GetCapabilities() const { return mCapabilities; } @@ -201,16 +187,18 @@ private: mozilla::ipc::IPCResult RecvAsyncShutdownRequired() override; mozilla::ipc::IPCResult RecvPGMPContentChildDestroyed() override; bool IsUsed() { return mGMPContentChildCount > 0; } + void ResolveGetContentParentPromises(); + void RejectGetContentParentPromises(); static void AbortWaitingForGMPAsyncShutdown(nsITimer* aTimer, void* aClosure); nsresult EnsureAsyncShutdownTimeoutSet(); GMPState mState; nsCOMPtr<nsIFile> mDirectory; // plugin directory on disk nsString mName; // base name of plugin on disk, UTF-16 because used for paths nsCString mDisplayName; // name of plugin displayed to users @@ -234,17 +222,17 @@ private: nsCOMPtr<nsIThread> mGMPThread; nsCOMPtr<nsITimer> mAsyncShutdownTimeout; // GMP Thread only. // NodeId the plugin is assigned to, or empty if the the plugin is not // assigned to a NodeId. nsCString mNodeId; // This is used for GMP content in the parent, there may be more of these in // the content processes. RefPtr<GMPContentParent> mGMPContentParent; - nsTArray<UniquePtr<GetGMPContentParentCallback>> mCallbacks; + nsTArray<UniquePtr<MozPromiseHolder<GetGMPContentParentPromise>>> mGetContentParentPromises; uint32_t mGMPContentChildCount; bool mAsyncShutdownRequired; bool mAsyncShutdownInProgress; int mChildPid; // We hold a self reference to ourself while the child process is alive.
--- a/dom/media/gmp/GMPService.cpp +++ b/dom/media/gmp/GMPService.cpp @@ -290,201 +290,126 @@ GeckoMediaPluginService::GetThread(nsITh RefPtr<AbstractThread> GeckoMediaPluginService::GetAbstractGMPThread() { MutexAutoLock lock(mMutex); return mAbstractGMPThread; } -class GetGMPContentParentForAudioDecoderDone : public GetGMPContentParentCallback -{ -public: - explicit GetGMPContentParentForAudioDecoderDone(UniquePtr<GetGMPAudioDecoderCallback>&& aCallback, - GMPCrashHelper* aHelper) - : mCallback(Move(aCallback)) - , mHelper(aHelper) - { - } - - void Done(GMPContentParent* aGMPParent) override - { - GMPAudioDecoderParent* gmpADP = nullptr; - if (aGMPParent && NS_SUCCEEDED(aGMPParent->GetGMPAudioDecoder(&gmpADP))) { - gmpADP->SetCrashHelper(mHelper); - } - mCallback->Done(gmpADP); - } - -private: - UniquePtr<GetGMPAudioDecoderCallback> mCallback; - RefPtr<GMPCrashHelper> mHelper; -}; - NS_IMETHODIMP GeckoMediaPluginService::GetGMPAudioDecoder(GMPCrashHelper* aHelper, nsTArray<nsCString>* aTags, const nsACString& aNodeId, UniquePtr<GetGMPAudioDecoderCallback>&& aCallback) { MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); NS_ENSURE_ARG(aTags && aTags->Length() > 0); NS_ENSURE_ARG(aCallback); if (mShuttingDownOnGMPThread) { return NS_ERROR_FAILURE; } - UniquePtr<GetGMPContentParentCallback> callback( - new GetGMPContentParentForAudioDecoderDone(Move(aCallback), aHelper)); - if (!GetContentParentFrom(aHelper, - aNodeId, - NS_LITERAL_CSTRING(GMP_API_AUDIO_DECODER), - *aTags, - Move(callback))) { - return NS_ERROR_FAILURE; - } + GetGMPAudioDecoderCallback* rawCallback = aCallback.release(); + RefPtr<AbstractThread> thread(GetAbstractGMPThread()); + RefPtr<GMPCrashHelper> helper(aHelper); + GetContentParent(aHelper, aNodeId, NS_LITERAL_CSTRING(GMP_API_AUDIO_DECODER), *aTags) + ->Then(thread, __func__, + [rawCallback, helper](RefPtr<GMPContentParent> parent) { + UniquePtr<GetGMPAudioDecoderCallback> callback(rawCallback); + GMPAudioDecoderParent* actor = nullptr; + if (parent && NS_SUCCEEDED(parent->GetGMPAudioDecoder(&actor))) { + actor->SetCrashHelper(helper); + } + callback->Done(actor); + }, + [rawCallback] { + UniquePtr<GetGMPAudioDecoderCallback> callback(rawCallback); + callback->Done(nullptr); + }); return NS_OK; } -class GetGMPContentParentForVideoDecoderDone : public GetGMPContentParentCallback -{ -public: - explicit GetGMPContentParentForVideoDecoderDone(UniquePtr<GetGMPVideoDecoderCallback>&& aCallback, - GMPCrashHelper* aHelper, - uint32_t aDecryptorId) - : mCallback(Move(aCallback)) - , mHelper(aHelper) - , mDecryptorId(aDecryptorId) - { - } - - void Done(GMPContentParent* aGMPParent) override - { - GMPVideoDecoderParent* gmpVDP = nullptr; - GMPVideoHostImpl* videoHost = nullptr; - if (aGMPParent && NS_SUCCEEDED(aGMPParent->GetGMPVideoDecoder(&gmpVDP, mDecryptorId))) { - videoHost = &gmpVDP->Host(); - gmpVDP->SetCrashHelper(mHelper); - } - mCallback->Done(gmpVDP, videoHost); - } - -private: - UniquePtr<GetGMPVideoDecoderCallback> mCallback; - RefPtr<GMPCrashHelper> mHelper; - const uint32_t mDecryptorId; -}; - NS_IMETHODIMP GeckoMediaPluginService::GetDecryptingGMPVideoDecoder(GMPCrashHelper* aHelper, nsTArray<nsCString>* aTags, const nsACString& aNodeId, UniquePtr<GetGMPVideoDecoderCallback>&& aCallback, uint32_t aDecryptorId) { MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); NS_ENSURE_ARG(aTags && aTags->Length() > 0); NS_ENSURE_ARG(aCallback); if (mShuttingDownOnGMPThread) { return NS_ERROR_FAILURE; } - UniquePtr<GetGMPContentParentCallback> callback( - new GetGMPContentParentForVideoDecoderDone(Move(aCallback), aHelper, aDecryptorId)); - if (!GetContentParentFrom(aHelper, - aNodeId, - NS_LITERAL_CSTRING(GMP_API_VIDEO_DECODER), - *aTags, - Move(callback))) { - return NS_ERROR_FAILURE; - } + GetGMPVideoDecoderCallback* rawCallback = aCallback.release(); + RefPtr<AbstractThread> thread(GetAbstractGMPThread()); + RefPtr<GMPCrashHelper> helper(aHelper); + GetContentParent(aHelper, aNodeId, NS_LITERAL_CSTRING(GMP_API_VIDEO_DECODER), *aTags) + ->Then(thread, __func__, + [rawCallback, helper, aDecryptorId](RefPtr<GMPContentParent> parent) { + UniquePtr<GetGMPVideoDecoderCallback> callback(rawCallback); + GMPVideoDecoderParent* actor = nullptr; + GMPVideoHostImpl* host = nullptr; + if (parent && NS_SUCCEEDED(parent->GetGMPVideoDecoder(&actor, aDecryptorId))) { + host = &(actor->Host()); + actor->SetCrashHelper(helper); + } + callback->Done(actor, host); + }, + [rawCallback] { + UniquePtr<GetGMPVideoDecoderCallback> callback(rawCallback); + callback->Done(nullptr, nullptr); + }); return NS_OK; } -class GetGMPContentParentForVideoEncoderDone : public GetGMPContentParentCallback -{ -public: - explicit GetGMPContentParentForVideoEncoderDone(UniquePtr<GetGMPVideoEncoderCallback>&& aCallback, - GMPCrashHelper* aHelper) - : mCallback(Move(aCallback)) - , mHelper(aHelper) - { - } - - void Done(GMPContentParent* aGMPParent) override - { - GMPVideoEncoderParent* gmpVEP = nullptr; - GMPVideoHostImpl* videoHost = nullptr; - if (aGMPParent && NS_SUCCEEDED(aGMPParent->GetGMPVideoEncoder(&gmpVEP))) { - videoHost = &gmpVEP->Host(); - gmpVEP->SetCrashHelper(mHelper); - } - mCallback->Done(gmpVEP, videoHost); - } - -private: - UniquePtr<GetGMPVideoEncoderCallback> mCallback; - RefPtr<GMPCrashHelper> mHelper; -}; - NS_IMETHODIMP GeckoMediaPluginService::GetGMPVideoEncoder(GMPCrashHelper* aHelper, nsTArray<nsCString>* aTags, const nsACString& aNodeId, UniquePtr<GetGMPVideoEncoderCallback>&& aCallback) { MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); NS_ENSURE_ARG(aTags && aTags->Length() > 0); NS_ENSURE_ARG(aCallback); if (mShuttingDownOnGMPThread) { return NS_ERROR_FAILURE; } - UniquePtr<GetGMPContentParentCallback> callback( - new GetGMPContentParentForVideoEncoderDone(Move(aCallback), aHelper)); - if (!GetContentParentFrom(aHelper, - aNodeId, - NS_LITERAL_CSTRING(GMP_API_VIDEO_ENCODER), - *aTags, - Move(callback))) { - return NS_ERROR_FAILURE; - } + GetGMPVideoEncoderCallback* rawCallback = aCallback.release(); + RefPtr<AbstractThread> thread(GetAbstractGMPThread()); + RefPtr<GMPCrashHelper> helper(aHelper); + GetContentParent(aHelper, aNodeId, NS_LITERAL_CSTRING(GMP_API_VIDEO_ENCODER), *aTags) + ->Then(thread, __func__, + [rawCallback, helper](RefPtr<GMPContentParent> parent) { + UniquePtr<GetGMPVideoEncoderCallback> callback(rawCallback); + GMPVideoEncoderParent* actor = nullptr; + GMPVideoHostImpl* host = nullptr; + if (parent && NS_SUCCEEDED(parent->GetGMPVideoEncoder(&actor))) { + host = &(actor->Host()); + actor->SetCrashHelper(helper); + } + callback->Done(actor, host); + }, + [rawCallback] { + UniquePtr<GetGMPVideoEncoderCallback> callback(rawCallback); + callback->Done(nullptr, nullptr); + }); return NS_OK; } -class GetGMPContentParentForDecryptorDone : public GetGMPContentParentCallback -{ -public: - explicit GetGMPContentParentForDecryptorDone(UniquePtr<GetGMPDecryptorCallback>&& aCallback, - GMPCrashHelper* aHelper) - : mCallback(Move(aCallback)) - , mHelper(aHelper) - { - } - - void Done(GMPContentParent* aGMPParent) override - { - GMPDecryptorParent* ksp = nullptr; - if (aGMPParent && NS_SUCCEEDED(aGMPParent->GetGMPDecryptor(&ksp))) { - ksp->SetCrashHelper(mHelper); - } - mCallback->Done(ksp); - } - -private: - UniquePtr<GetGMPDecryptorCallback> mCallback; - RefPtr<GMPCrashHelper> mHelper; -}; - NS_IMETHODIMP GeckoMediaPluginService::GetGMPDecryptor(GMPCrashHelper* aHelper, nsTArray<nsCString>* aTags, const nsACString& aNodeId, UniquePtr<GetGMPDecryptorCallback>&& aCallback) { #if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX) if (!SandboxInfo::Get().CanSandboxMedia()) { @@ -497,25 +422,33 @@ GeckoMediaPluginService::GetGMPDecryptor MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); NS_ENSURE_ARG(aTags && aTags->Length() > 0); NS_ENSURE_ARG(aCallback); if (mShuttingDownOnGMPThread) { return NS_ERROR_FAILURE; } - UniquePtr<GetGMPContentParentCallback> callback( - new GetGMPContentParentForDecryptorDone(Move(aCallback), aHelper)); - if (!GetContentParentFrom(aHelper, - aNodeId, - NS_LITERAL_CSTRING(GMP_API_DECRYPTOR), - *aTags, - Move(callback))) { - return NS_ERROR_FAILURE; - } + GetGMPDecryptorCallback* rawCallback = aCallback.release(); + RefPtr<AbstractThread> thread(GetAbstractGMPThread()); + RefPtr<GMPCrashHelper> helper(aHelper); + GetContentParent(aHelper, aNodeId, NS_LITERAL_CSTRING(GMP_API_DECRYPTOR), *aTags) + ->Then(thread, __func__, + [rawCallback, helper](RefPtr<GMPContentParent> parent) { + UniquePtr<GetGMPDecryptorCallback> callback(rawCallback); + GMPDecryptorParent* actor = nullptr; + if (parent && NS_SUCCEEDED(parent->GetGMPDecryptor(&actor))) { + actor->SetCrashHelper(helper); + } + callback->Done(actor); + }, + [rawCallback] { + UniquePtr<GetGMPDecryptorCallback> callback(rawCallback); + callback->Done(nullptr); + }); return NS_OK; } void GeckoMediaPluginService::ConnectCrashHelper(uint32_t aPluginId, GMPCrashHelper* aHelper) { if (!aHelper) {
--- a/dom/media/gmp/GMPService.h +++ b/dom/media/gmp/GMPService.h @@ -16,28 +16,30 @@ #include "nsCOMPtr.h" #include "nsIThread.h" #include "nsThreadUtils.h" #include "nsIDocument.h" #include "nsIWeakReference.h" #include "mozilla/AbstractThread.h" #include "nsClassHashtable.h" #include "nsISupportsImpl.h" +#include "mozilla/MozPromise.h" template <class> struct already_AddRefed; namespace mozilla { class GMPCrashHelper; extern LogModule* GetGMPLog(); namespace gmp { -class GetGMPContentParentCallback; +class GMPContentParent; +typedef MozPromise<RefPtr<GMPContentParent>, nsresult, /* IsExclusive = */ true> GetGMPContentParentPromise; class GeckoMediaPluginService : public mozIGeckoMediaPluginService , public nsIObserver { public: static already_AddRefed<GeckoMediaPluginService> GetGeckoMediaPluginService(); virtual nsresult Init(); @@ -88,21 +90,22 @@ public: void ConnectCrashHelper(uint32_t aPluginId, GMPCrashHelper* aHelper); void DisconnectCrashHelper(GMPCrashHelper* aHelper); protected: GeckoMediaPluginService(); virtual ~GeckoMediaPluginService(); virtual void InitializePlugins(AbstractThread* aAbstractGMPThread) = 0; - virtual bool GetContentParentFrom(GMPCrashHelper* aHelper, - const nsACString& aNodeId, - const nsCString& aAPI, - const nsTArray<nsCString>& aTags, - UniquePtr<GetGMPContentParentCallback>&& aCallback) = 0; + + virtual RefPtr<GetGMPContentParentPromise> + GetContentParent(GMPCrashHelper* aHelper, + const nsACString& aNodeId, + const nsCString& aAPI, + const nsTArray<nsCString>& aTags) = 0; nsresult GMPDispatch(nsIRunnable* event, uint32_t flags = NS_DISPATCH_NORMAL); nsresult GMPDispatch(already_AddRefed<nsIRunnable> event, uint32_t flags = NS_DISPATCH_NORMAL); void ShutdownGMPThread(); Mutex mMutex; // Protects mGMPThread, mAbstractGMPThread, mPluginCrashHelpers, // mGMPThreadShutdown and some members in derived classes. nsCOMPtr<nsIThread> mGMPThread;
--- a/dom/media/gmp/GMPServiceChild.cpp +++ b/dom/media/gmp/GMPServiceChild.cpp @@ -47,95 +47,77 @@ GeckoMediaPluginServiceChild::GetSinglet nsCOMPtr<mozIGeckoMediaPluginChromeService> chromeService; CallQueryInterface(service.get(), getter_AddRefs(chromeService)); MOZ_ASSERT(!chromeService); } #endif return service.forget().downcast<GeckoMediaPluginServiceChild>(); } -class GetContentParentFromDone : public GetServiceChildCallback -{ -public: - GetContentParentFromDone(GMPCrashHelper* aHelper, const nsACString& aNodeId, const nsCString& aAPI, - const nsTArray<nsCString>& aTags, - UniquePtr<GetGMPContentParentCallback>&& aCallback) - : mHelper(aHelper), - mNodeId(aNodeId), - mAPI(aAPI), - mTags(aTags), - mCallback(Move(aCallback)) - { - } - - void Done(GMPServiceChild* aGMPServiceChild) override - { - if (!aGMPServiceChild) { - mCallback->Done(nullptr); - return; - } - - uint32_t pluginId; - nsresult rv; - bool ok = aGMPServiceChild->SendSelectGMP(mNodeId, mAPI, mTags, &pluginId, &rv); - if (!ok || rv == NS_ERROR_ILLEGAL_DURING_SHUTDOWN) { - mCallback->Done(nullptr); - return; - } - - if (mHelper) { - RefPtr<GeckoMediaPluginService> gmps(GeckoMediaPluginService::GetGeckoMediaPluginService()); - gmps->ConnectCrashHelper(pluginId, mHelper); - } - - nsTArray<base::ProcessId> alreadyBridgedTo; - aGMPServiceChild->GetAlreadyBridgedTo(alreadyBridgedTo); - - base::ProcessId otherProcess; - nsCString displayName; - ok = aGMPServiceChild->SendLaunchGMP(pluginId, alreadyBridgedTo, &otherProcess, - &displayName, &rv); - if (!ok || rv == NS_ERROR_ILLEGAL_DURING_SHUTDOWN) { - mCallback->Done(nullptr); - return; - } - - RefPtr<GMPContentParent> parent; - aGMPServiceChild->GetBridgedGMPContentParent(otherProcess, - getter_AddRefs(parent)); - if (!alreadyBridgedTo.Contains(otherProcess)) { - parent->SetDisplayName(displayName); - parent->SetPluginId(pluginId); - } - - mCallback->Done(parent); - } - -private: - RefPtr<GMPCrashHelper> mHelper; - nsCString mNodeId; - nsCString mAPI; - const nsTArray<nsCString> mTags; - UniquePtr<GetGMPContentParentCallback> mCallback; -}; - -bool -GeckoMediaPluginServiceChild::GetContentParentFrom(GMPCrashHelper* aHelper, - const nsACString& aNodeId, - const nsCString& aAPI, - const nsTArray<nsCString>& aTags, - UniquePtr<GetGMPContentParentCallback>&& aCallback) +RefPtr<GetGMPContentParentPromise> +GeckoMediaPluginServiceChild::GetContentParent(GMPCrashHelper* aHelper, + const nsACString& aNodeId, + const nsCString& aAPI, + const nsTArray<nsCString>& aTags) { MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - UniquePtr<GetServiceChildCallback> callback( - new GetContentParentFromDone(aHelper, aNodeId, aAPI, aTags, Move(aCallback))); - GetServiceChild(Move(callback)); + MozPromiseHolder<GetGMPContentParentPromise>* rawHolder = new MozPromiseHolder<GetGMPContentParentPromise>(); + RefPtr<GetGMPContentParentPromise> promise = rawHolder->Ensure(__func__); + RefPtr<AbstractThread> thread(GetAbstractGMPThread()); + + nsCString nodeId(aNodeId); + nsCString api(aAPI); + nsTArray<nsCString> tags(aTags); + RefPtr<GMPCrashHelper> helper(aHelper); + RefPtr<GeckoMediaPluginServiceChild> self(this); + GetServiceChild()->Then(thread, __func__, + [self, nodeId, api, tags, helper, rawHolder](GMPServiceChild* child) { + UniquePtr<MozPromiseHolder<GetGMPContentParentPromise>> holder(rawHolder); + nsresult rv; + uint32_t pluginId = 0; + bool ok = child->SendSelectGMP(nodeId, api, tags, &pluginId, &rv); + if (!ok || rv == NS_ERROR_ILLEGAL_DURING_SHUTDOWN) { + holder->Reject(rv, __func__); + return; + } + + if (helper) { + self->ConnectCrashHelper(pluginId, helper); + } + + nsTArray<base::ProcessId> alreadyBridgedTo; + child->GetAlreadyBridgedTo(alreadyBridgedTo); - return true; + base::ProcessId otherProcess; + nsCString displayName; + ok = child->SendLaunchGMP(pluginId, + alreadyBridgedTo, + &otherProcess, + &displayName, + &rv); + if (!ok || rv == NS_ERROR_ILLEGAL_DURING_SHUTDOWN) { + holder->Reject(rv, __func__); + return; + } + + RefPtr<GMPContentParent> parent; + child->GetBridgedGMPContentParent(otherProcess, getter_AddRefs(parent)); + if (!alreadyBridgedTo.Contains(otherProcess)) { + parent->SetDisplayName(displayName); + parent->SetPluginId(pluginId); + } + holder->Resolve(parent, __func__); + }, + [rawHolder](nsresult rv) { + UniquePtr<MozPromiseHolder<GetGMPContentParentPromise>> holder(rawHolder); + holder->Reject(rv, __func__); + }); + + return promise; } typedef mozilla::dom::GMPCapabilityData GMPCapabilityData; typedef mozilla::dom::GMPAPITags GMPAPITags; struct GMPCapabilityAndVersion { explicit GMPCapabilityAndVersion(const GMPCapabilityData& aCapabilities) @@ -239,66 +221,49 @@ GeckoMediaPluginServiceChild::HasPluginF return NS_OK; } } *aHasPlugin = false; return NS_OK; } -class GetNodeIdDone : public GetServiceChildCallback -{ -public: - GetNodeIdDone(const nsAString& aOrigin, const nsAString& aTopLevelOrigin, - const nsAString& aGMPName, - bool aInPrivateBrowsing, UniquePtr<GetNodeIdCallback>&& aCallback) - : mOrigin(aOrigin), - mTopLevelOrigin(aTopLevelOrigin), - mGMPName(aGMPName), - mInPrivateBrowsing(aInPrivateBrowsing), - mCallback(Move(aCallback)) - { - } - - void Done(GMPServiceChild* aGMPServiceChild) override - { - if (!aGMPServiceChild) { - mCallback->Done(NS_ERROR_FAILURE, EmptyCString()); - return; - } - - nsCString outId; - if (!aGMPServiceChild->SendGetGMPNodeId(mOrigin, mTopLevelOrigin, - mGMPName, - mInPrivateBrowsing, &outId)) { - mCallback->Done(NS_ERROR_FAILURE, EmptyCString()); - return; - } - - mCallback->Done(NS_OK, outId); - } - -private: - nsString mOrigin; - nsString mTopLevelOrigin; - nsString mGMPName; - bool mInPrivateBrowsing; - UniquePtr<GetNodeIdCallback> mCallback; -}; - NS_IMETHODIMP GeckoMediaPluginServiceChild::GetNodeId(const nsAString& aOrigin, const nsAString& aTopLevelOrigin, const nsAString& aGMPName, bool aInPrivateBrowsing, UniquePtr<GetNodeIdCallback>&& aCallback) { - UniquePtr<GetServiceChildCallback> callback( - new GetNodeIdDone(aOrigin, aTopLevelOrigin, aGMPName, aInPrivateBrowsing, Move(aCallback))); - GetServiceChild(Move(callback)); + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); + + GetNodeIdCallback* rawCallback = aCallback.release(); + RefPtr<AbstractThread> thread(GetAbstractGMPThread()); + nsString origin(aOrigin); + nsString topLevelOrigin(aTopLevelOrigin); + nsString gmpName(aGMPName); + bool pb = aInPrivateBrowsing; + GetServiceChild()->Then(thread, __func__, + [rawCallback, origin, topLevelOrigin, gmpName, pb](GMPServiceChild* child) { + UniquePtr<GetNodeIdCallback> callback(rawCallback); + nsCString outId; + if (!child->SendGetGMPNodeId(origin, topLevelOrigin, + gmpName, + pb, &outId)) { + callback->Done(NS_ERROR_FAILURE, EmptyCString()); + return; + } + + callback->Done(NS_OK, outId); + }, + [rawCallback](nsresult rv) { + UniquePtr<GetNodeIdCallback> callback(rawCallback); + callback->Done(NS_ERROR_FAILURE, EmptyCString()); + }); + return NS_OK; } NS_IMETHODIMP GeckoMediaPluginServiceChild::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aSomeData) { @@ -311,51 +276,56 @@ GeckoMediaPluginServiceChild::Observe(ns mServiceChild = nullptr; } ShutdownGMPThread(); } return NS_OK; } -void -GeckoMediaPluginServiceChild::GetServiceChild(UniquePtr<GetServiceChildCallback>&& aCallback) +RefPtr<GeckoMediaPluginServiceChild::GetServiceChildPromise> +GeckoMediaPluginServiceChild::GetServiceChild() { - MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); if (!mServiceChild) { dom::ContentChild* contentChild = dom::ContentChild::GetSingleton(); if (!contentChild) { - return; + return GetServiceChildPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); } - mGetServiceChildCallbacks.AppendElement(Move(aCallback)); - if (mGetServiceChildCallbacks.Length() == 1) { + MozPromiseHolder<GetServiceChildPromise>* holder = mGetServiceChildPromises.AppendElement(); + RefPtr<GetServiceChildPromise> promise = holder->Ensure(__func__); + if (mGetServiceChildPromises.Length() == 1) { NS_DispatchToMainThread(WrapRunnable(contentChild, &dom::ContentChild::SendCreateGMPService)); } - return; + return promise; } - - aCallback->Done(mServiceChild.get()); + return GetServiceChildPromise::CreateAndResolve(mServiceChild.get(), __func__); } void GeckoMediaPluginServiceChild::SetServiceChild(UniquePtr<GMPServiceChild>&& aServiceChild) { + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); + mServiceChild = Move(aServiceChild); - nsTArray<UniquePtr<GetServiceChildCallback>> getServiceChildCallbacks; - getServiceChildCallbacks.SwapElements(mGetServiceChildCallbacks); - for (uint32_t i = 0, length = getServiceChildCallbacks.Length(); i < length; ++i) { - getServiceChildCallbacks[i]->Done(mServiceChild.get()); + + nsTArray<MozPromiseHolder<GetServiceChildPromise>> holders; + holders.SwapElements(mGetServiceChildPromises); + for (MozPromiseHolder<GetServiceChildPromise>& holder : holders) { + holder.Resolve(mServiceChild.get(), __func__); } } void GeckoMediaPluginServiceChild::RemoveGMPContentParent(GMPContentParent* aGMPContentParent) { + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); + if (mServiceChild) { mServiceChild->RemoveGMPContentParent(aGMPContentParent); } } GMPServiceChild::GMPServiceChild() { }
--- a/dom/media/gmp/GMPServiceChild.h +++ b/dom/media/gmp/GMPServiceChild.h @@ -14,30 +14,16 @@ #include "mozilla/dom/ContentChild.h" namespace mozilla { namespace gmp { class GMPContentParent; class GMPServiceChild; -class GetServiceChildCallback -{ -public: - GetServiceChildCallback() - { - MOZ_COUNT_CTOR(GetServiceChildCallback); - } - virtual ~GetServiceChildCallback() - { - MOZ_COUNT_DTOR(GetServiceChildCallback); - } - virtual void Done(GMPServiceChild* aGMPServiceChild) = 0; -}; - class GeckoMediaPluginServiceChild : public GeckoMediaPluginService { friend class GMPServiceChild; public: static already_AddRefed<GeckoMediaPluginServiceChild> GetSingleton(); NS_IMETHOD HasPluginForAPI(const nsACString& aAPI, @@ -57,30 +43,31 @@ public: static void UpdateGMPCapabilities(nsTArray<mozilla::dom::GMPCapabilityData>&& aCapabilities); protected: void InitializePlugins(AbstractThread*) override { // Nothing to do here. } - bool GetContentParentFrom(GMPCrashHelper* aHelper, - const nsACString& aNodeId, - const nsCString& aAPI, - const nsTArray<nsCString>& aTags, - UniquePtr<GetGMPContentParentCallback>&& aCallback) - override; + + virtual RefPtr<GetGMPContentParentPromise> + GetContentParent(GMPCrashHelper* aHelper, + const nsACString& aNodeId, + const nsCString& aAPI, + const nsTArray<nsCString>& aTags) override; private: friend class OpenPGMPServiceChild; - void GetServiceChild(UniquePtr<GetServiceChildCallback>&& aCallback); + typedef MozPromise<GMPServiceChild*, nsresult, /* IsExclusive = */ true> GetServiceChildPromise; + RefPtr<GetServiceChildPromise> GetServiceChild(); + nsTArray<MozPromiseHolder<GetServiceChildPromise>> mGetServiceChildPromises; UniquePtr<GMPServiceChild> mServiceChild; - nsTArray<UniquePtr<GetServiceChildCallback>> mGetServiceChildCallbacks; }; class GMPServiceChild : public PGMPServiceChild { public: explicit GMPServiceChild(); virtual ~GMPServiceChild();
--- a/dom/media/gmp/GMPServiceParent.cpp +++ b/dom/media/gmp/GMPServiceParent.cpp @@ -524,53 +524,55 @@ GeckoMediaPluginServiceParent::EnsureIni if (mLoadPluginsFromDiskComplete) { return GenericPromise::CreateAndResolve(true, __func__); } // We should have an init promise in flight. MOZ_ASSERT(!mInitPromise.IsEmpty()); return mInitPromise.Ensure(__func__); } -bool -GeckoMediaPluginServiceParent::GetContentParentFrom(GMPCrashHelper* aHelper, - const nsACString& aNodeId, - const nsCString& aAPI, - const nsTArray<nsCString>& aTags, - UniquePtr<GetGMPContentParentCallback>&& aCallback) +RefPtr<GetGMPContentParentPromise> +GeckoMediaPluginServiceParent::GetContentParent(GMPCrashHelper* aHelper, + const nsACString& aNodeId, + const nsCString& aAPI, + const nsTArray<nsCString>& aTags) { RefPtr<AbstractThread> thread(GetAbstractGMPThread()); if (!thread) { - return false; + return GetGMPContentParentPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); } + typedef MozPromiseHolder<GetGMPContentParentPromise> PromiseHolder; + PromiseHolder* rawHolder = new PromiseHolder(); RefPtr<GeckoMediaPluginServiceParent> self(this); + RefPtr<GetGMPContentParentPromise> promise = rawHolder->Ensure(__func__); nsCString nodeId(aNodeId); nsTArray<nsCString> tags(aTags); nsCString api(aAPI); - GetGMPContentParentCallback* rawCallback = aCallback.release(); RefPtr<GMPCrashHelper> helper(aHelper); EnsureInitialized()->Then(thread, __func__, - [self, tags, api, nodeId, rawCallback, helper]() -> void { - UniquePtr<GetGMPContentParentCallback> callback(rawCallback); + [self, tags, api, nodeId, helper, rawHolder]() -> void { + UniquePtr<PromiseHolder> holder(rawHolder); RefPtr<GMPParent> gmp = self->SelectPluginForAPI(nodeId, api, tags); LOGD(("%s: %p returning %p for api %s", __FUNCTION__, (void *)self, (void *)gmp, api.get())); if (!gmp) { NS_WARNING("GeckoMediaPluginServiceParent::GetContentParentFrom failed"); - callback->Done(nullptr); + holder->Reject(NS_ERROR_FAILURE, __func__); return; } self->ConnectCrashHelper(gmp->GetPluginId(), helper); - gmp->GetGMPContentParent(Move(callback)); + gmp->GetGMPContentParent(Move(holder)); }, - [rawCallback]() -> void { - UniquePtr<GetGMPContentParentCallback> callback(rawCallback); + [rawHolder]() -> void { + UniquePtr<PromiseHolder> holder(rawHolder); NS_WARNING("GMPService::EnsureInitialized failed."); - callback->Done(nullptr); + holder->Reject(NS_ERROR_FAILURE, __func__); }); - return true; + + return promise; } void GeckoMediaPluginServiceParent::InitializePlugins( AbstractThread* aAbstractGMPThread) { MOZ_ASSERT(aAbstractGMPThread); MonitorAutoLock lock(mInitPromiseMonitor);
--- a/dom/media/gmp/GMPServiceParent.h +++ b/dom/media/gmp/GMPServiceParent.h @@ -121,22 +121,23 @@ private: protected: friend class GMPParent; void ReAddOnGMPThread(const RefPtr<GMPParent>& aOld); void PluginTerminated(const RefPtr<GMPParent>& aOld); void InitializePlugins(AbstractThread* aAbstractGMPThread) override; RefPtr<GenericPromise::AllPromiseType> LoadFromEnvironment(); RefPtr<GenericPromise> AddOnGMPThread(nsString aDirectory); - bool GetContentParentFrom(GMPCrashHelper* aHelper, - const nsACString& aNodeId, - const nsCString& aAPI, - const nsTArray<nsCString>& aTags, - UniquePtr<GetGMPContentParentCallback>&& aCallback) - override; + + virtual RefPtr<GetGMPContentParentPromise> + GetContentParent(GMPCrashHelper* aHelper, + const nsACString& aNodeId, + const nsCString& aAPI, + const nsTArray<nsCString>& aTags) override; + private: // Creates a copy of aOriginal. Note that the caller is responsible for // adding this to GeckoMediaPluginServiceParent::mPlugins. already_AddRefed<GMPParent> ClonePlugin(const GMPParent* aOriginal); nsresult EnsurePluginsOnDiskScanned(); nsresult InitStorage(); class PathRunnable : public Runnable