ContentChild.cpp (178777B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=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 7 #ifdef MOZ_WIDGET_ANDROID 8 # include "AndroidDecoderModule.h" 9 #endif 10 11 #include "BrowserChild.h" 12 #include "ContentChild.h" 13 #include "GMPServiceChild.h" 14 #include "GeckoProfiler.h" 15 #include "Geolocation.h" 16 #include "HandlerServiceChild.h" 17 #include "ScrollingMetrics.h" 18 #include "gfxUtils.h" 19 #include "imgLoader.h" 20 #include "mozilla/AppShutdown.h" 21 #include "mozilla/Attributes.h" 22 #include "mozilla/BackgroundHangMonitor.h" 23 #include "mozilla/BasePrincipal.h" 24 #include "mozilla/ClipboardContentAnalysisChild.h" 25 #include "mozilla/ClipboardReadRequestChild.h" 26 #include "mozilla/Components.h" 27 #include "mozilla/FOGIPC.h" 28 #include "mozilla/HangDetails.h" 29 #include "mozilla/LoadInfo.h" 30 #include "mozilla/Logging.h" 31 #include "mozilla/LookAndFeel.h" 32 #include "mozilla/MemoryTelemetry.h" 33 #include "mozilla/NullPrincipal.h" 34 #include "mozilla/PerfStats.h" 35 #include "mozilla/Preferences.h" 36 #include "mozilla/ProcessHangMonitorIPC.h" 37 #include "mozilla/RemoteLazyInputStreamChild.h" 38 #include "mozilla/RemoteMediaManagerChild.h" 39 #include "mozilla/SchedulerGroup.h" 40 #include "mozilla/ScopeExit.h" 41 #include "mozilla/SharedStyleSheetCache.h" 42 #include "mozilla/SimpleEnumerator.h" 43 #include "mozilla/SpinEventLoopUntil.h" 44 #include "mozilla/StaticPrefs_browser.h" 45 #include "mozilla/StaticPrefs_dom.h" 46 #include "mozilla/StaticPrefs_fission.h" 47 #include "mozilla/StaticPrefs_javascript.h" 48 #include "mozilla/StaticPrefs_media.h" 49 #include "mozilla/StaticPrefs_threads.h" 50 #include "mozilla/StorageAccessAPIHelper.h" 51 #include "mozilla/TelemetryIPC.h" 52 #include "mozilla/WebBrowserPersistDocumentChild.h" 53 #include "mozilla/devtools/HeapSnapshotTempFileHelperChild.h" 54 #include "mozilla/dom/AutoSuppressEventHandlingAndSuspend.h" 55 #include "mozilla/dom/BlobImpl.h" 56 #include "mozilla/dom/BrowserBridgeHost.h" 57 #include "mozilla/dom/BrowsingContext.h" 58 #include "mozilla/dom/BrowsingContextGroup.h" 59 #include "mozilla/dom/ChildProcessChannelListener.h" 60 #include "mozilla/dom/ChildProcessMessageManager.h" 61 #include "mozilla/dom/ClientManager.h" 62 #include "mozilla/dom/ContentParent.h" 63 #include "mozilla/dom/ContentPlaybackController.h" 64 #include "mozilla/dom/ContentProcessManager.h" 65 #include "mozilla/dom/ContentProcessMessageManager.h" 66 #include "mozilla/dom/DataTransfer.h" 67 #include "mozilla/dom/DocGroup.h" 68 #include "mozilla/dom/ExternalHelperAppChild.h" 69 #include "mozilla/dom/GetFilesHelper.h" 70 #include "mozilla/dom/IPCBlobUtils.h" 71 #include "mozilla/dom/InProcessChild.h" 72 #include "mozilla/dom/JSActorService.h" 73 #include "mozilla/dom/JSProcessActorBinding.h" 74 #include "mozilla/dom/JSProcessActorChild.h" 75 #include "mozilla/dom/LSObject.h" 76 #include "mozilla/dom/MemoryReportRequest.h" 77 #include "mozilla/dom/Navigation.h" 78 #include "mozilla/dom/PSessionStorageObserverChild.h" 79 #include "mozilla/dom/PolicyContainer.h" 80 #include "mozilla/dom/PostMessageEvent.h" 81 #include "mozilla/dom/PushNotifier.h" 82 #include "mozilla/dom/RemoteWorkerDebuggerManagerChild.h" 83 #include "mozilla/dom/RemoteWorkerService.h" 84 #include "mozilla/dom/ScreenOrientation.h" 85 #include "mozilla/dom/ServiceWorkerManager.h" 86 #include "mozilla/dom/SessionStorageManager.h" 87 #include "mozilla/dom/SharedScriptCache.h" 88 #include "mozilla/dom/URLClassifierChild.h" 89 #include "mozilla/dom/UserActivation.h" 90 #include "mozilla/dom/WindowGlobalChild.h" 91 #include "mozilla/dom/WorkerDebugger.h" 92 #include "mozilla/dom/WorkerDebuggerManager.h" 93 #include "mozilla/dom/ipc/SharedMap.h" 94 #include "mozilla/extensions/ExtensionsChild.h" 95 #include "mozilla/extensions/StreamFilterParent.h" 96 #include "mozilla/gfx/2D.h" 97 #include "mozilla/gfx/Logging.h" 98 #include "mozilla/gfx/gfxVars.h" 99 #include "mozilla/hal_sandbox/PHalChild.h" 100 #include "mozilla/image/FetchDecodedImage.h" 101 #include "mozilla/intl/L10nRegistry.h" 102 #include "mozilla/intl/LocaleService.h" 103 #include "mozilla/intl/OSPreferences.h" 104 #include "mozilla/ipc/BackgroundChild.h" 105 #include "mozilla/ipc/Endpoint.h" 106 #include "mozilla/ipc/FileDescriptorUtils.h" 107 #include "mozilla/ipc/GeckoChildProcessHost.h" 108 #include "mozilla/ipc/ProcessChild.h" 109 #include "mozilla/ipc/TestShellChild.h" 110 #include "mozilla/layers/APZChild.h" 111 #include "mozilla/layers/CompositorManagerChild.h" 112 #include "mozilla/layers/ContentProcessController.h" 113 #include "mozilla/layers/ImageBridgeChild.h" 114 #include "nsNSSComponent.h" 115 #include "nsXPLookAndFeel.h" 116 #ifdef NS_PRINTING 117 # include "mozilla/layout/RemotePrintJobChild.h" 118 #endif 119 #include "ChildProfilerController.h" 120 #include "mozilla/loader/ScriptCacheActors.h" 121 #include "mozilla/media/MediaChild.h" 122 #include "mozilla/net/CaptivePortalService.h" 123 #include "mozilla/net/ChildDNSService.h" 124 #include "mozilla/net/CookieServiceChild.h" 125 #include "mozilla/net/DocumentChannelChild.h" 126 #include "mozilla/net/HttpChannelChild.h" 127 #include "mozilla/widget/RemoteLookAndFeel.h" 128 #include "mozilla/widget/ScreenManager.h" 129 #include "mozilla/widget/WidgetMessageUtils.h" 130 #include "mozmemory.h" 131 #include "nsBaseDragService.h" 132 #include "nsDocShellLoadTypes.h" 133 #include "nsFocusManager.h" 134 #include "nsHttpHandler.h" 135 #include "nsIConsoleService.h" 136 #include "nsIInputStreamChannel.h" 137 #include "nsILayoutHistoryState.h" 138 #include "nsILoadGroup.h" 139 #include "nsIOpenWindowInfo.h" 140 #include "nsISimpleEnumerator.h" 141 #include "nsIStringBundle.h" 142 #include "nsIURIMutator.h" 143 #include "nsOpenWindowInfo.h" 144 #include "nsQueryObject.h" 145 #include "nsRefreshDriver.h" 146 #include "nsSandboxFlags.h" 147 148 #if defined(MOZ_SANDBOX) 149 # include "mozilla/SandboxSettings.h" 150 # if defined(XP_WIN) 151 # include "mozilla/ProcInfo.h" 152 # include "mozilla/sandboxTarget.h" 153 # elif defined(XP_LINUX) 154 # include "CubebUtils.h" 155 # include "mozilla/Sandbox.h" 156 # include "mozilla/SandboxInfo.h" 157 # include "mozilla/SandboxProfilerObserver.h" 158 # elif defined(XP_MACOSX) 159 # include <CoreGraphics/CGError.h> 160 161 # include "mozilla/Sandbox.h" 162 # elif defined(__OpenBSD__) 163 # include <err.h> 164 # include <sys/stat.h> 165 # include <unistd.h> 166 167 # include <fstream> 168 169 # include "BinaryPath.h" 170 # include "SpecialSystemDirectory.h" 171 # include "mozilla/ipc/UtilityProcessSandboxing.h" 172 # include "nsILineInputStream.h" 173 # endif 174 # if defined(MOZ_DEBUG) && defined(ENABLE_TESTS) 175 # include "mozilla/SandboxTestingChild.h" 176 # endif 177 #endif 178 179 #include "IHistory.h" 180 #include "ReferrerInfo.h" 181 #include "SandboxHal.h" 182 #include "base/message_loop.h" 183 #include "base/process_util.h" 184 #include "base/task.h" 185 #include "mozInlineSpellChecker.h" 186 #include "mozilla/GlobalStyleSheetCache.h" 187 #include "mozilla/dom/BlobURLProtocolHandler.h" 188 #include "mozilla/dom/PCycleCollectWithLogsChild.h" 189 #include "mozilla/dom/PerformanceStorage.h" 190 #include "nsAnonymousTemporaryFile.h" 191 #include "nsCategoryManagerUtils.h" 192 #include "nsChromeRegistryContent.h" 193 #include "nsClipboardProxy.h" 194 #include "nsContentPermissionHelper.h" 195 #include "nsDebugImpl.h" 196 #include "nsDirectoryService.h" 197 #include "nsDirectoryServiceDefs.h" 198 #include "nsDirectoryServiceUtils.h" 199 #include "nsDocShell.h" 200 #include "nsDocShellLoadState.h" 201 #include "nsFrameMessageManager.h" 202 #include "nsHashPropertyBag.h" 203 #include "nsIConsoleListener.h" 204 #include "nsICycleCollectorListener.h" 205 #include "nsIDocShellTreeOwner.h" 206 #include "nsIDocumentViewer.h" 207 #include "nsIDragService.h" 208 #include "nsIInterfaceRequestorUtils.h" 209 #include "nsIMemoryInfoDumper.h" 210 #include "nsIMemoryReporter.h" 211 #include "nsIOService.h" 212 #include "nsIObserverService.h" 213 #include "nsIScriptError.h" 214 #include "nsIScriptSecurityManager.h" 215 #include "nsJSEnvironment.h" 216 #include "nsJSUtils.h" 217 #include "nsMemoryInfoDumper.h" 218 #include "nsNetUtil.h" 219 #include "nsServiceManagerUtils.h" 220 #include "nsStyleSheetService.h" 221 #include "nsThreadManager.h" 222 #include "nsWindowMemoryReporter.h" 223 #include "nsXULAppAPI.h" 224 225 #ifdef MOZ_WEBRTC 226 # include "jsapi/WebrtcGlobalChild.h" 227 #endif 228 229 #include "PermissionMessageUtils.h" 230 #include "mozilla/Permission.h" 231 #include "mozilla/PermissionManager.h" 232 233 #if defined(MOZ_WIDGET_ANDROID) 234 # include <sched.h> 235 236 # include "APKOpen.h" 237 #endif 238 239 #ifdef XP_WIN 240 # include <process.h> 241 # define getpid _getpid 242 # include "mozilla/WinDllServices.h" 243 #endif 244 245 #if defined(XP_MACOSX) 246 # include <sys/qos.h> 247 248 # include "nsMacUtilsImpl.h" 249 #endif /* XP_MACOSX */ 250 251 #ifdef MOZ_X11 252 # include "mozilla/X11Util.h" 253 #endif 254 255 #ifdef ACCESSIBILITY 256 # include "nsAccessibilityService.h" 257 # ifdef XP_WIN 258 # include "mozilla/a11y/AccessibleWrap.h" 259 # endif 260 # include "mozilla/a11y/DocAccessible.h" 261 # include "mozilla/a11y/DocManager.h" 262 # include "mozilla/a11y/OuterDocAccessible.h" 263 #endif 264 265 #include "mozilla/dom/File.h" 266 #include "mozilla/dom/MediaControllerBinding.h" 267 268 #ifdef MOZ_WEBSPEECH 269 # include "mozilla/dom/PSpeechSynthesisChild.h" 270 #endif 271 272 #include "ClearOnShutdown.h" 273 #include "DomainPolicy.h" 274 #include "GfxInfoBase.h" 275 #include "MMPrinter.h" 276 #include "VRManagerChild.h" 277 #include "gfxPlatform.h" 278 #include "gfxPlatformFontList.h" 279 #include "mozilla/RemoteSpellCheckEngineChild.h" 280 #include "mozilla/dom/TabContext.h" 281 #include "mozilla/dom/ipc/StructuredCloneData.h" 282 #include "mozilla/ipc/CrashReporterClient.h" 283 #include "mozilla/ipc/ProcessUtils.h" 284 #include "mozilla/ipc/URIUtils.h" 285 #include "mozilla/net/NeckoMessageUtils.h" 286 #include "mozilla/widget/PuppetBidiKeyboard.h" 287 #include "nsContentUtils.h" 288 #include "nsIPrincipal.h" 289 #include "nsString.h" 290 #include "nscore.h" // for NS_FREE_PERMANENT_DATA 291 #include "private/pprio.h" 292 293 #ifdef MOZ_WIDGET_GTK 294 # include <gtk/gtk.h> 295 296 # include "mozilla/WidgetUtilsGtk.h" 297 # include "nsAppRunner.h" 298 #endif 299 300 #ifdef MOZ_CODE_COVERAGE 301 # include "mozilla/CodeCoverageHandler.h" 302 #endif 303 304 #ifdef MOZ_WMF_CDM 305 # include "mozilla/dom/MediaKeySystemAccess.h" 306 #endif 307 308 extern mozilla::LazyLogModule gSHIPBFCacheLog; 309 310 using namespace mozilla; 311 using namespace mozilla::dom::ipc; 312 using namespace mozilla::media; 313 using namespace mozilla::embedding; 314 using namespace mozilla::gmp; 315 using namespace mozilla::hal_sandbox; 316 using namespace mozilla::ipc; 317 using namespace mozilla::intl; 318 using namespace mozilla::layers; 319 using namespace mozilla::layout; 320 using namespace mozilla::net; 321 using namespace mozilla::widget; 322 using mozilla::loader::PScriptCacheChild; 323 324 namespace geckoprofiler::markers { 325 struct ProcessPriorityChange { 326 static constexpr Span<const char> MarkerTypeName() { 327 return MakeStringSpan("ProcessPriorityChange"); 328 } 329 static void StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter& aWriter, 330 const ProfilerString8View& aPreviousPriority, 331 const ProfilerString8View& aNewPriority) { 332 aWriter.StringProperty("Before", aPreviousPriority); 333 aWriter.StringProperty("After", aNewPriority); 334 } 335 static MarkerSchema MarkerTypeDisplay() { 336 using MS = MarkerSchema; 337 MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable}; 338 schema.AddKeyFormat("Before", MS::Format::String); 339 schema.AddKeyFormat("After", MS::Format::String); 340 schema.AddStaticLabelValue("Note", 341 "This is a notification of the priority change " 342 "that was done by the parent process"); 343 schema.SetAllLabels( 344 "priority: {marker.data.Before} -> {marker.data.After}"); 345 return schema; 346 } 347 }; 348 349 struct ProcessPriority { 350 static constexpr Span<const char> MarkerTypeName() { 351 return MakeStringSpan("ProcessPriority"); 352 } 353 static void StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter& aWriter, 354 const ProfilerString8View& aPriority, 355 const ProfilingState& aProfilingState) { 356 aWriter.StringProperty("Priority", aPriority); 357 aWriter.StringProperty("Marker cause", 358 ProfilerString8View::WrapNullTerminatedString( 359 ProfilingStateToString(aProfilingState))); 360 } 361 static MarkerSchema MarkerTypeDisplay() { 362 using MS = MarkerSchema; 363 MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable}; 364 schema.AddKeyFormat("Priority", MS::Format::String); 365 schema.AddKeyFormat("Marker cause", MS::Format::String); 366 schema.SetAllLabels("priority: {marker.data.Priority}"); 367 return schema; 368 } 369 }; 370 } // namespace geckoprofiler::markers 371 372 namespace mozilla { 373 namespace dom { 374 375 // IPC sender for remote GC/CC logging. 376 class CycleCollectWithLogsChild final : public PCycleCollectWithLogsChild { 377 public: 378 NS_INLINE_DECL_REFCOUNTING(CycleCollectWithLogsChild) 379 380 class Sink final : public nsICycleCollectorLogSink { 381 NS_DECL_ISUPPORTS 382 383 Sink(CycleCollectWithLogsChild* aActor, const FileDescriptor& aGCLog, 384 const FileDescriptor& aCCLog) { 385 mActor = aActor; 386 mGCLog = FileDescriptorToFILE(aGCLog, "w"); 387 mCCLog = FileDescriptorToFILE(aCCLog, "w"); 388 } 389 390 NS_IMETHOD Open(FILE** aGCLog, FILE** aCCLog) override { 391 if (NS_WARN_IF(!mGCLog) || NS_WARN_IF(!mCCLog)) { 392 return NS_ERROR_FAILURE; 393 } 394 *aGCLog = mGCLog; 395 *aCCLog = mCCLog; 396 return NS_OK; 397 } 398 399 NS_IMETHOD CloseGCLog() override { 400 MOZ_ASSERT(mGCLog); 401 fclose(mGCLog); 402 mGCLog = nullptr; 403 mActor->SendCloseGCLog(); 404 return NS_OK; 405 } 406 407 NS_IMETHOD CloseCCLog() override { 408 MOZ_ASSERT(mCCLog); 409 fclose(mCCLog); 410 mCCLog = nullptr; 411 mActor->SendCloseCCLog(); 412 return NS_OK; 413 } 414 415 NS_IMETHOD GetFilenameIdentifier(nsAString& aIdentifier) override { 416 return UnimplementedProperty(); 417 } 418 419 NS_IMETHOD SetFilenameIdentifier(const nsAString& aIdentifier) override { 420 return UnimplementedProperty(); 421 } 422 423 NS_IMETHOD GetProcessIdentifier(int32_t* aIdentifier) override { 424 return UnimplementedProperty(); 425 } 426 427 NS_IMETHOD SetProcessIdentifier(int32_t aIdentifier) override { 428 return UnimplementedProperty(); 429 } 430 431 NS_IMETHOD GetGcLog(nsIFile** aPath) override { 432 return UnimplementedProperty(); 433 } 434 435 NS_IMETHOD GetCcLog(nsIFile** aPath) override { 436 return UnimplementedProperty(); 437 } 438 439 private: 440 ~Sink() { 441 if (mGCLog) { 442 fclose(mGCLog); 443 mGCLog = nullptr; 444 } 445 if (mCCLog) { 446 fclose(mCCLog); 447 mCCLog = nullptr; 448 } 449 // The XPCOM refcount drives the IPC lifecycle; 450 (void)mActor->Send__delete__(mActor); 451 } 452 453 nsresult UnimplementedProperty() { 454 MOZ_ASSERT(false, 455 "This object is a remote GC/CC logger;" 456 " this property isn't meaningful."); 457 return NS_ERROR_UNEXPECTED; 458 } 459 460 RefPtr<CycleCollectWithLogsChild> mActor; 461 FILE* mGCLog; 462 FILE* mCCLog; 463 }; 464 465 private: 466 ~CycleCollectWithLogsChild() = default; 467 }; 468 469 NS_IMPL_ISUPPORTS(CycleCollectWithLogsChild::Sink, nsICycleCollectorLogSink); 470 471 class ConsoleListener final : public nsIConsoleListener { 472 public: 473 explicit ConsoleListener(ContentChild* aChild) : mChild(aChild) {} 474 475 NS_DECL_ISUPPORTS 476 NS_DECL_NSICONSOLELISTENER 477 478 private: 479 ~ConsoleListener() = default; 480 481 ContentChild* mChild; 482 friend class ContentChild; 483 }; 484 485 NS_IMPL_ISUPPORTS(ConsoleListener, nsIConsoleListener) 486 487 // Before we send the error to the parent process (which 488 // involves copying the memory), truncate any long lines. CSS 489 // errors in particular share the memory for long lines with 490 // repeated errors, but the IPC communication we're about to do 491 // will break that sharing, so we better truncate now. 492 template <typename CharT> 493 static void TruncateString(nsTSubstring<CharT>& aString) { 494 if (aString.Length() > 1000) { 495 aString.Truncate(1000); 496 } 497 } 498 499 NS_IMETHODIMP 500 ConsoleListener::Observe(nsIConsoleMessage* aMessage) { 501 if (!mChild) { 502 return NS_OK; 503 } 504 505 nsCOMPtr<nsIScriptError> scriptError = do_QueryInterface(aMessage); 506 if (scriptError) { 507 nsAutoString msg; 508 nsAutoCString sourceName; 509 nsCString category; 510 uint32_t lineNum, colNum, flags; 511 bool fromPrivateWindow, fromChromeContext; 512 513 nsresult rv = scriptError->GetErrorMessage(msg); 514 NS_ENSURE_SUCCESS(rv, rv); 515 TruncateString(msg); 516 rv = scriptError->GetSourceName(sourceName); 517 NS_ENSURE_SUCCESS(rv, rv); 518 TruncateString(sourceName); 519 520 rv = scriptError->GetCategory(getter_Copies(category)); 521 NS_ENSURE_SUCCESS(rv, rv); 522 rv = scriptError->GetLineNumber(&lineNum); 523 NS_ENSURE_SUCCESS(rv, rv); 524 rv = scriptError->GetColumnNumber(&colNum); 525 NS_ENSURE_SUCCESS(rv, rv); 526 rv = scriptError->GetFlags(&flags); 527 NS_ENSURE_SUCCESS(rv, rv); 528 rv = scriptError->GetIsFromPrivateWindow(&fromPrivateWindow); 529 NS_ENSURE_SUCCESS(rv, rv); 530 rv = scriptError->GetIsFromChromeContext(&fromChromeContext); 531 NS_ENSURE_SUCCESS(rv, rv); 532 533 { 534 AutoJSAPI jsapi; 535 jsapi.Init(); 536 JSContext* cx = jsapi.cx(); 537 538 JS::Rooted<JS::Value> stack(cx); 539 rv = scriptError->GetStack(&stack); 540 NS_ENSURE_SUCCESS(rv, rv); 541 542 if (stack.isObject()) { 543 // Because |stack| might be a cross-compartment wrapper, we can't use it 544 // with JSAutoRealm. Use the stackGlobal for that. 545 JS::Rooted<JS::Value> stackGlobal(cx); 546 rv = scriptError->GetStackGlobal(&stackGlobal); 547 NS_ENSURE_SUCCESS(rv, rv); 548 549 JSAutoRealm ar(cx, &stackGlobal.toObject()); 550 551 StructuredCloneData data; 552 ErrorResult err; 553 data.Write(cx, stack, err); 554 if (err.Failed()) { 555 return err.StealNSResult(); 556 } 557 558 ClonedMessageData cloned; 559 if (!data.BuildClonedMessageData(cloned)) { 560 return NS_ERROR_FAILURE; 561 } 562 563 mChild->SendScriptErrorWithStack(msg, sourceName, lineNum, colNum, 564 flags, category, fromPrivateWindow, 565 fromChromeContext, cloned); 566 return NS_OK; 567 } 568 } 569 570 mChild->SendScriptError(msg, sourceName, lineNum, colNum, flags, category, 571 fromPrivateWindow, 0, fromChromeContext); 572 return NS_OK; 573 } 574 575 nsString msg; 576 nsresult rv = aMessage->GetMessageMoz(msg); 577 NS_ENSURE_SUCCESS(rv, rv); 578 mChild->SendConsoleMessage(msg); 579 return NS_OK; 580 } 581 582 #ifdef NIGHTLY_BUILD 583 /** 584 * The singleton of this class is registered with the BackgroundHangMonitor as 585 * an annotator, so that the hang monitor can record whether or not there were 586 * pending input events when the thread hung. 587 */ 588 class PendingInputEventHangAnnotator final : public BackgroundHangAnnotator { 589 public: 590 virtual void AnnotateHang(BackgroundHangAnnotations& aAnnotations) override { 591 int32_t pending = ContentChild::GetSingleton()->GetPendingInputEvents(); 592 if (pending > 0) { 593 aAnnotations.AddAnnotation(u"PendingInput"_ns, pending); 594 } 595 } 596 597 static PendingInputEventHangAnnotator sSingleton; 598 }; 599 PendingInputEventHangAnnotator PendingInputEventHangAnnotator::sSingleton; 600 #endif 601 602 class ContentChild::ShutdownCanary final {}; 603 604 ContentChild* ContentChild::sSingleton; 605 StaticAutoPtr<ContentChild::ShutdownCanary> ContentChild::sShutdownCanary; 606 607 ContentChild::ContentChild() 608 : mIsForBrowser(false), mIsAlive(true), mShuttingDown(false) { 609 // This process is a content process, so it's clearly running in 610 // multiprocess mode! 611 nsDebugImpl::SetMultiprocessMode("Child"); 612 613 // Our static analysis doesn't allow capturing ref-counted pointers in 614 // lambdas, so we need to hide it in a uintptr_t. This is safe because this 615 // lambda will be destroyed in ~ContentChild(). 616 uintptr_t self = reinterpret_cast<uintptr_t>(this); 617 profiler_add_state_change_callback( 618 AllProfilingStates(), 619 [self](ProfilingState aProfilingState) { 620 const ContentChild* selfPtr = 621 reinterpret_cast<const ContentChild*>(self); 622 PROFILER_MARKER("Process Priority", OTHER, 623 mozilla::MarkerThreadId::MainThread(), ProcessPriority, 624 ProfilerString8View::WrapNullTerminatedString( 625 ProcessPriorityToString(selfPtr->mProcessPriority)), 626 aProfilingState); 627 }, 628 self); 629 630 // When ContentChild is created, the observer service does not even exist. 631 // When ContentChild::RecvSetXPCOMProcessAttributes is called (the first 632 // IPDL call made on this object), shutdown may have already happened. Thus 633 // we create a canary here that relies upon getting cleared if shutdown 634 // happens without requiring the observer service at this time. 635 if (!sShutdownCanary) { 636 sShutdownCanary = new ShutdownCanary(); 637 ClearOnShutdown(&sShutdownCanary, ShutdownPhase::XPCOMShutdown); 638 } 639 } 640 641 #ifdef _MSC_VER 642 # pragma warning(push) 643 # pragma warning( \ 644 disable : 4722) /* Silence "destructor never returns" warning \ 645 */ 646 #endif 647 648 ContentChild::~ContentChild() { 649 profiler_remove_state_change_callback(reinterpret_cast<uintptr_t>(this)); 650 651 #ifndef NS_FREE_PERMANENT_DATA 652 MOZ_CRASH("Content Child shouldn't be destroyed."); 653 #endif 654 } 655 656 #ifdef _MSC_VER 657 # pragma warning(pop) 658 #endif 659 660 NS_INTERFACE_MAP_BEGIN(ContentChild) 661 NS_INTERFACE_MAP_ENTRY(nsIDOMProcessChild) 662 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMProcessChild) 663 NS_INTERFACE_MAP_END 664 665 mozilla::ipc::IPCResult ContentChild::RecvSetXPCOMProcessAttributes( 666 XPCOMInitData&& aXPCOMInit, 667 const UniquePtr<StructuredCloneData>& aInitialData, 668 FullLookAndFeel&& aLookAndFeelData, dom::SystemFontList&& aFontList, 669 Maybe<mozilla::ipc::ReadOnlySharedMemoryHandle>&& aSharedUASheetHandle, 670 const uintptr_t& aSharedUASheetAddress, 671 nsTArray<mozilla::ipc::ReadOnlySharedMemoryHandle>&& aSharedFontListBlocks, 672 const bool& aIsReadyForBackgroundProcessing) { 673 if (!sShutdownCanary) { 674 return IPC_OK(); 675 } 676 677 mLookAndFeelData = std::move(aLookAndFeelData); 678 mFontList = std::move(aFontList); 679 mSharedFontListBlocks = std::move(aSharedFontListBlocks); 680 681 gfx::gfxVars::SetValuesForInitialize(aXPCOMInit.gfxNonDefaultVarUpdates()); 682 PerfStats::SetCollectionMask(aXPCOMInit.perfStatsMask()); 683 LookAndFeel::EnsureInit(); 684 InitSharedUASheets(std::move(aSharedUASheetHandle), aSharedUASheetAddress); 685 InitXPCOM(std::move(aXPCOMInit), *aInitialData, 686 aIsReadyForBackgroundProcessing); 687 InitGraphicsDeviceData(aXPCOMInit.contentDeviceData()); 688 RefPtr<net::ChildDNSService> dnsServiceChild = 689 dont_AddRef(net::ChildDNSService::GetSingleton()); 690 if (dnsServiceChild) { 691 dnsServiceChild->SetTRRDomain(aXPCOMInit.trrDomain()); 692 dnsServiceChild->SetTRRModeInChild(aXPCOMInit.trrMode(), 693 aXPCOMInit.trrModeFromPref()); 694 } 695 return IPC_OK(); 696 } 697 698 void ContentChild::Init(mozilla::ipc::UntypedEndpoint&& aEndpoint, 699 const char* aParentBuildID, bool aIsForBrowser) { 700 #ifdef MOZ_WIDGET_GTK 701 // When running X11 only build we need to pass a display down 702 // to gtk_init because it's not going to use the one from the environment 703 // on its own when deciding which backend to use, and when starting under 704 // XWayland, it may choose to start with the wayland backend 705 // instead of the x11 backend. 706 // The DISPLAY environment variable is normally set by the parent process. 707 // The MOZ_GDK_DISPLAY environment variable is set from nsAppRunner.cpp 708 // when --display is set by the command line. 709 if (!gfxPlatform::IsHeadless()) { 710 const char* display_name = PR_GetEnv("MOZ_GDK_DISPLAY"); 711 if (!display_name) { 712 bool waylandEnabled = false; 713 # ifdef MOZ_WAYLAND 714 waylandEnabled = IsWaylandEnabled(); 715 # endif 716 if (!waylandEnabled) { 717 display_name = PR_GetEnv("DISPLAY"); 718 } 719 } 720 if (display_name) { 721 int argc = 3; 722 char option_name[] = "--display"; 723 char* argv[] = { 724 // argv0 is unused because g_set_prgname() was called in 725 // XRE_InitChildProcess(). 726 nullptr, option_name, const_cast<char*>(display_name), nullptr}; 727 char** argvp = argv; 728 gtk_init(&argc, &argvp); 729 } else { 730 gtk_init(nullptr, nullptr); 731 } 732 } 733 #endif 734 735 #ifdef MOZ_X11 736 if (!gfxPlatform::IsHeadless()) { 737 // Do this after initializing GDK, or GDK will install its own handler. 738 XRE_InstallX11ErrorHandler(); 739 } 740 #endif 741 742 MOZ_ASSERT(!sSingleton, "only one ContentChild per child"); 743 744 // Once we start sending IPC messages, we need the thread manager to be 745 // initialized so we can deal with the responses. Do that here before we 746 // try to construct the crash reporter. 747 nsresult rv = nsThreadManager::get().Init(); 748 if (NS_WARN_IF(NS_FAILED(rv))) { 749 MOZ_CRASH("Failed to initialize the thread manager in ContentChild::Init"); 750 } 751 752 if (!aEndpoint.Bind(this)) { 753 MOZ_CRASH("Bind failed in ContentChild::Init"); 754 } 755 sSingleton = this; 756 757 // If communications with the parent have broken down, take the process 758 // down so it's not hanging around. 759 GetIPCChannel()->SetAbortOnError(true); 760 761 // This must be checked before any IPDL message, which may hit sentinel 762 // errors due to parent and content processes having different 763 // versions. 764 MessageChannel* channel = GetIPCChannel(); 765 if (channel && !channel->SendBuildIDsMatchMessage(aParentBuildID)) { 766 // We need to quit this process if the buildID doesn't match the parent's. 767 // This can occur when an update occurred in the background. 768 ProcessChild::QuickExit(); 769 } 770 771 #if defined(__OpenBSD__) && defined(MOZ_SANDBOX) 772 StartOpenBSDSandbox(GeckoProcessType_Content); 773 #endif 774 775 #ifdef MOZ_X11 776 # ifdef MOZ_WIDGET_GTK 777 if (GdkIsX11Display() && !gfxPlatform::IsHeadless()) { 778 // Send the parent our X socket to act as a proxy reference for our X 779 // resources. 780 int xSocketFd = ConnectionNumber(DefaultXDisplay()); 781 SendBackUpXResources(FileDescriptor(xSocketFd)); 782 } 783 # endif 784 #endif 785 786 CrashReporterClient::InitSingleton(this); 787 788 mIsForBrowser = aIsForBrowser; 789 790 SetProcessName("Web Content"_ns); 791 792 #ifdef NIGHTLY_BUILD 793 // NOTE: We have to register the annotator on the main thread, as annotators 794 // only affect a single thread. 795 SchedulerGroup::Dispatch( 796 NS_NewRunnableFunction("RegisterPendingInputEventHangAnnotator", [] { 797 BackgroundHangMonitor::RegisterAnnotator( 798 PendingInputEventHangAnnotator::sSingleton); 799 })); 800 #endif 801 802 #if defined(MOZ_MEMORY) && defined(DEBUG) && !defined(MOZ_UBSAN) 803 jemalloc_stats_t stats; 804 jemalloc_stats(&stats); 805 MOZ_ASSERT(!stats.opt_randomize_small, 806 "Content process should not randomize small allocations"); 807 #endif 808 } 809 810 void ContentChild::AddProfileToProcessName(const nsACString& aProfile) { 811 nsCOMPtr<nsIPrincipal> isolationPrincipal = 812 ContentParent::CreateRemoteTypeIsolationPrincipal(mRemoteType); 813 if (isolationPrincipal) { 814 if (isolationPrincipal->OriginAttributesRef().IsPrivateBrowsing()) { 815 return; 816 } 817 } 818 819 mProcessName = aProfile + ":"_ns + mProcessName; //<profile_name>:example.com 820 } 821 822 void ContentChild::SetProcessName(const nsACString& aName, 823 const nsACString* aSite, 824 const nsACString* aCurrentProfile) { 825 char* name; 826 if ((name = PR_GetEnv("MOZ_DEBUG_APP_PROCESS")) && aName.EqualsASCII(name)) { 827 #ifdef XP_UNIX 828 printf_stderr("\n\nCHILDCHILDCHILDCHILD\n [%s] debug me @%d\n\n", name, 829 getpid()); 830 sleep(30); 831 #elif defined(XP_WIN) 832 // Windows has a decent JIT debugging story, so NS_DebugBreak does the 833 // right thing. 834 NS_DebugBreak(NS_DEBUG_BREAK, 835 "Invoking NS_DebugBreak() to debug child process", nullptr, 836 __FILE__, __LINE__); 837 #endif 838 } 839 840 if (aSite) { 841 profiler_set_process_name(aName, aSite); 842 } else { 843 profiler_set_process_name(aName); 844 } 845 846 mProcessName = aName; 847 848 // Requires pref flip 849 if (aSite && StaticPrefs::fission_processSiteNames()) { 850 nsCOMPtr<nsIPrincipal> isolationPrincipal = 851 ContentParent::CreateRemoteTypeIsolationPrincipal(mRemoteType); 852 if (isolationPrincipal) { 853 // DEFAULT_PRIVATE_BROWSING_ID is the value when it's not private 854 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug, 855 ("private = %d, pref = %d", 856 isolationPrincipal->OriginAttributesRef().IsPrivateBrowsing(), 857 StaticPrefs::fission_processPrivateWindowSiteNames())); 858 if (!isolationPrincipal->OriginAttributesRef().IsPrivateBrowsing() 859 #ifdef NIGHTLY_BUILD 860 // Nightly can show site names for private windows, with a second pref 861 || StaticPrefs::fission_processPrivateWindowSiteNames() 862 #endif 863 ) { 864 #if !defined(XP_MACOSX) 865 // Mac doesn't have the 15-character limit Linux does 866 // Sets profiler process name 867 if (isolationPrincipal->SchemeIs("https")) { 868 nsAutoCString schemeless; 869 isolationPrincipal->GetHostPort(schemeless); 870 nsAutoCString originSuffix; 871 isolationPrincipal->GetOriginSuffix(originSuffix); 872 schemeless.Append(originSuffix); 873 mProcessName = schemeless; 874 } else 875 #endif 876 { 877 mProcessName = *aSite; 878 } 879 } 880 } 881 } 882 883 if (StaticPrefs::fission_processProfileName() && aCurrentProfile && 884 !aCurrentProfile->IsEmpty()) { 885 AddProfileToProcessName(*aCurrentProfile); 886 } 887 888 // else private window, don't change process name, or the pref isn't set 889 // mProcessName is always flat (mProcessName == aName) 890 891 mozilla::ipc::SetThisProcessName(mProcessName.get()); 892 893 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug, 894 ("Changed name of process %d to %s", getpid(), 895 PromiseFlatCString(mProcessName).get())); 896 } 897 898 static nsresult GetCreateWindowParams(nsIOpenWindowInfo* aOpenWindowInfo, 899 nsDocShellLoadState* aLoadState, 900 bool aForceNoReferrer, 901 nsIReferrerInfo** aReferrerInfo, 902 nsIPrincipal** aTriggeringPrincipal, 903 nsIPolicyContainer** aPolicyContainer) { 904 if (!aTriggeringPrincipal || !aPolicyContainer) { 905 NS_ERROR("aTriggeringPrincipal || aPolicyContainer is null"); 906 return NS_ERROR_FAILURE; 907 } 908 909 if (!aReferrerInfo) { 910 NS_ERROR("aReferrerInfo is null"); 911 return NS_ERROR_FAILURE; 912 } 913 914 nsCOMPtr<nsIReferrerInfo> referrerInfo; 915 if (aForceNoReferrer) { 916 referrerInfo = new ReferrerInfo(nullptr, ReferrerPolicy::_empty, false); 917 } 918 if (aLoadState && !referrerInfo) { 919 referrerInfo = aLoadState->GetReferrerInfo(); 920 } 921 922 RefPtr<BrowsingContext> parent = aOpenWindowInfo->GetParent(); 923 nsCOMPtr<nsPIDOMWindowOuter> opener = 924 parent ? parent->GetDOMWindow() : nullptr; 925 if (!opener) { 926 nsCOMPtr<nsIPrincipal> nullPrincipal = 927 NullPrincipal::Create(aOpenWindowInfo->GetOriginAttributes()); 928 if (!referrerInfo) { 929 referrerInfo = new ReferrerInfo(nullptr, ReferrerPolicy::_empty); 930 } 931 932 referrerInfo.swap(*aReferrerInfo); 933 NS_ADDREF(*aTriggeringPrincipal = nullPrincipal); 934 return NS_OK; 935 } 936 937 nsCOMPtr<Document> doc = opener->GetDoc(); 938 NS_ADDREF(*aTriggeringPrincipal = doc->NodePrincipal()); 939 940 nsCOMPtr<nsIPolicyContainer> policyContainer = doc->GetPolicyContainer(); 941 if (policyContainer) { 942 policyContainer.forget(aPolicyContainer); 943 } 944 945 nsCOMPtr<nsIURI> baseURI = doc->GetDocBaseURI(); 946 if (!baseURI) { 947 NS_ERROR("Document didn't return a base URI"); 948 return NS_ERROR_FAILURE; 949 } 950 951 if (!referrerInfo) { 952 referrerInfo = new ReferrerInfo(*doc); 953 } 954 955 referrerInfo.swap(*aReferrerInfo); 956 return NS_OK; 957 } 958 959 nsresult ContentChild::ProvideWindowCommon( 960 NotNull<BrowserChild*> aTabOpener, nsIOpenWindowInfo* aOpenWindowInfo, 961 uint32_t aChromeFlags, bool aCalledFromJS, nsIURI* aURI, 962 const nsAString& aName, const nsACString& aFeatures, 963 const UserActivation::Modifiers& aModifiers, bool aForceNoOpener, 964 bool aForceNoReferrer, bool aIsPopupRequested, 965 nsDocShellLoadState* aLoadState, bool* aWindowIsNew, 966 BrowsingContext** aReturn) { 967 MOZ_ASSERT(aOpenWindowInfo, "Must have openwindowinfo"); 968 969 *aReturn = nullptr; 970 971 nsAutoCString features(aFeatures); 972 nsAutoString name(aName); 973 974 nsresult rv; 975 976 RefPtr<BrowsingContext> parent = aOpenWindowInfo->GetParent(); 977 MOZ_DIAGNOSTIC_ASSERT(parent, "We must have a parent BC"); 978 979 // Block the attempt to open a new window if the opening BrowsingContext is 980 // not marked to use remote tabs. This ensures that the newly opened window is 981 // correctly remote. 982 if (NS_WARN_IF(!parent->UseRemoteTabs())) { 983 return NS_ERROR_ABORT; 984 } 985 986 bool useRemoteSubframes = 987 aChromeFlags & nsIWebBrowserChrome::CHROME_FISSION_WINDOW; 988 989 uint32_t parentSandboxFlags = parent->SandboxFlags(); 990 Document* doc = parent->GetDocument(); 991 if (doc) { 992 parentSandboxFlags = doc->GetSandboxFlags(); 993 } 994 995 const bool isForPrinting = aOpenWindowInfo->GetIsForPrinting(); 996 // Certain conditions complicate the process of creating the new 997 // BrowsingContext, and prevent us from using the 998 // "CreateWindowInDifferentProcess" codepath. 999 // * With Fission enabled, process selection will happen during the load, so 1000 // switching processes eagerly will not provide a benefit. 1001 // * Windows created for printing must be created within the current process 1002 // so that a static clone of the source document can be created. 1003 // * Sandboxed popups require the full window creation codepath. 1004 // * Loads with form or POST data require the full window creation codepath. 1005 const bool cannotLoadInDifferentProcess = 1006 useRemoteSubframes || isForPrinting || 1007 (parentSandboxFlags & 1008 SANDBOX_PROPAGATES_TO_AUXILIARY_BROWSING_CONTEXTS) || 1009 (aLoadState && 1010 (aLoadState->IsFormSubmission() || aLoadState->PostDataStream())); 1011 if (!cannotLoadInDifferentProcess) { 1012 // If we're in a content process and we have noopener set, there's no reason 1013 // to load in our process, so let's load it elsewhere! 1014 bool loadInDifferentProcess = 1015 aForceNoOpener && StaticPrefs::dom_noopener_newprocess_enabled(); 1016 if (loadInDifferentProcess) { 1017 nsCOMPtr<nsIPrincipal> triggeringPrincipal; 1018 nsCOMPtr<nsIPolicyContainer> policyContainer; 1019 nsCOMPtr<nsIReferrerInfo> referrerInfo; 1020 rv = GetCreateWindowParams(aOpenWindowInfo, aLoadState, aForceNoReferrer, 1021 getter_AddRefs(referrerInfo), 1022 getter_AddRefs(triggeringPrincipal), 1023 getter_AddRefs(policyContainer)); 1024 if (NS_WARN_IF(NS_FAILED(rv))) { 1025 return rv; 1026 } 1027 1028 if (name.LowerCaseEqualsLiteral("_blank")) { 1029 name.Truncate(); 1030 } 1031 1032 MOZ_DIAGNOSTIC_ASSERT(!nsContentUtils::IsSpecialName(name)); 1033 1034 const bool hasValidUserGestureActivation = [aLoadState, doc] { 1035 if (aLoadState) { 1036 return aLoadState->HasValidUserGestureActivation(); 1037 } 1038 if (doc) { 1039 return doc->HasValidTransientUserGestureActivation(); 1040 } 1041 return false; 1042 }(); 1043 1044 const bool textDirectiveUserActivation = [aLoadState, doc] { 1045 if (doc && doc->ConsumeTextDirectiveUserActivation()) { 1046 return true; 1047 } 1048 if (aLoadState) { 1049 return aLoadState->GetTextDirectiveUserActivation(); 1050 } 1051 return false; 1052 }() || hasValidUserGestureActivation; 1053 1054 (void)SendCreateWindowInDifferentProcess( 1055 aTabOpener, parent, aChromeFlags, aCalledFromJS, 1056 aOpenWindowInfo->GetIsTopLevelCreatedByWebContent(), aURI, features, 1057 aModifiers, name, triggeringPrincipal, policyContainer, referrerInfo, 1058 aOpenWindowInfo->GetOriginAttributes(), hasValidUserGestureActivation, 1059 textDirectiveUserActivation); 1060 1061 // We return NS_ERROR_ABORT, so that the caller knows that we've abandoned 1062 // the window open as far as it is concerned. 1063 return NS_ERROR_ABORT; 1064 } 1065 } 1066 1067 TabId tabId(nsContentUtils::GenerateTabId()); 1068 1069 // We need to assign a TabGroup to the PBrowser actor before we send it to the 1070 // parent. Otherwise, the parent could send messages to us before we have a 1071 // proper TabGroup for that actor. 1072 RefPtr<BrowsingContext> openerBC; 1073 if (!aForceNoOpener) { 1074 openerBC = parent; 1075 } 1076 1077 RefPtr<BrowsingContext> browsingContext = BrowsingContext::CreateDetached( 1078 nullptr, openerBC, nullptr, aName, BrowsingContext::Type::Content, 1079 BrowsingContext::CreateDetachedOptions{ 1080 .isPopupRequested = aIsPopupRequested, 1081 .topLevelCreatedByWebContent = true, 1082 .isForPrinting = isForPrinting, 1083 }); 1084 MOZ_ALWAYS_SUCCEEDS(browsingContext->SetRemoteTabs(true)); 1085 MOZ_ALWAYS_SUCCEEDS(browsingContext->SetRemoteSubframes(useRemoteSubframes)); 1086 MOZ_ALWAYS_SUCCEEDS(browsingContext->SetOriginAttributes( 1087 aOpenWindowInfo->GetOriginAttributes())); 1088 1089 browsingContext->InitPendingInitialization(true); 1090 auto unsetPending = MakeScopeExit([browsingContext]() { 1091 (void)browsingContext->SetPendingInitialization(false); 1092 }); 1093 1094 browsingContext->EnsureAttached(); 1095 1096 // Since bug 543435, aOpenWindowInfo has the right principal to load for the 1097 // initial document. But creating windows is complicated and our code expects 1098 // to setup the initial window global and browser pairs before the document. 1099 // But without a document and window, we cannot use the 1100 // WindowGlobalActor::WindowInitializer to correctly initialize a window 1101 // global. So we must use the AboutBlankInitializer to create a dummy window 1102 // global with corresponding document and window. Then we immediately set the 1103 // correct principal which causes the creation of a new document, window and 1104 // window global. These use the dummy window to correctly initialize the 1105 // window global via a WindowInitializer. 1106 nsCOMPtr<nsIPrincipal> initialPrincipal = 1107 NullPrincipal::Create(browsingContext->OriginAttributesRef()); 1108 WindowGlobalInit windowInit = WindowGlobalActor::AboutBlankInitializer( 1109 browsingContext, initialPrincipal); 1110 nsCOMPtr<nsIOpenWindowInfo> openWindowInfoInitialPrincipal; 1111 // Init code expects window global and open window info to have matching 1112 // principals. 1113 aOpenWindowInfo->CloneWithPrincipals( 1114 initialPrincipal, initialPrincipal, 1115 getter_AddRefs(openWindowInfoInitialPrincipal)); 1116 1117 RefPtr<WindowGlobalChild> windowChild = 1118 WindowGlobalChild::CreateDisconnected(windowInit); 1119 if (NS_WARN_IF(!windowChild)) { 1120 return NS_ERROR_ABORT; 1121 } 1122 1123 auto newChild = MakeNotNull<RefPtr<BrowserChild>>( 1124 this, tabId, *aTabOpener, browsingContext, aChromeFlags, 1125 /* aIsTopLevel */ true); 1126 1127 if (IsShuttingDown()) { 1128 return NS_ERROR_ABORT; 1129 } 1130 1131 // Open a remote endpoint for our PBrowser actor. 1132 ManagedEndpoint<PBrowserParent> parentEp = OpenPBrowserEndpoint(newChild); 1133 if (NS_WARN_IF(!parentEp.IsValid())) { 1134 return NS_ERROR_ABORT; 1135 } 1136 1137 // Open a remote endpoint for our PWindowGlobal actor. 1138 ManagedEndpoint<PWindowGlobalParent> windowParentEp = 1139 newChild->OpenPWindowGlobalEndpoint(windowChild); 1140 if (NS_WARN_IF(!windowParentEp.IsValid())) { 1141 return NS_ERROR_ABORT; 1142 } 1143 1144 // Tell the parent process to set up its PBrowserParent. 1145 PopupIPCTabContext ipcContext(aTabOpener, 0); 1146 if (NS_WARN_IF(!SendConstructPopupBrowser( 1147 std::move(parentEp), std::move(windowParentEp), tabId, ipcContext, 1148 windowInit, aChromeFlags))) { 1149 return NS_ERROR_ABORT; 1150 } 1151 1152 windowChild->Init(); 1153 auto guardNullWindowGlobal = MakeScopeExit([&] { 1154 if (!windowChild->GetWindowGlobal()) { 1155 windowChild->Destroy(); 1156 } 1157 }); 1158 1159 // Now that |newChild| has had its IPC link established, call |Init| to set it 1160 // up. 1161 // XXX: This MOZ_KnownLive is only necessary because the static analysis can't 1162 // tell that NotNull<RefPtr<BrowserChild>> is a strong pointer. 1163 RefPtr<nsPIDOMWindowOuter> parentWindow = 1164 parent ? parent->GetDOMWindow() : nullptr; 1165 if (NS_FAILED(MOZ_KnownLive(newChild)->Init( 1166 parentWindow, windowChild, openWindowInfoInitialPrincipal))) { 1167 return NS_ERROR_ABORT; 1168 } 1169 1170 // Now change the principal to what it should be according to aOpenWindowInfo. 1171 // This creates a new document and the timing is quite fragile. 1172 NS_ENSURE_TRUE(browsingContext->GetDOMWindow(), NS_ERROR_ABORT); 1173 NS_ENSURE_TRUE(browsingContext->GetDOMWindow()->GetExtantDoc(), 1174 NS_ERROR_ABORT); 1175 browsingContext->GetDOMWindow()->SetInitialPrincipal( 1176 aOpenWindowInfo->PrincipalToInheritForAboutBlank()); 1177 1178 // Set to true when we're ready to return from this function. 1179 bool ready = false; 1180 1181 // NOTE: Capturing by reference here is safe, as this function won't return 1182 // until one of these callbacks is called. 1183 auto resolve = [&](CreatedWindowInfo&& info) { 1184 MOZ_RELEASE_ASSERT(NS_IsMainThread()); 1185 rv = info.rv(); 1186 *aWindowIsNew = info.windowOpened(); 1187 nsTArray<FrameScriptInfo> frameScripts(std::move(info.frameScripts())); 1188 uint32_t maxTouchPoints = info.maxTouchPoints(); 1189 DimensionInfo dimensionInfo = std::move(info.dimensions()); 1190 1191 // Once this function exits, we should try to exit the nested event loop. 1192 ready = true; 1193 1194 // NOTE: We have to handle this immediately in the resolve callback in order 1195 // to make sure that we don't process any more IPC messages before returning 1196 // from ProvideWindowCommon. 1197 1198 // Handle the error which we got back from the parent process, if we got 1199 // one. 1200 if (NS_FAILED(rv)) { 1201 return; 1202 } 1203 1204 if (!*aWindowIsNew) { 1205 rv = NS_ERROR_ABORT; 1206 return; 1207 } 1208 1209 // If the BrowserChild has been torn down, we don't need to do this anymore. 1210 if (NS_WARN_IF(!newChild->IPCOpen() || newChild->IsDestroyed())) { 1211 rv = NS_ERROR_ABORT; 1212 return; 1213 } 1214 1215 ParentShowInfo showInfo(u""_ns, /* fakeShowInfo = */ true, 1216 /* isTransparent = */ false, 1217 newChild->WebWidget()->GetDPI(), 1218 newChild->WebWidget()->RoundsWidgetCoordinatesTo(), 1219 newChild->WebWidget()->GetDefaultScale().scale); 1220 1221 newChild->SetMaxTouchPoints(maxTouchPoints); 1222 1223 if (aForceNoOpener || !parent) { 1224 MOZ_DIAGNOSTIC_ASSERT(!browsingContext->HadOriginalOpener()); 1225 MOZ_DIAGNOSTIC_ASSERT(browsingContext->GetTopLevelCreatedByWebContent()); 1226 MOZ_DIAGNOSTIC_ASSERT(browsingContext->GetOpenerId() == 0); 1227 } else { 1228 MOZ_DIAGNOSTIC_ASSERT(browsingContext->HadOriginalOpener()); 1229 MOZ_DIAGNOSTIC_ASSERT(browsingContext->GetTopLevelCreatedByWebContent()); 1230 MOZ_DIAGNOSTIC_ASSERT(browsingContext->GetOpenerId() == parent->Id()); 1231 } 1232 1233 // Unfortunately we don't get a window unless we've shown the frame. That's 1234 // pretty bogus; see bug 763602. 1235 newChild->DoFakeShow(showInfo); 1236 1237 newChild->RecvUpdateDimensions(dimensionInfo); 1238 1239 for (size_t i = 0; i < frameScripts.Length(); i++) { 1240 FrameScriptInfo& info = frameScripts[i]; 1241 if (!newChild->RecvLoadRemoteScript(info.url(), 1242 info.runInGlobalScope())) { 1243 MOZ_CRASH(); 1244 } 1245 } 1246 1247 if (xpc::IsInAutomation()) { 1248 if (nsCOMPtr<nsPIDOMWindowOuter> outer = 1249 do_GetInterface(newChild->WebNavigation())) { 1250 nsCOMPtr<nsIObserverService> obs(services::GetObserverService()); 1251 obs->NotifyObservers( 1252 outer, "dangerous:test-only:new-browser-child-ready", nullptr); 1253 } 1254 } 1255 1256 browsingContext.forget(aReturn); 1257 }; 1258 1259 // NOTE: Capturing by reference here is safe, as this function won't return 1260 // until one of these callbacks is called. 1261 auto reject = [&](ResponseRejectReason) { 1262 MOZ_RELEASE_ASSERT(NS_IsMainThread()); 1263 NS_WARNING("windowCreated promise rejected"); 1264 rv = NS_ERROR_NOT_AVAILABLE; 1265 ready = true; 1266 }; 1267 1268 // Send down the request to open the window. 1269 nsCOMPtr<nsIPrincipal> triggeringPrincipal; 1270 nsCOMPtr<nsIPolicyContainer> policyContainer; 1271 nsCOMPtr<nsIReferrerInfo> referrerInfo; 1272 rv = GetCreateWindowParams(aOpenWindowInfo, aLoadState, aForceNoReferrer, 1273 getter_AddRefs(referrerInfo), 1274 getter_AddRefs(triggeringPrincipal), 1275 getter_AddRefs(policyContainer)); 1276 if (NS_WARN_IF(NS_FAILED(rv))) { 1277 return rv; 1278 } 1279 1280 SendCreateWindow( 1281 aTabOpener, parent, newChild, aChromeFlags, aCalledFromJS, 1282 aOpenWindowInfo->GetIsForPrinting(), 1283 aOpenWindowInfo->GetIsForWindowDotPrint(), 1284 aOpenWindowInfo->GetIsTopLevelCreatedByWebContent(), aURI, features, 1285 aModifiers, triggeringPrincipal, policyContainer, referrerInfo, 1286 aOpenWindowInfo->GetOriginAttributes(), 1287 aLoadState ? aLoadState->HasValidUserGestureActivation() : false, 1288 aLoadState ? aLoadState->GetTextDirectiveUserActivation() : false, 1289 std::move(resolve), std::move(reject)); 1290 1291 // ======================= 1292 // Begin Nested Event Loop 1293 // ======================= 1294 1295 // We have to wait for a response from SendCreateWindow or with information 1296 // we're going to need to return from this function, So we spin a nested event 1297 // loop until they get back to us. 1298 1299 { 1300 // Suppress event handling for all contexts in our BrowsingContextGroup so 1301 // that event handlers cannot target our new window while it's still being 1302 // opened. Note that pending events that were suppressed while our blocker 1303 // was active will be dispatched asynchronously from a runnable dispatched 1304 // to the main event loop after this function returns, not immediately when 1305 // we leave this scope. 1306 AutoSuppressEventHandlingAndSuspend seh(browsingContext->Group()); 1307 1308 AutoNoJSAPI nojsapi; 1309 1310 // Spin the event loop until we get a response. Callers of this function 1311 // already have to guard against an inner event loop spinning in the 1312 // non-e10s case because of the need to spin one to create a new chrome 1313 // window. 1314 SpinEventLoopUntil("ContentChild::ProvideWindowCommon"_ns, 1315 [&]() { return ready; }); 1316 MOZ_RELEASE_ASSERT(ready, 1317 "We are on the main thread, so we should not exit this " 1318 "loop without ready being true."); 1319 } 1320 1321 // ===================== 1322 // End Nested Event Loop 1323 // ===================== 1324 1325 // It's possible for our new BrowsingContext to become discarded during the 1326 // nested event loop, in which case we shouldn't return it, since our callers 1327 // will generally not be prepared to deal with that. 1328 if (*aReturn && (*aReturn)->IsDiscarded()) { 1329 NS_RELEASE(*aReturn); 1330 return NS_ERROR_ABORT; 1331 } 1332 1333 // We should have the results already set by the callbacks. 1334 MOZ_ASSERT_IF(NS_SUCCEEDED(rv), *aReturn); 1335 return rv; 1336 } 1337 1338 bool ContentChild::IsAlive() const { return mIsAlive; } 1339 1340 bool ContentChild::IsShuttingDown() const { return mShuttingDown; } 1341 1342 void ContentChild::GetProcessName(nsACString& aName) const { 1343 aName = mProcessName; 1344 } 1345 1346 /* static */ 1347 void ContentChild::AppendProcessId(nsACString& aName) { 1348 if (!aName.IsEmpty()) { 1349 aName.Append(' '); 1350 } 1351 unsigned pid = getpid(); 1352 aName.Append(nsPrintfCString("(pid %u)", pid)); 1353 } 1354 1355 void ContentChild::InitGraphicsDeviceData(const ContentDeviceData& aData) { 1356 gfxPlatform::InitChild(aData); 1357 } 1358 1359 void ContentChild::InitSharedUASheets( 1360 Maybe<mozilla::ipc::ReadOnlySharedMemoryHandle>&& aHandle, 1361 uintptr_t aAddress) { 1362 MOZ_ASSERT_IF(!aHandle, !aAddress); 1363 1364 if (!aAddress) { 1365 return; 1366 } 1367 1368 // Map the shared memory storing the user agent style sheets. Do this as 1369 // early as possible to maximize the chance of being able to map at the 1370 // address we want. 1371 GlobalStyleSheetCache::SetSharedMemory(std::move(*aHandle), aAddress); 1372 } 1373 1374 void ContentChild::InitXPCOM( 1375 XPCOMInitData&& aXPCOMInit, 1376 const mozilla::dom::ipc::StructuredCloneData& aInitialData, 1377 bool aIsReadyForBackgroundProcessing) { 1378 #if defined(XP_WIN) 1379 // DLL services untrusted modules processing depends on 1380 // BackgroundChild::Startup having been called 1381 RefPtr<DllServices> dllSvc(DllServices::Get()); 1382 dllSvc->StartUntrustedModulesProcessor(aIsReadyForBackgroundProcessing); 1383 #endif // defined(XP_WIN) 1384 1385 PBackgroundChild* actorChild = BackgroundChild::GetOrCreateForCurrentThread(); 1386 if (NS_WARN_IF(!actorChild)) { 1387 MOZ_ASSERT_UNREACHABLE("PBackground init can't fail at this point"); 1388 return; 1389 } 1390 1391 ClientManager::Startup(); 1392 1393 // RemoteWorkerService will be initialized in RecvRemoteType, to avoid to 1394 // register it to the RemoteWorkerManager while it is still a prealloc 1395 // remoteType and defer it to the point the child process is assigned a. 1396 // actual remoteType. 1397 1398 nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID)); 1399 if (!svc) { 1400 NS_WARNING("Couldn't acquire console service"); 1401 return; 1402 } 1403 1404 mConsoleListener = new ConsoleListener(this); 1405 if (NS_FAILED(svc->RegisterListener(mConsoleListener))) 1406 NS_WARNING("Couldn't register console listener for child process"); 1407 1408 mAvailableDictionaries = std::move(aXPCOMInit.dictionaries()); 1409 1410 RecvSetOffline(aXPCOMInit.isOffline()); 1411 RecvSetConnectivity(aXPCOMInit.isConnected()); 1412 1413 OSPreferences::GetInstance()->AssignSysLocales(aXPCOMInit.sysLocales()); 1414 1415 LocaleService::GetInstance()->AssignAppLocales(aXPCOMInit.appLocales()); 1416 LocaleService::GetInstance()->AssignRequestedLocales( 1417 aXPCOMInit.requestedLocales()); 1418 1419 L10nRegistry::RegisterFileSourcesFromParentProcess( 1420 aXPCOMInit.l10nFileSources()); 1421 1422 RecvSetCaptivePortalState(aXPCOMInit.captivePortalState()); 1423 RecvBidiKeyboardNotify(aXPCOMInit.isLangRTL(), 1424 aXPCOMInit.haveBidiKeyboards()); 1425 1426 if (aXPCOMInit.domainPolicy().active()) { 1427 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); 1428 MOZ_ASSERT(ssm); 1429 ssm->ActivateDomainPolicyInternal(getter_AddRefs(mPolicy)); 1430 if (!mPolicy) { 1431 MOZ_CRASH("Failed to activate domain policy."); 1432 } 1433 mPolicy->ApplyClone(&aXPCOMInit.domainPolicy()); 1434 } 1435 1436 nsCOMPtr<nsIClipboard> clipboard( 1437 do_GetService("@mozilla.org/widget/clipboard;1")); 1438 if (nsCOMPtr<nsIClipboardProxy> clipboardProxy = 1439 do_QueryInterface(clipboard)) { 1440 clipboardProxy->SetCapabilities(aXPCOMInit.clipboardCaps()); 1441 } 1442 1443 { 1444 AutoJSAPI jsapi; 1445 if (NS_WARN_IF(!jsapi.Init(xpc::PrivilegedJunkScope()))) { 1446 MOZ_CRASH(); 1447 } 1448 ErrorResult rv; 1449 JS::Rooted<JS::Value> data(jsapi.cx()); 1450 mozilla::dom::ipc::StructuredCloneData id; 1451 id.Copy(aInitialData); 1452 id.Read(jsapi.cx(), &data, rv); 1453 if (NS_WARN_IF(rv.Failed())) { 1454 MOZ_CRASH(); 1455 } 1456 auto* global = ContentProcessMessageManager::Get(); 1457 global->SetInitialProcessData(data); 1458 } 1459 1460 // The stylesheet cache is not ready yet. Store this URL for future use. 1461 nsCOMPtr<nsIURI> ucsURL = std::move(aXPCOMInit.userContentSheetURL()); 1462 GlobalStyleSheetCache::SetUserContentCSSURL(ucsURL); 1463 1464 GfxInfoBase::SetFeatureStatus(std::move(aXPCOMInit.gfxFeatureStatus())); 1465 1466 // Initialize the RemoteMediaManager thread and its associated PBackground 1467 // channel. 1468 RemoteMediaManagerChild::Init(); 1469 1470 Preferences::RegisterCallbackAndCall(&OnFissionBlocklistPrefChange, 1471 kFissionEnforceBlockList); 1472 Preferences::RegisterCallbackAndCall(&OnFissionBlocklistPrefChange, 1473 kFissionOmitBlockListValues); 1474 1475 // Set the dynamic scalar definitions for this process. 1476 TelemetryIPC::AddDynamicScalarDefinitions(aXPCOMInit.dynamicScalarDefs()); 1477 } 1478 1479 mozilla::ipc::IPCResult ContentChild::RecvRequestMemoryReport( 1480 const uint32_t& aGeneration, const bool& aAnonymize, 1481 const bool& aMinimizeMemoryUsage, 1482 const Maybe<mozilla::ipc::FileDescriptor>& aDMDFile, 1483 const RequestMemoryReportResolver& aResolver) { 1484 nsCString process; 1485 if (aAnonymize || mRemoteType.IsEmpty()) { 1486 GetProcessName(process); 1487 } else { 1488 process = mRemoteType; 1489 } 1490 AppendProcessId(process); 1491 MOZ_ASSERT(!process.IsEmpty()); 1492 1493 MemoryReportRequestClient::Start( 1494 aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, process, 1495 [&](const MemoryReport& aReport) { 1496 (void)GetSingleton()->SendAddMemoryReport(aReport); 1497 }, 1498 aResolver); 1499 return IPC_OK(); 1500 } 1501 1502 mozilla::ipc::IPCResult ContentChild::RecvDecodeImage( 1503 NotNull<nsIURI*> aURI, const ImageIntSize& aSize, 1504 DecodeImageResolver&& aResolver) { 1505 auto size = aSize.ToUnknownSize(); 1506 // TODO(Bug 1999930): Investigate using a content-principal for 1507 // moz-remote-image: requests 1508 image::FetchDecodedImage(aURI, size, nsContentUtils::GetSystemPrincipal()) 1509 ->Then( 1510 GetCurrentSerialEventTarget(), __func__, 1511 [size, aResolver](already_AddRefed<imgIContainer> aImage) { 1512 using Result = std::tuple<nsresult, mozilla::Maybe<IPCImage>>; 1513 1514 nsCOMPtr<imgIContainer> image(std::move(aImage)); 1515 1516 const int32_t flags = imgIContainer::FLAG_SYNC_DECODE | 1517 imgIContainer::FLAG_ASYNC_NOTIFY; 1518 RefPtr<gfx::SourceSurface> surface; 1519 if (size.Width() && size.Height()) { 1520 surface = image->GetFrameAtSize(size, imgIContainer::FRAME_FIRST, 1521 flags); 1522 if (surface && surface->GetSize() != size) { 1523 surface = gfxUtils::ScaleSourceSurface(*surface, size); 1524 } 1525 } else { 1526 surface = image->GetFrame(imgIContainer::FRAME_FIRST, flags); 1527 } 1528 1529 if (!surface) { 1530 aResolver(Result(NS_ERROR_FAILURE, Nothing())); 1531 return; 1532 } 1533 1534 if (RefPtr<gfx::DataSourceSurface> dataSurface = 1535 surface->GetDataSurface()) { 1536 if (Maybe<IPCImage> image = 1537 nsContentUtils::SurfaceToIPCImage(*dataSurface)) { 1538 aResolver(Result(NS_OK, std::move(image))); 1539 return; 1540 } 1541 } 1542 1543 aResolver(Result(NS_ERROR_FAILURE, Nothing())); 1544 return; 1545 }, 1546 [aResolver](nsresult aStatus) { 1547 aResolver(std::tuple<nsresult, mozilla::Maybe<IPCImage>>( 1548 aStatus, Nothing())); 1549 }); 1550 1551 return IPC_OK(); 1552 } 1553 1554 #if defined(XP_WIN) 1555 mozilla::ipc::IPCResult ContentChild::RecvGetUntrustedModulesData( 1556 GetUntrustedModulesDataResolver&& aResolver) { 1557 RefPtr<DllServices> dllSvc(DllServices::Get()); 1558 dllSvc->GetUntrustedModulesData()->Then( 1559 GetMainThreadSerialEventTarget(), __func__, 1560 [aResolver](Maybe<UntrustedModulesData>&& aData) { 1561 aResolver(std::move(aData)); 1562 }, 1563 [aResolver](nsresult aReason) { aResolver(Nothing()); }); 1564 return IPC_OK(); 1565 } 1566 1567 mozilla::ipc::IPCResult ContentChild::RecvUnblockUntrustedModulesThread() { 1568 if (nsCOMPtr<nsIObserverService> obs = 1569 mozilla::services::GetObserverService()) { 1570 obs->NotifyObservers(nullptr, "unblock-untrusted-modules-thread", nullptr); 1571 } 1572 return IPC_OK(); 1573 } 1574 #endif // defined(XP_WIN) 1575 1576 PCycleCollectWithLogsChild* ContentChild::AllocPCycleCollectWithLogsChild( 1577 const bool& aDumpAllTraces, const FileDescriptor& aGCLog, 1578 const FileDescriptor& aCCLog) { 1579 return do_AddRef(new CycleCollectWithLogsChild()).take(); 1580 } 1581 1582 mozilla::ipc::IPCResult ContentChild::RecvPCycleCollectWithLogsConstructor( 1583 PCycleCollectWithLogsChild* aActor, const bool& aDumpAllTraces, 1584 const FileDescriptor& aGCLog, const FileDescriptor& aCCLog) { 1585 // The sink's destructor is called when the last reference goes away, which 1586 // will cause the actor to be closed down. 1587 auto* actor = static_cast<CycleCollectWithLogsChild*>(aActor); 1588 RefPtr<CycleCollectWithLogsChild::Sink> sink = 1589 new CycleCollectWithLogsChild::Sink(actor, aGCLog, aCCLog); 1590 1591 // Invoke the dumper, which will take a reference to the sink. 1592 nsCOMPtr<nsIMemoryInfoDumper> dumper = 1593 do_GetService("@mozilla.org/memory-info-dumper;1"); 1594 dumper->DumpGCAndCCLogsToSink(aDumpAllTraces, sink); 1595 return IPC_OK(); 1596 } 1597 1598 bool ContentChild::DeallocPCycleCollectWithLogsChild( 1599 PCycleCollectWithLogsChild* aActor) { 1600 RefPtr<CycleCollectWithLogsChild> actor = 1601 dont_AddRef(static_cast<CycleCollectWithLogsChild*>(aActor)); 1602 return true; 1603 } 1604 1605 mozilla::ipc::IPCResult ContentChild::RecvInitGMPService( 1606 Endpoint<PGMPServiceChild>&& aGMPService) { 1607 if (!GMPServiceChild::Create(std::move(aGMPService))) { 1608 return IPC_FAIL_NO_REASON(this); 1609 } 1610 return IPC_OK(); 1611 } 1612 1613 mozilla::ipc::IPCResult ContentChild::RecvInitProfiler( 1614 Endpoint<PProfilerChild>&& aEndpoint) { 1615 mProfilerController = ChildProfilerController::Create(std::move(aEndpoint)); 1616 return IPC_OK(); 1617 } 1618 1619 mozilla::ipc::IPCResult ContentChild::RecvGMPsChanged( 1620 nsTArray<GMPCapabilityData>&& capabilities) { 1621 GeckoMediaPluginServiceChild::UpdateGMPCapabilities(std::move(capabilities)); 1622 return IPC_OK(); 1623 } 1624 1625 mozilla::ipc::IPCResult ContentChild::RecvInitProcessHangMonitor( 1626 Endpoint<PProcessHangMonitorChild>&& aHangMonitor) { 1627 CreateHangMonitorChild(std::move(aHangMonitor)); 1628 return IPC_OK(); 1629 } 1630 1631 mozilla::ipc::IPCResult ContentChild::GetResultForRenderingInitFailure( 1632 GeckoChildID aOtherChildID) { 1633 if (aOtherChildID == XRE_GetChildID() || aOtherChildID == OtherChildID()) { 1634 // If we are talking to ourselves, or the UI process, then that is a fatal 1635 // protocol error. 1636 return IPC_FAIL_NO_REASON(this); 1637 } 1638 1639 // If we are talking to the GPU process, then we should recover from this on 1640 // the next ContentChild::RecvReinitRendering call. 1641 gfxCriticalNote << "Could not initialize rendering with GPU process"; 1642 return IPC_OK(); 1643 } 1644 1645 #if defined(XP_MACOSX) 1646 extern "C" { 1647 void CGSShutdownServerConnections(); 1648 }; 1649 #endif 1650 1651 mozilla::ipc::IPCResult ContentChild::RecvInitRendering( 1652 Endpoint<PCompositorManagerChild>&& aCompositor, 1653 Endpoint<PImageBridgeChild>&& aImageBridge, 1654 Endpoint<PVRManagerChild>&& aVRBridge, 1655 Endpoint<PRemoteMediaManagerChild>&& aVideoManager, 1656 nsTArray<uint32_t>&& namespaces) { 1657 MOZ_ASSERT(namespaces.Length() == 3); 1658 1659 // Note that for all of the methods below, if it can fail, it should only 1660 // return false if the failure is an IPDL error. In such situations, 1661 // ContentChild can reason about whether or not to wait for 1662 // RecvReinitRendering (because we surmised the GPU process crashed), or if it 1663 // should crash itself (because we are actually talking to the UI process). If 1664 // there are localized failures (e.g. failed to spawn a thread), then it 1665 // should MOZ_RELEASE_ASSERT or MOZ_CRASH as necessary instead. 1666 if (!CompositorManagerChild::Init(std::move(aCompositor), namespaces[0])) { 1667 return GetResultForRenderingInitFailure(aCompositor.OtherChildID()); 1668 } 1669 if (!CompositorManagerChild::CreateContentCompositorBridge(namespaces[1])) { 1670 return GetResultForRenderingInitFailure(aCompositor.OtherChildID()); 1671 } 1672 if (!ImageBridgeChild::InitForContent(std::move(aImageBridge), 1673 namespaces[2])) { 1674 return GetResultForRenderingInitFailure(aImageBridge.OtherChildID()); 1675 } 1676 if (!gfx::VRManagerChild::InitForContent(std::move(aVRBridge))) { 1677 return GetResultForRenderingInitFailure(aVRBridge.OtherChildID()); 1678 } 1679 RemoteMediaManagerChild::InitForGPUProcess(std::move(aVideoManager)); 1680 1681 #if defined(XP_MACOSX) && !defined(MOZ_SANDBOX) 1682 // Close all current connections to the WindowServer. This ensures that the 1683 // Activity Monitor will not label the content process as "Not responding" 1684 // because it's not running a native event loop. See bug 1384336. When the 1685 // build is configured with sandbox support, this is called during sandbox 1686 // setup. 1687 CGSShutdownServerConnections(); 1688 #endif 1689 1690 return IPC_OK(); 1691 } 1692 1693 mozilla::ipc::IPCResult ContentChild::RecvReinitRendering( 1694 Endpoint<PCompositorManagerChild>&& aCompositor, 1695 Endpoint<PImageBridgeChild>&& aImageBridge, 1696 Endpoint<PVRManagerChild>&& aVRBridge, 1697 Endpoint<PRemoteMediaManagerChild>&& aVideoManager, 1698 nsTArray<uint32_t>&& namespaces) { 1699 MOZ_ASSERT(namespaces.Length() == 3); 1700 nsTArray<RefPtr<BrowserChild>> tabs = BrowserChild::GetAll(); 1701 1702 // Re-establish singleton bridges to the compositor. 1703 if (!CompositorManagerChild::Init(std::move(aCompositor), namespaces[0])) { 1704 return GetResultForRenderingInitFailure(aCompositor.OtherChildID()); 1705 } 1706 if (!CompositorManagerChild::CreateContentCompositorBridge(namespaces[1])) { 1707 return GetResultForRenderingInitFailure(aCompositor.OtherChildID()); 1708 } 1709 if (!ImageBridgeChild::ReinitForContent(std::move(aImageBridge), 1710 namespaces[2])) { 1711 return GetResultForRenderingInitFailure(aImageBridge.OtherChildID()); 1712 } 1713 if (!gfx::VRManagerChild::InitForContent(std::move(aVRBridge))) { 1714 return GetResultForRenderingInitFailure(aVRBridge.OtherChildID()); 1715 } 1716 gfxPlatform::GetPlatform()->CompositorUpdated(); 1717 1718 // Establish new PLayerTransactions. 1719 for (const auto& browserChild : tabs) { 1720 if (browserChild->GetLayersId().IsValid()) { 1721 browserChild->ReinitRendering(); 1722 } 1723 } 1724 1725 // Notify any observers that the compositor has been reinitialized, 1726 // eg the ZoomConstraintsClients for documents in this process. 1727 // This must occur after the ReinitRendering call above so that the 1728 // APZCTreeManagers have been connected. 1729 nsCOMPtr<nsIObserverService> observerService = services::GetObserverService(); 1730 if (observerService) { 1731 observerService->NotifyObservers(nullptr, "compositor-reinitialized", 1732 nullptr); 1733 } 1734 1735 RemoteMediaManagerChild::InitForGPUProcess(std::move(aVideoManager)); 1736 return IPC_OK(); 1737 } 1738 1739 mozilla::ipc::IPCResult ContentChild::RecvReinitRenderingForDeviceReset() { 1740 gfxPlatform::GetPlatform()->CompositorUpdated(); 1741 1742 nsTArray<RefPtr<BrowserChild>> tabs = BrowserChild::GetAll(); 1743 for (const auto& browserChild : tabs) { 1744 if (browserChild->GetLayersId().IsValid()) { 1745 browserChild->ReinitRenderingForDeviceReset(); 1746 } 1747 } 1748 return IPC_OK(); 1749 } 1750 1751 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX) 1752 extern "C" { 1753 CGError CGSSetDenyWindowServerConnections(bool); 1754 }; 1755 1756 static void DisconnectWindowServer(bool aIsSandboxEnabled) { 1757 // Close all current connections to the WindowServer. This ensures that the 1758 // Activity Monitor will not label the content process as "Not responding" 1759 // because it's not running a native event loop. See bug 1384336. 1760 // This is required with or without the sandbox enabled. Until the 1761 // window server is blocked as the policy level, this should be called 1762 // just before CGSSetDenyWindowServerConnections() so there are no 1763 // windowserver connections active when CGSSetDenyWindowServerConnections() 1764 // is called. 1765 CGSShutdownServerConnections(); 1766 1767 // Actual security benefits are only achieved when we additionally deny 1768 // future connections using the sandbox policy. WebGL must be remoted if 1769 // the windowserver connections are blocked. WebGL remoting is disabled 1770 // for some tests. 1771 if (aIsSandboxEnabled && 1772 Preferences::GetBool( 1773 "security.sandbox.content.mac.disconnect-windowserver") && 1774 Preferences::GetBool("webgl.out-of-process")) { 1775 CGError result = CGSSetDenyWindowServerConnections(true); 1776 MOZ_DIAGNOSTIC_ASSERT(result == kCGErrorSuccess); 1777 # if !MOZ_DIAGNOSTIC_ASSERT_ENABLED 1778 (void)result; 1779 # endif 1780 } 1781 } 1782 #endif 1783 1784 mozilla::ipc::IPCResult ContentChild::RecvSetProcessSandbox( 1785 const Maybe<mozilla::ipc::FileDescriptor>& aBroker) { 1786 // We may want to move the sandbox initialization somewhere else 1787 // at some point; see bug 880808. 1788 #if defined(MOZ_SANDBOX) 1789 1790 bool sandboxEnabled = true; 1791 # if defined(XP_LINUX) 1792 // On Linux, we have to support systems that can't use any sandboxing. 1793 sandboxEnabled = SandboxInfo::Get().CanSandboxContent(); 1794 1795 if (sandboxEnabled && !StaticPrefs::media_cubeb_sandbox()) { 1796 // Pre-start audio before sandboxing; see bug 1443612. 1797 (void)CubebUtils::GetCubeb(); 1798 } 1799 1800 if (sandboxEnabled) { 1801 RegisterProfilerObserversForSandboxProfiler(); 1802 sandboxEnabled = SetContentProcessSandbox( 1803 ContentProcessSandboxParams::ForThisProcess(aBroker)); 1804 } 1805 # elif defined(XP_WIN) 1806 if (GetEffectiveContentSandboxLevel() > 7) { 1807 // Libraries required by Network Security Services (NSS). 1808 ::LoadLibraryW(L"freebl3.dll"); 1809 ::LoadLibraryW(L"softokn3.dll"); 1810 // Cache value that is retrieved from a registry entry. 1811 (void)GetCpuFrequencyMHz(); 1812 } 1813 mozilla::SandboxTarget::Instance()->StartSandbox(); 1814 # elif defined(XP_MACOSX) 1815 sandboxEnabled = (GetEffectiveContentSandboxLevel() >= 1); 1816 DisconnectWindowServer(sandboxEnabled); 1817 # elif defined(XP_IOS) 1818 LockdownExtensionKitProcess(ExtensionKitSandboxRevision::Revision1); 1819 # endif 1820 1821 CrashReporter::RecordAnnotationBool( 1822 CrashReporter::Annotation::ContentSandboxEnabled, sandboxEnabled); 1823 # if defined(XP_LINUX) && !defined(ANDROID) 1824 CrashReporter::RecordAnnotationU32( 1825 CrashReporter::Annotation::ContentSandboxCapabilities, 1826 SandboxInfo::Get().AsInteger()); 1827 # endif /* XP_LINUX && !ANDROID */ 1828 #endif /* MOZ_SANDBOX */ 1829 1830 return IPC_OK(); 1831 } 1832 1833 mozilla::ipc::IPCResult ContentChild::RecvBidiKeyboardNotify( 1834 const bool& aIsLangRTL, const bool& aHaveBidiKeyboards) { 1835 // bidi is always of type PuppetBidiKeyboard* (because in the child, the only 1836 // possible implementation of nsIBidiKeyboard is PuppetBidiKeyboard). 1837 PuppetBidiKeyboard* bidi = 1838 static_cast<PuppetBidiKeyboard*>(nsContentUtils::GetBidiKeyboard()); 1839 if (bidi) { 1840 bidi->SetBidiKeyboardInfo(aIsLangRTL, aHaveBidiKeyboards); 1841 } 1842 return IPC_OK(); 1843 } 1844 1845 static StaticRefPtr<CancelableRunnable> gFirstIdleTask; 1846 1847 static void FirstIdle(void) { 1848 MOZ_ASSERT(gFirstIdleTask); 1849 gFirstIdleTask = nullptr; 1850 1851 ContentChild::GetSingleton()->SendFirstIdle(); 1852 } 1853 1854 mozilla::ipc::IPCResult ContentChild::RecvConstructBrowser( 1855 ManagedEndpoint<PBrowserChild>&& aBrowserEp, 1856 ManagedEndpoint<PWindowGlobalChild>&& aWindowEp, const TabId& aTabId, 1857 const IPCTabContext& aContext, const WindowGlobalInit& aWindowInit, 1858 const uint32_t& aChromeFlags, const ContentParentId& aCpID, 1859 const bool& aIsForBrowser, const bool& aIsTopLevel) { 1860 MOZ_DIAGNOSTIC_ASSERT(!IsShuttingDown()); 1861 1862 static bool hasRunOnce = false; 1863 if (!hasRunOnce) { 1864 hasRunOnce = true; 1865 MOZ_ASSERT(!gFirstIdleTask); 1866 RefPtr<CancelableRunnable> firstIdleTask = 1867 NewCancelableRunnableFunction("FirstIdleRunnable", FirstIdle); 1868 gFirstIdleTask = firstIdleTask; 1869 if (NS_FAILED(NS_DispatchToCurrentThreadQueue(firstIdleTask.forget(), 1870 EventQueuePriority::Idle))) { 1871 gFirstIdleTask = nullptr; 1872 hasRunOnce = false; 1873 } 1874 } 1875 1876 RefPtr<BrowsingContext> browsingContext = 1877 BrowsingContext::Get(aWindowInit.context().mBrowsingContextId); 1878 if (!browsingContext || browsingContext->IsDiscarded()) { 1879 nsPrintfCString reason("%s initial %s BrowsingContext", 1880 browsingContext ? "discarded" : "missing", 1881 aIsTopLevel ? "top" : "frame"); 1882 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Warning, ("%s", reason.get())); 1883 if (!aIsTopLevel) { 1884 // Recover if the BrowsingContext is missing for a new subframe. The 1885 // `ManagedEndpoint` instances will be automatically destroyed. 1886 NS_WARNING(reason.get()); 1887 return IPC_OK(); 1888 } 1889 1890 // (these are the only possible values of `reason` at this point) 1891 return browsingContext 1892 ? IPC_FAIL(this, "discarded initial top BrowsingContext") 1893 : IPC_FAIL(this, "missing initial top BrowsingContext"); 1894 } 1895 1896 if (xpc::IsInAutomation() && 1897 StaticPrefs:: 1898 browser_tabs_remote_testOnly_failPBrowserCreation_enabled()) { 1899 nsAutoCString idString; 1900 if (NS_SUCCEEDED(Preferences::GetCString( 1901 "browser.tabs.remote.testOnly.failPBrowserCreation.browsingContext", 1902 idString))) { 1903 nsresult rv = NS_OK; 1904 uint64_t bcid = idString.ToInteger64(&rv); 1905 if (NS_SUCCEEDED(rv) && bcid == browsingContext->Id()) { 1906 NS_WARNING("Injecting artificial PBrowser creation failure"); 1907 return IPC_OK(); 1908 } 1909 } 1910 } 1911 1912 if (!aWindowInit.isInitialDocument() || 1913 !NS_IsAboutBlank(aWindowInit.documentURI())) { 1914 return IPC_FAIL(this, 1915 "Logic in CreateDocumentViewerForActor currently requires " 1916 "actors to be initial about:blank documents"); 1917 } 1918 1919 // We'll happily accept any kind of IPCTabContext here; we don't need to 1920 // check that it's of a certain type for security purposes, because we 1921 // believe whatever the parent process tells us. 1922 MaybeInvalidTabContext tc(aContext); 1923 if (!tc.IsValid()) { 1924 NS_ERROR(nsPrintfCString("Received an invalid TabContext from " 1925 "the parent process. (%s) Crashing...", 1926 tc.GetInvalidReason()) 1927 .get()); 1928 MOZ_CRASH("Invalid TabContext received from the parent process."); 1929 } 1930 1931 RefPtr<WindowGlobalChild> windowChild = 1932 WindowGlobalChild::CreateDisconnected(aWindowInit); 1933 if (!windowChild) { 1934 return IPC_FAIL(this, "Failed to create initial WindowGlobalChild"); 1935 } 1936 1937 RefPtr<BrowserChild> browserChild = 1938 BrowserChild::Create(this, aTabId, tc.GetTabContext(), browsingContext, 1939 aChromeFlags, aIsTopLevel); 1940 1941 // Bind the created BrowserChild to IPC to actually link the actor. 1942 if (NS_WARN_IF(!BindPBrowserEndpoint(std::move(aBrowserEp), browserChild))) { 1943 return IPC_FAIL(this, "BindPBrowserEndpoint failed"); 1944 } 1945 1946 if (NS_WARN_IF(!browserChild->BindPWindowGlobalEndpoint(std::move(aWindowEp), 1947 windowChild))) { 1948 return IPC_FAIL(this, "BindPWindowGlobalEndpoint failed"); 1949 } 1950 windowChild->Init(); 1951 auto guardNullWindowGlobal = MakeScopeExit([&] { 1952 if (!windowChild->GetWindowGlobal()) { 1953 windowChild->Destroy(); 1954 } 1955 }); 1956 1957 // Ensure that a BrowsingContext is set for our BrowserChild before 1958 // running `Init`. 1959 MOZ_RELEASE_ASSERT(browserChild->mBrowsingContext->Id() == 1960 aWindowInit.context().mBrowsingContextId); 1961 1962 RefPtr<nsOpenWindowInfo> openWindowInfo = new nsOpenWindowInfo(); 1963 openWindowInfo->mPrincipalToInheritForAboutBlank = aWindowInit.principal(); 1964 // XXX We should consider moving this to CreateAboutBlankDocumentViewer (bug 1965 // 2004943) 1966 openWindowInfo->mPolicyContainerToInheritForAboutBlank = 1967 new PolicyContainer(); 1968 1969 { 1970 // Block the script runner that notifies about the creation of the script 1971 // global for the initial about:blank. 1972 nsAutoScriptBlocker blockScripts; 1973 1974 if (NS_WARN_IF(NS_FAILED(browserChild->Init( 1975 /* aOpener */ nullptr, windowChild, openWindowInfo)))) { 1976 return IPC_FAIL(browserChild, "BrowserChild::Init failed"); 1977 } 1978 } 1979 1980 nsCOMPtr<nsIObserverService> os = services::GetObserverService(); 1981 if (os) { 1982 os->NotifyObservers(static_cast<nsIBrowserChild*>(browserChild), 1983 "tab-child-created", nullptr); 1984 } 1985 // Notify parent that we are ready to handle input events. 1986 browserChild->SendRemoteIsReadyToHandleInputEvents(); 1987 return IPC_OK(); 1988 } 1989 1990 void ContentChild::GetAvailableDictionaries( 1991 nsTArray<nsCString>& aDictionaries) { 1992 aDictionaries = mAvailableDictionaries.Clone(); 1993 } 1994 1995 mozilla::PRemoteSpellcheckEngineChild* 1996 ContentChild::AllocPRemoteSpellcheckEngineChild() { 1997 MOZ_CRASH( 1998 "Default Constructor for PRemoteSpellcheckEngineChild should never be " 1999 "called"); 2000 return nullptr; 2001 } 2002 2003 bool ContentChild::DeallocPRemoteSpellcheckEngineChild( 2004 PRemoteSpellcheckEngineChild* child) { 2005 delete child; 2006 return true; 2007 } 2008 2009 mozilla::ipc::IPCResult ContentChild::RecvNotifyEmptyHTTPCache() { 2010 MOZ_ASSERT(NS_IsMainThread()); 2011 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); 2012 obs->NotifyObservers(nullptr, "cacheservice:empty-cache", nullptr); 2013 return IPC_OK(); 2014 } 2015 2016 PHalChild* ContentChild::AllocPHalChild() { return CreateHalChild(); } 2017 2018 bool ContentChild::DeallocPHalChild(PHalChild* aHal) { 2019 delete aHal; 2020 return true; 2021 } 2022 2023 devtools::PHeapSnapshotTempFileHelperChild* 2024 ContentChild::AllocPHeapSnapshotTempFileHelperChild() { 2025 return devtools::HeapSnapshotTempFileHelperChild::Create(); 2026 } 2027 2028 bool ContentChild::DeallocPHeapSnapshotTempFileHelperChild( 2029 devtools::PHeapSnapshotTempFileHelperChild* aHeapSnapshotHelper) { 2030 delete aHeapSnapshotHelper; 2031 return true; 2032 } 2033 2034 already_AddRefed<PTestShellChild> ContentChild::AllocPTestShellChild() { 2035 return MakeAndAddRef<TestShellChild>(); 2036 } 2037 2038 mozilla::ipc::IPCResult ContentChild::RecvPTestShellConstructor( 2039 PTestShellChild* actor) { 2040 return IPC_OK(); 2041 } 2042 2043 RefPtr<GenericPromise> ContentChild::UpdateCookieStatus(nsIChannel* aChannel) { 2044 RefPtr<CookieServiceChild> csChild = CookieServiceChild::GetSingleton(); 2045 NS_ASSERTION(csChild, "Couldn't get CookieServiceChild"); 2046 2047 return csChild->TrackCookieLoad(aChannel); 2048 } 2049 2050 PScriptCacheChild* ContentChild::AllocPScriptCacheChild( 2051 const FileDescOrError& cacheFile, const bool& wantCacheData) { 2052 return new loader::ScriptCacheChild(); 2053 } 2054 2055 bool ContentChild::DeallocPScriptCacheChild(PScriptCacheChild* cache) { 2056 delete static_cast<loader::ScriptCacheChild*>(cache); 2057 return true; 2058 } 2059 2060 mozilla::ipc::IPCResult ContentChild::RecvPScriptCacheConstructor( 2061 PScriptCacheChild* actor, const FileDescOrError& cacheFile, 2062 const bool& wantCacheData) { 2063 Maybe<FileDescriptor> fd; 2064 if (cacheFile.type() == cacheFile.TFileDescriptor) { 2065 fd.emplace(cacheFile.get_FileDescriptor()); 2066 } 2067 2068 static_cast<loader::ScriptCacheChild*>(actor)->Init(fd, wantCacheData); 2069 2070 // Some scripts listen for "app-startup" to start. However, in the content 2071 // process, this category runs before the ScriptPreloader is initialized so 2072 // these scripts wouldn't be added to the cache. Instead, if a script needs to 2073 // run on start up in the content process, it should listen for this category. 2074 NS_CreateServicesFromCategory("content-process-ready-for-script", nullptr, 2075 "content-process-ready-for-script", nullptr); 2076 2077 return IPC_OK(); 2078 } 2079 2080 mozilla::ipc::IPCResult ContentChild::RecvNetworkLinkTypeChange( 2081 const uint32_t& aType) { 2082 mNetworkLinkType = aType; 2083 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); 2084 if (obs) { 2085 obs->NotifyObservers(nullptr, "contentchild:network-link-type-changed", 2086 nullptr); 2087 } 2088 return IPC_OK(); 2089 } 2090 2091 mozilla::ipc::IPCResult ContentChild::RecvSocketProcessCrashed() { 2092 nsIOService::IncreaseSocketProcessCrashCount(); 2093 return IPC_OK(); 2094 } 2095 2096 PRemotePrintJobChild* ContentChild::AllocPRemotePrintJobChild() { 2097 #ifdef NS_PRINTING 2098 return new RemotePrintJobChild(); 2099 #else 2100 return nullptr; 2101 #endif 2102 } 2103 2104 media::PMediaChild* ContentChild::AllocPMediaChild() { 2105 return media::AllocPMediaChild(); 2106 } 2107 2108 bool ContentChild::DeallocPMediaChild(media::PMediaChild* aActor) { 2109 return media::DeallocPMediaChild(aActor); 2110 } 2111 2112 #ifdef MOZ_WEBRTC 2113 PWebrtcGlobalChild* ContentChild::AllocPWebrtcGlobalChild() { 2114 auto* child = new WebrtcGlobalChild(); 2115 return child; 2116 } 2117 2118 bool ContentChild::DeallocPWebrtcGlobalChild(PWebrtcGlobalChild* aActor) { 2119 delete static_cast<WebrtcGlobalChild*>(aActor); 2120 return true; 2121 } 2122 #endif 2123 2124 mozilla::ipc::IPCResult ContentChild::RecvRegisterChrome( 2125 nsTArray<ChromePackage>&& packages, 2126 nsTArray<SubstitutionMapping>&& resources, 2127 nsTArray<OverrideMapping>&& overrides, const nsCString& locale, 2128 const bool& reset) { 2129 nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService(); 2130 nsChromeRegistryContent* chromeRegistry = 2131 static_cast<nsChromeRegistryContent*>(registrySvc.get()); 2132 if (!chromeRegistry) { 2133 return IPC_FAIL(this, "ChromeRegistryContent is null!"); 2134 } 2135 chromeRegistry->RegisterRemoteChrome(packages, resources, overrides, locale, 2136 reset); 2137 return IPC_OK(); 2138 } 2139 2140 mozilla::ipc::IPCResult ContentChild::RecvRegisterChromeItem( 2141 const ChromeRegistryItem& item) { 2142 nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService(); 2143 nsChromeRegistryContent* chromeRegistry = 2144 static_cast<nsChromeRegistryContent*>(registrySvc.get()); 2145 if (!chromeRegistry) { 2146 return IPC_FAIL(this, "ChromeRegistryContent is null!"); 2147 } 2148 switch (item.type()) { 2149 case ChromeRegistryItem::TChromePackage: 2150 chromeRegistry->RegisterPackage(item.get_ChromePackage()); 2151 break; 2152 2153 case ChromeRegistryItem::TOverrideMapping: 2154 chromeRegistry->RegisterOverride(item.get_OverrideMapping()); 2155 break; 2156 2157 case ChromeRegistryItem::TSubstitutionMapping: 2158 chromeRegistry->RegisterSubstitution(item.get_SubstitutionMapping()); 2159 break; 2160 2161 default: 2162 MOZ_ASSERT(false, "bad chrome item"); 2163 return IPC_FAIL_NO_REASON(this); 2164 } 2165 2166 return IPC_OK(); 2167 } 2168 mozilla::ipc::IPCResult ContentChild::RecvClearStyleSheetCache( 2169 const Maybe<bool>& aChrome, const Maybe<RefPtr<nsIPrincipal>>& aPrincipal, 2170 const Maybe<nsCString>& aSchemelessSite, 2171 const Maybe<OriginAttributesPattern>& aPattern, 2172 const Maybe<nsCString>& aURL) { 2173 SharedStyleSheetCache::Clear(aChrome, aPrincipal, aSchemelessSite, aPattern, 2174 aURL); 2175 return IPC_OK(); 2176 } 2177 2178 mozilla::ipc::IPCResult ContentChild::RecvClearScriptCache( 2179 const Maybe<bool>& aChrome, const Maybe<RefPtr<nsIPrincipal>>& aPrincipal, 2180 const Maybe<nsCString>& aSchemelessSite, 2181 const Maybe<OriginAttributesPattern>& aPattern, 2182 const Maybe<nsCString>& aURL) { 2183 SharedScriptCache::Clear(aChrome, aPrincipal, aSchemelessSite, aPattern, 2184 aURL); 2185 return IPC_OK(); 2186 } 2187 2188 mozilla::ipc::IPCResult ContentChild::RecvInvalidateScriptCache() { 2189 SharedScriptCache::Invalidate(); 2190 return IPC_OK(); 2191 } 2192 2193 mozilla::ipc::IPCResult ContentChild::RecvClearImageCache( 2194 const Maybe<bool>& aPrivateLoader, const Maybe<bool>& aChrome, 2195 const Maybe<RefPtr<nsIPrincipal>>& aPrincipal, 2196 const Maybe<nsCString>& aSchemelessSite, 2197 const Maybe<OriginAttributesPattern>& aPattern, 2198 const Maybe<nsCString>& aURL) { 2199 imgLoader::ClearCache(aPrincipal, aChrome, aPrincipal, aSchemelessSite, 2200 aPattern, aURL); 2201 return IPC_OK(); 2202 } 2203 2204 mozilla::ipc::IPCResult ContentChild::RecvSetOffline(const bool& offline) { 2205 nsCOMPtr<nsIIOService> io(do_GetIOService()); 2206 NS_ASSERTION(io, "IO Service can not be null"); 2207 2208 io->SetOffline(offline); 2209 2210 return IPC_OK(); 2211 } 2212 2213 mozilla::ipc::IPCResult ContentChild::RecvSetConnectivity( 2214 const bool& connectivity) { 2215 nsCOMPtr<nsIIOService> io(do_GetIOService()); 2216 nsCOMPtr<nsIIOServiceInternal> ioInternal(do_QueryInterface(io)); 2217 NS_ASSERTION(ioInternal, "IO Service can not be null"); 2218 2219 ioInternal->SetConnectivity(connectivity); 2220 2221 return IPC_OK(); 2222 } 2223 2224 mozilla::ipc::IPCResult ContentChild::RecvSetCaptivePortalState( 2225 const int32_t& aState) { 2226 nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID); 2227 if (!cps) { 2228 return IPC_OK(); 2229 } 2230 2231 mozilla::net::CaptivePortalService* portal = 2232 static_cast<mozilla::net::CaptivePortalService*>(cps.get()); 2233 portal->SetStateInChild(aState); 2234 2235 return IPC_OK(); 2236 } 2237 2238 mozilla::ipc::IPCResult ContentChild::RecvSetTRRMode( 2239 const nsIDNSService::ResolverMode& mode, 2240 const nsIDNSService::ResolverMode& modeFromPref) { 2241 RefPtr<net::ChildDNSService> dnsServiceChild = 2242 dont_AddRef(net::ChildDNSService::GetSingleton()); 2243 if (dnsServiceChild) { 2244 dnsServiceChild->SetTRRModeInChild(mode, modeFromPref); 2245 } 2246 return IPC_OK(); 2247 } 2248 2249 void ContentChild::ActorDestroy(ActorDestroyReason why) { 2250 #if defined(XP_LINUX) && defined(MOZ_SANDBOX) 2251 DestroySandboxProfiler(); 2252 #endif 2253 2254 if (mForceKillTimer) { 2255 mForceKillTimer->Cancel(); 2256 mForceKillTimer = nullptr; 2257 } 2258 2259 if (AbnormalShutdown == why) { 2260 NS_WARNING("shutting down early because of crash!"); 2261 ProcessChild::QuickExit(); 2262 } 2263 2264 #ifndef NS_FREE_PERMANENT_DATA 2265 // In release builds, there's no point in the content process 2266 // going through the full XPCOM shutdown path, because it doesn't 2267 // keep persistent state. 2268 ProcessChild::QuickExit(); 2269 #else 2270 // Destroy our JSProcessActors, and reject any pending queries. 2271 JSActorDidDestroy(); 2272 2273 # if defined(XP_WIN) 2274 RefPtr<DllServices> dllSvc(DllServices::Get()); 2275 dllSvc->DisableFull(); 2276 # endif // defined(XP_WIN) 2277 2278 if (gFirstIdleTask) { 2279 gFirstIdleTask->Cancel(); 2280 gFirstIdleTask = nullptr; 2281 } 2282 2283 BlobURLProtocolHandler::RemoveDataEntries(); 2284 2285 mSharedData = nullptr; 2286 2287 mIdleObservers.Clear(); 2288 2289 if (mConsoleListener) { 2290 nsCOMPtr<nsIConsoleService> svc( 2291 do_GetService(NS_CONSOLESERVICE_CONTRACTID)); 2292 if (svc) { 2293 svc->UnregisterListener(mConsoleListener); 2294 mConsoleListener->mChild = nullptr; 2295 } 2296 } 2297 mIsAlive = false; 2298 2299 CrashReporterClient::DestroySingleton(); 2300 2301 XRE_ShutdownChildProcess(); 2302 #endif // NS_FREE_PERMANENT_DATA 2303 } 2304 2305 void ContentChild::ProcessingError(Result aCode, const char* aReason) { 2306 switch (aCode) { 2307 case MsgDropped: 2308 NS_WARNING("MsgDropped in ContentChild"); 2309 return; 2310 2311 case MsgNotKnown: 2312 case MsgNotAllowed: 2313 case MsgPayloadError: 2314 case MsgProcessingError: 2315 case MsgValueError: 2316 break; 2317 2318 default: 2319 MOZ_CRASH("not reached"); 2320 } 2321 2322 CrashReporter::RecordAnnotationCString( 2323 CrashReporter::Annotation::ipc_channel_error, aReason); 2324 2325 MOZ_CRASH("Content child abort due to IPC error"); 2326 } 2327 2328 mozilla::ipc::IPCResult ContentChild::RecvPreferenceUpdate(const Pref& aPref) { 2329 Preferences::SetPreference(aPref); 2330 return IPC_OK(); 2331 } 2332 2333 mozilla::ipc::IPCResult ContentChild::RecvVarUpdate( 2334 const nsTArray<GfxVarUpdate>& aVar) { 2335 gfx::gfxVars::ApplyUpdate(aVar); 2336 return IPC_OK(); 2337 } 2338 2339 mozilla::ipc::IPCResult ContentChild::RecvUpdatePerfStatsCollectionMask( 2340 const uint64_t& aMask) { 2341 PerfStats::SetCollectionMask(static_cast<PerfStats::MetricMask>(aMask)); 2342 return IPC_OK(); 2343 } 2344 2345 mozilla::ipc::IPCResult ContentChild::RecvCollectPerfStatsJSON( 2346 CollectPerfStatsJSONResolver&& aResolver) { 2347 aResolver(PerfStats::CollectLocalPerfStatsJSON()); 2348 return IPC_OK(); 2349 } 2350 2351 mozilla::ipc::IPCResult ContentChild::RecvCollectScrollingMetrics( 2352 CollectScrollingMetricsResolver&& aResolver) { 2353 auto metrics = ScrollingMetrics::CollectLocalScrollingMetrics(); 2354 using ResolverArgs = std::tuple<const uint32_t&, const uint32_t&>; 2355 aResolver(ResolverArgs(std::get<0>(metrics), std::get<1>(metrics))); 2356 return IPC_OK(); 2357 } 2358 2359 mozilla::ipc::IPCResult ContentChild::RecvNotifyVisited( 2360 nsTArray<VisitedQueryResult>&& aURIs) { 2361 nsCOMPtr<IHistory> history = components::History::Service(); 2362 if (!history) { 2363 return IPC_OK(); 2364 } 2365 for (const VisitedQueryResult& result : aURIs) { 2366 nsCOMPtr<nsIURI> newURI = result.uri(); 2367 if (!newURI) { 2368 return IPC_FAIL_NO_REASON(this); 2369 } 2370 auto status = result.visited() ? IHistory::VisitedStatus::Visited 2371 : IHistory::VisitedStatus::Unvisited; 2372 history->NotifyVisited(newURI, status); 2373 } 2374 return IPC_OK(); 2375 } 2376 2377 mozilla::ipc::IPCResult ContentChild::RecvThemeChanged( 2378 FullLookAndFeel&& aLookAndFeelData, widget::ThemeChangeKind aKind) { 2379 LookAndFeel::SetData(std::move(aLookAndFeelData)); 2380 LookAndFeel::NotifyChangedAllWindows(aKind); 2381 return IPC_OK(); 2382 } 2383 2384 mozilla::ipc::IPCResult ContentChild::RecvLoadProcessScript( 2385 const nsString& aURL) { 2386 auto* global = ContentProcessMessageManager::Get(); 2387 if (global && global->LoadScript(aURL)) { 2388 return IPC_OK(); 2389 } 2390 return IPC_FAIL(this, "ContentProcessMessageManager::LoadScript failed"); 2391 } 2392 2393 mozilla::ipc::IPCResult ContentChild::RecvAsyncMessage( 2394 const nsString& aMsg, const ClonedMessageData& aData) { 2395 AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("ContentChild::RecvAsyncMessage", 2396 OTHER, aMsg); 2397 MMPrinter::Print("ContentChild::RecvAsyncMessage", aMsg, aData); 2398 2399 RefPtr<nsFrameMessageManager> cpm = 2400 nsFrameMessageManager::GetChildProcessManager(); 2401 if (cpm) { 2402 StructuredCloneData data; 2403 ipc::UnpackClonedMessageData(aData, data); 2404 cpm->ReceiveMessage(cpm, nullptr, aMsg, false, &data, nullptr, 2405 IgnoreErrors()); 2406 } 2407 return IPC_OK(); 2408 } 2409 2410 mozilla::ipc::IPCResult ContentChild::RecvRegisterStringBundles( 2411 nsTArray<mozilla::dom::StringBundleDescriptor>&& aDescriptors) { 2412 nsCOMPtr<nsIStringBundleService> stringBundleService = 2413 components::StringBundle::Service(); 2414 2415 for (auto& descriptor : aDescriptors) { 2416 stringBundleService->RegisterContentBundle( 2417 descriptor.bundleURL(), std::move(descriptor.mapHandle())); 2418 } 2419 2420 return IPC_OK(); 2421 } 2422 2423 mozilla::ipc::IPCResult ContentChild::RecvSimpleURIUnknownRemoteSchemes( 2424 nsTArray<nsCString>&& aRemoteSchemes) { 2425 RefPtr<nsIOService> io = nsIOService::GetInstance(); 2426 io->SetSimpleURIUnknownRemoteSchemes(aRemoteSchemes); 2427 return IPC_OK(); 2428 } 2429 2430 mozilla::ipc::IPCResult ContentChild::RecvUpdateL10nFileSources( 2431 nsTArray<mozilla::dom::L10nFileSourceDescriptor>&& aDescriptors) { 2432 L10nRegistry::RegisterFileSourcesFromParentProcess(aDescriptors); 2433 return IPC_OK(); 2434 } 2435 2436 mozilla::ipc::IPCResult ContentChild::RecvUpdateSharedData( 2437 mozilla::ipc::ReadOnlySharedMemoryHandle&& aMapHandle, 2438 nsTArray<IPCBlob>&& aBlobs, nsTArray<nsCString>&& aChangedKeys) { 2439 nsTArray<RefPtr<BlobImpl>> blobImpls(aBlobs.Length()); 2440 for (auto& ipcBlob : aBlobs) { 2441 blobImpls.AppendElement(IPCBlobUtils::Deserialize(ipcBlob)); 2442 } 2443 2444 if (mSharedData) { 2445 mSharedData->Update(std::move(aMapHandle), std::move(blobImpls), 2446 std::move(aChangedKeys)); 2447 } else { 2448 mSharedData = 2449 new SharedMap(ContentProcessMessageManager::Get()->GetParentObject(), 2450 std::move(aMapHandle), std::move(blobImpls)); 2451 } 2452 2453 return IPC_OK(); 2454 } 2455 2456 mozilla::ipc::IPCResult ContentChild::RecvForceGlobalReflow( 2457 const gfxPlatform::GlobalReflowFlags& aFlags) { 2458 gfxPlatform::ForceGlobalReflow(aFlags); 2459 2460 return IPC_OK(); 2461 } 2462 2463 mozilla::ipc::IPCResult ContentChild::RecvGeolocationUpdate( 2464 nsIDOMGeoPosition* aPosition) { 2465 RefPtr<nsGeolocationService> gs = 2466 nsGeolocationService::GetGeolocationService(); 2467 if (!gs) { 2468 return IPC_OK(); 2469 } 2470 gs->Update(aPosition); 2471 return IPC_OK(); 2472 } 2473 2474 mozilla::ipc::IPCResult ContentChild::RecvGeolocationError( 2475 const uint16_t& errorCode) { 2476 RefPtr<nsGeolocationService> gs = 2477 nsGeolocationService::GetGeolocationService(); 2478 if (!gs) { 2479 return IPC_OK(); 2480 } 2481 gs->NotifyError(errorCode); 2482 return IPC_OK(); 2483 } 2484 2485 mozilla::ipc::IPCResult ContentChild::RecvUpdateDictionaryList( 2486 nsTArray<nsCString>&& aDictionaries) { 2487 mAvailableDictionaries = std::move(aDictionaries); 2488 mozInlineSpellChecker::UpdateCanEnableInlineSpellChecking(); 2489 return IPC_OK(); 2490 } 2491 2492 mozilla::ipc::IPCResult ContentChild::RecvUpdateFontList( 2493 dom::SystemFontList&& aFontList) { 2494 mFontList = std::move(aFontList); 2495 if (gfxPlatform::Initialized()) { 2496 gfxPlatform::GetPlatform()->UpdateFontList(true); 2497 } 2498 return IPC_OK(); 2499 } 2500 2501 mozilla::ipc::IPCResult ContentChild::RecvRebuildFontList( 2502 const bool& aFullRebuild) { 2503 if (gfxPlatform::Initialized()) { 2504 gfxPlatform::GetPlatform()->UpdateFontList(aFullRebuild); 2505 } 2506 return IPC_OK(); 2507 } 2508 2509 mozilla::ipc::IPCResult ContentChild::RecvFontListShmBlockAdded( 2510 const uint32_t& aGeneration, const uint32_t& aIndex, 2511 mozilla::ipc::ReadOnlySharedMemoryHandle&& aHandle) { 2512 if (gfxPlatform::Initialized()) { 2513 gfxPlatformFontList::PlatformFontList()->ShmBlockAdded(aGeneration, aIndex, 2514 std::move(aHandle)); 2515 } 2516 return IPC_OK(); 2517 } 2518 2519 mozilla::ipc::IPCResult ContentChild::RecvUpdateAppLocales( 2520 nsTArray<nsCString>&& aAppLocales) { 2521 LocaleService::GetInstance()->AssignAppLocales(aAppLocales); 2522 return IPC_OK(); 2523 } 2524 2525 mozilla::ipc::IPCResult ContentChild::RecvUpdateRequestedLocales( 2526 nsTArray<nsCString>&& aRequestedLocales) { 2527 LocaleService::GetInstance()->AssignRequestedLocales(aRequestedLocales); 2528 return IPC_OK(); 2529 } 2530 2531 mozilla::ipc::IPCResult ContentChild::RecvSystemTimezoneChanged() { 2532 nsJSUtils::ResetTimeZone(); 2533 return IPC_OK(); 2534 } 2535 2536 mozilla::ipc::IPCResult ContentChild::RecvAddPermission( 2537 const IPC::Permission& permission) { 2538 RefPtr<PermissionManager> permissionManager = 2539 PermissionManager::GetInstance(); 2540 MOZ_ASSERT(permissionManager, 2541 "We have no permissionManager in the Content process !"); 2542 2543 // note we do not need to force mUserContextId to the default here because 2544 // the permission manager does that internally. 2545 nsAutoCString originNoSuffix; 2546 OriginAttributes attrs; 2547 bool success = attrs.PopulateFromOrigin(permission.origin, originNoSuffix); 2548 NS_ENSURE_TRUE(success, IPC_FAIL_NO_REASON(this)); 2549 2550 nsCOMPtr<nsIURI> uri; 2551 nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix); 2552 NS_ENSURE_SUCCESS(rv, IPC_OK()); 2553 2554 nsCOMPtr<nsIPrincipal> principal = 2555 mozilla::BasePrincipal::CreateContentPrincipal(uri, attrs); 2556 2557 // child processes don't care about modification time. 2558 int64_t modificationTime = 0; 2559 2560 permissionManager->Add( 2561 principal, nsCString(permission.type), permission.capability, 0, 2562 permission.expireType, permission.expireTime, modificationTime, 2563 PermissionManager::eNotify, PermissionManager::eNoDBOperation); 2564 2565 return IPC_OK(); 2566 } 2567 2568 mozilla::ipc::IPCResult ContentChild::RecvRemoveAllPermissions() { 2569 RefPtr<PermissionManager> permissionManager = 2570 PermissionManager::GetInstance(); 2571 MOZ_ASSERT(permissionManager, 2572 "We have no permissionManager in the Content process !"); 2573 2574 permissionManager->RemoveAllFromIPC(); 2575 return IPC_OK(); 2576 } 2577 2578 mozilla::ipc::IPCResult ContentChild::RecvFlushMemory(const nsString& reason) { 2579 nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService(); 2580 if (!mShuttingDown && os) { 2581 os->NotifyObservers(nullptr, "memory-pressure", reason.get()); 2582 } 2583 return IPC_OK(); 2584 } 2585 2586 mozilla::ipc::IPCResult ContentChild::RecvActivateA11y(uint64_t aCacheDomains) { 2587 #ifdef ACCESSIBILITY 2588 // Start accessibility in content process if it's running in chrome 2589 // process. 2590 GetOrCreateAccService(nsAccessibilityService::eMainProcess, aCacheDomains); 2591 #endif // ACCESSIBILITY 2592 return IPC_OK(); 2593 } 2594 2595 mozilla::ipc::IPCResult ContentChild::RecvShutdownA11y() { 2596 #ifdef ACCESSIBILITY 2597 // Try to shutdown accessibility in content process if it's shutting down in 2598 // chrome process. 2599 MaybeShutdownAccService(nsAccessibilityService::eMainProcess); 2600 #endif 2601 return IPC_OK(); 2602 } 2603 2604 mozilla::ipc::IPCResult ContentChild::RecvSetCacheDomains( 2605 uint64_t aCacheDomains) { 2606 #ifdef ACCESSIBILITY 2607 nsAccessibilityService* accService = GetAccService(); 2608 if (!accService) { 2609 return IPC_FAIL(this, "Accessibility service should exist"); 2610 } 2611 accService->SetCacheDomains(aCacheDomains); 2612 #endif 2613 return IPC_OK(); 2614 } 2615 2616 mozilla::ipc::IPCResult ContentChild::RecvApplicationForeground() { 2617 // Rebroadcast the "application-foreground" 2618 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); 2619 if (obs) { 2620 obs->NotifyObservers(nullptr, "application-foreground", nullptr); 2621 } 2622 return IPC_OK(); 2623 } 2624 2625 mozilla::ipc::IPCResult ContentChild::RecvApplicationBackground() { 2626 // Rebroadcast the "application-background" 2627 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); 2628 if (obs) { 2629 obs->NotifyObservers(nullptr, "application-background", nullptr); 2630 } 2631 return IPC_OK(); 2632 } 2633 2634 mozilla::ipc::IPCResult ContentChild::RecvGarbageCollect() { 2635 // Rebroadcast the "child-gc-request" so that workers will GC. 2636 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); 2637 if (obs) { 2638 obs->NotifyObservers(nullptr, "child-gc-request", nullptr); 2639 } 2640 nsJSContext::GarbageCollectNow(JS::GCReason::DOM_IPC); 2641 return IPC_OK(); 2642 } 2643 2644 mozilla::ipc::IPCResult ContentChild::RecvCycleCollect() { 2645 // Rebroadcast the "child-cc-request" so that workers will CC. 2646 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); 2647 if (obs) { 2648 obs->NotifyObservers(nullptr, "child-cc-request", nullptr); 2649 } 2650 nsJSContext::CycleCollectNow(CCReason::IPC_MESSAGE); 2651 return IPC_OK(); 2652 } 2653 2654 mozilla::ipc::IPCResult ContentChild::RecvUnlinkGhosts() { 2655 #ifdef DEBUG 2656 nsWindowMemoryReporter::UnlinkGhostWindows(); 2657 #endif 2658 return IPC_OK(); 2659 } 2660 2661 mozilla::ipc::IPCResult ContentChild::RecvAppInfo( 2662 const nsCString& version, const nsCString& buildID, const nsCString& name, 2663 const nsCString& UAName, const nsCString& ID, const nsCString& vendor, 2664 const nsCString& sourceURL, const nsCString& updateURL) { 2665 mAppInfo.version.Assign(version); 2666 mAppInfo.buildID.Assign(buildID); 2667 mAppInfo.name.Assign(name); 2668 mAppInfo.UAName.Assign(UAName); 2669 mAppInfo.ID.Assign(ID); 2670 mAppInfo.vendor.Assign(vendor); 2671 mAppInfo.sourceURL.Assign(sourceURL); 2672 mAppInfo.updateURL.Assign(updateURL); 2673 2674 return IPC_OK(); 2675 } 2676 2677 mozilla::ipc::IPCResult ContentChild::RecvRemoteType( 2678 const nsCString& aRemoteType, const nsCString& aProfile) { 2679 if (aRemoteType == mRemoteType) { 2680 // Allocation of preallocated processes that are still launching can 2681 // cause this 2682 return IPC_OK(); 2683 } 2684 2685 if (!mRemoteType.IsVoid()) { 2686 // Preallocated processes are type PREALLOC_REMOTE_TYPE; they may not 2687 // become a File: process, or Privileged About Content Process 2688 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug, 2689 ("Changing remoteType of process %d from %s to %s", getpid(), 2690 mRemoteType.get(), aRemoteType.get())); 2691 // prealloc->anything (but file) or web->web allowed, and no-change 2692 MOZ_RELEASE_ASSERT(mRemoteType == PREALLOC_REMOTE_TYPE && 2693 aRemoteType != FILE_REMOTE_TYPE && 2694 aRemoteType != PRIVILEGEDABOUT_REMOTE_TYPE); 2695 } else { 2696 // Initial setting of remote type. Either to 'prealloc' or the actual 2697 // final type (if we didn't use a preallocated process) 2698 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug, 2699 ("Setting remoteType of process %d to %s", getpid(), 2700 aRemoteType.get())); 2701 2702 if (aRemoteType == PREALLOC_REMOTE_TYPE) { 2703 PreallocInit(); 2704 } 2705 } 2706 2707 auto remoteTypePrefix = RemoteTypePrefix(aRemoteType); 2708 2709 // Must do before SetProcessName 2710 mRemoteType.Assign(aRemoteType); 2711 2712 // Update the process name so about:memory's process names are more obvious. 2713 if (aRemoteType == FILE_REMOTE_TYPE) { 2714 SetProcessName("file:// Content"_ns, nullptr, &aProfile); 2715 } else if (aRemoteType == EXTENSION_REMOTE_TYPE) { 2716 SetProcessName("WebExtensions"_ns, nullptr, &aProfile); 2717 } else if (aRemoteType == PRIVILEGEDABOUT_REMOTE_TYPE) { 2718 SetProcessName("Privileged Content"_ns, nullptr, &aProfile); 2719 } else if (aRemoteType == PRIVILEGEDMOZILLA_REMOTE_TYPE) { 2720 SetProcessName("Privileged Mozilla"_ns, nullptr, &aProfile); 2721 } else if (aRemoteType == INFERENCE_REMOTE_TYPE) { 2722 SetProcessName("Inference"_ns, nullptr, &aProfile); 2723 } else if (remoteTypePrefix == WITH_COOP_COEP_REMOTE_TYPE) { 2724 // The profiler can sanitize out the eTLD+1 2725 nsDependentCSubstring etld = 2726 Substring(aRemoteType, WITH_COOP_COEP_REMOTE_TYPE.Length() + 1); 2727 #ifdef NIGHTLY_BUILD 2728 SetProcessName("WebCOOP+COEP Content"_ns, &etld, &aProfile); 2729 #else 2730 SetProcessName("Isolated Web Content"_ns, &etld, 2731 &aProfile); // to avoid confusing people 2732 #endif 2733 } else if (remoteTypePrefix == FISSION_WEB_REMOTE_TYPE) { 2734 // The profiler can sanitize out the eTLD+1 2735 nsDependentCSubstring etld = 2736 Substring(aRemoteType, FISSION_WEB_REMOTE_TYPE.Length() + 1); 2737 SetProcessName("Isolated Web Content"_ns, &etld, &aProfile); 2738 } else if (remoteTypePrefix == SERVICEWORKER_REMOTE_TYPE) { 2739 // The profiler can sanitize out the eTLD+1 2740 nsDependentCSubstring etld = 2741 Substring(aRemoteType, SERVICEWORKER_REMOTE_TYPE.Length() + 1); 2742 SetProcessName("Isolated Service Worker"_ns, &etld, &aProfile); 2743 } else { 2744 // else "prealloc" or "web" type -> "Web Content" 2745 SetProcessName("Web Content"_ns, nullptr, &aProfile); 2746 } 2747 2748 // Turn off Spectre mitigations in isolated web content processes. 2749 if (StaticPrefs::javascript_options_spectre_disable_for_isolated_content() && 2750 StaticPrefs::browser_opaqueResponseBlocking() && 2751 (remoteTypePrefix == FISSION_WEB_REMOTE_TYPE || 2752 remoteTypePrefix == SERVICEWORKER_REMOTE_TYPE || 2753 remoteTypePrefix == WITH_COOP_COEP_REMOTE_TYPE || 2754 aRemoteType == PRIVILEGEDABOUT_REMOTE_TYPE || 2755 aRemoteType == PRIVILEGEDMOZILLA_REMOTE_TYPE)) { 2756 JS::DisableSpectreMitigationsAfterInit(); 2757 } 2758 2759 // Use the prefix to avoid URIs from Fission isolated processes. 2760 CrashReporter::RecordAnnotationNSCString( 2761 CrashReporter::Annotation::RemoteType, remoteTypePrefix); 2762 2763 return IPC_OK(); 2764 } 2765 2766 // A method to initialize anything we need during the preallocation phase 2767 void ContentChild::PreallocInit() { 2768 EnsureNSSInitializedChromeOrContent(); 2769 2770 // SetAcceptLanguages() needs to read localized strings (file access), 2771 // which is slow, so do this in prealloc 2772 nsHttpHandler::PresetAcceptLanguages(); 2773 } 2774 2775 // Call RemoteTypePrefix() on the result to remove URIs if you want to use this 2776 // for telemetry. 2777 const nsACString& ContentChild::GetRemoteType() const { return mRemoteType; } 2778 2779 mozilla::ipc::IPCResult ContentChild::RecvInitRemoteWorkerService( 2780 Endpoint<PRemoteWorkerServiceChild>&& aEndpoint, 2781 Endpoint<PRemoteWorkerDebuggerManagerChild>&& aDebuggerChiledEp) { 2782 RemoteWorkerService::InitializeChild(std::move(aEndpoint), 2783 std::move(aDebuggerChiledEp)); 2784 return IPC_OK(); 2785 } 2786 2787 mozilla::ipc::IPCResult ContentChild::RecvInitBlobURLs( 2788 nsTArray<BlobURLRegistrationData>&& aRegistrations) { 2789 for (uint32_t i = 0; i < aRegistrations.Length(); ++i) { 2790 BlobURLRegistrationData& registration = aRegistrations[i]; 2791 RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(registration.blob()); 2792 MOZ_ASSERT(blobImpl); 2793 2794 BlobURLProtocolHandler::AddDataEntry(registration.url(), 2795 registration.principal(), 2796 registration.partitionKey(), blobImpl); 2797 // If we have received an already-revoked blobURL, we have to keep it alive 2798 // for a while (see BlobURLProtocolHandler) in order to support pending 2799 // operations such as navigation, download and so on. 2800 if (registration.revoked()) { 2801 BlobURLProtocolHandler::RemoveDataEntries(nsTArray{registration.url()}, 2802 false); 2803 } 2804 } 2805 2806 return IPC_OK(); 2807 } 2808 2809 mozilla::ipc::IPCResult ContentChild::RecvInitJSActorInfos( 2810 nsTArray<JSProcessActorInfo>&& aContentInfos, 2811 nsTArray<JSWindowActorInfo>&& aWindowInfos) { 2812 RefPtr<JSActorService> actSvc = JSActorService::GetSingleton(); 2813 actSvc->LoadJSActorInfos(aContentInfos, aWindowInfos); 2814 return IPC_OK(); 2815 } 2816 2817 mozilla::ipc::IPCResult ContentChild::RecvUnregisterJSWindowActor( 2818 const nsCString& aName) { 2819 RefPtr<JSActorService> actSvc = JSActorService::GetSingleton(); 2820 actSvc->UnregisterWindowActor(aName); 2821 return IPC_OK(); 2822 } 2823 2824 mozilla::ipc::IPCResult ContentChild::RecvUnregisterJSProcessActor( 2825 const nsCString& aName) { 2826 RefPtr<JSActorService> actSvc = JSActorService::GetSingleton(); 2827 actSvc->UnregisterProcessActor(aName); 2828 return IPC_OK(); 2829 } 2830 2831 mozilla::ipc::IPCResult ContentChild::RecvLastPrivateDocShellDestroyed() { 2832 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); 2833 obs->NotifyObservers(nullptr, "last-pb-context-exited", nullptr); 2834 return IPC_OK(); 2835 } 2836 2837 mozilla::ipc::IPCResult ContentChild::RecvNotifyProcessPriorityChanged( 2838 const hal::ProcessPriority& aPriority) { 2839 nsCOMPtr<nsIObserverService> os = services::GetObserverService(); 2840 NS_ENSURE_TRUE(os, IPC_OK()); 2841 2842 RefPtr<nsHashPropertyBag> props = new nsHashPropertyBag(); 2843 props->SetPropertyAsInt32(u"priority"_ns, static_cast<int32_t>(aPriority)); 2844 2845 PROFILER_MARKER("Process Priority", OTHER, 2846 mozilla::MarkerThreadId::MainThread(), ProcessPriorityChange, 2847 ProfilerString8View::WrapNullTerminatedString( 2848 ProcessPriorityToString(mProcessPriority)), 2849 ProfilerString8View::WrapNullTerminatedString( 2850 ProcessPriorityToString(aPriority))); 2851 2852 // Record FOG data before the priority change. 2853 // Ignore the change if it's the first time we set the process priority. 2854 if (mProcessPriority != hal::PROCESS_PRIORITY_UNKNOWN) { 2855 glean::RecordPowerMetrics(); 2856 } 2857 2858 ConfigureThreadPerformanceHints(aPriority); 2859 2860 mProcessPriority = aPriority; 2861 2862 os->NotifyObservers(static_cast<nsIPropertyBag2*>(props), 2863 "ipc:process-priority-changed", nullptr); 2864 if (StaticPrefs:: 2865 dom_memory_foreground_content_processes_have_larger_page_cache()) { 2866 #ifdef MOZ_MEMORY 2867 if (mProcessPriority >= hal::PROCESS_PRIORITY_FOREGROUND) { 2868 // Note: keep this in sync with the JS shell (js/src/shell/js.cpp). 2869 moz_set_max_dirty_page_modifier(4); 2870 } 2871 #endif 2872 if (mProcessPriority == hal::PROCESS_PRIORITY_BACKGROUND) { 2873 #ifdef MOZ_MEMORY 2874 moz_set_max_dirty_page_modifier(-2); 2875 2876 if (StaticPrefs::dom_memory_memory_pressure_on_background() == 1) { 2877 jemalloc_free_dirty_pages(); 2878 } 2879 #endif 2880 if (StaticPrefs::dom_memory_memory_pressure_on_background() == 2) { 2881 nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService(); 2882 obsServ->NotifyObservers(nullptr, "memory-pressure", u"heap-minimize"); 2883 } else if (StaticPrefs::dom_memory_memory_pressure_on_background() == 3) { 2884 nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService(); 2885 obsServ->NotifyObservers(nullptr, "memory-pressure", u"low-memory"); 2886 } 2887 #ifdef MOZ_MEMORY 2888 } else { 2889 moz_set_max_dirty_page_modifier(0); 2890 #endif 2891 } 2892 } 2893 2894 return IPC_OK(); 2895 } 2896 2897 mozilla::ipc::IPCResult ContentChild::RecvMinimizeMemoryUsage() { 2898 nsCOMPtr<nsIMemoryReporterManager> mgr = 2899 do_GetService("@mozilla.org/memory-reporter-manager;1"); 2900 NS_ENSURE_TRUE(mgr, IPC_OK()); 2901 2902 (void)mgr->MinimizeMemoryUsage(/* callback = */ nullptr); 2903 return IPC_OK(); 2904 } 2905 2906 void ContentChild::AddIdleObserver(nsIObserver* aObserver, 2907 uint32_t aIdleTimeInS) { 2908 MOZ_ASSERT(aObserver, "null idle observer"); 2909 // Make sure aObserver isn't released while we wait for the parent 2910 aObserver->AddRef(); 2911 SendAddIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS); 2912 mIdleObservers.Insert(aObserver); 2913 } 2914 2915 void ContentChild::RemoveIdleObserver(nsIObserver* aObserver, 2916 uint32_t aIdleTimeInS) { 2917 MOZ_ASSERT(aObserver, "null idle observer"); 2918 SendRemoveIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS); 2919 aObserver->Release(); 2920 mIdleObservers.Remove(aObserver); 2921 } 2922 2923 mozilla::ipc::IPCResult ContentChild::RecvNotifyIdleObserver( 2924 const uint64_t& aObserver, const nsCString& aTopic, 2925 const nsString& aTimeStr) { 2926 nsIObserver* observer = reinterpret_cast<nsIObserver*>(aObserver); 2927 if (mIdleObservers.Contains(observer)) { 2928 observer->Observe(nullptr, aTopic.get(), aTimeStr.get()); 2929 } else { 2930 NS_WARNING("Received notification for an idle observer that was removed."); 2931 } 2932 return IPC_OK(); 2933 } 2934 2935 mozilla::ipc::IPCResult ContentChild::RecvLoadAndRegisterSheet( 2936 nsIURI* aURI, const uint32_t& aType) { 2937 if (!aURI) { 2938 return IPC_OK(); 2939 } 2940 2941 nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance(); 2942 if (sheetService) { 2943 sheetService->LoadAndRegisterSheet(aURI, aType); 2944 } 2945 2946 return IPC_OK(); 2947 } 2948 2949 mozilla::ipc::IPCResult ContentChild::RecvUnregisterSheet( 2950 nsIURI* aURI, const uint32_t& aType) { 2951 if (!aURI) { 2952 return IPC_OK(); 2953 } 2954 2955 nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance(); 2956 if (sheetService) { 2957 sheetService->UnregisterSheet(aURI, aType); 2958 } 2959 2960 return IPC_OK(); 2961 } 2962 2963 mozilla::ipc::IPCResult ContentChild::RecvDomainSetChanged( 2964 const uint32_t& aSetType, const uint32_t& aChangeType, nsIURI* aDomain) { 2965 if (aChangeType == ACTIVATE_POLICY) { 2966 if (mPolicy) { 2967 return IPC_OK(); 2968 } 2969 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); 2970 MOZ_ASSERT(ssm); 2971 ssm->ActivateDomainPolicyInternal(getter_AddRefs(mPolicy)); 2972 if (!mPolicy) { 2973 return IPC_FAIL_NO_REASON(this); 2974 } 2975 return IPC_OK(); 2976 } 2977 if (!mPolicy) { 2978 MOZ_ASSERT_UNREACHABLE( 2979 "If the domain policy is not active yet," 2980 " the first message should be ACTIVATE_POLICY"); 2981 return IPC_FAIL_NO_REASON(this); 2982 } 2983 2984 NS_ENSURE_TRUE(mPolicy, IPC_FAIL_NO_REASON(this)); 2985 2986 if (aChangeType == DEACTIVATE_POLICY) { 2987 mPolicy->Deactivate(); 2988 mPolicy = nullptr; 2989 return IPC_OK(); 2990 } 2991 2992 nsCOMPtr<nsIDomainSet> set; 2993 switch (aSetType) { 2994 case BLOCKLIST: 2995 mPolicy->GetBlocklist(getter_AddRefs(set)); 2996 break; 2997 case SUPER_BLOCKLIST: 2998 mPolicy->GetSuperBlocklist(getter_AddRefs(set)); 2999 break; 3000 case ALLOWLIST: 3001 mPolicy->GetAllowlist(getter_AddRefs(set)); 3002 break; 3003 case SUPER_ALLOWLIST: 3004 mPolicy->GetSuperAllowlist(getter_AddRefs(set)); 3005 break; 3006 default: 3007 MOZ_ASSERT_UNREACHABLE("Unexpected setType"); 3008 return IPC_FAIL_NO_REASON(this); 3009 } 3010 3011 MOZ_ASSERT(set); 3012 3013 switch (aChangeType) { 3014 case ADD_DOMAIN: 3015 NS_ENSURE_TRUE(aDomain, IPC_FAIL_NO_REASON(this)); 3016 set->Add(aDomain); 3017 break; 3018 case REMOVE_DOMAIN: 3019 NS_ENSURE_TRUE(aDomain, IPC_FAIL_NO_REASON(this)); 3020 set->Remove(aDomain); 3021 break; 3022 case CLEAR_DOMAINS: 3023 set->Clear(); 3024 break; 3025 default: 3026 MOZ_ASSERT_UNREACHABLE("Unexpected changeType"); 3027 return IPC_FAIL_NO_REASON(this); 3028 } 3029 3030 return IPC_OK(); 3031 } 3032 3033 void ContentChild::StartForceKillTimer() { 3034 if (mForceKillTimer) { 3035 return; 3036 } 3037 3038 int32_t timeoutSecs = StaticPrefs::dom_ipc_tabs_shutdownTimeoutSecs(); 3039 if (timeoutSecs > 0) { 3040 NS_NewTimerWithFuncCallback(getter_AddRefs(mForceKillTimer), 3041 ContentChild::ForceKillTimerCallback, this, 3042 timeoutSecs * 1000, nsITimer::TYPE_ONE_SHOT, 3043 "dom::ContentChild::StartForceKillTimer"_ns); 3044 MOZ_ASSERT(mForceKillTimer); 3045 } 3046 } 3047 3048 /* static */ 3049 void ContentChild::ForceKillTimerCallback(nsITimer* aTimer, void* aClosure) { 3050 ProcessChild::QuickExit(); 3051 } 3052 3053 mozilla::ipc::IPCResult ContentChild::RecvShutdown() { 3054 ProcessChild::AppendToIPCShutdownStateAnnotation("RecvShutdown entry"_ns); 3055 3056 // Signal the ongoing shutdown to AppShutdown, this 3057 // will make abort nested SpinEventLoopUntilOrQuit loops 3058 AppShutdown::AdvanceShutdownPhaseWithoutNotify( 3059 ShutdownPhase::AppShutdownConfirmed); 3060 3061 nsCOMPtr<nsIObserverService> os = services::GetObserverService(); 3062 if (os) { 3063 ProcessChild::AppendToIPCShutdownStateAnnotation( 3064 "content-child-will-shutdown started"_ns); 3065 3066 os->NotifyObservers(ToSupports(this), "content-child-will-shutdown", 3067 nullptr); 3068 } 3069 3070 ShutdownInternal(); 3071 return IPC_OK(); 3072 } 3073 3074 void ContentChild::ShutdownInternal() { 3075 ProcessChild::AppendToIPCShutdownStateAnnotation("ShutdownInternal entry"_ns); 3076 3077 // If we receive the shutdown message from within a nested event loop, we want 3078 // to wait for that event loop to finish. Otherwise we could prematurely 3079 // terminate an "unload" or "pagehide" event handler (which might be doing a 3080 // sync XHR, for example). 3081 3082 MOZ_ASSERT(NS_IsMainThread()); 3083 RefPtr<nsThread> mainThread = nsThreadManager::get().GetCurrentThread(); 3084 // Note that we only have to check the recursion count for the current 3085 // cooperative thread. Since the Shutdown message is not labeled with a 3086 // SchedulerGroup, there can be no other cooperative threads doing work while 3087 // we're running. 3088 if (mainThread && mainThread->RecursionDepth() > 1) { 3089 // We're in a nested event loop. Let's delay for an arbitrary period of 3090 // time (100ms) in the hopes that the event loop will have finished by 3091 // then. 3092 GetCurrentSerialEventTarget()->DelayedDispatch( 3093 NewRunnableMethod("dom::ContentChild::RecvShutdown", this, 3094 &ContentChild::ShutdownInternal), 3095 100); 3096 return; 3097 } 3098 3099 mShuttingDown = true; 3100 3101 #ifdef NIGHTLY_BUILD 3102 BackgroundHangMonitor::UnregisterAnnotator( 3103 PendingInputEventHangAnnotator::sSingleton); 3104 #endif 3105 3106 if (mPolicy) { 3107 mPolicy->Deactivate(); 3108 mPolicy = nullptr; 3109 } 3110 3111 nsCOMPtr<nsIObserverService> os = services::GetObserverService(); 3112 if (os) { 3113 ProcessChild::AppendToIPCShutdownStateAnnotation( 3114 "content-child-shutdown started"_ns); 3115 os->NotifyObservers(ToSupports(this), "content-child-shutdown", nullptr); 3116 } 3117 3118 GetIPCChannel()->SetAbortOnError(false); 3119 3120 if (mProfilerController) { 3121 const bool isProfiling = profiler_is_active(); 3122 CrashReporter::RecordAnnotationCString( 3123 CrashReporter::Annotation::ProfilerChildShutdownPhase, 3124 isProfiling ? "Profiling - GrabShutdownProfileAndShutdown" 3125 : "Not profiling - GrabShutdownProfileAndShutdown"); 3126 ProfileAndAdditionalInformation shutdownProfileAndAdditionalInformation = 3127 mProfilerController->GrabShutdownProfileAndShutdown(); 3128 CrashReporter::RecordAnnotationCString( 3129 CrashReporter::Annotation::ProfilerChildShutdownPhase, 3130 isProfiling ? "Profiling - Destroying ChildProfilerController" 3131 : "Not profiling - Destroying ChildProfilerController"); 3132 mProfilerController = nullptr; 3133 CrashReporter::RecordAnnotationCString( 3134 CrashReporter::Annotation::ProfilerChildShutdownPhase, 3135 isProfiling ? "Profiling - SendShutdownProfile (sending)" 3136 : "Not profiling - SendShutdownProfile (sending)"); 3137 if (const size_t len = shutdownProfileAndAdditionalInformation.SizeOf(); 3138 len >= size_t(IPC::Channel::kMaximumMessageSize)) { 3139 shutdownProfileAndAdditionalInformation.mProfile = nsPrintfCString( 3140 "*Profile from pid %u bigger (%zu) than IPC max (%zu)", 3141 unsigned(profiler_current_process_id().ToNumber()), len, 3142 size_t(IPC::Channel::kMaximumMessageSize)); 3143 } 3144 // Send the shutdown profile to the parent process through our own 3145 // message channel, which we know will survive for long enough. 3146 bool sent = 3147 SendShutdownProfile(shutdownProfileAndAdditionalInformation.mProfile); 3148 CrashReporter::RecordAnnotationCString( 3149 CrashReporter::Annotation::ProfilerChildShutdownPhase, 3150 sent ? (isProfiling ? "Profiling - SendShutdownProfile (sent)" 3151 : "Not profiling - SendShutdownProfile (sent)") 3152 : (isProfiling ? "Profiling - SendShutdownProfile (failed)" 3153 : "Not profiling - SendShutdownProfile (failed)")); 3154 } 3155 3156 if (PerfStats::GetCollectionMask() != 0) { 3157 SendShutdownPerfStats(PerfStats::CollectLocalPerfStatsJSON()); 3158 } 3159 3160 // Start a timer that will ensure we quickly exit after a reasonable period 3161 // of time. Prevents shutdown hangs after our connection to the parent 3162 // closes or when the parent is too busy to ever kill us. 3163 ProcessChild::AppendToIPCShutdownStateAnnotation("StartForceKillTimer"_ns); 3164 StartForceKillTimer(); 3165 3166 ProcessChild::AppendToIPCShutdownStateAnnotation( 3167 "SendFinishShutdown (sending)"_ns); 3168 3169 // Notify the parent that we are done with shutdown. This is sent with high 3170 // priority and will just flag we are done. 3171 (void)SendNotifyShutdownSuccess(); 3172 3173 // Now tell the parent to actually destroy our channel which will make end 3174 // our process. This is expected to be the last event the parent will 3175 // ever process for this ContentChild. 3176 bool sent = SendFinishShutdown(); 3177 3178 ProcessChild::AppendToIPCShutdownStateAnnotation( 3179 sent ? "SendFinishShutdown (sent)"_ns : "SendFinishShutdown (failed)"_ns); 3180 } 3181 3182 mozilla::ipc::IPCResult ContentChild::RecvUpdateWindow( 3183 const uintptr_t& aChildId) { 3184 MOZ_ASSERT( 3185 false, 3186 "ContentChild::RecvUpdateWindow calls unexpected on this platform."); 3187 return IPC_FAIL_NO_REASON(this); 3188 } 3189 3190 PContentPermissionRequestChild* 3191 ContentChild::AllocPContentPermissionRequestChild( 3192 Span<const PermissionRequest> aRequests, nsIPrincipal* aPrincipal, 3193 nsIPrincipal* aTopLevelPrincipal, const bool& aIsHandlingUserInput, 3194 const bool& aMaybeUnsafePermissionDelegate, const TabId& aTabId) { 3195 MOZ_CRASH("unused"); 3196 return nullptr; 3197 } 3198 3199 bool ContentChild::DeallocPContentPermissionRequestChild( 3200 PContentPermissionRequestChild* actor) { 3201 nsContentPermissionUtils::NotifyRemoveContentPermissionRequestChild(actor); 3202 auto child = static_cast<RemotePermissionRequest*>(actor); 3203 child->IPDLRelease(); 3204 return true; 3205 } 3206 3207 already_AddRefed<PWebBrowserPersistDocumentChild> 3208 ContentChild::AllocPWebBrowserPersistDocumentChild( 3209 PBrowserChild* aBrowser, const MaybeDiscarded<BrowsingContext>& aContext) { 3210 return MakeAndAddRef<WebBrowserPersistDocumentChild>(); 3211 } 3212 3213 mozilla::ipc::IPCResult ContentChild::RecvPWebBrowserPersistDocumentConstructor( 3214 PWebBrowserPersistDocumentChild* aActor, PBrowserChild* aBrowser, 3215 const MaybeDiscarded<BrowsingContext>& aContext) { 3216 if (NS_WARN_IF(!aBrowser)) { 3217 return IPC_FAIL_NO_REASON(this); 3218 } 3219 3220 if (aContext.IsNullOrDiscarded()) { 3221 aActor->SendInitFailure(NS_ERROR_NO_CONTENT); 3222 return IPC_OK(); 3223 } 3224 3225 nsCOMPtr<Document> foundDoc = aContext.get()->GetDocument(); 3226 3227 if (!foundDoc) { 3228 aActor->SendInitFailure(NS_ERROR_NO_CONTENT); 3229 } else { 3230 static_cast<WebBrowserPersistDocumentChild*>(aActor)->Start(foundDoc); 3231 } 3232 return IPC_OK(); 3233 } 3234 3235 mozilla::ipc::IPCResult ContentChild::RecvPush(const nsCString& aScope, 3236 nsIPrincipal* aPrincipal, 3237 const nsString& aMessageId) { 3238 PushMessageDispatcher dispatcher(aScope, aPrincipal, aMessageId, Nothing()); 3239 (void)NS_WARN_IF(NS_FAILED(dispatcher.NotifyObserversAndWorkers())); 3240 return IPC_OK(); 3241 } 3242 3243 mozilla::ipc::IPCResult ContentChild::RecvPushWithData( 3244 const nsCString& aScope, nsIPrincipal* aPrincipal, 3245 const nsString& aMessageId, nsTArray<uint8_t>&& aData) { 3246 PushMessageDispatcher dispatcher(aScope, aPrincipal, aMessageId, 3247 Some(std::move(aData))); 3248 (void)NS_WARN_IF(NS_FAILED(dispatcher.NotifyObserversAndWorkers())); 3249 return IPC_OK(); 3250 } 3251 3252 mozilla::ipc::IPCResult ContentChild::RecvPushError(const nsCString& aScope, 3253 nsIPrincipal* aPrincipal, 3254 const nsString& aMessage, 3255 const uint32_t& aFlags) { 3256 PushErrorDispatcher dispatcher(aScope, aPrincipal, aMessage, aFlags); 3257 (void)NS_WARN_IF(NS_FAILED(dispatcher.NotifyObserversAndWorkers())); 3258 return IPC_OK(); 3259 } 3260 3261 mozilla::ipc::IPCResult 3262 ContentChild::RecvNotifyPushSubscriptionModifiedObservers( 3263 const nsCString& aScope, nsIPrincipal* aPrincipal) { 3264 PushSubscriptionModifiedDispatcher dispatcher(aScope, aPrincipal); 3265 (void)NS_WARN_IF(NS_FAILED(dispatcher.NotifyObservers())); 3266 return IPC_OK(); 3267 } 3268 3269 mozilla::ipc::IPCResult ContentChild::RecvBlobURLRegistration( 3270 const nsCString& aURI, const IPCBlob& aBlob, nsIPrincipal* aPrincipal, 3271 const nsCString& aPartitionKey) { 3272 RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(aBlob); 3273 MOZ_ASSERT(blobImpl); 3274 3275 BlobURLProtocolHandler::AddDataEntry(aURI, aPrincipal, aPartitionKey, 3276 blobImpl); 3277 return IPC_OK(); 3278 } 3279 3280 mozilla::ipc::IPCResult ContentChild::RecvBlobURLUnregistration( 3281 const nsTArray<nsCString>& aURIs) { 3282 BlobURLProtocolHandler::RemoveDataEntries( 3283 aURIs, 3284 /* aBroadcastToOtherProcesses = */ false); 3285 return IPC_OK(); 3286 } 3287 3288 void ContentChild::CreateGetFilesRequest(nsTArray<nsString>&& aDirectoryPaths, 3289 bool aRecursiveFlag, nsID& aUUID, 3290 GetFilesHelperChild* aChild) { 3291 MOZ_ASSERT(aChild); 3292 MOZ_ASSERT(!mGetFilesPendingRequests.Contains(aUUID)); 3293 3294 (void)SendGetFilesRequest(aUUID, aDirectoryPaths, aRecursiveFlag); 3295 mGetFilesPendingRequests.InsertOrUpdate(aUUID, RefPtr{aChild}); 3296 } 3297 3298 void ContentChild::DeleteGetFilesRequest(nsID& aUUID, 3299 GetFilesHelperChild* aChild) { 3300 MOZ_ASSERT(aChild); 3301 MOZ_ASSERT(mGetFilesPendingRequests.Contains(aUUID)); 3302 3303 (void)SendDeleteGetFilesRequest(aUUID); 3304 mGetFilesPendingRequests.Remove(aUUID); 3305 } 3306 3307 mozilla::ipc::IPCResult ContentChild::RecvGetFilesResponse( 3308 const nsID& aUUID, const GetFilesResponseResult& aResult) { 3309 RefPtr<GetFilesHelperChild> child; 3310 3311 // This object can already been deleted in case DeleteGetFilesRequest has 3312 // been called when the response was sending by the parent. 3313 if (!mGetFilesPendingRequests.Remove(aUUID, getter_AddRefs(child))) { 3314 return IPC_OK(); 3315 } 3316 3317 if (aResult.type() == GetFilesResponseResult::TGetFilesResponseFailure) { 3318 child->Finished(aResult.get_GetFilesResponseFailure().errorCode()); 3319 } else { 3320 MOZ_ASSERT(aResult.type() == 3321 GetFilesResponseResult::TGetFilesResponseSuccess); 3322 3323 const nsTArray<IPCBlob>& ipcBlobs = 3324 aResult.get_GetFilesResponseSuccess().blobs(); 3325 3326 bool succeeded = true; 3327 for (uint32_t i = 0; succeeded && i < ipcBlobs.Length(); ++i) { 3328 RefPtr<BlobImpl> impl = IPCBlobUtils::Deserialize(ipcBlobs[i]); 3329 succeeded = child->AppendBlobImpl(impl); 3330 } 3331 3332 child->Finished(succeeded ? NS_OK : NS_ERROR_OUT_OF_MEMORY); 3333 } 3334 return IPC_OK(); 3335 } 3336 3337 /* static */ 3338 void ContentChild::FatalErrorIfNotUsingGPUProcess(const char* const aErrorMsg, 3339 GeckoChildID aChildID) { 3340 // If we're communicating with the same process or the UI process then we 3341 // want to crash normally. Otherwise we want to just warn as the other end 3342 // must be the GPU process and it crashing shouldn't be fatal for us. 3343 if (aChildID == XRE_GetChildID() || aChildID == 0) { 3344 mozilla::ipc::FatalError(aErrorMsg, false); 3345 } else { 3346 nsAutoCString formattedMessage("IPDL error: \""); 3347 formattedMessage.AppendASCII(aErrorMsg); 3348 formattedMessage.AppendLiteral(R"(".)"); 3349 NS_WARNING(formattedMessage.get()); 3350 } 3351 } 3352 3353 PURLClassifierChild* ContentChild::AllocPURLClassifierChild( 3354 nsIPrincipal* aPrincipal, bool* aSuccess) { 3355 *aSuccess = true; 3356 return new URLClassifierChild(); 3357 } 3358 3359 bool ContentChild::DeallocPURLClassifierChild(PURLClassifierChild* aActor) { 3360 MOZ_ASSERT(aActor); 3361 delete aActor; 3362 return true; 3363 } 3364 3365 PURLClassifierLocalChild* ContentChild::AllocPURLClassifierLocalChild( 3366 nsIURI* aUri, Span<const IPCURLClassifierFeature> aFeatures) { 3367 return new URLClassifierLocalChild(); 3368 } 3369 3370 bool ContentChild::DeallocPURLClassifierLocalChild( 3371 PURLClassifierLocalChild* aActor) { 3372 MOZ_ASSERT(aActor); 3373 delete aActor; 3374 return true; 3375 } 3376 3377 PURLClassifierLocalByNameChild* 3378 ContentChild::AllocPURLClassifierLocalByNameChild( 3379 nsIURI* aUri, Span<const nsCString> aFeatures, 3380 const nsIUrlClassifierFeature::listType& aListType) { 3381 return new URLClassifierLocalByNameChild(); 3382 } 3383 3384 bool ContentChild::DeallocPURLClassifierLocalByNameChild( 3385 PURLClassifierLocalByNameChild* aActor) { 3386 MOZ_ASSERT(aActor); 3387 delete aActor; 3388 return true; 3389 } 3390 3391 PSessionStorageObserverChild* 3392 ContentChild::AllocPSessionStorageObserverChild() { 3393 MOZ_CRASH( 3394 "PSessionStorageObserverChild actors should be manually constructed!"); 3395 } 3396 3397 bool ContentChild::DeallocPSessionStorageObserverChild( 3398 PSessionStorageObserverChild* aActor) { 3399 MOZ_ASSERT(aActor); 3400 3401 delete aActor; 3402 return true; 3403 } 3404 3405 mozilla::ipc::IPCResult ContentChild::RecvProvideAnonymousTemporaryFile( 3406 const uint64_t& aID, const FileDescOrError& aFDOrError) { 3407 mozilla::UniquePtr<AnonymousTemporaryFileCallback> callback; 3408 mPendingAnonymousTemporaryFiles.Remove(aID, &callback); 3409 MOZ_ASSERT(callback); 3410 3411 PRFileDesc* prfile = nullptr; 3412 if (aFDOrError.type() == FileDescOrError::Tnsresult) { 3413 DebugOnly<nsresult> rv = aFDOrError.get_nsresult(); 3414 MOZ_ASSERT(NS_FAILED(rv)); 3415 } else { 3416 auto rawFD = aFDOrError.get_FileDescriptor().ClonePlatformHandle(); 3417 prfile = PR_ImportFile(PROsfd(rawFD.release())); 3418 } 3419 (*callback)(prfile); 3420 return IPC_OK(); 3421 } 3422 3423 nsresult ContentChild::AsyncOpenAnonymousTemporaryFile( 3424 const AnonymousTemporaryFileCallback& aCallback) { 3425 MOZ_ASSERT(NS_IsMainThread()); 3426 3427 static uint64_t id = 0; 3428 auto newID = id++; 3429 if (!SendRequestAnonymousTemporaryFile(newID)) { 3430 return NS_ERROR_FAILURE; 3431 } 3432 3433 // Remember the association with the callback. 3434 MOZ_ASSERT(!mPendingAnonymousTemporaryFiles.Get(newID)); 3435 mPendingAnonymousTemporaryFiles.GetOrInsertNew(newID, aCallback); 3436 return NS_OK; 3437 } 3438 3439 mozilla::ipc::IPCResult ContentChild::RecvSetPermissionsWithKey( 3440 const nsCString& aPermissionKey, nsTArray<IPC::Permission>&& aPerms) { 3441 RefPtr<PermissionManager> permManager = PermissionManager::GetInstance(); 3442 if (permManager) { 3443 permManager->SetPermissionsWithKey(aPermissionKey, aPerms); 3444 } 3445 3446 return IPC_OK(); 3447 } 3448 3449 mozilla::ipc::IPCResult ContentChild::RecvRefreshScreens( 3450 nsTArray<ScreenDetails>&& aScreens) { 3451 ScreenManager& screenManager = ScreenManager::GetSingleton(); 3452 screenManager.Refresh(std::move(aScreens)); 3453 return IPC_OK(); 3454 } 3455 3456 mozilla::ipc::IPCResult ContentChild::RecvShareCodeCoverageMutex( 3457 CrossProcessMutexHandle aHandle) { 3458 #ifdef MOZ_CODE_COVERAGE 3459 CodeCoverageHandler::Init(std::move(aHandle)); 3460 return IPC_OK(); 3461 #else 3462 MOZ_CRASH("Shouldn't receive this message in non-code coverage builds!"); 3463 #endif 3464 } 3465 3466 mozilla::ipc::IPCResult ContentChild::RecvFlushCodeCoverageCounters( 3467 FlushCodeCoverageCountersResolver&& aResolver) { 3468 #ifdef MOZ_CODE_COVERAGE 3469 CodeCoverageHandler::FlushCounters(); 3470 aResolver(/* unused */ true); 3471 return IPC_OK(); 3472 #else 3473 MOZ_CRASH("Shouldn't receive this message in non-code coverage builds!"); 3474 #endif 3475 } 3476 3477 mozilla::ipc::IPCResult ContentChild::RecvSetInputEventQueueEnabled() { 3478 nsThreadManager::get().EnableMainThreadEventPrioritization(); 3479 return IPC_OK(); 3480 } 3481 3482 mozilla::ipc::IPCResult ContentChild::RecvFlushInputEventQueue() { 3483 nsThreadManager::get().FlushInputEventPrioritization(); 3484 return IPC_OK(); 3485 } 3486 3487 mozilla::ipc::IPCResult ContentChild::RecvSuspendInputEventQueue() { 3488 nsThreadManager::get().SuspendInputEventPrioritization(); 3489 return IPC_OK(); 3490 } 3491 3492 mozilla::ipc::IPCResult ContentChild::RecvResumeInputEventQueue() { 3493 nsThreadManager::get().ResumeInputEventPrioritization(); 3494 return IPC_OK(); 3495 } 3496 3497 mozilla::ipc::IPCResult ContentChild::RecvAddDynamicScalars( 3498 nsTArray<DynamicScalarDefinition>&& aDefs) { 3499 TelemetryIPC::AddDynamicScalarDefinitions(aDefs); 3500 return IPC_OK(); 3501 } 3502 3503 mozilla::ipc::IPCResult ContentChild::RecvCrossProcessRedirect( 3504 RedirectToRealChannelArgs&& aArgs, 3505 nsTArray<Endpoint<extensions::PStreamFilterParent>>&& aEndpoints, 3506 CrossProcessRedirectResolver&& aResolve) { 3507 nsCOMPtr<nsILoadInfo> loadInfo; 3508 nsresult rv = mozilla::ipc::LoadInfoArgsToLoadInfo( 3509 aArgs.loadInfo(), NOT_REMOTE_TYPE, getter_AddRefs(loadInfo)); 3510 if (NS_FAILED(rv)) { 3511 MOZ_DIAGNOSTIC_CRASH("LoadInfoArgsToLoadInfo failed"); 3512 return IPC_OK(); 3513 } 3514 3515 nsCOMPtr<nsIChannel> newChannel; 3516 MOZ_ASSERT((aArgs.loadStateInternalLoadFlags() & 3517 nsDocShell::InternalLoad::INTERNAL_LOAD_FLAGS_IS_SRCDOC) || 3518 aArgs.srcdocData().IsVoid()); 3519 rv = nsDocShell::CreateRealChannelForDocument( 3520 getter_AddRefs(newChannel), aArgs.uri(), loadInfo, nullptr, 3521 aArgs.newLoadFlags(), aArgs.srcdocData(), aArgs.baseUri()); 3522 3523 if (RefPtr<HttpBaseChannel> httpChannel = do_QueryObject(newChannel)) { 3524 httpChannel->SetEarlyHints(std::move(aArgs.earlyHints())); 3525 httpChannel->SetEarlyHintLinkType(aArgs.earlyHintLinkType()); 3526 } 3527 3528 // This is used to report any errors back to the parent by calling 3529 // CrossProcessRedirectFinished. 3530 RefPtr<HttpChannelChild> httpChild = do_QueryObject(newChannel); 3531 auto resolve = [=](const nsresult& aRv) { 3532 nsresult rv = aRv; 3533 if (httpChild) { 3534 rv = httpChild->CrossProcessRedirectFinished(rv); 3535 } 3536 aResolve(rv); 3537 }; 3538 auto scopeExit = MakeScopeExit([&]() { resolve(rv); }); 3539 3540 if (NS_FAILED(rv)) { 3541 return IPC_OK(); 3542 } 3543 3544 if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel)) { 3545 rv = httpChannel->SetChannelId(aArgs.channelId()); 3546 } 3547 if (NS_FAILED(rv)) { 3548 return IPC_OK(); 3549 } 3550 3551 rv = newChannel->SetOriginalURI(aArgs.originalURI()); 3552 if (NS_FAILED(rv)) { 3553 return IPC_OK(); 3554 } 3555 3556 if (nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal = 3557 do_QueryInterface(newChannel)) { 3558 rv = httpChannelInternal->SetRedirectMode(aArgs.redirectMode()); 3559 } 3560 if (NS_FAILED(rv)) { 3561 return IPC_OK(); 3562 } 3563 3564 if (aArgs.init()) { 3565 HttpBaseChannel::ReplacementChannelConfig config(std::move(*aArgs.init())); 3566 HttpBaseChannel::ConfigureReplacementChannel( 3567 newChannel, config, 3568 HttpBaseChannel::ReplacementReason::DocumentChannel); 3569 } 3570 3571 if (aArgs.contentDisposition()) { 3572 newChannel->SetContentDisposition(*aArgs.contentDisposition()); 3573 } 3574 3575 if (aArgs.contentDispositionFilename()) { 3576 newChannel->SetContentDispositionFilename( 3577 *aArgs.contentDispositionFilename()); 3578 } 3579 3580 if (nsCOMPtr<nsIChildChannel> childChannel = do_QueryInterface(newChannel)) { 3581 // Connect to the parent if this is a remote channel. If it's entirely 3582 // handled locally, then we'll call AsyncOpen from the docshell when 3583 // we complete the setup 3584 rv = childChannel->ConnectParent( 3585 aArgs.registrarId()); // creates parent channel 3586 if (NS_FAILED(rv)) { 3587 return IPC_OK(); 3588 } 3589 } 3590 3591 // We need to copy the property bag before signaling that the channel 3592 // is ready so that the nsDocShell can retrieve the history data when called. 3593 if (nsCOMPtr<nsIWritablePropertyBag> bag = do_QueryInterface(newChannel)) { 3594 nsHashPropertyBag::CopyFrom(bag, aArgs.properties()); 3595 } 3596 3597 RefPtr<nsDocShellLoadState> loadState; 3598 rv = nsDocShellLoadState::CreateFromPendingChannel( 3599 newChannel, aArgs.loadIdentifier(), aArgs.registrarId(), 3600 getter_AddRefs(loadState)); 3601 if (NS_WARN_IF(NS_FAILED(rv))) { 3602 return IPC_OK(); 3603 } 3604 loadState->SetLoadFlags(aArgs.loadStateExternalLoadFlags()); 3605 loadState->SetInternalLoadFlags(aArgs.loadStateInternalLoadFlags()); 3606 if (IsValidLoadType(aArgs.loadStateLoadType())) { 3607 loadState->SetLoadType(aArgs.loadStateLoadType()); 3608 } 3609 3610 if (aArgs.loadingSessionHistoryInfo().isSome()) { 3611 loadState->SetLoadingSessionHistoryInfo( 3612 aArgs.loadingSessionHistoryInfo().ref()); 3613 } 3614 if (aArgs.originalUriString().isSome()) { 3615 loadState->SetOriginalURIString(aArgs.originalUriString().ref()); 3616 } 3617 3618 RefPtr<ChildProcessChannelListener> processListener = 3619 ChildProcessChannelListener::GetSingleton(); 3620 // The listener will call completeRedirectSetup or asyncOpen on the channel. 3621 processListener->OnChannelReady(loadState, aArgs.loadIdentifier(), 3622 std::move(aEndpoints), aArgs.timing(), 3623 std::move(resolve)); 3624 scopeExit.release(); 3625 3626 // scopeExit will call CrossProcessRedirectFinished(rv) here 3627 return IPC_OK(); 3628 } 3629 3630 mozilla::ipc::IPCResult ContentChild::RecvStartDelayedAutoplayMediaComponents( 3631 const MaybeDiscarded<BrowsingContext>& aContext) { 3632 if (NS_WARN_IF(aContext.IsNullOrDiscarded())) { 3633 return IPC_OK(); 3634 } 3635 3636 aContext.get()->StartDelayedAutoplayMediaComponents(); 3637 return IPC_OK(); 3638 } 3639 3640 mozilla::ipc::IPCResult ContentChild::RecvUpdateMediaControlAction( 3641 const MaybeDiscarded<BrowsingContext>& aContext, 3642 const MediaControlAction& aAction) { 3643 if (NS_WARN_IF(aContext.IsNullOrDiscarded())) { 3644 return IPC_OK(); 3645 } 3646 3647 ContentMediaControlKeyHandler::HandleMediaControlAction(aContext.get(), 3648 aAction); 3649 return IPC_OK(); 3650 } 3651 3652 mozilla::ipc::IPCResult ContentChild::RecvOnAllowAccessFor( 3653 const MaybeDiscarded<BrowsingContext>& aContext, 3654 const nsCString& aTrackingOrigin, uint32_t aCookieBehavior, 3655 const ContentBlockingNotifier::StorageAccessPermissionGrantedReason& 3656 aReason) { 3657 MOZ_ASSERT(!aContext.IsNull(), "Browsing context cannot be null"); 3658 3659 StorageAccessAPIHelper::OnAllowAccessFor( 3660 aContext.GetMaybeDiscarded(), aTrackingOrigin, aCookieBehavior, aReason); 3661 3662 return IPC_OK(); 3663 } 3664 3665 mozilla::ipc::IPCResult ContentChild::RecvOnContentBlockingDecision( 3666 const MaybeDiscarded<BrowsingContext>& aContext, 3667 const ContentBlockingNotifier::BlockingDecision& aDecision, 3668 uint32_t aRejectedReason) { 3669 MOZ_ASSERT(!aContext.IsNull(), "Browsing context cannot be null"); 3670 3671 nsCOMPtr<nsPIDOMWindowOuter> outer = aContext.get()->GetDOMWindow(); 3672 if (!outer) { 3673 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, 3674 ("ChildIPC: Trying to send a message to a context without a outer " 3675 "window")); 3676 return IPC_OK(); 3677 } 3678 3679 nsCOMPtr<nsPIDOMWindowInner> inner = outer->GetCurrentInnerWindow(); 3680 if (!inner) { 3681 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, 3682 ("ChildIPC: Trying to send a message to a context without a inner " 3683 "window")); 3684 return IPC_OK(); 3685 } 3686 3687 ContentBlockingNotifier::OnDecision(inner, aDecision, aRejectedReason); 3688 return IPC_OK(); 3689 } 3690 3691 #ifdef NIGHTLY_BUILD 3692 void ContentChild::OnChannelReceivedMessage(const Message& aMsg) { 3693 if (nsContentUtils::IsMessageInputEvent(aMsg)) { 3694 mPendingInputEvents++; 3695 } 3696 } 3697 3698 PContentChild::Result ContentChild::OnMessageReceived(const Message& aMsg) { 3699 if (nsContentUtils::IsMessageInputEvent(aMsg)) { 3700 DebugOnly<uint32_t> prevEvts = mPendingInputEvents--; 3701 MOZ_ASSERT(prevEvts > 0); 3702 } 3703 3704 return PContentChild::OnMessageReceived(aMsg); 3705 } 3706 3707 PContentChild::Result ContentChild::OnMessageReceived( 3708 const Message& aMsg, UniquePtr<Message>& aReply) { 3709 return PContentChild::OnMessageReceived(aMsg, aReply); 3710 } 3711 #endif 3712 3713 mozilla::ipc::IPCResult ContentChild::RecvCreateBrowsingContext( 3714 uint64_t aGroupId, BrowsingContext::IPCInitializer&& aInit) { 3715 // We can't already have a BrowsingContext with this ID. 3716 if (RefPtr<BrowsingContext> existing = BrowsingContext::Get(aInit.mId)) { 3717 return IPC_FAIL(this, "Browsing context already exists"); 3718 } 3719 3720 RefPtr<WindowContext> parent = WindowContext::GetById(aInit.mParentId); 3721 if (!parent && aInit.mParentId != 0) { 3722 // Handle this case by ignoring the request, as parent must be in the 3723 // process of being discarded. 3724 // In the future it would be nice to avoid sending this message to the child 3725 // at all. 3726 NS_WARNING("Attempt to attach BrowsingContext to discarded parent"); 3727 return IPC_OK(); 3728 } 3729 3730 RefPtr<BrowsingContextGroup> group = 3731 BrowsingContextGroup::GetOrCreate(aGroupId); 3732 return BrowsingContext::CreateFromIPC(std::move(aInit), group, nullptr); 3733 } 3734 3735 mozilla::ipc::IPCResult ContentChild::RecvDiscardBrowsingContext( 3736 const MaybeDiscarded<BrowsingContext>& aContext, bool aDoDiscard, 3737 DiscardBrowsingContextResolver&& aResolve) { 3738 if (BrowsingContext* context = aContext.GetMaybeDiscarded()) { 3739 if (aDoDiscard && !context->IsDiscarded()) { 3740 context->Detach(/* aFromIPC */ true); 3741 } 3742 context->AddDiscardListener(aResolve); 3743 return IPC_OK(); 3744 } 3745 3746 // Immediately resolve the promise, as we've received the message. This will 3747 // allow the parent process to discard references to this BC. 3748 aResolve(true); 3749 return IPC_OK(); 3750 } 3751 3752 mozilla::ipc::IPCResult ContentChild::RecvRegisterBrowsingContextGroup( 3753 uint64_t aGroupId, nsTArray<SyncedContextInitializer>&& aInits, 3754 nsTArray<OriginAgentClusterInitializer>&& aUseOriginAgentCluster) { 3755 RefPtr<BrowsingContextGroup> group = 3756 BrowsingContextGroup::GetOrCreate(aGroupId); 3757 3758 for (auto& entry : aUseOriginAgentCluster) { 3759 group->SetUseOriginAgentClusterFromIPC(entry.principal(), 3760 entry.useOriginAgentCluster()); 3761 } 3762 3763 // Each of the initializers in aInits is sorted in pre-order, so our parent 3764 // should always be available before the element itself. 3765 for (auto& initUnion : aInits) { 3766 switch (initUnion.type()) { 3767 case SyncedContextInitializer::TBrowsingContextInitializer: { 3768 auto& init = initUnion.get_BrowsingContextInitializer(); 3769 #ifdef DEBUG 3770 RefPtr<BrowsingContext> existing = BrowsingContext::Get(init.mId); 3771 MOZ_ASSERT(!existing, "BrowsingContext must not exist yet!"); 3772 3773 RefPtr<WindowContext> parent = init.GetParent(); 3774 MOZ_ASSERT_IF(parent, parent->Group() == group); 3775 #endif 3776 3777 BrowsingContext::CreateFromIPC(std::move(init), group, nullptr); 3778 break; 3779 } 3780 case SyncedContextInitializer::TWindowContextInitializer: { 3781 auto& init = initUnion.get_WindowContextInitializer(); 3782 #ifdef DEBUG 3783 RefPtr<WindowContext> existing = 3784 WindowContext::GetById(init.mInnerWindowId); 3785 MOZ_ASSERT(!existing, "WindowContext must not exist yet!"); 3786 RefPtr<BrowsingContext> parent = 3787 BrowsingContext::Get(init.mBrowsingContextId); 3788 MOZ_ASSERT(parent && parent->Group() == group); 3789 #endif 3790 3791 WindowContext::CreateFromIPC(std::move(init)); 3792 break; 3793 }; 3794 default: 3795 MOZ_ASSERT_UNREACHABLE(); 3796 } 3797 } 3798 3799 return IPC_OK(); 3800 } 3801 3802 mozilla::ipc::IPCResult ContentChild::RecvDestroyBrowsingContextGroup( 3803 uint64_t aGroupId) { 3804 if (RefPtr<BrowsingContextGroup> group = 3805 BrowsingContextGroup::GetExisting(aGroupId)) { 3806 group->ChildDestroy(); 3807 } 3808 return IPC_OK(); 3809 } 3810 3811 mozilla::ipc::IPCResult ContentChild::RecvSetUseOriginAgentCluster( 3812 uint64_t aGroupId, nsIPrincipal* aPrincipal, bool aUseOriginAgentCluster) { 3813 RefPtr<BrowsingContextGroup> group = 3814 BrowsingContextGroup::GetOrCreate(aGroupId); 3815 group->SetUseOriginAgentClusterFromIPC(aPrincipal, aUseOriginAgentCluster); 3816 return IPC_OK(); 3817 } 3818 3819 mozilla::ipc::IPCResult ContentChild::RecvWindowClose( 3820 const MaybeDiscarded<BrowsingContext>& aContext, bool aTrustedCaller) { 3821 if (aContext.IsNullOrDiscarded()) { 3822 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, 3823 ("ChildIPC: Trying to send a message to dead or detached context")); 3824 return IPC_OK(); 3825 } 3826 3827 nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow(); 3828 if (!window) { 3829 MOZ_LOG( 3830 BrowsingContext::GetLog(), LogLevel::Debug, 3831 ("ChildIPC: Trying to send a message to a context without a window")); 3832 return IPC_OK(); 3833 } 3834 3835 // Call `GetDocument()` to force the document and its inner window to be 3836 // created, as it would be forced to be created if this call was being 3837 // performed in-process. 3838 if (NS_WARN_IF(!aContext.get()->GetDocument())) { 3839 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, 3840 ("ChildIPC: Trying to send a message to a context but document " 3841 "creation failed")); 3842 return IPC_OK(); 3843 } 3844 3845 nsGlobalWindowOuter::Cast(window)->CloseOuter(aTrustedCaller); 3846 return IPC_OK(); 3847 } 3848 3849 mozilla::ipc::IPCResult ContentChild::RecvWindowFocus( 3850 const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType, 3851 uint64_t aActionId) { 3852 if (aContext.IsNullOrDiscarded()) { 3853 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, 3854 ("ChildIPC: Trying to send a message to dead or detached context")); 3855 return IPC_OK(); 3856 } 3857 3858 nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow(); 3859 if (!window) { 3860 MOZ_LOG( 3861 BrowsingContext::GetLog(), LogLevel::Debug, 3862 ("ChildIPC: Trying to send a message to a context without a window")); 3863 return IPC_OK(); 3864 } 3865 3866 // Call `GetDocument()` to force the document and its inner window to be 3867 // created, as it would be forced to be created if this call was being 3868 // performed in-process. 3869 if (NS_WARN_IF(!aContext.get()->GetDocument())) { 3870 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, 3871 ("ChildIPC: Trying to send a message to a context but document " 3872 "creation failed")); 3873 return IPC_OK(); 3874 } 3875 3876 nsGlobalWindowOuter::Cast(window)->FocusOuter( 3877 aCallerType, /* aFromOtherProcess */ true, aActionId); 3878 return IPC_OK(); 3879 } 3880 3881 mozilla::ipc::IPCResult ContentChild::RecvWindowBlur( 3882 const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType) { 3883 if (aContext.IsNullOrDiscarded()) { 3884 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, 3885 ("ChildIPC: Trying to send a message to dead or detached context")); 3886 return IPC_OK(); 3887 } 3888 3889 nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow(); 3890 if (!window) { 3891 MOZ_LOG( 3892 BrowsingContext::GetLog(), LogLevel::Debug, 3893 ("ChildIPC: Trying to send a message to a context without a window")); 3894 return IPC_OK(); 3895 } 3896 3897 // Call `GetDocument()` to force the document and its inner window to be 3898 // created, as it would be forced to be created if this call was being 3899 // performed in-process. 3900 if (NS_WARN_IF(!aContext.get()->GetDocument())) { 3901 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, 3902 ("ChildIPC: Trying to send a message to a context but document " 3903 "creation failed")); 3904 return IPC_OK(); 3905 } 3906 3907 nsGlobalWindowOuter::Cast(window)->BlurOuter(aCallerType); 3908 return IPC_OK(); 3909 } 3910 3911 mozilla::ipc::IPCResult ContentChild::RecvRaiseWindow( 3912 const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType, 3913 uint64_t aActionId) { 3914 if (aContext.IsNullOrDiscarded()) { 3915 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, 3916 ("ChildIPC: Trying to send a message to dead or detached context")); 3917 return IPC_OK(); 3918 } 3919 3920 nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow(); 3921 if (!window) { 3922 MOZ_LOG( 3923 BrowsingContext::GetLog(), LogLevel::Debug, 3924 ("ChildIPC: Trying to send a message to a context without a window")); 3925 return IPC_OK(); 3926 } 3927 3928 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) { 3929 fm->RaiseWindow(window, aCallerType, aActionId); 3930 } 3931 return IPC_OK(); 3932 } 3933 3934 mozilla::ipc::IPCResult ContentChild::RecvAdjustWindowFocus( 3935 const MaybeDiscarded<BrowsingContext>& aContext, bool aIsVisible, 3936 uint64_t aActionId, bool aShouldClearAncestorFocus, 3937 const MaybeDiscarded<BrowsingContext>& aAncestorBrowsingContextToFocus) { 3938 if (aContext.IsNullOrDiscarded()) { 3939 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, 3940 ("ChildIPC: Trying to send a message to dead or detached context")); 3941 return IPC_OK(); 3942 } 3943 3944 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) { 3945 RefPtr<BrowsingContext> bc = aContext.get(); 3946 RefPtr<BrowsingContext> ancestor = 3947 aAncestorBrowsingContextToFocus.IsNullOrDiscarded() 3948 ? nullptr 3949 : aAncestorBrowsingContextToFocus.get(); 3950 fm->AdjustInProcessWindowFocus(bc, false, aIsVisible, aActionId, 3951 aShouldClearAncestorFocus, ancestor); 3952 } 3953 return IPC_OK(); 3954 } 3955 3956 mozilla::ipc::IPCResult ContentChild::RecvClearFocus( 3957 const MaybeDiscarded<BrowsingContext>& aContext) { 3958 if (aContext.IsNullOrDiscarded()) { 3959 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, 3960 ("ChildIPC: Trying to send a message to dead or detached context")); 3961 return IPC_OK(); 3962 } 3963 3964 nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow(); 3965 if (!window) { 3966 MOZ_LOG( 3967 BrowsingContext::GetLog(), LogLevel::Debug, 3968 ("ChildIPC: Trying to send a message to a context without a window")); 3969 return IPC_OK(); 3970 } 3971 3972 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) { 3973 fm->ClearFocus(window); 3974 } 3975 return IPC_OK(); 3976 } 3977 3978 mozilla::ipc::IPCResult ContentChild::RecvSetFocusedBrowsingContext( 3979 const MaybeDiscarded<BrowsingContext>& aContext, uint64_t aActionId) { 3980 if (aContext.IsNullOrDiscarded()) { 3981 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, 3982 ("ChildIPC: Trying to send a message to dead or detached context")); 3983 return IPC_OK(); 3984 } 3985 3986 nsFocusManager* fm = nsFocusManager::GetFocusManager(); 3987 if (fm) { 3988 fm->SetFocusedBrowsingContextFromOtherProcess(aContext.get(), aActionId); 3989 } 3990 return IPC_OK(); 3991 } 3992 3993 mozilla::ipc::IPCResult ContentChild::RecvSetActiveBrowsingContext( 3994 const MaybeDiscarded<BrowsingContext>& aContext, uint64_t aActionId) { 3995 if (aContext.IsNullOrDiscarded()) { 3996 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, 3997 ("ChildIPC: Trying to send a message to dead or detached context")); 3998 return IPC_OK(); 3999 } 4000 4001 nsFocusManager* fm = nsFocusManager::GetFocusManager(); 4002 if (fm) { 4003 fm->SetActiveBrowsingContextFromOtherProcess(aContext.get(), aActionId); 4004 } 4005 return IPC_OK(); 4006 } 4007 4008 mozilla::ipc::IPCResult ContentChild::RecvAbortOrientationPendingPromises( 4009 const MaybeDiscarded<BrowsingContext>& aContext) { 4010 if (aContext.IsNullOrDiscarded()) { 4011 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, 4012 ("ChildIPC: Trying to send a message to dead or detached context")); 4013 return IPC_OK(); 4014 } 4015 4016 dom::ScreenOrientation::AbortInProcessOrientationPromises(aContext.get()); 4017 return IPC_OK(); 4018 } 4019 4020 mozilla::ipc::IPCResult ContentChild::RecvUnsetActiveBrowsingContext( 4021 const MaybeDiscarded<BrowsingContext>& aContext, uint64_t aActionId) { 4022 if (aContext.IsNullOrDiscarded()) { 4023 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, 4024 ("ChildIPC: Trying to send a message to dead or detached context")); 4025 return IPC_OK(); 4026 } 4027 4028 nsFocusManager* fm = nsFocusManager::GetFocusManager(); 4029 if (fm) { 4030 fm->UnsetActiveBrowsingContextFromOtherProcess(aContext.get(), aActionId); 4031 } 4032 return IPC_OK(); 4033 } 4034 4035 mozilla::ipc::IPCResult ContentChild::RecvSetFocusedElement( 4036 const MaybeDiscarded<BrowsingContext>& aContext, bool aNeedsFocus) { 4037 if (aContext.IsNullOrDiscarded()) { 4038 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, 4039 ("ChildIPC: Trying to send a message to dead or detached context")); 4040 return IPC_OK(); 4041 } 4042 4043 nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow(); 4044 if (!window) { 4045 MOZ_LOG( 4046 BrowsingContext::GetLog(), LogLevel::Debug, 4047 ("ChildIPC: Trying to send a message to a context without a window")); 4048 return IPC_OK(); 4049 } 4050 4051 window->SetFocusedElement(nullptr, 0, aNeedsFocus); 4052 return IPC_OK(); 4053 } 4054 4055 mozilla::ipc::IPCResult ContentChild::RecvFinalizeFocusOuter( 4056 const MaybeDiscarded<BrowsingContext>& aContext, bool aCanFocus, 4057 CallerType aCallerType) { 4058 if (aContext.IsNullOrDiscarded()) { 4059 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, 4060 ("ChildIPC: Trying to send a message to dead or detached context")); 4061 return IPC_OK(); 4062 } 4063 4064 if (Element* frame = aContext.get()->GetEmbedderElement()) { 4065 nsContentUtils::RequestFrameFocus(*frame, aCanFocus, aCallerType); 4066 } 4067 4068 return IPC_OK(); 4069 } 4070 4071 mozilla::ipc::IPCResult ContentChild::RecvBlurToChild( 4072 const MaybeDiscarded<BrowsingContext>& aFocusedBrowsingContext, 4073 const MaybeDiscarded<BrowsingContext>& aBrowsingContextToClear, 4074 const MaybeDiscarded<BrowsingContext>& aAncestorBrowsingContextToFocus, 4075 bool aIsLeavingDocument, bool aAdjustWidget, uint64_t aActionId) { 4076 if (aFocusedBrowsingContext.IsNullOrDiscarded()) { 4077 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, 4078 ("ChildIPC: Trying to send a message to dead or detached context")); 4079 return IPC_OK(); 4080 } 4081 4082 RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager(); 4083 if (MOZ_UNLIKELY(!fm)) { 4084 return IPC_OK(); 4085 } 4086 4087 RefPtr<BrowsingContext> toClear = aBrowsingContextToClear.IsDiscarded() 4088 ? nullptr 4089 : aBrowsingContextToClear.get(); 4090 RefPtr<BrowsingContext> toFocus = 4091 aAncestorBrowsingContextToFocus.IsDiscarded() 4092 ? nullptr 4093 : aAncestorBrowsingContextToFocus.get(); 4094 4095 RefPtr<BrowsingContext> focusedBrowsingContext = 4096 aFocusedBrowsingContext.get(); 4097 4098 fm->BlurFromOtherProcess(focusedBrowsingContext, toClear, toFocus, 4099 aIsLeavingDocument, aAdjustWidget, aActionId); 4100 return IPC_OK(); 4101 } 4102 4103 mozilla::ipc::IPCResult ContentChild::RecvSetupFocusedAndActive( 4104 const MaybeDiscarded<BrowsingContext>& aFocusedBrowsingContext, 4105 uint64_t aActionIdForFocused, 4106 const MaybeDiscarded<BrowsingContext>& aActiveBrowsingContext, 4107 uint64_t aActionIdForActive) { 4108 nsFocusManager* fm = nsFocusManager::GetFocusManager(); 4109 if (fm) { 4110 if (!aActiveBrowsingContext.IsNullOrDiscarded()) { 4111 fm->SetActiveBrowsingContextFromOtherProcess(aActiveBrowsingContext.get(), 4112 aActionIdForActive); 4113 } 4114 if (!aFocusedBrowsingContext.IsNullOrDiscarded()) { 4115 fm->SetFocusedBrowsingContextFromOtherProcess( 4116 aFocusedBrowsingContext.get(), aActionIdForFocused); 4117 } 4118 } 4119 return IPC_OK(); 4120 } 4121 4122 mozilla::ipc::IPCResult ContentChild::RecvReviseActiveBrowsingContext( 4123 uint64_t aOldActionId, 4124 const MaybeDiscarded<BrowsingContext>& aActiveBrowsingContext, 4125 uint64_t aNewActionId) { 4126 nsFocusManager* fm = nsFocusManager::GetFocusManager(); 4127 if (fm && !aActiveBrowsingContext.IsNullOrDiscarded()) { 4128 fm->ReviseActiveBrowsingContext(aOldActionId, aActiveBrowsingContext.get(), 4129 aNewActionId); 4130 } 4131 return IPC_OK(); 4132 } 4133 4134 mozilla::ipc::IPCResult ContentChild::RecvReviseFocusedBrowsingContext( 4135 uint64_t aOldActionId, 4136 const MaybeDiscarded<BrowsingContext>& aFocusedBrowsingContext, 4137 uint64_t aNewActionId) { 4138 nsFocusManager* fm = nsFocusManager::GetFocusManager(); 4139 if (fm && !aFocusedBrowsingContext.IsNullOrDiscarded()) { 4140 fm->ReviseFocusedBrowsingContext( 4141 aOldActionId, aFocusedBrowsingContext.get(), aNewActionId); 4142 } 4143 return IPC_OK(); 4144 } 4145 4146 mozilla::ipc::IPCResult ContentChild::RecvMaybeExitFullscreen( 4147 const MaybeDiscarded<BrowsingContext>& aContext) { 4148 if (aContext.IsNullOrDiscarded()) { 4149 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, 4150 ("ChildIPC: Trying to send a message to dead or detached context")); 4151 return IPC_OK(); 4152 } 4153 4154 nsIDocShell* shell = aContext.get()->GetDocShell(); 4155 if (!shell) { 4156 return IPC_OK(); 4157 } 4158 4159 Document* doc = shell->GetDocument(); 4160 if (doc && doc->GetFullscreenElement()) { 4161 Document::AsyncExitFullscreen(doc); 4162 } 4163 4164 return IPC_OK(); 4165 } 4166 4167 mozilla::ipc::IPCResult ContentChild::RecvWindowPostMessage( 4168 const MaybeDiscarded<BrowsingContext>& aContext, 4169 const ClonedOrErrorMessageData& aMessage, const PostMessageData& aData) { 4170 if (aContext.IsNullOrDiscarded()) { 4171 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, 4172 ("ChildIPC: Trying to send a message to dead or detached context")); 4173 return IPC_OK(); 4174 } 4175 4176 RefPtr<nsGlobalWindowOuter> window = 4177 nsGlobalWindowOuter::Cast(aContext.get()->GetDOMWindow()); 4178 if (!window) { 4179 MOZ_LOG( 4180 BrowsingContext::GetLog(), LogLevel::Debug, 4181 ("ChildIPC: Trying to send a message to a context without a window")); 4182 return IPC_OK(); 4183 } 4184 4185 nsCOMPtr<nsIPrincipal> providedPrincipal; 4186 if (!window->GetPrincipalForPostMessage( 4187 aData.targetOrigin(), aData.targetOriginURI(), 4188 aData.callerPrincipal(), *aData.subjectPrincipal(), 4189 getter_AddRefs(providedPrincipal))) { 4190 return IPC_OK(); 4191 } 4192 4193 // Call `GetDocument()` to force the document and its inner window to be 4194 // created, as it would be forced to be created if this call was being 4195 // performed in-process. 4196 if (NS_WARN_IF(!aContext.get()->GetDocument())) { 4197 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug, 4198 ("ChildIPC: Trying to send a message to a context but document " 4199 "creation failed")); 4200 return IPC_OK(); 4201 } 4202 4203 // It's OK if `sourceBc` has already been discarded, so long as we can 4204 // continue to wrap it. 4205 RefPtr<BrowsingContext> sourceBc = aData.source().GetMaybeDiscarded(); 4206 4207 // Create and asynchronously dispatch a runnable which will handle actual DOM 4208 // event creation and dispatch. 4209 RefPtr<PostMessageEvent> event = 4210 new PostMessageEvent(sourceBc, aData.origin(), window, providedPrincipal, 4211 aData.innerWindowId(), aData.callerURI(), 4212 aData.scriptLocation(), aData.isFromPrivateWindow()); 4213 event->UnpackFrom(aMessage); 4214 4215 event->DispatchToTargetThread(IgnoredErrorResult()); 4216 return IPC_OK(); 4217 } 4218 4219 mozilla::ipc::IPCResult ContentChild::RecvCommitBrowsingContextTransaction( 4220 const MaybeDiscarded<BrowsingContext>& aContext, 4221 BrowsingContext::BaseTransaction&& aTransaction, uint64_t aEpoch) { 4222 return aTransaction.CommitFromIPC(aContext, aEpoch, this); 4223 } 4224 4225 mozilla::ipc::IPCResult ContentChild::RecvCommitWindowContextTransaction( 4226 const MaybeDiscarded<WindowContext>& aContext, 4227 WindowContext::BaseTransaction&& aTransaction, uint64_t aEpoch) { 4228 return aTransaction.CommitFromIPC(aContext, aEpoch, this); 4229 } 4230 4231 mozilla::ipc::IPCResult ContentChild::RecvCreateWindowContext( 4232 WindowContext::IPCInitializer&& aInit) { 4233 RefPtr<BrowsingContext> bc = BrowsingContext::Get(aInit.mBrowsingContextId); 4234 if (!bc) { 4235 // Handle this case by ignoring the request, as bc must be in the process of 4236 // being discarded. 4237 // In the future it would be nice to avoid sending this message to the child 4238 // at all. 4239 NS_WARNING("Attempt to attach WindowContext to discarded parent"); 4240 return IPC_OK(); 4241 } 4242 4243 WindowContext::CreateFromIPC(std::move(aInit)); 4244 return IPC_OK(); 4245 } 4246 4247 mozilla::ipc::IPCResult ContentChild::RecvDiscardWindowContext( 4248 uint64_t aContextId, DiscardWindowContextResolver&& aResolve) { 4249 // Resolve immediately to acknowledge call 4250 aResolve(true); 4251 4252 RefPtr<WindowContext> window = WindowContext::GetById(aContextId); 4253 if (NS_WARN_IF(!window) || NS_WARN_IF(window->IsDiscarded())) { 4254 return IPC_OK(); 4255 } 4256 4257 window->Discard(); 4258 return IPC_OK(); 4259 } 4260 4261 mozilla::ipc::IPCResult ContentChild::RecvScriptError( 4262 const nsString& aMessage, const nsCString& aSourceName, 4263 const uint32_t& aLineNumber, const uint32_t& aColNumber, 4264 const uint32_t& aFlags, const nsCString& aCategory, 4265 const bool& aFromPrivateWindow, const uint64_t& aInnerWindowId, 4266 const bool& aFromChromeContext) { 4267 nsresult rv = NS_OK; 4268 nsCOMPtr<nsIConsoleService> consoleService = 4269 do_GetService(NS_CONSOLESERVICE_CONTRACTID, &rv); 4270 NS_ENSURE_SUCCESS(rv, IPC_FAIL(this, "Failed to get console service")); 4271 4272 nsCOMPtr<nsIScriptError> scriptError( 4273 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID)); 4274 NS_ENSURE_TRUE(scriptError, 4275 IPC_FAIL(this, "Failed to construct nsIScriptError")); 4276 4277 scriptError->InitWithWindowID(aMessage, aSourceName, aLineNumber, aColNumber, 4278 aFlags, aCategory, aInnerWindowId, 4279 aFromChromeContext); 4280 rv = consoleService->LogMessage(scriptError); 4281 NS_ENSURE_SUCCESS(rv, IPC_FAIL(this, "Failed to log script error")); 4282 4283 return IPC_OK(); 4284 } 4285 4286 mozilla::ipc::IPCResult ContentChild::RecvReportFrameTimingData( 4287 const LoadInfoArgs& loadInfoArgs, const nsString& entryName, 4288 const nsString& initiatorType, UniquePtr<PerformanceTimingData>&& aData) { 4289 if (!aData) { 4290 return IPC_FAIL(this, "aData should not be null"); 4291 } 4292 4293 nsCOMPtr<nsILoadInfo> loadInfo; 4294 nsresult rv = mozilla::ipc::LoadInfoArgsToLoadInfo( 4295 loadInfoArgs, NOT_REMOTE_TYPE, getter_AddRefs(loadInfo)); 4296 if (NS_FAILED(rv)) { 4297 MOZ_DIAGNOSTIC_CRASH("LoadInfoArgsToLoadInfo failed"); 4298 return IPC_OK(); 4299 } 4300 4301 // It is important to call LoadInfo::GetPerformanceStorage instead of simply 4302 // getting the performance object via the innerWindowID in order to perform 4303 // necessary cross origin checks. 4304 if (PerformanceStorage* storage = loadInfo->GetPerformanceStorage()) { 4305 storage->AddEntry(entryName, initiatorType, std::move(aData)); 4306 } 4307 return IPC_OK(); 4308 } 4309 4310 mozilla::ipc::IPCResult ContentChild::RecvLoadURI( 4311 const MaybeDiscarded<BrowsingContext>& aContext, 4312 nsDocShellLoadState* aLoadState, bool aSetNavigating, 4313 LoadURIResolver&& aResolve) { 4314 auto resolveOnExit = MakeScopeExit([&] { aResolve(true); }); 4315 4316 if (aContext.IsNullOrDiscarded()) { 4317 return IPC_OK(); 4318 } 4319 RefPtr<BrowsingContext> context = aContext.get(); 4320 if (!context->IsInProcess()) { 4321 // The DocShell has been torn down or the BrowsingContext has changed 4322 // process in the middle of the load request. There's not much we can do at 4323 // this point, so just give up. 4324 return IPC_OK(); 4325 } 4326 4327 context->LoadURI(aLoadState, aSetNavigating); 4328 4329 nsCOMPtr<nsPIDOMWindowOuter> window = context->GetDOMWindow(); 4330 BrowserChild* bc = BrowserChild::GetFrom(window); 4331 if (bc) { 4332 bc->NotifyNavigationFinished(); 4333 } 4334 4335 #ifdef MOZ_CRASHREPORTER 4336 if (CrashReporter::GetEnabled()) { 4337 nsCOMPtr<nsIURI> annotationURI; 4338 4339 nsresult rv = NS_MutateURI(aLoadState->URI()) 4340 .SetUserPass(""_ns) 4341 .Finalize(annotationURI); 4342 4343 if (NS_FAILED(rv)) { 4344 // Ignore failures on about: URIs. 4345 annotationURI = aLoadState->URI(); 4346 } 4347 4348 CrashReporter::RecordAnnotationNSCString(CrashReporter::Annotation::URL, 4349 annotationURI->GetSpecOrDefault()); 4350 } 4351 #endif 4352 4353 return IPC_OK(); 4354 } 4355 4356 mozilla::ipc::IPCResult ContentChild::RecvInternalLoad( 4357 nsDocShellLoadState* aLoadState) { 4358 if (!aLoadState->Target().IsEmpty() || 4359 aLoadState->TargetBrowsingContext().IsNull()) { 4360 return IPC_FAIL(this, "must already be retargeted"); 4361 } 4362 if (aLoadState->TargetBrowsingContext().IsDiscarded()) { 4363 return IPC_OK(); 4364 } 4365 RefPtr<BrowsingContext> context = aLoadState->TargetBrowsingContext().get(); 4366 4367 context->InternalLoad(aLoadState); 4368 4369 #ifdef MOZ_CRASHREPORTER 4370 if (CrashReporter::GetEnabled()) { 4371 nsCOMPtr<nsIURI> annotationURI; 4372 4373 nsresult rv = NS_MutateURI(aLoadState->URI()) 4374 .SetUserPass(""_ns) 4375 .Finalize(annotationURI); 4376 4377 if (NS_FAILED(rv)) { 4378 // Ignore failures on about: URIs. 4379 annotationURI = aLoadState->URI(); 4380 } 4381 4382 CrashReporter::RecordAnnotationNSCString(CrashReporter::Annotation::URL, 4383 annotationURI->GetSpecOrDefault()); 4384 } 4385 #endif 4386 4387 return IPC_OK(); 4388 } 4389 4390 mozilla::ipc::IPCResult ContentChild::RecvDisplayLoadError( 4391 const MaybeDiscarded<BrowsingContext>& aContext, const nsAString& aURI) { 4392 if (aContext.IsNullOrDiscarded()) { 4393 return IPC_OK(); 4394 } 4395 RefPtr<BrowsingContext> context = aContext.get(); 4396 4397 context->DisplayLoadError(aURI); 4398 4399 nsCOMPtr<nsPIDOMWindowOuter> window = context->GetDOMWindow(); 4400 BrowserChild* bc = BrowserChild::GetFrom(window); 4401 if (bc) { 4402 bc->NotifyNavigationFinished(); 4403 } 4404 return IPC_OK(); 4405 } 4406 4407 mozilla::ipc::IPCResult ContentChild::RecvHistoryCommitIndexAndLength( 4408 const MaybeDiscarded<BrowsingContext>& aContext, const uint32_t& aIndex, 4409 const uint32_t& aLength, const nsID& aChangeID) { 4410 if (!aContext.IsNullOrDiscarded()) { 4411 ChildSHistory* shistory = aContext.get()->GetChildSessionHistory(); 4412 if (shistory) { 4413 shistory->SetIndexAndLength(aIndex, aLength, aChangeID); 4414 } 4415 } 4416 return IPC_OK(); 4417 } 4418 4419 mozilla::ipc::IPCResult ContentChild::RecvConsumeHistoryActivation( 4420 const MaybeDiscarded<BrowsingContext>& aTop) { 4421 if (!aTop.IsNullOrDiscarded()) { 4422 aTop->ConsumeHistoryActivation(); 4423 } 4424 return IPC_OK(); 4425 } 4426 4427 mozilla::ipc::IPCResult ContentChild::RecvGetLayoutHistoryState( 4428 const MaybeDiscarded<BrowsingContext>& aContext, 4429 GetLayoutHistoryStateResolver&& aResolver) { 4430 nsCOMPtr<nsILayoutHistoryState> state; 4431 nsIDocShell* docShell; 4432 mozilla::Maybe<mozilla::dom::Wireframe> wireframe; 4433 if (!aContext.IsNullOrDiscarded() && 4434 (docShell = aContext.get()->GetDocShell())) { 4435 docShell->PersistLayoutHistoryState(); 4436 docShell->GetLayoutHistoryState(getter_AddRefs(state)); 4437 wireframe = static_cast<nsDocShell*>(docShell)->GetWireframe(); 4438 } 4439 aResolver( 4440 std::tuple<nsILayoutHistoryState*, const mozilla::Maybe<Wireframe>&>( 4441 state, wireframe)); 4442 4443 return IPC_OK(); 4444 } 4445 4446 mozilla::ipc::IPCResult ContentChild::RecvDispatchLocationChangeEvent( 4447 const MaybeDiscarded<BrowsingContext>& aContext) { 4448 if (!aContext.IsNullOrDiscarded() && aContext.get()->GetDocShell()) { 4449 aContext.get()->GetDocShell()->DispatchLocationChangeEvent(); 4450 } 4451 return IPC_OK(); 4452 } 4453 4454 mozilla::ipc::IPCResult ContentChild::RecvDispatchBeforeUnloadToSubtree( 4455 const MaybeDiscarded<BrowsingContext>& aStartingAt, 4456 const mozilla::Maybe<SessionHistoryInfo>& aInfo, 4457 DispatchBeforeUnloadToSubtreeResolver&& aResolver) { 4458 if (aStartingAt.IsNullOrDiscarded()) { 4459 aResolver(nsIDocumentViewer::eContinue); 4460 } else { 4461 DispatchBeforeUnloadToSubtree(aStartingAt.get(), aInfo, aResolver); 4462 } 4463 return IPC_OK(); 4464 } 4465 4466 /* static */ void ContentChild::DispatchBeforeUnloadToSubtree( 4467 BrowsingContext* aStartingAt, 4468 const mozilla::Maybe<SessionHistoryInfo>& aInfo, 4469 const DispatchBeforeUnloadToSubtreeResolver& aResolver) { 4470 bool resolved = false; 4471 4472 aStartingAt->PreOrderWalk( 4473 [&](const RefPtr<dom::BrowsingContext>& aBC) 4474 MOZ_CAN_RUN_SCRIPT_BOUNDARY_LAMBDA { 4475 if (RefPtr docShell = nsDocShell::Cast(aBC->GetDocShell())) { 4476 nsCOMPtr<nsIDocumentViewer> viewer; 4477 docShell->GetDocViewer(getter_AddRefs(viewer)); 4478 nsIDocumentViewer::PermitUnloadResult finalStatus = 4479 nsIDocumentViewer::eContinue; 4480 if (viewer) { 4481 finalStatus = viewer->DispatchBeforeUnload(); 4482 } 4483 4484 if (finalStatus == nsIDocumentViewer::eContinue && aBC->IsTop() && 4485 aInfo) { 4486 // https://html.spec.whatwg.org/#preventing-navigation:fire-a-traverse-navigate-event. 4487 // If this is the top-level navigable and we've passed `aInfo`, 4488 // we should perform #fire-a-traverse-navigate-event. 4489 // #checking-if-unloading-is-canceled will block the navigation 4490 // if the "navigate" event handler for the top level window's 4491 // navigation object returns false. 4492 // This should send the correct user involvment. See bug 4493 // 1903552. 4494 finalStatus = docShell->MaybeFireTraversableTraverseHistory( 4495 *aInfo, Nothing()); 4496 } 4497 4498 if (!resolved && finalStatus != nsIDocumentViewer::eContinue) { 4499 // Send our response as soon as we find any blocker, so that we 4500 // can show the permit unload prompt as soon as possible, 4501 // without giving subsequent handlers a chance to delay it. 4502 aResolver(finalStatus); 4503 resolved = true; 4504 } 4505 } 4506 }); 4507 4508 if (!resolved) { 4509 aResolver(nsIDocumentViewer::eContinue); 4510 } 4511 } 4512 4513 mozilla::ipc::IPCResult ContentChild::RecvDispatchNavigateToTraversable( 4514 const MaybeDiscarded<BrowsingContext>& aTraversable, 4515 const mozilla::Maybe<SessionHistoryInfo>& aInfo, 4516 DispatchNavigateToTraversableResolver&& aResolver) { 4517 if (aTraversable.IsNullOrDiscarded() || !aTraversable->GetDocShell()) { 4518 aResolver(nsIDocumentViewer::eContinue); 4519 } else { 4520 RefPtr docShell = nsDocShell::Cast(aTraversable->GetDocShell()); 4521 aResolver(docShell->MaybeFireTraversableTraverseHistory(*aInfo, Nothing())); 4522 } 4523 return IPC_OK(); 4524 } 4525 4526 mozilla::ipc::IPCResult ContentChild::RecvInitNextGenLocalStorageEnabled( 4527 const bool& aEnabled) { 4528 mozilla::dom::RecvInitNextGenLocalStorageEnabled(aEnabled); 4529 4530 return IPC_OK(); 4531 } 4532 4533 mozilla::ipc::IPCResult ContentChild::RecvGoBack( 4534 const MaybeDiscarded<BrowsingContext>& aContext, 4535 const Maybe<int32_t>& aCancelContentJSEpoch, bool aRequireUserInteraction, 4536 bool aUserActivation) { 4537 if (aContext.IsNullOrDiscarded()) { 4538 return IPC_OK(); 4539 } 4540 BrowsingContext* bc = aContext.get(); 4541 4542 if (RefPtr<nsDocShell> docShell = nsDocShell::Cast(bc->GetDocShell())) { 4543 if (aCancelContentJSEpoch) { 4544 docShell->SetCancelContentJSEpoch(*aCancelContentJSEpoch); 4545 } 4546 docShell->GoBack(aRequireUserInteraction, aUserActivation); 4547 4548 if (BrowserChild* browserChild = BrowserChild::GetFrom(docShell)) { 4549 browserChild->NotifyNavigationFinished(); 4550 } 4551 } 4552 4553 return IPC_OK(); 4554 } 4555 4556 mozilla::ipc::IPCResult ContentChild::RecvGoForward( 4557 const MaybeDiscarded<BrowsingContext>& aContext, 4558 const Maybe<int32_t>& aCancelContentJSEpoch, bool aRequireUserInteraction, 4559 bool aUserActivation) { 4560 if (aContext.IsNullOrDiscarded()) { 4561 return IPC_OK(); 4562 } 4563 BrowsingContext* bc = aContext.get(); 4564 4565 if (RefPtr<nsDocShell> docShell = nsDocShell::Cast(bc->GetDocShell())) { 4566 if (aCancelContentJSEpoch) { 4567 docShell->SetCancelContentJSEpoch(*aCancelContentJSEpoch); 4568 } 4569 docShell->GoForward(aRequireUserInteraction, aUserActivation); 4570 4571 if (BrowserChild* browserChild = BrowserChild::GetFrom(docShell)) { 4572 browserChild->NotifyNavigationFinished(); 4573 } 4574 } 4575 4576 return IPC_OK(); 4577 } 4578 4579 mozilla::ipc::IPCResult ContentChild::RecvGoToIndex( 4580 const MaybeDiscarded<BrowsingContext>& aContext, const int32_t& aIndex, 4581 const Maybe<int32_t>& aCancelContentJSEpoch, bool aUserActivation) { 4582 if (aContext.IsNullOrDiscarded()) { 4583 return IPC_OK(); 4584 } 4585 BrowsingContext* bc = aContext.get(); 4586 4587 if (RefPtr<nsDocShell> docShell = nsDocShell::Cast(bc->GetDocShell())) { 4588 if (aCancelContentJSEpoch) { 4589 docShell->SetCancelContentJSEpoch(*aCancelContentJSEpoch); 4590 } 4591 docShell->GotoIndex(aIndex, aUserActivation); 4592 4593 if (BrowserChild* browserChild = BrowserChild::GetFrom(docShell)) { 4594 browserChild->NotifyNavigationFinished(); 4595 } 4596 } 4597 4598 return IPC_OK(); 4599 } 4600 4601 mozilla::ipc::IPCResult ContentChild::RecvReload( 4602 const MaybeDiscarded<BrowsingContext>& aContext, 4603 const uint32_t aReloadFlags) { 4604 if (aContext.IsNullOrDiscarded()) { 4605 return IPC_OK(); 4606 } 4607 BrowsingContext* bc = aContext.get(); 4608 4609 if (RefPtr<nsDocShell> docShell = nsDocShell::Cast(bc->GetDocShell())) { 4610 docShell->Reload(aReloadFlags); 4611 } 4612 4613 return IPC_OK(); 4614 } 4615 4616 mozilla::ipc::IPCResult ContentChild::RecvStopLoad( 4617 const MaybeDiscarded<BrowsingContext>& aContext, 4618 const uint32_t aStopFlags) { 4619 if (aContext.IsNullOrDiscarded()) { 4620 return IPC_OK(); 4621 } 4622 BrowsingContext* bc = aContext.get(); 4623 4624 if (auto* docShell = nsDocShell::Cast(bc->GetDocShell())) { 4625 docShell->Stop(aStopFlags); 4626 } 4627 4628 return IPC_OK(); 4629 } 4630 4631 #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS) 4632 mozilla::ipc::IPCResult ContentChild::RecvInitSandboxTesting( 4633 Endpoint<PSandboxTestingChild>&& aEndpoint) { 4634 if (!SandboxTestingChild::Initialize(std::move(aEndpoint))) { 4635 return IPC_FAIL( 4636 this, "InitSandboxTesting failed to initialise the child process."); 4637 } 4638 return IPC_OK(); 4639 } 4640 #endif 4641 4642 NS_IMETHODIMP ContentChild::GetChildID(uint64_t* aOut) { 4643 *aOut = XRE_GetChildID(); 4644 return NS_OK; 4645 } 4646 4647 NS_IMETHODIMP ContentChild::GetActor(const nsACString& aName, JSContext* aCx, 4648 JSProcessActorChild** retval) { 4649 ErrorResult error; 4650 RefPtr<JSProcessActorChild> actor = 4651 JSActorManager::GetActor(aCx, aName, error) 4652 .downcast<JSProcessActorChild>(); 4653 if (error.MaybeSetPendingException(aCx)) { 4654 return NS_ERROR_FAILURE; 4655 } 4656 actor.forget(retval); 4657 return NS_OK; 4658 } 4659 4660 NS_IMETHODIMP ContentChild::GetExistingActor(const nsACString& aName, 4661 JSProcessActorChild** retval) { 4662 RefPtr<JSProcessActorChild> actor = 4663 JSActorManager::GetExistingActor(aName).downcast<JSProcessActorChild>(); 4664 actor.forget(retval); 4665 return NS_OK; 4666 } 4667 4668 already_AddRefed<JSActor> ContentChild::InitJSActor( 4669 JS::Handle<JSObject*> aMaybeActor, const nsACString& aName, 4670 ErrorResult& aRv) { 4671 RefPtr<JSProcessActorChild> actor; 4672 if (aMaybeActor.get()) { 4673 aRv = UNWRAP_OBJECT(JSProcessActorChild, aMaybeActor.get(), actor); 4674 if (aRv.Failed()) { 4675 return nullptr; 4676 } 4677 } else { 4678 actor = new JSProcessActorChild(); 4679 } 4680 4681 MOZ_RELEASE_ASSERT(!actor->Manager(), 4682 "mManager was already initialized once!"); 4683 actor->Init(aName, this); 4684 return actor.forget(); 4685 } 4686 4687 IPCResult ContentChild::RecvRawMessage( 4688 const JSActorMessageMeta& aMeta, JSIPCValue&& aData, 4689 const UniquePtr<ClonedMessageData>& aStack) { 4690 UniquePtr<StructuredCloneData> stack; 4691 if (aStack) { 4692 stack = MakeUnique<StructuredCloneData>(); 4693 stack->BorrowFromClonedMessageData(*aStack); 4694 } 4695 ReceiveRawMessage(aMeta, std::move(aData), std::move(stack)); 4696 return IPC_OK(); 4697 } 4698 4699 NS_IMETHODIMP ContentChild::GetCanSend(bool* aCanSend) { 4700 *aCanSend = CanSend(); 4701 return NS_OK; 4702 } 4703 4704 ContentChild* ContentChild::AsContentChild() { return this; } 4705 4706 JSActorManager* ContentChild::AsJSActorManager() { return this; } 4707 4708 IPCResult ContentChild::RecvFlushFOGData(FlushFOGDataResolver&& aResolver) { 4709 glean::FlushFOGData(std::move(aResolver)); 4710 return IPC_OK(); 4711 } 4712 4713 IPCResult ContentChild::RecvUpdateMediaCodecsSupported( 4714 RemoteMediaIn aLocation, const media::MediaCodecsSupported& aSupported) { 4715 RemoteMediaManagerChild::SetSupported(aLocation, aSupported); 4716 4717 return IPC_OK(); 4718 } 4719 4720 void ContentChild::ConfigureThreadPerformanceHints( 4721 const hal::ProcessPriority& aPriority) { 4722 if (aPriority >= hal::PROCESS_PRIORITY_FOREGROUND) { 4723 static bool canUsePerformanceHintSession = true; 4724 if (!mPerformanceHintSession && canUsePerformanceHintSession) { 4725 nsTArray<PlatformThreadHandle> threads; 4726 Servo_ThreadPool_GetThreadHandles(&threads); 4727 #ifdef XP_WIN 4728 threads.AppendElement(GetCurrentThread()); 4729 #else 4730 threads.AppendElement(pthread_self()); 4731 #endif 4732 4733 mPerformanceHintSession = hal::CreatePerformanceHintSession( 4734 threads, GetPerformanceHintTarget(TimeDuration::FromMilliseconds( 4735 nsRefreshDriver::DefaultInterval()))); 4736 4737 // Avoid repeatedly attempting to create a session if it is not 4738 // supported. 4739 canUsePerformanceHintSession = mPerformanceHintSession != nullptr; 4740 } 4741 4742 #ifdef MOZ_WIDGET_ANDROID 4743 // On Android if we are unable to use PerformanceHintManager then fall back 4744 // to setting the stylo threads' affinities to the performant cores. Android 4745 // automatically sets each thread's affinity to all cores when a process is 4746 // foregrounded, and to a subset of cores when the process is backgrounded. 4747 // We must therefore override this each time the process is foregrounded, 4748 // but we don't have to do anything when backgrounded. 4749 if (!mPerformanceHintSession) { 4750 if (const auto& cpuInfo = hal::GetHeterogeneousCpuInfo()) { 4751 // If CPUs are homogeneous there is no point setting affinity. 4752 if (cpuInfo->mBigCpus.Count() != cpuInfo->mTotalNumCpus) { 4753 BitSet<hal::HeterogeneousCpuInfo::MAX_CPUS> cpus = cpuInfo->mBigCpus; 4754 if (cpus.Count() < 2) { 4755 // From testing on a variety of devices it appears using only the 4756 // big cores gives best performance when there are 2 or more big 4757 // cores. If there are fewer than 2 big cores then additionally 4758 // using the medium cores performs better. 4759 cpus |= cpuInfo->mMediumCpus; 4760 } 4761 4762 static_assert( 4763 hal::HeterogeneousCpuInfo::MAX_CPUS <= CPU_SETSIZE, 4764 "HeterogeneousCpuInfo::MAX_CPUS is too large for CPU_SETSIZE"); 4765 4766 cpu_set_t cpuset; 4767 CPU_ZERO(&cpuset); 4768 for (size_t i = 0; i < cpuInfo->mTotalNumCpus; i++) { 4769 if (cpus.test(i)) { 4770 CPU_SET(i, &cpuset); 4771 } 4772 } 4773 4774 // Only set the affinity for the stylo threads, not the main thread. 4775 // Testing showed no difference in performance between the two 4776 // options, and as newly spawned threads automatically inherit their 4777 // parent's affinity mask there may be unintended consequences to 4778 // setting the main thread affinity. 4779 nsTArray<PlatformThreadHandle> threads; 4780 Servo_ThreadPool_GetThreadHandles(&threads); 4781 for (pthread_t thread : threads) { 4782 int ret = sched_setaffinity(pthread_gettid_np(thread), 4783 sizeof(cpu_set_t), &cpuset); 4784 // Occasionally sched_setaffinity fails, presumably due to a race 4785 // between us receiving the process foreground signal and whatever 4786 // is responsible for restricting which processes can use certain 4787 // cores. Trying again in a runnable seems to do the trick, but if 4788 // that still fails it's not the end of the world. 4789 if (ret < 0) { 4790 NS_DispatchToCurrentThread(NS_NewRunnableFunction( 4791 "ContentChild::ConfigureThreadPerformanceHints", 4792 [threads = std::move(threads), cpuset] { 4793 for (pthread_t thread : threads) { 4794 sched_setaffinity(pthread_gettid_np(thread), 4795 sizeof(cpu_set_t), &cpuset); 4796 } 4797 })); 4798 break; 4799 } 4800 } 4801 } 4802 } 4803 } 4804 #endif 4805 } else { 4806 mPerformanceHintSession = nullptr; 4807 } 4808 } 4809 4810 #ifdef MOZ_WMF_CDM 4811 mozilla::ipc::IPCResult ContentChild::RecvUpdateMFCDMOriginEntries( 4812 const nsTArray<IPCOriginStatusEntry>& aEntries) { 4813 MediaKeySystemAccess::UpdateMFCDMOriginEntries(aEntries); 4814 return IPC_OK(); 4815 } 4816 #endif 4817 4818 } // namespace dom 4819 4820 #if defined(__OpenBSD__) && defined(MOZ_SANDBOX) 4821 4822 static LazyLogModule sPledgeLog("OpenBSDSandbox"); 4823 4824 NS_IMETHODIMP 4825 OpenBSDFindPledgeUnveilFilePath(const char* file, nsACString& result) { 4826 struct stat st; 4827 4828 // Allow overriding files in /etc/$MOZ_APP_NAME 4829 result.Assign(nsPrintfCString("/etc/%s/%s", MOZ_APP_NAME, file)); 4830 if (stat(PromiseFlatCString(result).get(), &st) == 0) { 4831 return NS_OK; 4832 } 4833 4834 // Or look in the system default directory 4835 result.Assign(nsPrintfCString( 4836 "/usr/local/lib/%s/browser/defaults/preferences/%s", MOZ_APP_NAME, file)); 4837 if (stat(PromiseFlatCString(result).get(), &st) == 0) { 4838 return NS_OK; 4839 } 4840 4841 errx(1, "can't locate %s", file); 4842 } 4843 4844 NS_IMETHODIMP 4845 OpenBSDPledgePromises(const nsACString& aPath) { 4846 // Using NS_LOCAL_FILE_CONTRACTID/NS_LOCALFILEINPUTSTREAM_CONTRACTID requires 4847 // a lot of setup before they are supported and we want to pledge early on 4848 // before all of that, so read the file directly 4849 std::ifstream input(PromiseFlatCString(aPath).get()); 4850 4851 // Build up one line of pledge promises without comments 4852 nsAutoCString promises; 4853 bool disabled = false; 4854 int linenum = 0; 4855 for (std::string tLine; std::getline(input, tLine);) { 4856 nsAutoCString line(tLine.c_str()); 4857 linenum++; 4858 4859 // Cut off any comments at the end of the line, also catches lines 4860 // that are entirely a comment 4861 int32_t hash = line.FindChar('#'); 4862 if (hash >= 0) { 4863 line = Substring(line, 0, hash); 4864 } 4865 line.CompressWhitespace(true, true); 4866 if (line.IsEmpty()) { 4867 continue; 4868 } 4869 4870 if (linenum == 1 && line.EqualsLiteral("disable")) { 4871 disabled = true; 4872 break; 4873 } 4874 4875 if (!promises.IsEmpty()) { 4876 promises.Append(" "); 4877 } 4878 promises.Append(line); 4879 } 4880 input.close(); 4881 4882 if (disabled) { 4883 warnx("%s: disabled", PromiseFlatCString(aPath).get()); 4884 } else { 4885 MOZ_LOG( 4886 sPledgeLog, LogLevel::Debug, 4887 ("%s: pledge(%s)\n", PromiseFlatCString(aPath).get(), promises.get())); 4888 if (pledge(promises.get(), nullptr) != 0) { 4889 err(1, "%s: pledge(%s) failed", PromiseFlatCString(aPath).get(), 4890 promises.get()); 4891 } 4892 } 4893 4894 return NS_OK; 4895 } 4896 4897 void ExpandUnveilPath(nsAutoCString& path) { 4898 // Expand $XDG_RUNTIME_DIR to the environment variable, or ~/.cache 4899 nsCString xdgRuntimeDir(PR_GetEnv("XDG_RUNTIME_DIR")); 4900 if (xdgRuntimeDir.IsEmpty()) { 4901 xdgRuntimeDir = "~/.cache"; 4902 } 4903 path.ReplaceSubstring("$XDG_RUNTIME_DIR", xdgRuntimeDir.get()); 4904 4905 // Expand $XDG_CONFIG_HOME to the environment variable, or ~/.config 4906 nsCString xdgConfigHome(PR_GetEnv("XDG_CONFIG_HOME")); 4907 if (xdgConfigHome.IsEmpty()) { 4908 xdgConfigHome = "~/.config"; 4909 } 4910 path.ReplaceSubstring("$XDG_CONFIG_HOME", xdgConfigHome.get()); 4911 4912 // Expand $XDG_CACHE_HOME to the environment variable, or ~/.cache 4913 nsCString xdgCacheHome(PR_GetEnv("XDG_CACHE_HOME")); 4914 if (xdgCacheHome.IsEmpty()) { 4915 xdgCacheHome = "~/.cache"; 4916 } 4917 path.ReplaceSubstring("$XDG_CACHE_HOME", xdgCacheHome.get()); 4918 4919 // Expand $XDG_DATA_HOME to the environment variable, or ~/.local/share 4920 nsCString xdgDataHome(PR_GetEnv("XDG_DATA_HOME")); 4921 if (xdgDataHome.IsEmpty()) { 4922 xdgDataHome = "~/.local/share"; 4923 } 4924 path.ReplaceSubstring("$XDG_DATA_HOME", xdgDataHome.get()); 4925 4926 // Expand leading ~ to the user's home directory 4927 nsCOMPtr<nsIFile> homeDir; 4928 nsresult rv = 4929 GetSpecialSystemDirectory(Unix_HomeDirectory, getter_AddRefs(homeDir)); 4930 if (NS_FAILED(rv)) { 4931 errx(1, "failed getting home directory"); 4932 } 4933 if (path.FindChar('~') == 0) { 4934 nsCString tHome(homeDir->NativePath()); 4935 tHome.Append(Substring(path, 1, path.Length() - 1)); 4936 path = tHome.get(); 4937 } 4938 } 4939 4940 void MkdirP(nsAutoCString& path) { 4941 // nsLocalFile::CreateAllAncestors would be nice to use 4942 4943 nsAutoCString tPath(""); 4944 for (const nsACString& dir : path.Split('/')) { 4945 struct stat st; 4946 4947 if (dir.IsEmpty()) { 4948 continue; 4949 } 4950 4951 tPath.Append("/"); 4952 tPath.Append(dir); 4953 4954 if (stat(tPath.get(), &st) == -1) { 4955 if (mkdir(tPath.get(), 0700) == -1) { 4956 err(1, "failed mkdir(%s) while MkdirP(%s)", 4957 PromiseFlatCString(tPath).get(), PromiseFlatCString(path).get()); 4958 } 4959 } 4960 } 4961 } 4962 4963 NS_IMETHODIMP 4964 OpenBSDUnveilPaths(const nsACString& uPath, const nsACString& pledgePath) { 4965 // Using NS_LOCAL_FILE_CONTRACTID/NS_LOCALFILEINPUTSTREAM_CONTRACTID requires 4966 // a lot of setup before they are allowed/supported and we want to pledge and 4967 // unveil early on before all of that is setup 4968 std::ifstream input(PromiseFlatCString(uPath).get()); 4969 4970 bool disabled = false; 4971 int linenum = 0; 4972 for (std::string tLine; std::getline(input, tLine);) { 4973 nsAutoCString line(tLine.c_str()); 4974 linenum++; 4975 4976 // Cut off any comments at the end of the line, also catches lines 4977 // that are entirely a comment 4978 int32_t hash = line.FindChar('#'); 4979 if (hash >= 0) { 4980 line = Substring(line, 0, hash); 4981 } 4982 line.CompressWhitespace(true, true); 4983 if (line.IsEmpty()) { 4984 continue; 4985 } 4986 4987 if (linenum == 1 && line.EqualsLiteral("disable")) { 4988 disabled = true; 4989 break; 4990 } 4991 4992 int32_t space = line.FindChar(' '); 4993 if (space <= 0) { 4994 errx(1, "%s: line %d: invalid format", PromiseFlatCString(uPath).get(), 4995 linenum); 4996 } 4997 4998 nsAutoCString uPath(Substring(line, 0, space)); 4999 ExpandUnveilPath(uPath); 5000 5001 nsAutoCString perms(Substring(line, space + 1, line.Length() - space - 1)); 5002 5003 MOZ_LOG(sPledgeLog, LogLevel::Debug, 5004 ("%s: unveil(%s, %s)\n", PromiseFlatCString(uPath).get(), 5005 uPath.get(), perms.get())); 5006 if (unveil(uPath.get(), perms.get()) == -1 && errno != ENOENT) { 5007 err(1, "%s: unveil(%s, %s) failed", PromiseFlatCString(uPath).get(), 5008 uPath.get(), perms.get()); 5009 } 5010 } 5011 input.close(); 5012 5013 if (disabled) { 5014 warnx("%s: disabled", PromiseFlatCString(uPath).get()); 5015 } else { 5016 struct stat st; 5017 5018 // Only unveil the pledgePath file if it's not already unveiled, otherwise 5019 // some containing directory will lose visibility. 5020 if (stat(PromiseFlatCString(pledgePath).get(), &st) == -1) { 5021 if (errno == ENOENT) { 5022 if (unveil(PromiseFlatCString(pledgePath).get(), "r") == -1) { 5023 err(1, "unveil(%s, r) failed", PromiseFlatCString(pledgePath).get()); 5024 } 5025 } else { 5026 err(1, "stat(%s)", PromiseFlatCString(pledgePath).get()); 5027 } 5028 } 5029 } 5030 5031 return NS_OK; 5032 } 5033 5034 bool StartOpenBSDSandbox(GeckoProcessType type, ipc::SandboxingKind kind) { 5035 nsAutoCString pledgeFile; 5036 nsAutoCString unveilFile; 5037 char binaryPath[MAXPATHLEN]; 5038 5039 switch (type) { 5040 case GeckoProcessType_Default: { 5041 OpenBSDFindPledgeUnveilFilePath("pledge.main", pledgeFile); 5042 OpenBSDFindPledgeUnveilFilePath("unveil.main", unveilFile); 5043 5044 // Ensure dconf dir exists before we veil the filesystem 5045 nsAutoCString dConf("$XDG_RUNTIME_DIR/dconf"); 5046 ExpandUnveilPath(dConf); 5047 MkdirP(dConf); 5048 break; 5049 } 5050 5051 case GeckoProcessType_Content: 5052 OpenBSDFindPledgeUnveilFilePath("pledge.content", pledgeFile); 5053 OpenBSDFindPledgeUnveilFilePath("unveil.content", unveilFile); 5054 break; 5055 5056 case GeckoProcessType_GPU: 5057 OpenBSDFindPledgeUnveilFilePath("pledge.gpu", pledgeFile); 5058 OpenBSDFindPledgeUnveilFilePath("unveil.gpu", unveilFile); 5059 break; 5060 5061 case GeckoProcessType_Socket: 5062 OpenBSDFindPledgeUnveilFilePath("pledge.socket", pledgeFile); 5063 OpenBSDFindPledgeUnveilFilePath("unveil.socket", unveilFile); 5064 break; 5065 5066 case GeckoProcessType_RDD: 5067 OpenBSDFindPledgeUnveilFilePath("pledge.rdd", pledgeFile); 5068 OpenBSDFindPledgeUnveilFilePath("unveil.rdd", unveilFile); 5069 break; 5070 5071 case GeckoProcessType_Utility: { 5072 MOZ_RELEASE_ASSERT(kind <= SandboxingKind::COUNT, 5073 "Should define a sandbox"); 5074 switch (kind) { 5075 case ipc::SandboxingKind::GENERIC_UTILITY: 5076 default: 5077 OpenBSDFindPledgeUnveilFilePath("pledge.utility", pledgeFile); 5078 OpenBSDFindPledgeUnveilFilePath("unveil.utility", unveilFile); 5079 break; 5080 } 5081 } break; 5082 5083 default: 5084 MOZ_ASSERT(false, "unknown process type"); 5085 return false; 5086 } 5087 5088 nsresult rv = mozilla::BinaryPath::Get(binaryPath); 5089 if (NS_FAILED(rv)) { 5090 errx(1, "failed to cache binary path ?"); 5091 } 5092 5093 if (NS_WARN_IF(NS_FAILED(OpenBSDUnveilPaths(unveilFile, pledgeFile)))) { 5094 errx(1, "failed reading/parsing %s", unveilFile.get()); 5095 } 5096 5097 if (NS_WARN_IF(NS_FAILED(OpenBSDPledgePromises(pledgeFile)))) { 5098 errx(1, "failed reading/parsing %s", pledgeFile.get()); 5099 } 5100 5101 // Don't overwrite an existing session dbus address, but ensure it is set 5102 if (!PR_GetEnv("DBUS_SESSION_BUS_ADDRESS")) { 5103 PR_SetEnv("DBUS_SESSION_BUS_ADDRESS="); 5104 } 5105 5106 return true; 5107 } 5108 #endif 5109 5110 } // namespace mozilla 5111 5112 /* static */ 5113 nsIDOMProcessChild* nsIDOMProcessChild::GetSingleton() { 5114 if (XRE_IsContentProcess()) { 5115 return mozilla::dom::ContentChild::GetSingleton(); 5116 } 5117 return mozilla::dom::InProcessChild::Singleton(); 5118 }