fune/dom/plugins/ipc/FunctionBrokerParent.cpp

138 lines
4.1 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 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 "FunctionBrokerParent.h"
#include "FunctionBroker.h"
#include "FunctionBrokerThread.h"
namespace mozilla {
namespace plugins {
#if defined(XP_WIN)
UlongPairToIdMap sPairToIdMap;
IdToUlongPairMap sIdToPairMap;
PtrToIdMap sPtrToIdMap;
IdToPtrMap sIdToPtrMap;
#endif // defined(XP_WIN)
/* static */ FunctionBrokerParent* FunctionBrokerParent::Create(
Endpoint<PFunctionBrokerParent>&& aParentEnd) {
FunctionBrokerThread* thread = FunctionBrokerThread::Create();
if (!thread) {
return nullptr;
}
// We get the FunctionHooks so that they are created here, not on the
// message thread.
FunctionHook::GetHooks();
return new FunctionBrokerParent(thread, std::move(aParentEnd));
}
FunctionBrokerParent::FunctionBrokerParent(
FunctionBrokerThread* aThread, Endpoint<PFunctionBrokerParent>&& aParentEnd)
: mThread(aThread),
mMonitor("FunctionBrokerParent Lock"),
mShutdownDone(false) {
MOZ_ASSERT(mThread);
mThread->Dispatch(
NewNonOwningRunnableMethod<Endpoint<PFunctionBrokerParent>&&>(
"FunctionBrokerParent::Bind", this, &FunctionBrokerParent::Bind,
std::move(aParentEnd)));
}
FunctionBrokerParent::~FunctionBrokerParent() {
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
// Clean up any file permissions that we granted to the child process.
MOZ_RELEASE_ASSERT(NS_IsMainThread());
RemovePermissionsForProcess(OtherPid());
#endif
}
void FunctionBrokerParent::Bind(Endpoint<PFunctionBrokerParent>&& aEnd) {
MOZ_RELEASE_ASSERT(mThread->IsOnThread());
DebugOnly<bool> ok = aEnd.Bind(this);
MOZ_ASSERT(ok);
}
void FunctionBrokerParent::ShutdownOnBrokerThread() {
MOZ_ASSERT(mThread->IsOnThread());
Close();
// Notify waiting thread that we are done.
MonitorAutoLock lock(mMonitor);
mShutdownDone = true;
mMonitor.Notify();
}
void FunctionBrokerParent::Destroy(FunctionBrokerParent* aInst) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aInst);
{
// Hold the lock while we destroy the actor on the broker thread.
MonitorAutoLock lock(aInst->mMonitor);
aInst->mThread->Dispatch(NewNonOwningRunnableMethod(
"FunctionBrokerParent::ShutdownOnBrokerThread", aInst,
&FunctionBrokerParent::ShutdownOnBrokerThread));
// Wait for broker thread to complete destruction.
while (!aInst->mShutdownDone) {
aInst->mMonitor.Wait();
}
}
delete aInst;
}
void FunctionBrokerParent::ActorDestroy(ActorDestroyReason aWhy) {
MOZ_RELEASE_ASSERT(mThread->IsOnThread());
}
mozilla::ipc::IPCResult FunctionBrokerParent::RecvBrokerFunction(
const FunctionHookId& aFunctionId, const IpdlTuple& aInTuple,
IpdlTuple* aOutTuple) {
#if defined(XP_WIN)
MOZ_ASSERT(mThread->IsOnThread());
if (RunBrokeredFunction(OtherPid(), aFunctionId, aInTuple, aOutTuple)) {
return IPC_OK();
}
return IPC_FAIL_NO_REASON(this);
#else
MOZ_ASSERT_UNREACHABLE(
"BrokerFunction is currently only implemented on Windows.");
return IPC_FAIL_NO_REASON(this);
#endif
}
// static
bool FunctionBrokerParent::RunBrokeredFunction(
base::ProcessId aClientId, const FunctionHookId& aFunctionId,
const IPC::IpdlTuple& aInTuple, IPC::IpdlTuple* aOutTuple) {
if ((size_t)aFunctionId >= FunctionHook::GetHooks()->Length()) {
MOZ_ASSERT_UNREACHABLE("Invalid function ID");
return false;
}
FunctionHook* hook = FunctionHook::GetHooks()->ElementAt(aFunctionId);
MOZ_ASSERT(hook->FunctionId() == aFunctionId);
return hook->RunOriginalFunction(aClientId, aInTuple, aOutTuple);
}
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
mozilla::SandboxPermissions FunctionBrokerParent::sSandboxPermissions;
// static
void FunctionBrokerParent::RemovePermissionsForProcess(
base::ProcessId aClientId) {
sSandboxPermissions.RemovePermissionsForProcess(aClientId);
}
#endif // defined(XP_WIN) && defined(MOZ_SANDBOX)
} // namespace plugins
} // namespace mozilla