зеркало из https://github.com/mozilla/gecko-dev.git
305 строки
8.7 KiB
C++
305 строки
8.7 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* 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 "RDDParent.h"
|
|
|
|
#if defined(XP_WIN)
|
|
# include <dwrite.h>
|
|
# include <process.h>
|
|
|
|
# include "WMF.h"
|
|
# include "WMFDecoderModule.h"
|
|
# include "mozilla/WinDllServices.h"
|
|
# include "mozilla/gfx/DeviceManagerDx.h"
|
|
#else
|
|
# include <unistd.h>
|
|
#endif
|
|
|
|
#include "PDMFactory.h"
|
|
#include "chrome/common/ipc_channel.h"
|
|
#include "gfxConfig.h"
|
|
#include "mozilla/Assertions.h"
|
|
#include "mozilla/HangDetails.h"
|
|
#include "mozilla/Preferences.h"
|
|
#include "mozilla/RemoteDecoderManagerChild.h"
|
|
#include "mozilla/RemoteDecoderManagerParent.h"
|
|
#include "mozilla/ScopeExit.h"
|
|
#include "mozilla/TimeStamp.h"
|
|
#include "mozilla/dom/MemoryReportRequest.h"
|
|
#include "mozilla/gfx/gfxVars.h"
|
|
#include "mozilla/ipc/CrashReporterClient.h"
|
|
#include "mozilla/ipc/ProcessChild.h"
|
|
|
|
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
|
|
# include "mozilla/Sandbox.h"
|
|
#endif
|
|
|
|
#ifdef MOZ_GECKO_PROFILER
|
|
# include "ChildProfilerController.h"
|
|
#endif
|
|
|
|
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
|
# include "RDDProcessHost.h"
|
|
# include "mozilla/Sandbox.h"
|
|
# include "nsMacUtilsImpl.h"
|
|
#endif
|
|
|
|
#include "ProcessUtils.h"
|
|
#include "nsDebugImpl.h"
|
|
#include "nsThreadManager.h"
|
|
|
|
namespace mozilla {
|
|
|
|
using namespace ipc;
|
|
using namespace gfx;
|
|
|
|
static RDDParent* sRDDParent;
|
|
|
|
RDDParent::RDDParent() : mLaunchTime(TimeStamp::Now()) { sRDDParent = this; }
|
|
|
|
RDDParent::~RDDParent() { sRDDParent = nullptr; }
|
|
|
|
/* static */
|
|
RDDParent* RDDParent::GetSingleton() {
|
|
MOZ_DIAGNOSTIC_ASSERT(sRDDParent);
|
|
return sRDDParent;
|
|
}
|
|
|
|
bool RDDParent::Init(base::ProcessId aParentPid, const char* aParentBuildID,
|
|
MessageLoop* aIOLoop, UniquePtr<IPC::Channel> aChannel) {
|
|
// Initialize the thread manager before starting IPC. Otherwise, messages
|
|
// may be posted to the main thread and we won't be able to process them.
|
|
if (NS_WARN_IF(NS_FAILED(nsThreadManager::get().Init()))) {
|
|
return false;
|
|
}
|
|
|
|
// Now it's safe to start IPC.
|
|
if (NS_WARN_IF(!Open(std::move(aChannel), aParentPid, aIOLoop))) {
|
|
return false;
|
|
}
|
|
|
|
nsDebugImpl::SetMultiprocessMode("RDD");
|
|
|
|
// This must be checked before any IPDL message, which may hit sentinel
|
|
// errors due to parent and content processes having different
|
|
// versions.
|
|
MessageChannel* channel = GetIPCChannel();
|
|
if (channel && !channel->SendBuildIDsMatchMessage(aParentBuildID)) {
|
|
// We need to quit this process if the buildID doesn't match the parent's.
|
|
// This can occur when an update occurred in the background.
|
|
ProcessChild::QuickExit();
|
|
}
|
|
|
|
// Init crash reporter support.
|
|
CrashReporterClient::InitSingleton(this);
|
|
|
|
if (NS_FAILED(NS_InitMinimalXPCOM())) {
|
|
return false;
|
|
}
|
|
|
|
gfxConfig::Init();
|
|
gfxVars::Initialize();
|
|
#ifdef XP_WIN
|
|
DeviceManagerDx::Init();
|
|
wmf::MFStartup();
|
|
#endif
|
|
|
|
mozilla::ipc::SetThisProcessName("RDD Process");
|
|
|
|
return true;
|
|
}
|
|
|
|
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
|
extern "C" {
|
|
void CGSShutdownServerConnections();
|
|
};
|
|
#endif
|
|
|
|
mozilla::ipc::IPCResult RDDParent::RecvInit(
|
|
nsTArray<GfxVarUpdate>&& vars, const Maybe<FileDescriptor>& aBrokerFd,
|
|
const bool& aCanRecordReleaseTelemetry) {
|
|
for (const auto& var : vars) {
|
|
gfxVars::ApplyUpdate(var);
|
|
}
|
|
|
|
auto supported = PDMFactory::Supported();
|
|
Unused << SendUpdateMediaCodecsSupported(supported);
|
|
|
|
#if defined(MOZ_SANDBOX)
|
|
# if defined(XP_MACOSX)
|
|
// Close all current connections to the WindowServer. This ensures that the
|
|
// Activity Monitor will not label the content process as "Not responding"
|
|
// because it's not running a native event loop. See bug 1384336.
|
|
CGSShutdownServerConnections();
|
|
|
|
# elif defined(XP_LINUX)
|
|
int fd = -1;
|
|
if (aBrokerFd.isSome()) {
|
|
fd = aBrokerFd.value().ClonePlatformHandle().release();
|
|
}
|
|
SetRemoteDataDecoderSandbox(fd);
|
|
# endif // XP_MACOSX/XP_LINUX
|
|
#endif // MOZ_SANDBOX
|
|
|
|
#if defined(XP_WIN)
|
|
if (aCanRecordReleaseTelemetry) {
|
|
RefPtr<DllServices> dllSvc(DllServices::Get());
|
|
dllSvc->StartUntrustedModulesProcessor();
|
|
}
|
|
#endif // defined(XP_WIN)
|
|
return IPC_OK();
|
|
}
|
|
|
|
IPCResult RDDParent::RecvUpdateVar(const GfxVarUpdate& aUpdate) {
|
|
#if defined(XP_WIN)
|
|
auto scopeExit = MakeScopeExit(
|
|
[couldUseHWDecoder = gfx::gfxVars::CanUseHardwareVideoDecoding()] {
|
|
if (couldUseHWDecoder != gfx::gfxVars::CanUseHardwareVideoDecoding()) {
|
|
// The capabilities of the system may have changed, force a refresh by
|
|
// re-initializing the WMF PDM.
|
|
WMFDecoderModule::Init();
|
|
Unused << RDDParent::GetSingleton()->SendUpdateMediaCodecsSupported(
|
|
PDMFactory::Supported(true /* force refresh */));
|
|
}
|
|
});
|
|
#endif
|
|
gfxVars::ApplyUpdate(aUpdate);
|
|
return IPC_OK();
|
|
}
|
|
|
|
mozilla::ipc::IPCResult RDDParent::RecvInitProfiler(
|
|
Endpoint<PProfilerChild>&& aEndpoint) {
|
|
#ifdef MOZ_GECKO_PROFILER
|
|
mProfilerController = ChildProfilerController::Create(std::move(aEndpoint));
|
|
#endif
|
|
return IPC_OK();
|
|
}
|
|
|
|
mozilla::ipc::IPCResult RDDParent::RecvNewContentRemoteDecoderManager(
|
|
Endpoint<PRemoteDecoderManagerParent>&& aEndpoint) {
|
|
if (!RemoteDecoderManagerParent::CreateForContent(std::move(aEndpoint))) {
|
|
return IPC_FAIL_NO_REASON(this);
|
|
}
|
|
return IPC_OK();
|
|
}
|
|
|
|
mozilla::ipc::IPCResult RDDParent::RecvInitVideoBridge(
|
|
Endpoint<PVideoBridgeChild>&& aEndpoint, const bool& aCreateHardwareDevice,
|
|
const ContentDeviceData& aContentDeviceData) {
|
|
if (!RemoteDecoderManagerParent::CreateVideoBridgeToOtherProcess(
|
|
std::move(aEndpoint))) {
|
|
return IPC_FAIL_NO_REASON(this);
|
|
}
|
|
|
|
gfxConfig::Inherit(
|
|
{
|
|
Feature::HW_COMPOSITING,
|
|
Feature::D3D11_COMPOSITING,
|
|
Feature::OPENGL_COMPOSITING,
|
|
Feature::ADVANCED_LAYERS,
|
|
Feature::DIRECT2D,
|
|
Feature::WEBGPU,
|
|
},
|
|
aContentDeviceData.prefs());
|
|
#ifdef XP_WIN
|
|
if (gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
|
|
auto* devmgr = DeviceManagerDx::Get();
|
|
if (devmgr) {
|
|
devmgr->ImportDeviceInfo(aContentDeviceData.d3d11());
|
|
if (aCreateHardwareDevice) {
|
|
devmgr->CreateContentDevices();
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return IPC_OK();
|
|
}
|
|
|
|
mozilla::ipc::IPCResult RDDParent::RecvRequestMemoryReport(
|
|
const uint32_t& aGeneration, const bool& aAnonymize,
|
|
const bool& aMinimizeMemoryUsage, const Maybe<FileDescriptor>& aDMDFile,
|
|
const RequestMemoryReportResolver& aResolver) {
|
|
nsPrintfCString processName("RDD (pid %u)", (unsigned)getpid());
|
|
|
|
mozilla::dom::MemoryReportRequestClient::Start(
|
|
aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, processName,
|
|
[&](const MemoryReport& aReport) {
|
|
Unused << GetSingleton()->SendAddMemoryReport(aReport);
|
|
},
|
|
aResolver);
|
|
return IPC_OK();
|
|
}
|
|
|
|
mozilla::ipc::IPCResult RDDParent::RecvGetUntrustedModulesData(
|
|
GetUntrustedModulesDataResolver&& aResolver) {
|
|
#if defined(XP_WIN)
|
|
RefPtr<DllServices> dllSvc(DllServices::Get());
|
|
dllSvc->GetUntrustedModulesData()->Then(
|
|
GetMainThreadSerialEventTarget(), __func__,
|
|
[aResolver](Maybe<UntrustedModulesData>&& aData) {
|
|
aResolver(std::move(aData));
|
|
},
|
|
[aResolver](nsresult aReason) { aResolver(Nothing()); });
|
|
return IPC_OK();
|
|
#else
|
|
return IPC_FAIL(this, "Unsupported on this platform");
|
|
#endif // defined(XP_WIN)
|
|
}
|
|
|
|
mozilla::ipc::IPCResult RDDParent::RecvPreferenceUpdate(const Pref& aPref) {
|
|
Preferences::SetPreference(aPref);
|
|
return IPC_OK();
|
|
}
|
|
|
|
void RDDParent::ActorDestroy(ActorDestroyReason aWhy) {
|
|
if (AbnormalShutdown == aWhy) {
|
|
NS_WARNING("Shutting down RDD process early due to a crash!");
|
|
ProcessChild::QuickExit();
|
|
}
|
|
|
|
#ifndef NS_FREE_PERMANENT_DATA
|
|
# ifdef XP_WIN
|
|
wmf::MFShutdown();
|
|
# endif
|
|
// No point in going through XPCOM shutdown because we don't keep persistent
|
|
// state.
|
|
ProcessChild::QuickExit();
|
|
#endif
|
|
|
|
// Wait until all RemoteDecoderManagerParent have closed.
|
|
mShutdownBlockers.WaitUntilClear(10 * 1000 /* 10s timeout*/)
|
|
->Then(GetCurrentSerialEventTarget(), __func__, [this]() {
|
|
|
|
#ifdef XP_WIN
|
|
wmf::MFShutdown();
|
|
#endif
|
|
|
|
#if defined(XP_WIN)
|
|
RefPtr<DllServices> dllSvc(DllServices::Get());
|
|
dllSvc->DisableFull();
|
|
#endif // defined(XP_WIN)
|
|
|
|
#ifdef MOZ_GECKO_PROFILER
|
|
if (mProfilerController) {
|
|
mProfilerController->Shutdown();
|
|
mProfilerController = nullptr;
|
|
}
|
|
#endif
|
|
|
|
RemoteDecoderManagerParent::ShutdownVideoBridge();
|
|
|
|
#ifdef XP_WIN
|
|
DeviceManagerDx::Shutdown();
|
|
#endif
|
|
gfxVars::Shutdown();
|
|
gfxConfig::Shutdown();
|
|
CrashReporterClient::DestroySingleton();
|
|
XRE_ShutdownChildProcess();
|
|
});
|
|
}
|
|
|
|
} // namespace mozilla
|