--- 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