зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1057908 - GeckoMediaPluginService needs to be proxied from Content processes to parent process. Part 5 - use bridging for GMP in e10s. r=billm.
--HG-- extra : rebase_source : a20ed3386758ceabccb50b68a9b9081c17a95c49
This commit is contained in:
Родитель
8308cf3a1b
Коммит
166fcb5464
|
@ -178,6 +178,7 @@
|
|||
#include "mozilla/dom/voicemail/VoicemailIPCService.h"
|
||||
#include "mozilla/net/NeckoMessageUtils.h"
|
||||
#include "mozilla/RemoteSpellCheckEngineChild.h"
|
||||
#include "GMPServiceChild.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::docshell;
|
||||
|
@ -191,6 +192,7 @@ using namespace mozilla::dom::mobilemessage;
|
|||
using namespace mozilla::dom::telephony;
|
||||
using namespace mozilla::dom::voicemail;
|
||||
using namespace mozilla::embedding;
|
||||
using namespace mozilla::gmp;
|
||||
using namespace mozilla::hal_sandbox;
|
||||
using namespace mozilla::ipc;
|
||||
using namespace mozilla::layers;
|
||||
|
@ -1036,6 +1038,13 @@ ContentChild::AllocPContentBridgeParent(mozilla::ipc::Transport* aTransport,
|
|||
return mLastBridge;
|
||||
}
|
||||
|
||||
PGMPServiceChild*
|
||||
ContentChild::AllocPGMPServiceChild(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess)
|
||||
{
|
||||
return GMPServiceChild::Create(aTransport, aOtherProcess);
|
||||
}
|
||||
|
||||
PCompositorChild*
|
||||
ContentChild::AllocPCompositorChild(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess)
|
||||
|
|
|
@ -115,6 +115,10 @@ public:
|
|||
AllocPContentBridgeChild(mozilla::ipc::Transport* transport,
|
||||
base::ProcessId otherProcess) override;
|
||||
|
||||
PGMPServiceChild*
|
||||
AllocPGMPServiceChild(mozilla::ipc::Transport* transport,
|
||||
base::ProcessId otherProcess) override;
|
||||
|
||||
PCompositorChild*
|
||||
AllocPCompositorChild(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess) override;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "AudioChannelService.h"
|
||||
#include "BlobParent.h"
|
||||
#include "CrashReporterParent.h"
|
||||
#include "GMPServiceParent.h"
|
||||
#include "IHistory.h"
|
||||
#include "mozIApplication.h"
|
||||
#ifdef ACCESSIBILITY
|
||||
|
@ -233,6 +234,7 @@ using namespace mozilla::dom::mobilemessage;
|
|||
using namespace mozilla::dom::telephony;
|
||||
using namespace mozilla::dom::voicemail;
|
||||
using namespace mozilla::embedding;
|
||||
using namespace mozilla::gmp;
|
||||
using namespace mozilla::hal;
|
||||
using namespace mozilla::ipc;
|
||||
using namespace mozilla::layers;
|
||||
|
@ -981,6 +983,23 @@ static nsIDocShell* GetOpenerDocShellHelper(Element* aFrameElement)
|
|||
return docShell;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvCreateGMPService()
|
||||
{
|
||||
return PGMPService::Open(this);
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvGetGMPPluginVersionForAPI(const nsCString& aAPI,
|
||||
nsTArray<nsCString>&& aTags,
|
||||
bool* aHasVersion,
|
||||
nsCString* aVersion)
|
||||
{
|
||||
return GMPServiceParent::RecvGetGMPPluginVersionForAPI(aAPI, Move(aTags),
|
||||
aHasVersion,
|
||||
aVersion);
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvLoadPlugin(const uint32_t& aPluginId, nsresult* aRv)
|
||||
{
|
||||
|
@ -3062,6 +3081,13 @@ ContentParent::RecvPDocAccessibleConstructor(PDocAccessibleParent* aDoc, PDocAcc
|
|||
return true;
|
||||
}
|
||||
|
||||
PGMPServiceParent*
|
||||
ContentParent::AllocPGMPServiceParent(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess)
|
||||
{
|
||||
return GMPServiceParent::Create(aTransport, aOtherProcess);
|
||||
}
|
||||
|
||||
PCompositorParent*
|
||||
ContentParent::AllocPCompositorParent(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess)
|
||||
|
|
|
@ -153,6 +153,12 @@ public:
|
|||
TabId* aTabId) override;
|
||||
virtual bool RecvBridgeToChildProcess(const ContentParentId& aCpId) override;
|
||||
|
||||
virtual bool RecvCreateGMPService() override;
|
||||
virtual bool RecvGetGMPPluginVersionForAPI(const nsCString& aAPI,
|
||||
nsTArray<nsCString>&& aTags,
|
||||
bool* aHasPlugin,
|
||||
nsCString* aVersion) override;
|
||||
|
||||
virtual bool RecvLoadPlugin(const uint32_t& aPluginId, nsresult* aRv) override;
|
||||
virtual bool RecvConnectPluginBridge(const uint32_t& aPluginId, nsresult* aRv) override;
|
||||
virtual bool RecvFindPlugins(const uint32_t& aPluginEpoch,
|
||||
|
@ -488,6 +494,9 @@ private:
|
|||
|
||||
static void ForceKillTimerCallback(nsITimer* aTimer, void* aClosure);
|
||||
|
||||
PGMPServiceParent*
|
||||
AllocPGMPServiceParent(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess) override;
|
||||
PCompositorParent*
|
||||
AllocPCompositorParent(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess) override;
|
||||
|
|
|
@ -27,7 +27,15 @@ include protocol PImageBridge;
|
|||
include protocol PMemoryReportRequest;
|
||||
include protocol PMobileConnection;
|
||||
include protocol PNecko;
|
||||
// FIXME This is pretty ridiculous, but we have to keep the order of the
|
||||
// following 4 includes, or the parser is confused about PGMPContent
|
||||
// bridging PContent and PGMP. As soon as it registers the bridge between
|
||||
// PContent and PPluginModule it seems to think that PContent's parent and
|
||||
// child live in the same process!
|
||||
include protocol PGMPContent;
|
||||
include protocol PGMPService;
|
||||
include protocol PPluginModule;
|
||||
include protocol PGMP;
|
||||
include protocol PPrinting;
|
||||
include protocol POfflineCacheUpdate;
|
||||
include protocol PScreenManager;
|
||||
|
@ -364,6 +372,7 @@ prio(normal upto urgent) sync protocol PContent
|
|||
parent opens PProcessHangMonitor;
|
||||
parent opens PSharedBufferManager;
|
||||
parent opens PImageBridge;
|
||||
parent opens PGMPService;
|
||||
child opens PBackground;
|
||||
|
||||
manages PAsmJSCacheEntry;
|
||||
|
@ -608,6 +617,10 @@ parent:
|
|||
returns (ContentParentId cpId, bool isForApp, bool isForBrowser, TabId tabId);
|
||||
sync BridgeToChildProcess(ContentParentId cpId);
|
||||
|
||||
async CreateGMPService();
|
||||
sync GetGMPPluginVersionForAPI(nsCString api, nsCString[] tags)
|
||||
returns (bool hasPlugin, nsCString version);
|
||||
|
||||
/**
|
||||
* This call connects the content process to a plugin process. While this
|
||||
* call runs, a new PluginModuleParent will be created in the ContentChild
|
||||
|
|
|
@ -110,7 +110,9 @@ private:
|
|||
bool mInitDone;
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
};
|
||||
|
||||
void GetGMPAPI(GMPInitDoneRunnable* aInitDone);
|
||||
|
||||
class GMPInitDoneCallback : public GetGMPAudioDecoderCallback
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -126,7 +126,9 @@ private:
|
|||
bool mInitDone;
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
};
|
||||
|
||||
void GetGMPAPI(GMPInitDoneRunnable* aInitDone);
|
||||
|
||||
class GMPInitDoneCallback : public GetGMPVideoDecoderCallback
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "GMPAudioDecoderParent.h"
|
||||
#include "GMPDecryptorParent.h"
|
||||
#include "GMPParent.h"
|
||||
#include "GMPServiceChild.h"
|
||||
#include "GMPVideoDecoderParent.h"
|
||||
#include "GMPVideoEncoderParent.h"
|
||||
#include "mozIGeckoMediaPluginService.h"
|
||||
|
@ -128,7 +129,15 @@ GMPContentParent::CloseIfUnused()
|
|||
mDecryptors.IsEmpty() &&
|
||||
mVideoDecoders.IsEmpty() &&
|
||||
mVideoEncoders.IsEmpty()) {
|
||||
nsRefPtr<GMPContentParent> toClose(mParent->ForgetGMPContentParent());
|
||||
nsRefPtr<GMPContentParent> toClose;
|
||||
if (mParent) {
|
||||
toClose = mParent->ForgetGMPContentParent();
|
||||
} else {
|
||||
toClose = this;
|
||||
nsRefPtr<GeckoMediaPluginServiceChild> gmp(
|
||||
GeckoMediaPluginServiceChild::GetSingleton());
|
||||
gmp->RemoveGMPContentParent(toClose);
|
||||
}
|
||||
NS_DispatchToCurrentThread(NS_NewRunnableMethod(toClose,
|
||||
&GMPContentParent::Close));
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ class GMPContentParent final : public PGMPContentParent,
|
|||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPContentParent)
|
||||
|
||||
explicit GMPContentParent(GMPParent* aParent);
|
||||
explicit GMPContentParent(GMPParent* aParent = nullptr);
|
||||
|
||||
nsresult GetGMPVideoDecoder(GMPVideoDecoderParent** aGMPVD);
|
||||
void VideoDecoderDestroyed(GMPVideoDecoderParent* aDecoder);
|
||||
|
|
|
@ -894,6 +894,26 @@ GMPParent::ForgetGMPContentParent()
|
|||
return Move(mGMPContentParent.forget());
|
||||
}
|
||||
|
||||
bool
|
||||
GMPParent::EnsureProcessLoaded(base::ProcessId* aID)
|
||||
{
|
||||
if (!EnsureProcessLoaded()) {
|
||||
return false;
|
||||
}
|
||||
*aID = OtherPid();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GMPParent::Bridge(GMPServiceParent* aGMPServiceParent)
|
||||
{
|
||||
if (!PGMPContent::Bridge(aGMPServiceParent, this)) {
|
||||
return false;
|
||||
}
|
||||
++mGMPContentChildCount;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace gmp
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -139,6 +139,10 @@ public:
|
|||
bool GetGMPContentParent(UniquePtr<GetGMPContentParentCallback>&& aCallback);
|
||||
already_AddRefed<GMPContentParent> ForgetGMPContentParent();
|
||||
|
||||
bool EnsureProcessLoaded(base::ProcessId* aID);
|
||||
|
||||
bool Bridge(GMPServiceParent* aGMPServiceParent);
|
||||
|
||||
private:
|
||||
~GMPParent();
|
||||
nsRefPtr<GeckoMediaPluginServiceParent> mService;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "GMPServiceParent.h"
|
||||
#include "GMPServiceChild.h"
|
||||
#include "prio.h"
|
||||
#include "prlog.h"
|
||||
#include "GMPParent.h"
|
||||
|
@ -108,11 +109,18 @@ private:
|
|||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!sSingletonService) {
|
||||
nsRefPtr<GeckoMediaPluginServiceParent> service =
|
||||
new GeckoMediaPluginServiceParent();
|
||||
service->Init();
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
nsRefPtr<GeckoMediaPluginServiceParent> service =
|
||||
new GeckoMediaPluginServiceParent();
|
||||
service->Init();
|
||||
sSingletonService = service;
|
||||
} else {
|
||||
nsRefPtr<GeckoMediaPluginServiceChild> service =
|
||||
new GeckoMediaPluginServiceChild();
|
||||
service->Init();
|
||||
sSingletonService = service;
|
||||
}
|
||||
|
||||
sSingletonService = service;
|
||||
ClearOnShutdown(&sSingletonService);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,382 @@
|
|||
/* -*- 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 "GMPService.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#ifdef LOG
|
||||
#undef LOG
|
||||
#endif
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
#define LOGD(msg) PR_LOG(GetGMPLog(), PR_LOG_DEBUG, msg)
|
||||
#define LOG(level, msg) PR_LOG(GetGMPLog(), (level), msg)
|
||||
#else
|
||||
#define LOGD(msg)
|
||||
#define LOG(leve1, msg)
|
||||
#endif
|
||||
|
||||
#ifdef __CLASS__
|
||||
#undef __CLASS__
|
||||
#endif
|
||||
#define __CLASS__ "GMPService"
|
||||
|
||||
namespace gmp {
|
||||
|
||||
already_AddRefed<GeckoMediaPluginServiceChild>
|
||||
GeckoMediaPluginServiceChild::GetSingleton()
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() != GeckoProcessType_Default);
|
||||
nsRefPtr<GeckoMediaPluginService> service(
|
||||
GeckoMediaPluginService::GetGeckoMediaPluginService());
|
||||
#ifdef DEBUG
|
||||
if (service) {
|
||||
nsCOMPtr<mozIGeckoMediaPluginChromeService> chromeService;
|
||||
CallQueryInterface(service.get(), getter_AddRefs(chromeService));
|
||||
MOZ_ASSERT(!chromeService);
|
||||
}
|
||||
#endif
|
||||
return service.forget().downcast<GeckoMediaPluginServiceChild>();
|
||||
}
|
||||
|
||||
class GetServiceChildCallback
|
||||
{
|
||||
public:
|
||||
GetServiceChildCallback()
|
||||
{
|
||||
MOZ_COUNT_CTOR(GetServiceChildCallback);
|
||||
}
|
||||
virtual ~GetServiceChildCallback()
|
||||
{
|
||||
MOZ_COUNT_DTOR(GetServiceChildCallback);
|
||||
}
|
||||
virtual void Done(GMPServiceChild* aGMPServiceChild) = 0;
|
||||
};
|
||||
|
||||
class GetContentParentFromDone : public GetServiceChildCallback
|
||||
{
|
||||
public:
|
||||
GetContentParentFromDone(const nsACString& aNodeId, const nsCString& aAPI,
|
||||
const nsTArray<nsCString>& aTags,
|
||||
UniquePtr<GetGMPContentParentCallback>&& aCallback)
|
||||
: mNodeId(aNodeId),
|
||||
mAPI(aAPI),
|
||||
mTags(aTags),
|
||||
mCallback(Move(aCallback))
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Done(GMPServiceChild* aGMPServiceChild)
|
||||
{
|
||||
if (!aGMPServiceChild) {
|
||||
mCallback->Done(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
nsTArray<base::ProcessId> alreadyBridgedTo;
|
||||
aGMPServiceChild->GetAlreadyBridgedTo(alreadyBridgedTo);
|
||||
|
||||
base::ProcessId otherProcess;
|
||||
nsCString displayName;
|
||||
nsCString pluginId;
|
||||
bool ok = aGMPServiceChild->SendLoadGMP(mNodeId, mAPI, mTags,
|
||||
alreadyBridgedTo, &otherProcess,
|
||||
&displayName, &pluginId);
|
||||
if (!ok) {
|
||||
mCallback->Done(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<GMPContentParent> parent;
|
||||
aGMPServiceChild->GetBridgedGMPContentParent(otherProcess,
|
||||
getter_AddRefs(parent));
|
||||
if (!alreadyBridgedTo.Contains(otherProcess)) {
|
||||
parent->SetDisplayName(displayName);
|
||||
parent->SetPluginId(pluginId);
|
||||
}
|
||||
|
||||
mCallback->Done(parent);
|
||||
}
|
||||
|
||||
private:
|
||||
nsCString mNodeId;
|
||||
nsCString mAPI;
|
||||
const nsTArray<nsCString> mTags;
|
||||
UniquePtr<GetGMPContentParentCallback> mCallback;
|
||||
};
|
||||
|
||||
bool
|
||||
GeckoMediaPluginServiceChild::GetContentParentFrom(const nsACString& aNodeId,
|
||||
const nsCString& aAPI,
|
||||
const nsTArray<nsCString>& aTags,
|
||||
UniquePtr<GetGMPContentParentCallback>&& aCallback)
|
||||
{
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
||||
|
||||
UniquePtr<GetServiceChildCallback> callback(
|
||||
new GetContentParentFromDone(aNodeId, aAPI, aTags, Move(aCallback)));
|
||||
GetServiceChild(Move(callback));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GeckoMediaPluginServiceChild::GetPluginVersionForAPI(const nsACString& aAPI,
|
||||
nsTArray<nsCString>* aTags,
|
||||
bool* aHasPlugin,
|
||||
nsACString& aOutVersion)
|
||||
{
|
||||
dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
|
||||
if (!contentChild) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCString version;
|
||||
bool ok = contentChild->SendGetGMPPluginVersionForAPI(nsCString(aAPI), *aTags,
|
||||
aHasPlugin, &version);
|
||||
aOutVersion = version;
|
||||
return ok ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
class GetNodeIdDone : public GetServiceChildCallback
|
||||
{
|
||||
public:
|
||||
GetNodeIdDone(const nsAString& aOrigin, const nsAString& aTopLevelOrigin,
|
||||
bool aInPrivateBrowsing,
|
||||
UniquePtr<GetNodeIdCallback>&& aCallback)
|
||||
: mOrigin(aOrigin),
|
||||
mTopLevelOrigin(aTopLevelOrigin),
|
||||
mInPrivateBrowsing(aInPrivateBrowsing),
|
||||
mCallback(Move(aCallback))
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Done(GMPServiceChild* aGMPServiceChild)
|
||||
{
|
||||
if (!aGMPServiceChild) {
|
||||
mCallback->Done(NS_ERROR_FAILURE, EmptyCString());
|
||||
return;
|
||||
}
|
||||
|
||||
nsCString outId;
|
||||
if (!aGMPServiceChild->SendGetGMPNodeId(mOrigin, mTopLevelOrigin,
|
||||
mInPrivateBrowsing, &outId)) {
|
||||
mCallback->Done(NS_ERROR_FAILURE, EmptyCString());
|
||||
return;
|
||||
}
|
||||
|
||||
mCallback->Done(NS_OK, outId);
|
||||
}
|
||||
|
||||
private:
|
||||
nsString mOrigin;
|
||||
nsString mTopLevelOrigin;
|
||||
bool mInPrivateBrowsing;
|
||||
UniquePtr<GetNodeIdCallback> mCallback;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
GeckoMediaPluginServiceChild::GetNodeId(const nsAString& aOrigin,
|
||||
const nsAString& aTopLevelOrigin,
|
||||
bool aInPrivateBrowsing,
|
||||
UniquePtr<GetNodeIdCallback>&& aCallback)
|
||||
{
|
||||
UniquePtr<GetServiceChildCallback> callback(
|
||||
new GetNodeIdDone(aOrigin, aTopLevelOrigin, aInPrivateBrowsing,
|
||||
Move(aCallback)));
|
||||
GetServiceChild(Move(callback));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GeckoMediaPluginServiceChild::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const char16_t* aSomeData)
|
||||
{
|
||||
LOGD(("%s::%s: %s", __CLASS__, __FUNCTION__, aTopic));
|
||||
if (!strcmp(NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, aTopic)) {
|
||||
if (mServiceChild) {
|
||||
mozilla::SyncRunnable::DispatchToThread(mGMPThread,
|
||||
WrapRunnable(mServiceChild.get(),
|
||||
&PGMPServiceChild::Close));
|
||||
mServiceChild = nullptr;
|
||||
}
|
||||
ShutdownGMPThread();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
GeckoMediaPluginServiceChild::GetServiceChild(UniquePtr<GetServiceChildCallback>&& aCallback)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
if (!mServiceChild) {
|
||||
dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
|
||||
if (!contentChild) {
|
||||
return;
|
||||
}
|
||||
mGetServiceChildCallbacks.AppendElement(Move(aCallback));
|
||||
if (mGetServiceChildCallbacks.Length() == 1) {
|
||||
NS_DispatchToMainThread(WrapRunnable(contentChild,
|
||||
&dom::ContentChild::SendCreateGMPService));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
aCallback->Done(mServiceChild.get());
|
||||
}
|
||||
|
||||
void
|
||||
GeckoMediaPluginServiceChild::SetServiceChild(UniquePtr<GMPServiceChild>&& aServiceChild)
|
||||
{
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GeckoMediaPluginServiceChild::RemoveGMPContentParent(GMPContentParent* aGMPContentParent)
|
||||
{
|
||||
if (mServiceChild) {
|
||||
mServiceChild->RemoveGMPContentParent(aGMPContentParent);
|
||||
}
|
||||
}
|
||||
|
||||
GMPServiceChild::GMPServiceChild()
|
||||
{
|
||||
}
|
||||
|
||||
GMPServiceChild::~GMPServiceChild()
|
||||
{
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
|
||||
new DeleteTask<Transport>(GetTransport()));
|
||||
}
|
||||
|
||||
PGMPContentParent*
|
||||
GMPServiceChild::AllocPGMPContentParent(Transport* aTransport,
|
||||
ProcessId aOtherPid)
|
||||
{
|
||||
MOZ_ASSERT(!mContentParents.GetWeak(aOtherPid));
|
||||
|
||||
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
|
||||
MOZ_ASSERT(mainThread);
|
||||
|
||||
nsRefPtr<GMPContentParent> parent = new GMPContentParent();
|
||||
|
||||
DebugOnly<bool> ok = parent->Open(aTransport, aOtherPid,
|
||||
XRE_GetIOMessageLoop(),
|
||||
mozilla::ipc::ParentSide);
|
||||
MOZ_ASSERT(ok);
|
||||
|
||||
mContentParents.Put(aOtherPid, parent);
|
||||
return parent;
|
||||
}
|
||||
|
||||
void
|
||||
GMPServiceChild::GetBridgedGMPContentParent(ProcessId aOtherPid,
|
||||
GMPContentParent** aGMPContentParent)
|
||||
{
|
||||
mContentParents.Get(aOtherPid, aGMPContentParent);
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
FindAndRemoveGMPContentParent(const uint64_t& aKey,
|
||||
nsRefPtr<GMPContentParent>& aData,
|
||||
void* aUserArg)
|
||||
{
|
||||
return aData == aUserArg ?
|
||||
(PLDHashOperator)(PL_DHASH_STOP | PL_DHASH_REMOVE) :
|
||||
PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
GMPServiceChild::RemoveGMPContentParent(GMPContentParent* aGMPContentParent)
|
||||
{
|
||||
mContentParents.Enumerate(FindAndRemoveGMPContentParent, aGMPContentParent);
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
FillProcessIDArray(const uint64_t& aKey, GMPContentParent*, void* aUserArg)
|
||||
{
|
||||
static_cast<nsTArray<base::ProcessId>*>(aUserArg)->AppendElement(aKey);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
GMPServiceChild::GetAlreadyBridgedTo(nsTArray<base::ProcessId>& aAlreadyBridgedTo)
|
||||
{
|
||||
aAlreadyBridgedTo.SetCapacity(mContentParents.Count());
|
||||
mContentParents.EnumerateRead(FillProcessIDArray, &aAlreadyBridgedTo);
|
||||
}
|
||||
|
||||
class OpenPGMPServiceChild : public nsRunnable
|
||||
{
|
||||
public:
|
||||
OpenPGMPServiceChild(UniquePtr<GMPServiceChild>&& aGMPServiceChild,
|
||||
mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherPid)
|
||||
: mGMPServiceChild(Move(aGMPServiceChild)),
|
||||
mTransport(aTransport),
|
||||
mOtherPid(aOtherPid)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
nsRefPtr<GeckoMediaPluginServiceChild> gmp =
|
||||
GeckoMediaPluginServiceChild::GetSingleton();
|
||||
MOZ_ASSERT(!gmp->mServiceChild);
|
||||
if (mGMPServiceChild->Open(mTransport, mOtherPid, XRE_GetIOMessageLoop(),
|
||||
ipc::ChildSide)) {
|
||||
gmp->SetServiceChild(Move(mGMPServiceChild));
|
||||
} else {
|
||||
gmp->SetServiceChild(nullptr);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
UniquePtr<GMPServiceChild> mGMPServiceChild;
|
||||
mozilla::ipc::Transport* mTransport;
|
||||
base::ProcessId mOtherPid;
|
||||
};
|
||||
|
||||
/* static */
|
||||
PGMPServiceChild*
|
||||
GMPServiceChild::Create(Transport* aTransport, ProcessId aOtherPid)
|
||||
{
|
||||
nsRefPtr<GeckoMediaPluginServiceChild> gmp =
|
||||
GeckoMediaPluginServiceChild::GetSingleton();
|
||||
MOZ_ASSERT(!gmp->mServiceChild);
|
||||
|
||||
UniquePtr<GMPServiceChild> serviceChild(new GMPServiceChild());
|
||||
|
||||
nsCOMPtr<nsIThread> gmpThread;
|
||||
nsresult rv = gmp->GetThread(getter_AddRefs(gmpThread));
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
GMPServiceChild* result = serviceChild.get();
|
||||
rv = gmpThread->Dispatch(new OpenPGMPServiceChild(Move(serviceChild),
|
||||
aTransport,
|
||||
aOtherPid),
|
||||
NS_DISPATCH_NORMAL);
|
||||
if (NS_FAILED(rv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace gmp
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,90 @@
|
|||
/* -*- 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 GMPServiceChild_h_
|
||||
#define GMPServiceChild_h_
|
||||
|
||||
#include "GMPService.h"
|
||||
#include "base/process.h"
|
||||
#include "mozilla/ipc/Transport.h"
|
||||
#include "mozilla/gmp/PGMPServiceChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gmp {
|
||||
|
||||
#define GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT 3000
|
||||
|
||||
class GMPContentParent;
|
||||
class GMPServiceChild;
|
||||
class GetServiceChildCallback;
|
||||
|
||||
class GeckoMediaPluginServiceChild : public GeckoMediaPluginService
|
||||
{
|
||||
friend class GMPServiceChild;
|
||||
|
||||
public:
|
||||
static already_AddRefed<GeckoMediaPluginServiceChild> GetSingleton();
|
||||
|
||||
NS_IMETHOD GetPluginVersionForAPI(const nsACString& aAPI,
|
||||
nsTArray<nsCString>* aTags,
|
||||
bool* aHasPlugin,
|
||||
nsACString& aOutVersion) override;
|
||||
NS_IMETHOD GetNodeId(const nsAString& aOrigin,
|
||||
const nsAString& aTopLevelOrigin,
|
||||
bool aInPrivateBrowsingMode,
|
||||
UniquePtr<GetNodeIdCallback>&& aCallback) override;
|
||||
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
void SetServiceChild(UniquePtr<GMPServiceChild>&& aServiceChild);
|
||||
|
||||
void RemoveGMPContentParent(GMPContentParent* aGMPContentParent);
|
||||
|
||||
protected:
|
||||
virtual void InitializePlugins() override
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
virtual bool GetContentParentFrom(const nsACString& aNodeId,
|
||||
const nsCString& aAPI,
|
||||
const nsTArray<nsCString>& aTags,
|
||||
UniquePtr<GetGMPContentParentCallback>&& aCallback)
|
||||
override;
|
||||
|
||||
private:
|
||||
friend class OpenPGMPServiceChild;
|
||||
|
||||
void GetServiceChild(UniquePtr<GetServiceChildCallback>&& aCallback);
|
||||
|
||||
UniquePtr<GMPServiceChild> mServiceChild;
|
||||
nsTArray<UniquePtr<GetServiceChildCallback>> mGetServiceChildCallbacks;
|
||||
};
|
||||
|
||||
class GMPServiceChild : public PGMPServiceChild
|
||||
{
|
||||
public:
|
||||
explicit GMPServiceChild();
|
||||
virtual ~GMPServiceChild();
|
||||
|
||||
virtual PGMPContentParent* AllocPGMPContentParent(Transport* aTransport,
|
||||
ProcessId aOtherPid)
|
||||
override;
|
||||
|
||||
void GetBridgedGMPContentParent(ProcessId aOtherPid,
|
||||
GMPContentParent** aGMPContentParent);
|
||||
void RemoveGMPContentParent(GMPContentParent* aGMPContentParent);
|
||||
|
||||
void GetAlreadyBridgedTo(nsTArray<ProcessId>& aAlreadyBridgedTo);
|
||||
|
||||
static PGMPServiceChild* Create(Transport* aTransport, ProcessId aOtherPid);
|
||||
|
||||
private:
|
||||
nsRefPtrHashtable<nsUint64HashKey, GMPContentParent> mContentParents;
|
||||
};
|
||||
|
||||
} // namespace gmp
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // GMPServiceChild_h_
|
|
@ -1329,5 +1329,138 @@ GeckoMediaPluginServiceParent::ClearStorage()
|
|||
NS_DispatchToMainThread(new NotifyObserversTask("gmp-clear-storage-complete"), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
GMPServiceParent::~GMPServiceParent()
|
||||
{
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
|
||||
new DeleteTask<Transport>(GetTransport()));
|
||||
}
|
||||
|
||||
bool
|
||||
GMPServiceParent::RecvLoadGMP(const nsCString& aNodeId,
|
||||
const nsCString& aAPI,
|
||||
nsTArray<nsCString>&& aTags,
|
||||
nsTArray<ProcessId>&& aAlreadyBridgedTo,
|
||||
ProcessId* aId,
|
||||
nsCString* aDisplayName,
|
||||
nsCString* aPluginId)
|
||||
{
|
||||
nsRefPtr<GMPParent> gmp = mService->SelectPluginForAPI(aNodeId, aAPI, aTags);
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
nsCString api = aTags[0];
|
||||
LOGD(("%s: %p returning %p for api %s", __FUNCTION__, (void *)this, (void *)gmp, api.get()));
|
||||
#endif
|
||||
|
||||
if (!gmp || !gmp->EnsureProcessLoaded(aId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*aDisplayName = gmp->GetDisplayName();
|
||||
*aPluginId = gmp->GetPluginId();
|
||||
|
||||
return aAlreadyBridgedTo.Contains(*aId) || gmp->Bridge(this);
|
||||
}
|
||||
|
||||
bool
|
||||
GMPServiceParent::RecvGetGMPNodeId(const nsString& aOrigin,
|
||||
const nsString& aTopLevelOrigin,
|
||||
const bool& aInPrivateBrowsing,
|
||||
nsCString* aID)
|
||||
{
|
||||
nsresult rv = mService->GetNodeId(aOrigin, aTopLevelOrigin,
|
||||
aInPrivateBrowsing, *aID);
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
GMPServiceParent::RecvGetGMPPluginVersionForAPI(const nsCString& aAPI,
|
||||
nsTArray<nsCString>&& aTags,
|
||||
bool* aHasPlugin,
|
||||
nsCString* aVersion)
|
||||
{
|
||||
nsRefPtr<GeckoMediaPluginServiceParent> service =
|
||||
GeckoMediaPluginServiceParent::GetSingleton();
|
||||
return service &&
|
||||
NS_SUCCEEDED(service->GetPluginVersionForAPI(aAPI, &aTags, aHasPlugin,
|
||||
*aVersion));
|
||||
}
|
||||
|
||||
class DeleteGMPServiceParent : public nsRunnable
|
||||
{
|
||||
public:
|
||||
explicit DeleteGMPServiceParent(GMPServiceParent* aToDelete)
|
||||
: mToDelete(aToDelete)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP Run()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsAutoPtr<GMPServiceParent> mToDelete;
|
||||
};
|
||||
|
||||
void
|
||||
GMPServiceParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
NS_DispatchToCurrentThread(new DeleteGMPServiceParent(this));
|
||||
}
|
||||
|
||||
class OpenPGMPServiceParent : public nsRunnable
|
||||
{
|
||||
public:
|
||||
OpenPGMPServiceParent(GMPServiceParent* aGMPServiceParent,
|
||||
mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherPid,
|
||||
bool* aResult)
|
||||
: mGMPServiceParent(aGMPServiceParent),
|
||||
mTransport(aTransport),
|
||||
mOtherPid(aOtherPid),
|
||||
mResult(aResult)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
*mResult = mGMPServiceParent->Open(mTransport, mOtherPid,
|
||||
XRE_GetIOMessageLoop(), ipc::ParentSide);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
GMPServiceParent* mGMPServiceParent;
|
||||
mozilla::ipc::Transport* mTransport;
|
||||
base::ProcessId mOtherPid;
|
||||
bool* mResult;
|
||||
};
|
||||
|
||||
/* static */
|
||||
PGMPServiceParent*
|
||||
GMPServiceParent::Create(Transport* aTransport, ProcessId aOtherPid)
|
||||
{
|
||||
nsRefPtr<GeckoMediaPluginServiceParent> gmp =
|
||||
GeckoMediaPluginServiceParent::GetSingleton();
|
||||
|
||||
nsAutoPtr<GMPServiceParent> serviceParent(new GMPServiceParent(gmp));
|
||||
|
||||
nsCOMPtr<nsIThread> gmpThread;
|
||||
nsresult rv = gmp->GetThread(getter_AddRefs(gmpThread));
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
bool ok;
|
||||
rv = gmpThread->Dispatch(new OpenPGMPServiceParent(serviceParent,
|
||||
aTransport,
|
||||
aOtherPid, &ok),
|
||||
NS_DISPATCH_SYNC);
|
||||
if (NS_FAILED(rv) || !ok) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return serviceParent.forget();
|
||||
}
|
||||
|
||||
} // namespace gmp
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#define GMPServiceParent_h_
|
||||
|
||||
#include "GMPService.h"
|
||||
#include "mozilla/gmp/PGMPServiceParent.h"
|
||||
#include "mozIGeckoMediaPluginChromeService.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
@ -53,6 +54,8 @@ public:
|
|||
int32_t AsyncShutdownTimeoutMs();
|
||||
|
||||
private:
|
||||
friend class GMPServiceParent;
|
||||
|
||||
virtual ~GeckoMediaPluginServiceParent();
|
||||
|
||||
void ClearStorage();
|
||||
|
@ -169,6 +172,39 @@ private:
|
|||
nsresult ReadSalt(nsIFile* aPath, nsACString& aOutData);
|
||||
bool MatchOrigin(nsIFile* aPath, const nsACString& aOrigin);
|
||||
|
||||
class GMPServiceParent final : public PGMPServiceParent
|
||||
{
|
||||
public:
|
||||
explicit GMPServiceParent(GeckoMediaPluginServiceParent* aService)
|
||||
: mService(aService)
|
||||
{
|
||||
}
|
||||
virtual ~GMPServiceParent();
|
||||
|
||||
virtual bool RecvLoadGMP(const nsCString& aNodeId,
|
||||
const nsCString& aApi,
|
||||
nsTArray<nsCString>&& aTags,
|
||||
nsTArray<ProcessId>&& aAlreadyBridgedTo,
|
||||
base::ProcessId* aID,
|
||||
nsCString* aDisplayName,
|
||||
nsCString* aPluginId) override;
|
||||
virtual bool RecvGetGMPNodeId(const nsString& aOrigin,
|
||||
const nsString& aTopLevelOrigin,
|
||||
const bool& aInPrivateBrowsing,
|
||||
nsCString* aID) override;
|
||||
static bool RecvGetGMPPluginVersionForAPI(const nsCString& aAPI,
|
||||
nsTArray<nsCString>&& aTags,
|
||||
bool* aHasPlugin,
|
||||
nsCString* aVersion);
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason aWhy);
|
||||
|
||||
static PGMPServiceParent* Create(Transport* aTransport, ProcessId aOtherPid);
|
||||
|
||||
private:
|
||||
nsRefPtr<GeckoMediaPluginServiceParent> mService;
|
||||
};
|
||||
|
||||
} // namespace gmp
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
* 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 protocol PGMP;
|
||||
include protocol PGMPService;
|
||||
include protocol PGMPVideoDecoder;
|
||||
include protocol PGMPVideoEncoder;
|
||||
include protocol PGMPDecryptor;
|
||||
|
@ -13,6 +15,8 @@ namespace gmp {
|
|||
|
||||
intr protocol PGMPContent
|
||||
{
|
||||
bridges PGMPService, PGMP;
|
||||
|
||||
manages PGMPAudioDecoder;
|
||||
manages PGMPDecryptor;
|
||||
manages PGMPVideoDecoder;
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/* -*- 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 protocol PGMP;
|
||||
|
||||
using base::ProcessId from "base/process.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace gmp {
|
||||
|
||||
sync protocol PGMPService
|
||||
{
|
||||
parent spawns PGMP as child;
|
||||
|
||||
parent:
|
||||
sync LoadGMP(nsCString nodeId, nsCString api, nsCString[] tags,
|
||||
ProcessId[] alreadyBridgedTo)
|
||||
returns (ProcessId id, nsCString displayName, nsCString pluginId);
|
||||
sync GetGMPNodeId(nsString origin, nsString topLevelOrigin,
|
||||
bool inPrivateBrowsing)
|
||||
returns (nsCString id);
|
||||
};
|
||||
|
||||
} // namespace gmp
|
||||
} // namespace mozilla
|
|
@ -49,6 +49,7 @@ EXPORTS += [
|
|||
'GMPProcessChild.h',
|
||||
'GMPProcessParent.h',
|
||||
'GMPService.h',
|
||||
'GMPServiceChild.h',
|
||||
'GMPServiceParent.h',
|
||||
'GMPSharedMemManager.h',
|
||||
'GMPStorageChild.h',
|
||||
|
@ -90,6 +91,7 @@ UNIFIED_SOURCES += [
|
|||
'GMPProcessChild.cpp',
|
||||
'GMPProcessParent.cpp',
|
||||
'GMPService.cpp',
|
||||
'GMPServiceChild.cpp',
|
||||
'GMPServiceParent.cpp',
|
||||
'GMPSharedMemManager.cpp',
|
||||
'GMPStorageChild.cpp',
|
||||
|
@ -117,6 +119,7 @@ IPDL_SOURCES += [
|
|||
'PGMPAudioDecoder.ipdl',
|
||||
'PGMPContent.ipdl',
|
||||
'PGMPDecryptor.ipdl',
|
||||
'PGMPService.ipdl',
|
||||
'PGMPStorage.ipdl',
|
||||
'PGMPTimer.ipdl',
|
||||
'PGMPVideoDecoder.ipdl',
|
||||
|
|
Загрузка…
Ссылка в новой задаче