RDDParent.cpp (11132B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 #include "RDDParent.h" 7 8 #if defined(XP_WIN) 9 # include <dwrite.h> 10 # include <process.h> 11 12 # include "WMF.h" 13 # include "WMFDecoderModule.h" 14 # include "mozilla/WinDllServices.h" 15 # include "mozilla/gfx/DeviceManagerDx.h" 16 #else 17 # include <unistd.h> 18 #endif 19 20 #include "MediaCodecsSupport.h" 21 #include "gfxConfig.h" 22 #include "mozilla/Assertions.h" 23 #include "mozilla/FOGIPC.h" 24 #include "mozilla/Preferences.h" 25 #include "mozilla/RemoteMediaManagerParent.h" 26 #include "mozilla/TimeStamp.h" 27 #include "mozilla/dom/MemoryReportRequest.h" 28 #include "mozilla/gfx/gfxVars.h" 29 #include "mozilla/glean/GleanTestsTestMetrics.h" 30 #include "mozilla/glean/IpcMetrics.h" 31 #include "mozilla/ipc/CrashReporterClient.h" 32 #include "mozilla/ipc/ProcessChild.h" 33 34 #if defined(XP_LINUX) && defined(MOZ_SANDBOX) 35 # include "mozilla/Sandbox.h" 36 # include "mozilla/SandboxProfilerObserver.h" 37 #endif 38 39 #include "ChildProfilerController.h" 40 41 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX) 42 # include "RDDProcessHost.h" 43 # include "mozilla/Sandbox.h" 44 # include "nsMacUtilsImpl.h" 45 #endif 46 47 #include "mozilla/ipc/ProcessUtils.h" 48 #include "nsDebugImpl.h" 49 #include "nsIObserverService.h" 50 #include "nsIXULRuntime.h" 51 #include "nsThreadManager.h" 52 53 #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS) 54 # include "mozilla/SandboxTestingChild.h" 55 #endif 56 57 #if defined(XP_MACOSX) || defined(XP_LINUX) 58 # include "VideoUtils.h" 59 #endif 60 61 #if defined(MOZ_WIDGET_GTK) 62 # include "mozilla/widget/DMABufSurface.h" 63 #endif 64 65 namespace TelemetryScalar { 66 void Set(mozilla::Telemetry::ScalarID aId, uint32_t aValue); 67 } 68 69 namespace mozilla { 70 71 using namespace ipc; 72 using namespace gfx; 73 74 static RDDParent* sRDDParent; 75 76 RDDParent::RDDParent() : mLaunchTime(TimeStamp::Now()) { sRDDParent = this; } 77 78 RDDParent::~RDDParent() { sRDDParent = nullptr; } 79 80 /* static */ 81 RDDParent* RDDParent::GetSingleton() { 82 MOZ_DIAGNOSTIC_ASSERT(sRDDParent); 83 return sRDDParent; 84 } 85 86 bool RDDParent::Init(mozilla::ipc::UntypedEndpoint&& aEndpoint, 87 const char* aParentBuildID) { 88 // Initialize the thread manager before starting IPC. Otherwise, messages 89 // may be posted to the main thread and we won't be able to process them. 90 if (NS_WARN_IF(NS_FAILED(nsThreadManager::get().Init()))) { 91 return false; 92 } 93 94 // Now it's safe to start IPC. 95 if (NS_WARN_IF(!aEndpoint.Bind(this))) { 96 return false; 97 } 98 99 nsDebugImpl::SetMultiprocessMode("RDD"); 100 101 // This must be checked before any IPDL message, which may hit sentinel 102 // errors due to parent and content processes having different 103 // versions. 104 MessageChannel* channel = GetIPCChannel(); 105 if (channel && !channel->SendBuildIDsMatchMessage(aParentBuildID)) { 106 // We need to quit this process if the buildID doesn't match the parent's. 107 // This can occur when an update occurred in the background. 108 ProcessChild::QuickExit(); 109 } 110 111 // Init crash reporter support. 112 CrashReporterClient::InitSingleton(this); 113 114 if (NS_FAILED(NS_InitMinimalXPCOM())) { 115 return false; 116 } 117 118 gfxConfig::Init(); 119 gfxVars::Initialize(); 120 #ifdef XP_WIN 121 DeviceManagerDx::Init(); 122 auto rv = wmf::MediaFoundationInitializer::HasInitialized(); 123 if (!rv) { 124 NS_WARNING("Failed to init Media Foundation in the RDD process"); 125 } 126 #endif 127 128 mozilla::ipc::SetThisProcessName("RDD Process"); 129 130 return true; 131 } 132 133 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX) 134 extern "C" { 135 void CGSShutdownServerConnections(); 136 }; 137 #endif 138 139 mozilla::ipc::IPCResult RDDParent::RecvInit( 140 nsTArray<GfxVarUpdate>&& vars, const Maybe<FileDescriptor>& aBrokerFd, 141 const bool& aCanRecordReleaseTelemetry, 142 const bool& aIsReadyForBackgroundProcessing) { 143 gfxVars::ApplyUpdate(vars); 144 145 auto supported = media::MCSInfo::GetSupportFromFactory(); 146 (void)SendUpdateMediaCodecsSupported(supported); 147 148 #if defined(MOZ_SANDBOX) 149 # if defined(XP_MACOSX) 150 // Close all current connections to the WindowServer. This ensures that the 151 // Activity Monitor will not label the content process as "Not responding" 152 // because it's not running a native event loop. See bug 1384336. 153 CGSShutdownServerConnections(); 154 155 # elif defined(XP_LINUX) 156 int fd = -1; 157 if (aBrokerFd.isSome()) { 158 fd = aBrokerFd.value().ClonePlatformHandle().release(); 159 } 160 RegisterProfilerObserversForSandboxProfiler(); 161 SetRemoteDataDecoderSandbox(fd); 162 # endif // XP_MACOSX/XP_LINUX 163 #endif // MOZ_SANDBOX 164 165 #if defined(XP_WIN) 166 if (aCanRecordReleaseTelemetry) { 167 RefPtr<DllServices> dllSvc(DllServices::Get()); 168 dllSvc->StartUntrustedModulesProcessor(aIsReadyForBackgroundProcessing); 169 } 170 #endif // defined(XP_WIN) 171 return IPC_OK(); 172 } 173 174 IPCResult RDDParent::RecvUpdateVar(const nsTArray<GfxVarUpdate>& aUpdate) { 175 gfxVars::ApplyUpdate(aUpdate); 176 177 MOZ_ALWAYS_SUCCEEDS(NS_DispatchBackgroundTask( 178 NS_NewRunnableFunction( 179 "RDDParent::RecvUpdateVar", 180 []() { 181 NS_DispatchToMainThread(NS_NewRunnableFunction( 182 "RDDParent::UpdateMediaCodecsSupported", 183 [supported = media::MCSInfo::GetSupportFromFactory( 184 true /* force refresh */)]() { 185 if (auto* rdd = RDDParent::GetSingleton()) { 186 (void)rdd->SendUpdateMediaCodecsSupported(supported); 187 } 188 })); 189 }), 190 nsIEventTarget::DISPATCH_NORMAL)); 191 return IPC_OK(); 192 } 193 194 mozilla::ipc::IPCResult RDDParent::RecvInitProfiler( 195 Endpoint<PProfilerChild>&& aEndpoint) { 196 mProfilerController = ChildProfilerController::Create(std::move(aEndpoint)); 197 return IPC_OK(); 198 } 199 200 mozilla::ipc::IPCResult RDDParent::RecvNewContentRemoteMediaManager( 201 Endpoint<PRemoteMediaManagerParent>&& aEndpoint, 202 const ContentParentId& aParentId) { 203 if (!RemoteMediaManagerParent::CreateForContent(std::move(aEndpoint), 204 aParentId)) { 205 return IPC_FAIL_NO_REASON(this); 206 } 207 return IPC_OK(); 208 } 209 210 mozilla::ipc::IPCResult RDDParent::RecvInitVideoBridge( 211 Endpoint<PVideoBridgeChild>&& aEndpoint, const bool& aCreateHardwareDevice, 212 const ContentDeviceData& aContentDeviceData) { 213 if (!RemoteMediaManagerParent::CreateVideoBridgeToOtherProcess( 214 std::move(aEndpoint))) { 215 return IPC_FAIL_NO_REASON(this); 216 } 217 218 gfxConfig::Inherit( 219 { 220 Feature::HW_COMPOSITING, 221 Feature::D3D11_COMPOSITING, 222 Feature::OPENGL_COMPOSITING, 223 }, 224 aContentDeviceData.prefs()); 225 #ifdef XP_WIN 226 if (gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) { 227 auto* devmgr = DeviceManagerDx::Get(); 228 if (devmgr) { 229 devmgr->ImportDeviceInfo(aContentDeviceData.d3d11()); 230 if (aCreateHardwareDevice) { 231 devmgr->CreateContentDevices(); 232 } 233 } 234 } 235 #endif 236 237 return IPC_OK(); 238 } 239 240 mozilla::ipc::IPCResult RDDParent::RecvRequestMemoryReport( 241 const uint32_t& aGeneration, const bool& aAnonymize, 242 const bool& aMinimizeMemoryUsage, const Maybe<FileDescriptor>& aDMDFile, 243 const RequestMemoryReportResolver& aResolver) { 244 nsPrintfCString processName("RDD (pid %u)", (unsigned)getpid()); 245 246 mozilla::dom::MemoryReportRequestClient::Start( 247 aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, processName, 248 [&](const MemoryReport& aReport) { 249 (void)GetSingleton()->SendAddMemoryReport(aReport); 250 }, 251 aResolver); 252 return IPC_OK(); 253 } 254 255 #if defined(XP_WIN) 256 mozilla::ipc::IPCResult RDDParent::RecvGetUntrustedModulesData( 257 GetUntrustedModulesDataResolver&& aResolver) { 258 RefPtr<DllServices> dllSvc(DllServices::Get()); 259 dllSvc->GetUntrustedModulesData()->Then( 260 GetMainThreadSerialEventTarget(), __func__, 261 [aResolver](Maybe<UntrustedModulesData>&& aData) { 262 aResolver(std::move(aData)); 263 }, 264 [aResolver](nsresult aReason) { aResolver(Nothing()); }); 265 return IPC_OK(); 266 } 267 268 mozilla::ipc::IPCResult RDDParent::RecvUnblockUntrustedModulesThread() { 269 if (nsCOMPtr<nsIObserverService> obs = 270 mozilla::services::GetObserverService()) { 271 obs->NotifyObservers(nullptr, "unblock-untrusted-modules-thread", nullptr); 272 } 273 return IPC_OK(); 274 } 275 #endif // defined(XP_WIN) 276 277 mozilla::ipc::IPCResult RDDParent::RecvPreferenceUpdate(const Pref& aPref) { 278 Preferences::SetPreference(aPref); 279 return IPC_OK(); 280 } 281 282 #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS) 283 mozilla::ipc::IPCResult RDDParent::RecvInitSandboxTesting( 284 Endpoint<PSandboxTestingChild>&& aEndpoint) { 285 if (!SandboxTestingChild::Initialize(std::move(aEndpoint))) { 286 return IPC_FAIL( 287 this, "InitSandboxTesting failed to initialise the child process."); 288 } 289 return IPC_OK(); 290 } 291 #endif 292 293 mozilla::ipc::IPCResult RDDParent::RecvFlushFOGData( 294 FlushFOGDataResolver&& aResolver) { 295 glean::FlushFOGData(std::move(aResolver)); 296 return IPC_OK(); 297 } 298 299 mozilla::ipc::IPCResult RDDParent::RecvTestTriggerMetrics( 300 TestTriggerMetricsResolver&& aResolve) { 301 mozilla::glean::test_only_ipc::a_counter.Add(nsIXULRuntime::PROCESS_TYPE_RDD); 302 aResolve(true); 303 return IPC_OK(); 304 } 305 306 mozilla::ipc::IPCResult RDDParent::RecvTestTelemetryProbes() { 307 const uint32_t kExpectedUintValue = 42; 308 TelemetryScalar::Set(Telemetry::ScalarID::TELEMETRY_TEST_RDD_ONLY_UINT, 309 kExpectedUintValue); 310 return IPC_OK(); 311 } 312 313 void RDDParent::ActorDestroy(ActorDestroyReason aWhy) { 314 #if defined(XP_LINUX) && defined(MOZ_SANDBOX) 315 DestroySandboxProfiler(); 316 #endif 317 318 if (AbnormalShutdown == aWhy) { 319 NS_WARNING("Shutting down RDD process early due to a crash!"); 320 glean::subprocess::abnormal_abort.Get("rdd"_ns).Add(1); 321 ProcessChild::QuickExit(); 322 } 323 324 // Send the last bits of Glean data over to the main process. 325 glean::FlushFOGData( 326 [](ByteBuf&& aBuf) { glean::SendFOGData(std::move(aBuf)); }); 327 328 #ifndef NS_FREE_PERMANENT_DATA 329 // No point in going through XPCOM shutdown because we don't keep persistent 330 // state. 331 ProcessChild::QuickExit(); 332 #endif 333 334 // Wait until all RemoteMediaManagerParent have closed. 335 mShutdownBlockers.WaitUntilClear(10 * 1000 /* 10s timeout*/) 336 ->Then(GetCurrentSerialEventTarget(), __func__, [&]() { 337 338 #if defined(XP_WIN) 339 RefPtr<DllServices> dllSvc(DllServices::Get()); 340 dllSvc->DisableFull(); 341 #endif // defined(XP_WIN) 342 343 if (mProfilerController) { 344 mProfilerController->Shutdown(); 345 mProfilerController = nullptr; 346 } 347 348 RemoteMediaManagerParent::ShutdownVideoBridge(); 349 350 #if defined(MOZ_WIDGET_GTK) 351 // Linux runs VA-API decode on RDD process so we need to 352 // shutdown GL here. 353 DMABufSurface::ReleaseSnapshotGLContext(); 354 #endif 355 356 #ifdef XP_WIN 357 DeviceManagerDx::Shutdown(); 358 #endif 359 gfxVars::Shutdown(); 360 gfxConfig::Shutdown(); 361 CrashReporterClient::DestroySingleton(); 362 XRE_ShutdownChildProcess(); 363 }); 364 } 365 366 } // namespace mozilla