/* -*- 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" #include "mozilla/ipc/Endpoint.h" namespace mozilla::plugins { #if defined(XP_WIN) UlongPairToIdMap sPairToIdMap; IdToUlongPairMap sIdToPairMap; PtrToIdMap sPtrToIdMap; IdToPtrMap sIdToPtrMap; #endif // defined(XP_WIN) /* static */ FunctionBrokerParent* FunctionBrokerParent::Create( Endpoint&& 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&& aParentEnd) : mThread(aThread), mMonitor("FunctionBrokerParent Lock"), mShutdownDone(false) { MOZ_ASSERT(mThread); mThread->Dispatch( NewNonOwningRunnableMethod&&>( "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&& aEnd) { MOZ_RELEASE_ASSERT(mThread->IsOnThread()); DebugOnly 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 mozilla::plugins