зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1088488 - Add GMPLoader interface to encapsulate loading GMPs, pass that to XRE_InitChildProcess. r=jesup,r=bsmedberg,r=glandium
This commit is contained in:
Родитель
a05d3eba03
Коммит
f3af16c459
|
@ -0,0 +1,124 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: sw=4 ts=4 et :
|
||||
* 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 "GMPLoader.h"
|
||||
#include <stdio.h>
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/NullPtr.h"
|
||||
#include "gmp-entrypoints.h"
|
||||
#include "prlink.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace mozilla {
|
||||
namespace gmp {
|
||||
|
||||
class GMPLoaderImpl : public GMPLoader {
|
||||
public:
|
||||
explicit GMPLoaderImpl(SandboxStarter* aStarter)
|
||||
: mSandboxStarter(aStarter)
|
||||
{}
|
||||
virtual ~GMPLoaderImpl() {}
|
||||
|
||||
virtual bool Load(const char* aLibPath,
|
||||
uint32_t aLibPathLen,
|
||||
char* aOriginSalt,
|
||||
uint32_t aOriginSaltLen,
|
||||
const GMPPlatformAPI* aPlatformAPI) MOZ_OVERRIDE;
|
||||
|
||||
virtual GMPErr GetAPI(const char* aAPIName,
|
||||
void* aHostAPI,
|
||||
void** aPluginAPI) MOZ_OVERRIDE;
|
||||
|
||||
virtual void Shutdown() MOZ_OVERRIDE;
|
||||
|
||||
#ifdef SANDBOX_NOT_STATICALLY_LINKED_INTO_PLUGIN_CONTAINER
|
||||
virtual void SetStartSandboxStarter(SandboxStarter* aStarter) MOZ_OVERRIDE {
|
||||
mSandboxStarter = aStarter;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
PRLibrary* mLib;
|
||||
GMPGetAPIFunc mGetAPIFunc;
|
||||
SandboxStarter* mSandboxStarter;
|
||||
};
|
||||
|
||||
GMPLoader* CreateGMPLoader(SandboxStarter* aStarter) {
|
||||
return static_cast<GMPLoader*>(new GMPLoaderImpl(aStarter));
|
||||
}
|
||||
|
||||
bool
|
||||
GMPLoaderImpl::Load(const char* aLibPath,
|
||||
uint32_t aLibPathLen,
|
||||
char* aOriginSalt,
|
||||
uint32_t aOriginSaltLen,
|
||||
const GMPPlatformAPI* aPlatformAPI)
|
||||
{
|
||||
std::string nodeId(aOriginSalt, aOriginSalt + aOriginSaltLen);
|
||||
|
||||
// TODO (subsequent patch): Hash node id with device id, send to GMP.
|
||||
|
||||
#if defined(MOZ_GMP_SANDBOX)
|
||||
// Start the sandbox now that we've generated the device bound node id.
|
||||
// This must happen after the node id is bound to the device id, as
|
||||
// generating the device id requires privileges.
|
||||
if (mSandboxStarter) {
|
||||
mSandboxStarter->Start();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Load the GMP.
|
||||
PRLibSpec libSpec;
|
||||
libSpec.value.pathname = aLibPath;
|
||||
libSpec.type = PR_LibSpec_Pathname;
|
||||
mLib = PR_LoadLibraryWithFlags(libSpec, 0);
|
||||
if (!mLib) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GMPInitFunc initFunc = reinterpret_cast<GMPInitFunc>(PR_FindFunctionSymbol(mLib, "GMPInit"));
|
||||
if (!initFunc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (initFunc(aPlatformAPI) != GMPNoErr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mGetAPIFunc = reinterpret_cast<GMPGetAPIFunc>(PR_FindFunctionSymbol(mLib, "GMPGetAPI"));
|
||||
if (!mGetAPIFunc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GMPErr
|
||||
GMPLoaderImpl::GetAPI(const char* aAPIName,
|
||||
void* aHostAPI,
|
||||
void** aPluginAPI)
|
||||
{
|
||||
return mGetAPIFunc ? mGetAPIFunc(aAPIName, aHostAPI, aPluginAPI)
|
||||
: GMPGenericErr;
|
||||
}
|
||||
|
||||
void
|
||||
GMPLoaderImpl::Shutdown()
|
||||
{
|
||||
if (mLib) {
|
||||
GMPShutdownFunc shutdownFunc = reinterpret_cast<GMPShutdownFunc>(PR_FindFunctionSymbol(mLib, "GMPShutdown"));
|
||||
if (shutdownFunc) {
|
||||
shutdownFunc();
|
||||
}
|
||||
PR_UnloadLibrary(mLib);
|
||||
mLib = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gmp
|
||||
} // namespace mozilla
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: sw=4 ts=4 et :
|
||||
* 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 GMP_LOADER_H__
|
||||
#define GMP_LOADER_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "gmp-entrypoints.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gmp {
|
||||
|
||||
class SandboxStarter {
|
||||
public:
|
||||
virtual ~SandboxStarter() {}
|
||||
virtual void Start() = 0;
|
||||
};
|
||||
|
||||
#if (defined(XP_LINUX) || defined(XP_MACOSX))
|
||||
#define SANDBOX_NOT_STATICALLY_LINKED_INTO_PLUGIN_CONTAINER 1
|
||||
#endif
|
||||
|
||||
// Encapsulates generating the device-bound node id, activating the sandbox,
|
||||
// loading the GMP, and passing the node id to the GMP (in that order).
|
||||
//
|
||||
// In Desktop Gecko, the implementation of this lives in plugin-container,
|
||||
// and is passed into XUL code from on startup. The GMP IPC child protocol actor
|
||||
// uses this interface to load and retrieve interfaces from the GMPs.
|
||||
//
|
||||
// In Desktop Gecko the implementation lives in the plugin-container so that
|
||||
// it can be covered by DRM vendor's voucher.
|
||||
//
|
||||
// On Android the GMPLoader implementation lives in libxul (because for the time
|
||||
// being GMPLoader relies upon NSPR, which we can't use in plugin-container
|
||||
// on Android).
|
||||
//
|
||||
// There is exactly one GMPLoader per GMP child process, and only one GMP
|
||||
// per child process (so the GMPLoader only loads one GMP).
|
||||
class GMPLoader {
|
||||
public:
|
||||
virtual ~GMPLoader() {}
|
||||
|
||||
// Calculates the device-bound node id, then activates the sandbox,
|
||||
// then loads the GMP library and (if applicable) passes the bound node id
|
||||
// to the GMP.
|
||||
virtual bool Load(const char* aLibPath,
|
||||
uint32_t aLibPathLen,
|
||||
char* aOriginSalt,
|
||||
uint32_t aOriginSaltLen,
|
||||
const GMPPlatformAPI* aPlatformAPI) = 0;
|
||||
|
||||
// Retrieves an interface pointer from the GMP.
|
||||
virtual GMPErr GetAPI(const char* aAPIName, void* aHostAPI, void** aPluginAPI) = 0;
|
||||
|
||||
// Calls the GMPShutdown function exported by the GMP lib, and unloads the
|
||||
// plugin library.
|
||||
virtual void Shutdown() = 0;
|
||||
|
||||
#ifdef SANDBOX_NOT_STATICALLY_LINKED_INTO_PLUGIN_CONTAINER
|
||||
// Encapsulates starting the sandbox on Linux and MacOSX.
|
||||
// TODO: Remove this, and put sandbox in plugin-container on all platforms.
|
||||
virtual void SetStartSandboxStarter(SandboxStarter* aStarter) = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
// On Desktop, this function resides in plugin-container.
|
||||
// On Mobile, this function resides in XUL.
|
||||
GMPLoader* CreateGMPLoader(SandboxStarter* aStarter);
|
||||
|
||||
} // namespace gmp
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // GMP_LOADER_H__
|
|
@ -59,5 +59,21 @@ GMPProcessChild::CleanUp()
|
|||
BackgroundHangMonitor::Shutdown();
|
||||
}
|
||||
|
||||
GMPLoader* GMPProcessChild::mLoader = nullptr;
|
||||
|
||||
/* static */
|
||||
void
|
||||
GMPProcessChild::SetGMPLoader(GMPLoader* aLoader)
|
||||
{
|
||||
mLoader = aLoader;
|
||||
}
|
||||
|
||||
/* static */
|
||||
GMPLoader*
|
||||
GMPProcessChild::GetGMPLoader()
|
||||
{
|
||||
return mLoader;
|
||||
}
|
||||
|
||||
} // namespace gmp
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
namespace mozilla {
|
||||
namespace gmp {
|
||||
|
||||
class GMPLoader;
|
||||
|
||||
class GMPProcessChild MOZ_FINAL : public mozilla::ipc::ProcessChild {
|
||||
protected:
|
||||
typedef mozilla::ipc::ProcessChild ProcessChild;
|
||||
|
@ -23,9 +25,15 @@ public:
|
|||
virtual bool Init() MOZ_OVERRIDE;
|
||||
virtual void CleanUp() MOZ_OVERRIDE;
|
||||
|
||||
// Set/get the GMPLoader singleton for this child process.
|
||||
// Note: The GMPLoader is not deleted by this object, the caller of
|
||||
// SetGMPLoader() must manage the GMPLoader's lifecycle.
|
||||
static void SetGMPLoader(GMPLoader* aHost);
|
||||
static GMPLoader* GetGMPLoader();
|
||||
|
||||
private:
|
||||
GMPChild mPlugin;
|
||||
|
||||
static GMPLoader* mLoader;
|
||||
DISALLOW_COPY_AND_ASSIGN(GMPProcessChild);
|
||||
};
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ EXPORTS += [
|
|||
'GMPDecryptorParent.h',
|
||||
'GMPDecryptorProxy.h',
|
||||
'GMPEncryptedBufferDataImpl.h',
|
||||
'GMPLoader.h',
|
||||
'GMPMessageUtils.h',
|
||||
'GMPParent.h',
|
||||
'GMPPlatform.h',
|
||||
|
@ -62,6 +63,13 @@ EXPORTS += [
|
|||
'GMPVideoPlaneImpl.h',
|
||||
]
|
||||
|
||||
# We link GMPLoader into xul on B2G/Fennec as its code does not need to be
|
||||
# covered by a DRM vendor's voucher.
|
||||
if CONFIG['OS_TARGET'] == 'Android':
|
||||
SOURCES += [
|
||||
'GMPLoader.cpp',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'GMPAudioDecoderChild.cpp',
|
||||
'GMPAudioDecoderParent.cpp',
|
||||
|
|
|
@ -33,6 +33,13 @@ LOCAL_INCLUDES += [
|
|||
'/xpcom/base',
|
||||
]
|
||||
|
||||
# We link GMPLoader into plugin-container on desktop so that its code is
|
||||
# covered by the desktop DRM vendor's voucher.
|
||||
if CONFIG['OS_TARGET'] != 'Android':
|
||||
SOURCES += [
|
||||
'../../dom/media/gmp/GMPLoader.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
|
||||
# For sandbox includes and the include dependencies those have
|
||||
LOCAL_INCLUDES += [
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
// FIXME/cjones testing
|
||||
#if !defined(OS_WIN)
|
||||
|
@ -21,6 +22,8 @@
|
|||
#include "nsSetDllDirectory.h"
|
||||
#endif
|
||||
|
||||
#include "GMPLoader.h"
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
#include "sandbox/chromium/base/basictypes.h"
|
||||
#include "sandbox/win/src/sandbox.h"
|
||||
|
@ -82,8 +85,29 @@ void StartSandboxCallback()
|
|||
target_service->LowerToken();
|
||||
}
|
||||
}
|
||||
|
||||
class WinSandboxStarter : public mozilla::gmp::SandboxStarter {
|
||||
public:
|
||||
virtual void Start() MOZ_OVERRIDE {
|
||||
StartSandboxCallback();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
mozilla::gmp::SandboxStarter*
|
||||
MakeSandboxStarter()
|
||||
{
|
||||
// Note: Linux and MacOSX create their SandboxStarters inside xul code,
|
||||
// they need to change to statically link their sandbox code into
|
||||
// plugin-container. Once they do that, we can create SandboxStarters for
|
||||
// them here.
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
return new WinSandboxStarter();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
content_process_main(int argc, char* argv[])
|
||||
{
|
||||
|
@ -154,8 +178,16 @@ content_process_main(int argc, char* argv[])
|
|||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
nsresult rv = XRE_InitChildProcess(argc, argv);
|
||||
nsAutoPtr<mozilla::gmp::GMPLoader> loader;
|
||||
#if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_GONK)
|
||||
// On desktop, the GMPLoader lives in plugin-container, so that its
|
||||
// code can be covered by an EME/GMP vendor's voucher.
|
||||
nsAutoPtr<mozilla::gmp::SandboxStarter> starter(MakeSandboxStarter());
|
||||
if (XRE_GetProcessType() == GeckoProcessType_GMPlugin) {
|
||||
loader = mozilla::gmp::CreateGMPLoader(starter);
|
||||
}
|
||||
#endif
|
||||
nsresult rv = XRE_InitChildProcess(argc, argv, loader);
|
||||
NS_ENSURE_SUCCESS(rv, 1);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -445,11 +445,11 @@ ChildProcessInit(int argc, char* argv[])
|
|||
void (*fXRE_SetProcessType)(char*);
|
||||
xul_dlsym("XRE_SetProcessType", &fXRE_SetProcessType);
|
||||
|
||||
mozglueresult (*fXRE_InitChildProcess)(int, char**);
|
||||
mozglueresult (*fXRE_InitChildProcess)(int, char**, void*);
|
||||
xul_dlsym("XRE_InitChildProcess", &fXRE_InitChildProcess);
|
||||
|
||||
fXRE_SetProcessType(argv[--argc]);
|
||||
|
||||
return fXRE_InitChildProcess(argc, argv);
|
||||
return fXRE_InitChildProcess(argc, argv, nullptr);
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
#include "mozilla/ipc/XPCShellEnvironment.h"
|
||||
|
||||
#include "GMPProcessChild.h"
|
||||
#include "GMPLoader.h"
|
||||
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
|
@ -104,6 +105,10 @@ using mozilla::dom::ContentProcess;
|
|||
using mozilla::dom::ContentParent;
|
||||
using mozilla::dom::ContentChild;
|
||||
|
||||
using mozilla::gmp::GMPLoader;
|
||||
using mozilla::gmp::CreateGMPLoader;
|
||||
using mozilla::gmp::GMPProcessChild;
|
||||
|
||||
using mozilla::ipc::TestShellParent;
|
||||
using mozilla::ipc::TestShellCommandParent;
|
||||
using mozilla::ipc::XPCShellEnvironment;
|
||||
|
@ -288,12 +293,25 @@ SetTaskbarGroupId(const nsString& aId)
|
|||
|
||||
nsresult
|
||||
XRE_InitChildProcess(int aArgc,
|
||||
char* aArgv[])
|
||||
char* aArgv[],
|
||||
GMPLoader* aGMPLoader)
|
||||
{
|
||||
NS_ENSURE_ARG_MIN(aArgc, 2);
|
||||
NS_ENSURE_ARG_POINTER(aArgv);
|
||||
NS_ENSURE_ARG_POINTER(aArgv[0]);
|
||||
|
||||
#if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_GONK)
|
||||
// On non-Fennec Gecko, the GMPLoader code resides in plugin-container,
|
||||
// and we must forward it through to the GMP code here.
|
||||
GMPProcessChild::SetGMPLoader(aGMPLoader);
|
||||
#else
|
||||
// On Fennec, the GMPLoader's code resides inside XUL (because for the time
|
||||
// being GMPLoader relies upon NSPR, which we can't use in plugin-container
|
||||
// on Android), so we create it here inside XUL and pass it to the GMP code.
|
||||
nsAutoPtr<GMPLoader> loader(CreateGMPLoader(nullptr));
|
||||
GMPProcessChild::SetGMPLoader(loader);
|
||||
#endif
|
||||
|
||||
#if defined(XP_WIN)
|
||||
// From the --attach-console support in nsNativeAppSupportWin.cpp, but
|
||||
// here we are a content child process, so we always attempt to attach
|
||||
|
|
|
@ -393,9 +393,16 @@ XRE_API(bool,
|
|||
XRE_SetRemoteExceptionHandler, (const char* aPipe))
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace gmp {
|
||||
class GMPLoader;
|
||||
} // namespace gmp
|
||||
} // namepsace mozilla
|
||||
|
||||
XRE_API(nsresult,
|
||||
XRE_InitChildProcess, (int aArgc,
|
||||
char* aArgv[]))
|
||||
char* aArgv[],
|
||||
mozilla::gmp::GMPLoader* aGMPLoader))
|
||||
|
||||
XRE_API(GeckoProcessType,
|
||||
XRE_GetProcessType, ())
|
||||
|
|
Загрузка…
Ссылка в новой задаче