Bug 1057908 - GeckoMediaPluginService needs to be proxied from Content processes to parent process. Part 1 - split GeckoMediaPluginService into a part for chrome and a part for both content and chrome. r=jwwang.

This commit is contained in:
Peter Van der Beken 2015-02-09 21:54:12 +01:00
parent b9e2957259
commit e98292c191
14 changed files with 1596 additions and 1379 deletions

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GMPAudioDecoder.h"
#include "nsServiceManagerUtils.h"
namespace mozilla {

View File

@ -87,7 +87,7 @@ GMPParent::CloneFrom(const GMPParent* aOther)
}
nsresult
GMPParent::Init(GeckoMediaPluginService *aService, nsIFile* aPluginDir)
GMPParent::Init(GeckoMediaPluginServiceParent* aService, nsIFile* aPluginDir)
{
MOZ_ASSERT(aPluginDir);
MOZ_ASSERT(aService);
@ -188,8 +188,8 @@ AbortWaitingForGMPAsyncShutdown(nsITimer* aTimer, void* aClosure)
{
NS_WARNING("Timed out waiting for GMP async shutdown!");
GMPParent* parent = reinterpret_cast<GMPParent*>(aClosure);
nsRefPtr<GeckoMediaPluginService> service =
GeckoMediaPluginService::GetGeckoMediaPluginService();
nsRefPtr<GeckoMediaPluginServiceParent> service =
GeckoMediaPluginServiceParent::GetSingleton();
if (service) {
service->AsyncShutdownComplete(parent);
}
@ -216,8 +216,8 @@ GMPParent::EnsureAsyncShutdownTimeoutSet()
}
int32_t timeout = GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT;
nsRefPtr<GeckoMediaPluginService> service =
GeckoMediaPluginService::GetGeckoMediaPluginService();
nsRefPtr<GeckoMediaPluginServiceParent> service =
GeckoMediaPluginServiceParent::GetSingleton();
if (service) {
timeout = service->AsyncShutdownTimeoutMs();
}

View File

@ -7,7 +7,7 @@
#define GMPParent_h_
#include "GMPProcessParent.h"
#include "GMPService.h"
#include "GMPServiceParent.h"
#include "GMPAudioDecoderParent.h"
#include "GMPDecryptorParent.h"
#include "GMPVideoDecoderParent.h"
@ -62,7 +62,7 @@ public:
GMPParent();
nsresult Init(GeckoMediaPluginService *aService, nsIFile* aPluginDir);
nsresult Init(GeckoMediaPluginServiceParent* aService, nsIFile* aPluginDir);
nsresult CloneFrom(const GMPParent* aOther);
void Crash();
@ -138,7 +138,7 @@ public:
private:
~GMPParent();
nsRefPtr<GeckoMediaPluginService> mService;
nsRefPtr<GeckoMediaPluginServiceParent> mService;
bool EnsureProcessLoaded();
nsresult ReadGMPMetaData();
#ifdef MOZ_CRASHREPORTER

File diff suppressed because it is too large Load Diff

View File

@ -15,37 +15,47 @@
#include "nsString.h"
#include "nsCOMPtr.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;
namespace mozilla {
extern PRLogModuleInfo* GetGMPLog();
namespace gmp {
class GMPParent;
#define GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT 3000
class GeckoMediaPluginService final : public mozIGeckoMediaPluginService
, public nsIObserver
class GeckoMediaPluginService : public mozIGeckoMediaPluginService
, public nsIObserver
{
public:
static already_AddRefed<GeckoMediaPluginService> GetGeckoMediaPluginService();
GeckoMediaPluginService();
nsresult Init();
virtual nsresult Init();
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_MOZIGECKOMEDIAPLUGINSERVICE
NS_DECL_NSIOBSERVER
void AsyncShutdownNeeded(GMPParent* aParent);
void AsyncShutdownComplete(GMPParent* aParent);
void AbortAsyncShutdown();
// mozIGeckoMediaPluginService
NS_IMETHOD GetThread(nsIThread** aThread) override;
NS_IMETHOD HasPluginForAPI(const nsACString& aAPI, nsTArray<nsCString>* aTags,
bool *aRetVal) override;
NS_IMETHOD GetGMPVideoDecoder(nsTArray<nsCString>* aTags,
const nsACString& aNodeId,
GMPVideoHost** aOutVideoHost,
GMPVideoDecoderProxy** aGMPVD) override;
NS_IMETHOD GetGMPVideoEncoder(nsTArray<nsCString>* aTags,
const nsACString& aNodeId,
GMPVideoHost **aOutVideoHost,
GMPVideoEncoderProxy** aGMPVE) override;
NS_IMETHOD GetGMPAudioDecoder(nsTArray<nsCString>* aTags,
const nsACString& aNodeId,
GMPAudioDecoderProxy **aGMPAD) override;
NS_IMETHOD GetGMPDecryptor(nsTArray<nsCString>* aTags,
const nsACString& aNodeId,
GMPDecryptorProxy** aDecryptor) override;
int32_t AsyncShutdownTimeoutMs();
@ -77,120 +87,28 @@ public:
const nsACString& aPluginName,
const nsAString& aPluginDumpId);
private:
~GeckoMediaPluginService();
protected:
GeckoMediaPluginService();
virtual ~GeckoMediaPluginService();
virtual void InitializePlugins() = 0;
virtual GMPParent* SelectPluginForAPI(const nsACString& aNodeId,
const nsCString& aAPI,
const nsTArray<nsCString>& aTags) = 0;
nsresult GMPDispatch(nsIRunnable* event, uint32_t flags = NS_DISPATCH_NORMAL);
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);
void ShutdownGMPThread();
protected:
friend class GMPParent;
void ReAddOnGMPThread(nsRefPtr<GMPParent>& aOld);
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;
Mutex mMutex; // Protects mGMPThread and mGMPThreadShutdown and some members
// in derived classes.
nsCOMPtr<nsIThread> mGMPThread;
bool mShuttingDown;
bool mGMPThreadShutdown;
bool mShuttingDownOnGMPThread;
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 mozilla

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,167 @@
/* -*- 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 "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,
nsACString& aOutId) override;
NS_DECL_MOZIGECKOMEDIAPLUGINCHROMESERVICE
NS_DECL_NSIOBSERVER
void AsyncShutdownNeeded(GMPParent* aParent);
void AsyncShutdownComplete(GMPParent* aParent);
void AbortAsyncShutdown();
int32_t AsyncShutdownTimeoutMs();
private:
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);
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;
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);
} // namespace gmp
} // namespace mozilla
#endif // GMPServiceParent_h_

View File

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

View File

@ -7,6 +7,7 @@
XPIDL_MODULE = 'content_geckomediaplugins'
XPIDL_SOURCES += [
'mozIGeckoMediaPluginChromeService.idl',
'mozIGeckoMediaPluginService.idl',
]
@ -46,6 +47,7 @@ EXPORTS += [
'GMPProcessChild.h',
'GMPProcessParent.h',
'GMPService.h',
'GMPServiceParent.h',
'GMPSharedMemManager.h',
'GMPStorageChild.h',
'GMPStorageParent.h',
@ -84,6 +86,7 @@ UNIFIED_SOURCES += [
'GMPProcessChild.cpp',
'GMPProcessParent.cpp',
'GMPService.cpp',
'GMPServiceParent.cpp',
'GMPSharedMemManager.cpp',
'GMPStorageChild.cpp',
'GMPStorageParent.cpp',

View File

@ -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();
};

View File

@ -5,8 +5,6 @@
#include "nsISupports.idl"
#include "nsIThread.idl"
#include "nsIPrincipal.idl"
#include "nsIFile.idl"
%{C++
#include "nsTArray.h"
@ -21,12 +19,11 @@ class GMPVideoHost;
[ptr] native GMPVideoDecoderProxy(GMPVideoDecoderProxy);
[ptr] native GMPVideoEncoderProxy(GMPVideoEncoderProxy);
[ptr] native GMPVideoHost(GMPVideoHost);
[ptr] native MessageLoop(MessageLoop);
[ptr] native TagArray(nsTArray<nsCString>);
[ptr] native GMPDecryptorProxy(GMPDecryptorProxy);
[ptr] native GMPAudioDecoderProxy(GMPAudioDecoderProxy);
[scriptable, uuid(168a1c68-dc41-4da7-82a5-991874ad5e58)]
[scriptable, uuid(fed4d2d8-87d8-42fe-a141-98c15b5f7a1e)]
interface mozIGeckoMediaPluginService : nsISupports
{
@ -85,46 +82,10 @@ interface mozIGeckoMediaPluginService : nsISupports
// Callable only on GMP thread.
GMPDecryptorProxy getGMPDecryptor(in TagArray tags, in ACString nodeId);
/**
* 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);
/**
* Gets the NodeId for a (origin, urlbarOrigin, isInprivateBrowsing) tuple.
*/
ACString getNodeId(in AString origin,
in AString topLevelOrigin,
in bool inPrivateBrowsingMode);
/**
* 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();
};

View File

@ -11,12 +11,13 @@
#include "GMPVideoDecoderProxy.h"
#include "GMPVideoEncoderProxy.h"
#include "GMPDecryptorProxy.h"
#include "GMPService.h"
#include "GMPServiceParent.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsIFile.h"
#include "nsISimpleEnumerator.h"
#include "mozilla/Atomics.h"
#include "nsNSSComponent.h"
#include "mozilla/DebugOnly.h"
#if defined(XP_WIN)
#include "mozilla/WindowsVersion.h"
@ -158,8 +159,8 @@ template<typename T>
static nsresult
EnumerateGMPStorageDir(const nsACString& aDir, T&& aDirIter)
{
nsRefPtr<GeckoMediaPluginService> service =
GeckoMediaPluginService::GetGeckoMediaPluginService();
nsRefPtr<GeckoMediaPluginServiceParent> service =
GeckoMediaPluginServiceParent::GetSingleton();
MOZ_ASSERT(service);
// $profileDir/gmp/
@ -317,8 +318,8 @@ GetNodeId(const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
bool aInPBMode)
{
nsRefPtr<GeckoMediaPluginService> service =
GeckoMediaPluginService::GetGeckoMediaPluginService();
nsRefPtr<GeckoMediaPluginServiceParent> service =
GeckoMediaPluginServiceParent::GetSingleton();
EXPECT_TRUE(service);
nsCString nodeId;
nsresult rv = service->GetNodeId(aOrigin,
@ -332,8 +333,8 @@ GetNodeId(const nsAString& aOrigin,
static bool
IsGMPStorageIsEmpty()
{
nsRefPtr<GeckoMediaPluginService> service =
GeckoMediaPluginService::GetGeckoMediaPluginService();
nsRefPtr<GeckoMediaPluginServiceParent> service =
GeckoMediaPluginServiceParent::GetSingleton();
MOZ_ASSERT(service);
nsCOMPtr<nsIFile> storage;
nsresult rv = service->GetStorageDir(getter_AddRefs(storage));
@ -545,8 +546,8 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
}
void TestForgetThisSite_Forget(nsAutoPtr<NodeInfo> aSiteInfo) {
nsRefPtr<GeckoMediaPluginService> service =
GeckoMediaPluginService::GetGeckoMediaPluginService();
nsRefPtr<GeckoMediaPluginServiceParent> service =
GeckoMediaPluginServiceParent::GetSingleton();
service->ForgetThisSite(NS_ConvertUTF8toUTF16(aSiteInfo->siteToForget));
nsCOMPtr<nsIThread> thread;

View File

@ -82,7 +82,7 @@ this.ForgetAboutSite = {
// EME
let mps = Cc["@mozilla.org/gecko-media-plugin-service;1"].
getService(Ci.mozIGeckoMediaPluginService);
getService(Ci.mozIGeckoMediaPluginChromeService);
mps.forgetThisSite(aDomain);
// Plugin data

View File

@ -68,7 +68,7 @@ const GMP_PLUGINS = [
XPCOMUtils.defineLazyGetter(this, "pluginsBundle",
() => Services.strings.createBundle("chrome://global/locale/plugins.properties"));
XPCOMUtils.defineLazyGetter(this, "gmpService",
() => Cc["@mozilla.org/gecko-media-plugin-service;1"].getService(Ci.mozIGeckoMediaPluginService));
() => Cc["@mozilla.org/gecko-media-plugin-service;1"].getService(Ci.mozIGeckoMediaPluginChromeService));
let messageManager = Cc["@mozilla.org/globalmessagemanager;1"]
.getService(Ci.nsIMessageListenerManager);