mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
66d1734f54
Also refactors how sandbox support and disabling are handled, and allows simulating a lack of sandbox support with an env var (for testing without rebuilding a kernel).
402 lines
9.0 KiB
C++
402 lines
9.0 KiB
C++
/* -*- 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 "GMPChild.h"
|
|
#include "GMPVideoDecoderChild.h"
|
|
#include "GMPVideoEncoderChild.h"
|
|
#include "GMPAudioDecoderChild.h"
|
|
#include "GMPDecryptorChild.h"
|
|
#include "GMPVideoHost.h"
|
|
#include "nsIFile.h"
|
|
#include "nsXULAppAPI.h"
|
|
#include "gmp-video-decode.h"
|
|
#include "gmp-video-encode.h"
|
|
#include "GMPPlatform.h"
|
|
#include "mozilla/dom/CrashReporterChild.h"
|
|
|
|
using mozilla::dom::CrashReporterChild;
|
|
|
|
#ifdef XP_WIN
|
|
#include <stdlib.h> // for _exit()
|
|
#else
|
|
#include <unistd.h> // for _exit()
|
|
#endif
|
|
|
|
#if defined(XP_WIN)
|
|
#define TARGET_SANDBOX_EXPORTS
|
|
#include "mozilla/sandboxTarget.h"
|
|
#elif defined (MOZ_GMP_SANDBOX)
|
|
#if defined(XP_LINUX) || defined(XP_MACOSX)
|
|
#include "mozilla/Sandbox.h"
|
|
#endif
|
|
#endif
|
|
|
|
namespace mozilla {
|
|
namespace gmp {
|
|
|
|
GMPChild::GMPChild()
|
|
: mLib(nullptr)
|
|
, mGetAPIFunc(nullptr)
|
|
, mGMPMessageLoop(MessageLoop::current())
|
|
{
|
|
}
|
|
|
|
GMPChild::~GMPChild()
|
|
{
|
|
}
|
|
|
|
static bool
|
|
GetPluginBinaryPath(const std::string& aPluginPath,
|
|
nsCString &aPluginBinaryPath)
|
|
{
|
|
nsDependentCString pluginPath(aPluginPath.c_str());
|
|
|
|
nsCOMPtr<nsIFile> libFile;
|
|
nsresult rv = NS_NewNativeLocalFile(pluginPath, true, getter_AddRefs(libFile));
|
|
if (NS_FAILED(rv)) {
|
|
return false;
|
|
}
|
|
|
|
nsAutoString leafName;
|
|
if (NS_FAILED(libFile->GetLeafName(leafName))) {
|
|
return false;
|
|
}
|
|
nsAutoString baseName(Substring(leafName, 4, leafName.Length() - 1));
|
|
|
|
#if defined(XP_MACOSX)
|
|
nsAutoString binaryName = NS_LITERAL_STRING("lib") + baseName + NS_LITERAL_STRING(".dylib");
|
|
#elif defined(OS_POSIX)
|
|
nsAutoString binaryName = NS_LITERAL_STRING("lib") + baseName + NS_LITERAL_STRING(".so");
|
|
#elif defined(XP_WIN)
|
|
nsAutoString binaryName = baseName + NS_LITERAL_STRING(".dll");
|
|
#else
|
|
#error not defined
|
|
#endif
|
|
libFile->AppendRelativePath(binaryName);
|
|
|
|
libFile->GetNativePath(aPluginBinaryPath);
|
|
return true;
|
|
}
|
|
|
|
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
|
|
void
|
|
GMPChild::OnChannelConnected(int32_t aPid)
|
|
{
|
|
MacSandboxInfo info;
|
|
info.type = MacSandboxType_Plugin;
|
|
info.pluginInfo.type = MacSandboxPluginType_GMPlugin_Default;
|
|
info.pluginInfo.pluginPath.Assign(mPluginPath.c_str());
|
|
|
|
nsAutoCString pluginBinaryPath;
|
|
if (!GetPluginBinaryPath(mPluginPath, pluginBinaryPath)) {
|
|
MOZ_CRASH("Error scanning plugin path");
|
|
}
|
|
mPluginBinaryPath.Assign(pluginBinaryPath);
|
|
info.pluginInfo.pluginBinaryPath.Assign(pluginBinaryPath);
|
|
|
|
nsAutoCString err;
|
|
if (!mozilla::StartMacSandbox(info, err)) {
|
|
NS_WARNING(err.get());
|
|
MOZ_CRASH("sandbox_init() failed");
|
|
}
|
|
|
|
if (!LoadPluginLibrary(mPluginPath)) {
|
|
err.AppendPrintf("Failed to load GMP plugin \"%s\"",
|
|
mPluginPath.c_str());
|
|
NS_WARNING(err.get());
|
|
MOZ_CRASH("Failed to load GMP plugin");
|
|
}
|
|
}
|
|
#endif // XP_MACOSX && MOZ_GMP_SANDBOX
|
|
|
|
void
|
|
GMPChild::CheckThread()
|
|
{
|
|
MOZ_ASSERT(mGMPMessageLoop == MessageLoop::current());
|
|
}
|
|
|
|
bool
|
|
GMPChild::Init(const std::string& aPluginPath,
|
|
base::ProcessHandle aParentProcessHandle,
|
|
MessageLoop* aIOLoop,
|
|
IPC::Channel* aChannel)
|
|
{
|
|
if (!Open(aChannel, aParentProcessHandle, aIOLoop)) {
|
|
return false;
|
|
}
|
|
|
|
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
|
|
mPluginPath = aPluginPath;
|
|
return true;
|
|
#endif
|
|
|
|
#ifdef MOZ_CRASHREPORTER
|
|
SendPCrashReporterConstructor(CrashReporter::CurrentThreadId());
|
|
#endif
|
|
#if defined(XP_WIN)
|
|
mozilla::SandboxTarget::Instance()->StartSandbox();
|
|
#endif
|
|
|
|
return LoadPluginLibrary(aPluginPath);
|
|
}
|
|
|
|
bool
|
|
GMPChild::LoadPluginLibrary(const std::string& aPluginPath)
|
|
{
|
|
nsAutoCString nativePath;
|
|
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
|
|
nativePath.Assign(mPluginBinaryPath);
|
|
#else
|
|
if (!GetPluginBinaryPath(aPluginPath, nativePath)) {
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
|
|
// Enable sandboxing here -- we know the plugin file's path, but
|
|
// this process's execution hasn't been affected by its content yet.
|
|
MOZ_ASSERT(mozilla::CanSandboxMediaPlugin());
|
|
mozilla::SetMediaPluginSandbox(nativePath.get());
|
|
#endif
|
|
|
|
mLib = PR_LoadLibrary(nativePath.get());
|
|
if (!mLib) {
|
|
return false;
|
|
}
|
|
|
|
GMPInitFunc initFunc = reinterpret_cast<GMPInitFunc>(PR_FindFunctionSymbol(mLib, "GMPInit"));
|
|
if (!initFunc) {
|
|
return false;
|
|
}
|
|
|
|
auto platformAPI = new GMPPlatformAPI();
|
|
InitPlatformAPI(*platformAPI, this);
|
|
|
|
if (initFunc(platformAPI) != GMPNoErr) {
|
|
return false;
|
|
}
|
|
|
|
mGetAPIFunc = reinterpret_cast<GMPGetAPIFunc>(PR_FindFunctionSymbol(mLib, "GMPGetAPI"));
|
|
if (!mGetAPIFunc) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
MessageLoop*
|
|
GMPChild::GMPMessageLoop()
|
|
{
|
|
return mGMPMessageLoop;
|
|
}
|
|
|
|
void
|
|
GMPChild::ActorDestroy(ActorDestroyReason aWhy)
|
|
{
|
|
if (mLib) {
|
|
GMPShutdownFunc shutdownFunc = reinterpret_cast<GMPShutdownFunc>(PR_FindFunctionSymbol(mLib, "GMPShutdown"));
|
|
if (shutdownFunc) {
|
|
shutdownFunc();
|
|
}
|
|
}
|
|
|
|
if (AbnormalShutdown == aWhy) {
|
|
NS_WARNING("Abnormal shutdown of GMP process!");
|
|
_exit(0);
|
|
}
|
|
|
|
XRE_ShutdownChildProcess();
|
|
}
|
|
|
|
void
|
|
GMPChild::ProcessingError(Result aWhat)
|
|
{
|
|
switch (aWhat) {
|
|
case MsgDropped:
|
|
_exit(0); // Don't trigger a crash report.
|
|
case MsgNotKnown:
|
|
MOZ_CRASH("aborting because of MsgNotKnown");
|
|
case MsgNotAllowed:
|
|
MOZ_CRASH("aborting because of MsgNotAllowed");
|
|
case MsgPayloadError:
|
|
MOZ_CRASH("aborting because of MsgPayloadError");
|
|
case MsgProcessingError:
|
|
MOZ_CRASH("aborting because of MsgProcessingError");
|
|
case MsgRouteError:
|
|
MOZ_CRASH("aborting because of MsgRouteError");
|
|
case MsgValueError:
|
|
MOZ_CRASH("aborting because of MsgValueError");
|
|
default:
|
|
MOZ_CRASH("not reached");
|
|
}
|
|
}
|
|
|
|
PGMPAudioDecoderChild*
|
|
GMPChild::AllocPGMPAudioDecoderChild()
|
|
{
|
|
return new GMPAudioDecoderChild(this);
|
|
}
|
|
|
|
bool
|
|
GMPChild::DeallocPGMPAudioDecoderChild(PGMPAudioDecoderChild* aActor)
|
|
{
|
|
delete aActor;
|
|
return true;
|
|
}
|
|
|
|
mozilla::dom::PCrashReporterChild*
|
|
GMPChild::AllocPCrashReporterChild(const NativeThreadId& aThread)
|
|
{
|
|
return new CrashReporterChild();
|
|
}
|
|
|
|
bool
|
|
GMPChild::DeallocPCrashReporterChild(PCrashReporterChild* aCrashReporter)
|
|
{
|
|
delete aCrashReporter;
|
|
return true;
|
|
}
|
|
|
|
PGMPVideoDecoderChild*
|
|
GMPChild::AllocPGMPVideoDecoderChild()
|
|
{
|
|
return new GMPVideoDecoderChild(this);
|
|
}
|
|
|
|
bool
|
|
GMPChild::DeallocPGMPVideoDecoderChild(PGMPVideoDecoderChild* aActor)
|
|
{
|
|
delete aActor;
|
|
return true;
|
|
}
|
|
|
|
PGMPDecryptorChild*
|
|
GMPChild::AllocPGMPDecryptorChild()
|
|
{
|
|
return new GMPDecryptorChild(this);
|
|
}
|
|
|
|
bool
|
|
GMPChild::DeallocPGMPDecryptorChild(PGMPDecryptorChild* aActor)
|
|
{
|
|
delete aActor;
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
GMPChild::RecvPGMPAudioDecoderConstructor(PGMPAudioDecoderChild* aActor)
|
|
{
|
|
auto vdc = static_cast<GMPAudioDecoderChild*>(aActor);
|
|
|
|
void* vd = nullptr;
|
|
GMPErr err = mGetAPIFunc("decode-audio", &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 = mGetAPIFunc("decode-video", &vdc->Host(), &vd);
|
|
if (err != GMPNoErr || !vd) {
|
|
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 = mGetAPIFunc("encode-video", &vec->Host(), &ve);
|
|
if (err != GMPNoErr || !ve) {
|
|
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 = mGetAPIFunc("eme-decrypt", host, &session);
|
|
if (err != GMPNoErr || !session) {
|
|
return false;
|
|
}
|
|
|
|
child->Init(static_cast<GMPDecryptor*>(session));
|
|
|
|
return true;
|
|
}
|
|
|
|
PGMPTimerChild*
|
|
GMPChild::AllocPGMPTimerChild()
|
|
{
|
|
return new GMPTimerChild(this);
|
|
}
|
|
|
|
bool
|
|
GMPChild::DeallocPGMPTimerChild(PGMPTimerChild* aActor)
|
|
{
|
|
MOZ_ASSERT(mTimerChild == static_cast<GMPTimerChild*>(aActor));
|
|
mTimerChild = nullptr;
|
|
return true;
|
|
}
|
|
|
|
GMPTimerChild*
|
|
GMPChild::GetGMPTimers()
|
|
{
|
|
if (!mTimerChild) {
|
|
PGMPTimerChild* sc = SendPGMPTimerConstructor();
|
|
if (!sc) {
|
|
return nullptr;
|
|
}
|
|
mTimerChild = static_cast<GMPTimerChild*>(sc);
|
|
}
|
|
return mTimerChild;
|
|
}
|
|
|
|
bool
|
|
GMPChild::RecvCrashPluginNow()
|
|
{
|
|
MOZ_CRASH();
|
|
return true;
|
|
}
|
|
|
|
} // namespace gmp
|
|
} // namespace mozilla
|