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:
Peter Van der Beken 2015-02-10 11:49:03 +01:00
Родитель 8308cf3a1b
Коммит 166fcb5464
19 изменённых файлов: 787 добавлений и 6 удалений

Просмотреть файл

@ -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',