summaryrefslogtreecommitdiffstats
path: root/dom/media/ipc/RDDParent.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/ipc/RDDParent.cpp')
-rw-r--r--dom/media/ipc/RDDParent.cpp340
1 files changed, 340 insertions, 0 deletions
diff --git a/dom/media/ipc/RDDParent.cpp b/dom/media/ipc/RDDParent.cpp
new file mode 100644
index 0000000000..0fae2703e8
--- /dev/null
+++ b/dom/media/ipc/RDDParent.cpp
@@ -0,0 +1,340 @@
+/* -*- 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 "gfxConfig.h"
+#include "mozilla/Assertions.h"
+#include "mozilla/FOGIPC.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/RemoteDecoderManagerParent.h"
+#include "mozilla/TimeStamp.h"
+#include "mozilla/dom/MemoryReportRequest.h"
+#include "mozilla/gfx/gfxVars.h"
+#include "mozilla/glean/GleanMetrics.h"
+#include "mozilla/ipc/CrashReporterClient.h"
+#include "mozilla/ipc/ProcessChild.h"
+
+#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
+# include "mozilla/Sandbox.h"
+#endif
+
+#include "ChildProfilerController.h"
+
+#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
+# include "RDDProcessHost.h"
+# include "mozilla/Sandbox.h"
+# include "nsMacUtilsImpl.h"
+#endif
+
+#include "mozilla/ipc/ProcessUtils.h"
+#include "nsDebugImpl.h"
+#include "nsIXULRuntime.h"
+#include "nsThreadManager.h"
+
+#if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
+# include "mozilla/SandboxTestingChild.h"
+#endif
+
+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(mozilla::ipc::UntypedEndpoint&& aEndpoint,
+ const char* aParentBuildID) {
+ // 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(!aEndpoint.Bind(this))) {
+ 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();
+ auto rv = wmf::MediaFoundationInitializer::HasInitialized();
+ if (!rv) {
+ NS_WARNING("Failed to init Media Foundation in the RDD process");
+ }
+#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,
+ const bool& aIsReadyForBackgroundProcessing) {
+ 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(aIsReadyForBackgroundProcessing);
+ }
+#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) {
+ mProfilerController = ChildProfilerController::Create(std::move(aEndpoint));
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult RDDParent::RecvNewContentRemoteDecoderManager(
+ Endpoint<PRemoteDecoderManagerParent>&& aEndpoint,
+ const ContentParentId& aParentId) {
+ if (!RemoteDecoderManagerParent::CreateForContent(std::move(aEndpoint),
+ aParentId)) {
+ 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::DIRECT2D,
+ },
+ 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();
+}
+
+#if defined(XP_WIN)
+mozilla::ipc::IPCResult RDDParent::RecvGetUntrustedModulesData(
+ GetUntrustedModulesDataResolver&& aResolver) {
+ 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();
+}
+
+mozilla::ipc::IPCResult RDDParent::RecvUnblockUntrustedModulesThread() {
+ if (nsCOMPtr<nsIObserverService> obs =
+ mozilla::services::GetObserverService()) {
+ obs->NotifyObservers(nullptr, "unblock-untrusted-modules-thread", nullptr);
+ }
+ return IPC_OK();
+}
+#endif // defined(XP_WIN)
+
+mozilla::ipc::IPCResult RDDParent::RecvPreferenceUpdate(const Pref& aPref) {
+ Preferences::SetPreference(aPref);
+ return IPC_OK();
+}
+
+#if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
+mozilla::ipc::IPCResult RDDParent::RecvInitSandboxTesting(
+ Endpoint<PSandboxTestingChild>&& aEndpoint) {
+ if (!SandboxTestingChild::Initialize(std::move(aEndpoint))) {
+ return IPC_FAIL(
+ this, "InitSandboxTesting failed to initialise the child process.");
+ }
+ return IPC_OK();
+}
+#endif
+
+mozilla::ipc::IPCResult RDDParent::RecvFlushFOGData(
+ FlushFOGDataResolver&& aResolver) {
+ glean::FlushFOGData(std::move(aResolver));
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult RDDParent::RecvTestTriggerMetrics(
+ TestTriggerMetricsResolver&& aResolve) {
+ mozilla::glean::test_only_ipc::a_counter.Add(nsIXULRuntime::PROCESS_TYPE_RDD);
+ aResolve(true);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult RDDParent::RecvTestTelemetryProbes() {
+ const uint32_t kExpectedUintValue = 42;
+ Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_RDD_ONLY_UINT,
+ kExpectedUintValue);
+ return IPC_OK();
+}
+
+void RDDParent::ActorDestroy(ActorDestroyReason aWhy) {
+ if (AbnormalShutdown == aWhy) {
+ NS_WARNING("Shutting down RDD process early due to a crash!");
+ Telemetry::Accumulate(Telemetry::SUBPROCESS_ABNORMAL_ABORT, "rdd"_ns, 1);
+ ProcessChild::QuickExit();
+ }
+
+ // Send the last bits of Glean data over to the main process.
+ glean::FlushFOGData(
+ [](ByteBuf&& aBuf) { glean::SendFOGData(std::move(aBuf)); });
+
+#ifndef NS_FREE_PERMANENT_DATA
+ // 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__, [&]() {
+
+#if defined(XP_WIN)
+ RefPtr<DllServices> dllSvc(DllServices::Get());
+ dllSvc->DisableFull();
+#endif // defined(XP_WIN)
+
+ if (mProfilerController) {
+ mProfilerController->Shutdown();
+ mProfilerController = nullptr;
+ }
+
+ RemoteDecoderManagerParent::ShutdownVideoBridge();
+
+#ifdef XP_WIN
+ DeviceManagerDx::Shutdown();
+#endif
+ gfxVars::Shutdown();
+ gfxConfig::Shutdown();
+ CrashReporterClient::DestroySingleton();
+ XRE_ShutdownChildProcess();
+ });
+}
+
+} // namespace mozilla