Merge m-c to b2g-inbound. a=merge

This commit is contained in:
Ryan VanderMeulen 2015-04-02 16:23:41 -04:00
Родитель 84d517d734 8cd202eaa0
Коммит 1755e88a07
178 изменённых файлов: 5425 добавлений и 2710 удалений

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

@ -1177,6 +1177,8 @@ pref("dom.ipc.plugins.enabled.x86_64", true);
pref("dom.ipc.plugins.enabled", true); pref("dom.ipc.plugins.enabled", true);
#endif #endif
pref("dom.ipc.shims.enabledWarnings", false);
// Start the browser in e10s mode // Start the browser in e10s mode
pref("browser.tabs.remote.autostart", false); pref("browser.tabs.remote.autostart", false);
pref("browser.tabs.remote.desktopbehavior", true); pref("browser.tabs.remote.desktopbehavior", true);

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

@ -1801,13 +1801,10 @@ nsSHistory::SetRootDocShell(nsIDocShell * aDocShell)
NS_IMETHODIMP NS_IMETHODIMP
nsSHistory::GetSHistoryEnumerator(nsISimpleEnumerator** aEnumerator) nsSHistory::GetSHistoryEnumerator(nsISimpleEnumerator** aEnumerator)
{ {
nsresult status = NS_OK;
NS_ENSURE_ARG_POINTER(aEnumerator); NS_ENSURE_ARG_POINTER(aEnumerator);
nsSHEnumerator * iterator = new nsSHEnumerator(this); nsRefPtr<nsSHEnumerator> iterator = new nsSHEnumerator(this);
if (iterator && NS_FAILED(status = CallQueryInterface(iterator, aEnumerator))) iterator.forget(aEnumerator);
delete iterator; return NS_OK;
return status;
} }

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

@ -46,7 +46,8 @@ MultipartFileImpl::GetInternalStream(nsIInputStream** aStream)
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
return CallQueryInterface(stream, aStream); stream.forget(aStream);
return NS_OK;
} }
already_AddRefed<FileImpl> already_AddRefed<FileImpl>

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

@ -2499,7 +2499,9 @@ nsFrameLoader::GetMessageManager(nsIMessageSender** aManager)
{ {
EnsureMessageManager(); EnsureMessageManager();
if (mMessageManager) { if (mMessageManager) {
CallQueryInterface(mMessageManager, aManager); nsRefPtr<nsFrameMessageManager> mm(mMessageManager);
mm.forget(aManager);
return NS_OK;
} }
return NS_OK; return NS_OK;
} }

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

@ -1490,11 +1490,12 @@ NS_NewGlobalMessageManager(nsIMessageBroadcaster** aResult)
{ {
NS_ENSURE_TRUE(XRE_GetProcessType() == GeckoProcessType_Default, NS_ENSURE_TRUE(XRE_GetProcessType() == GeckoProcessType_Default,
NS_ERROR_NOT_AVAILABLE); NS_ERROR_NOT_AVAILABLE);
nsFrameMessageManager* mm = new nsFrameMessageManager(nullptr, nsRefPtr<nsFrameMessageManager> mm = new nsFrameMessageManager(nullptr,
nullptr, nullptr,
MM_CHROME | MM_GLOBAL | MM_BROADCASTER); MM_CHROME | MM_GLOBAL | MM_BROADCASTER);
RegisterStrongMemoryReporter(new MessageManagerReporter()); RegisterStrongMemoryReporter(new MessageManagerReporter());
return CallQueryInterface(mm, aResult); mm.forget(aResult);
return NS_OK;
} }
nsDataHashtable<nsStringHashKey, nsMessageManagerScriptHolder*>* nsDataHashtable<nsStringHashKey, nsMessageManagerScriptHolder*>*
@ -2008,7 +2009,8 @@ NS_NewParentProcessMessageManager(nsIMessageBroadcaster** aResult)
MM_CHROME | MM_PROCESSMANAGER | MM_BROADCASTER); MM_CHROME | MM_PROCESSMANAGER | MM_BROADCASTER);
nsFrameMessageManager::sParentProcessManager = mm; nsFrameMessageManager::sParentProcessManager = mm;
nsFrameMessageManager::NewProcessMessageManager(false); // Create same process message manager. nsFrameMessageManager::NewProcessMessageManager(false); // Create same process message manager.
return CallQueryInterface(mm, aResult); mm.forget(aResult);
return NS_OK;
} }
@ -2055,9 +2057,10 @@ NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult)
nullptr, nullptr,
MM_PROCESSMANAGER | MM_OWNSCALLBACK); MM_PROCESSMANAGER | MM_OWNSCALLBACK);
nsFrameMessageManager::SetChildProcessManager(mm); nsFrameMessageManager::SetChildProcessManager(mm);
ProcessGlobal* global = new ProcessGlobal(mm); nsRefPtr<ProcessGlobal> global = new ProcessGlobal(mm);
NS_ENSURE_TRUE(global->Init(), NS_ERROR_UNEXPECTED); NS_ENSURE_TRUE(global->Init(), NS_ERROR_UNEXPECTED);
return CallQueryInterface(global, aResult); global.forget(aResult);
return NS_OK;
} }

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

@ -40,14 +40,12 @@
using namespace mozilla::dom; using namespace mozilla::dom;
nsresult NS_NewHTMLContentSerializer(nsIContentSerializer** aSerializer) nsresult
NS_NewHTMLContentSerializer(nsIContentSerializer** aSerializer)
{ {
nsHTMLContentSerializer* it = new nsHTMLContentSerializer(); nsRefPtr<nsHTMLContentSerializer> it = new nsHTMLContentSerializer();
if (!it) { it.forget(aSerializer);
return NS_ERROR_OUT_OF_MEMORY; return NS_OK;
}
return CallQueryInterface(it, aSerializer);
} }
nsHTMLContentSerializer::nsHTMLContentSerializer() nsHTMLContentSerializer::nsHTMLContentSerializer()

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

@ -54,14 +54,12 @@ static int32_t GetUnicharStringWidth(const char16_t* pwcs, int32_t n);
static const uint32_t TagStackSize = 500; static const uint32_t TagStackSize = 500;
static const uint32_t OLStackSize = 100; static const uint32_t OLStackSize = 100;
nsresult NS_NewPlainTextSerializer(nsIContentSerializer** aSerializer) nsresult
NS_NewPlainTextSerializer(nsIContentSerializer** aSerializer)
{ {
nsPlainTextSerializer* it = new nsPlainTextSerializer(); nsRefPtr<nsPlainTextSerializer> it = new nsPlainTextSerializer();
if (!it) { it.forget(aSerializer);
return NS_ERROR_OUT_OF_MEMORY; return NS_OK;
}
return CallQueryInterface(it, aSerializer);
} }
nsPlainTextSerializer::nsPlainTextSerializer() nsPlainTextSerializer::nsPlainTextSerializer()

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

@ -40,14 +40,12 @@ static const int32_t kLongLineLen = 128;
#define kXMLNS "xmlns" #define kXMLNS "xmlns"
nsresult NS_NewXHTMLContentSerializer(nsIContentSerializer** aSerializer) nsresult
NS_NewXHTMLContentSerializer(nsIContentSerializer** aSerializer)
{ {
nsXHTMLContentSerializer* it = new nsXHTMLContentSerializer(); nsRefPtr<nsXHTMLContentSerializer> it = new nsXHTMLContentSerializer();
if (!it) { it.forget(aSerializer);
return NS_ERROR_OUT_OF_MEMORY; return NS_OK;
}
return CallQueryInterface(it, aSerializer);
} }
nsXHTMLContentSerializer::nsXHTMLContentSerializer() nsXHTMLContentSerializer::nsXHTMLContentSerializer()

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

@ -43,14 +43,12 @@ using namespace mozilla::dom;
#define INDENT_STRING " " #define INDENT_STRING " "
#define INDENT_STRING_LENGTH 2 #define INDENT_STRING_LENGTH 2
nsresult NS_NewXMLContentSerializer(nsIContentSerializer** aSerializer) nsresult
NS_NewXMLContentSerializer(nsIContentSerializer** aSerializer)
{ {
nsXMLContentSerializer* it = new nsXMLContentSerializer(); nsRefPtr<nsXMLContentSerializer> it = new nsXMLContentSerializer();
if (!it) { it.forget(aSerializer);
return NS_ERROR_OUT_OF_MEMORY; return NS_OK;
}
return CallQueryInterface(it, aSerializer);
} }
nsXMLContentSerializer::nsXMLContentSerializer() nsXMLContentSerializer::nsXMLContentSerializer()

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

@ -23,6 +23,7 @@ skip-if = debug == false
[test_bug963382.html] [test_bug963382.html]
skip-if = debug == false skip-if = debug == false
[test_bug1041646.html] [test_bug1041646.html]
[test_bug1123875.html]
[test_barewordGetsWindow.html] [test_barewordGetsWindow.html]
[test_callback_default_thisval.html] [test_callback_default_thisval.html]
[test_cloneAndImportNode.html] [test_cloneAndImportNode.html]

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

@ -0,0 +1,14 @@
<!doctype html>
<meta charset=utf-8>
<title>Test for Bug 1123875</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<div id=log></div>
<script>
test(() => {
assert_throws(new TypeError, () => {
"use strict";
document.childNodes.length = 0;
});
}, "setting a readonly attribute on a proxy in strict mode should throw a TypeError");
</script>

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

@ -1910,7 +1910,7 @@ HTMLInputElement::GetList(nsIDOMHTMLElement** aValue)
return NS_OK; return NS_OK;
} }
CallQueryInterface(element, aValue); element.forget(aValue);
return NS_OK; return NS_OK;
} }

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

@ -178,6 +178,7 @@
#include "mozilla/dom/voicemail/VoicemailIPCService.h" #include "mozilla/dom/voicemail/VoicemailIPCService.h"
#include "mozilla/net/NeckoMessageUtils.h" #include "mozilla/net/NeckoMessageUtils.h"
#include "mozilla/RemoteSpellCheckEngineChild.h" #include "mozilla/RemoteSpellCheckEngineChild.h"
#include "GMPServiceChild.h"
using namespace mozilla; using namespace mozilla;
using namespace mozilla::docshell; using namespace mozilla::docshell;
@ -191,6 +192,7 @@ using namespace mozilla::dom::mobilemessage;
using namespace mozilla::dom::telephony; using namespace mozilla::dom::telephony;
using namespace mozilla::dom::voicemail; using namespace mozilla::dom::voicemail;
using namespace mozilla::embedding; using namespace mozilla::embedding;
using namespace mozilla::gmp;
using namespace mozilla::hal_sandbox; using namespace mozilla::hal_sandbox;
using namespace mozilla::ipc; using namespace mozilla::ipc;
using namespace mozilla::layers; using namespace mozilla::layers;
@ -1036,6 +1038,13 @@ ContentChild::AllocPContentBridgeParent(mozilla::ipc::Transport* aTransport,
return mLastBridge; return mLastBridge;
} }
PGMPServiceChild*
ContentChild::AllocPGMPServiceChild(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess)
{
return GMPServiceChild::Create(aTransport, aOtherProcess);
}
PCompositorChild* PCompositorChild*
ContentChild::AllocPCompositorChild(mozilla::ipc::Transport* aTransport, ContentChild::AllocPCompositorChild(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess) base::ProcessId aOtherProcess)

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

@ -115,6 +115,10 @@ public:
AllocPContentBridgeChild(mozilla::ipc::Transport* transport, AllocPContentBridgeChild(mozilla::ipc::Transport* transport,
base::ProcessId otherProcess) override; base::ProcessId otherProcess) override;
PGMPServiceChild*
AllocPGMPServiceChild(mozilla::ipc::Transport* transport,
base::ProcessId otherProcess) override;
PCompositorChild* PCompositorChild*
AllocPCompositorChild(mozilla::ipc::Transport* aTransport, AllocPCompositorChild(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess) override; base::ProcessId aOtherProcess) override;

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

@ -28,6 +28,7 @@
#include "AudioChannelService.h" #include "AudioChannelService.h"
#include "BlobParent.h" #include "BlobParent.h"
#include "CrashReporterParent.h" #include "CrashReporterParent.h"
#include "GMPServiceParent.h"
#include "IHistory.h" #include "IHistory.h"
#include "mozIApplication.h" #include "mozIApplication.h"
#ifdef ACCESSIBILITY #ifdef ACCESSIBILITY
@ -233,6 +234,7 @@ using namespace mozilla::dom::mobilemessage;
using namespace mozilla::dom::telephony; using namespace mozilla::dom::telephony;
using namespace mozilla::dom::voicemail; using namespace mozilla::dom::voicemail;
using namespace mozilla::embedding; using namespace mozilla::embedding;
using namespace mozilla::gmp;
using namespace mozilla::hal; using namespace mozilla::hal;
using namespace mozilla::ipc; using namespace mozilla::ipc;
using namespace mozilla::layers; using namespace mozilla::layers;
@ -981,6 +983,23 @@ static nsIDocShell* GetOpenerDocShellHelper(Element* aFrameElement)
return docShell; 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 bool
ContentParent::RecvLoadPlugin(const uint32_t& aPluginId, nsresult* aRv) ContentParent::RecvLoadPlugin(const uint32_t& aPluginId, nsresult* aRv)
{ {
@ -3062,6 +3081,13 @@ ContentParent::RecvPDocAccessibleConstructor(PDocAccessibleParent* aDoc, PDocAcc
return true; return true;
} }
PGMPServiceParent*
ContentParent::AllocPGMPServiceParent(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess)
{
return GMPServiceParent::Create(aTransport, aOtherProcess);
}
PCompositorParent* PCompositorParent*
ContentParent::AllocPCompositorParent(mozilla::ipc::Transport* aTransport, ContentParent::AllocPCompositorParent(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess) base::ProcessId aOtherProcess)

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

@ -153,6 +153,12 @@ public:
TabId* aTabId) override; TabId* aTabId) override;
virtual bool RecvBridgeToChildProcess(const ContentParentId& aCpId) 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 RecvLoadPlugin(const uint32_t& aPluginId, nsresult* aRv) override;
virtual bool RecvConnectPluginBridge(const uint32_t& aPluginId, nsresult* aRv) override; virtual bool RecvConnectPluginBridge(const uint32_t& aPluginId, nsresult* aRv) override;
virtual bool RecvFindPlugins(const uint32_t& aPluginEpoch, virtual bool RecvFindPlugins(const uint32_t& aPluginEpoch,
@ -488,6 +494,9 @@ private:
static void ForceKillTimerCallback(nsITimer* aTimer, void* aClosure); static void ForceKillTimerCallback(nsITimer* aTimer, void* aClosure);
PGMPServiceParent*
AllocPGMPServiceParent(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess) override;
PCompositorParent* PCompositorParent*
AllocPCompositorParent(mozilla::ipc::Transport* aTransport, AllocPCompositorParent(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess) override; base::ProcessId aOtherProcess) override;

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

@ -27,7 +27,15 @@ include protocol PImageBridge;
include protocol PMemoryReportRequest; include protocol PMemoryReportRequest;
include protocol PMobileConnection; include protocol PMobileConnection;
include protocol PNecko; 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 PPluginModule;
include protocol PGMP;
include protocol PPrinting; include protocol PPrinting;
include protocol POfflineCacheUpdate; include protocol POfflineCacheUpdate;
include protocol PScreenManager; include protocol PScreenManager;
@ -364,6 +372,7 @@ prio(normal upto urgent) sync protocol PContent
parent opens PProcessHangMonitor; parent opens PProcessHangMonitor;
parent opens PSharedBufferManager; parent opens PSharedBufferManager;
parent opens PImageBridge; parent opens PImageBridge;
parent opens PGMPService;
child opens PBackground; child opens PBackground;
manages PAsmJSCacheEntry; manages PAsmJSCacheEntry;
@ -608,6 +617,10 @@ parent:
returns (ContentParentId cpId, bool isForApp, bool isForBrowser, TabId tabId); returns (ContentParentId cpId, bool isForApp, bool isForBrowser, TabId tabId);
sync BridgeToChildProcess(ContentParentId cpId); 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 * This call connects the content process to a plugin process. While this
* call runs, a new PluginModuleParent will be created in the ContentChild * call runs, a new PluginModuleParent will be created in the ContentChild

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

@ -25,6 +25,7 @@ CDMProxy::CDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem)
, mKeySystem(aKeySystem) , mKeySystem(aKeySystem)
, mCDM(nullptr) , mCDM(nullptr)
, mDecryptionJobCount(0) , mDecryptionJobCount(0)
, mShutdownCalled(false)
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
MOZ_COUNT_CTOR(CDMProxy); MOZ_COUNT_CTOR(CDMProxy);
@ -70,7 +71,7 @@ CDMProxy::Init(PromiseId aPromiseId,
nsCOMPtr<nsIRunnable> task( nsCOMPtr<nsIRunnable> task(
NS_NewRunnableMethodWithArg<nsAutoPtr<InitData>>(this, NS_NewRunnableMethodWithArg<nsAutoPtr<InitData>>(this,
&CDMProxy::gmp_Init, &CDMProxy::gmp_Init,
data)); Move(data)));
mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL); mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
} }
@ -83,7 +84,69 @@ CDMProxy::IsOnGMPThread()
#endif #endif
void void
CDMProxy::gmp_Init(nsAutoPtr<InitData> aData) CDMProxy::gmp_InitDone(GMPDecryptorProxy* aCDM, nsAutoPtr<InitData>&& aData)
{
EME_LOG("CDMProxy::gmp_InitDone");
if (!aCDM || mShutdownCalled) {
if (aCDM) {
aCDM->Close();
}
RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
mCDM = aCDM;
mCallback = new CDMCallbackProxy(this);
mCDM->Init(mCallback);
nsCOMPtr<nsIRunnable> task(
NS_NewRunnableMethodWithArg<uint32_t>(this,
&CDMProxy::OnCDMCreated,
aData->mPromiseId));
NS_DispatchToMainThread(task);
}
class gmp_InitDoneCallback : public GetGMPDecryptorCallback
{
public:
gmp_InitDoneCallback(CDMProxy* aCDMProxy,
nsAutoPtr<CDMProxy::InitData>&& aData)
: mCDMProxy(aCDMProxy),
mData(Move(aData))
{
}
void Done(GMPDecryptorProxy* aCDM)
{
mCDMProxy->gmp_InitDone(aCDM, Move(mData));
}
private:
nsRefPtr<CDMProxy> mCDMProxy;
nsAutoPtr<CDMProxy::InitData> mData;
};
class gmp_InitGetGMPDecryptorCallback : public GetNodeIdCallback
{
public:
gmp_InitGetGMPDecryptorCallback(CDMProxy* aCDMProxy,
nsAutoPtr<CDMProxy::InitData>&& aData)
: mCDMProxy(aCDMProxy),
mData(aData)
{
}
void Done(nsresult aResult, const nsACString& aNodeId)
{
mCDMProxy->gmp_InitGetGMPDecryptor(aResult, aNodeId, Move(mData));
}
private:
nsRefPtr<CDMProxy> mCDMProxy;
nsAutoPtr<CDMProxy::InitData> mData;
};
void
CDMProxy::gmp_Init(nsAutoPtr<InitData>&& aData)
{ {
MOZ_ASSERT(IsOnGMPThread()); MOZ_ASSERT(IsOnGMPThread());
@ -94,13 +157,38 @@ CDMProxy::gmp_Init(nsAutoPtr<InitData> aData)
return; return;
} }
nsresult rv = mps->GetNodeId(aData->mOrigin, // Make a copy before we transfer ownership of aData to the
aData->mTopLevelOrigin, // gmp_InitGetGMPDecryptorCallback.
aData->mInPrivateBrowsing, InitData data(*aData);
mNodeId); UniquePtr<GetNodeIdCallback> callback(
MOZ_ASSERT(!GetNodeId().IsEmpty()); new gmp_InitGetGMPDecryptorCallback(this, Move(aData)));
nsresult rv = mps->GetNodeId(data.mOrigin,
data.mTopLevelOrigin,
data.mInPrivateBrowsing,
Move(callback));
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR); RejectPromise(data.mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
}
}
void
CDMProxy::gmp_InitGetGMPDecryptor(nsresult aResult,
const nsACString& aNodeId,
nsAutoPtr<InitData>&& aData)
{
uint32_t promiseID = aData->mPromiseId;
if (NS_FAILED(aResult)) {
RejectPromise(promiseID, NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
mNodeId = aNodeId;
MOZ_ASSERT(!GetNodeId().IsEmpty());
nsCOMPtr<mozIGeckoMediaPluginService> mps =
do_GetService("@mozilla.org/gecko-media-plugin-service;1");
if (!mps) {
RejectPromise(promiseID, NS_ERROR_DOM_INVALID_STATE_ERR);
return; return;
} }
@ -112,17 +200,12 @@ CDMProxy::gmp_Init(nsAutoPtr<InitData> aData)
nsTArray<nsCString> tags; nsTArray<nsCString> tags;
tags.AppendElement(NS_ConvertUTF16toUTF8(mKeySystem)); tags.AppendElement(NS_ConvertUTF16toUTF8(mKeySystem));
rv = mps->GetGMPDecryptor(&tags, GetNodeId(), &mCDM);
if (NS_FAILED(rv) || !mCDM) { UniquePtr<GetGMPDecryptorCallback> callback(new gmp_InitDoneCallback(this,
RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR); Move(aData)));
} else { nsresult rv = mps->GetGMPDecryptor(&tags, GetNodeId(), Move(callback));
mCallback = new CDMCallbackProxy(this); if (NS_FAILED(rv)) {
mCDM->Init(mCallback); RejectPromise(promiseID, NS_ERROR_DOM_INVALID_STATE_ERR);
nsCOMPtr<nsIRunnable> task(
NS_NewRunnableMethodWithArg<uint32_t>(this,
&CDMProxy::OnCDMCreated,
aData->mPromiseId));
NS_DispatchToMainThread(task);
} }
} }
@ -341,6 +424,8 @@ CDMProxy::gmp_Shutdown()
{ {
MOZ_ASSERT(IsOnGMPThread()); MOZ_ASSERT(IsOnGMPThread());
mShutdownCalled = true;
// Abort any pending decrypt jobs, to awaken any clients waiting on a job. // Abort any pending decrypt jobs, to awaken any clients waiting on a job.
for (size_t i = 0; i < mDecryptionJobs.Length(); i++) { for (size_t i = 0; i < mDecryptionJobs.Length(); i++) {
DecryptJob* job = mDecryptionJobs[i]; DecryptJob* job = mDecryptionJobs[i];

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

@ -174,6 +174,8 @@ public:
#endif #endif
private: private:
friend class gmp_InitDoneCallback;
friend class gmp_InitGetGMPDecryptorCallback;
struct InitData { struct InitData {
uint32_t mPromiseId; uint32_t mPromiseId;
@ -183,7 +185,11 @@ private:
}; };
// GMP thread only. // GMP thread only.
void gmp_Init(nsAutoPtr<InitData> aData); void gmp_Init(nsAutoPtr<InitData>&& aData);
void gmp_InitDone(GMPDecryptorProxy* aCDM, nsAutoPtr<InitData>&& aData);
void gmp_InitGetGMPDecryptor(nsresult aResult,
const nsACString& aNodeId,
nsAutoPtr<InitData>&& aData);
// GMP thread only. // GMP thread only.
void gmp_Shutdown(); void gmp_Shutdown();
@ -320,6 +326,10 @@ private:
// from it. // from it.
// GMP thread only. // GMP thread only.
uint32_t mDecryptionJobCount; uint32_t mDecryptionJobCount;
// True if CDMProxy::gmp_Shutdown was called.
// GMP thread only.
bool mShutdownCalled;
}; };

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

@ -93,25 +93,34 @@ HaveGMPFor(mozIGeckoMediaPluginService* aGMPService,
static MediaKeySystemStatus static MediaKeySystemStatus
EnsureMinCDMVersion(mozIGeckoMediaPluginService* aGMPService, EnsureMinCDMVersion(mozIGeckoMediaPluginService* aGMPService,
const nsAString& aKeySystem, const nsAString& aKeySystem,
int32_t aMinCdmVersion) int32_t aMinCdmVersion,
bool aCheckForV6=false)
{ {
if (aMinCdmVersion == NO_CDM_VERSION) {
return MediaKeySystemStatus::Available;
}
nsTArray<nsCString> tags; nsTArray<nsCString> tags;
tags.AppendElement(NS_ConvertUTF16toUTF8(aKeySystem)); tags.AppendElement(NS_ConvertUTF16toUTF8(aKeySystem));
bool hasPlugin;
nsAutoCString versionStr; nsAutoCString versionStr;
if (NS_FAILED(aGMPService->GetPluginVersionForAPI(NS_LITERAL_CSTRING(GMP_API_DECRYPTOR), if (NS_FAILED(aGMPService->GetPluginVersionForAPI(NS_LITERAL_CSTRING(GMP_API_DECRYPTOR),
&tags, &tags,
versionStr)) && &hasPlugin,
versionStr)) ||
// XXX to be removed later in bug 1147692 // XXX to be removed later in bug 1147692
NS_FAILED(aGMPService->GetPluginVersionForAPI(NS_LITERAL_CSTRING(GMP_API_DECRYPTOR_COMPAT), (aCheckForV6 && !hasPlugin &&
&tags, NS_FAILED(aGMPService->GetPluginVersionForAPI(NS_LITERAL_CSTRING(GMP_API_DECRYPTOR_COMPAT),
versionStr))) { &tags,
&hasPlugin,
versionStr)))) {
return MediaKeySystemStatus::Error; return MediaKeySystemStatus::Error;
} }
if (!hasPlugin) {
return MediaKeySystemStatus::Cdm_not_installed;
}
if (aMinCdmVersion == NO_CDM_VERSION) {
return MediaKeySystemStatus::Available;
}
nsresult rv; nsresult rv;
int32_t version = versionStr.ToInteger(&rv); int32_t version = versionStr.ToInteger(&rv);
if (NS_FAILED(rv) || version < 0 || aMinCdmVersion > version) { if (NS_FAILED(rv) || version < 0 || aMinCdmVersion > version) {
@ -137,11 +146,6 @@ MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem,
if (!Preferences::GetBool("media.eme.clearkey.enabled", true)) { if (!Preferences::GetBool("media.eme.clearkey.enabled", true)) {
return MediaKeySystemStatus::Cdm_disabled; return MediaKeySystemStatus::Cdm_disabled;
} }
if (!HaveGMPFor(mps,
NS_LITERAL_CSTRING("org.w3.clearkey"),
NS_LITERAL_CSTRING(GMP_API_DECRYPTOR))) {
return MediaKeySystemStatus::Cdm_not_installed;
}
return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion); return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion);
} }
@ -155,16 +159,7 @@ MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem,
if (!Preferences::GetBool("media.gmp-eme-adobe.enabled", false)) { if (!Preferences::GetBool("media.gmp-eme-adobe.enabled", false)) {
return MediaKeySystemStatus::Cdm_disabled; return MediaKeySystemStatus::Cdm_disabled;
} }
if (!HaveGMPFor(mps, return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion, true);
NS_ConvertUTF16toUTF8(aKeySystem),
NS_LITERAL_CSTRING(GMP_API_DECRYPTOR)) &&
// XXX to be removed later in bug 1147692
!HaveGMPFor(mps,
NS_ConvertUTF16toUTF8(aKeySystem),
NS_LITERAL_CSTRING(GMP_API_DECRYPTOR_COMPAT))) {
return MediaKeySystemStatus::Cdm_not_installed;
}
return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion);
} }
#endif #endif

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

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GMPAudioDecoder.h" #include "GMPAudioDecoder.h"
#include "nsServiceManagerUtils.h"
namespace mozilla { namespace mozilla {
@ -132,6 +133,39 @@ GMPAudioDecoder::GetNodeId()
return NS_LITERAL_CSTRING(""); return NS_LITERAL_CSTRING("");
} }
void
GMPAudioDecoder::GetGMPAPI(GMPInitDoneRunnable* aInitDone)
{
MOZ_ASSERT(IsOnGMPThread());
nsTArray<nsCString> tags;
InitTags(tags);
UniquePtr<GetGMPAudioDecoderCallback> callback(
new GMPInitDoneCallback(this, aInitDone));
if (NS_FAILED(mMPS->GetGMPAudioDecoder(&tags, GetNodeId(), Move(callback)))) {
aInitDone->Dispatch();
}
}
void
GMPAudioDecoder::GMPInitDone(GMPAudioDecoderProxy* aGMP)
{
MOZ_ASSERT(aGMP);
nsTArray<uint8_t> codecSpecific;
codecSpecific.AppendElements(mConfig.audio_specific_config->Elements(),
mConfig.audio_specific_config->Length());
nsresult rv = aGMP->InitDecode(kGMPAudioCodecAAC,
mConfig.channel_count,
mConfig.bits_per_sample,
mConfig.samples_per_second,
codecSpecific,
mAdapter);
if (NS_SUCCEEDED(rv)) {
mGMP = aGMP;
}
}
nsresult nsresult
GMPAudioDecoder::Init() GMPAudioDecoder::Init()
{ {
@ -140,25 +174,20 @@ GMPAudioDecoder::Init()
mMPS = do_GetService("@mozilla.org/gecko-media-plugin-service;1"); mMPS = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
MOZ_ASSERT(mMPS); MOZ_ASSERT(mMPS);
nsTArray<nsCString> tags; nsCOMPtr<nsIThread> gmpThread = NS_GetCurrentThread();
InitTags(tags);
nsresult rv = mMPS->GetGMPAudioDecoder(&tags, GetNodeId(), &mGMP);
NS_ENSURE_SUCCESS(rv, rv);
MOZ_ASSERT(mGMP);
nsTArray<uint8_t> codecSpecific; nsRefPtr<GMPInitDoneRunnable> initDone(new GMPInitDoneRunnable());
codecSpecific.AppendElements(mConfig.audio_specific_config->Elements(), gmpThread->Dispatch(
mConfig.audio_specific_config->Length()); NS_NewRunnableMethodWithArg<GMPInitDoneRunnable*>(this,
&GMPAudioDecoder::GetGMPAPI,
initDone),
NS_DISPATCH_NORMAL);
rv = mGMP->InitDecode(kGMPAudioCodecAAC, while (!initDone->IsDone()) {
mConfig.channel_count, NS_ProcessNextEvent(gmpThread, true);
mConfig.bits_per_sample, }
mConfig.samples_per_second,
codecSpecific,
mAdapter);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK; return mGMP ? NS_OK : NS_ERROR_FAILURE;
} }
nsresult nsresult

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

@ -80,6 +80,63 @@ protected:
virtual nsCString GetNodeId(); virtual nsCString GetNodeId();
private: private:
class GMPInitDoneRunnable : public nsRunnable
{
public:
GMPInitDoneRunnable()
: mInitDone(false),
mThread(do_GetCurrentThread())
{
}
NS_IMETHOD Run()
{
mInitDone = true;
return NS_OK;
}
void Dispatch()
{
mThread->Dispatch(this, NS_DISPATCH_NORMAL);
}
bool IsDone()
{
MOZ_ASSERT(nsCOMPtr<nsIThread>(do_GetCurrentThread()) == mThread);
return mInitDone;
}
private:
bool mInitDone;
nsCOMPtr<nsIThread> mThread;
};
void GetGMPAPI(GMPInitDoneRunnable* aInitDone);
class GMPInitDoneCallback : public GetGMPAudioDecoderCallback
{
public:
GMPInitDoneCallback(GMPAudioDecoder* aDecoder,
GMPInitDoneRunnable* aGMPInitDone)
: mDecoder(aDecoder)
, mGMPInitDone(aGMPInitDone)
{
}
virtual void Done(GMPAudioDecoderProxy* aGMP)
{
if (aGMP) {
mDecoder->GMPInitDone(aGMP);
}
mGMPInitDone->Dispatch();
}
private:
nsRefPtr<GMPAudioDecoder> mDecoder;
nsRefPtr<GMPInitDoneRunnable> mGMPInitDone;
};
void GMPInitDone(GMPAudioDecoderProxy* aGMP);
const mp4_demuxer::AudioDecoderConfig& mConfig; const mp4_demuxer::AudioDecoderConfig& mConfig;
MediaDataDecoderCallbackProxy* mCallback; MediaDataDecoderCallbackProxy* mCallback;
nsCOMPtr<mozIGeckoMediaPluginService> mMPS; nsCOMPtr<mozIGeckoMediaPluginService> mMPS;

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

@ -157,29 +157,24 @@ GMPVideoDecoder::CreateFrame(mp4_demuxer::MP4Sample* aSample)
return frame; return frame;
} }
nsresult void
GMPVideoDecoder::Init() GMPVideoDecoder::GetGMPAPI(GMPInitDoneRunnable* aInitDone)
{ {
MOZ_ASSERT(IsOnGMPThread()); MOZ_ASSERT(IsOnGMPThread());
mMPS = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
MOZ_ASSERT(mMPS);
nsTArray<nsCString> tags; nsTArray<nsCString> tags;
InitTags(tags); InitTags(tags);
nsresult rv = mMPS->GetGMPVideoDecoder(&tags, GetNodeId(), &mHost, &mGMP); UniquePtr<GetGMPVideoDecoderCallback> callback(
NS_ENSURE_SUCCESS(rv, rv); new GMPInitDoneCallback(this, aInitDone));
MOZ_ASSERT(mHost && mGMP); if (NS_FAILED(mMPS->GetGMPVideoDecoder(&tags, GetNodeId(), Move(callback)))) {
aInitDone->Dispatch();
}
}
// GMP implementations have interpreted the meaning of GMP_BufferLength32 void
// differently. The OpenH264 GMP expects GMP_BufferLength32 to behave as GMPVideoDecoder::GMPInitDone(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost)
// specified in the GMP API, where each buffer is prefixed by a 32-bit {
// host-endian buffer length that includes the size of the buffer length MOZ_ASSERT(aHost && aGMP);
// field. Other existing GMPs currently expect GMP_BufferLength32 (when
// combined with kGMPVideoCodecH264) to mean "like AVCC but restricted to
// 4-byte NAL lengths" (i.e. buffer lengths are specified in big-endian
// and do not include the length of the buffer length field.
mConvertNALUnitLengths = mGMP->GetDisplayName().EqualsLiteral("gmpopenh264");
GMPVideoCodec codec; GMPVideoCodec codec;
memset(&codec, 0, sizeof(codec)); memset(&codec, 0, sizeof(codec));
@ -195,13 +190,48 @@ GMPVideoDecoder::Init()
codecSpecific.AppendElements(mConfig.extra_data->Elements(), codecSpecific.AppendElements(mConfig.extra_data->Elements(),
mConfig.extra_data->Length()); mConfig.extra_data->Length());
rv = mGMP->InitDecode(codec, nsresult rv = aGMP->InitDecode(codec,
codecSpecific, codecSpecific,
mAdapter, mAdapter,
PR_GetNumberOfProcessors()); PR_GetNumberOfProcessors());
NS_ENSURE_SUCCESS(rv, rv); if (NS_SUCCEEDED(rv)) {
mGMP = aGMP;
mHost = aHost;
return NS_OK; // GMP implementations have interpreted the meaning of GMP_BufferLength32
// differently. The OpenH264 GMP expects GMP_BufferLength32 to behave as
// specified in the GMP API, where each buffer is prefixed by a 32-bit
// host-endian buffer length that includes the size of the buffer length
// field. Other existing GMPs currently expect GMP_BufferLength32 (when
// combined with kGMPVideoCodecH264) to mean "like AVCC but restricted to
// 4-byte NAL lengths" (i.e. buffer lengths are specified in big-endian
// and do not include the length of the buffer length field.
mConvertNALUnitLengths = mGMP->GetDisplayName().EqualsLiteral("gmpopenh264");
}
}
nsresult
GMPVideoDecoder::Init()
{
MOZ_ASSERT(IsOnGMPThread());
mMPS = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
MOZ_ASSERT(mMPS);
nsCOMPtr<nsIThread> gmpThread = NS_GetCurrentThread();
nsRefPtr<GMPInitDoneRunnable> initDone(new GMPInitDoneRunnable());
gmpThread->Dispatch(
NS_NewRunnableMethodWithArg<GMPInitDoneRunnable*>(this,
&GMPVideoDecoder::GetGMPAPI,
initDone),
NS_DISPATCH_NORMAL);
while (!initDone->IsDone()) {
NS_ProcessNextEvent(gmpThread, true);
}
return mGMP ? NS_OK : NS_ERROR_FAILURE;
} }
nsresult nsresult

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

@ -96,6 +96,63 @@ protected:
virtual GMPUnique<GMPVideoEncodedFrame>::Ptr CreateFrame(mp4_demuxer::MP4Sample* aSample); virtual GMPUnique<GMPVideoEncodedFrame>::Ptr CreateFrame(mp4_demuxer::MP4Sample* aSample);
private: private:
class GMPInitDoneRunnable : public nsRunnable
{
public:
GMPInitDoneRunnable()
: mInitDone(false),
mThread(do_GetCurrentThread())
{
}
NS_IMETHOD Run()
{
mInitDone = true;
return NS_OK;
}
void Dispatch()
{
mThread->Dispatch(this, NS_DISPATCH_NORMAL);
}
bool IsDone()
{
MOZ_ASSERT(nsCOMPtr<nsIThread>(do_GetCurrentThread()) == mThread);
return mInitDone;
}
private:
bool mInitDone;
nsCOMPtr<nsIThread> mThread;
};
void GetGMPAPI(GMPInitDoneRunnable* aInitDone);
class GMPInitDoneCallback : public GetGMPVideoDecoderCallback
{
public:
GMPInitDoneCallback(GMPVideoDecoder* aDecoder,
GMPInitDoneRunnable* aGMPInitDone)
: mDecoder(aDecoder)
, mGMPInitDone(aGMPInitDone)
{
}
virtual void Done(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost)
{
if (aGMP) {
mDecoder->GMPInitDone(aGMP, aHost);
}
mGMPInitDone->Dispatch();
}
private:
nsRefPtr<GMPVideoDecoder> mDecoder;
nsRefPtr<GMPInitDoneRunnable> mGMPInitDone;
};
void GMPInitDone(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost);
const mp4_demuxer::VideoDecoderConfig& mConfig; const mp4_demuxer::VideoDecoderConfig& mConfig;
MediaDataDecoderCallbackProxy* mCallback; MediaDataDecoderCallbackProxy* mCallback;
nsCOMPtr<mozIGeckoMediaPluginService> mMPS; nsCOMPtr<mozIGeckoMediaPluginService> mMPS;

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

@ -14,6 +14,7 @@
#include "WMFMediaDataDecoder.h" #include "WMFMediaDataDecoder.h"
#include "nsIWindowsRegKey.h" #include "nsIWindowsRegKey.h"
#include "nsComponentManagerUtils.h" #include "nsComponentManagerUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsIGfxInfo.h" #include "nsIGfxInfo.h"
#include "GfxDriverInfo.h" #include "GfxDriverInfo.h"
#include "gfxWindowsPlatform.h" #include "gfxWindowsPlatform.h"

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

@ -4,7 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GMPAudioDecoderChild.h" #include "GMPAudioDecoderChild.h"
#include "GMPChild.h" #include "GMPContentChild.h"
#include "GMPAudioHost.h" #include "GMPAudioHost.h"
#include "mozilla/unused.h" #include "mozilla/unused.h"
#include <stdio.h> #include <stdio.h>
@ -12,7 +12,7 @@
namespace mozilla { namespace mozilla {
namespace gmp { namespace gmp {
GMPAudioDecoderChild::GMPAudioDecoderChild(GMPChild* aPlugin) GMPAudioDecoderChild::GMPAudioDecoderChild(GMPContentChild* aPlugin)
: mPlugin(aPlugin) : mPlugin(aPlugin)
, mAudioDecoder(nullptr) , mAudioDecoder(nullptr)
{ {

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

@ -13,13 +13,13 @@
namespace mozilla { namespace mozilla {
namespace gmp { namespace gmp {
class GMPChild; class GMPContentChild;
class GMPAudioDecoderChild : public PGMPAudioDecoderChild, class GMPAudioDecoderChild : public PGMPAudioDecoderChild,
public GMPAudioDecoderCallback public GMPAudioDecoderCallback
{ {
public: public:
explicit GMPAudioDecoderChild(GMPChild* aPlugin); explicit GMPAudioDecoderChild(GMPContentChild* aPlugin);
virtual ~GMPAudioDecoderChild(); virtual ~GMPAudioDecoderChild();
void Init(GMPAudioDecoder* aDecoder); void Init(GMPAudioDecoder* aDecoder);
@ -40,7 +40,7 @@ private:
virtual bool RecvDrain() override; virtual bool RecvDrain() override;
virtual bool RecvDecodingComplete() override; virtual bool RecvDecodingComplete() override;
GMPChild* mPlugin; GMPContentChild* mPlugin;
GMPAudioDecoder* mAudioDecoder; GMPAudioDecoder* mAudioDecoder;
GMPAudioHostImpl mAudioHost; GMPAudioHostImpl mAudioHost;
}; };

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

@ -4,7 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GMPAudioDecoderParent.h" #include "GMPAudioDecoderParent.h"
#include "GMPParent.h" #include "GMPContentParent.h"
#include <stdio.h> #include <stdio.h>
#include "mozilla/unused.h" #include "mozilla/unused.h"
#include "GMPMessageUtils.h" #include "GMPMessageUtils.h"
@ -29,7 +29,7 @@ extern PRLogModuleInfo* GetGMPLog();
namespace gmp { namespace gmp {
GMPAudioDecoderParent::GMPAudioDecoderParent(GMPParent* aPlugin) GMPAudioDecoderParent::GMPAudioDecoderParent(GMPContentParent* aPlugin)
: mIsOpen(false) : mIsOpen(false)
, mShuttingDown(false) , mShuttingDown(false)
, mPlugin(aPlugin) , mPlugin(aPlugin)
@ -263,6 +263,13 @@ GMPAudioDecoderParent::RecvError(const GMPErr& aError)
return true; return true;
} }
bool
GMPAudioDecoderParent::RecvShutdown()
{
Shutdown();
return true;
}
bool bool
GMPAudioDecoderParent::Recv__delete__() GMPAudioDecoderParent::Recv__delete__()
{ {

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

@ -16,7 +16,7 @@
namespace mozilla { namespace mozilla {
namespace gmp { namespace gmp {
class GMPParent; class GMPContentParent;
class GMPAudioDecoderParent final : public GMPAudioDecoderProxy class GMPAudioDecoderParent final : public GMPAudioDecoderProxy
, public PGMPAudioDecoderParent , public PGMPAudioDecoderParent
@ -24,7 +24,7 @@ class GMPAudioDecoderParent final : public GMPAudioDecoderProxy
public: public:
NS_INLINE_DECL_REFCOUNTING(GMPAudioDecoderParent) NS_INLINE_DECL_REFCOUNTING(GMPAudioDecoderParent)
explicit GMPAudioDecoderParent(GMPParent *aPlugin); explicit GMPAudioDecoderParent(GMPContentParent *aPlugin);
nsresult Shutdown(); nsresult Shutdown();
@ -50,11 +50,12 @@ private:
virtual bool RecvDrainComplete() override; virtual bool RecvDrainComplete() override;
virtual bool RecvResetComplete() override; virtual bool RecvResetComplete() override;
virtual bool RecvError(const GMPErr& aError) override; virtual bool RecvError(const GMPErr& aError) override;
virtual bool RecvShutdown() override;
virtual bool Recv__delete__() override; virtual bool Recv__delete__() override;
bool mIsOpen; bool mIsOpen;
bool mShuttingDown; bool mShuttingDown;
nsRefPtr<GMPParent> mPlugin; nsRefPtr<GMPContentParent> mPlugin;
GMPAudioDecoderCallbackProxy* mCallback; GMPAudioDecoderCallbackProxy* mCallback;
}; };

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

@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GMPChild.h" #include "GMPChild.h"
#include "GMPContentChild.h"
#include "GMPProcessChild.h" #include "GMPProcessChild.h"
#include "GMPLoader.h" #include "GMPLoader.h"
#include "GMPVideoDecoderChild.h" #include "GMPVideoDecoderChild.h"
@ -256,12 +257,6 @@ GMPChild::StartMacSandbox()
} }
#endif // XP_MACOSX && MOZ_GMP_SANDBOX #endif // XP_MACOSX && MOZ_GMP_SANDBOX
void
GMPChild::CheckThread()
{
MOZ_ASSERT(mGMPMessageLoop == MessageLoop::current());
}
bool bool
GMPChild::Init(const std::string& aPluginPath, GMPChild::Init(const std::string& aPluginPath,
const std::string& aVoucherPath, const std::string& aVoucherPath,
@ -467,6 +462,11 @@ GMPChild::ActorDestroy(ActorDestroyReason aWhy)
{ {
LOGD("%s reason=%d", __FUNCTION__, aWhy); LOGD("%s reason=%d", __FUNCTION__, aWhy);
for (uint32_t i = mGMPContentChildren.Length(); i > 0; i--) {
MOZ_ASSERT_IF(aWhy == NormalShutdown, !mGMPContentChildren[i - 1]->IsUsed());
mGMPContentChildren[i - 1]->Close();
}
if (mGMPLoader) { if (mGMPLoader) {
mGMPLoader->Shutdown(); mGMPLoader->Shutdown();
} }
@ -501,19 +501,6 @@ GMPChild::ProcessingError(Result aCode, const char* aReason)
} }
} }
PGMPAudioDecoderChild*
GMPChild::AllocPGMPAudioDecoderChild()
{
return new GMPAudioDecoderChild(this);
}
bool
GMPChild::DeallocPGMPAudioDecoderChild(PGMPAudioDecoderChild* aActor)
{
delete aActor;
return true;
}
mozilla::dom::PCrashReporterChild* mozilla::dom::PCrashReporterChild*
GMPChild::AllocPCrashReporterChild(const NativeThreadId& aThread) GMPChild::AllocPCrashReporterChild(const NativeThreadId& aThread)
{ {
@ -527,120 +514,6 @@ GMPChild::DeallocPCrashReporterChild(PCrashReporterChild* aCrashReporter)
return true; return true;
} }
PGMPVideoDecoderChild*
GMPChild::AllocPGMPVideoDecoderChild()
{
return new GMPVideoDecoderChild(this);
}
bool
GMPChild::DeallocPGMPVideoDecoderChild(PGMPVideoDecoderChild* aActor)
{
delete aActor;
return true;
}
PGMPDecryptorChild*
GMPChild::AllocPGMPDecryptorChild()
{
GMPDecryptorChild* actor = new GMPDecryptorChild(this, mPluginVoucher, mSandboxVoucher);
actor->AddRef();
return actor;
}
bool
GMPChild::DeallocPGMPDecryptorChild(PGMPDecryptorChild* aActor)
{
static_cast<GMPDecryptorChild*>(aActor)->Release();
return true;
}
bool
GMPChild::RecvPGMPAudioDecoderConstructor(PGMPAudioDecoderChild* aActor)
{
auto vdc = static_cast<GMPAudioDecoderChild*>(aActor);
void* vd = nullptr;
GMPErr err = GetAPI(GMP_API_AUDIO_DECODER, &vdc->Host(), &vd);
if (err != GMPNoErr || !vd) {
return false;
}
vdc->Init(static_cast<GMPAudioDecoder*>(vd));
return true;
}
PGMPVideoEncoderChild*
GMPChild::AllocPGMPVideoEncoderChild()
{
return new GMPVideoEncoderChild(this);
}
bool
GMPChild::DeallocPGMPVideoEncoderChild(PGMPVideoEncoderChild* aActor)
{
delete aActor;
return true;
}
bool
GMPChild::RecvPGMPVideoDecoderConstructor(PGMPVideoDecoderChild* aActor)
{
auto vdc = static_cast<GMPVideoDecoderChild*>(aActor);
void* vd = nullptr;
GMPErr err = GetAPI(GMP_API_VIDEO_DECODER, &vdc->Host(), &vd);
if (err != GMPNoErr || !vd) {
NS_WARNING("GMPGetAPI call failed trying to construct decoder.");
return false;
}
vdc->Init(static_cast<GMPVideoDecoder*>(vd));
return true;
}
bool
GMPChild::RecvPGMPVideoEncoderConstructor(PGMPVideoEncoderChild* aActor)
{
auto vec = static_cast<GMPVideoEncoderChild*>(aActor);
void* ve = nullptr;
GMPErr err = GetAPI(GMP_API_VIDEO_ENCODER, &vec->Host(), &ve);
if (err != GMPNoErr || !ve) {
NS_WARNING("GMPGetAPI call failed trying to construct encoder.");
return false;
}
vec->Init(static_cast<GMPVideoEncoder*>(ve));
return true;
}
bool
GMPChild::RecvPGMPDecryptorConstructor(PGMPDecryptorChild* aActor)
{
GMPDecryptorChild* child = static_cast<GMPDecryptorChild*>(aActor);
GMPDecryptorHost* host = static_cast<GMPDecryptorHost*>(child);
void* session = nullptr;
GMPErr err = GetAPI(GMP_API_DECRYPTOR, host, &session);
if (err != GMPNoErr && !session) {
// XXX to remove in bug 1147692
err = GetAPI(GMP_API_DECRYPTOR_COMPAT, host, &session);
}
if (err != GMPNoErr || !session) {
return false;
}
child->Init(static_cast<GMPDecryptor*>(session));
return true;
}
PGMPTimerChild* PGMPTimerChild*
GMPChild::AllocPGMPTimerChild() GMPChild::AllocPGMPTimerChild()
{ {
@ -715,6 +588,15 @@ GMPChild::RecvBeginAsyncShutdown()
return true; return true;
} }
bool
GMPChild::RecvCloseActive()
{
for (uint32_t i = mGMPContentChildren.Length(); i > 0; i--) {
mGMPContentChildren[i - 1]->CloseActive();
}
return true;
}
void void
GMPChild::ShutdownComplete() GMPChild::ShutdownComplete()
{ {
@ -802,6 +684,32 @@ GMPChild::PreLoadSandboxVoucher()
} }
} }
PGMPContentChild*
GMPChild::AllocPGMPContentChild(Transport* aTransport,
ProcessId aOtherPid)
{
GMPContentChild* child =
mGMPContentChildren.AppendElement(new GMPContentChild(this))->get();
child->Open(aTransport, aOtherPid, XRE_GetIOMessageLoop(), ipc::ChildSide);
return child;
}
void
GMPChild::GMPContentChildActorDestroy(GMPContentChild* aGMPContentChild)
{
for (uint32_t i = mGMPContentChildren.Length(); i > 0; i--) {
UniquePtr<GMPContentChild>& toDestroy = mGMPContentChildren[i - 1];
if (toDestroy.get() == aGMPContentChild) {
SendPGMPContentChildDestroyed();
MessageLoop::current()->PostTask(FROM_HERE,
new DeleteTask<GMPContentChild>(toDestroy.release()));
mGMPContentChildren.RemoveElementAt(i - 1);
break;
}
}
}
} // namespace gmp } // namespace gmp
} // namespace mozilla } // namespace mozilla

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

@ -7,7 +7,6 @@
#define GMPChild_h_ #define GMPChild_h_
#include "mozilla/gmp/PGMPChild.h" #include "mozilla/gmp/PGMPChild.h"
#include "GMPSharedMemManager.h"
#include "GMPTimerChild.h" #include "GMPTimerChild.h"
#include "GMPStorageChild.h" #include "GMPStorageChild.h"
#include "GMPLoader.h" #include "GMPLoader.h"
@ -18,8 +17,9 @@
namespace mozilla { namespace mozilla {
namespace gmp { namespace gmp {
class GMPContentChild;
class GMPChild : public PGMPChild class GMPChild : public PGMPChild
, public GMPSharedMem
, public GMPAsyncShutdownHost , public GMPAsyncShutdownHost
{ {
public: public:
@ -40,9 +40,6 @@ public:
GMPTimerChild* GetGMPTimers(); GMPTimerChild* GetGMPTimers();
GMPStorageChild* GetGMPStorage(); GMPStorageChild* GetGMPStorage();
// GMPSharedMem
virtual void CheckThread() override;
// GMPAsyncShutdownHost // GMPAsyncShutdownHost
void ShutdownComplete() override; void ShutdownComplete() override;
@ -51,6 +48,7 @@ public:
#endif #endif
private: private:
friend class GMPContentChild;
bool PreLoadPluginVoucher(const std::string& aPluginPath); bool PreLoadPluginVoucher(const std::string& aPluginPath);
void PreLoadSandboxVoucher(); void PreLoadSandboxVoucher();
@ -63,36 +61,27 @@ private:
virtual PCrashReporterChild* AllocPCrashReporterChild(const NativeThreadId& aThread) override; virtual PCrashReporterChild* AllocPCrashReporterChild(const NativeThreadId& aThread) override;
virtual bool DeallocPCrashReporterChild(PCrashReporterChild*) override; virtual bool DeallocPCrashReporterChild(PCrashReporterChild*) override;
virtual PGMPVideoDecoderChild* AllocPGMPVideoDecoderChild() override;
virtual bool DeallocPGMPVideoDecoderChild(PGMPVideoDecoderChild* aActor) override;
virtual bool RecvPGMPVideoDecoderConstructor(PGMPVideoDecoderChild* aActor) override;
virtual PGMPVideoEncoderChild* AllocPGMPVideoEncoderChild() override;
virtual bool DeallocPGMPVideoEncoderChild(PGMPVideoEncoderChild* aActor) override;
virtual bool RecvPGMPVideoEncoderConstructor(PGMPVideoEncoderChild* aActor) override;
virtual PGMPDecryptorChild* AllocPGMPDecryptorChild() override;
virtual bool DeallocPGMPDecryptorChild(PGMPDecryptorChild* aActor) override;
virtual bool RecvPGMPDecryptorConstructor(PGMPDecryptorChild* aActor) override;
virtual PGMPAudioDecoderChild* AllocPGMPAudioDecoderChild() override;
virtual bool DeallocPGMPAudioDecoderChild(PGMPAudioDecoderChild* aActor) override;
virtual bool RecvPGMPAudioDecoderConstructor(PGMPAudioDecoderChild* aActor) override;
virtual PGMPTimerChild* AllocPGMPTimerChild() override; virtual PGMPTimerChild* AllocPGMPTimerChild() override;
virtual bool DeallocPGMPTimerChild(PGMPTimerChild* aActor) override; virtual bool DeallocPGMPTimerChild(PGMPTimerChild* aActor) override;
virtual PGMPStorageChild* AllocPGMPStorageChild() override; virtual PGMPStorageChild* AllocPGMPStorageChild() override;
virtual bool DeallocPGMPStorageChild(PGMPStorageChild* aActor) override; virtual bool DeallocPGMPStorageChild(PGMPStorageChild* aActor) override;
virtual PGMPContentChild* AllocPGMPContentChild(Transport* aTransport,
ProcessId aOtherPid) override;
void GMPContentChildActorDestroy(GMPContentChild* aGMPContentChild);
virtual bool RecvCrashPluginNow() override; virtual bool RecvCrashPluginNow() override;
virtual bool RecvBeginAsyncShutdown() override; virtual bool RecvBeginAsyncShutdown() override;
virtual bool RecvCloseActive() override;
virtual void ActorDestroy(ActorDestroyReason aWhy) override; virtual void ActorDestroy(ActorDestroyReason aWhy) override;
virtual void ProcessingError(Result aCode, const char* aReason) override; virtual void ProcessingError(Result aCode, const char* aReason) override;
GMPErr GetAPI(const char* aAPIName, void* aHostAPI, void** aPluginAPI); GMPErr GetAPI(const char* aAPIName, void* aHostAPI, void** aPluginAPI);
nsTArray<UniquePtr<GMPContentChild>> mGMPContentChildren;
GMPAsyncShutdown* mAsyncShutdown; GMPAsyncShutdown* mAsyncShutdown;
nsRefPtr<GMPTimerChild> mTimerChild; nsRefPtr<GMPTimerChild> mTimerChild;
nsRefPtr<GMPStorageChild> mStorage; nsRefPtr<GMPStorageChild> mStorage;

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

@ -0,0 +1,215 @@
/* -*- 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 "GMPContentChild.h"
namespace mozilla {
namespace gmp {
GMPContentChild::GMPContentChild(GMPChild* aChild)
: mGMPChild(aChild)
{
MOZ_COUNT_CTOR(GMPContentChild);
}
GMPContentChild::~GMPContentChild()
{
MOZ_COUNT_DTOR(GMPContentChild);
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
new DeleteTask<Transport>(GetTransport()));
}
MessageLoop*
GMPContentChild::GMPMessageLoop()
{
return mGMPChild->GMPMessageLoop();
}
void
GMPContentChild::CheckThread()
{
MOZ_ASSERT(mGMPChild->mGMPMessageLoop == MessageLoop::current());
}
void
GMPContentChild::ActorDestroy(ActorDestroyReason aWhy)
{
mGMPChild->GMPContentChildActorDestroy(this);
}
void
GMPContentChild::ProcessingError(Result aCode, const char* aReason)
{
mGMPChild->ProcessingError(aCode, aReason);
}
PGMPAudioDecoderChild*
GMPContentChild::AllocPGMPAudioDecoderChild()
{
return new GMPAudioDecoderChild(this);
}
bool
GMPContentChild::DeallocPGMPAudioDecoderChild(PGMPAudioDecoderChild* aActor)
{
delete aActor;
return true;
}
PGMPDecryptorChild*
GMPContentChild::AllocPGMPDecryptorChild()
{
GMPDecryptorChild* actor = new GMPDecryptorChild(this,
mGMPChild->mPluginVoucher,
mGMPChild->mSandboxVoucher);
actor->AddRef();
return actor;
}
bool
GMPContentChild::DeallocPGMPDecryptorChild(PGMPDecryptorChild* aActor)
{
static_cast<GMPDecryptorChild*>(aActor)->Release();
return true;
}
PGMPVideoDecoderChild*
GMPContentChild::AllocPGMPVideoDecoderChild()
{
return new GMPVideoDecoderChild(this);
}
bool
GMPContentChild::DeallocPGMPVideoDecoderChild(PGMPVideoDecoderChild* aActor)
{
delete aActor;
return true;
}
PGMPVideoEncoderChild*
GMPContentChild::AllocPGMPVideoEncoderChild()
{
return new GMPVideoEncoderChild(this);
}
bool
GMPContentChild::DeallocPGMPVideoEncoderChild(PGMPVideoEncoderChild* aActor)
{
delete aActor;
return true;
}
bool
GMPContentChild::RecvPGMPDecryptorConstructor(PGMPDecryptorChild* aActor)
{
GMPDecryptorChild* child = static_cast<GMPDecryptorChild*>(aActor);
GMPDecryptorHost* host = static_cast<GMPDecryptorHost*>(child);
void* session = nullptr;
GMPErr err = mGMPChild->GetAPI(GMP_API_DECRYPTOR, host, &session);
if (err != GMPNoErr && !session) {
// XXX to remove in bug 1147692
err = mGMPChild->GetAPI(GMP_API_DECRYPTOR_COMPAT, host, &session);
}
if (err != GMPNoErr || !session) {
return false;
}
child->Init(static_cast<GMPDecryptor*>(session));
return true;
}
bool
GMPContentChild::RecvPGMPAudioDecoderConstructor(PGMPAudioDecoderChild* aActor)
{
auto vdc = static_cast<GMPAudioDecoderChild*>(aActor);
void* vd = nullptr;
GMPErr err = mGMPChild->GetAPI(GMP_API_AUDIO_DECODER, &vdc->Host(), &vd);
if (err != GMPNoErr || !vd) {
return false;
}
vdc->Init(static_cast<GMPAudioDecoder*>(vd));
return true;
}
bool
GMPContentChild::RecvPGMPVideoDecoderConstructor(PGMPVideoDecoderChild* aActor)
{
auto vdc = static_cast<GMPVideoDecoderChild*>(aActor);
void* vd = nullptr;
GMPErr err = mGMPChild->GetAPI(GMP_API_VIDEO_DECODER, &vdc->Host(), &vd);
if (err != GMPNoErr || !vd) {
NS_WARNING("GMPGetAPI call failed trying to construct decoder.");
return false;
}
vdc->Init(static_cast<GMPVideoDecoder*>(vd));
return true;
}
bool
GMPContentChild::RecvPGMPVideoEncoderConstructor(PGMPVideoEncoderChild* aActor)
{
auto vec = static_cast<GMPVideoEncoderChild*>(aActor);
void* ve = nullptr;
GMPErr err = mGMPChild->GetAPI(GMP_API_VIDEO_ENCODER, &vec->Host(), &ve);
if (err != GMPNoErr || !ve) {
NS_WARNING("GMPGetAPI call failed trying to construct encoder.");
return false;
}
vec->Init(static_cast<GMPVideoEncoder*>(ve));
return true;
}
void
GMPContentChild::CloseActive()
{
// Invalidate and remove any remaining API objects.
const nsTArray<PGMPAudioDecoderChild*>& audioDecoders =
ManagedPGMPAudioDecoderChild();
for (uint32_t i = audioDecoders.Length(); i > 0; i--) {
audioDecoders[i - 1]->SendShutdown();
}
const nsTArray<PGMPDecryptorChild*>& decryptors =
ManagedPGMPDecryptorChild();
for (uint32_t i = decryptors.Length(); i > 0; i--) {
decryptors[i - 1]->SendShutdown();
}
const nsTArray<PGMPVideoDecoderChild*>& videoDecoders =
ManagedPGMPVideoDecoderChild();
for (uint32_t i = videoDecoders.Length(); i > 0; i--) {
videoDecoders[i - 1]->SendShutdown();
}
const nsTArray<PGMPVideoEncoderChild*>& videoEncoders =
ManagedPGMPVideoEncoderChild();
for (uint32_t i = videoEncoders.Length(); i > 0; i--) {
videoEncoders[i - 1]->SendShutdown();
}
}
bool
GMPContentChild::IsUsed()
{
return !ManagedPGMPAudioDecoderChild().IsEmpty() ||
!ManagedPGMPDecryptorChild().IsEmpty() ||
!ManagedPGMPVideoDecoderChild().IsEmpty() ||
!ManagedPGMPVideoEncoderChild().IsEmpty();
}
} // namespace gmp
} // namespace mozilla

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

@ -0,0 +1,58 @@
/* -*- 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 GMPContentChild_h_
#define GMPContentChild_h_
#include "mozilla/gmp/PGMPContentChild.h"
#include "GMPSharedMemManager.h"
namespace mozilla {
namespace gmp {
class GMPChild;
class GMPContentChild : public PGMPContentChild
, public GMPSharedMem
{
public:
explicit GMPContentChild(GMPChild* aChild);
virtual ~GMPContentChild();
MessageLoop* GMPMessageLoop();
virtual bool RecvPGMPAudioDecoderConstructor(PGMPAudioDecoderChild* aActor) override;
virtual bool RecvPGMPDecryptorConstructor(PGMPDecryptorChild* aActor) override;
virtual bool RecvPGMPVideoDecoderConstructor(PGMPVideoDecoderChild* aActor) override;
virtual bool RecvPGMPVideoEncoderConstructor(PGMPVideoEncoderChild* aActor) override;
virtual PGMPAudioDecoderChild* AllocPGMPAudioDecoderChild() override;
virtual bool DeallocPGMPAudioDecoderChild(PGMPAudioDecoderChild* aActor) override;
virtual PGMPDecryptorChild* AllocPGMPDecryptorChild() override;
virtual bool DeallocPGMPDecryptorChild(PGMPDecryptorChild* aActor) override;
virtual PGMPVideoDecoderChild* AllocPGMPVideoDecoderChild() override;
virtual bool DeallocPGMPVideoDecoderChild(PGMPVideoDecoderChild* aActor) override;
virtual PGMPVideoEncoderChild* AllocPGMPVideoEncoderChild() override;
virtual bool DeallocPGMPVideoEncoderChild(PGMPVideoEncoderChild* aActor) override;
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
virtual void ProcessingError(Result aCode, const char* aReason) override;
// GMPSharedMem
virtual void CheckThread() override;
void CloseActive();
bool IsUsed();
GMPChild* mGMPChild;
};
} // namespace gmp
} // namespace mozilla
#endif // GMPContentChild_h_

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

@ -0,0 +1,302 @@
/* -*- 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 "GMPContentParent.h"
#include "GMPAudioDecoderParent.h"
#include "GMPDecryptorParent.h"
#include "GMPParent.h"
#include "GMPServiceChild.h"
#include "GMPVideoDecoderParent.h"
#include "GMPVideoEncoderParent.h"
#include "mozIGeckoMediaPluginService.h"
#include "prlog.h"
namespace mozilla {
#ifdef LOG
#undef LOG
#endif
#ifdef PR_LOGGING
extern PRLogModuleInfo* GetGMPLog();
#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(level, msg)
#endif
#ifdef __CLASS__
#undef __CLASS__
#endif
#define __CLASS__ "GMPContentParent"
namespace gmp {
GMPContentParent::GMPContentParent(GMPParent* aParent)
: mParent(aParent)
{
if (mParent) {
SetDisplayName(mParent->GetDisplayName());
SetPluginId(mParent->GetPluginId());
}
}
GMPContentParent::~GMPContentParent()
{
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
new DeleteTask<Transport>(GetTransport()));
}
class ReleaseGMPContentParent : public nsRunnable
{
public:
explicit ReleaseGMPContentParent(GMPContentParent* aToRelease)
: mToRelease(aToRelease)
{
}
NS_IMETHOD Run()
{
return NS_OK;
}
private:
nsRefPtr<GMPContentParent> mToRelease;
};
void
GMPContentParent::ActorDestroy(ActorDestroyReason aWhy)
{
MOZ_ASSERT(mAudioDecoders.IsEmpty() &&
mDecryptors.IsEmpty() &&
mVideoDecoders.IsEmpty() &&
mVideoEncoders.IsEmpty());
NS_DispatchToCurrentThread(new ReleaseGMPContentParent(this));
}
void
GMPContentParent::CheckThread()
{
MOZ_ASSERT(mGMPThread == NS_GetCurrentThread());
}
void
GMPContentParent::AudioDecoderDestroyed(GMPAudioDecoderParent* aDecoder)
{
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
MOZ_ALWAYS_TRUE(mAudioDecoders.RemoveElement(aDecoder));
CloseIfUnused();
}
void
GMPContentParent::VideoDecoderDestroyed(GMPVideoDecoderParent* aDecoder)
{
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
// If the constructor fails, we'll get called before it's added
unused << NS_WARN_IF(!mVideoDecoders.RemoveElement(aDecoder));
CloseIfUnused();
}
void
GMPContentParent::VideoEncoderDestroyed(GMPVideoEncoderParent* aEncoder)
{
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
// If the constructor fails, we'll get called before it's added
unused << NS_WARN_IF(!mVideoEncoders.RemoveElement(aEncoder));
CloseIfUnused();
}
void
GMPContentParent::DecryptorDestroyed(GMPDecryptorParent* aSession)
{
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
MOZ_ALWAYS_TRUE(mDecryptors.RemoveElement(aSession));
CloseIfUnused();
}
void
GMPContentParent::CloseIfUnused()
{
if (mAudioDecoders.IsEmpty() &&
mDecryptors.IsEmpty() &&
mVideoDecoders.IsEmpty() &&
mVideoEncoders.IsEmpty()) {
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));
}
}
nsresult
GMPContentParent::GetGMPDecryptor(GMPDecryptorParent** aGMPDP)
{
PGMPDecryptorParent* pdp = SendPGMPDecryptorConstructor();
if (!pdp) {
return NS_ERROR_FAILURE;
}
GMPDecryptorParent* dp = static_cast<GMPDecryptorParent*>(pdp);
// This addref corresponds to the Proxy pointer the consumer is returned.
// It's dropped by calling Close() on the interface.
NS_ADDREF(dp);
mDecryptors.AppendElement(dp);
*aGMPDP = dp;
return NS_OK;
}
nsIThread*
GMPContentParent::GMPThread()
{
if (!mGMPThread) {
nsCOMPtr<mozIGeckoMediaPluginService> mps = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
MOZ_ASSERT(mps);
if (!mps) {
return nullptr;
}
// Not really safe if we just grab to the mGMPThread, as we don't know
// what thread we're running on and other threads may be trying to
// access this without locks! However, debug only, and primary failure
// mode outside of compiler-helped TSAN is a leak. But better would be
// to use swap() under a lock.
mps->GetThread(getter_AddRefs(mGMPThread));
MOZ_ASSERT(mGMPThread);
}
return mGMPThread;
}
nsresult
GMPContentParent::GetGMPAudioDecoder(GMPAudioDecoderParent** aGMPAD)
{
PGMPAudioDecoderParent* pvap = SendPGMPAudioDecoderConstructor();
if (!pvap) {
return NS_ERROR_FAILURE;
}
GMPAudioDecoderParent* vap = static_cast<GMPAudioDecoderParent*>(pvap);
// This addref corresponds to the Proxy pointer the consumer is returned.
// It's dropped by calling Close() on the interface.
NS_ADDREF(vap);
*aGMPAD = vap;
mAudioDecoders.AppendElement(vap);
return NS_OK;
}
nsresult
GMPContentParent::GetGMPVideoDecoder(GMPVideoDecoderParent** aGMPVD)
{
// returned with one anonymous AddRef that locks it until Destroy
PGMPVideoDecoderParent* pvdp = SendPGMPVideoDecoderConstructor();
if (!pvdp) {
return NS_ERROR_FAILURE;
}
GMPVideoDecoderParent *vdp = static_cast<GMPVideoDecoderParent*>(pvdp);
// This addref corresponds to the Proxy pointer the consumer is returned.
// It's dropped by calling Close() on the interface.
NS_ADDREF(vdp);
*aGMPVD = vdp;
mVideoDecoders.AppendElement(vdp);
return NS_OK;
}
nsresult
GMPContentParent::GetGMPVideoEncoder(GMPVideoEncoderParent** aGMPVE)
{
// returned with one anonymous AddRef that locks it until Destroy
PGMPVideoEncoderParent* pvep = SendPGMPVideoEncoderConstructor();
if (!pvep) {
return NS_ERROR_FAILURE;
}
GMPVideoEncoderParent *vep = static_cast<GMPVideoEncoderParent*>(pvep);
// This addref corresponds to the Proxy pointer the consumer is returned.
// It's dropped by calling Close() on the interface.
NS_ADDREF(vep);
*aGMPVE = vep;
mVideoEncoders.AppendElement(vep);
return NS_OK;
}
PGMPVideoDecoderParent*
GMPContentParent::AllocPGMPVideoDecoderParent()
{
GMPVideoDecoderParent* vdp = new GMPVideoDecoderParent(this);
NS_ADDREF(vdp);
return vdp;
}
bool
GMPContentParent::DeallocPGMPVideoDecoderParent(PGMPVideoDecoderParent* aActor)
{
GMPVideoDecoderParent* vdp = static_cast<GMPVideoDecoderParent*>(aActor);
NS_RELEASE(vdp);
return true;
}
PGMPVideoEncoderParent*
GMPContentParent::AllocPGMPVideoEncoderParent()
{
GMPVideoEncoderParent* vep = new GMPVideoEncoderParent(this);
NS_ADDREF(vep);
return vep;
}
bool
GMPContentParent::DeallocPGMPVideoEncoderParent(PGMPVideoEncoderParent* aActor)
{
GMPVideoEncoderParent* vep = static_cast<GMPVideoEncoderParent*>(aActor);
NS_RELEASE(vep);
return true;
}
PGMPDecryptorParent*
GMPContentParent::AllocPGMPDecryptorParent()
{
GMPDecryptorParent* ksp = new GMPDecryptorParent(this);
NS_ADDREF(ksp);
return ksp;
}
bool
GMPContentParent::DeallocPGMPDecryptorParent(PGMPDecryptorParent* aActor)
{
GMPDecryptorParent* ksp = static_cast<GMPDecryptorParent*>(aActor);
NS_RELEASE(ksp);
return true;
}
PGMPAudioDecoderParent*
GMPContentParent::AllocPGMPAudioDecoderParent()
{
GMPAudioDecoderParent* vdp = new GMPAudioDecoderParent(this);
NS_ADDREF(vdp);
return vdp;
}
bool
GMPContentParent::DeallocPGMPAudioDecoderParent(PGMPAudioDecoderParent* aActor)
{
GMPAudioDecoderParent* vdp = static_cast<GMPAudioDecoderParent*>(aActor);
NS_RELEASE(vdp);
return true;
}
} // namespace gmp
} // namespace mozilla

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

@ -0,0 +1,105 @@
/* -*- 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 GMPContentParent_h_
#define GMPContentParent_h_
#include "mozilla/gmp/PGMPContentParent.h"
#include "nsISupportsImpl.h"
class nsITimer;
namespace mozilla {
namespace gmp {
class GeckoMediaPluginService;
class GMPAudioDecoderParent;
class GMPCapability;
class GMPDecryptorParent;
class GMPParent;
class GMPVideoDecoderParent;
class GMPVideoEncoderParent;
class GMPContentParent final : public PGMPContentParent,
public GMPSharedMem
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPContentParent)
explicit GMPContentParent(GMPParent* aParent = nullptr);
nsresult GetGMPVideoDecoder(GMPVideoDecoderParent** aGMPVD);
void VideoDecoderDestroyed(GMPVideoDecoderParent* aDecoder);
nsresult GetGMPVideoEncoder(GMPVideoEncoderParent** aGMPVE);
void VideoEncoderDestroyed(GMPVideoEncoderParent* aEncoder);
nsresult GetGMPDecryptor(GMPDecryptorParent** aGMPKS);
void DecryptorDestroyed(GMPDecryptorParent* aSession);
nsresult GetGMPAudioDecoder(GMPAudioDecoderParent** aGMPAD);
void AudioDecoderDestroyed(GMPAudioDecoderParent* aDecoder);
nsIThread* GMPThread();
// GMPSharedMem
virtual void CheckThread() override;
void SetDisplayName(const nsCString& aDisplayName)
{
mDisplayName = aDisplayName;
}
const nsCString& GetDisplayName()
{
return mDisplayName;
}
void SetPluginId(const nsCString& aPluginId)
{
mPluginId = aPluginId;
}
const nsCString& GetPluginId()
{
return mPluginId;
}
private:
~GMPContentParent();
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
virtual PGMPVideoDecoderParent* AllocPGMPVideoDecoderParent() override;
virtual bool DeallocPGMPVideoDecoderParent(PGMPVideoDecoderParent* aActor) override;
virtual PGMPVideoEncoderParent* AllocPGMPVideoEncoderParent() override;
virtual bool DeallocPGMPVideoEncoderParent(PGMPVideoEncoderParent* aActor) override;
virtual PGMPDecryptorParent* AllocPGMPDecryptorParent() override;
virtual bool DeallocPGMPDecryptorParent(PGMPDecryptorParent* aActor) override;
virtual PGMPAudioDecoderParent* AllocPGMPAudioDecoderParent() override;
virtual bool DeallocPGMPAudioDecoderParent(PGMPAudioDecoderParent* aActor) override;
void CloseIfUnused();
// Needed because NS_NewRunnableMethod tried to use the class that the method
// lives on to store the receiver, but PGMPContentParent isn't refcounted.
void Close()
{
PGMPContentParent::Close();
}
nsTArray<nsRefPtr<GMPVideoDecoderParent>> mVideoDecoders;
nsTArray<nsRefPtr<GMPVideoEncoderParent>> mVideoEncoders;
nsTArray<nsRefPtr<GMPDecryptorParent>> mDecryptors;
nsTArray<nsRefPtr<GMPAudioDecoderParent>> mAudioDecoders;
nsCOMPtr<nsIThread> mGMPThread;
nsRefPtr<GMPParent> mParent;
nsCString mDisplayName;
nsCString mPluginId;
};
} // namespace gmp
} // namespace mozilla
#endif // GMPParent_h_

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

@ -18,7 +18,7 @@
namespace mozilla { namespace mozilla {
namespace gmp { namespace gmp {
GMPDecryptorChild::GMPDecryptorChild(GMPChild* aPlugin, GMPDecryptorChild::GMPDecryptorChild(GMPContentChild* aPlugin,
const nsTArray<uint8_t>& aPluginVoucher, const nsTArray<uint8_t>& aPluginVoucher,
const nsTArray<uint8_t>& aSandboxVoucher) const nsTArray<uint8_t>& aSandboxVoucher)
: mSession(nullptr) : mSession(nullptr)

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

@ -15,7 +15,7 @@
namespace mozilla { namespace mozilla {
namespace gmp { namespace gmp {
class GMPChild; class GMPContentChild;
class GMPDecryptorChild : public GMPDecryptorCallback class GMPDecryptorChild : public GMPDecryptorCallback
, public GMPDecryptorHost , public GMPDecryptorHost
@ -24,7 +24,7 @@ class GMPDecryptorChild : public GMPDecryptorCallback
public: public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPDecryptorChild); NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPDecryptorChild);
explicit GMPDecryptorChild(GMPChild* aPlugin, explicit GMPDecryptorChild(GMPContentChild* aPlugin,
const nsTArray<uint8_t>& aPluginVoucher, const nsTArray<uint8_t>& aPluginVoucher,
const nsTArray<uint8_t>& aSandboxVoucher); const nsTArray<uint8_t>& aSandboxVoucher);
@ -123,7 +123,7 @@ private:
// GMP's GMPDecryptor implementation. // GMP's GMPDecryptor implementation.
// Only call into this on the (GMP process) main thread. // Only call into this on the (GMP process) main thread.
GMPDecryptor* mSession; GMPDecryptor* mSession;
GMPChild* mPlugin; GMPContentChild* mPlugin;
// Reference to the vouchers owned by the GMPChild. // Reference to the vouchers owned by the GMPChild.
const nsTArray<uint8_t>& mPluginVoucher; const nsTArray<uint8_t>& mPluginVoucher;

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

@ -4,14 +4,14 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GMPDecryptorParent.h" #include "GMPDecryptorParent.h"
#include "GMPParent.h" #include "GMPContentParent.h"
#include "mp4_demuxer/DecoderData.h" #include "mp4_demuxer/DecoderData.h"
#include "mozilla/unused.h" #include "mozilla/unused.h"
namespace mozilla { namespace mozilla {
namespace gmp { namespace gmp {
GMPDecryptorParent::GMPDecryptorParent(GMPParent* aPlugin) GMPDecryptorParent::GMPDecryptorParent(GMPContentParent* aPlugin)
: mIsOpen(false) : mIsOpen(false)
, mShuttingDown(false) , mShuttingDown(false)
, mPlugin(aPlugin) , mPlugin(aPlugin)
@ -307,6 +307,13 @@ GMPDecryptorParent::RecvDecrypted(const uint32_t& aId,
return true; return true;
} }
bool
GMPDecryptorParent::RecvShutdown()
{
Shutdown();
return true;
}
// Note: may be called via Terminated() // Note: may be called via Terminated()
void void
GMPDecryptorParent::Close() GMPDecryptorParent::Close()

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

@ -17,7 +17,7 @@ class CryptoSample;
namespace mozilla { namespace mozilla {
namespace gmp { namespace gmp {
class GMPParent; class GMPContentParent;
class GMPDecryptorParent final : public GMPDecryptorProxy class GMPDecryptorParent final : public GMPDecryptorProxy
, public PGMPDecryptorParent , public PGMPDecryptorParent
@ -25,7 +25,7 @@ class GMPDecryptorParent final : public GMPDecryptorProxy
public: public:
NS_INLINE_DECL_REFCOUNTING(GMPDecryptorParent) NS_INLINE_DECL_REFCOUNTING(GMPDecryptorParent)
explicit GMPDecryptorParent(GMPParent *aPlugin); explicit GMPDecryptorParent(GMPContentParent *aPlugin);
// GMPDecryptorProxy // GMPDecryptorProxy
@ -104,12 +104,14 @@ private:
virtual bool RecvSetCaps(const uint64_t& aCaps) override; virtual bool RecvSetCaps(const uint64_t& aCaps) override;
virtual bool RecvShutdown() override;
virtual void ActorDestroy(ActorDestroyReason aWhy) override; virtual void ActorDestroy(ActorDestroyReason aWhy) override;
virtual bool Recv__delete__() override; virtual bool Recv__delete__() override;
bool mIsOpen; bool mIsOpen;
bool mShuttingDown; bool mShuttingDown;
nsRefPtr<GMPParent> mPlugin; nsRefPtr<GMPContentParent> mPlugin;
nsCString mPluginId; nsCString mPluginId;
GMPDecryptorProxyCallback* mCallback; GMPDecryptorProxyCallback* mCallback;
#ifdef DEBUG #ifdef DEBUG

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

@ -14,6 +14,7 @@
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "nsIRunnable.h" #include "nsIRunnable.h"
#include "mozIGeckoMediaPluginService.h" #include "mozIGeckoMediaPluginService.h"
#include "mozilla/SyncRunnable.h"
#include "mozilla/unused.h" #include "mozilla/unused.h"
#include "nsIObserverService.h" #include "nsIObserverService.h"
#include "GMPTimerParent.h" #include "GMPTimerParent.h"
@ -53,6 +54,7 @@ GMPParent::GMPParent()
, mProcess(nullptr) , mProcess(nullptr)
, mDeleteProcessOnlyOnUnload(false) , mDeleteProcessOnlyOnUnload(false)
, mAbnormalShutdownInProgress(false) , mAbnormalShutdownInProgress(false)
, mGMPContentChildCount(0)
, mAsyncShutdownRequired(false) , mAsyncShutdownRequired(false)
, mAsyncShutdownInProgress(false) , mAsyncShutdownInProgress(false)
#ifdef PR_LOGGING #ifdef PR_LOGGING
@ -72,12 +74,6 @@ GMPParent::~GMPParent()
LOGD("GMPParent dtor"); LOGD("GMPParent dtor");
} }
void
GMPParent::CheckThread()
{
MOZ_ASSERT(mGMPThread == NS_GetCurrentThread());
}
nsresult nsresult
GMPParent::CloneFrom(const GMPParent* aOther) GMPParent::CloneFrom(const GMPParent* aOther)
{ {
@ -87,7 +83,7 @@ GMPParent::CloneFrom(const GMPParent* aOther)
} }
nsresult nsresult
GMPParent::Init(GeckoMediaPluginService *aService, nsIFile* aPluginDir) GMPParent::Init(GeckoMediaPluginServiceParent* aService, nsIFile* aPluginDir)
{ {
MOZ_ASSERT(aPluginDir); MOZ_ASSERT(aPluginDir);
MOZ_ASSERT(aService); MOZ_ASSERT(aService);
@ -188,8 +184,8 @@ AbortWaitingForGMPAsyncShutdown(nsITimer* aTimer, void* aClosure)
{ {
NS_WARNING("Timed out waiting for GMP async shutdown!"); NS_WARNING("Timed out waiting for GMP async shutdown!");
GMPParent* parent = reinterpret_cast<GMPParent*>(aClosure); GMPParent* parent = reinterpret_cast<GMPParent*>(aClosure);
nsRefPtr<GeckoMediaPluginService> service = nsRefPtr<GeckoMediaPluginServiceParent> service =
GeckoMediaPluginService::GetGeckoMediaPluginService(); GeckoMediaPluginServiceParent::GetSingleton();
if (service) { if (service) {
service->AsyncShutdownComplete(parent); service->AsyncShutdownComplete(parent);
} }
@ -216,8 +212,8 @@ GMPParent::EnsureAsyncShutdownTimeoutSet()
} }
int32_t timeout = GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT; int32_t timeout = GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT;
nsRefPtr<GeckoMediaPluginService> service = nsRefPtr<GeckoMediaPluginServiceParent> service =
GeckoMediaPluginService::GetGeckoMediaPluginService(); GeckoMediaPluginServiceParent::GetSingleton();
if (service) { if (service) {
timeout = service->AsyncShutdownTimeoutMs(); timeout = service->AsyncShutdownTimeoutMs();
} }
@ -226,6 +222,16 @@ GMPParent::EnsureAsyncShutdownTimeoutSet()
nsITimer::TYPE_ONE_SHOT); nsITimer::TYPE_ONE_SHOT);
} }
bool
GMPParent::RecvPGMPContentChildDestroyed()
{
--mGMPContentChildCount;
if (!IsUsed()) {
CloseIfUnused();
}
return true;
}
void void
GMPParent::CloseIfUnused() GMPParent::CloseIfUnused()
{ {
@ -235,11 +241,7 @@ GMPParent::CloseIfUnused()
if ((mDeleteProcessOnlyOnUnload || if ((mDeleteProcessOnlyOnUnload ||
mState == GMPStateLoaded || mState == GMPStateLoaded ||
mState == GMPStateUnloading) && mState == GMPStateUnloading) &&
mVideoDecoders.IsEmpty() && !IsUsed()) {
mVideoEncoders.IsEmpty() &&
mDecryptors.IsEmpty() &&
mAudioDecoders.IsEmpty()) {
// Ensure all timers are killed. // Ensure all timers are killed.
for (uint32_t i = mTimers.Length(); i > 0; i--) { for (uint32_t i = mTimers.Length(); i > 0; i--) {
mTimers[i - 1]->Shutdown(); mTimers[i - 1]->Shutdown();
@ -286,57 +288,21 @@ GMPParent::AbortAsyncShutdown()
CloseIfUnused(); CloseIfUnused();
} }
void
GMPParent::AudioDecoderDestroyed(GMPAudioDecoderParent* aDecoder)
{
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
MOZ_ALWAYS_TRUE(mAudioDecoders.RemoveElement(aDecoder));
// Recv__delete__ is on the stack, don't potentially destroy the top-level actor
// until after this has completed.
nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &GMPParent::CloseIfUnused);
NS_DispatchToCurrentThread(event);
}
void void
GMPParent::CloseActive(bool aDieWhenUnloaded) GMPParent::CloseActive(bool aDieWhenUnloaded)
{ {
LOGD("%s: state %d", __FUNCTION__, mState); LOGD("%s: state %d", __FUNCTION__, mState);
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
if (aDieWhenUnloaded) { if (aDieWhenUnloaded) {
mDeleteProcessOnlyOnUnload = true; // don't allow this to go back... mDeleteProcessOnlyOnUnload = true; // don't allow this to go back...
} }
if (mState == GMPStateLoaded) { if (mState == GMPStateLoaded) {
mState = GMPStateUnloading; mState = GMPStateUnloading;
} }
if (mState != GMPStateNotLoaded && IsUsed()) {
// Invalidate and remove any remaining API objects. unused << SendCloseActive();
for (uint32_t i = mVideoDecoders.Length(); i > 0; i--) {
mVideoDecoders[i - 1]->Shutdown();
} }
for (uint32_t i = mVideoEncoders.Length(); i > 0; i--) {
mVideoEncoders[i - 1]->Shutdown();
}
for (uint32_t i = mDecryptors.Length(); i > 0; i--) {
mDecryptors[i - 1]->Shutdown();
}
for (uint32_t i = mAudioDecoders.Length(); i > 0; i--) {
mAudioDecoders[i - 1]->Shutdown();
}
// Note: we don't shutdown timers here, we do that in CloseIfUnused(),
// as there are multiple entry points to CloseIfUnused().
// Note: We don't shutdown storage API objects here, as they need to
// work during async shutdown of GMPs.
// Note: the shutdown of the codecs is async! don't kill
// the plugin-container until they're all safely shut down via
// CloseIfUnused();
CloseIfUnused();
} }
void void
@ -350,7 +316,8 @@ GMPParent::Shutdown()
if (mAbnormalShutdownInProgress) { if (mAbnormalShutdownInProgress) {
return; return;
} }
MOZ_ASSERT(mVideoDecoders.IsEmpty() && mVideoEncoders.IsEmpty());
MOZ_ASSERT(!IsUsed());
if (mState == GMPStateNotLoaded || mState == GMPStateClosing) { if (mState == GMPStateNotLoaded || mState == GMPStateClosing) {
return; return;
} }
@ -406,78 +373,6 @@ GMPParent::DeleteProcess()
} }
void
GMPParent::VideoDecoderDestroyed(GMPVideoDecoderParent* aDecoder)
{
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
// If the constructor fails, we'll get called before it's added
unused << NS_WARN_IF(!mVideoDecoders.RemoveElement(aDecoder));
if (mVideoDecoders.IsEmpty() &&
mVideoEncoders.IsEmpty()) {
// Recv__delete__ is on the stack, don't potentially destroy the top-level actor
// until after this has completed.
nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &GMPParent::CloseIfUnused);
NS_DispatchToCurrentThread(event);
}
}
void
GMPParent::VideoEncoderDestroyed(GMPVideoEncoderParent* aEncoder)
{
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
// If the constructor fails, we'll get called before it's added
unused << NS_WARN_IF(!mVideoEncoders.RemoveElement(aEncoder));
if (mVideoDecoders.IsEmpty() &&
mVideoEncoders.IsEmpty()) {
// Recv__delete__ is on the stack, don't potentially destroy the top-level actor
// until after this has completed.
nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &GMPParent::CloseIfUnused);
NS_DispatchToCurrentThread(event);
}
}
void
GMPParent::DecryptorDestroyed(GMPDecryptorParent* aSession)
{
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
MOZ_ALWAYS_TRUE(mDecryptors.RemoveElement(aSession));
// Recv__delete__ is on the stack, don't potentially destroy the top-level actor
// until after this has completed.
if (mDecryptors.IsEmpty()) {
nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &GMPParent::CloseIfUnused);
NS_DispatchToCurrentThread(event);
}
}
nsresult
GMPParent::GetGMPDecryptor(GMPDecryptorParent** aGMPDP)
{
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
if (!EnsureProcessLoaded()) {
return NS_ERROR_FAILURE;
}
PGMPDecryptorParent* pdp = SendPGMPDecryptorConstructor();
if (!pdp) {
return NS_ERROR_FAILURE;
}
GMPDecryptorParent* dp = static_cast<GMPDecryptorParent*>(pdp);
// This addref corresponds to the Proxy pointer the consumer is returned.
// It's dropped by calling Close() on the interface.
NS_ADDREF(dp);
mDecryptors.AppendElement(dp);
*aGMPDP = dp;
return NS_OK;
}
GMPState GMPState
GMPParent::State() const GMPParent::State() const
{ {
@ -539,77 +434,6 @@ GMPParent::EnsureProcessLoaded()
return NS_SUCCEEDED(rv); return NS_SUCCEEDED(rv);
} }
nsresult
GMPParent::GetGMPAudioDecoder(GMPAudioDecoderParent** aGMPAD)
{
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
if (!EnsureProcessLoaded()) {
return NS_ERROR_FAILURE;
}
PGMPAudioDecoderParent* pvap = SendPGMPAudioDecoderConstructor();
if (!pvap) {
return NS_ERROR_FAILURE;
}
GMPAudioDecoderParent* vap = static_cast<GMPAudioDecoderParent*>(pvap);
// This addref corresponds to the Proxy pointer the consumer is returned.
// It's dropped by calling Close() on the interface.
NS_ADDREF(vap);
*aGMPAD = vap;
mAudioDecoders.AppendElement(vap);
return NS_OK;
}
nsresult
GMPParent::GetGMPVideoDecoder(GMPVideoDecoderParent** aGMPVD)
{
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
if (!EnsureProcessLoaded()) {
return NS_ERROR_FAILURE;
}
// returned with one anonymous AddRef that locks it until Destroy
PGMPVideoDecoderParent* pvdp = SendPGMPVideoDecoderConstructor();
if (!pvdp) {
return NS_ERROR_FAILURE;
}
GMPVideoDecoderParent *vdp = static_cast<GMPVideoDecoderParent*>(pvdp);
// This addref corresponds to the Proxy pointer the consumer is returned.
// It's dropped by calling Close() on the interface.
NS_ADDREF(vdp);
*aGMPVD = vdp;
mVideoDecoders.AppendElement(vdp);
return NS_OK;
}
nsresult
GMPParent::GetGMPVideoEncoder(GMPVideoEncoderParent** aGMPVE)
{
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
if (!EnsureProcessLoaded()) {
return NS_ERROR_FAILURE;
}
// returned with one anonymous AddRef that locks it until Destroy
PGMPVideoEncoderParent* pvep = SendPGMPVideoEncoderConstructor();
if (!pvep) {
return NS_ERROR_FAILURE;
}
GMPVideoEncoderParent *vep = static_cast<GMPVideoEncoderParent*>(pvep);
// This addref corresponds to the Proxy pointer the consumer is returned.
// It's dropped by calling Close() on the interface.
NS_ADDREF(vep);
*aGMPVE = vep;
mVideoEncoders.AppendElement(vep);
return NS_OK;
}
#ifdef MOZ_CRASHREPORTER #ifdef MOZ_CRASHREPORTER
void void
GMPParent::WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes) GMPParent::WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes)
@ -724,70 +548,6 @@ GMPParent::DeallocPCrashReporterParent(PCrashReporterParent* aCrashReporter)
return true; return true;
} }
PGMPVideoDecoderParent*
GMPParent::AllocPGMPVideoDecoderParent()
{
GMPVideoDecoderParent* vdp = new GMPVideoDecoderParent(this);
NS_ADDREF(vdp);
return vdp;
}
bool
GMPParent::DeallocPGMPVideoDecoderParent(PGMPVideoDecoderParent* aActor)
{
GMPVideoDecoderParent* vdp = static_cast<GMPVideoDecoderParent*>(aActor);
NS_RELEASE(vdp);
return true;
}
PGMPVideoEncoderParent*
GMPParent::AllocPGMPVideoEncoderParent()
{
GMPVideoEncoderParent* vep = new GMPVideoEncoderParent(this);
NS_ADDREF(vep);
return vep;
}
bool
GMPParent::DeallocPGMPVideoEncoderParent(PGMPVideoEncoderParent* aActor)
{
GMPVideoEncoderParent* vep = static_cast<GMPVideoEncoderParent*>(aActor);
NS_RELEASE(vep);
return true;
}
PGMPDecryptorParent*
GMPParent::AllocPGMPDecryptorParent()
{
GMPDecryptorParent* ksp = new GMPDecryptorParent(this);
NS_ADDREF(ksp);
return ksp;
}
bool
GMPParent::DeallocPGMPDecryptorParent(PGMPDecryptorParent* aActor)
{
GMPDecryptorParent* ksp = static_cast<GMPDecryptorParent*>(aActor);
NS_RELEASE(ksp);
return true;
}
PGMPAudioDecoderParent*
GMPParent::AllocPGMPAudioDecoderParent()
{
GMPAudioDecoderParent* vdp = new GMPAudioDecoderParent(this);
NS_ADDREF(vdp);
return vdp;
}
bool
GMPParent::DeallocPGMPAudioDecoderParent(PGMPAudioDecoderParent* aActor)
{
GMPAudioDecoderParent* vdp = static_cast<GMPAudioDecoderParent*>(aActor);
NS_RELEASE(vdp);
return true;
}
PGMPStorageParent* PGMPStorageParent*
GMPParent::AllocPGMPStorageParent() GMPParent::AllocPGMPStorageParent()
{ {
@ -1024,7 +784,7 @@ GMPParent::GetVersion() const
return mVersion; return mVersion;
} }
const nsACString& const nsCString&
GMPParent::GetPluginId() const GMPParent::GetPluginId() const
{ {
return mPluginId; return mPluginId;
@ -1053,6 +813,107 @@ GMPParent::RecvAsyncShutdownComplete()
return true; return true;
} }
class RunCreateContentParentCallbacks : public nsRunnable
{
public:
explicit RunCreateContentParentCallbacks(GMPContentParent* aGMPContentParent)
: mGMPContentParent(aGMPContentParent)
{
}
void TakeCallbacks(nsTArray<UniquePtr<GetGMPContentParentCallback>>& aCallbacks)
{
mCallbacks.SwapElements(aCallbacks);
}
NS_IMETHOD
Run()
{
for (uint32_t i = 0, length = mCallbacks.Length(); i < length; ++i) {
mCallbacks[i]->Done(mGMPContentParent);
}
return NS_OK;
}
private:
nsRefPtr<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);
nsRefPtr<RunCreateContentParentCallbacks> runCallbacks =
new RunCreateContentParentCallbacks(mGMPContentParent);
runCallbacks->TakeCallbacks(mCallbacks);
NS_DispatchToCurrentThread(runCallbacks);
MOZ_ASSERT(mCallbacks.IsEmpty());
return mGMPContentParent;
}
bool
GMPParent::GetGMPContentParent(UniquePtr<GetGMPContentParentCallback>&& aCallback)
{
LOGD("%s %p", __FUNCTION__, this);
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
if (mGMPContentParent) {
aCallback->Done(mGMPContentParent);
} else {
mCallbacks.AppendElement(Move(aCallback));
// 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
// 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 (!EnsureProcessLoaded() || !PGMPContent::Open(this)) {
return false;
}
// 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());
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 gmp
} // namespace mozilla } // namespace mozilla

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

@ -7,7 +7,7 @@
#define GMPParent_h_ #define GMPParent_h_
#include "GMPProcessParent.h" #include "GMPProcessParent.h"
#include "GMPService.h" #include "GMPServiceParent.h"
#include "GMPAudioDecoderParent.h" #include "GMPAudioDecoderParent.h"
#include "GMPDecryptorParent.h" #include "GMPDecryptorParent.h"
#include "GMPVideoDecoderParent.h" #include "GMPVideoDecoderParent.h"
@ -54,15 +54,30 @@ enum GMPState {
GMPStateClosing GMPStateClosing
}; };
class GMPParent final : public PGMPParent, class GMPContentParent;
public GMPSharedMem
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: public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(GMPParent) NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(GMPParent)
GMPParent(); GMPParent();
nsresult Init(GeckoMediaPluginService *aService, nsIFile* aPluginDir); nsresult Init(GeckoMediaPluginServiceParent* aService, nsIFile* aPluginDir);
nsresult CloneFrom(const GMPParent* aOther); nsresult CloneFrom(const GMPParent* aOther);
void Crash(); void Crash();
@ -84,18 +99,6 @@ public:
bool SupportsAPI(const nsCString& aAPI, const nsCString& aTag); bool SupportsAPI(const nsCString& aAPI, const nsCString& aTag);
nsresult GetGMPVideoDecoder(GMPVideoDecoderParent** aGMPVD);
void VideoDecoderDestroyed(GMPVideoDecoderParent* aDecoder);
nsresult GetGMPVideoEncoder(GMPVideoEncoderParent** aGMPVE);
void VideoEncoderDestroyed(GMPVideoEncoderParent* aEncoder);
nsresult GetGMPDecryptor(GMPDecryptorParent** aGMPKS);
void DecryptorDestroyed(GMPDecryptorParent* aSession);
nsresult GetGMPAudioDecoder(GMPAudioDecoderParent** aGMPAD);
void AudioDecoderDestroyed(GMPAudioDecoderParent* aDecoder);
GMPState State() const; GMPState State() const;
nsIThread* GMPThread(); nsIThread* GMPThread();
@ -117,7 +120,7 @@ public:
const nsCString& GetDisplayName() const; const nsCString& GetDisplayName() const;
const nsCString& GetVersion() const; const nsCString& GetVersion() const;
const nsACString& GetPluginId() const; const nsCString& GetPluginId() const;
// Returns true if a plugin can be or is being used across multiple NodeIds. // Returns true if a plugin can be or is being used across multiple NodeIds.
bool CanBeSharedCrossNodeIds() const; bool CanBeSharedCrossNodeIds() const;
@ -131,14 +134,18 @@ public:
return nsCOMPtr<nsIFile>(mDirectory).forget(); return nsCOMPtr<nsIFile>(mDirectory).forget();
} }
// GMPSharedMem
virtual void CheckThread() override;
void AbortAsyncShutdown(); void AbortAsyncShutdown();
bool GetGMPContentParent(UniquePtr<GetGMPContentParentCallback>&& aCallback);
already_AddRefed<GMPContentParent> ForgetGMPContentParent();
bool EnsureProcessLoaded(base::ProcessId* aID);
bool Bridge(GMPServiceParent* aGMPServiceParent);
private: private:
~GMPParent(); ~GMPParent();
nsRefPtr<GeckoMediaPluginService> mService; nsRefPtr<GeckoMediaPluginServiceParent> mService;
bool EnsureProcessLoaded(); bool EnsureProcessLoaded();
nsresult ReadGMPMetaData(); nsresult ReadGMPMetaData();
#ifdef MOZ_CRASHREPORTER #ifdef MOZ_CRASHREPORTER
@ -150,22 +157,13 @@ private:
virtual PCrashReporterParent* AllocPCrashReporterParent(const NativeThreadId& aThread) override; virtual PCrashReporterParent* AllocPCrashReporterParent(const NativeThreadId& aThread) override;
virtual bool DeallocPCrashReporterParent(PCrashReporterParent* aCrashReporter) override; virtual bool DeallocPCrashReporterParent(PCrashReporterParent* aCrashReporter) override;
virtual PGMPVideoDecoderParent* AllocPGMPVideoDecoderParent() override;
virtual bool DeallocPGMPVideoDecoderParent(PGMPVideoDecoderParent* aActor) override;
virtual PGMPVideoEncoderParent* AllocPGMPVideoEncoderParent() override;
virtual bool DeallocPGMPVideoEncoderParent(PGMPVideoEncoderParent* aActor) override;
virtual PGMPDecryptorParent* AllocPGMPDecryptorParent() override;
virtual bool DeallocPGMPDecryptorParent(PGMPDecryptorParent* aActor) override;
virtual PGMPAudioDecoderParent* AllocPGMPAudioDecoderParent() override;
virtual bool DeallocPGMPAudioDecoderParent(PGMPAudioDecoderParent* aActor) override;
virtual bool RecvPGMPStorageConstructor(PGMPStorageParent* actor) override; virtual bool RecvPGMPStorageConstructor(PGMPStorageParent* actor) override;
virtual PGMPStorageParent* AllocPGMPStorageParent() override; virtual PGMPStorageParent* AllocPGMPStorageParent() override;
virtual bool DeallocPGMPStorageParent(PGMPStorageParent* aActor) override; virtual bool DeallocPGMPStorageParent(PGMPStorageParent* aActor) override;
virtual PGMPContentParent* AllocPGMPContentParent(Transport* aTransport,
ProcessId aOtherPid) override;
virtual bool RecvPGMPTimerConstructor(PGMPTimerParent* actor) override; virtual bool RecvPGMPTimerConstructor(PGMPTimerParent* actor) override;
virtual PGMPTimerParent* AllocPGMPTimerParent() override; virtual PGMPTimerParent* AllocPGMPTimerParent() override;
virtual bool DeallocPGMPTimerParent(PGMPTimerParent* aActor) override; virtual bool DeallocPGMPTimerParent(PGMPTimerParent* aActor) override;
@ -173,6 +171,13 @@ private:
virtual bool RecvAsyncShutdownComplete() override; virtual bool RecvAsyncShutdownComplete() override;
virtual bool RecvAsyncShutdownRequired() override; virtual bool RecvAsyncShutdownRequired() override;
virtual bool RecvPGMPContentChildDestroyed() override;
bool IsUsed()
{
return mGMPContentChildCount > 0;
}
nsresult EnsureAsyncShutdownTimeoutSet(); nsresult EnsureAsyncShutdownTimeoutSet();
GMPState mState; GMPState mState;
@ -187,10 +192,6 @@ private:
bool mDeleteProcessOnlyOnUnload; bool mDeleteProcessOnlyOnUnload;
bool mAbnormalShutdownInProgress; bool mAbnormalShutdownInProgress;
nsTArray<nsRefPtr<GMPVideoDecoderParent>> mVideoDecoders;
nsTArray<nsRefPtr<GMPVideoEncoderParent>> mVideoEncoders;
nsTArray<nsRefPtr<GMPDecryptorParent>> mDecryptors;
nsTArray<nsRefPtr<GMPAudioDecoderParent>> mAudioDecoders;
nsTArray<nsRefPtr<GMPTimerParent>> mTimers; nsTArray<nsRefPtr<GMPTimerParent>> mTimers;
nsTArray<nsRefPtr<GMPStorageParent>> mStorage; nsTArray<nsRefPtr<GMPStorageParent>> mStorage;
nsCOMPtr<nsIThread> mGMPThread; nsCOMPtr<nsIThread> mGMPThread;
@ -198,6 +199,11 @@ private:
// NodeId the plugin is assigned to, or empty if the the plugin is not // NodeId the plugin is assigned to, or empty if the the plugin is not
// assigned to a NodeId. // assigned to a NodeId.
nsAutoCString mNodeId; nsAutoCString mNodeId;
// This is used for GMP content in the parent, there may be more of these in
// the content processes.
nsRefPtr<GMPContentParent> mGMPContentParent;
nsTArray<UniquePtr<GetGMPContentParentCallback>> mCallbacks;
uint32_t mGMPContentChildCount;
bool mAsyncShutdownRequired; bool mAsyncShutdownRequired;
bool mAsyncShutdownInProgress; bool mAsyncShutdownInProgress;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -15,37 +15,49 @@
#include "nsString.h" #include "nsString.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsIThread.h" #include "nsIThread.h"
#include "nsThreadUtils.h"
#include "nsITimer.h"
#include "nsClassHashtable.h"
#include "nsDataHashtable.h"
#include "mozilla/Atomics.h"
template <class> struct already_AddRefed; template <class> struct already_AddRefed;
namespace mozilla { namespace mozilla {
extern PRLogModuleInfo* GetGMPLog();
namespace gmp { namespace gmp {
class GMPParent; class GetGMPContentParentCallback;
#define GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT 3000 #define GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT 3000
class GeckoMediaPluginService final : public mozIGeckoMediaPluginService class GeckoMediaPluginService : public mozIGeckoMediaPluginService
, public nsIObserver , public nsIObserver
{ {
public: public:
static already_AddRefed<GeckoMediaPluginService> GetGeckoMediaPluginService(); static already_AddRefed<GeckoMediaPluginService> GetGeckoMediaPluginService();
GeckoMediaPluginService(); virtual nsresult Init();
nsresult Init();
NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_MOZIGECKOMEDIAPLUGINSERVICE
NS_DECL_NSIOBSERVER
void AsyncShutdownNeeded(GMPParent* aParent); // mozIGeckoMediaPluginService
void AsyncShutdownComplete(GMPParent* aParent); NS_IMETHOD GetThread(nsIThread** aThread) override;
void AbortAsyncShutdown(); NS_IMETHOD HasPluginForAPI(const nsACString& aAPI, nsTArray<nsCString>* aTags,
bool *aRetVal) override;
NS_IMETHOD GetGMPVideoDecoder(nsTArray<nsCString>* aTags,
const nsACString& aNodeId,
UniquePtr<GetGMPVideoDecoderCallback>&& aCallback)
override;
NS_IMETHOD GetGMPVideoEncoder(nsTArray<nsCString>* aTags,
const nsACString& aNodeId,
UniquePtr<GetGMPVideoEncoderCallback>&& aCallback)
override;
NS_IMETHOD GetGMPAudioDecoder(nsTArray<nsCString>* aTags,
const nsACString& aNodeId,
UniquePtr<GetGMPAudioDecoderCallback>&& aCallback)
override;
NS_IMETHOD GetGMPDecryptor(nsTArray<nsCString>* aTags,
const nsACString& aNodeId,
UniquePtr<GetGMPDecryptorCallback>&& aCallback)
override;
int32_t AsyncShutdownTimeoutMs(); int32_t AsyncShutdownTimeoutMs();
@ -77,120 +89,29 @@ public:
const nsACString& aPluginName, const nsACString& aPluginName,
const nsAString& aPluginDumpId); const nsAString& aPluginDumpId);
private: protected:
~GeckoMediaPluginService(); GeckoMediaPluginService();
virtual ~GeckoMediaPluginService();
virtual void InitializePlugins() = 0;
virtual bool GetContentParentFrom(const nsACString& aNodeId,
const nsCString& aAPI,
const nsTArray<nsCString>& aTags,
UniquePtr<GetGMPContentParentCallback>&& aCallback) = 0;
nsresult GMPDispatch(nsIRunnable* event, uint32_t flags = NS_DISPATCH_NORMAL); nsresult GMPDispatch(nsIRunnable* event, uint32_t flags = NS_DISPATCH_NORMAL);
void ShutdownGMPThread();
void ClearStorage();
GMPParent* SelectPluginForAPI(const nsACString& aNodeId,
const nsCString& aAPI,
const nsTArray<nsCString>& aTags);
GMPParent* FindPluginForAPIFrom(size_t aSearchStartIndex,
const nsCString& aAPI,
const nsTArray<nsCString>& aTags,
size_t* aOutPluginIndex);
void UnloadPlugins();
void CrashPlugins();
void SetAsyncShutdownComplete();
void LoadFromEnvironment();
void ProcessPossiblePlugin(nsIFile* aDir);
void AddOnGMPThread(const nsAString& aDirectory);
void RemoveOnGMPThread(const nsAString& aDirectory,
const bool aDeleteFromDisk);
nsresult SetAsyncShutdownTimeout();
struct DirectoryFilter {
virtual bool operator()(nsIFile* aPath) = 0;
~DirectoryFilter() {}
};
void ClearNodeIdAndPlugin(DirectoryFilter& aFilter);
void ForgetThisSiteOnGMPThread(const nsACString& aOrigin);
void ClearRecentHistoryOnGMPThread(PRTime aSince);
protected: protected:
friend class GMPParent; Mutex mMutex; // Protects mGMPThread and mGMPThreadShutdown and some members
void ReAddOnGMPThread(nsRefPtr<GMPParent>& aOld); // in derived classes.
private:
GMPParent* ClonePlugin(const GMPParent* aOriginal);
nsresult EnsurePluginsOnDiskScanned();
nsresult InitStorage();
class PathRunnable : public nsRunnable
{
public:
enum EOperation {
ADD,
REMOVE,
REMOVE_AND_DELETE_FROM_DISK,
};
PathRunnable(GeckoMediaPluginService* aService, const nsAString& aPath,
EOperation aOperation)
: mService(aService)
, mPath(aPath)
, mOperation(aOperation)
{ }
NS_DECL_NSIRUNNABLE
private:
nsRefPtr<GeckoMediaPluginService> mService;
nsString mPath;
EOperation mOperation;
};
Mutex mMutex; // Protects mGMPThread and mShuttingDown and mPlugins
nsTArray<nsRefPtr<GMPParent>> mPlugins;
nsCOMPtr<nsIThread> mGMPThread; nsCOMPtr<nsIThread> mGMPThread;
bool mShuttingDown; bool mGMPThreadShutdown;
bool mShuttingDownOnGMPThread; bool mShuttingDownOnGMPThread;
nsTArray<nsRefPtr<PluginCrashCallback>> mPluginCrashCallbacks; nsTArray<nsRefPtr<PluginCrashCallback>> mPluginCrashCallbacks;
// True if we've inspected MOZ_GMP_PATH on the GMP thread and loaded any
// plugins found there into mPlugins.
Atomic<bool> mScannedPluginOnDisk;
template<typename T>
class MainThreadOnly {
public:
MOZ_IMPLICIT MainThreadOnly(T aValue)
: mValue(aValue)
{}
operator T&() {
MOZ_ASSERT(NS_IsMainThread());
return mValue;
}
private:
T mValue;
};
MainThreadOnly<bool> mWaitingForPluginsAsyncShutdown;
nsTArray<nsRefPtr<GMPParent>> mAsyncShutdownPlugins; // GMP Thread only.
nsCOMPtr<nsIFile> mStorageBaseDir;
// Hashes of (origin,topLevelOrigin) to the node id for
// non-persistent sessions.
nsClassHashtable<nsUint32HashKey, nsCString> mTempNodeIds;
// Hashes node id to whether that node id is allowed to store data
// persistently on disk.
nsDataHashtable<nsCStringHashKey, bool> mPersistentStorageAllowed;
}; };
nsresult ReadSalt(nsIFile* aPath, nsACString& aOutData);
bool MatchOrigin(nsIFile* aPath, const nsACString& aOrigin);
} // namespace gmp } // namespace gmp
} // namespace mozilla } // namespace mozilla

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

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

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -0,0 +1,211 @@
/* -*- 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 GMPServiceParent_h_
#define GMPServiceParent_h_
#include "GMPService.h"
#include "mozilla/gmp/PGMPServiceParent.h"
#include "mozIGeckoMediaPluginChromeService.h"
#include "nsClassHashtable.h"
#include "nsDataHashtable.h"
#include "mozilla/Atomics.h"
#include "nsThreadUtils.h"
template <class> struct already_AddRefed;
namespace mozilla {
namespace gmp {
class GMPParent;
#define GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT 3000
class GeckoMediaPluginServiceParent final : public GeckoMediaPluginService
, public mozIGeckoMediaPluginChromeService
{
public:
static already_AddRefed<GeckoMediaPluginServiceParent> GetSingleton();
GeckoMediaPluginServiceParent();
virtual nsresult Init() override;
NS_DECL_ISUPPORTS_INHERITED
// mozIGeckoMediaPluginService
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_MOZIGECKOMEDIAPLUGINCHROMESERVICE
NS_DECL_NSIOBSERVER
void AsyncShutdownNeeded(GMPParent* aParent);
void AsyncShutdownComplete(GMPParent* aParent);
void AbortAsyncShutdown();
int32_t AsyncShutdownTimeoutMs();
private:
friend class GMPServiceParent;
virtual ~GeckoMediaPluginServiceParent();
void ClearStorage();
GMPParent* SelectPluginForAPI(const nsACString& aNodeId,
const nsCString& aAPI,
const nsTArray<nsCString>& aTags);
GMPParent* FindPluginForAPIFrom(size_t aSearchStartIndex,
const nsCString& aAPI,
const nsTArray<nsCString>& aTags,
size_t* aOutPluginIndex);
nsresult GetNodeId(const nsAString& aOrigin, const nsAString& aTopLevelOrigin,
bool aInPrivateBrowsing, nsACString& aOutId);
void UnloadPlugins();
void CrashPlugins();
void SetAsyncShutdownComplete();
void LoadFromEnvironment();
void ProcessPossiblePlugin(nsIFile* aDir);
void AddOnGMPThread(const nsAString& aDirectory);
void RemoveOnGMPThread(const nsAString& aDirectory,
const bool aDeleteFromDisk);
nsresult SetAsyncShutdownTimeout();
struct DirectoryFilter {
virtual bool operator()(nsIFile* aPath) = 0;
~DirectoryFilter() {}
};
void ClearNodeIdAndPlugin(DirectoryFilter& aFilter);
void ForgetThisSiteOnGMPThread(const nsACString& aOrigin);
void ClearRecentHistoryOnGMPThread(PRTime aSince);
protected:
friend class GMPParent;
void ReAddOnGMPThread(nsRefPtr<GMPParent>& aOld);
virtual void InitializePlugins() override;
virtual bool GetContentParentFrom(const nsACString& aNodeId,
const nsCString& aAPI,
const nsTArray<nsCString>& aTags,
UniquePtr<GetGMPContentParentCallback>&& aCallback)
override;
private:
GMPParent* ClonePlugin(const GMPParent* aOriginal);
nsresult EnsurePluginsOnDiskScanned();
nsresult InitStorage();
class PathRunnable : public nsRunnable
{
public:
enum EOperation {
ADD,
REMOVE,
REMOVE_AND_DELETE_FROM_DISK,
};
PathRunnable(GeckoMediaPluginServiceParent* aService, const nsAString& aPath,
EOperation aOperation)
: mService(aService)
, mPath(aPath)
, mOperation(aOperation)
{ }
NS_DECL_NSIRUNNABLE
private:
nsRefPtr<GeckoMediaPluginServiceParent> mService;
nsString mPath;
EOperation mOperation;
};
// Protected by mMutex from the base class.
nsTArray<nsRefPtr<GMPParent>> mPlugins;
bool mShuttingDown;
// True if we've inspected MOZ_GMP_PATH on the GMP thread and loaded any
// plugins found there into mPlugins.
Atomic<bool> mScannedPluginOnDisk;
template<typename T>
class MainThreadOnly {
public:
MOZ_IMPLICIT MainThreadOnly(T aValue)
: mValue(aValue)
{}
operator T&() {
MOZ_ASSERT(NS_IsMainThread());
return mValue;
}
private:
T mValue;
};
MainThreadOnly<bool> mWaitingForPluginsAsyncShutdown;
nsTArray<nsRefPtr<GMPParent>> mAsyncShutdownPlugins; // GMP Thread only.
nsCOMPtr<nsIFile> mStorageBaseDir;
// Hashes of (origin,topLevelOrigin) to the node id for
// non-persistent sessions.
nsClassHashtable<nsUint32HashKey, nsCString> mTempNodeIds;
// Hashes node id to whether that node id is allowed to store data
// persistently on disk.
nsDataHashtable<nsCStringHashKey, bool> mPersistentStorageAllowed;
};
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
#endif // GMPServiceParent_h_

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

@ -52,7 +52,7 @@ GetGMPStorageDir(nsIFile** aTempDir, const nsCString& aNodeId)
return NS_ERROR_INVALID_ARG; return NS_ERROR_INVALID_ARG;
} }
nsCOMPtr<mozIGeckoMediaPluginService> mps = nsCOMPtr<mozIGeckoMediaPluginChromeService> mps =
do_GetService("@mozilla.org/gecko-media-plugin-service;1"); do_GetService("@mozilla.org/gecko-media-plugin-service;1");
if (NS_WARN_IF(!mps)) { if (NS_WARN_IF(!mps)) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
@ -468,7 +468,7 @@ GMPStorageParent::Init()
if (NS_WARN_IF(mNodeId.IsEmpty())) { if (NS_WARN_IF(mNodeId.IsEmpty())) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
nsCOMPtr<mozIGeckoMediaPluginService> mps = nsCOMPtr<mozIGeckoMediaPluginChromeService> mps =
do_GetService("@mozilla.org/gecko-media-plugin-service;1"); do_GetService("@mozilla.org/gecko-media-plugin-service;1");
if (NS_WARN_IF(!mps)) { if (NS_WARN_IF(!mps)) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;

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

@ -5,7 +5,7 @@
#include "GMPVideoDecoderChild.h" #include "GMPVideoDecoderChild.h"
#include "GMPVideoi420FrameImpl.h" #include "GMPVideoi420FrameImpl.h"
#include "GMPChild.h" #include "GMPContentChild.h"
#include <stdio.h> #include <stdio.h>
#include "mozilla/unused.h" #include "mozilla/unused.h"
#include "GMPVideoEncodedFrameImpl.h" #include "GMPVideoEncodedFrameImpl.h"
@ -13,7 +13,7 @@
namespace mozilla { namespace mozilla {
namespace gmp { namespace gmp {
GMPVideoDecoderChild::GMPVideoDecoderChild(GMPChild* aPlugin) GMPVideoDecoderChild::GMPVideoDecoderChild(GMPContentChild* aPlugin)
: GMPSharedMemManager(aPlugin), : GMPSharedMemManager(aPlugin),
mPlugin(aPlugin), mPlugin(aPlugin),
mVideoDecoder(nullptr), mVideoDecoder(nullptr),

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

@ -16,14 +16,14 @@
namespace mozilla { namespace mozilla {
namespace gmp { namespace gmp {
class GMPChild; class GMPContentChild;
class GMPVideoDecoderChild : public PGMPVideoDecoderChild, class GMPVideoDecoderChild : public PGMPVideoDecoderChild,
public GMPVideoDecoderCallback, public GMPVideoDecoderCallback,
public GMPSharedMemManager public GMPSharedMemManager
{ {
public: public:
explicit GMPVideoDecoderChild(GMPChild* aPlugin); explicit GMPVideoDecoderChild(GMPContentChild* aPlugin);
virtual ~GMPVideoDecoderChild(); virtual ~GMPVideoDecoderChild();
void Init(GMPVideoDecoder* aDecoder); void Init(GMPVideoDecoder* aDecoder);
@ -74,7 +74,7 @@ private:
virtual bool RecvDrain() override; virtual bool RecvDrain() override;
virtual bool RecvDecodingComplete() override; virtual bool RecvDecodingComplete() override;
GMPChild* mPlugin; GMPContentChild* mPlugin;
GMPVideoDecoder* mVideoDecoder; GMPVideoDecoder* mVideoDecoder;
GMPVideoHostImpl mVideoHost; GMPVideoHostImpl mVideoHost;
}; };

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

@ -11,7 +11,7 @@
#include "GMPUtils.h" #include "GMPUtils.h"
#include "GMPVideoEncodedFrameImpl.h" #include "GMPVideoEncodedFrameImpl.h"
#include "GMPVideoi420FrameImpl.h" #include "GMPVideoi420FrameImpl.h"
#include "GMPParent.h" #include "GMPContentParent.h"
#include "GMPMessageUtils.h" #include "GMPMessageUtils.h"
#include "mozilla/gmp/GMPTypes.h" #include "mozilla/gmp/GMPTypes.h"
@ -43,7 +43,7 @@ namespace gmp {
// on Shutdown -> Dead // on Shutdown -> Dead
// Dead: mIsOpen == false // Dead: mIsOpen == false
GMPVideoDecoderParent::GMPVideoDecoderParent(GMPParent* aPlugin) GMPVideoDecoderParent::GMPVideoDecoderParent(GMPContentParent* aPlugin)
: GMPSharedMemManager(aPlugin) : GMPSharedMemManager(aPlugin)
, mIsOpen(false) , mIsOpen(false)
, mShuttingDown(false) , mShuttingDown(false)
@ -335,6 +335,13 @@ GMPVideoDecoderParent::RecvError(const GMPErr& aError)
return true; return true;
} }
bool
GMPVideoDecoderParent::RecvShutdown()
{
Shutdown();
return true;
}
bool bool
GMPVideoDecoderParent::RecvParentShmemForPool(Shmem&& aEncodedBuffer) GMPVideoDecoderParent::RecvParentShmemForPool(Shmem&& aEncodedBuffer)
{ {

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

@ -18,7 +18,7 @@
namespace mozilla { namespace mozilla {
namespace gmp { namespace gmp {
class GMPParent; class GMPContentParent;
class GMPVideoDecoderParent final : public PGMPVideoDecoderParent class GMPVideoDecoderParent final : public PGMPVideoDecoderParent
, public GMPVideoDecoderProxy , public GMPVideoDecoderProxy
@ -27,7 +27,7 @@ class GMPVideoDecoderParent final : public PGMPVideoDecoderParent
public: public:
NS_INLINE_DECL_REFCOUNTING(GMPVideoDecoderParent) NS_INLINE_DECL_REFCOUNTING(GMPVideoDecoderParent)
explicit GMPVideoDecoderParent(GMPParent *aPlugin); explicit GMPVideoDecoderParent(GMPContentParent *aPlugin);
GMPVideoHostImpl& Host(); GMPVideoHostImpl& Host();
nsresult Shutdown(); nsresult Shutdown();
@ -73,6 +73,7 @@ private:
virtual bool RecvDrainComplete() override; virtual bool RecvDrainComplete() override;
virtual bool RecvResetComplete() override; virtual bool RecvResetComplete() override;
virtual bool RecvError(const GMPErr& aError) override; virtual bool RecvError(const GMPErr& aError) override;
virtual bool RecvShutdown() override;
virtual bool RecvParentShmemForPool(Shmem&& aEncodedBuffer) override; virtual bool RecvParentShmemForPool(Shmem&& aEncodedBuffer) override;
virtual bool AnswerNeedShmem(const uint32_t& aFrameBufferSize, virtual bool AnswerNeedShmem(const uint32_t& aFrameBufferSize,
Shmem* aMem) override; Shmem* aMem) override;
@ -80,7 +81,7 @@ private:
bool mIsOpen; bool mIsOpen;
bool mShuttingDown; bool mShuttingDown;
nsRefPtr<GMPParent> mPlugin; nsRefPtr<GMPContentParent> mPlugin;
GMPVideoDecoderCallbackProxy* mCallback; GMPVideoDecoderCallbackProxy* mCallback;
GMPVideoHostImpl mVideoHost; GMPVideoHostImpl mVideoHost;
}; };

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

@ -4,7 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GMPVideoEncoderChild.h" #include "GMPVideoEncoderChild.h"
#include "GMPChild.h" #include "GMPContentChild.h"
#include <stdio.h> #include <stdio.h>
#include "mozilla/unused.h" #include "mozilla/unused.h"
#include "GMPVideoEncodedFrameImpl.h" #include "GMPVideoEncodedFrameImpl.h"
@ -13,7 +13,7 @@
namespace mozilla { namespace mozilla {
namespace gmp { namespace gmp {
GMPVideoEncoderChild::GMPVideoEncoderChild(GMPChild* aPlugin) GMPVideoEncoderChild::GMPVideoEncoderChild(GMPContentChild* aPlugin)
: GMPSharedMemManager(aPlugin), : GMPSharedMemManager(aPlugin),
mPlugin(aPlugin), mPlugin(aPlugin),
mVideoEncoder(nullptr), mVideoEncoder(nullptr),

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

@ -15,14 +15,14 @@
namespace mozilla { namespace mozilla {
namespace gmp { namespace gmp {
class GMPChild; class GMPContentChild;
class GMPVideoEncoderChild : public PGMPVideoEncoderChild, class GMPVideoEncoderChild : public PGMPVideoEncoderChild,
public GMPVideoEncoderCallback, public GMPVideoEncoderCallback,
public GMPSharedMemManager public GMPSharedMemManager
{ {
public: public:
explicit GMPVideoEncoderChild(GMPChild* aPlugin); explicit GMPVideoEncoderChild(GMPContentChild* aPlugin);
virtual ~GMPVideoEncoderChild(); virtual ~GMPVideoEncoderChild();
void Init(GMPVideoEncoder* aEncoder); void Init(GMPVideoEncoder* aEncoder);
@ -73,7 +73,7 @@ private:
virtual bool RecvSetPeriodicKeyFrames(const bool& aEnable) override; virtual bool RecvSetPeriodicKeyFrames(const bool& aEnable) override;
virtual bool RecvEncodingComplete() override; virtual bool RecvEncodingComplete() override;
GMPChild* mPlugin; GMPContentChild* mPlugin;
GMPVideoEncoder* mVideoEncoder; GMPVideoEncoder* mVideoEncoder;
GMPVideoHostImpl mVideoHost; GMPVideoHostImpl mVideoHost;
}; };

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

@ -10,7 +10,7 @@
#include "mozilla/unused.h" #include "mozilla/unused.h"
#include "GMPMessageUtils.h" #include "GMPMessageUtils.h"
#include "nsAutoRef.h" #include "nsAutoRef.h"
#include "GMPParent.h" #include "GMPContentParent.h"
#include "mozilla/gmp/GMPTypes.h" #include "mozilla/gmp/GMPTypes.h"
#include "nsThread.h" #include "nsThread.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
@ -50,7 +50,7 @@ namespace gmp {
// on Shutdown -> Dead // on Shutdown -> Dead
// Dead: mIsOpen == false // Dead: mIsOpen == false
GMPVideoEncoderParent::GMPVideoEncoderParent(GMPParent *aPlugin) GMPVideoEncoderParent::GMPVideoEncoderParent(GMPContentParent *aPlugin)
: GMPSharedMemManager(aPlugin), : GMPSharedMemManager(aPlugin),
mIsOpen(false), mIsOpen(false),
mShuttingDown(false), mShuttingDown(false),
@ -320,6 +320,13 @@ GMPVideoEncoderParent::RecvError(const GMPErr& aError)
return true; return true;
} }
bool
GMPVideoEncoderParent::RecvShutdown()
{
Shutdown();
return true;
}
bool bool
GMPVideoEncoderParent::RecvParentShmemForPool(Shmem&& aFrameBuffer) GMPVideoEncoderParent::RecvParentShmemForPool(Shmem&& aFrameBuffer)
{ {

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

@ -18,7 +18,7 @@
namespace mozilla { namespace mozilla {
namespace gmp { namespace gmp {
class GMPParent; class GMPContentParent;
class GMPVideoEncoderParent : public GMPVideoEncoderProxy, class GMPVideoEncoderParent : public GMPVideoEncoderProxy,
public PGMPVideoEncoderParent, public PGMPVideoEncoderParent,
@ -27,7 +27,7 @@ class GMPVideoEncoderParent : public GMPVideoEncoderProxy,
public: public:
NS_INLINE_DECL_REFCOUNTING(GMPVideoEncoderParent) NS_INLINE_DECL_REFCOUNTING(GMPVideoEncoderParent)
explicit GMPVideoEncoderParent(GMPParent *aPlugin); explicit GMPVideoEncoderParent(GMPContentParent *aPlugin);
GMPVideoHostImpl& Host(); GMPVideoHostImpl& Host();
void Shutdown(); void Shutdown();
@ -69,6 +69,7 @@ private:
virtual bool RecvEncoded(const GMPVideoEncodedFrameData& aEncodedFrame, virtual bool RecvEncoded(const GMPVideoEncodedFrameData& aEncodedFrame,
InfallibleTArray<uint8_t>&& aCodecSpecificInfo) override; InfallibleTArray<uint8_t>&& aCodecSpecificInfo) override;
virtual bool RecvError(const GMPErr& aError) override; virtual bool RecvError(const GMPErr& aError) override;
virtual bool RecvShutdown() override;
virtual bool RecvParentShmemForPool(Shmem&& aFrameBuffer) override; virtual bool RecvParentShmemForPool(Shmem&& aFrameBuffer) override;
virtual bool AnswerNeedShmem(const uint32_t& aEncodedBufferSize, virtual bool AnswerNeedShmem(const uint32_t& aEncodedBufferSize,
Shmem* aMem) override; Shmem* aMem) override;
@ -76,7 +77,7 @@ private:
bool mIsOpen; bool mIsOpen;
bool mShuttingDown; bool mShuttingDown;
nsRefPtr<GMPParent> mPlugin; nsRefPtr<GMPContentParent> mPlugin;
GMPVideoEncoderCallbackProxy* mCallback; GMPVideoEncoderCallbackProxy* mCallback;
GMPVideoHostImpl mVideoHost; GMPVideoHostImpl mVideoHost;
nsCOMPtr<nsIThread> mEncodedThread; nsCOMPtr<nsIThread> mEncodedThread;

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

@ -3,11 +3,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PGMPVideoDecoder;
include protocol PGMPVideoEncoder;
include protocol PCrashReporter; include protocol PCrashReporter;
include protocol PGMPDecryptor; include protocol PGMPContent;
include protocol PGMPAudioDecoder;
include protocol PGMPTimer; include protocol PGMPTimer;
include protocol PGMPStorage; include protocol PGMPStorage;
@ -18,10 +15,8 @@ namespace gmp {
intr protocol PGMP intr protocol PGMP
{ {
manages PGMPAudioDecoder; parent opens PGMPContent;
manages PGMPDecryptor;
manages PGMPVideoDecoder;
manages PGMPVideoEncoder;
manages PCrashReporter; manages PCrashReporter;
manages PGMPTimer; manages PGMPTimer;
manages PGMPStorage; manages PGMPStorage;
@ -31,19 +26,17 @@ parent:
async PGMPTimer(); async PGMPTimer();
async PGMPStorage(); async PGMPStorage();
async PGMPContentChildDestroyed();
async AsyncShutdownComplete(); async AsyncShutdownComplete();
async AsyncShutdownRequired(); async AsyncShutdownRequired();
child: child:
async PGMPAudioDecoder();
async PGMPDecryptor();
async PGMPVideoDecoder();
async PGMPVideoEncoder();
async SetNodeId(nsCString nodeId);
async StartPlugin();
async BeginAsyncShutdown(); async BeginAsyncShutdown();
async CrashPluginNow(); async CrashPluginNow();
async StartPlugin();
async SetNodeId(nsCString nodeId);
async CloseActive();
}; };
} // namespace gmp } // namespace gmp

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

@ -3,7 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PGMP; include protocol PGMPContent;
include GMPTypes; include GMPTypes;
using GMPCodecSpecificInfo from "gmp-audio-codec.h"; using GMPCodecSpecificInfo from "gmp-audio-codec.h";
@ -16,7 +16,7 @@ namespace gmp {
async protocol PGMPAudioDecoder async protocol PGMPAudioDecoder
{ {
manager PGMP; manager PGMPContent;
child: child:
InitDecode(GMPAudioCodecData aCodecSettings); InitDecode(GMPAudioCodecData aCodecSettings);
Decode(GMPAudioEncodedSampleData aInput); Decode(GMPAudioEncodedSampleData aInput);
@ -30,6 +30,7 @@ parent:
DrainComplete(); DrainComplete();
ResetComplete(); ResetComplete();
Error(GMPErr aErr); Error(GMPErr aErr);
async Shutdown();
}; };
} // namespace gmp } // namespace gmp

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

@ -0,0 +1,33 @@
/* -*- 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;
include protocol PGMPService;
include protocol PGMPVideoDecoder;
include protocol PGMPVideoEncoder;
include protocol PGMPDecryptor;
include protocol PGMPAudioDecoder;
namespace mozilla {
namespace gmp {
intr protocol PGMPContent
{
bridges PGMPService, PGMP;
manages PGMPAudioDecoder;
manages PGMPDecryptor;
manages PGMPVideoDecoder;
manages PGMPVideoEncoder;
child:
async PGMPAudioDecoder();
async PGMPDecryptor();
async PGMPVideoDecoder();
async PGMPVideoEncoder();
};
} // namespace gmp
} // namespace mozilla

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

@ -3,7 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PGMP; include protocol PGMPContent;
include GMPTypes; include GMPTypes;
using GMPSessionMessageType from "gmp-decryption.h"; using GMPSessionMessageType from "gmp-decryption.h";
@ -17,7 +17,7 @@ namespace gmp {
async protocol PGMPDecryptor async protocol PGMPDecryptor
{ {
manager PGMP; manager PGMPContent;
child: child:
Init(); Init();
@ -84,6 +84,8 @@ parent:
SetCaps(uint64_t aCaps); SetCaps(uint64_t aCaps);
Decrypted(uint32_t aId, GMPErr aResult, uint8_t[] aBuffer); Decrypted(uint32_t aId, GMPErr aResult, uint8_t[] aBuffer);
async Shutdown();
}; };
} // namespace gmp } // namespace gmp

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

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

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

@ -3,7 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PGMP; include protocol PGMPContent;
include GMPTypes; include GMPTypes;
using GMPVideoCodec from "gmp-video-codec.h"; using GMPVideoCodec from "gmp-video-codec.h";
@ -16,7 +16,7 @@ namespace gmp {
intr protocol PGMPVideoDecoder intr protocol PGMPVideoDecoder
{ {
manager PGMP; manager PGMPContent;
child: child:
async InitDecode(GMPVideoCodec aCodecSettings, async InitDecode(GMPVideoCodec aCodecSettings,
uint8_t[] aCodecSpecific, uint8_t[] aCodecSpecific,
@ -39,6 +39,7 @@ parent:
async DrainComplete(); async DrainComplete();
async ResetComplete(); async ResetComplete();
async Error(GMPErr aErr); async Error(GMPErr aErr);
async Shutdown();
async ParentShmemForPool(Shmem aEncodedBuffer); async ParentShmemForPool(Shmem aEncodedBuffer);
// MUST be intr - if sync and we create a new Shmem, when the returned // MUST be intr - if sync and we create a new Shmem, when the returned
// Shmem is received in the Child it will fail to Deserialize // Shmem is received in the Child it will fail to Deserialize

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

@ -3,7 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PGMP; include protocol PGMPContent;
include GMPTypes; include GMPTypes;
using GMPVideoCodec from "gmp-video-codec.h"; using GMPVideoCodec from "gmp-video-codec.h";
@ -17,7 +17,7 @@ namespace gmp {
intr protocol PGMPVideoEncoder intr protocol PGMPVideoEncoder
{ {
manager PGMP; manager PGMPContent;
child: child:
async InitEncode(GMPVideoCodec aCodecSettings, async InitEncode(GMPVideoCodec aCodecSettings,
uint8_t[] aCodecSpecific, uint8_t[] aCodecSpecific,
@ -37,6 +37,7 @@ parent:
async Encoded(GMPVideoEncodedFrameData aEncodedFrame, async Encoded(GMPVideoEncodedFrameData aEncodedFrame,
uint8_t[] aCodecSpecificInfo); uint8_t[] aCodecSpecificInfo);
async Error(GMPErr aErr); async Error(GMPErr aErr);
async Shutdown();
async ParentShmemForPool(Shmem aFrameBuffer); async ParentShmemForPool(Shmem aFrameBuffer);
// MUST be intr - if sync and we create a new Shmem, when the returned // MUST be intr - if sync and we create a new Shmem, when the returned
// Shmem is received in the Child it will fail to Deserialize // Shmem is received in the Child it will fail to Deserialize

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

@ -7,6 +7,7 @@
XPIDL_MODULE = 'content_geckomediaplugins' XPIDL_MODULE = 'content_geckomediaplugins'
XPIDL_SOURCES += [ XPIDL_SOURCES += [
'mozIGeckoMediaPluginChromeService.idl',
'mozIGeckoMediaPluginService.idl', 'mozIGeckoMediaPluginService.idl',
] ]
@ -35,6 +36,8 @@ EXPORTS += [
'GMPAudioHost.h', 'GMPAudioHost.h',
'GMPCallbackBase.h', 'GMPCallbackBase.h',
'GMPChild.h', 'GMPChild.h',
'GMPContentChild.h',
'GMPContentParent.h',
'GMPDecryptorChild.h', 'GMPDecryptorChild.h',
'GMPDecryptorParent.h', 'GMPDecryptorParent.h',
'GMPDecryptorProxy.h', 'GMPDecryptorProxy.h',
@ -46,6 +49,8 @@ EXPORTS += [
'GMPProcessChild.h', 'GMPProcessChild.h',
'GMPProcessParent.h', 'GMPProcessParent.h',
'GMPService.h', 'GMPService.h',
'GMPServiceChild.h',
'GMPServiceParent.h',
'GMPSharedMemManager.h', 'GMPSharedMemManager.h',
'GMPStorageChild.h', 'GMPStorageChild.h',
'GMPStorageParent.h', 'GMPStorageParent.h',
@ -76,6 +81,8 @@ UNIFIED_SOURCES += [
'GMPAudioDecoderParent.cpp', 'GMPAudioDecoderParent.cpp',
'GMPAudioHost.cpp', 'GMPAudioHost.cpp',
'GMPChild.cpp', 'GMPChild.cpp',
'GMPContentChild.cpp',
'GMPContentParent.cpp',
'GMPDecryptorChild.cpp', 'GMPDecryptorChild.cpp',
'GMPDecryptorParent.cpp', 'GMPDecryptorParent.cpp',
'GMPEncryptedBufferDataImpl.cpp', 'GMPEncryptedBufferDataImpl.cpp',
@ -84,6 +91,8 @@ UNIFIED_SOURCES += [
'GMPProcessChild.cpp', 'GMPProcessChild.cpp',
'GMPProcessParent.cpp', 'GMPProcessParent.cpp',
'GMPService.cpp', 'GMPService.cpp',
'GMPServiceChild.cpp',
'GMPServiceParent.cpp',
'GMPSharedMemManager.cpp', 'GMPSharedMemManager.cpp',
'GMPStorageChild.cpp', 'GMPStorageChild.cpp',
'GMPStorageParent.cpp', 'GMPStorageParent.cpp',
@ -108,7 +117,9 @@ IPDL_SOURCES += [
'GMPTypes.ipdlh', 'GMPTypes.ipdlh',
'PGMP.ipdl', 'PGMP.ipdl',
'PGMPAudioDecoder.ipdl', 'PGMPAudioDecoder.ipdl',
'PGMPContent.ipdl',
'PGMPDecryptor.ipdl', 'PGMPDecryptor.ipdl',
'PGMPService.ipdl',
'PGMPStorage.ipdl', 'PGMPStorage.ipdl',
'PGMPTimer.ipdl', 'PGMPTimer.ipdl',
'PGMPVideoDecoder.ipdl', 'PGMPVideoDecoder.ipdl',

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

@ -0,0 +1,47 @@
/* -*- 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 "nsISupports.idl"
#include "nsIFile.idl"
[scriptable, uuid(5878366c-73f6-486e-ad2f-9aca602864e4)]
interface mozIGeckoMediaPluginChromeService : nsISupports
{
/**
* Add a directory to scan for gecko media plugins.
* @note Main-thread API.
*/
void addPluginDirectory(in AString directory);
/**
* Remove a directory for gecko media plugins.
* @note Main-thread API.
*/
void removePluginDirectory(in AString directory);
/**
* Remove a directory for gecko media plugins and delete it from disk.
* @note Main-thread API.
*/
void removeAndDeletePluginDirectory(in AString directory);
/**
* Clears storage data associated with the origin.
*/
void forgetThisSite(in AString origin);
/**
* Returns true if the given node id is allowed to store things
* persistently on disk. Private Browsing and local content are not
* allowed to store persistent data.
*/
bool isPersistentStorageAllowed(in ACString nodeId);
/**
* Returns the directory to use as the base for storing data about GMPs.
*/
nsIFile getStorageDir();
};

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

@ -5,10 +5,9 @@
#include "nsISupports.idl" #include "nsISupports.idl"
#include "nsIThread.idl" #include "nsIThread.idl"
#include "nsIPrincipal.idl"
#include "nsIFile.idl"
%{C++ %{C++
#include "mozilla/UniquePtr.h"
#include "nsTArray.h" #include "nsTArray.h"
#include "nsStringGlue.h" #include "nsStringGlue.h"
class GMPAudioDecoderProxy; class GMPAudioDecoderProxy;
@ -16,17 +15,44 @@ class GMPDecryptorProxy;
class GMPVideoDecoderProxy; class GMPVideoDecoderProxy;
class GMPVideoEncoderProxy; class GMPVideoEncoderProxy;
class GMPVideoHost; class GMPVideoHost;
template<class T>
class GMPGetterCallback
{
public:
GMPGetterCallback() { MOZ_COUNT_CTOR(GMPGetterCallback<T>); }
virtual ~GMPGetterCallback() { MOZ_COUNT_DTOR(GMPGetterCallback<T>); }
virtual void Done(T*) = 0;
};
template<class T>
class GMPVideoGetterCallback
{
public:
GMPVideoGetterCallback() { MOZ_COUNT_CTOR(GMPVideoGetterCallback<T>); }
virtual ~GMPVideoGetterCallback() { MOZ_COUNT_DTOR(GMPVideoGetterCallback<T>); }
virtual void Done(T*, GMPVideoHost*) = 0;
};
typedef GMPGetterCallback<GMPDecryptorProxy> GetGMPDecryptorCallback;
typedef GMPGetterCallback<GMPAudioDecoderProxy> GetGMPAudioDecoderCallback;
typedef GMPVideoGetterCallback<GMPVideoDecoderProxy> GetGMPVideoDecoderCallback;
typedef GMPVideoGetterCallback<GMPVideoEncoderProxy> GetGMPVideoEncoderCallback;
class GetNodeIdCallback
{
public:
GetNodeIdCallback() { MOZ_COUNT_CTOR(GetNodeIdCallback); }
virtual ~GetNodeIdCallback() { MOZ_COUNT_DTOR(GetNodeIdCallback); }
virtual void Done(nsresult aResult, const nsACString& aNodeId) = 0;
};
%} %}
[ptr] native GMPVideoDecoderProxy(GMPVideoDecoderProxy);
[ptr] native GMPVideoEncoderProxy(GMPVideoEncoderProxy);
[ptr] native GMPVideoHost(GMPVideoHost);
[ptr] native MessageLoop(MessageLoop);
[ptr] native TagArray(nsTArray<nsCString>); [ptr] native TagArray(nsTArray<nsCString>);
[ptr] native GMPDecryptorProxy(GMPDecryptorProxy); native GetGMPDecryptorCallback(mozilla::UniquePtr<GetGMPDecryptorCallback>&&);
[ptr] native GMPAudioDecoderProxy(GMPAudioDecoderProxy); native GetGMPAudioDecoderCallback(mozilla::UniquePtr<GetGMPAudioDecoderCallback>&&);
native GetGMPVideoDecoderCallback(mozilla::UniquePtr<GetGMPVideoDecoderCallback>&&);
native GetGMPVideoEncoderCallback(mozilla::UniquePtr<GetGMPVideoEncoderCallback>&&);
native GetNodeIdCallback(mozilla::UniquePtr<GetNodeIdCallback>&&);
[scriptable, uuid(f71e6e57-5175-4cf3-8cc2-629273a75b67)] [scriptable, uuid(2b0c90e1-df89-4583-a123-8bdb2f5f7e39)]
interface mozIGeckoMediaPluginService : nsISupports interface mozIGeckoMediaPluginService : nsISupports
{ {
@ -47,84 +73,78 @@ interface mozIGeckoMediaPluginService : nsISupports
* Callable on any thread * Callable on any thread
*/ */
[noscript] [noscript]
ACString getPluginVersionForAPI(in ACString api, void getPluginVersionForAPI(in ACString api, in TagArray tags,
in TagArray tags); out boolean hasPlugin, out ACString version);
/** /**
* Get a video decoder that supports the specified tags. * Get a video decoder that supports the specified tags.
* The array of tags should at least contain a codec tag, and optionally * The array of tags should at least contain a codec tag, and optionally
* other tags such as for EME keysystem. * other tags such as for EME keysystem.
* Callable only on GMP thread. * Callable only on GMP thread.
* This is an asynchronous operation, the Done method of the callback object
* will be called on the GMP thread with the result (which might be null in
* the case of failure). This method always takes ownership of the callback
* object, but if this method returns an error then the Done method of the
* callback object will not be called at all.
*/ */
[noscript] [noscript]
GMPVideoDecoderProxy getGMPVideoDecoder(in TagArray tags, void getGMPVideoDecoder(in TagArray tags,
[optional] in ACString nodeId, [optional] in ACString nodeId,
out GMPVideoHost outVideoHost); in GetGMPVideoDecoderCallback callback);
/** /**
* Get a video encoder that supports the specified tags. * Get a video encoder that supports the specified tags.
* The array of tags should at least contain a codec tag, and optionally * The array of tags should at least contain a codec tag, and optionally
* other tags. * other tags.
* Callable only on GMP thread. * Callable only on GMP thread.
* This is an asynchronous operation, the Done method of the callback object
* will be called on the GMP thread with the result (which might be null in
* the case of failure). This method always takes ownership of the callback
* object, but if this method returns an error then the Done method of the
* callback object will not be called at all.
*/ */
[noscript] [noscript]
GMPVideoEncoderProxy getGMPVideoEncoder(in TagArray tags, void getGMPVideoEncoder(in TagArray tags,
[optional] in ACString nodeId, [optional] in ACString nodeId,
out GMPVideoHost outVideoHost); in GetGMPVideoEncoderCallback callback);
// Returns an audio decoder that supports the specified tags.
// The array of tags should at least contain a codec tag, and optionally
// other tags such as for EME keysystem.
// Callable only on GMP thread.
GMPAudioDecoderProxy getGMPAudioDecoder(in TagArray tags,
[optional] in ACString nodeId);
// Returns a decryption session manager that supports the specified tags.
// The array of tags should at least contain a key system tag, and optionally
// other tags.
// Callable only on GMP thread.
GMPDecryptorProxy getGMPDecryptor(in TagArray tags, in ACString nodeId);
/** /**
* Add a directory to scan for gecko media plugins. * Returns an audio decoder that supports the specified tags.
* @note Main-thread API. * The array of tags should at least contain a codec tag, and optionally
* other tags such as for EME keysystem.
* Callable only on GMP thread.
* This is an asynchronous operation, the Done method of the callback object
* will be called on the GMP thread with the result (which might be null in
* the case of failure). This method always takes ownership of the callback
* object, but if this method returns an error then the Done method of the
* callback object will not be called at all.
*/ */
void addPluginDirectory(in AString directory); [noscript]
void getGMPAudioDecoder(in TagArray tags,
[optional] in ACString nodeId,
in GetGMPAudioDecoderCallback callback);
/** /**
* Remove a directory for gecko media plugins. * Returns a decryption session manager that supports the specified tags.
* @note Main-thread API. * The array of tags should at least contain a key system tag, and optionally
* other tags.
* Callable only on GMP thread.
* This is an asynchronous operation, the Done method of the callback object
* will be called on the GMP thread with the result (which might be null in
* the case of failure). This method always takes ownership of the callback
* object, but if this method returns an error then the Done method of the
* callback object will not be called at all.
*/ */
void removePluginDirectory(in AString directory); [noscript]
void getGMPDecryptor(in TagArray tags, in ACString nodeId,
/** in GetGMPDecryptorCallback callback);
* Remove a directory for gecko media plugins and delete it from disk.
* @note Main-thread API.
*/
void removeAndDeletePluginDirectory(in AString directory);
/** /**
* Gets the NodeId for a (origin, urlbarOrigin, isInprivateBrowsing) tuple. * Gets the NodeId for a (origin, urlbarOrigin, isInprivateBrowsing) tuple.
*/ */
ACString getNodeId(in AString origin, [noscript]
in AString topLevelOrigin, void getNodeId(in AString origin,
in bool inPrivateBrowsingMode); in AString topLevelOrigin,
in bool inPrivateBrowsingMode,
/** in GetNodeIdCallback callback);
* Clears storage data associated with the origin.
*/
void forgetThisSite(in AString origin);
/**
* Returns true if the given node id is allowed to store things
* persistently on disk. Private Browsing and local content are not
* allowed to store persistent data.
*/
bool isPersistentStorageAllowed(in ACString nodeId);
/**
* Returns the directory to use as the base for storing data about GMPs.
*/
nsIFile getStorageDir();
}; };

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

@ -11,12 +11,13 @@
#include "GMPVideoDecoderProxy.h" #include "GMPVideoDecoderProxy.h"
#include "GMPVideoEncoderProxy.h" #include "GMPVideoEncoderProxy.h"
#include "GMPDecryptorProxy.h" #include "GMPDecryptorProxy.h"
#include "GMPService.h" #include "GMPServiceParent.h"
#include "nsAppDirectoryServiceDefs.h" #include "nsAppDirectoryServiceDefs.h"
#include "nsIFile.h" #include "nsIFile.h"
#include "nsISimpleEnumerator.h" #include "nsISimpleEnumerator.h"
#include "mozilla/Atomics.h" #include "mozilla/Atomics.h"
#include "nsNSSComponent.h" #include "nsNSSComponent.h"
#include "mozilla/DebugOnly.h"
#if defined(XP_WIN) #if defined(XP_WIN)
#include "mozilla/WindowsVersion.h" #include "mozilla/WindowsVersion.h"
@ -27,87 +28,234 @@ using namespace std;
using namespace mozilla; using namespace mozilla;
using namespace mozilla::gmp; using namespace mozilla::gmp;
class GMPTestMonitor
{
public:
GMPTestMonitor()
: mFinished(false)
{
}
void AwaitFinished()
{
MOZ_ASSERT(NS_IsMainThread());
while (!mFinished) {
NS_ProcessNextEvent(nullptr, true);
}
mFinished = false;
}
private:
void MarkFinished()
{
mFinished = true;
}
public:
void SetFinished()
{
NS_DispatchToMainThread(NS_NewNonOwningRunnableMethod(this,
&GMPTestMonitor::MarkFinished));
}
private:
bool mFinished;
};
struct GMPTestRunner struct GMPTestRunner
{ {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPTestRunner) NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPTestRunner)
void DoTest(void (GMPTestRunner::*aTestMethod)()); void DoTest(void (GMPTestRunner::*aTestMethod)(GMPTestMonitor&));
void RunTestGMPTestCodec(); void RunTestGMPTestCodec1(GMPTestMonitor& aMonitor);
void RunTestGMPCrossOrigin(); void RunTestGMPTestCodec2(GMPTestMonitor& aMonitor);
void RunTestGMPTestCodec3(GMPTestMonitor& aMonitor);
void RunTestGMPCrossOrigin1(GMPTestMonitor& aMonitor);
void RunTestGMPCrossOrigin2(GMPTestMonitor& aMonitor);
void RunTestGMPCrossOrigin3(GMPTestMonitor& aMonitor);
void RunTestGMPCrossOrigin4(GMPTestMonitor& aMonitor);
private: private:
~GMPTestRunner() { } ~GMPTestRunner() { }
}; };
void template<class T, class Base,
GMPTestRunner::RunTestGMPTestCodec() nsresult (NS_STDCALL GeckoMediaPluginService::*Getter)(nsTArray<nsCString>*,
const nsACString&,
UniquePtr<Base>&&)>
class RunTestGMPVideoCodec : public Base
{ {
nsRefPtr<GeckoMediaPluginService> service = public:
GeckoMediaPluginService::GetGeckoMediaPluginService(); virtual void Done(T* aGMP, GMPVideoHost* aHost)
{
EXPECT_TRUE(aGMP);
EXPECT_TRUE(aHost);
if (aGMP) {
aGMP->Close();
}
mMonitor.SetFinished();
}
GMPVideoHost* host = nullptr; static void Run(GMPTestMonitor& aMonitor, const nsCString& aOrigin)
GMPVideoDecoderProxy* decoder = nullptr; {
GMPVideoDecoderProxy* decoder2 = nullptr; UniquePtr<GMPCallbackType> callback(new RunTestGMPVideoCodec(aMonitor));
GMPVideoEncoderProxy* encoder = nullptr; Get(aOrigin, Move(callback));
}
nsTArray<nsCString> tags; protected:
tags.AppendElement(NS_LITERAL_CSTRING("h264")); typedef T GMPCodecType;
typedef Base GMPCallbackType;
service->GetGMPVideoDecoder(&tags, NS_LITERAL_CSTRING("o"), &host, &decoder2); explicit RunTestGMPVideoCodec(GMPTestMonitor& aMonitor)
service->GetGMPVideoDecoder(&tags, NS_LITERAL_CSTRING(""), &host, &decoder); : mMonitor(aMonitor)
{
}
service->GetGMPVideoEncoder(&tags, NS_LITERAL_CSTRING(""), &host, &encoder); static nsresult Get(const nsACString& aNodeId, UniquePtr<Base>&& aCallback)
{
nsTArray<nsCString> tags;
tags.AppendElement(NS_LITERAL_CSTRING("h264"));
EXPECT_TRUE(host); nsRefPtr<GeckoMediaPluginService> service =
EXPECT_TRUE(decoder); GeckoMediaPluginService::GetGeckoMediaPluginService();
EXPECT_TRUE(decoder2); return ((*service).*Getter)(&tags, aNodeId, Move(aCallback));
EXPECT_TRUE(encoder); }
if (decoder) decoder->Close(); protected:
if (decoder2) decoder2->Close(); GMPTestMonitor& mMonitor;
if (encoder) encoder->Close(); };
typedef RunTestGMPVideoCodec<GMPVideoDecoderProxy,
GetGMPVideoDecoderCallback,
&GeckoMediaPluginService::GetGMPVideoDecoder>
RunTestGMPVideoDecoder;
typedef RunTestGMPVideoCodec<GMPVideoEncoderProxy,
GetGMPVideoEncoderCallback,
&GeckoMediaPluginService::GetGMPVideoEncoder>
RunTestGMPVideoEncoder;
void
GMPTestRunner::RunTestGMPTestCodec1(GMPTestMonitor& aMonitor)
{
RunTestGMPVideoDecoder::Run(aMonitor, NS_LITERAL_CSTRING("o"));
} }
void void
GMPTestRunner::RunTestGMPCrossOrigin() GMPTestRunner::RunTestGMPTestCodec2(GMPTestMonitor& aMonitor)
{ {
nsRefPtr<GeckoMediaPluginService> service = RunTestGMPVideoDecoder::Run(aMonitor, NS_LITERAL_CSTRING(""));
GeckoMediaPluginService::GetGeckoMediaPluginService(); }
GMPVideoHost* host = nullptr; void
nsTArray<nsCString> tags; GMPTestRunner::RunTestGMPTestCodec3(GMPTestMonitor& aMonitor)
tags.AppendElement(NS_LITERAL_CSTRING("h264")); {
RunTestGMPVideoEncoder::Run(aMonitor, NS_LITERAL_CSTRING(""));
}
GMPVideoDecoderProxy* decoder1 = nullptr; template<class Base>
GMPVideoDecoderProxy* decoder2 = nullptr; class RunTestGMPCrossOrigin : public Base
GMPVideoEncoderProxy* encoder1 = nullptr; {
GMPVideoEncoderProxy* encoder2 = nullptr; public:
virtual void Done(typename Base::GMPCodecType* aGMP, GMPVideoHost* aHost)
{
EXPECT_TRUE(aGMP);
service->GetGMPVideoDecoder(&tags, NS_LITERAL_CSTRING("origin1"), &host, &decoder1); UniquePtr<typename Base::GMPCallbackType> callback(
service->GetGMPVideoDecoder(&tags, NS_LITERAL_CSTRING("origin2"), &host, &decoder2); new Step2(Base::mMonitor, aGMP, mShouldBeEqual));
EXPECT_TRUE(!!decoder1 && !!decoder2 && nsresult rv = Base::Get(mOrigin2, Move(callback));
decoder1->ParentID() != decoder2->ParentID()); EXPECT_TRUE(NS_SUCCEEDED(rv));
if (NS_FAILED(rv)) {
Base::mMonitor.SetFinished();
}
}
service->GetGMPVideoEncoder(&tags, NS_LITERAL_CSTRING("origin1"), &host, &encoder1); static void Run(GMPTestMonitor& aMonitor, const nsCString& aOrigin1,
service->GetGMPVideoEncoder(&tags, NS_LITERAL_CSTRING("origin2"), &host, &encoder2); const nsCString& aOrigin2)
EXPECT_TRUE(!!encoder1 && !!encoder2 && {
encoder1->ParentID() != encoder2->ParentID()); UniquePtr<typename Base::GMPCallbackType> callback(
new RunTestGMPCrossOrigin<Base>(aMonitor, aOrigin1, aOrigin2));
nsresult rv = Base::Get(aOrigin1, Move(callback));
EXPECT_TRUE(NS_SUCCEEDED(rv));
if (NS_FAILED(rv)) {
aMonitor.SetFinished();
}
}
if (decoder2) decoder2->Close(); private:
if (encoder2) encoder2->Close(); RunTestGMPCrossOrigin(GMPTestMonitor& aMonitor, const nsCString& aOrigin1,
const nsCString& aOrigin2)
: Base(aMonitor),
mGMP(nullptr),
mOrigin2(aOrigin2),
mShouldBeEqual(aOrigin1.Equals(aOrigin2))
{
}
service->GetGMPVideoDecoder(&tags, NS_LITERAL_CSTRING("origin1"), &host, &decoder2); class Step2 : public Base
EXPECT_TRUE(!!decoder1 && !!decoder2 && {
decoder1->ParentID() == decoder2->ParentID()); public:
Step2(GMPTestMonitor& aMonitor,
typename Base::GMPCodecType* aGMP,
bool aShouldBeEqual)
: Base(aMonitor),
mGMP(aGMP),
mShouldBeEqual(aShouldBeEqual)
{
}
virtual void Done(typename Base::GMPCodecType* aGMP, GMPVideoHost* aHost)
{
EXPECT_TRUE(aGMP);
if (aGMP) {
EXPECT_TRUE(mGMP &&
(mGMP->ParentID() == aGMP->ParentID()) == mShouldBeEqual);
}
if (mGMP) {
mGMP->Close();
}
Base::Done(aGMP, aHost);
}
service->GetGMPVideoEncoder(&tags, NS_LITERAL_CSTRING("origin1"), &host, &encoder2); private:
EXPECT_TRUE(!!encoder1 && !!encoder2 && typename Base::GMPCodecType* mGMP;
encoder1->ParentID() == encoder2->ParentID()); bool mShouldBeEqual;
};
if (decoder1) decoder1->Close(); typename Base::GMPCodecType* mGMP;
if (decoder2) decoder2->Close(); nsCString mOrigin2;
if (encoder1) encoder1->Close(); bool mShouldBeEqual;
if (encoder2) encoder2->Close(); };
typedef RunTestGMPCrossOrigin<RunTestGMPVideoDecoder>
RunTestGMPVideoDecoderCrossOrigin;
typedef RunTestGMPCrossOrigin<RunTestGMPVideoEncoder>
RunTestGMPVideoEncoderCrossOrigin;
void
GMPTestRunner::RunTestGMPCrossOrigin1(GMPTestMonitor& aMonitor)
{
RunTestGMPVideoDecoderCrossOrigin::Run(
aMonitor, NS_LITERAL_CSTRING("origin1"), NS_LITERAL_CSTRING("origin2"));
}
void
GMPTestRunner::RunTestGMPCrossOrigin2(GMPTestMonitor& aMonitor)
{
RunTestGMPVideoEncoderCrossOrigin::Run(
aMonitor, NS_LITERAL_CSTRING("origin1"), NS_LITERAL_CSTRING("origin2"));
}
void
GMPTestRunner::RunTestGMPCrossOrigin3(GMPTestMonitor& aMonitor)
{
RunTestGMPVideoDecoderCrossOrigin::Run(
aMonitor, NS_LITERAL_CSTRING("origin1"), NS_LITERAL_CSTRING("origin1"));
}
void
GMPTestRunner::RunTestGMPCrossOrigin4(GMPTestMonitor& aMonitor)
{
RunTestGMPVideoEncoderCrossOrigin::Run(
aMonitor, NS_LITERAL_CSTRING("origin1"), NS_LITERAL_CSTRING("origin1"));
} }
static already_AddRefed<nsIThread> static already_AddRefed<nsIThread>
@ -158,8 +306,8 @@ template<typename T>
static nsresult static nsresult
EnumerateGMPStorageDir(const nsACString& aDir, T&& aDirIter) EnumerateGMPStorageDir(const nsACString& aDir, T&& aDirIter)
{ {
nsRefPtr<GeckoMediaPluginService> service = nsRefPtr<GeckoMediaPluginServiceParent> service =
GeckoMediaPluginService::GetGeckoMediaPluginService(); GeckoMediaPluginServiceParent::GetSingleton();
MOZ_ASSERT(service); MOZ_ASSERT(service);
// $profileDir/gmp/ // $profileDir/gmp/
@ -312,28 +460,53 @@ SimulatePBModeExit()
NS_DispatchToMainThread(new NotifyObserversTask("last-pb-context-exited"), NS_DISPATCH_SYNC); NS_DispatchToMainThread(new NotifyObserversTask("last-pb-context-exited"), NS_DISPATCH_SYNC);
} }
class TestGetNodeIdCallback : public GetNodeIdCallback
{
public:
TestGetNodeIdCallback(nsCString& aNodeId, nsresult& aResult)
: mNodeId(aNodeId),
mResult(aResult)
{
}
void Done(nsresult aResult, const nsACString& aNodeId)
{
mResult = aResult;
mNodeId = aNodeId;
}
private:
nsCString& mNodeId;
nsresult& mResult;
};
static nsCString static nsCString
GetNodeId(const nsAString& aOrigin, GetNodeId(const nsAString& aOrigin,
const nsAString& aTopLevelOrigin, const nsAString& aTopLevelOrigin,
bool aInPBMode) bool aInPBMode)
{ {
nsRefPtr<GeckoMediaPluginService> service = nsRefPtr<GeckoMediaPluginServiceParent> service =
GeckoMediaPluginService::GetGeckoMediaPluginService(); GeckoMediaPluginServiceParent::GetSingleton();
EXPECT_TRUE(service); EXPECT_TRUE(service);
nsCString nodeId; nsCString nodeId;
nsresult result;
UniquePtr<GetNodeIdCallback> callback(new TestGetNodeIdCallback(nodeId,
result));
// We rely on the fact that the GetNodeId implementation for
// GeckoMediaPluginServiceParent is synchronous.
nsresult rv = service->GetNodeId(aOrigin, nsresult rv = service->GetNodeId(aOrigin,
aTopLevelOrigin, aTopLevelOrigin,
aInPBMode, aInPBMode,
nodeId); Move(callback));
EXPECT_TRUE(NS_SUCCEEDED(rv)); EXPECT_TRUE(NS_SUCCEEDED(rv) && NS_SUCCEEDED(result));
return nodeId; return nodeId;
} }
static bool static bool
IsGMPStorageIsEmpty() IsGMPStorageIsEmpty()
{ {
nsRefPtr<GeckoMediaPluginService> service = nsRefPtr<GeckoMediaPluginServiceParent> service =
GeckoMediaPluginService::GetGeckoMediaPluginService(); GeckoMediaPluginServiceParent::GetSingleton();
MOZ_ASSERT(service); MOZ_ASSERT(service);
nsCOMPtr<nsIFile> storage; nsCOMPtr<nsIFile> storage;
nsresult rv = service->GetStorageDir(getter_AddRefs(storage)); nsresult rv = service->GetStorageDir(getter_AddRefs(storage));
@ -437,9 +610,73 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
SetFinished(); SetFinished();
} }
class CreateDecryptorDone : public GetGMPDecryptorCallback
{
public:
CreateDecryptorDone(GMPStorageTest* aRunner, nsIRunnable* aContinuation)
: mRunner(aRunner),
mContinuation(aContinuation)
{
}
virtual void Done(GMPDecryptorProxy* aDecryptor) override
{
mRunner->mDecryptor = aDecryptor;
EXPECT_TRUE(!!mRunner->mDecryptor);
if (mRunner->mDecryptor) {
mRunner->mDecryptor->Init(mRunner);
}
nsCOMPtr<nsIThread> thread(GetGMPThread());
thread->Dispatch(mContinuation, NS_DISPATCH_NORMAL);
}
private:
nsRefPtr<GMPStorageTest> mRunner;
nsCOMPtr<nsIRunnable> mContinuation;
};
void CreateDecryptor(const nsAString& aOrigin, void CreateDecryptor(const nsAString& aOrigin,
const nsAString& aTopLevelOrigin, const nsAString& aTopLevelOrigin,
bool aInPBMode) { bool aInPBMode,
const nsCString& aUpdate)
{
nsTArray<nsCString> updates;
updates.AppendElement(aUpdate);
CreateDecryptor(aOrigin, aTopLevelOrigin, aInPBMode, Move(updates));
}
class Updates : public nsRunnable
{
public:
Updates(GMPStorageTest* aRunner, nsTArray<nsCString>&& aUpdates)
: mRunner(aRunner),
mUpdates(aUpdates)
{
}
NS_IMETHOD Run()
{
for (auto& update : mUpdates) {
mRunner->Update(update);
}
return NS_OK;
}
private:
nsRefPtr<GMPStorageTest> mRunner;
nsTArray<nsCString> mUpdates;
};
void CreateDecryptor(const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
bool aInPBMode,
nsTArray<nsCString>&& aUpdates) {
nsCOMPtr<nsIRunnable> updates(new Updates(this, Move(aUpdates)));
CreateDecryptor(aOrigin, aTopLevelOrigin, aInPBMode, updates);
}
void CreateDecryptor(const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
bool aInPBMode,
nsIRunnable* aContinuation) {
nsRefPtr<GeckoMediaPluginService> service = nsRefPtr<GeckoMediaPluginService> service =
GeckoMediaPluginService::GetGeckoMediaPluginService(); GeckoMediaPluginService::GetGeckoMediaPluginService();
EXPECT_TRUE(service); EXPECT_TRUE(service);
@ -450,13 +687,11 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
nsTArray<nsCString> tags; nsTArray<nsCString> tags;
tags.AppendElement(NS_LITERAL_CSTRING("fake")); tags.AppendElement(NS_LITERAL_CSTRING("fake"));
nsresult rv = service->GetGMPDecryptor(&tags, mNodeId, &mDecryptor); UniquePtr<GetGMPDecryptorCallback> callback(
new CreateDecryptorDone(this, aContinuation));
nsresult rv =
service->GetGMPDecryptor(&tags, mNodeId, Move(callback));
EXPECT_TRUE(NS_SUCCEEDED(rv)); EXPECT_TRUE(NS_SUCCEEDED(rv));
EXPECT_TRUE(!!mDecryptor);
if (mDecryptor) {
mDecryptor->Init(this);
}
} }
void TestBasicStorage() { void TestBasicStorage() {
@ -466,16 +701,16 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
nsRefPtr<GeckoMediaPluginService> service = nsRefPtr<GeckoMediaPluginService> service =
GeckoMediaPluginService::GetGeckoMediaPluginService(); GeckoMediaPluginService::GetGeckoMediaPluginService();
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
NS_LITERAL_STRING("example2.com"),
false);
// Send a message to the fake GMP for it to run its own tests internally. // Send a message to the fake GMP for it to run its own tests internally.
// It sends us a "test-storage complete" message when its passed, or // It sends us a "test-storage complete" message when its passed, or
// some other message if its tests fail. // some other message if its tests fail.
Expect(NS_LITERAL_CSTRING("test-storage complete"), Expect(NS_LITERAL_CSTRING("test-storage complete"),
NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished)); NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished));
Update(NS_LITERAL_CSTRING("test-storage"));
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
NS_LITERAL_STRING("example2.com"),
false,
NS_LITERAL_CSTRING("test-storage"));
} }
/** /**
@ -489,28 +724,28 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
EXPECT_TRUE(IsGMPStorageIsEmpty()); EXPECT_TRUE(IsGMPStorageIsEmpty());
// Generate storage data for some site. // Generate storage data for some site.
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
NS_LITERAL_STRING("example2.com"),
false);
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod( nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
this, &GMPStorageTest::TestForgetThisSite_AnotherSite); this, &GMPStorageTest::TestForgetThisSite_AnotherSite);
Expect(NS_LITERAL_CSTRING("test-storage complete"), r); Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
Update(NS_LITERAL_CSTRING("test-storage"));
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
NS_LITERAL_STRING("example2.com"),
false,
NS_LITERAL_CSTRING("test-storage"));
} }
void TestForgetThisSite_AnotherSite() { void TestForgetThisSite_AnotherSite() {
Shutdown(); Shutdown();
// Generate storage data for another site. // Generate storage data for another site.
CreateDecryptor(NS_LITERAL_STRING("example3.com"),
NS_LITERAL_STRING("example4.com"),
false);
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod( nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
this, &GMPStorageTest::TestForgetThisSite_CollectSiteInfo); this, &GMPStorageTest::TestForgetThisSite_CollectSiteInfo);
Expect(NS_LITERAL_CSTRING("test-storage complete"), r); Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
Update(NS_LITERAL_CSTRING("test-storage"));
CreateDecryptor(NS_LITERAL_STRING("example3.com"),
NS_LITERAL_STRING("example4.com"),
false,
NS_LITERAL_CSTRING("test-storage"));
} }
struct NodeInfo { struct NodeInfo {
@ -545,8 +780,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
} }
void TestForgetThisSite_Forget(nsAutoPtr<NodeInfo> aSiteInfo) { void TestForgetThisSite_Forget(nsAutoPtr<NodeInfo> aSiteInfo) {
nsRefPtr<GeckoMediaPluginService> service = nsRefPtr<GeckoMediaPluginServiceParent> service =
GeckoMediaPluginService::GetGeckoMediaPluginService(); GeckoMediaPluginServiceParent::GetSingleton();
service->ForgetThisSite(NS_ConvertUTF8toUTF16(aSiteInfo->siteToForget)); service->ForgetThisSite(NS_ConvertUTF8toUTF16(aSiteInfo->siteToForget));
nsCOMPtr<nsIThread> thread; nsCOMPtr<nsIThread> thread;
@ -622,16 +857,15 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
EXPECT_TRUE(IsGMPStorageIsEmpty()); EXPECT_TRUE(IsGMPStorageIsEmpty());
// Generate storage data for some site. // Generate storage data for some site.
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
NS_LITERAL_STRING("example2.com"),
false);
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod( nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
this, &GMPStorageTest::TestClearRecentHistory1_Clear); this, &GMPStorageTest::TestClearRecentHistory1_Clear);
Expect(NS_LITERAL_CSTRING("test-storage complete"), r); Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
Update(NS_LITERAL_CSTRING("test-storage"));
} CreateDecryptor(NS_LITERAL_STRING("example1.com"),
NS_LITERAL_STRING("example2.com"),
false,
NS_LITERAL_CSTRING("test-storage"));
}
/** /**
* 1. Generate some storage data. * 1. Generate some storage data.
@ -645,15 +879,14 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
EXPECT_TRUE(IsGMPStorageIsEmpty()); EXPECT_TRUE(IsGMPStorageIsEmpty());
// Generate storage data for some site. // Generate storage data for some site.
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
NS_LITERAL_STRING("example2.com"),
false);
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod( nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
this, &GMPStorageTest::TestClearRecentHistory2_Clear); this, &GMPStorageTest::TestClearRecentHistory2_Clear);
Expect(NS_LITERAL_CSTRING("test-storage complete"), r); Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
Update(NS_LITERAL_CSTRING("test-storage"));
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
NS_LITERAL_STRING("example2.com"),
false,
NS_LITERAL_CSTRING("test-storage"));
} }
/** /**
@ -668,15 +901,14 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
EXPECT_TRUE(IsGMPStorageIsEmpty()); EXPECT_TRUE(IsGMPStorageIsEmpty());
// Generate storage data for some site. // Generate storage data for some site.
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
NS_LITERAL_STRING("example2.com"),
false);
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod( nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
this, &GMPStorageTest::TestClearRecentHistory3_Clear); this, &GMPStorageTest::TestClearRecentHistory3_Clear);
Expect(NS_LITERAL_CSTRING("test-storage complete"), r); Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
Update(NS_LITERAL_CSTRING("test-storage"));
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
NS_LITERAL_STRING("example2.com"),
false,
NS_LITERAL_CSTRING("test-storage"));
} }
class MaxMTimeFinder { class MaxMTimeFinder {
@ -774,12 +1006,6 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
void TestCrossOriginStorage() { void TestCrossOriginStorage() {
EXPECT_TRUE(!mDecryptor); EXPECT_TRUE(!mDecryptor);
// Open decryptor on one, origin, write a record, and test that that
// record can't be read on another origin.
CreateDecryptor(NS_LITERAL_STRING("example3.com"),
NS_LITERAL_STRING("example4.com"),
false);
// Send the decryptor the message "store recordid $time" // Send the decryptor the message "store recordid $time"
// Wait for the decrytor to send us "stored recordid $time" // Wait for the decrytor to send us "stored recordid $time"
auto t = time(0); auto t = time(0);
@ -790,7 +1016,13 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
nsCString update("store crossOriginTestRecordId "); nsCString update("store crossOriginTestRecordId ");
update.AppendInt((int64_t)t); update.AppendInt((int64_t)t);
Update(update);
// Open decryptor on one, origin, write a record, and test that that
// record can't be read on another origin.
CreateDecryptor(NS_LITERAL_STRING("example3.com"),
NS_LITERAL_STRING("example4.com"),
false,
update);
} }
void TestCrossOriginStorage_RecordStoredContinuation() { void TestCrossOriginStorage_RecordStoredContinuation() {
@ -798,87 +1030,102 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
// and try to read the record. // and try to read the record.
Shutdown(); Shutdown();
CreateDecryptor(NS_LITERAL_STRING("example5.com"),
NS_LITERAL_STRING("example6.com"),
false);
Expect(NS_LITERAL_CSTRING("retrieve crossOriginTestRecordId succeeded (length 0 bytes)"), Expect(NS_LITERAL_CSTRING("retrieve crossOriginTestRecordId succeeded (length 0 bytes)"),
NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished)); NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished));
Update(NS_LITERAL_CSTRING("retrieve crossOriginTestRecordId"));
CreateDecryptor(NS_LITERAL_STRING("example5.com"),
NS_LITERAL_STRING("example6.com"),
false,
NS_LITERAL_CSTRING("retrieve crossOriginTestRecordId"));
} }
void TestPBStorage() { void TestPBStorage() {
// Open decryptor on one, origin, write a record, close decryptor,
// open another, and test that record can be read, close decryptor,
// then send pb-last-context-closed notification, then open decryptor
// and check that it can't read that data; it should have been purged.
CreateDecryptor(NS_LITERAL_STRING("pb1.com"),
NS_LITERAL_STRING("pb2.com"),
true);
// Send the decryptor the message "store recordid $time" // Send the decryptor the message "store recordid $time"
// Wait for the decrytor to send us "stored recordid $time" // Wait for the decrytor to send us "stored recordid $time"
nsCString response("stored pbdata test-pb-data"); nsCString response("stored pbdata test-pb-data");
Expect(response, NS_NewRunnableMethod(this, Expect(response, NS_NewRunnableMethod(this,
&GMPStorageTest::TestPBStorage_RecordStoredContinuation)); &GMPStorageTest::TestPBStorage_RecordStoredContinuation));
nsCString update("store pbdata test-pb-data"); // Open decryptor on one, origin, write a record, close decryptor,
Update(update); // open another, and test that record can be read, close decryptor,
// then send pb-last-context-closed notification, then open decryptor
// and check that it can't read that data; it should have been purged.
CreateDecryptor(NS_LITERAL_STRING("pb1.com"),
NS_LITERAL_STRING("pb2.com"),
true,
NS_LITERAL_CSTRING("store pbdata test-pb-data"));
} }
void TestPBStorage_RecordStoredContinuation() { void TestPBStorage_RecordStoredContinuation() {
Shutdown(); Shutdown();
CreateDecryptor(NS_LITERAL_STRING("pb1.com"),
NS_LITERAL_STRING("pb2.com"),
true);
Expect(NS_LITERAL_CSTRING("retrieve pbdata succeeded (length 12 bytes)"), Expect(NS_LITERAL_CSTRING("retrieve pbdata succeeded (length 12 bytes)"),
NS_NewRunnableMethod(this, NS_NewRunnableMethod(this,
&GMPStorageTest::TestPBStorage_RecordRetrievedContinuation)); &GMPStorageTest::TestPBStorage_RecordRetrievedContinuation));
Update(NS_LITERAL_CSTRING("retrieve pbdata"));
CreateDecryptor(NS_LITERAL_STRING("pb1.com"),
NS_LITERAL_STRING("pb2.com"),
true,
NS_LITERAL_CSTRING("retrieve pbdata"));
} }
void TestPBStorage_RecordRetrievedContinuation() { void TestPBStorage_RecordRetrievedContinuation() {
Shutdown(); Shutdown();
SimulatePBModeExit(); SimulatePBModeExit();
CreateDecryptor(NS_LITERAL_STRING("pb1.com"),
NS_LITERAL_STRING("pb2.com"),
true);
Expect(NS_LITERAL_CSTRING("retrieve pbdata succeeded (length 0 bytes)"), Expect(NS_LITERAL_CSTRING("retrieve pbdata succeeded (length 0 bytes)"),
NS_NewRunnableMethod(this, NS_NewRunnableMethod(this,
&GMPStorageTest::SetFinished)); &GMPStorageTest::SetFinished));
Update(NS_LITERAL_CSTRING("retrieve pbdata"));
CreateDecryptor(NS_LITERAL_STRING("pb1.com"),
NS_LITERAL_STRING("pb2.com"),
true,
NS_LITERAL_CSTRING("retrieve pbdata"));
}
void NextAsyncShutdownTimeoutTest(nsIRunnable* aContinuation)
{
if (mDecryptor) {
Update(NS_LITERAL_CSTRING("shutdown-mode timeout"));
Shutdown();
}
nsCOMPtr<nsIThread> thread(GetGMPThread());
thread->Dispatch(aContinuation, NS_DISPATCH_NORMAL);
} }
void CreateAsyncShutdownTimeoutGMP(const nsAString& aOrigin1, void CreateAsyncShutdownTimeoutGMP(const nsAString& aOrigin1,
const nsAString& aOrigin2) { const nsAString& aOrigin2,
CreateDecryptor(aOrigin1, aOrigin2, false); void (GMPStorageTest::*aCallback)()) {
Update(NS_LITERAL_CSTRING("shutdown-mode timeout")); nsCOMPtr<nsIRunnable> continuation(
Shutdown(); NS_NewRunnableMethodWithArg<nsCOMPtr<nsIRunnable>>(
this,
&GMPStorageTest::NextAsyncShutdownTimeoutTest,
NS_NewRunnableMethod(this, aCallback)));
CreateDecryptor(aOrigin1, aOrigin2, false, continuation);
} }
void TestAsyncShutdownTimeout() { void TestAsyncShutdownTimeout() {
// Create decryptors that timeout in their async shutdown. // Create decryptors that timeout in their async shutdown.
// If the gtest hangs on shutdown, test fails! // If the gtest hangs on shutdown, test fails!
CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("example7.com"), CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("example7.com"),
NS_LITERAL_STRING("example8.com")); NS_LITERAL_STRING("example8.com"),
&GMPStorageTest::TestAsyncShutdownTimeout2);
};
void TestAsyncShutdownTimeout2() {
CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("example9.com"), CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("example9.com"),
NS_LITERAL_STRING("example10.com")); NS_LITERAL_STRING("example10.com"),
&GMPStorageTest::TestAsyncShutdownTimeout3);
};
void TestAsyncShutdownTimeout3() {
CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("example11.com"), CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("example11.com"),
NS_LITERAL_STRING("example12.com")); NS_LITERAL_STRING("example12.com"),
SetFinished(); &GMPStorageTest::SetFinished);
}; };
void TestAsyncShutdownStorage() { void TestAsyncShutdownStorage() {
// Test that a GMP can write to storage during shutdown, and retrieve
// that written data in a subsequent session.
CreateDecryptor(NS_LITERAL_STRING("example13.com"),
NS_LITERAL_STRING("example14.com"),
false);
// Instruct the GMP to write a token (the current timestamp, so it's // Instruct the GMP to write a token (the current timestamp, so it's
// unique) during async shutdown, then shutdown the plugin, re-create // unique) during async shutdown, then shutdown the plugin, re-create
// it, and check that the token was successfully stored. // it, and check that the token was successfully stored.
@ -895,7 +1142,12 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
Expect(response, NS_NewRunnableMethodWithArg<nsCString>(this, Expect(response, NS_NewRunnableMethodWithArg<nsCString>(this,
&GMPStorageTest::TestAsyncShutdownStorage_ReceivedShutdownToken, token)); &GMPStorageTest::TestAsyncShutdownStorage_ReceivedShutdownToken, token));
Update(update); // Test that a GMP can write to storage during shutdown, and retrieve
// that written data in a subsequent session.
CreateDecryptor(NS_LITERAL_STRING("example13.com"),
NS_LITERAL_STRING("example14.com"),
false,
update);
} }
void TestAsyncShutdownStorage_ReceivedShutdownToken(const nsCString& aToken) { void TestAsyncShutdownStorage_ReceivedShutdownToken(const nsCString& aToken) {
@ -906,37 +1158,39 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
void TestAsyncShutdownStorage_AsyncShutdownComplete(const nsCString& aToken) { void TestAsyncShutdownStorage_AsyncShutdownComplete(const nsCString& aToken) {
// Create a new instance of the plugin, retrieve the token written // Create a new instance of the plugin, retrieve the token written
// during shutdown and verify it is correct. // during shutdown and verify it is correct.
CreateDecryptor(NS_LITERAL_STRING("example13.com"),
NS_LITERAL_STRING("example14.com"),
false);
nsCString response("retrieved shutdown-token "); nsCString response("retrieved shutdown-token ");
response.Append(aToken); response.Append(aToken);
Expect(response, Expect(response,
NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished)); NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished));
Update(NS_LITERAL_CSTRING("retrieve-shutdown-token"));
CreateDecryptor(NS_LITERAL_STRING("example13.com"),
NS_LITERAL_STRING("example14.com"),
false,
NS_LITERAL_CSTRING("retrieve-shutdown-token"));
} }
#if defined(XP_WIN) #if defined(XP_WIN)
void TestOutputProtection() { void TestOutputProtection() {
Shutdown(); Shutdown();
CreateDecryptor(NS_LITERAL_STRING("example15.com"),
NS_LITERAL_STRING("example16.com"),
false);
Expect(NS_LITERAL_CSTRING("OP tests completed"), Expect(NS_LITERAL_CSTRING("OP tests completed"),
NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished)); NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished));
Update(NS_LITERAL_CSTRING("test-op-apis"));
CreateDecryptor(NS_LITERAL_STRING("example15.com"),
NS_LITERAL_STRING("example16.com"),
false,
NS_LITERAL_CSTRING("test-op-apis"));
} }
#endif #endif
void TestPluginVoucher() { void TestPluginVoucher() {
CreateDecryptor(NS_LITERAL_STRING("example17.com"),
NS_LITERAL_STRING("example18.com"),
false);
Expect(NS_LITERAL_CSTRING("retrieved plugin-voucher: gmp-fake placeholder voucher"), Expect(NS_LITERAL_CSTRING("retrieved plugin-voucher: gmp-fake placeholder voucher"),
NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished)); NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished));
Update(NS_LITERAL_CSTRING("retrieve-plugin-voucher"));
CreateDecryptor(NS_LITERAL_STRING("example17.com"),
NS_LITERAL_STRING("example18.com"),
false,
NS_LITERAL_CSTRING("retrieve-plugin-voucher"));
} }
void TestGetRecordNamesInMemoryStorage() { void TestGetRecordNamesInMemoryStorage() {
@ -953,12 +1207,9 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
} }
void TestGetRecordNames(bool aPrivateBrowsing) { void TestGetRecordNames(bool aPrivateBrowsing) {
CreateDecryptor(NS_LITERAL_STRING("foo.com"),
NS_LITERAL_STRING("bar.com"),
aPrivateBrowsing);
// Create a number of records of different names. // Create a number of records of different names.
const uint32_t num = 100; const uint32_t num = 100;
nsTArray<nsCString> updates(num);
for (uint32_t i = 0; i < num; i++) { for (uint32_t i = 0; i < num; i++) {
nsAutoCString response; nsAutoCString response;
response.AppendLiteral("stored data"); response.AppendLiteral("stored data");
@ -972,7 +1223,7 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
mRecordNames.AppendLiteral("data"); mRecordNames.AppendLiteral("data");
AppendIntPadded(mRecordNames, i); AppendIntPadded(mRecordNames, i);
nsAutoCString update; nsCString& update = *updates.AppendElement();
update.AppendLiteral("store data"); update.AppendLiteral("store data");
AppendIntPadded(update, i); AppendIntPadded(update, i);
update.AppendLiteral(" test-data"); update.AppendLiteral(" test-data");
@ -984,8 +1235,12 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
NS_NewRunnableMethod(this, &GMPStorageTest::TestGetRecordNames_QueryNames); NS_NewRunnableMethod(this, &GMPStorageTest::TestGetRecordNames_QueryNames);
} }
Expect(response, continuation); Expect(response, continuation);
Update(update);
} }
CreateDecryptor(NS_LITERAL_STRING("foo.com"),
NS_LITERAL_STRING("bar.com"),
aPrivateBrowsing,
Move(updates));
} }
void TestGetRecordNames_QueryNames() { void TestGetRecordNames_QueryNames() {
@ -1025,10 +1280,6 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
MOZ_ASSERT(longRecordName.Length() < GMP_MAX_RECORD_NAME_SIZE); MOZ_ASSERT(longRecordName.Length() < GMP_MAX_RECORD_NAME_SIZE);
MOZ_ASSERT(longRecordName.Length() > 260); // Windows MAX_PATH MOZ_ASSERT(longRecordName.Length() > 260); // Windows MAX_PATH
CreateDecryptor(NS_LITERAL_STRING("fuz.com"),
NS_LITERAL_STRING("baz.com"),
false);
nsCString response("stored "); nsCString response("stored ");
response.Append(longRecordName); response.Append(longRecordName);
response.AppendLiteral(" "); response.AppendLiteral(" ");
@ -1039,7 +1290,10 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
update.Append(longRecordName); update.Append(longRecordName);
update.AppendLiteral(" "); update.AppendLiteral(" ");
update.Append(data); update.Append(data);
Update(update); CreateDecryptor(NS_LITERAL_STRING("fuz.com"),
NS_LITERAL_STRING("baz.com"),
false,
update);
} }
void Expect(const nsCString& aMessage, nsIRunnable* aContinuation) { void Expect(const nsCString& aMessage, nsIRunnable* aContinuation) {
@ -1146,24 +1400,31 @@ private:
}; };
void void
GMPTestRunner::DoTest(void (GMPTestRunner::*aTestMethod)()) GMPTestRunner::DoTest(void (GMPTestRunner::*aTestMethod)(GMPTestMonitor&))
{ {
nsRefPtr<GeckoMediaPluginService> service = nsCOMPtr<nsIThread> thread(GetGMPThread());
GeckoMediaPluginService::GetGeckoMediaPluginService();
nsCOMPtr<nsIThread> thread;
service->GetThread(getter_AddRefs(thread)); GMPTestMonitor monitor;
thread->Dispatch(NS_NewRunnableMethod(this, aTestMethod), NS_DISPATCH_SYNC); thread->Dispatch(NS_NewRunnableMethodWithArg<GMPTestMonitor&>(this,
aTestMethod,
monitor),
NS_DISPATCH_NORMAL);
monitor.AwaitFinished();
} }
TEST(GeckoMediaPlugins, GMPTestCodec) { TEST(GeckoMediaPlugins, GMPTestCodec) {
nsRefPtr<GMPTestRunner> runner = new GMPTestRunner(); nsRefPtr<GMPTestRunner> runner = new GMPTestRunner();
runner->DoTest(&GMPTestRunner::RunTestGMPTestCodec); runner->DoTest(&GMPTestRunner::RunTestGMPTestCodec1);
runner->DoTest(&GMPTestRunner::RunTestGMPTestCodec2);
runner->DoTest(&GMPTestRunner::RunTestGMPTestCodec3);
} }
TEST(GeckoMediaPlugins, GMPCrossOrigin) { TEST(GeckoMediaPlugins, GMPCrossOrigin) {
nsRefPtr<GMPTestRunner> runner = new GMPTestRunner(); nsRefPtr<GMPTestRunner> runner = new GMPTestRunner();
runner->DoTest(&GMPTestRunner::RunTestGMPCrossOrigin); runner->DoTest(&GMPTestRunner::RunTestGMPCrossOrigin1);
runner->DoTest(&GMPTestRunner::RunTestGMPCrossOrigin2);
runner->DoTest(&GMPTestRunner::RunTestGMPCrossOrigin3);
runner->DoTest(&GMPTestRunner::RunTestGMPCrossOrigin4);
} }
TEST(GeckoMediaPlugins, GMPStorageGetNodeId) { TEST(GeckoMediaPlugins, GMPStorageGetNodeId) {

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

@ -371,22 +371,22 @@ skip-if = buildapp == 'b2g' && toolkit != 'gonk' # bug 1082984
[test_dormant_playback.html] [test_dormant_playback.html]
skip-if = (os == 'win' && os_version == '5.1') || (os != 'win' && toolkit != 'gonk') skip-if = (os == 'win' && os_version == '5.1') || (os != 'win' && toolkit != 'gonk')
[test_eme_canvas_blocked.html] [test_eme_canvas_blocked.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s || (os == 'win' && !debug) # bug 1043403, bug 1057908, bug 1140675 skip-if = buildapp == 'b2g' || toolkit == 'android' || (os == 'win' && !debug) # bug 1043403, bug 1140675
[test_eme_non_mse_fails.html] [test_eme_non_mse_fails.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # bug 1043403, bug 1057908 skip-if = buildapp == 'b2g' || toolkit == 'android' # bug 1043403
#[test_eme_obs_notification.html] #[test_eme_obs_notification.html]
#skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # bug 1043403, bug 1057908 #skip-if = buildapp == 'b2g' || toolkit == 'android' # bug 1043403
# Disabled (bug 1140778) since this test fails and we don't want to remove the # Disabled (bug 1140778) since this test fails and we don't want to remove the
# functionality being tested by this test. We should still test other observers # functionality being tested by this test. We should still test other observers
# in future however, so I'm not removing the test, just disabling it. # in future however, so I'm not removing the test, just disabling it.
[test_eme_persistent_sessions.html] [test_eme_persistent_sessions.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # bug 1043403, bug 1057908 skip-if = buildapp == 'b2g' || toolkit == 'android' # bug 1043403
[test_eme_playback.html] [test_eme_playback.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # bug 1043403, bug 1057908 skip-if = buildapp == 'b2g' || toolkit == 'android' # bug 1043403
[test_eme_requestKeySystemAccess.html] [test_eme_requestKeySystemAccess.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # bug 1043403, bug 1057908 skip-if = buildapp == 'b2g' || toolkit == 'android' # bug 1043403
[test_eme_stream_capture_blocked.html] [test_eme_stream_capture_blocked.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s || (os == 'win' && !debug) # bug 1043403, bug 1057908, bug 1140675 skip-if = buildapp == 'b2g' || toolkit == 'android' || (os == 'win' && !debug) # bug 1043403, bug 1140675
[test_empty_resource.html] [test_empty_resource.html]
[test_error_in_video_document.html] [test_error_in_video_document.html]
skip-if = toolkit == 'android' || (os == 'win' && !debug) || (os == 'mac' && !debug) # bug 608634 skip-if = toolkit == 'android' || (os == 'win' && !debug) || (os == 'mac' && !debug) # bug 608634

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

@ -72,7 +72,7 @@
is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount); is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount);
// Focus the window. // Focus the window.
window.focus(); SpecialPowers.focus(window);
is(plugin1.getFocusState(), true, "(3) Plugin should still have focus."); is(plugin1.getFocusState(), true, "(3) Plugin should still have focus.");
is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount); is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount);

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

@ -38,13 +38,12 @@ NS_NewXBLContentSink(nsIXMLContentSink** aResult,
{ {
NS_ENSURE_ARG_POINTER(aResult); NS_ENSURE_ARG_POINTER(aResult);
nsXBLContentSink* it = new nsXBLContentSink(); nsRefPtr<nsXBLContentSink> it = new nsXBLContentSink();
nsCOMPtr<nsIXMLContentSink> kungFuDeathGrip = it;
nsresult rv = it->Init(aDoc, aURI, aContainer); nsresult rv = it->Init(aDoc, aURI, aContainer);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
return CallQueryInterface(it, aResult); it.forget(aResult);
return NS_OK;
} }
nsXBLContentSink::nsXBLContentSink() nsXBLContentSink::nsXBLContentSink()

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

@ -86,13 +86,13 @@ NS_NewXMLContentSink(nsIXMLContentSink** aResult,
if (nullptr == aResult) { if (nullptr == aResult) {
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
} }
nsXMLContentSink* it = new nsXMLContentSink(); nsRefPtr<nsXMLContentSink> it = new nsXMLContentSink();
nsCOMPtr<nsIXMLContentSink> kungFuDeathGrip = it;
nsresult rv = it->Init(aDoc, aURI, aContainer, aChannel); nsresult rv = it->Init(aDoc, aURI, aContainer, aChannel);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
return CallQueryInterface(it, aResult); it.forget(aResult);
return NS_OK;
} }
nsXMLContentSink::nsXMLContentSink() nsXMLContentSink::nsXMLContentSink()

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

@ -172,7 +172,7 @@ nsXULCommandDispatcher::GetFocusedWindow(nsIDOMWindow** aWindow)
if (domdoc && !nsContentUtils::CanCallerAccess(domdoc)) if (domdoc && !nsContentUtils::CanCallerAccess(domdoc))
return NS_ERROR_DOM_SECURITY_ERR; return NS_ERROR_DOM_SECURITY_ERR;
CallQueryInterface(window, aWindow); window.forget(aWindow);
return NS_OK; return NS_OK;
} }

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

@ -1314,14 +1314,14 @@ nsXULTemplateQueryProcessorRDF::ParseLiteral(const nsString& aParseType,
rv = gRDFService->GetIntLiteral(intValue, getter_AddRefs(intLiteral)); rv = gRDFService->GetIntLiteral(intValue, getter_AddRefs(intLiteral));
if (NS_FAILED(rv)) if (NS_FAILED(rv))
return rv; return rv;
rv = CallQueryInterface(intLiteral, aResult); intLiteral.forget(aResult);
} }
else { else {
nsCOMPtr<nsIRDFLiteral> literal; nsCOMPtr<nsIRDFLiteral> literal;
rv = gRDFService->GetLiteral(aValue.get(), getter_AddRefs(literal)); rv = gRDFService->GetLiteral(aValue.get(), getter_AddRefs(literal));
if (NS_FAILED(rv)) if (NS_FAILED(rv))
return rv; return rv;
rv = CallQueryInterface(literal, aResult); literal.forget(aResult);
} }
return rv; return rv;
} }

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

@ -628,6 +628,9 @@ APZCCallbackHelper::SendSetTargetAPZCNotification(nsIWidget* aWidget,
uint64_t aInputBlockId, uint64_t aInputBlockId,
const nsRefPtr<SetTargetAPZCCallback>& aCallback) const nsRefPtr<SetTargetAPZCCallback>& aCallback)
{ {
if (!aWidget || !aDocument) {
return;
}
if (nsIPresShell* shell = aDocument->GetShell()) { if (nsIPresShell* shell = aDocument->GetShell()) {
if (nsIFrame* rootFrame = shell->GetRootFrame()) { if (nsIFrame* rootFrame = shell->GetRootFrame()) {
bool waitForRefresh = false; bool waitForRefresh = false;

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

@ -615,7 +615,7 @@ bool ImageBridgeChild::StartUpOnThread(Thread* aThread)
} }
sImageBridgeChildSingleton = new ImageBridgeChild(); sImageBridgeChildSingleton = new ImageBridgeChild();
sImageBridgeParentSingleton = new ImageBridgeParent( sImageBridgeParentSingleton = new ImageBridgeParent(
CompositorParent::CompositorLoop(), nullptr, ipc::kCurrentProcessId); CompositorParent::CompositorLoop(), nullptr, base::GetCurrentProcId());
sImageBridgeChildSingleton->ConnectAsync(sImageBridgeParentSingleton); sImageBridgeChildSingleton->ConnectAsync(sImageBridgeParentSingleton);
return true; return true;
} else { } else {
@ -943,7 +943,7 @@ void ImageBridgeChild::RemoveTexture(TextureClient* aTexture)
bool ImageBridgeChild::IsSameProcess() const bool ImageBridgeChild::IsSameProcess() const
{ {
return OtherPid() == ipc::kCurrentProcessId; return OtherPid() == base::GetCurrentProcId();
} }
void ImageBridgeChild::SendPendingAsyncMessges() void ImageBridgeChild::SendPendingAsyncMessges()

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

@ -340,7 +340,7 @@ ImageBridgeParent::CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds
bool ImageBridgeParent::IsSameProcess() const bool ImageBridgeParent::IsSameProcess() const
{ {
return OtherPid() == ipc::kCurrentProcessId; return OtherPid() == base::GetCurrentProcId();
} }
void void

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

@ -976,7 +976,7 @@ LayerTransactionParent::ActorDestroy(ActorDestroyReason why)
bool LayerTransactionParent::IsSameProcess() const bool LayerTransactionParent::IsSameProcess() const
{ {
return OtherPid() == ipc::kCurrentProcessId; return OtherPid() == base::GetCurrentProcId();
} }
void void

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

@ -738,7 +738,7 @@ ShadowLayerForwarder::IsSameProcess() const
if (!HasShadowManager() || !mShadowManager->IPCOpen()) { if (!HasShadowManager() || !mShadowManager->IPCOpen()) {
return false; return false;
} }
return mShadowManager->OtherPid() == kCurrentProcessId; return mShadowManager->OtherPid() == base::GetCurrentProcId();
} }
/** /**

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

@ -141,7 +141,8 @@ static nsresult EncodeImageData(DataSourceSurface* aDataSurface,
aDataSurface->Unmap(); aDataSurface->Unmap();
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
return CallQueryInterface(encoder, aStream); encoder.forget(aStream);
return NS_OK;
} }
NS_IMETHODIMP imgTools::EncodeImage(imgIContainer *aContainer, NS_IMETHODIMP imgTools::EncodeImage(imgIContainer *aContainer,

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

@ -1957,7 +1957,7 @@ ChildImpl::OpenMainProcessActorRunnable::Run()
} }
// Make sure the parent knows it is same process. // Make sure the parent knows it is same process.
parentActor->SetOtherProcessId(kCurrentProcessId); parentActor->SetOtherProcessId(base::GetCurrentProcId());
// Now that Open() has succeeded transfer the ownership of the actors to IPDL. // Now that Open() has succeeded transfer the ownership of the actors to IPDL.
unused << parentActor.forget(); unused << parentActor.forget();

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

@ -265,7 +265,7 @@ bool DuplicateHandle(HANDLE aSourceHandle,
DWORD aDesiredAccess, DWORD aDesiredAccess,
DWORD aOptions) { DWORD aOptions) {
// If our process is the target just duplicate the handle. // If our process is the target just duplicate the handle.
if (aTargetProcessId == kCurrentProcessId) { if (aTargetProcessId == base::GetCurrentProcId()) {
return !!::DuplicateHandle(::GetCurrentProcess(), aSourceHandle, return !!::DuplicateHandle(::GetCurrentProcess(), aSourceHandle,
::GetCurrentProcess(), aTargetHandle, ::GetCurrentProcess(), aTargetHandle,
aDesiredAccess, false, aOptions); aDesiredAccess, false, aOptions);
@ -318,7 +318,7 @@ FatalError(const char* aProtocolName, const char* aMsg,
formattedMessage.AppendLiteral("\". Killing child side as a result."); formattedMessage.AppendLiteral("\". Killing child side as a result.");
NS_ERROR(formattedMessage.get()); NS_ERROR(formattedMessage.get());
if (aOtherPid != kInvalidProcessId && aOtherPid != kCurrentProcessId) { if (aOtherPid != kInvalidProcessId && aOtherPid != base::GetCurrentProcId()) {
ScopedProcessHandle otherProcessHandle; ScopedProcessHandle otherProcessHandle;
if (base::OpenProcessHandle(aOtherPid, &otherProcessHandle.rwget())) { if (base::OpenProcessHandle(aOtherPid, &otherProcessHandle.rwget())) {
if (!base::KillProcess(otherProcessHandle, if (!base::KillProcess(otherProcessHandle,

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

@ -72,7 +72,6 @@ const base::ProcessId kInvalidProcessId = kuint32max;
const base::ProcessHandle kInvalidProcessHandle = -1; const base::ProcessHandle kInvalidProcessHandle = -1;
const base::ProcessId kInvalidProcessId = -1; const base::ProcessId kInvalidProcessId = -1;
#endif #endif
const base::ProcessId kCurrentProcessId = base::GetCurrentProcId();
// Scoped base::ProcessHandle to ensure base::CloseProcessHandle is called. // Scoped base::ProcessHandle to ensure base::CloseProcessHandle is called.
struct ScopedProcessHandleTraits struct ScopedProcessHandleTraits

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

@ -185,7 +185,7 @@ class CxxCodeGen(CodePrinter, Visitor):
if md.inline: if md.inline:
self.write('inline ') self.write('inline ')
if md.inline: if md.never_inline:
self.write('MOZ_NEVER_INLINE ') self.write('MOZ_NEVER_INLINE ')
if md.static: if md.static:
self.write('static ') self.write('static ')

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

@ -3005,7 +3005,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
ret=Type.BOOL)) ret=Type.BOOL))
openmeth.addstmts([ openmeth.addstmts([
StmtExpr(ExprAssn(p.otherPidVar(), ExprVar('ipc::kCurrentProcessId'))), StmtExpr(ExprAssn(p.otherPidVar(), ExprCall(ExprVar('base::GetCurrentProcId')))),
StmtReturn(ExprCall(ExprSelect(p.channelVar(), '.', 'Open'), StmtReturn(ExprCall(ExprSelect(p.channelVar(), '.', 'Open'),
[ aChannel, aMessageLoop, sidevar ])) [ aChannel, aMessageLoop, sidevar ]))
]) ])

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

@ -19,7 +19,7 @@ bool
IPDLUnitTestProcessChild::Init() IPDLUnitTestProcessChild::Init()
{ {
IPDLUnitTestChildInit(IOThreadChild::channel(), IPDLUnitTestChildInit(IOThreadChild::channel(),
ParentId(), ParentPid(),
IOThreadChild::message_loop()); IOThreadChild::message_loop());
if (NS_FAILED(nsRegion::InitStatic())) if (NS_FAILED(nsRegion::InitStatic()))

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

@ -181,7 +181,7 @@ ${PARENT_ENABLED_CASES_PROC}
if (!transport) if (!transport)
fail("no transport"); fail("no transport");
base::ProcessHandle child = gSubprocess->GetChildProcessHandle(); base::ProcessId child = base::GetProcId(gSubprocess->GetChildProcessHandle());
switch (test) { switch (test) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

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

@ -27,15 +27,10 @@ TestBridgeMainParent::Main()
PTestBridgeMainSubParent* PTestBridgeMainSubParent*
TestBridgeMainParent::AllocPTestBridgeMainSubParent(Transport* transport, TestBridgeMainParent::AllocPTestBridgeMainSubParent(Transport* transport,
ProcessId otherProcess) ProcessId otherPid)
{ {
ProcessHandle h;
if (!base::OpenProcessHandle(otherProcess, &h)) {
return nullptr;
}
nsAutoPtr<TestBridgeMainSubParent> a(new TestBridgeMainSubParent(transport)); nsAutoPtr<TestBridgeMainSubParent> a(new TestBridgeMainSubParent(transport));
if (!a->Open(transport, h, XRE_GetIOMessageLoop(), ipc::ParentSide)) { if (!a->Open(transport, otherPid, XRE_GetIOMessageLoop(), ipc::ParentSide)) {
return nullptr; return nullptr;
} }
return a.forget(); return a.forget();
@ -110,7 +105,7 @@ TestBridgeMainChild::RecvStart()
fail("no transport"); fail("no transport");
TestBridgeSubParent* bsp = new TestBridgeSubParent(); TestBridgeSubParent* bsp = new TestBridgeSubParent();
bsp->Open(transport, mSubprocess->GetChildProcessHandle()); bsp->Open(transport, base::GetProcId(mSubprocess->GetChildProcessHandle()));
bsp->Main(); bsp->Main();
return true; return true;
@ -178,15 +173,10 @@ TestBridgeSubChild::RecvPing()
PTestBridgeMainSubChild* PTestBridgeMainSubChild*
TestBridgeSubChild::AllocPTestBridgeMainSubChild(Transport* transport, TestBridgeSubChild::AllocPTestBridgeMainSubChild(Transport* transport,
ProcessId otherProcess) ProcessId otherPid)
{ {
ProcessHandle h;
if (!base::OpenProcessHandle(otherProcess, &h)) {
return nullptr;
}
nsAutoPtr<TestBridgeMainSubChild> a(new TestBridgeMainSubChild(transport)); nsAutoPtr<TestBridgeMainSubChild> a(new TestBridgeMainSubChild(transport));
if (!a->Open(transport, h, XRE_GetIOMessageLoop(), ipc::ChildSide)) { if (!a->Open(transport, otherPid, XRE_GetIOMessageLoop(), ipc::ChildSide)) {
return nullptr; return nullptr;
} }

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

@ -494,7 +494,7 @@ TestDataStructuresChild::RecvStart()
Test15(); Test15();
Test16(); Test16();
Test17(); Test17();
if (OtherProcess() != 0) { if (OtherPid() != base::GetCurrentProcId()) {
//FIXME/bug 703317 allocation of nsIntRegion uses a global //FIXME/bug 703317 allocation of nsIntRegion uses a global
//region pool which breaks threads //region pool which breaks threads
Test18(); Test18();

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

@ -110,7 +110,7 @@ TestFailedCtorChild::DeallocPTestFailedCtorSubChild(PTestFailedCtorSubChild* act
void void
TestFailedCtorChild::ProcessingError(Result aCode, const char* aReason) TestFailedCtorChild::ProcessingError(Result aCode, const char* aReason)
{ {
if (OtherProcess() != 0) // thread-mode if (OtherPid() != base::GetCurrentProcId()) // thread-mode
_exit(0); _exit(0);
} }

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

@ -111,8 +111,14 @@ TestHangsParent::AnswerStackFrame()
void void
TestHangsParent::CleanUp() TestHangsParent::CleanUp()
{ {
if (!KillProcess(OtherProcess(), 0, false)) ipc::ScopedProcessHandle otherProcessHandle;
fail("terminating child process"); if (!base::OpenProcessHandle(OtherPid(), &otherProcessHandle.rwget())) {
fail("couldn't open child process");
} else {
if (!KillProcess(otherProcessHandle, 0, false)) {
fail("terminating child process");
}
}
Close(); Close();
} }

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

@ -54,29 +54,24 @@ TestOpensParent::Main()
static void static void
OpenParent(TestOpensOpenedParent* aParent, OpenParent(TestOpensOpenedParent* aParent,
Transport* aTransport, ProcessHandle aOtherProcess) Transport* aTransport, base::ProcessId aOtherPid)
{ {
AssertNotMainThread(); AssertNotMainThread();
// Open the actor on the off-main thread to park it there. // Open the actor on the off-main thread to park it there.
// Messages will be delivered to this thread's message loop // Messages will be delivered to this thread's message loop
// instead of the main thread's. // instead of the main thread's.
if (!aParent->Open(aTransport, aOtherProcess, if (!aParent->Open(aTransport, aOtherPid,
XRE_GetIOMessageLoop(), ipc::ParentSide)) XRE_GetIOMessageLoop(), ipc::ParentSide))
fail("opening Parent"); fail("opening Parent");
} }
PTestOpensOpenedParent* PTestOpensOpenedParent*
TestOpensParent::AllocPTestOpensOpenedParent(Transport* transport, TestOpensParent::AllocPTestOpensOpenedParent(Transport* transport,
ProcessId otherProcess) ProcessId otherPid)
{ {
gMainThread = MessageLoop::current(); gMainThread = MessageLoop::current();
ProcessHandle h;
if (!base::OpenProcessHandle(otherProcess, &h)) {
return nullptr;
}
gParentThread = new Thread("ParentThread"); gParentThread = new Thread("ParentThread");
if (!gParentThread->Start()) if (!gParentThread->Start())
fail("starting parent thread"); fail("starting parent thread");
@ -84,7 +79,7 @@ TestOpensParent::AllocPTestOpensOpenedParent(Transport* transport,
TestOpensOpenedParent* a = new TestOpensOpenedParent(transport); TestOpensOpenedParent* a = new TestOpensOpenedParent(transport);
gParentThread->message_loop()->PostTask( gParentThread->message_loop()->PostTask(
FROM_HERE, FROM_HERE,
NewRunnableFunction(OpenParent, a, transport, h)); NewRunnableFunction(OpenParent, a, transport, otherPid));
return a; return a;
} }
@ -174,14 +169,14 @@ TestOpensChild::RecvStart()
static void static void
OpenChild(TestOpensOpenedChild* aChild, OpenChild(TestOpensOpenedChild* aChild,
Transport* aTransport, ProcessHandle aOtherProcess) Transport* aTransport, base::ProcessId aOtherPid)
{ {
AssertNotMainThread(); AssertNotMainThread();
// Open the actor on the off-main thread to park it there. // Open the actor on the off-main thread to park it there.
// Messages will be delivered to this thread's message loop // Messages will be delivered to this thread's message loop
// instead of the main thread's. // instead of the main thread's.
if (!aChild->Open(aTransport, aOtherProcess, if (!aChild->Open(aTransport, aOtherPid,
XRE_GetIOMessageLoop(), ipc::ChildSide)) XRE_GetIOMessageLoop(), ipc::ChildSide))
fail("opening Child"); fail("opening Child");
@ -192,15 +187,10 @@ OpenChild(TestOpensOpenedChild* aChild,
PTestOpensOpenedChild* PTestOpensOpenedChild*
TestOpensChild::AllocPTestOpensOpenedChild(Transport* transport, TestOpensChild::AllocPTestOpensOpenedChild(Transport* transport,
ProcessId otherProcess) ProcessId otherPid)
{ {
gMainThread = MessageLoop::current(); gMainThread = MessageLoop::current();
ProcessHandle h;
if (!base::OpenProcessHandle(otherProcess, &h)) {
return nullptr;
}
gChildThread = new Thread("ChildThread"); gChildThread = new Thread("ChildThread");
if (!gChildThread->Start()) if (!gChildThread->Start())
fail("starting child thread"); fail("starting child thread");
@ -208,7 +198,7 @@ TestOpensChild::AllocPTestOpensOpenedChild(Transport* transport,
TestOpensOpenedChild* a = new TestOpensOpenedChild(transport); TestOpensOpenedChild* a = new TestOpensOpenedChild(transport);
gChildThread->message_loop()->PostTask( gChildThread->message_loop()->PostTask(
FROM_HERE, FROM_HERE,
NewRunnableFunction(OpenChild, a, transport, h)); NewRunnableFunction(OpenChild, a, transport, otherPid));
return a; return a;
} }

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

@ -116,7 +116,7 @@ def main(argv):
%sChild** child = %sChild** child =
reinterpret_cast<%sChild**>(&gChildActor); reinterpret_cast<%sChild**>(&gChildActor);
*child = new %sChild(); *child = new %sChild();
(*child)->Open(transport, parent, worker); (*child)->Open(transport, parentPid, worker);
return; return;
} }
'''% (t, t, t, t) for t in unittests+extras ]) '''% (t, t, t, t) for t in unittests+extras ])

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

@ -98,7 +98,8 @@ class Logging
} }
void formatObject(bool incoming, bool local, ObjectId id, nsCString& out) { void formatObject(bool incoming, bool local, ObjectId id, nsCString& out) {
const char* side, *objDesc; const char* side;
const char* objDesc;
void* ptr; void* ptr;
if (local == incoming) { if (local == incoming) {

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

@ -870,7 +870,8 @@ class HashTable : private AllocPolicy
++cur; ++cur;
} }
Entry* cur, *end; Entry* cur;
Entry* end;
#ifdef JS_DEBUG #ifdef JS_DEBUG
const HashTable* table_; const HashTable* table_;
uint64_t mutationCount; uint64_t mutationCount;
@ -1090,7 +1091,8 @@ class HashTable : private AllocPolicy
static void destroyTable(AllocPolicy& alloc, Entry* oldTable, uint32_t capacity) static void destroyTable(AllocPolicy& alloc, Entry* oldTable, uint32_t capacity)
{ {
for (Entry* e = oldTable, *end = e + capacity; e < end; ++e) Entry* end = oldTable + capacity;
for (Entry* e = oldTable; e < end; ++e)
e->destroyIfLive(); e->destroyIfLive();
alloc.free_(oldTable); alloc.free_(oldTable);
} }
@ -1346,7 +1348,8 @@ class HashTable : private AllocPolicy
table = newTable; table = newTable;
// Copy only live entries, leaving removed ones behind. // Copy only live entries, leaving removed ones behind.
for (Entry* src = oldTable, *end = src + oldCap; src < end; ++src) { Entry* end = oldTable + oldCap;
for (Entry* src = oldTable; src < end; ++src) {
if (src->isLive()) { if (src->isLive()) {
HashNumber hn = src->getKeyHash(); HashNumber hn = src->getKeyHash();
findFreeEntry(hn).setLive( findFreeEntry(hn).setLive(
@ -1480,7 +1483,8 @@ class HashTable : private AllocPolicy
memset(table, 0, sizeof(*table) * capacity()); memset(table, 0, sizeof(*table) * capacity());
} else { } else {
uint32_t tableCapacity = capacity(); uint32_t tableCapacity = capacity();
for (Entry* e = table, *end = table + tableCapacity; e < end; ++e) Entry* end = table + tableCapacity;
for (Entry* e = table; e < end; ++e)
e->clear(); e->clear();
} }
removedCount = 0; removedCount = 0;

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

@ -795,7 +795,8 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
* example, Rooted<JSObject> and Rooted<JSFunction>, which use the same * example, Rooted<JSObject> and Rooted<JSFunction>, which use the same
* stack head pointer for different classes. * stack head pointer for different classes.
*/ */
Rooted<void*>** stack, *prev; Rooted<void*>** stack;
Rooted<void*>* prev;
/* /*
* |ptr| must be the last field in Rooted because the analysis treats all * |ptr| must be the last field in Rooted because the analysis treats all

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

@ -6363,7 +6363,8 @@ CheckConditional(FunctionCompiler& f, ParseNode* ternary, MDefinition** def, Typ
if (!condType.isInt()) if (!condType.isInt())
return f.failf(cond, "%s is not a subtype of int", condType.toChars()); return f.failf(cond, "%s is not a subtype of int", condType.toChars());
MBasicBlock* thenBlock = nullptr, *elseBlock = nullptr; MBasicBlock* thenBlock = nullptr;
MBasicBlock* elseBlock = nullptr;
if (!f.branchAndStartThen(condDef, &thenBlock, &elseBlock, thenExpr, elseExpr)) if (!f.branchAndStartThen(condDef, &thenBlock, &elseBlock, thenExpr, elseExpr))
return false; return false;
@ -6482,7 +6483,8 @@ CheckAddOrSub(FunctionCompiler& f, ParseNode* expr, MDefinition** def, Type* typ
ParseNode* lhs = AddSubLeft(expr); ParseNode* lhs = AddSubLeft(expr);
ParseNode* rhs = AddSubRight(expr); ParseNode* rhs = AddSubRight(expr);
MDefinition* lhsDef, *rhsDef; MDefinition* lhsDef;
MDefinition* rhsDef;
Type lhsType, rhsType; Type lhsType, rhsType;
unsigned lhsNumAddOrSub, rhsNumAddOrSub; unsigned lhsNumAddOrSub, rhsNumAddOrSub;
@ -6545,7 +6547,8 @@ CheckDivOrMod(FunctionCompiler& f, ParseNode* expr, MDefinition** def, Type* typ
ParseNode* lhs = DivOrModLeft(expr); ParseNode* lhs = DivOrModLeft(expr);
ParseNode* rhs = DivOrModRight(expr); ParseNode* rhs = DivOrModRight(expr);
MDefinition* lhsDef, *rhsDef; MDefinition* lhsDef;
MDefinition* rhsDef;
Type lhsType, rhsType; Type lhsType, rhsType;
if (!CheckExpr(f, lhs, &lhsDef, &lhsType)) if (!CheckExpr(f, lhs, &lhsDef, &lhsType))
return false; return false;
@ -6600,7 +6603,8 @@ CheckComparison(FunctionCompiler& f, ParseNode* comp, MDefinition** def, Type* t
ParseNode* lhs = ComparisonLeft(comp); ParseNode* lhs = ComparisonLeft(comp);
ParseNode* rhs = ComparisonRight(comp); ParseNode* rhs = ComparisonRight(comp);
MDefinition* lhsDef, *rhsDef; MDefinition* lhsDef;
MDefinition* rhsDef;
Type lhsType, rhsType; Type lhsType, rhsType;
if (!CheckExpr(f, lhs, &lhsDef, &lhsType)) if (!CheckExpr(f, lhs, &lhsDef, &lhsType))
return false; return false;
@ -6947,9 +6951,12 @@ CheckIfConditional(FunctionCompiler& f, ParseNode* conditional, ParseNode* thenS
ParseNode* lhs = TernaryKid2(conditional); ParseNode* lhs = TernaryKid2(conditional);
ParseNode* rhs = TernaryKid3(conditional); ParseNode* rhs = TernaryKid3(conditional);
MBasicBlock* maybeAndTest = nullptr, *maybeOrTest = nullptr; MBasicBlock* maybeAndTest = nullptr;
MBasicBlock** ifTrueBlock = &maybeAndTest, **ifFalseBlock = &maybeOrTest; MBasicBlock* maybeOrTest = nullptr;
ParseNode* ifTrueBlockNode = lhs, *ifFalseBlockNode = rhs; MBasicBlock** ifTrueBlock = &maybeAndTest;
MBasicBlock** ifFalseBlock = &maybeOrTest;
ParseNode* ifTrueBlockNode = lhs;
ParseNode* ifFalseBlockNode = rhs;
// Try to spot opportunities for short-circuiting in the AND subpart // Try to spot opportunities for short-circuiting in the AND subpart
uint32_t andTestLiteral = 0; uint32_t andTestLiteral = 0;
@ -7071,7 +7078,8 @@ CheckIf(FunctionCompiler& f, ParseNode* ifStmt)
ParseNode* thenStmt = TernaryKid2(ifStmt); ParseNode* thenStmt = TernaryKid2(ifStmt);
ParseNode* elseStmt = TernaryKid3(ifStmt); ParseNode* elseStmt = TernaryKid3(ifStmt);
MBasicBlock* thenBlock = nullptr, *elseBlock = nullptr; MBasicBlock* thenBlock = nullptr;
MBasicBlock* elseBlock = nullptr;
ParseNode* elseOrJoinStmt = elseStmt ? elseStmt : nextStmt; ParseNode* elseOrJoinStmt = elseStmt ? elseStmt : nextStmt;
if (!CheckIfCondition(f, cond, thenStmt, elseOrJoinStmt, &thenBlock, &elseBlock)) if (!CheckIfCondition(f, cond, thenStmt, elseOrJoinStmt, &thenBlock, &elseBlock))

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

@ -137,9 +137,10 @@ class OrderedHashTable
} }
~OrderedHashTable() { ~OrderedHashTable() {
for (Range* r = ranges, *next; r; r = next) { for (Range* r = ranges; r; ) {
next = r->next; Range* next = r->next;
r->onTableDestroyed(); r->onTableDestroyed();
r = next;
} }
alloc.free_(hashTable); alloc.free_(hashTable);
freeData(data, dataLength); freeData(data, dataLength);
@ -593,7 +594,8 @@ class OrderedHashTable
void rehashInPlace() { void rehashInPlace() {
for (uint32_t i = 0, N = hashBuckets(); i < N; i++) for (uint32_t i = 0, N = hashBuckets(); i < N; i++)
hashTable[i] = nullptr; hashTable[i] = nullptr;
Data* wp = data, *end = data + dataLength; Data* wp = data;
Data* end = data + dataLength;
for (Data* rp = data; rp != end; rp++) { for (Data* rp = data; rp != end; rp++) {
if (!Ops::isEmpty(Ops::getKey(rp->element))) { if (!Ops::isEmpty(Ops::getKey(rp->element))) {
HashNumber h = prepareHash(Ops::getKey(rp->element)) >> hashShift; HashNumber h = prepareHash(Ops::getKey(rp->element)) >> hashShift;
@ -642,7 +644,8 @@ class OrderedHashTable
} }
Data* wp = newData; Data* wp = newData;
for (Data* p = data, *end = data + dataLength; p != end; p++) { Data* end = data + dataLength;
for (Data* p = data; p != end; p++) {
if (!Ops::isEmpty(Ops::getKey(p->element))) { if (!Ops::isEmpty(Ops::getKey(p->element))) {
HashNumber h = prepareHash(Ops::getKey(p->element)) >> newHashShift; HashNumber h = prepareHash(Ops::getKey(p->element)) >> newHashShift;
new (wp) Data(Move(p->element), newHashTable[h]); new (wp) Data(Move(p->element), newHashTable[h]);

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

@ -60,7 +60,8 @@ class InlineMap
MOZ_ASSERT(map.initialized()); MOZ_ASSERT(map.initialized());
} }
for (InlineElem* it = inl, *end = inl + inlNext; it != end; ++it) { InlineElem* end = inl + inlNext;
for (InlineElem* it = inl; it != end; ++it) {
if (it->key && !map.putNew(it->key, it->value)) if (it->key && !map.putNew(it->key, it->value))
return false; return false;
} }
@ -211,7 +212,8 @@ class InlineMap
if (usingMap()) if (usingMap())
return Ptr(map.lookup(key)); return Ptr(map.lookup(key));
for (InlineElem* it = inl, *end = inl + inlNext; it != end; ++it) { InlineElem* end = inl + inlNext;
for (InlineElem* it = inl; it != end; ++it) {
if (it->key == key) if (it->key == key)
return Ptr(it); return Ptr(it);
} }
@ -224,7 +226,8 @@ class InlineMap
if (usingMap()) if (usingMap())
return AddPtr(map.lookupForAdd(key)); return AddPtr(map.lookupForAdd(key));
for (InlineElem* it = inl, *end = inl + inlNext; it != end; ++it) { InlineElem* end = inl + inlNext;
for (InlineElem* it = inl; it != end; ++it) {
if (it->key == key) if (it->key == key)
return AddPtr(it, true); return AddPtr(it, true);
} }

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

@ -25,7 +25,9 @@ class SplayTree
{ {
struct Node { struct Node {
T item; T item;
Node* left, *right, *parent; Node* left;
Node* right;
Node* parent;
explicit Node(const T& item) explicit Node(const T& item)
: item(item), left(nullptr), right(nullptr), parent(nullptr) : item(item), left(nullptr), right(nullptr), parent(nullptr)
@ -33,7 +35,8 @@ class SplayTree
}; };
LifoAlloc* alloc; LifoAlloc* alloc;
Node* root, *freeList; Node* root;
Node* freeList;
#ifdef DEBUG #ifdef DEBUG
bool enableCheckCoherency; bool enableCheckCoherency;
@ -124,7 +127,8 @@ class SplayTree
// Find another node which can be swapped in for the root: either the // Find another node which can be swapped in for the root: either the
// rightmost child of the root's left, or the leftmost child of the // rightmost child of the root's left, or the leftmost child of the
// root's right. // root's right.
Node* swap, *swapChild; Node* swap;
Node* swapChild;
if (root->left) { if (root->left) {
swap = root->left; swap = root->left;
while (swap->right) while (swap->right)
@ -167,7 +171,8 @@ class SplayTree
Node* lookup(const T& v) Node* lookup(const T& v)
{ {
MOZ_ASSERT(root); MOZ_ASSERT(root);
Node* node = root, *parent; Node* node = root;
Node* parent;
do { do {
parent = node; parent = node;
int c = C::compare(v, node->item); int c = C::compare(v, node->item);

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

@ -2280,7 +2280,8 @@ BytecodeEmitter::emitPropLHS(ParseNode* pn, JSOp op)
*/ */
if (pn2->isKind(PNK_DOT)) { if (pn2->isKind(PNK_DOT)) {
ParseNode* pndot = pn2; ParseNode* pndot = pn2;
ParseNode* pnup = nullptr, *pndown; ParseNode* pnup = nullptr;
ParseNode* pndown;
ptrdiff_t top = offset(); ptrdiff_t top = offset();
for (;;) { for (;;) {
/* Reverse pndot->pn_expr to point up, not down. */ /* Reverse pndot->pn_expr to point up, not down. */
@ -6673,8 +6674,8 @@ BytecodeEmitter::emitDefaults(ParseNode* pn)
{ {
MOZ_ASSERT(pn->isKind(PNK_ARGSBODY)); MOZ_ASSERT(pn->isKind(PNK_ARGSBODY));
ParseNode* arg, *pnlast = pn->last(); ParseNode* pnlast = pn->last();
for (arg = pn->pn_head; arg != pnlast; arg = arg->pn_next) { for (ParseNode* arg = pn->pn_head; arg != pnlast; arg = arg->pn_next) {
if (!(arg->pn_dflags & PND_DEFAULT)) if (!(arg->pn_dflags & PND_DEFAULT))
continue; continue;
if (!bindNameToSlot(arg)) if (!bindNameToSlot(arg))

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше