Bug 1936278 - Prevent search mode chiclet from being dismissed when clicking in page...
[gecko.git] / dom / ipc / ContentChild.cpp
bloba611511630436c7a89db01dad627174f47e1af38
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/. */
7 #ifdef MOZ_WIDGET_ANDROID
8 # include "AndroidDecoderModule.h"
9 #endif
11 #include "BrowserChild.h"
12 #include "nsNSSComponent.h"
13 #include "ContentChild.h"
14 #include "GeckoProfiler.h"
15 #include "HandlerServiceChild.h"
16 #include "nsXPLookAndFeel.h"
17 #include "mozilla/AppShutdown.h"
18 #include "mozilla/Attributes.h"
19 #include "mozilla/BackgroundHangMonitor.h"
20 #include "mozilla/BenchmarkStorageChild.h"
21 #include "mozilla/FOGIPC.h"
22 #include "GMPServiceChild.h"
23 #include "Geolocation.h"
24 #include "imgLoader.h"
25 #include "ScrollingMetrics.h"
26 #include "mozilla/BasePrincipal.h"
27 #include "mozilla/ClipboardContentAnalysisChild.h"
28 #include "mozilla/ClipboardReadRequestChild.h"
29 #include "mozilla/Components.h"
30 #include "mozilla/HangDetails.h"
31 #include "mozilla/LoadInfo.h"
32 #include "mozilla/Logging.h"
33 #include "mozilla/LookAndFeel.h"
34 #include "mozilla/MemoryTelemetry.h"
35 #include "mozilla/NullPrincipal.h"
36 #include "mozilla/PerfStats.h"
37 #include "mozilla/Preferences.h"
38 #include "mozilla/ProcessHangMonitorIPC.h"
39 #include "mozilla/RemoteDecoderManagerChild.h"
40 #include "mozilla/RemoteLazyInputStreamChild.h"
41 #include "mozilla/SchedulerGroup.h"
42 #include "mozilla/ScopeExit.h"
43 #include "mozilla/SharedStyleSheetCache.h"
44 #include "mozilla/dom/SharedScriptCache.h"
45 #include "mozilla/SimpleEnumerator.h"
46 #include "mozilla/SpinEventLoopUntil.h"
47 #include "mozilla/StaticPrefs_browser.h"
48 #include "mozilla/StaticPrefs_dom.h"
49 #include "mozilla/StaticPrefs_fission.h"
50 #include "mozilla/StaticPrefs_javascript.h"
51 #include "mozilla/StaticPrefs_media.h"
52 #include "mozilla/StaticPrefs_threads.h"
53 #include "mozilla/StorageAccessAPIHelper.h"
54 #include "mozilla/TelemetryIPC.h"
55 #include "mozilla/Unused.h"
56 #include "mozilla/WebBrowserPersistDocumentChild.h"
57 #include "mozilla/devtools/HeapSnapshotTempFileHelperChild.h"
58 #include "mozilla/dom/AutoSuppressEventHandlingAndSuspend.h"
59 #include "mozilla/dom/BlobImpl.h"
60 #include "mozilla/dom/BrowserBridgeHost.h"
61 #include "mozilla/dom/BrowsingContext.h"
62 #include "mozilla/dom/BrowsingContextGroup.h"
63 #include "mozilla/dom/ChildProcessChannelListener.h"
64 #include "mozilla/dom/ChildProcessMessageManager.h"
65 #include "mozilla/dom/ClientManager.h"
66 #include "mozilla/dom/ContentParent.h"
67 #include "mozilla/dom/ContentProcessManager.h"
68 #include "mozilla/dom/ContentPlaybackController.h"
69 #include "mozilla/dom/ContentProcessMessageManager.h"
70 #include "mozilla/dom/DataTransfer.h"
71 #include "mozilla/dom/DocGroup.h"
72 #include "mozilla/dom/ExternalHelperAppChild.h"
73 #include "mozilla/dom/GetFilesHelper.h"
74 #include "mozilla/dom/IPCBlobUtils.h"
75 #include "mozilla/dom/InProcessChild.h"
76 #include "mozilla/dom/JSActorService.h"
77 #include "mozilla/dom/JSProcessActorBinding.h"
78 #include "mozilla/dom/JSProcessActorChild.h"
79 #include "mozilla/dom/LSObject.h"
80 #include "mozilla/dom/MemoryReportRequest.h"
81 #include "mozilla/dom/PSessionStorageObserverChild.h"
82 #include "mozilla/dom/PostMessageEvent.h"
83 #include "mozilla/dom/PushNotifier.h"
84 #include "mozilla/dom/RemoteWorkerService.h"
85 #include "mozilla/dom/ScreenOrientation.h"
86 #include "mozilla/dom/ServiceWorkerManager.h"
87 #include "mozilla/dom/SessionStorageManager.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/Logging.h"
97 #include "mozilla/gfx/gfxVars.h"
98 #include "mozilla/hal_sandbox/PHalChild.h"
99 #include "mozilla/intl/L10nRegistry.h"
100 #include "mozilla/intl/LocaleService.h"
101 #include "mozilla/ipc/BackgroundChild.h"
102 #include "mozilla/ipc/Endpoint.h"
103 #include "mozilla/ipc/FileDescriptorUtils.h"
104 #include "mozilla/ipc/GeckoChildProcessHost.h"
105 #include "mozilla/ipc/ProcessChild.h"
106 #include "mozilla/ipc/TestShellChild.h"
107 #include "mozilla/layers/APZChild.h"
108 #include "mozilla/layers/CompositorManagerChild.h"
109 #include "mozilla/layers/ContentProcessController.h"
110 #include "mozilla/layers/ImageBridgeChild.h"
111 #ifdef NS_PRINTING
112 # include "mozilla/layout/RemotePrintJobChild.h"
113 #endif
114 #include "mozilla/loader/ScriptCacheActors.h"
115 #include "mozilla/media/MediaChild.h"
116 #include "mozilla/net/CaptivePortalService.h"
117 #include "mozilla/net/ChildDNSService.h"
118 #include "mozilla/net/CookieServiceChild.h"
119 #include "mozilla/net/DocumentChannelChild.h"
120 #include "mozilla/net/HttpChannelChild.h"
121 #include "mozilla/widget/RemoteLookAndFeel.h"
122 #include "mozilla/widget/ScreenManager.h"
123 #include "mozilla/widget/WidgetMessageUtils.h"
124 #include "nsBaseDragService.h"
125 #include "nsDocShellLoadTypes.h"
126 #include "nsFocusManager.h"
127 #include "nsHttpHandler.h"
128 #include "nsIConsoleService.h"
129 #include "nsIInputStreamChannel.h"
130 #include "nsILayoutHistoryState.h"
131 #include "nsILoadGroup.h"
132 #include "nsIOpenWindowInfo.h"
133 #include "nsISimpleEnumerator.h"
134 #include "nsIStringBundle.h"
135 #include "nsIURIMutator.h"
136 #include "nsQueryObject.h"
137 #include "nsRefreshDriver.h"
138 #include "nsSandboxFlags.h"
139 #include "mozmemory.h"
141 #include "ChildProfilerController.h"
143 #if defined(MOZ_SANDBOX)
144 # include "mozilla/SandboxSettings.h"
145 # if defined(XP_WIN)
146 # include "mozilla/sandboxTarget.h"
147 # include "mozilla/ProcInfo.h"
148 # elif defined(XP_LINUX)
149 # include "CubebUtils.h"
150 # include "mozilla/Sandbox.h"
151 # include "mozilla/SandboxInfo.h"
152 # include "mozilla/SandboxProfilerObserver.h"
153 # elif defined(XP_MACOSX)
154 # include <CoreGraphics/CGError.h>
155 # include "mozilla/Sandbox.h"
156 # elif defined(__OpenBSD__)
157 # include <err.h>
158 # include <sys/stat.h>
159 # include <unistd.h>
161 # include <fstream>
163 # include "BinaryPath.h"
164 # include "SpecialSystemDirectory.h"
165 # include "nsILineInputStream.h"
166 # include "mozilla/ipc/UtilityProcessSandboxing.h"
167 # endif
168 # if defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
169 # include "mozilla/SandboxTestingChild.h"
170 # endif
171 #endif
173 #include "SandboxHal.h"
174 #include "mozInlineSpellChecker.h"
175 #include "mozilla/GlobalStyleSheetCache.h"
176 #include "nsAnonymousTemporaryFile.h"
177 #include "nsCategoryManagerUtils.h"
178 #include "nsClipboardProxy.h"
179 #include "nsContentPermissionHelper.h"
180 #include "nsDebugImpl.h"
181 #include "nsDirectoryService.h"
182 #include "nsDirectoryServiceDefs.h"
183 #include "nsDirectoryServiceUtils.h"
184 #include "nsDocShell.h"
185 #include "nsDocShellLoadState.h"
186 #include "nsHashPropertyBag.h"
187 #include "nsIConsoleListener.h"
188 #include "nsICycleCollectorListener.h"
189 #include "nsIDocShellTreeOwner.h"
190 #include "nsIDocumentViewer.h"
191 #include "nsIDragService.h"
192 #include "nsIInterfaceRequestorUtils.h"
193 #include "nsIMemoryInfoDumper.h"
194 #include "nsIMemoryReporter.h"
195 #include "nsIObserverService.h"
196 #include "nsIOService.h"
197 #include "nsIScriptError.h"
198 #include "nsIScriptSecurityManager.h"
199 #include "nsJSEnvironment.h"
200 #include "nsJSUtils.h"
201 #include "nsMemoryInfoDumper.h"
202 #include "nsServiceManagerUtils.h"
203 #include "nsStyleSheetService.h"
204 #include "nsThreadManager.h"
205 #include "nsXULAppAPI.h"
206 #include "IHistory.h"
207 #include "ReferrerInfo.h"
208 #include "base/message_loop.h"
209 #include "base/process_util.h"
210 #include "base/task.h"
211 #include "mozilla/dom/BlobURLProtocolHandler.h"
212 #include "mozilla/dom/PCycleCollectWithLogsChild.h"
213 #include "mozilla/dom/PerformanceStorage.h"
214 #include "nsChromeRegistryContent.h"
215 #include "nsFrameMessageManager.h"
216 #include "nsNetUtil.h"
217 #include "nsWindowMemoryReporter.h"
219 #ifdef MOZ_WEBRTC
220 # include "jsapi/WebrtcGlobalChild.h"
221 #endif
223 #include "PermissionMessageUtils.h"
224 #include "mozilla/Permission.h"
225 #include "mozilla/PermissionManager.h"
227 #if defined(MOZ_WIDGET_ANDROID)
228 # include "APKOpen.h"
229 # include <sched.h>
230 #endif
232 #ifdef XP_WIN
233 # include <process.h>
234 # define getpid _getpid
235 # include "mozilla/WinDllServices.h"
236 #endif
238 #if defined(XP_MACOSX)
239 # include "nsMacUtilsImpl.h"
240 # include <sys/qos.h>
241 #endif /* XP_MACOSX */
243 #ifdef MOZ_X11
244 # include "mozilla/X11Util.h"
245 #endif
247 #ifdef ACCESSIBILITY
248 # include "nsAccessibilityService.h"
249 # ifdef XP_WIN
250 # include "mozilla/a11y/AccessibleWrap.h"
251 # endif
252 # include "mozilla/a11y/DocAccessible.h"
253 # include "mozilla/a11y/DocManager.h"
254 # include "mozilla/a11y/OuterDocAccessible.h"
255 #endif
257 #include "mozilla/dom/File.h"
258 #include "mozilla/dom/MediaControllerBinding.h"
260 #ifdef MOZ_WEBSPEECH
261 # include "mozilla/dom/PSpeechSynthesisChild.h"
262 #endif
264 #include "ClearOnShutdown.h"
265 #include "DomainPolicy.h"
266 #include "GfxInfoBase.h"
267 #include "MMPrinter.h"
268 #include "mozilla/ipc/ProcessUtils.h"
269 #include "mozilla/ipc/URIUtils.h"
270 #include "VRManagerChild.h"
271 #include "gfxPlatform.h"
272 #include "gfxPlatformFontList.h"
273 #include "mozilla/RemoteSpellCheckEngineChild.h"
274 #include "mozilla/dom/TabContext.h"
275 #include "mozilla/dom/ipc/StructuredCloneData.h"
276 #include "mozilla/ipc/CrashReporterClient.h"
277 #include "mozilla/net/NeckoMessageUtils.h"
278 #include "mozilla/widget/PuppetBidiKeyboard.h"
279 #include "nsContentUtils.h"
280 #include "nsIPrincipal.h"
281 #include "nsString.h"
282 #include "nscore.h" // for NS_FREE_PERMANENT_DATA
283 #include "private/pprio.h"
285 #ifdef MOZ_WIDGET_GTK
286 # include "mozilla/WidgetUtilsGtk.h"
287 # include "nsAppRunner.h"
288 # include <gtk/gtk.h>
289 #endif
291 #ifdef MOZ_CODE_COVERAGE
292 # include "mozilla/CodeCoverageHandler.h"
293 #endif
295 extern mozilla::LazyLogModule gSHIPBFCacheLog;
297 using namespace mozilla;
298 using namespace mozilla::dom::ipc;
299 using namespace mozilla::media;
300 using namespace mozilla::embedding;
301 using namespace mozilla::gmp;
302 using namespace mozilla::hal_sandbox;
303 using namespace mozilla::ipc;
304 using namespace mozilla::intl;
305 using namespace mozilla::layers;
306 using namespace mozilla::layout;
307 using namespace mozilla::net;
308 using namespace mozilla::widget;
309 using mozilla::loader::PScriptCacheChild;
311 namespace geckoprofiler::markers {
312 struct ProcessPriorityChange {
313 static constexpr Span<const char> MarkerTypeName() {
314 return MakeStringSpan("ProcessPriorityChange");
316 static void StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter& aWriter,
317 const ProfilerString8View& aPreviousPriority,
318 const ProfilerString8View& aNewPriority) {
319 aWriter.StringProperty("Before", aPreviousPriority);
320 aWriter.StringProperty("After", aNewPriority);
322 static MarkerSchema MarkerTypeDisplay() {
323 using MS = MarkerSchema;
324 MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable};
325 schema.AddKeyFormat("Before", MS::Format::String);
326 schema.AddKeyFormat("After", MS::Format::String);
327 schema.AddStaticLabelValue("Note",
328 "This is a notification of the priority change "
329 "that was done by the parent process");
330 schema.SetAllLabels(
331 "priority: {marker.data.Before} -> {marker.data.After}");
332 return schema;
336 struct ProcessPriority {
337 static constexpr Span<const char> MarkerTypeName() {
338 return MakeStringSpan("ProcessPriority");
340 static void StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter& aWriter,
341 const ProfilerString8View& aPriority,
342 const ProfilingState& aProfilingState) {
343 aWriter.StringProperty("Priority", aPriority);
344 aWriter.StringProperty("Marker cause",
345 ProfilerString8View::WrapNullTerminatedString(
346 ProfilingStateToString(aProfilingState)));
348 static MarkerSchema MarkerTypeDisplay() {
349 using MS = MarkerSchema;
350 MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable};
351 schema.AddKeyFormat("Priority", MS::Format::String);
352 schema.AddKeyFormat("Marker cause", MS::Format::String);
353 schema.SetAllLabels("priority: {marker.data.Priority}");
354 return schema;
357 } // namespace geckoprofiler::markers
359 namespace mozilla {
360 namespace dom {
362 // IPC sender for remote GC/CC logging.
363 class CycleCollectWithLogsChild final : public PCycleCollectWithLogsChild {
364 public:
365 NS_INLINE_DECL_REFCOUNTING(CycleCollectWithLogsChild)
367 class Sink final : public nsICycleCollectorLogSink {
368 NS_DECL_ISUPPORTS
370 Sink(CycleCollectWithLogsChild* aActor, const FileDescriptor& aGCLog,
371 const FileDescriptor& aCCLog) {
372 mActor = aActor;
373 mGCLog = FileDescriptorToFILE(aGCLog, "w");
374 mCCLog = FileDescriptorToFILE(aCCLog, "w");
377 NS_IMETHOD Open(FILE** aGCLog, FILE** aCCLog) override {
378 if (NS_WARN_IF(!mGCLog) || NS_WARN_IF(!mCCLog)) {
379 return NS_ERROR_FAILURE;
381 *aGCLog = mGCLog;
382 *aCCLog = mCCLog;
383 return NS_OK;
386 NS_IMETHOD CloseGCLog() override {
387 MOZ_ASSERT(mGCLog);
388 fclose(mGCLog);
389 mGCLog = nullptr;
390 mActor->SendCloseGCLog();
391 return NS_OK;
394 NS_IMETHOD CloseCCLog() override {
395 MOZ_ASSERT(mCCLog);
396 fclose(mCCLog);
397 mCCLog = nullptr;
398 mActor->SendCloseCCLog();
399 return NS_OK;
402 NS_IMETHOD GetFilenameIdentifier(nsAString& aIdentifier) override {
403 return UnimplementedProperty();
406 NS_IMETHOD SetFilenameIdentifier(const nsAString& aIdentifier) override {
407 return UnimplementedProperty();
410 NS_IMETHOD GetProcessIdentifier(int32_t* aIdentifier) override {
411 return UnimplementedProperty();
414 NS_IMETHOD SetProcessIdentifier(int32_t aIdentifier) override {
415 return UnimplementedProperty();
418 NS_IMETHOD GetGcLog(nsIFile** aPath) override {
419 return UnimplementedProperty();
422 NS_IMETHOD GetCcLog(nsIFile** aPath) override {
423 return UnimplementedProperty();
426 private:
427 ~Sink() {
428 if (mGCLog) {
429 fclose(mGCLog);
430 mGCLog = nullptr;
432 if (mCCLog) {
433 fclose(mCCLog);
434 mCCLog = nullptr;
436 // The XPCOM refcount drives the IPC lifecycle;
437 Unused << mActor->Send__delete__(mActor);
440 nsresult UnimplementedProperty() {
441 MOZ_ASSERT(false,
442 "This object is a remote GC/CC logger;"
443 " this property isn't meaningful.");
444 return NS_ERROR_UNEXPECTED;
447 RefPtr<CycleCollectWithLogsChild> mActor;
448 FILE* mGCLog;
449 FILE* mCCLog;
452 private:
453 ~CycleCollectWithLogsChild() = default;
456 NS_IMPL_ISUPPORTS(CycleCollectWithLogsChild::Sink, nsICycleCollectorLogSink);
458 class ConsoleListener final : public nsIConsoleListener {
459 public:
460 explicit ConsoleListener(ContentChild* aChild) : mChild(aChild) {}
462 NS_DECL_ISUPPORTS
463 NS_DECL_NSICONSOLELISTENER
465 private:
466 ~ConsoleListener() = default;
468 ContentChild* mChild;
469 friend class ContentChild;
472 NS_IMPL_ISUPPORTS(ConsoleListener, nsIConsoleListener)
474 // Before we send the error to the parent process (which
475 // involves copying the memory), truncate any long lines. CSS
476 // errors in particular share the memory for long lines with
477 // repeated errors, but the IPC communication we're about to do
478 // will break that sharing, so we better truncate now.
479 template <typename CharT>
480 static void TruncateString(nsTSubstring<CharT>& aString) {
481 if (aString.Length() > 1000) {
482 aString.Truncate(1000);
486 NS_IMETHODIMP
487 ConsoleListener::Observe(nsIConsoleMessage* aMessage) {
488 if (!mChild) {
489 return NS_OK;
492 nsCOMPtr<nsIScriptError> scriptError = do_QueryInterface(aMessage);
493 if (scriptError) {
494 nsAutoString msg;
495 nsAutoCString sourceName;
496 nsCString category;
497 uint32_t lineNum, colNum, flags;
498 bool fromPrivateWindow, fromChromeContext;
500 nsresult rv = scriptError->GetErrorMessage(msg);
501 NS_ENSURE_SUCCESS(rv, rv);
502 TruncateString(msg);
503 rv = scriptError->GetSourceName(sourceName);
504 NS_ENSURE_SUCCESS(rv, rv);
505 TruncateString(sourceName);
507 rv = scriptError->GetCategory(getter_Copies(category));
508 NS_ENSURE_SUCCESS(rv, rv);
509 rv = scriptError->GetLineNumber(&lineNum);
510 NS_ENSURE_SUCCESS(rv, rv);
511 rv = scriptError->GetColumnNumber(&colNum);
512 NS_ENSURE_SUCCESS(rv, rv);
513 rv = scriptError->GetFlags(&flags);
514 NS_ENSURE_SUCCESS(rv, rv);
515 rv = scriptError->GetIsFromPrivateWindow(&fromPrivateWindow);
516 NS_ENSURE_SUCCESS(rv, rv);
517 rv = scriptError->GetIsFromChromeContext(&fromChromeContext);
518 NS_ENSURE_SUCCESS(rv, rv);
521 AutoJSAPI jsapi;
522 jsapi.Init();
523 JSContext* cx = jsapi.cx();
525 JS::Rooted<JS::Value> stack(cx);
526 rv = scriptError->GetStack(&stack);
527 NS_ENSURE_SUCCESS(rv, rv);
529 if (stack.isObject()) {
530 // Because |stack| might be a cross-compartment wrapper, we can't use it
531 // with JSAutoRealm. Use the stackGlobal for that.
532 JS::Rooted<JS::Value> stackGlobal(cx);
533 rv = scriptError->GetStackGlobal(&stackGlobal);
534 NS_ENSURE_SUCCESS(rv, rv);
536 JSAutoRealm ar(cx, &stackGlobal.toObject());
538 StructuredCloneData data;
539 ErrorResult err;
540 data.Write(cx, stack, err);
541 if (err.Failed()) {
542 return err.StealNSResult();
545 ClonedMessageData cloned;
546 if (!data.BuildClonedMessageData(cloned)) {
547 return NS_ERROR_FAILURE;
550 mChild->SendScriptErrorWithStack(msg, sourceName, lineNum, colNum,
551 flags, category, fromPrivateWindow,
552 fromChromeContext, cloned);
553 return NS_OK;
557 mChild->SendScriptError(msg, sourceName, lineNum, colNum, flags, category,
558 fromPrivateWindow, 0, fromChromeContext);
559 return NS_OK;
562 nsString msg;
563 nsresult rv = aMessage->GetMessageMoz(msg);
564 NS_ENSURE_SUCCESS(rv, rv);
565 mChild->SendConsoleMessage(msg);
566 return NS_OK;
569 #ifdef NIGHTLY_BUILD
571 * The singleton of this class is registered with the BackgroundHangMonitor as
572 * an annotator, so that the hang monitor can record whether or not there were
573 * pending input events when the thread hung.
575 class PendingInputEventHangAnnotator final : public BackgroundHangAnnotator {
576 public:
577 virtual void AnnotateHang(BackgroundHangAnnotations& aAnnotations) override {
578 int32_t pending = ContentChild::GetSingleton()->GetPendingInputEvents();
579 if (pending > 0) {
580 aAnnotations.AddAnnotation(u"PendingInput"_ns, pending);
584 static PendingInputEventHangAnnotator sSingleton;
586 PendingInputEventHangAnnotator PendingInputEventHangAnnotator::sSingleton;
587 #endif
589 class ContentChild::ShutdownCanary final {};
591 ContentChild* ContentChild::sSingleton;
592 StaticAutoPtr<ContentChild::ShutdownCanary> ContentChild::sShutdownCanary;
594 ContentChild::ContentChild()
595 : mIsForBrowser(false), mIsAlive(true), mShuttingDown(false) {
596 // This process is a content process, so it's clearly running in
597 // multiprocess mode!
598 nsDebugImpl::SetMultiprocessMode("Child");
600 // Our static analysis doesn't allow capturing ref-counted pointers in
601 // lambdas, so we need to hide it in a uintptr_t. This is safe because this
602 // lambda will be destroyed in ~ContentChild().
603 uintptr_t self = reinterpret_cast<uintptr_t>(this);
604 profiler_add_state_change_callback(
605 AllProfilingStates(),
606 [self](ProfilingState aProfilingState) {
607 const ContentChild* selfPtr =
608 reinterpret_cast<const ContentChild*>(self);
609 PROFILER_MARKER("Process Priority", OTHER,
610 mozilla::MarkerThreadId::MainThread(), ProcessPriority,
611 ProfilerString8View::WrapNullTerminatedString(
612 ProcessPriorityToString(selfPtr->mProcessPriority)),
613 aProfilingState);
615 self);
617 // When ContentChild is created, the observer service does not even exist.
618 // When ContentChild::RecvSetXPCOMProcessAttributes is called (the first
619 // IPDL call made on this object), shutdown may have already happened. Thus
620 // we create a canary here that relies upon getting cleared if shutdown
621 // happens without requiring the observer service at this time.
622 if (!sShutdownCanary) {
623 sShutdownCanary = new ShutdownCanary();
624 ClearOnShutdown(&sShutdownCanary, ShutdownPhase::XPCOMShutdown);
628 #ifdef _MSC_VER
629 # pragma warning(push)
630 # pragma warning( \
631 disable : 4722) /* Silence "destructor never returns" warning \
633 #endif
635 ContentChild::~ContentChild() {
636 profiler_remove_state_change_callback(reinterpret_cast<uintptr_t>(this));
638 #ifndef NS_FREE_PERMANENT_DATA
639 MOZ_CRASH("Content Child shouldn't be destroyed.");
640 #endif
643 #ifdef _MSC_VER
644 # pragma warning(pop)
645 #endif
647 NS_INTERFACE_MAP_BEGIN(ContentChild)
648 NS_INTERFACE_MAP_ENTRY(nsIDOMProcessChild)
649 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMProcessChild)
650 NS_INTERFACE_MAP_END
652 mozilla::ipc::IPCResult ContentChild::RecvSetXPCOMProcessAttributes(
653 XPCOMInitData&& aXPCOMInit, const StructuredCloneData& aInitialData,
654 FullLookAndFeel&& aLookAndFeelData, dom::SystemFontList&& aFontList,
655 Maybe<SharedMemoryHandle>&& aSharedUASheetHandle,
656 const uintptr_t& aSharedUASheetAddress,
657 nsTArray<SharedMemoryHandle>&& aSharedFontListBlocks,
658 const bool& aIsReadyForBackgroundProcessing) {
659 if (!sShutdownCanary) {
660 return IPC_OK();
663 mLookAndFeelData = std::move(aLookAndFeelData);
664 mFontList = std::move(aFontList);
665 mSharedFontListBlocks = std::move(aSharedFontListBlocks);
667 gfx::gfxVars::SetValuesForInitialize(aXPCOMInit.gfxNonDefaultVarUpdates());
668 PerfStats::SetCollectionMask(aXPCOMInit.perfStatsMask());
669 InitSharedUASheets(std::move(aSharedUASheetHandle), aSharedUASheetAddress);
670 InitXPCOM(std::move(aXPCOMInit), aInitialData,
671 aIsReadyForBackgroundProcessing);
672 InitGraphicsDeviceData(aXPCOMInit.contentDeviceData());
673 RefPtr<net::ChildDNSService> dnsServiceChild =
674 dont_AddRef(net::ChildDNSService::GetSingleton());
675 if (dnsServiceChild) {
676 dnsServiceChild->SetTRRDomain(aXPCOMInit.trrDomain());
677 dnsServiceChild->SetTRRModeInChild(aXPCOMInit.trrMode(),
678 aXPCOMInit.trrModeFromPref());
680 return IPC_OK();
683 class nsGtkNativeInitRunnable : public Runnable {
684 public:
685 nsGtkNativeInitRunnable() : Runnable("nsGtkNativeInitRunnable") {}
687 NS_IMETHOD Run() override {
688 LookAndFeel::NativeInit();
689 return NS_OK;
693 void ContentChild::Init(mozilla::ipc::UntypedEndpoint&& aEndpoint,
694 const char* aParentBuildID, bool aIsForBrowser) {
695 #ifdef MOZ_WIDGET_GTK
696 // When running X11 only build we need to pass a display down
697 // to gtk_init because it's not going to use the one from the environment
698 // on its own when deciding which backend to use, and when starting under
699 // XWayland, it may choose to start with the wayland backend
700 // instead of the x11 backend.
701 // The DISPLAY environment variable is normally set by the parent process.
702 // The MOZ_GDK_DISPLAY environment variable is set from nsAppRunner.cpp
703 // when --display is set by the command line.
704 if (!gfxPlatform::IsHeadless()) {
705 const char* display_name = PR_GetEnv("MOZ_GDK_DISPLAY");
706 if (!display_name) {
707 bool waylandEnabled = false;
708 # ifdef MOZ_WAYLAND
709 waylandEnabled = IsWaylandEnabled();
710 # endif
711 if (!waylandEnabled) {
712 display_name = PR_GetEnv("DISPLAY");
715 if (display_name) {
716 int argc = 3;
717 char option_name[] = "--display";
718 char* argv[] = {
719 // argv0 is unused because g_set_prgname() was called in
720 // XRE_InitChildProcess().
721 nullptr, option_name, const_cast<char*>(display_name), nullptr};
722 char** argvp = argv;
723 gtk_init(&argc, &argvp);
724 } else {
725 gtk_init(nullptr, nullptr);
728 #endif
730 #ifdef MOZ_X11
731 if (!gfxPlatform::IsHeadless()) {
732 // Do this after initializing GDK, or GDK will install its own handler.
733 XRE_InstallX11ErrorHandler();
735 #endif
737 MOZ_ASSERT(!sSingleton, "only one ContentChild per child");
739 // Once we start sending IPC messages, we need the thread manager to be
740 // initialized so we can deal with the responses. Do that here before we
741 // try to construct the crash reporter.
742 nsresult rv = nsThreadManager::get().Init();
743 if (NS_WARN_IF(NS_FAILED(rv))) {
744 MOZ_CRASH("Failed to initialize the thread manager in ContentChild::Init");
747 if (!aEndpoint.Bind(this)) {
748 MOZ_CRASH("Bind failed in ContentChild::Init");
750 sSingleton = this;
752 // If communications with the parent have broken down, take the process
753 // down so it's not hanging around.
754 GetIPCChannel()->SetAbortOnError(true);
756 // This must be checked before any IPDL message, which may hit sentinel
757 // errors due to parent and content processes having different
758 // versions.
759 MessageChannel* channel = GetIPCChannel();
760 if (channel && !channel->SendBuildIDsMatchMessage(aParentBuildID)) {
761 // We need to quit this process if the buildID doesn't match the parent's.
762 // This can occur when an update occurred in the background.
763 ProcessChild::QuickExit();
766 #if defined(__OpenBSD__) && defined(MOZ_SANDBOX)
767 StartOpenBSDSandbox(GeckoProcessType_Content);
768 #endif
770 #ifdef MOZ_X11
771 # ifdef MOZ_WIDGET_GTK
772 if (GdkIsX11Display() && !gfxPlatform::IsHeadless()) {
773 // Send the parent our X socket to act as a proxy reference for our X
774 // resources.
775 int xSocketFd = ConnectionNumber(DefaultXDisplay());
776 SendBackUpXResources(FileDescriptor(xSocketFd));
778 # endif
779 #endif
781 CrashReporterClient::InitSingleton(this);
783 mIsForBrowser = aIsForBrowser;
785 SetProcessName("Web Content"_ns);
787 #ifdef NIGHTLY_BUILD
788 // NOTE: We have to register the annotator on the main thread, as annotators
789 // only affect a single thread.
790 SchedulerGroup::Dispatch(
791 NS_NewRunnableFunction("RegisterPendingInputEventHangAnnotator", [] {
792 BackgroundHangMonitor::RegisterAnnotator(
793 PendingInputEventHangAnnotator::sSingleton);
794 }));
795 #endif
797 #if defined(MOZ_MEMORY) && defined(DEBUG) && !defined(MOZ_UBSAN)
798 jemalloc_stats_t stats;
799 jemalloc_stats(&stats);
800 MOZ_ASSERT(!stats.opt_randomize_small,
801 "Content process should not randomize small allocations");
802 #endif
805 void ContentChild::AddProfileToProcessName(const nsACString& aProfile) {
806 nsCOMPtr<nsIPrincipal> isolationPrincipal =
807 ContentParent::CreateRemoteTypeIsolationPrincipal(mRemoteType);
808 if (isolationPrincipal) {
809 if (isolationPrincipal->OriginAttributesRef().IsPrivateBrowsing()) {
810 return;
814 mProcessName = aProfile + ":"_ns + mProcessName; //<profile_name>:example.com
817 void ContentChild::SetProcessName(const nsACString& aName,
818 const nsACString* aSite,
819 const nsACString* aCurrentProfile) {
820 char* name;
821 if ((name = PR_GetEnv("MOZ_DEBUG_APP_PROCESS")) && aName.EqualsASCII(name)) {
822 #ifdef XP_UNIX
823 printf_stderr("\n\nCHILDCHILDCHILDCHILD\n [%s] debug me @%d\n\n", name,
824 getpid());
825 sleep(30);
826 #elif defined(XP_WIN)
827 // Windows has a decent JIT debugging story, so NS_DebugBreak does the
828 // right thing.
829 NS_DebugBreak(NS_DEBUG_BREAK,
830 "Invoking NS_DebugBreak() to debug child process", nullptr,
831 __FILE__, __LINE__);
832 #endif
835 if (aSite) {
836 profiler_set_process_name(aName, aSite);
837 } else {
838 profiler_set_process_name(aName);
841 mProcessName = aName;
843 // Requires pref flip
844 if (aSite && StaticPrefs::fission_processSiteNames()) {
845 nsCOMPtr<nsIPrincipal> isolationPrincipal =
846 ContentParent::CreateRemoteTypeIsolationPrincipal(mRemoteType);
847 if (isolationPrincipal) {
848 // DEFAULT_PRIVATE_BROWSING_ID is the value when it's not private
849 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
850 ("private = %d, pref = %d",
851 isolationPrincipal->OriginAttributesRef().IsPrivateBrowsing(),
852 StaticPrefs::fission_processPrivateWindowSiteNames()));
853 if (!isolationPrincipal->OriginAttributesRef().IsPrivateBrowsing()
854 #ifdef NIGHTLY_BUILD
855 // Nightly can show site names for private windows, with a second pref
856 || StaticPrefs::fission_processPrivateWindowSiteNames()
857 #endif
859 #if !defined(XP_MACOSX)
860 // Mac doesn't have the 15-character limit Linux does
861 // Sets profiler process name
862 if (isolationPrincipal->SchemeIs("https")) {
863 nsAutoCString schemeless;
864 isolationPrincipal->GetHostPort(schemeless);
865 nsAutoCString originSuffix;
866 isolationPrincipal->GetOriginSuffix(originSuffix);
867 schemeless.Append(originSuffix);
868 mProcessName = schemeless;
869 } else
870 #endif
872 mProcessName = *aSite;
878 if (StaticPrefs::fission_processProfileName() && aCurrentProfile &&
879 !aCurrentProfile->IsEmpty()) {
880 AddProfileToProcessName(*aCurrentProfile);
883 // else private window, don't change process name, or the pref isn't set
884 // mProcessName is always flat (mProcessName == aName)
886 mozilla::ipc::SetThisProcessName(mProcessName.get());
888 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
889 ("Changed name of process %d to %s", getpid(),
890 PromiseFlatCString(mProcessName).get()));
893 static nsresult GetCreateWindowParams(nsIOpenWindowInfo* aOpenWindowInfo,
894 nsDocShellLoadState* aLoadState,
895 bool aForceNoReferrer,
896 nsIReferrerInfo** aReferrerInfo,
897 nsIPrincipal** aTriggeringPrincipal,
898 nsIContentSecurityPolicy** aCsp) {
899 if (!aTriggeringPrincipal || !aCsp) {
900 NS_ERROR("aTriggeringPrincipal || aCsp is null");
901 return NS_ERROR_FAILURE;
904 if (!aReferrerInfo) {
905 NS_ERROR("aReferrerInfo is null");
906 return NS_ERROR_FAILURE;
909 nsCOMPtr<nsIReferrerInfo> referrerInfo;
910 if (aForceNoReferrer) {
911 referrerInfo = new ReferrerInfo(nullptr, ReferrerPolicy::_empty, false);
913 if (aLoadState && !referrerInfo) {
914 referrerInfo = aLoadState->GetReferrerInfo();
917 RefPtr<BrowsingContext> parent = aOpenWindowInfo->GetParent();
918 nsCOMPtr<nsPIDOMWindowOuter> opener =
919 parent ? parent->GetDOMWindow() : nullptr;
920 if (!opener) {
921 nsCOMPtr<nsIPrincipal> nullPrincipal =
922 NullPrincipal::Create(aOpenWindowInfo->GetOriginAttributes());
923 if (!referrerInfo) {
924 referrerInfo = new ReferrerInfo(nullptr, ReferrerPolicy::_empty);
927 referrerInfo.swap(*aReferrerInfo);
928 NS_ADDREF(*aTriggeringPrincipal = nullPrincipal);
929 return NS_OK;
932 nsCOMPtr<Document> doc = opener->GetDoc();
933 NS_ADDREF(*aTriggeringPrincipal = doc->NodePrincipal());
935 nsCOMPtr<nsIContentSecurityPolicy> csp = doc->GetCsp();
936 if (csp) {
937 csp.forget(aCsp);
940 nsCOMPtr<nsIURI> baseURI = doc->GetDocBaseURI();
941 if (!baseURI) {
942 NS_ERROR("Document didn't return a base URI");
943 return NS_ERROR_FAILURE;
946 if (!referrerInfo) {
947 referrerInfo = new ReferrerInfo(*doc);
950 referrerInfo.swap(*aReferrerInfo);
951 return NS_OK;
954 nsresult ContentChild::ProvideWindowCommon(
955 NotNull<BrowserChild*> aTabOpener, nsIOpenWindowInfo* aOpenWindowInfo,
956 uint32_t aChromeFlags, bool aCalledFromJS, nsIURI* aURI,
957 const nsAString& aName, const nsACString& aFeatures,
958 const UserActivation::Modifiers& aModifiers, bool aForceNoOpener,
959 bool aForceNoReferrer, bool aIsPopupRequested,
960 nsDocShellLoadState* aLoadState, bool* aWindowIsNew,
961 BrowsingContext** aReturn) {
962 *aReturn = nullptr;
964 nsAutoCString features(aFeatures);
965 nsAutoString name(aName);
967 nsresult rv;
969 RefPtr<BrowsingContext> parent = aOpenWindowInfo->GetParent();
970 MOZ_DIAGNOSTIC_ASSERT(parent, "We must have a parent BC");
972 // Block the attempt to open a new window if the opening BrowsingContext is
973 // not marked to use remote tabs. This ensures that the newly opened window is
974 // correctly remote.
975 if (NS_WARN_IF(!parent->UseRemoteTabs())) {
976 return NS_ERROR_ABORT;
979 bool useRemoteSubframes =
980 aChromeFlags & nsIWebBrowserChrome::CHROME_FISSION_WINDOW;
982 uint32_t parentSandboxFlags = parent->SandboxFlags();
983 Document* doc = parent->GetDocument();
984 if (doc) {
985 parentSandboxFlags = doc->GetSandboxFlags();
988 const bool isForPrinting = aOpenWindowInfo->GetIsForPrinting();
989 // Certain conditions complicate the process of creating the new
990 // BrowsingContext, and prevent us from using the
991 // "CreateWindowInDifferentProcess" codepath.
992 // * With Fission enabled, process selection will happen during the load, so
993 // switching processes eagerly will not provide a benefit.
994 // * Windows created for printing must be created within the current process
995 // so that a static clone of the source document can be created.
996 // * Sandboxed popups require the full window creation codepath.
997 // * Loads with form or POST data require the full window creation codepath.
998 const bool cannotLoadInDifferentProcess =
999 useRemoteSubframes || isForPrinting ||
1000 (parentSandboxFlags &
1001 SANDBOX_PROPAGATES_TO_AUXILIARY_BROWSING_CONTEXTS) ||
1002 (aLoadState &&
1003 (aLoadState->IsFormSubmission() || aLoadState->PostDataStream()));
1004 if (!cannotLoadInDifferentProcess) {
1005 // If we're in a content process and we have noopener set, there's no reason
1006 // to load in our process, so let's load it elsewhere!
1007 bool loadInDifferentProcess =
1008 aForceNoOpener && StaticPrefs::dom_noopener_newprocess_enabled();
1009 if (loadInDifferentProcess) {
1010 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
1011 nsCOMPtr<nsIContentSecurityPolicy> csp;
1012 nsCOMPtr<nsIReferrerInfo> referrerInfo;
1013 rv = GetCreateWindowParams(aOpenWindowInfo, aLoadState, aForceNoReferrer,
1014 getter_AddRefs(referrerInfo),
1015 getter_AddRefs(triggeringPrincipal),
1016 getter_AddRefs(csp));
1017 if (NS_WARN_IF(NS_FAILED(rv))) {
1018 return rv;
1021 if (name.LowerCaseEqualsLiteral("_blank")) {
1022 name.Truncate();
1025 MOZ_DIAGNOSTIC_ASSERT(!nsContentUtils::IsSpecialName(name));
1027 const bool hasValidUserGestureActivation = [aLoadState, doc] {
1028 if (aLoadState) {
1029 return aLoadState->HasValidUserGestureActivation();
1031 if (doc) {
1032 return doc->HasValidTransientUserGestureActivation();
1034 return false;
1035 }();
1037 const bool textDirectiveUserActivation = [aLoadState, doc] {
1038 if (doc && doc->ConsumeTextDirectiveUserActivation()) {
1039 return true;
1041 if (aLoadState) {
1042 return aLoadState->GetTextDirectiveUserActivation();
1044 return false;
1045 }() || hasValidUserGestureActivation;
1047 Unused << SendCreateWindowInDifferentProcess(
1048 aTabOpener, parent, aChromeFlags, aCalledFromJS,
1049 aOpenWindowInfo->GetIsTopLevelCreatedByWebContent(), aURI, features,
1050 aModifiers, name, triggeringPrincipal, csp, referrerInfo,
1051 aOpenWindowInfo->GetOriginAttributes(), hasValidUserGestureActivation,
1052 textDirectiveUserActivation);
1054 // We return NS_ERROR_ABORT, so that the caller knows that we've abandoned
1055 // the window open as far as it is concerned.
1056 return NS_ERROR_ABORT;
1060 TabId tabId(nsContentUtils::GenerateTabId());
1062 // We need to assign a TabGroup to the PBrowser actor before we send it to the
1063 // parent. Otherwise, the parent could send messages to us before we have a
1064 // proper TabGroup for that actor.
1065 RefPtr<BrowsingContext> openerBC;
1066 if (!aForceNoOpener) {
1067 openerBC = parent;
1070 RefPtr<BrowsingContext> browsingContext = BrowsingContext::CreateDetached(
1071 nullptr, openerBC, nullptr, aName, BrowsingContext::Type::Content,
1072 BrowsingContext::CreateDetachedOptions{
1073 .isPopupRequested = aIsPopupRequested,
1074 .topLevelCreatedByWebContent = true,
1075 .isForPrinting = isForPrinting,
1077 MOZ_ALWAYS_SUCCEEDS(browsingContext->SetRemoteTabs(true));
1078 MOZ_ALWAYS_SUCCEEDS(browsingContext->SetRemoteSubframes(useRemoteSubframes));
1079 MOZ_ALWAYS_SUCCEEDS(browsingContext->SetOriginAttributes(
1080 aOpenWindowInfo->GetOriginAttributes()));
1082 browsingContext->InitPendingInitialization(true);
1083 auto unsetPending = MakeScopeExit([browsingContext]() {
1084 Unused << browsingContext->SetPendingInitialization(false);
1087 browsingContext->EnsureAttached();
1089 // The initial about:blank document we generate within the nsDocShell will
1090 // almost certainly be replaced at some point. Unfortunately, getting the
1091 // principal right here causes bugs due to frame scripts not getting events
1092 // they expect, due to the real initial about:blank not being created yet.
1094 // For this reason, we intentionally mispredict the initial principal here, so
1095 // that we can act the same as we did before when not predicting a result
1096 // principal. This `PWindowGlobal` will almost immediately be destroyed.
1097 nsCOMPtr<nsIPrincipal> initialPrincipal =
1098 NullPrincipal::Create(browsingContext->OriginAttributesRef());
1099 WindowGlobalInit windowInit = WindowGlobalActor::AboutBlankInitializer(
1100 browsingContext, initialPrincipal);
1102 RefPtr<WindowGlobalChild> windowChild =
1103 WindowGlobalChild::CreateDisconnected(windowInit);
1104 if (NS_WARN_IF(!windowChild)) {
1105 return NS_ERROR_ABORT;
1108 auto newChild = MakeNotNull<RefPtr<BrowserChild>>(
1109 this, tabId, *aTabOpener, browsingContext, aChromeFlags,
1110 /* aIsTopLevel */ true);
1112 if (IsShuttingDown()) {
1113 return NS_ERROR_ABORT;
1116 // Open a remote endpoint for our PBrowser actor.
1117 ManagedEndpoint<PBrowserParent> parentEp = OpenPBrowserEndpoint(newChild);
1118 if (NS_WARN_IF(!parentEp.IsValid())) {
1119 return NS_ERROR_ABORT;
1122 // Open a remote endpoint for our PWindowGlobal actor.
1123 ManagedEndpoint<PWindowGlobalParent> windowParentEp =
1124 newChild->OpenPWindowGlobalEndpoint(windowChild);
1125 if (NS_WARN_IF(!windowParentEp.IsValid())) {
1126 return NS_ERROR_ABORT;
1129 // Tell the parent process to set up its PBrowserParent.
1130 PopupIPCTabContext ipcContext(aTabOpener, 0);
1131 if (NS_WARN_IF(!SendConstructPopupBrowser(
1132 std::move(parentEp), std::move(windowParentEp), tabId, ipcContext,
1133 windowInit, aChromeFlags))) {
1134 return NS_ERROR_ABORT;
1137 windowChild->Init();
1138 auto guardNullWindowGlobal = MakeScopeExit([&] {
1139 if (!windowChild->GetWindowGlobal()) {
1140 windowChild->Destroy();
1144 // Now that |newChild| has had its IPC link established, call |Init| to set it
1145 // up.
1146 // XXX: This MOZ_KnownLive is only necessary because the static analysis can't
1147 // tell that NotNull<RefPtr<BrowserChild>> is a strong pointer.
1148 RefPtr<nsPIDOMWindowOuter> parentWindow =
1149 parent ? parent->GetDOMWindow() : nullptr;
1150 if (NS_FAILED(MOZ_KnownLive(newChild)->Init(parentWindow, windowChild))) {
1151 return NS_ERROR_ABORT;
1154 // Set to true when we're ready to return from this function.
1155 bool ready = false;
1157 // NOTE: Capturing by reference here is safe, as this function won't return
1158 // until one of these callbacks is called.
1159 auto resolve = [&](CreatedWindowInfo&& info) {
1160 MOZ_RELEASE_ASSERT(NS_IsMainThread());
1161 rv = info.rv();
1162 *aWindowIsNew = info.windowOpened();
1163 nsTArray<FrameScriptInfo> frameScripts(std::move(info.frameScripts()));
1164 uint32_t maxTouchPoints = info.maxTouchPoints();
1165 DimensionInfo dimensionInfo = std::move(info.dimensions());
1167 // Once this function exits, we should try to exit the nested event loop.
1168 ready = true;
1170 // NOTE: We have to handle this immediately in the resolve callback in order
1171 // to make sure that we don't process any more IPC messages before returning
1172 // from ProvideWindowCommon.
1174 // Handle the error which we got back from the parent process, if we got
1175 // one.
1176 if (NS_FAILED(rv)) {
1177 return;
1180 if (!*aWindowIsNew) {
1181 rv = NS_ERROR_ABORT;
1182 return;
1185 // If the BrowserChild has been torn down, we don't need to do this anymore.
1186 if (NS_WARN_IF(!newChild->IPCOpen() || newChild->IsDestroyed())) {
1187 rv = NS_ERROR_ABORT;
1188 return;
1191 ParentShowInfo showInfo(u""_ns, /* fakeShowInfo = */ true,
1192 /* isTransparent = */ false,
1193 newChild->WebWidget()->GetDPI(),
1194 newChild->WebWidget()->RoundsWidgetCoordinatesTo(),
1195 newChild->WebWidget()->GetDefaultScale().scale);
1197 newChild->SetMaxTouchPoints(maxTouchPoints);
1199 if (aForceNoOpener || !parent) {
1200 MOZ_DIAGNOSTIC_ASSERT(!browsingContext->HadOriginalOpener());
1201 MOZ_DIAGNOSTIC_ASSERT(browsingContext->GetTopLevelCreatedByWebContent());
1202 MOZ_DIAGNOSTIC_ASSERT(browsingContext->GetOpenerId() == 0);
1203 } else {
1204 MOZ_DIAGNOSTIC_ASSERT(browsingContext->HadOriginalOpener());
1205 MOZ_DIAGNOSTIC_ASSERT(browsingContext->GetTopLevelCreatedByWebContent());
1206 MOZ_DIAGNOSTIC_ASSERT(browsingContext->GetOpenerId() == parent->Id());
1209 // Unfortunately we don't get a window unless we've shown the frame. That's
1210 // pretty bogus; see bug 763602.
1211 newChild->DoFakeShow(showInfo);
1213 newChild->RecvUpdateDimensions(dimensionInfo);
1215 for (size_t i = 0; i < frameScripts.Length(); i++) {
1216 FrameScriptInfo& info = frameScripts[i];
1217 if (!newChild->RecvLoadRemoteScript(info.url(),
1218 info.runInGlobalScope())) {
1219 MOZ_CRASH();
1223 if (xpc::IsInAutomation()) {
1224 if (nsCOMPtr<nsPIDOMWindowOuter> outer =
1225 do_GetInterface(newChild->WebNavigation())) {
1226 nsCOMPtr<nsIObserverService> obs(services::GetObserverService());
1227 obs->NotifyObservers(
1228 outer, "dangerous:test-only:new-browser-child-ready", nullptr);
1232 browsingContext.forget(aReturn);
1235 // NOTE: Capturing by reference here is safe, as this function won't return
1236 // until one of these callbacks is called.
1237 auto reject = [&](ResponseRejectReason) {
1238 MOZ_RELEASE_ASSERT(NS_IsMainThread());
1239 NS_WARNING("windowCreated promise rejected");
1240 rv = NS_ERROR_NOT_AVAILABLE;
1241 ready = true;
1244 // Send down the request to open the window.
1245 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
1246 nsCOMPtr<nsIContentSecurityPolicy> csp;
1247 nsCOMPtr<nsIReferrerInfo> referrerInfo;
1248 rv = GetCreateWindowParams(aOpenWindowInfo, aLoadState, aForceNoReferrer,
1249 getter_AddRefs(referrerInfo),
1250 getter_AddRefs(triggeringPrincipal),
1251 getter_AddRefs(csp));
1252 if (NS_WARN_IF(NS_FAILED(rv))) {
1253 return rv;
1256 SendCreateWindow(
1257 aTabOpener, parent, newChild, aChromeFlags, aCalledFromJS,
1258 aOpenWindowInfo->GetIsForPrinting(),
1259 aOpenWindowInfo->GetIsForWindowDotPrint(),
1260 aOpenWindowInfo->GetIsTopLevelCreatedByWebContent(), aURI, features,
1261 aModifiers, triggeringPrincipal, csp, referrerInfo,
1262 aOpenWindowInfo->GetOriginAttributes(),
1263 aLoadState ? aLoadState->HasValidUserGestureActivation() : false,
1264 aLoadState ? aLoadState->GetTextDirectiveUserActivation() : false,
1265 std::move(resolve), std::move(reject));
1267 // =======================
1268 // Begin Nested Event Loop
1269 // =======================
1271 // We have to wait for a response from SendCreateWindow or with information
1272 // we're going to need to return from this function, So we spin a nested event
1273 // loop until they get back to us.
1276 // Suppress event handling for all contexts in our BrowsingContextGroup so
1277 // that event handlers cannot target our new window while it's still being
1278 // opened. Note that pending events that were suppressed while our blocker
1279 // was active will be dispatched asynchronously from a runnable dispatched
1280 // to the main event loop after this function returns, not immediately when
1281 // we leave this scope.
1282 AutoSuppressEventHandlingAndSuspend seh(browsingContext->Group());
1284 AutoNoJSAPI nojsapi;
1286 // Spin the event loop until we get a response. Callers of this function
1287 // already have to guard against an inner event loop spinning in the
1288 // non-e10s case because of the need to spin one to create a new chrome
1289 // window.
1290 SpinEventLoopUntil("ContentChild::ProvideWindowCommon"_ns,
1291 [&]() { return ready; });
1292 MOZ_RELEASE_ASSERT(ready,
1293 "We are on the main thread, so we should not exit this "
1294 "loop without ready being true.");
1297 // =====================
1298 // End Nested Event Loop
1299 // =====================
1301 // It's possible for our new BrowsingContext to become discarded during the
1302 // nested event loop, in which case we shouldn't return it, since our callers
1303 // will generally not be prepared to deal with that.
1304 if (*aReturn && (*aReturn)->IsDiscarded()) {
1305 NS_RELEASE(*aReturn);
1306 return NS_ERROR_ABORT;
1309 // We should have the results already set by the callbacks.
1310 MOZ_ASSERT_IF(NS_SUCCEEDED(rv), *aReturn);
1311 return rv;
1314 bool ContentChild::IsAlive() const { return mIsAlive; }
1316 bool ContentChild::IsShuttingDown() const { return mShuttingDown; }
1318 void ContentChild::GetProcessName(nsACString& aName) const {
1319 aName = mProcessName;
1322 /* static */
1323 void ContentChild::AppendProcessId(nsACString& aName) {
1324 if (!aName.IsEmpty()) {
1325 aName.Append(' ');
1327 unsigned pid = getpid();
1328 aName.Append(nsPrintfCString("(pid %u)", pid));
1331 void ContentChild::InitGraphicsDeviceData(const ContentDeviceData& aData) {
1332 gfxPlatform::InitChild(aData);
1335 void ContentChild::InitSharedUASheets(Maybe<SharedMemoryHandle>&& aHandle,
1336 uintptr_t aAddress) {
1337 MOZ_ASSERT_IF(!aHandle, !aAddress);
1339 if (!aAddress) {
1340 return;
1343 // Map the shared memory storing the user agent style sheets. Do this as
1344 // early as possible to maximize the chance of being able to map at the
1345 // address we want.
1346 GlobalStyleSheetCache::SetSharedMemory(std::move(*aHandle), aAddress);
1349 void ContentChild::InitXPCOM(
1350 XPCOMInitData&& aXPCOMInit,
1351 const mozilla::dom::ipc::StructuredCloneData& aInitialData,
1352 bool aIsReadyForBackgroundProcessing) {
1353 #ifdef MOZ_WIDGET_GTK
1354 // LookAndFeel::NativeInit takes a long time to run on Linux, here we schedule
1355 // it as soon as possible after BackgroundChild::Startup to give
1356 // it chance to run ahead of ConstructBrowser
1357 nsCOMPtr<nsIRunnable> event = new nsGtkNativeInitRunnable();
1358 NS_DispatchToMainThreadQueue(event.forget(), EventQueuePriority::Idle);
1359 #endif
1361 #if defined(XP_WIN)
1362 // DLL services untrusted modules processing depends on
1363 // BackgroundChild::Startup having been called
1364 RefPtr<DllServices> dllSvc(DllServices::Get());
1365 dllSvc->StartUntrustedModulesProcessor(aIsReadyForBackgroundProcessing);
1366 #endif // defined(XP_WIN)
1368 PBackgroundChild* actorChild = BackgroundChild::GetOrCreateForCurrentThread();
1369 if (NS_WARN_IF(!actorChild)) {
1370 MOZ_ASSERT_UNREACHABLE("PBackground init can't fail at this point");
1371 return;
1374 ClientManager::Startup();
1376 // RemoteWorkerService will be initialized in RecvRemoteType, to avoid to
1377 // register it to the RemoteWorkerManager while it is still a prealloc
1378 // remoteType and defer it to the point the child process is assigned a.
1379 // actual remoteType.
1381 nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
1382 if (!svc) {
1383 NS_WARNING("Couldn't acquire console service");
1384 return;
1387 mConsoleListener = new ConsoleListener(this);
1388 if (NS_FAILED(svc->RegisterListener(mConsoleListener)))
1389 NS_WARNING("Couldn't register console listener for child process");
1391 mAvailableDictionaries = std::move(aXPCOMInit.dictionaries());
1393 RecvSetOffline(aXPCOMInit.isOffline());
1394 RecvSetConnectivity(aXPCOMInit.isConnected());
1396 LocaleService::GetInstance()->AssignAppLocales(aXPCOMInit.appLocales());
1397 LocaleService::GetInstance()->AssignRequestedLocales(
1398 aXPCOMInit.requestedLocales());
1400 L10nRegistry::RegisterFileSourcesFromParentProcess(
1401 aXPCOMInit.l10nFileSources());
1403 RecvSetCaptivePortalState(aXPCOMInit.captivePortalState());
1404 RecvBidiKeyboardNotify(aXPCOMInit.isLangRTL(),
1405 aXPCOMInit.haveBidiKeyboards());
1407 if (aXPCOMInit.domainPolicy().active()) {
1408 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
1409 MOZ_ASSERT(ssm);
1410 ssm->ActivateDomainPolicyInternal(getter_AddRefs(mPolicy));
1411 if (!mPolicy) {
1412 MOZ_CRASH("Failed to activate domain policy.");
1414 mPolicy->ApplyClone(&aXPCOMInit.domainPolicy());
1417 nsCOMPtr<nsIClipboard> clipboard(
1418 do_GetService("@mozilla.org/widget/clipboard;1"));
1419 if (nsCOMPtr<nsIClipboardProxy> clipboardProxy =
1420 do_QueryInterface(clipboard)) {
1421 clipboardProxy->SetCapabilities(aXPCOMInit.clipboardCaps());
1425 AutoJSAPI jsapi;
1426 if (NS_WARN_IF(!jsapi.Init(xpc::PrivilegedJunkScope()))) {
1427 MOZ_CRASH();
1429 ErrorResult rv;
1430 JS::Rooted<JS::Value> data(jsapi.cx());
1431 mozilla::dom::ipc::StructuredCloneData id;
1432 id.Copy(aInitialData);
1433 id.Read(jsapi.cx(), &data, rv);
1434 if (NS_WARN_IF(rv.Failed())) {
1435 MOZ_CRASH();
1437 auto* global = ContentProcessMessageManager::Get();
1438 global->SetInitialProcessData(data);
1441 // The stylesheet cache is not ready yet. Store this URL for future use.
1442 nsCOMPtr<nsIURI> ucsURL = std::move(aXPCOMInit.userContentSheetURL());
1443 GlobalStyleSheetCache::SetUserContentCSSURL(ucsURL);
1445 GfxInfoBase::SetFeatureStatus(std::move(aXPCOMInit.gfxFeatureStatus()));
1447 // Initialize the RemoteDecoderManager thread and its associated PBackground
1448 // channel.
1449 RemoteDecoderManagerChild::Init();
1451 Preferences::RegisterCallbackAndCall(&OnFissionBlocklistPrefChange,
1452 kFissionEnforceBlockList);
1453 Preferences::RegisterCallbackAndCall(&OnFissionBlocklistPrefChange,
1454 kFissionOmitBlockListValues);
1456 // Set the dynamic scalar definitions for this process.
1457 TelemetryIPC::AddDynamicScalarDefinitions(aXPCOMInit.dynamicScalarDefs());
1460 mozilla::ipc::IPCResult ContentChild::RecvRequestMemoryReport(
1461 const uint32_t& aGeneration, const bool& aAnonymize,
1462 const bool& aMinimizeMemoryUsage,
1463 const Maybe<mozilla::ipc::FileDescriptor>& aDMDFile,
1464 const RequestMemoryReportResolver& aResolver) {
1465 nsCString process;
1466 if (aAnonymize || mRemoteType.IsEmpty()) {
1467 GetProcessName(process);
1468 } else {
1469 process = mRemoteType;
1471 AppendProcessId(process);
1472 MOZ_ASSERT(!process.IsEmpty());
1474 MemoryReportRequestClient::Start(
1475 aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, process,
1476 [&](const MemoryReport& aReport) {
1477 Unused << GetSingleton()->SendAddMemoryReport(aReport);
1479 aResolver);
1480 return IPC_OK();
1483 #if defined(XP_WIN)
1484 mozilla::ipc::IPCResult ContentChild::RecvGetUntrustedModulesData(
1485 GetUntrustedModulesDataResolver&& aResolver) {
1486 RefPtr<DllServices> dllSvc(DllServices::Get());
1487 dllSvc->GetUntrustedModulesData()->Then(
1488 GetMainThreadSerialEventTarget(), __func__,
1489 [aResolver](Maybe<UntrustedModulesData>&& aData) {
1490 aResolver(std::move(aData));
1492 [aResolver](nsresult aReason) { aResolver(Nothing()); });
1493 return IPC_OK();
1496 mozilla::ipc::IPCResult ContentChild::RecvUnblockUntrustedModulesThread() {
1497 if (nsCOMPtr<nsIObserverService> obs =
1498 mozilla::services::GetObserverService()) {
1499 obs->NotifyObservers(nullptr, "unblock-untrusted-modules-thread", nullptr);
1501 return IPC_OK();
1503 #endif // defined(XP_WIN)
1505 PCycleCollectWithLogsChild* ContentChild::AllocPCycleCollectWithLogsChild(
1506 const bool& aDumpAllTraces, const FileDescriptor& aGCLog,
1507 const FileDescriptor& aCCLog) {
1508 return do_AddRef(new CycleCollectWithLogsChild()).take();
1511 mozilla::ipc::IPCResult ContentChild::RecvPCycleCollectWithLogsConstructor(
1512 PCycleCollectWithLogsChild* aActor, const bool& aDumpAllTraces,
1513 const FileDescriptor& aGCLog, const FileDescriptor& aCCLog) {
1514 // The sink's destructor is called when the last reference goes away, which
1515 // will cause the actor to be closed down.
1516 auto* actor = static_cast<CycleCollectWithLogsChild*>(aActor);
1517 RefPtr<CycleCollectWithLogsChild::Sink> sink =
1518 new CycleCollectWithLogsChild::Sink(actor, aGCLog, aCCLog);
1520 // Invoke the dumper, which will take a reference to the sink.
1521 nsCOMPtr<nsIMemoryInfoDumper> dumper =
1522 do_GetService("@mozilla.org/memory-info-dumper;1");
1523 dumper->DumpGCAndCCLogsToSink(aDumpAllTraces, sink);
1524 return IPC_OK();
1527 bool ContentChild::DeallocPCycleCollectWithLogsChild(
1528 PCycleCollectWithLogsChild* aActor) {
1529 RefPtr<CycleCollectWithLogsChild> actor =
1530 dont_AddRef(static_cast<CycleCollectWithLogsChild*>(aActor));
1531 return true;
1534 mozilla::ipc::IPCResult ContentChild::RecvInitGMPService(
1535 Endpoint<PGMPServiceChild>&& aGMPService) {
1536 if (!GMPServiceChild::Create(std::move(aGMPService))) {
1537 return IPC_FAIL_NO_REASON(this);
1539 return IPC_OK();
1542 mozilla::ipc::IPCResult ContentChild::RecvInitProfiler(
1543 Endpoint<PProfilerChild>&& aEndpoint) {
1544 mProfilerController = ChildProfilerController::Create(std::move(aEndpoint));
1545 return IPC_OK();
1548 mozilla::ipc::IPCResult ContentChild::RecvGMPsChanged(
1549 nsTArray<GMPCapabilityData>&& capabilities) {
1550 GeckoMediaPluginServiceChild::UpdateGMPCapabilities(std::move(capabilities));
1551 return IPC_OK();
1554 mozilla::ipc::IPCResult ContentChild::RecvInitProcessHangMonitor(
1555 Endpoint<PProcessHangMonitorChild>&& aHangMonitor) {
1556 CreateHangMonitorChild(std::move(aHangMonitor));
1557 return IPC_OK();
1560 mozilla::ipc::IPCResult ContentChild::GetResultForRenderingInitFailure(
1561 GeckoChildID aOtherChildID) {
1562 if (aOtherChildID == XRE_GetChildID() || aOtherChildID == OtherChildID()) {
1563 // If we are talking to ourselves, or the UI process, then that is a fatal
1564 // protocol error.
1565 return IPC_FAIL_NO_REASON(this);
1568 // If we are talking to the GPU process, then we should recover from this on
1569 // the next ContentChild::RecvReinitRendering call.
1570 gfxCriticalNote << "Could not initialize rendering with GPU process";
1571 return IPC_OK();
1574 #if defined(XP_MACOSX)
1575 extern "C" {
1576 void CGSShutdownServerConnections();
1578 #endif
1580 mozilla::ipc::IPCResult ContentChild::RecvInitRendering(
1581 Endpoint<PCompositorManagerChild>&& aCompositor,
1582 Endpoint<PImageBridgeChild>&& aImageBridge,
1583 Endpoint<PVRManagerChild>&& aVRBridge,
1584 Endpoint<PRemoteDecoderManagerChild>&& aVideoManager,
1585 nsTArray<uint32_t>&& namespaces) {
1586 MOZ_ASSERT(namespaces.Length() == 3);
1588 // Note that for all of the methods below, if it can fail, it should only
1589 // return false if the failure is an IPDL error. In such situations,
1590 // ContentChild can reason about whether or not to wait for
1591 // RecvReinitRendering (because we surmised the GPU process crashed), or if it
1592 // should crash itself (because we are actually talking to the UI process). If
1593 // there are localized failures (e.g. failed to spawn a thread), then it
1594 // should MOZ_RELEASE_ASSERT or MOZ_CRASH as necessary instead.
1595 if (!CompositorManagerChild::Init(std::move(aCompositor), namespaces[0])) {
1596 return GetResultForRenderingInitFailure(aCompositor.OtherChildID());
1598 if (!CompositorManagerChild::CreateContentCompositorBridge(namespaces[1])) {
1599 return GetResultForRenderingInitFailure(aCompositor.OtherChildID());
1601 if (!ImageBridgeChild::InitForContent(std::move(aImageBridge),
1602 namespaces[2])) {
1603 return GetResultForRenderingInitFailure(aImageBridge.OtherChildID());
1605 if (!gfx::VRManagerChild::InitForContent(std::move(aVRBridge))) {
1606 return GetResultForRenderingInitFailure(aVRBridge.OtherChildID());
1608 RemoteDecoderManagerChild::InitForGPUProcess(std::move(aVideoManager));
1610 #if defined(XP_MACOSX) && !defined(MOZ_SANDBOX)
1611 // Close all current connections to the WindowServer. This ensures that the
1612 // Activity Monitor will not label the content process as "Not responding"
1613 // because it's not running a native event loop. See bug 1384336. When the
1614 // build is configured with sandbox support, this is called during sandbox
1615 // setup.
1616 CGSShutdownServerConnections();
1617 #endif
1619 return IPC_OK();
1622 mozilla::ipc::IPCResult ContentChild::RecvReinitRendering(
1623 Endpoint<PCompositorManagerChild>&& aCompositor,
1624 Endpoint<PImageBridgeChild>&& aImageBridge,
1625 Endpoint<PVRManagerChild>&& aVRBridge,
1626 Endpoint<PRemoteDecoderManagerChild>&& aVideoManager,
1627 nsTArray<uint32_t>&& namespaces) {
1628 MOZ_ASSERT(namespaces.Length() == 3);
1629 nsTArray<RefPtr<BrowserChild>> tabs = BrowserChild::GetAll();
1631 // Re-establish singleton bridges to the compositor.
1632 if (!CompositorManagerChild::Init(std::move(aCompositor), namespaces[0])) {
1633 return GetResultForRenderingInitFailure(aCompositor.OtherChildID());
1635 if (!CompositorManagerChild::CreateContentCompositorBridge(namespaces[1])) {
1636 return GetResultForRenderingInitFailure(aCompositor.OtherChildID());
1638 if (!ImageBridgeChild::ReinitForContent(std::move(aImageBridge),
1639 namespaces[2])) {
1640 return GetResultForRenderingInitFailure(aImageBridge.OtherChildID());
1642 if (!gfx::VRManagerChild::InitForContent(std::move(aVRBridge))) {
1643 return GetResultForRenderingInitFailure(aVRBridge.OtherChildID());
1645 gfxPlatform::GetPlatform()->CompositorUpdated();
1647 // Establish new PLayerTransactions.
1648 for (const auto& browserChild : tabs) {
1649 if (browserChild->GetLayersId().IsValid()) {
1650 browserChild->ReinitRendering();
1654 // Notify any observers that the compositor has been reinitialized,
1655 // eg the ZoomConstraintsClients for documents in this process.
1656 // This must occur after the ReinitRendering call above so that the
1657 // APZCTreeManagers have been connected.
1658 nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
1659 if (observerService) {
1660 observerService->NotifyObservers(nullptr, "compositor-reinitialized",
1661 nullptr);
1664 RemoteDecoderManagerChild::InitForGPUProcess(std::move(aVideoManager));
1665 return IPC_OK();
1668 mozilla::ipc::IPCResult ContentChild::RecvReinitRenderingForDeviceReset() {
1669 gfxPlatform::GetPlatform()->CompositorUpdated();
1671 nsTArray<RefPtr<BrowserChild>> tabs = BrowserChild::GetAll();
1672 for (const auto& browserChild : tabs) {
1673 if (browserChild->GetLayersId().IsValid()) {
1674 browserChild->ReinitRenderingForDeviceReset();
1677 return IPC_OK();
1680 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
1681 extern "C" {
1682 CGError CGSSetDenyWindowServerConnections(bool);
1685 static void DisconnectWindowServer(bool aIsSandboxEnabled) {
1686 // Close all current connections to the WindowServer. This ensures that the
1687 // Activity Monitor will not label the content process as "Not responding"
1688 // because it's not running a native event loop. See bug 1384336.
1689 // This is required with or without the sandbox enabled. Until the
1690 // window server is blocked as the policy level, this should be called
1691 // just before CGSSetDenyWindowServerConnections() so there are no
1692 // windowserver connections active when CGSSetDenyWindowServerConnections()
1693 // is called.
1694 CGSShutdownServerConnections();
1696 // Actual security benefits are only achieved when we additionally deny
1697 // future connections using the sandbox policy. WebGL must be remoted if
1698 // the windowserver connections are blocked. WebGL remoting is disabled
1699 // for some tests.
1700 if (aIsSandboxEnabled &&
1701 Preferences::GetBool(
1702 "security.sandbox.content.mac.disconnect-windowserver") &&
1703 Preferences::GetBool("webgl.out-of-process")) {
1704 CGError result = CGSSetDenyWindowServerConnections(true);
1705 MOZ_DIAGNOSTIC_ASSERT(result == kCGErrorSuccess);
1706 # if !MOZ_DIAGNOSTIC_ASSERT_ENABLED
1707 Unused << result;
1708 # endif
1711 #endif
1713 mozilla::ipc::IPCResult ContentChild::RecvSetProcessSandbox(
1714 const Maybe<mozilla::ipc::FileDescriptor>& aBroker) {
1715 // We may want to move the sandbox initialization somewhere else
1716 // at some point; see bug 880808.
1717 #if defined(MOZ_SANDBOX)
1719 bool sandboxEnabled = true;
1720 # if defined(XP_LINUX)
1721 // On Linux, we have to support systems that can't use any sandboxing.
1722 sandboxEnabled = SandboxInfo::Get().CanSandboxContent();
1724 if (sandboxEnabled && !StaticPrefs::media_cubeb_sandbox()) {
1725 // Pre-start audio before sandboxing; see bug 1443612.
1726 Unused << CubebUtils::GetCubeb();
1729 if (sandboxEnabled) {
1730 RegisterProfilerObserversForSandboxProfiler();
1731 sandboxEnabled = SetContentProcessSandbox(
1732 ContentProcessSandboxParams::ForThisProcess(aBroker));
1734 # elif defined(XP_WIN)
1735 if (GetEffectiveContentSandboxLevel() > 7) {
1736 // Libraries required by Network Security Services (NSS).
1737 ::LoadLibraryW(L"freebl3.dll");
1738 ::LoadLibraryW(L"softokn3.dll");
1739 // Cache value that is retrieved from a registry entry.
1740 Unused << GetCpuFrequencyMHz();
1742 mozilla::SandboxTarget::Instance()->StartSandbox();
1743 # elif defined(XP_MACOSX)
1744 sandboxEnabled = (GetEffectiveContentSandboxLevel() >= 1);
1745 DisconnectWindowServer(sandboxEnabled);
1746 # endif
1748 CrashReporter::RecordAnnotationBool(
1749 CrashReporter::Annotation::ContentSandboxEnabled, sandboxEnabled);
1750 # if defined(XP_LINUX) && !defined(ANDROID)
1751 CrashReporter::RecordAnnotationU32(
1752 CrashReporter::Annotation::ContentSandboxCapabilities,
1753 SandboxInfo::Get().AsInteger());
1754 # endif /* XP_LINUX && !ANDROID */
1755 #endif /* MOZ_SANDBOX */
1757 return IPC_OK();
1760 mozilla::ipc::IPCResult ContentChild::RecvBidiKeyboardNotify(
1761 const bool& aIsLangRTL, const bool& aHaveBidiKeyboards) {
1762 // bidi is always of type PuppetBidiKeyboard* (because in the child, the only
1763 // possible implementation of nsIBidiKeyboard is PuppetBidiKeyboard).
1764 PuppetBidiKeyboard* bidi =
1765 static_cast<PuppetBidiKeyboard*>(nsContentUtils::GetBidiKeyboard());
1766 if (bidi) {
1767 bidi->SetBidiKeyboardInfo(aIsLangRTL, aHaveBidiKeyboards);
1769 return IPC_OK();
1772 static StaticRefPtr<CancelableRunnable> gFirstIdleTask;
1774 static void FirstIdle(void) {
1775 MOZ_ASSERT(gFirstIdleTask);
1776 gFirstIdleTask = nullptr;
1778 ContentChild::GetSingleton()->SendFirstIdle();
1781 mozilla::ipc::IPCResult ContentChild::RecvConstructBrowser(
1782 ManagedEndpoint<PBrowserChild>&& aBrowserEp,
1783 ManagedEndpoint<PWindowGlobalChild>&& aWindowEp, const TabId& aTabId,
1784 const IPCTabContext& aContext, const WindowGlobalInit& aWindowInit,
1785 const uint32_t& aChromeFlags, const ContentParentId& aCpID,
1786 const bool& aIsForBrowser, const bool& aIsTopLevel) {
1787 MOZ_DIAGNOSTIC_ASSERT(!IsShuttingDown());
1789 static bool hasRunOnce = false;
1790 if (!hasRunOnce) {
1791 hasRunOnce = true;
1792 MOZ_ASSERT(!gFirstIdleTask);
1793 RefPtr<CancelableRunnable> firstIdleTask =
1794 NewCancelableRunnableFunction("FirstIdleRunnable", FirstIdle);
1795 gFirstIdleTask = firstIdleTask;
1796 if (NS_FAILED(NS_DispatchToCurrentThreadQueue(firstIdleTask.forget(),
1797 EventQueuePriority::Idle))) {
1798 gFirstIdleTask = nullptr;
1799 hasRunOnce = false;
1803 RefPtr<BrowsingContext> browsingContext =
1804 BrowsingContext::Get(aWindowInit.context().mBrowsingContextId);
1805 if (!browsingContext || browsingContext->IsDiscarded()) {
1806 nsPrintfCString reason("%s initial %s BrowsingContext",
1807 browsingContext ? "discarded" : "missing",
1808 aIsTopLevel ? "top" : "frame");
1809 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Warning, ("%s", reason.get()));
1810 if (!aIsTopLevel) {
1811 // Recover if the BrowsingContext is missing for a new subframe. The
1812 // `ManagedEndpoint` instances will be automatically destroyed.
1813 NS_WARNING(reason.get());
1814 return IPC_OK();
1817 // (these are the only possible values of `reason` at this point)
1818 return browsingContext
1819 ? IPC_FAIL(this, "discarded initial top BrowsingContext")
1820 : IPC_FAIL(this, "missing initial top BrowsingContext");
1823 if (xpc::IsInAutomation() &&
1824 StaticPrefs::
1825 browser_tabs_remote_testOnly_failPBrowserCreation_enabled()) {
1826 nsAutoCString idString;
1827 if (NS_SUCCEEDED(Preferences::GetCString(
1828 "browser.tabs.remote.testOnly.failPBrowserCreation.browsingContext",
1829 idString))) {
1830 nsresult rv = NS_OK;
1831 uint64_t bcid = idString.ToInteger64(&rv);
1832 if (NS_SUCCEEDED(rv) && bcid == browsingContext->Id()) {
1833 NS_WARNING("Injecting artificial PBrowser creation failure");
1834 return IPC_OK();
1839 if (!aWindowInit.isInitialDocument() ||
1840 !NS_IsAboutBlank(aWindowInit.documentURI())) {
1841 return IPC_FAIL(this,
1842 "Logic in CreateDocumentViewerForActor currently requires "
1843 "actors to be initial about:blank documents");
1846 // We'll happily accept any kind of IPCTabContext here; we don't need to
1847 // check that it's of a certain type for security purposes, because we
1848 // believe whatever the parent process tells us.
1849 MaybeInvalidTabContext tc(aContext);
1850 if (!tc.IsValid()) {
1851 NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
1852 "the parent process. (%s) Crashing...",
1853 tc.GetInvalidReason())
1854 .get());
1855 MOZ_CRASH("Invalid TabContext received from the parent process.");
1858 RefPtr<WindowGlobalChild> windowChild =
1859 WindowGlobalChild::CreateDisconnected(aWindowInit);
1860 if (!windowChild) {
1861 return IPC_FAIL(this, "Failed to create initial WindowGlobalChild");
1864 RefPtr<BrowserChild> browserChild =
1865 BrowserChild::Create(this, aTabId, tc.GetTabContext(), browsingContext,
1866 aChromeFlags, aIsTopLevel);
1868 // Bind the created BrowserChild to IPC to actually link the actor.
1869 if (NS_WARN_IF(!BindPBrowserEndpoint(std::move(aBrowserEp), browserChild))) {
1870 return IPC_FAIL(this, "BindPBrowserEndpoint failed");
1873 if (NS_WARN_IF(!browserChild->BindPWindowGlobalEndpoint(std::move(aWindowEp),
1874 windowChild))) {
1875 return IPC_FAIL(this, "BindPWindowGlobalEndpoint failed");
1877 windowChild->Init();
1878 auto guardNullWindowGlobal = MakeScopeExit([&] {
1879 if (!windowChild->GetWindowGlobal()) {
1880 windowChild->Destroy();
1884 // Ensure that a BrowsingContext is set for our BrowserChild before
1885 // running `Init`.
1886 MOZ_RELEASE_ASSERT(browserChild->mBrowsingContext->Id() ==
1887 aWindowInit.context().mBrowsingContextId);
1889 if (NS_WARN_IF(
1890 NS_FAILED(browserChild->Init(/* aOpener */ nullptr, windowChild)))) {
1891 return IPC_FAIL(browserChild, "BrowserChild::Init failed");
1894 nsCOMPtr<nsIObserverService> os = services::GetObserverService();
1895 if (os) {
1896 os->NotifyObservers(static_cast<nsIBrowserChild*>(browserChild),
1897 "tab-child-created", nullptr);
1899 // Notify parent that we are ready to handle input events.
1900 browserChild->SendRemoteIsReadyToHandleInputEvents();
1901 return IPC_OK();
1904 void ContentChild::GetAvailableDictionaries(
1905 nsTArray<nsCString>& aDictionaries) {
1906 aDictionaries = mAvailableDictionaries.Clone();
1909 mozilla::PRemoteSpellcheckEngineChild*
1910 ContentChild::AllocPRemoteSpellcheckEngineChild() {
1911 MOZ_CRASH(
1912 "Default Constructor for PRemoteSpellcheckEngineChild should never be "
1913 "called");
1914 return nullptr;
1917 bool ContentChild::DeallocPRemoteSpellcheckEngineChild(
1918 PRemoteSpellcheckEngineChild* child) {
1919 delete child;
1920 return true;
1923 mozilla::ipc::IPCResult ContentChild::RecvNotifyEmptyHTTPCache() {
1924 MOZ_ASSERT(NS_IsMainThread());
1925 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
1926 obs->NotifyObservers(nullptr, "cacheservice:empty-cache", nullptr);
1927 return IPC_OK();
1930 PHalChild* ContentChild::AllocPHalChild() { return CreateHalChild(); }
1932 bool ContentChild::DeallocPHalChild(PHalChild* aHal) {
1933 delete aHal;
1934 return true;
1937 devtools::PHeapSnapshotTempFileHelperChild*
1938 ContentChild::AllocPHeapSnapshotTempFileHelperChild() {
1939 return devtools::HeapSnapshotTempFileHelperChild::Create();
1942 bool ContentChild::DeallocPHeapSnapshotTempFileHelperChild(
1943 devtools::PHeapSnapshotTempFileHelperChild* aHeapSnapshotHelper) {
1944 delete aHeapSnapshotHelper;
1945 return true;
1948 already_AddRefed<PTestShellChild> ContentChild::AllocPTestShellChild() {
1949 return MakeAndAddRef<TestShellChild>();
1952 mozilla::ipc::IPCResult ContentChild::RecvPTestShellConstructor(
1953 PTestShellChild* actor) {
1954 return IPC_OK();
1957 RefPtr<GenericPromise> ContentChild::UpdateCookieStatus(nsIChannel* aChannel) {
1958 RefPtr<CookieServiceChild> csChild = CookieServiceChild::GetSingleton();
1959 NS_ASSERTION(csChild, "Couldn't get CookieServiceChild");
1961 return csChild->TrackCookieLoad(aChannel);
1964 PScriptCacheChild* ContentChild::AllocPScriptCacheChild(
1965 const FileDescOrError& cacheFile, const bool& wantCacheData) {
1966 return new loader::ScriptCacheChild();
1969 bool ContentChild::DeallocPScriptCacheChild(PScriptCacheChild* cache) {
1970 delete static_cast<loader::ScriptCacheChild*>(cache);
1971 return true;
1974 mozilla::ipc::IPCResult ContentChild::RecvPScriptCacheConstructor(
1975 PScriptCacheChild* actor, const FileDescOrError& cacheFile,
1976 const bool& wantCacheData) {
1977 Maybe<FileDescriptor> fd;
1978 if (cacheFile.type() == cacheFile.TFileDescriptor) {
1979 fd.emplace(cacheFile.get_FileDescriptor());
1982 static_cast<loader::ScriptCacheChild*>(actor)->Init(fd, wantCacheData);
1984 // Some scripts listen for "app-startup" to start. However, in the content
1985 // process, this category runs before the ScriptPreloader is initialized so
1986 // these scripts wouldn't be added to the cache. Instead, if a script needs to
1987 // run on start up in the content process, it should listen for this category.
1988 NS_CreateServicesFromCategory("content-process-ready-for-script", nullptr,
1989 "content-process-ready-for-script", nullptr);
1991 return IPC_OK();
1994 mozilla::ipc::IPCResult ContentChild::RecvNetworkLinkTypeChange(
1995 const uint32_t& aType) {
1996 mNetworkLinkType = aType;
1997 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
1998 if (obs) {
1999 obs->NotifyObservers(nullptr, "contentchild:network-link-type-changed",
2000 nullptr);
2002 return IPC_OK();
2005 mozilla::ipc::IPCResult ContentChild::RecvSocketProcessCrashed() {
2006 nsIOService::IncreaseSocketProcessCrashCount();
2007 return IPC_OK();
2010 PRemotePrintJobChild* ContentChild::AllocPRemotePrintJobChild() {
2011 #ifdef NS_PRINTING
2012 return new RemotePrintJobChild();
2013 #else
2014 return nullptr;
2015 #endif
2018 media::PMediaChild* ContentChild::AllocPMediaChild() {
2019 return media::AllocPMediaChild();
2022 bool ContentChild::DeallocPMediaChild(media::PMediaChild* aActor) {
2023 return media::DeallocPMediaChild(aActor);
2026 PBenchmarkStorageChild* ContentChild::AllocPBenchmarkStorageChild() {
2027 return BenchmarkStorageChild::Instance();
2030 bool ContentChild::DeallocPBenchmarkStorageChild(
2031 PBenchmarkStorageChild* aActor) {
2032 delete aActor;
2033 return true;
2036 #ifdef MOZ_WEBRTC
2037 PWebrtcGlobalChild* ContentChild::AllocPWebrtcGlobalChild() {
2038 auto* child = new WebrtcGlobalChild();
2039 return child;
2042 bool ContentChild::DeallocPWebrtcGlobalChild(PWebrtcGlobalChild* aActor) {
2043 delete static_cast<WebrtcGlobalChild*>(aActor);
2044 return true;
2046 #endif
2048 mozilla::ipc::IPCResult ContentChild::RecvRegisterChrome(
2049 nsTArray<ChromePackage>&& packages,
2050 nsTArray<SubstitutionMapping>&& resources,
2051 nsTArray<OverrideMapping>&& overrides, const nsCString& locale,
2052 const bool& reset) {
2053 nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
2054 nsChromeRegistryContent* chromeRegistry =
2055 static_cast<nsChromeRegistryContent*>(registrySvc.get());
2056 if (!chromeRegistry) {
2057 return IPC_FAIL(this, "ChromeRegistryContent is null!");
2059 chromeRegistry->RegisterRemoteChrome(packages, resources, overrides, locale,
2060 reset);
2061 return IPC_OK();
2064 mozilla::ipc::IPCResult ContentChild::RecvRegisterChromeItem(
2065 const ChromeRegistryItem& item) {
2066 nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
2067 nsChromeRegistryContent* chromeRegistry =
2068 static_cast<nsChromeRegistryContent*>(registrySvc.get());
2069 if (!chromeRegistry) {
2070 return IPC_FAIL(this, "ChromeRegistryContent is null!");
2072 switch (item.type()) {
2073 case ChromeRegistryItem::TChromePackage:
2074 chromeRegistry->RegisterPackage(item.get_ChromePackage());
2075 break;
2077 case ChromeRegistryItem::TOverrideMapping:
2078 chromeRegistry->RegisterOverride(item.get_OverrideMapping());
2079 break;
2081 case ChromeRegistryItem::TSubstitutionMapping:
2082 chromeRegistry->RegisterSubstitution(item.get_SubstitutionMapping());
2083 break;
2085 default:
2086 MOZ_ASSERT(false, "bad chrome item");
2087 return IPC_FAIL_NO_REASON(this);
2090 return IPC_OK();
2092 mozilla::ipc::IPCResult ContentChild::RecvClearStyleSheetCache(
2093 const Maybe<RefPtr<nsIPrincipal>>& aPrincipal,
2094 const Maybe<nsCString>& aSchemelessSite,
2095 const Maybe<OriginAttributesPattern>& aPattern) {
2096 SharedStyleSheetCache::Clear(aPrincipal, aSchemelessSite, aPattern);
2097 return IPC_OK();
2100 mozilla::ipc::IPCResult ContentChild::RecvClearScriptCache(
2101 const Maybe<RefPtr<nsIPrincipal>>& aPrincipal,
2102 const Maybe<nsCString>& aSchemelessSite,
2103 const Maybe<OriginAttributesPattern>& aPattern) {
2104 SharedScriptCache::Clear(aPrincipal, aSchemelessSite, aPattern);
2105 return IPC_OK();
2108 mozilla::ipc::IPCResult ContentChild::RecvClearImageCacheFromPrincipal(
2109 nsIPrincipal* aPrincipal) {
2110 imgLoader* loader;
2111 if (aPrincipal->OriginAttributesRef().IsPrivateBrowsing()) {
2112 loader = imgLoader::PrivateBrowsingLoader();
2113 } else {
2114 loader = imgLoader::NormalLoader();
2117 loader->RemoveEntriesInternal(Some(aPrincipal), Nothing(), Nothing());
2118 return IPC_OK();
2121 mozilla::ipc::IPCResult ContentChild::RecvClearImageCacheFromSite(
2122 const nsCString& aSchemelessSite, const OriginAttributesPattern& aPattern) {
2123 imgLoader::NormalLoader()->RemoveEntriesInternal(
2124 Nothing(), Some(aSchemelessSite), Some(aPattern));
2125 imgLoader::PrivateBrowsingLoader()->RemoveEntriesInternal(
2126 Nothing(), Some(aSchemelessSite), Some(aPattern));
2128 return IPC_OK();
2131 mozilla::ipc::IPCResult ContentChild::RecvClearImageCache(
2132 const bool& privateLoader, const bool& chrome) {
2133 imgLoader* loader = privateLoader ? imgLoader::PrivateBrowsingLoader()
2134 : imgLoader::NormalLoader();
2136 loader->ClearCache(chrome);
2137 return IPC_OK();
2140 mozilla::ipc::IPCResult ContentChild::RecvSetOffline(const bool& offline) {
2141 nsCOMPtr<nsIIOService> io(do_GetIOService());
2142 NS_ASSERTION(io, "IO Service can not be null");
2144 io->SetOffline(offline);
2146 return IPC_OK();
2149 mozilla::ipc::IPCResult ContentChild::RecvSetConnectivity(
2150 const bool& connectivity) {
2151 nsCOMPtr<nsIIOService> io(do_GetIOService());
2152 nsCOMPtr<nsIIOServiceInternal> ioInternal(do_QueryInterface(io));
2153 NS_ASSERTION(ioInternal, "IO Service can not be null");
2155 ioInternal->SetConnectivity(connectivity);
2157 return IPC_OK();
2160 mozilla::ipc::IPCResult ContentChild::RecvSetCaptivePortalState(
2161 const int32_t& aState) {
2162 nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID);
2163 if (!cps) {
2164 return IPC_OK();
2167 mozilla::net::CaptivePortalService* portal =
2168 static_cast<mozilla::net::CaptivePortalService*>(cps.get());
2169 portal->SetStateInChild(aState);
2171 return IPC_OK();
2174 mozilla::ipc::IPCResult ContentChild::RecvSetTRRMode(
2175 const nsIDNSService::ResolverMode& mode,
2176 const nsIDNSService::ResolverMode& modeFromPref) {
2177 RefPtr<net::ChildDNSService> dnsServiceChild =
2178 dont_AddRef(net::ChildDNSService::GetSingleton());
2179 if (dnsServiceChild) {
2180 dnsServiceChild->SetTRRModeInChild(mode, modeFromPref);
2182 return IPC_OK();
2185 void ContentChild::ActorDestroy(ActorDestroyReason why) {
2186 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
2187 DestroySandboxProfiler();
2188 #endif
2190 if (mForceKillTimer) {
2191 mForceKillTimer->Cancel();
2192 mForceKillTimer = nullptr;
2195 if (AbnormalShutdown == why) {
2196 NS_WARNING("shutting down early because of crash!");
2197 ProcessChild::QuickExit();
2200 #ifndef NS_FREE_PERMANENT_DATA
2201 // In release builds, there's no point in the content process
2202 // going through the full XPCOM shutdown path, because it doesn't
2203 // keep persistent state.
2204 ProcessChild::QuickExit();
2205 #else
2206 // Destroy our JSProcessActors, and reject any pending queries.
2207 JSActorDidDestroy();
2209 # if defined(XP_WIN)
2210 RefPtr<DllServices> dllSvc(DllServices::Get());
2211 dllSvc->DisableFull();
2212 # endif // defined(XP_WIN)
2214 if (gFirstIdleTask) {
2215 gFirstIdleTask->Cancel();
2216 gFirstIdleTask = nullptr;
2219 BlobURLProtocolHandler::RemoveDataEntries();
2221 mSharedData = nullptr;
2223 mIdleObservers.Clear();
2225 if (mConsoleListener) {
2226 nsCOMPtr<nsIConsoleService> svc(
2227 do_GetService(NS_CONSOLESERVICE_CONTRACTID));
2228 if (svc) {
2229 svc->UnregisterListener(mConsoleListener);
2230 mConsoleListener->mChild = nullptr;
2233 mIsAlive = false;
2235 CrashReporterClient::DestroySingleton();
2237 XRE_ShutdownChildProcess();
2238 #endif // NS_FREE_PERMANENT_DATA
2241 void ContentChild::ProcessingError(Result aCode, const char* aReason) {
2242 switch (aCode) {
2243 case MsgDropped:
2244 NS_WARNING("MsgDropped in ContentChild");
2245 return;
2247 case MsgNotKnown:
2248 case MsgNotAllowed:
2249 case MsgPayloadError:
2250 case MsgProcessingError:
2251 case MsgValueError:
2252 break;
2254 default:
2255 MOZ_CRASH("not reached");
2258 CrashReporter::RecordAnnotationCString(
2259 CrashReporter::Annotation::ipc_channel_error, aReason);
2261 MOZ_CRASH("Content child abort due to IPC error");
2264 mozilla::ipc::IPCResult ContentChild::RecvPreferenceUpdate(const Pref& aPref) {
2265 Preferences::SetPreference(aPref);
2266 return IPC_OK();
2269 mozilla::ipc::IPCResult ContentChild::RecvVarUpdate(const GfxVarUpdate& aVar) {
2270 gfx::gfxVars::ApplyUpdate(aVar);
2271 return IPC_OK();
2274 mozilla::ipc::IPCResult ContentChild::RecvUpdatePerfStatsCollectionMask(
2275 const uint64_t& aMask) {
2276 PerfStats::SetCollectionMask(static_cast<PerfStats::MetricMask>(aMask));
2277 return IPC_OK();
2280 mozilla::ipc::IPCResult ContentChild::RecvCollectPerfStatsJSON(
2281 CollectPerfStatsJSONResolver&& aResolver) {
2282 aResolver(PerfStats::CollectLocalPerfStatsJSON());
2283 return IPC_OK();
2286 mozilla::ipc::IPCResult ContentChild::RecvCollectScrollingMetrics(
2287 CollectScrollingMetricsResolver&& aResolver) {
2288 auto metrics = ScrollingMetrics::CollectLocalScrollingMetrics();
2289 using ResolverArgs = std::tuple<const uint32_t&, const uint32_t&>;
2290 aResolver(ResolverArgs(std::get<0>(metrics), std::get<1>(metrics)));
2291 return IPC_OK();
2294 mozilla::ipc::IPCResult ContentChild::RecvNotifyVisited(
2295 nsTArray<VisitedQueryResult>&& aURIs) {
2296 nsCOMPtr<IHistory> history = components::History::Service();
2297 if (!history) {
2298 return IPC_OK();
2300 for (const VisitedQueryResult& result : aURIs) {
2301 nsCOMPtr<nsIURI> newURI = result.uri();
2302 if (!newURI) {
2303 return IPC_FAIL_NO_REASON(this);
2305 auto status = result.visited() ? IHistory::VisitedStatus::Visited
2306 : IHistory::VisitedStatus::Unvisited;
2307 history->NotifyVisited(newURI, status);
2309 return IPC_OK();
2312 mozilla::ipc::IPCResult ContentChild::RecvThemeChanged(
2313 FullLookAndFeel&& aLookAndFeelData, widget::ThemeChangeKind aKind) {
2314 LookAndFeel::SetData(std::move(aLookAndFeelData));
2315 LookAndFeel::NotifyChangedAllWindows(aKind);
2316 return IPC_OK();
2319 mozilla::ipc::IPCResult ContentChild::RecvLoadProcessScript(
2320 const nsString& aURL) {
2321 auto* global = ContentProcessMessageManager::Get();
2322 if (global && global->LoadScript(aURL)) {
2323 return IPC_OK();
2325 return IPC_FAIL(this, "ContentProcessMessageManager::LoadScript failed");
2328 mozilla::ipc::IPCResult ContentChild::RecvAsyncMessage(
2329 const nsString& aMsg, const ClonedMessageData& aData) {
2330 AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("ContentChild::RecvAsyncMessage",
2331 OTHER, aMsg);
2332 MMPrinter::Print("ContentChild::RecvAsyncMessage", aMsg, aData);
2334 RefPtr<nsFrameMessageManager> cpm =
2335 nsFrameMessageManager::GetChildProcessManager();
2336 if (cpm) {
2337 StructuredCloneData data;
2338 ipc::UnpackClonedMessageData(aData, data);
2339 cpm->ReceiveMessage(cpm, nullptr, aMsg, false, &data, nullptr,
2340 IgnoreErrors());
2342 return IPC_OK();
2345 mozilla::ipc::IPCResult ContentChild::RecvRegisterStringBundles(
2346 nsTArray<mozilla::dom::StringBundleDescriptor>&& aDescriptors) {
2347 nsCOMPtr<nsIStringBundleService> stringBundleService =
2348 components::StringBundle::Service();
2350 for (auto& descriptor : aDescriptors) {
2351 stringBundleService->RegisterContentBundle(
2352 descriptor.bundleURL(), descriptor.mapHandle(), descriptor.mapSize());
2355 return IPC_OK();
2358 mozilla::ipc::IPCResult ContentChild::RecvSimpleURIUnknownRemoteSchemes(
2359 nsTArray<nsCString>&& aRemoteSchemes) {
2360 RefPtr<nsIOService> io = nsIOService::GetInstance();
2361 io->SetSimpleURIUnknownRemoteSchemes(aRemoteSchemes);
2362 return IPC_OK();
2365 mozilla::ipc::IPCResult ContentChild::RecvUpdateL10nFileSources(
2366 nsTArray<mozilla::dom::L10nFileSourceDescriptor>&& aDescriptors) {
2367 L10nRegistry::RegisterFileSourcesFromParentProcess(aDescriptors);
2368 return IPC_OK();
2371 mozilla::ipc::IPCResult ContentChild::RecvUpdateSharedData(
2372 SharedMemoryHandle&& aMapHandle, const uint32_t& aMapSize,
2373 nsTArray<IPCBlob>&& aBlobs, nsTArray<nsCString>&& aChangedKeys) {
2374 nsTArray<RefPtr<BlobImpl>> blobImpls(aBlobs.Length());
2375 for (auto& ipcBlob : aBlobs) {
2376 blobImpls.AppendElement(IPCBlobUtils::Deserialize(ipcBlob));
2379 if (mSharedData) {
2380 mSharedData->Update(std::move(aMapHandle), aMapSize, std::move(blobImpls),
2381 std::move(aChangedKeys));
2382 } else {
2383 mSharedData =
2384 new SharedMap(ContentProcessMessageManager::Get()->GetParentObject(),
2385 std::move(aMapHandle), aMapSize, std::move(blobImpls));
2388 return IPC_OK();
2391 mozilla::ipc::IPCResult ContentChild::RecvFontListChanged() {
2392 gfxPlatformFontList::PlatformFontList()->FontListChanged();
2394 return IPC_OK();
2397 mozilla::ipc::IPCResult ContentChild::RecvForceGlobalReflow(
2398 bool aNeedsReframe) {
2399 gfxPlatform::ForceGlobalReflow(aNeedsReframe ? gfxPlatform::NeedsReframe::Yes
2400 : gfxPlatform::NeedsReframe::No);
2402 return IPC_OK();
2405 mozilla::ipc::IPCResult ContentChild::RecvGeolocationUpdate(
2406 nsIDOMGeoPosition* aPosition) {
2407 RefPtr<nsGeolocationService> gs =
2408 nsGeolocationService::GetGeolocationService();
2409 if (!gs) {
2410 return IPC_OK();
2412 gs->Update(aPosition);
2413 return IPC_OK();
2416 mozilla::ipc::IPCResult ContentChild::RecvGeolocationError(
2417 const uint16_t& errorCode) {
2418 RefPtr<nsGeolocationService> gs =
2419 nsGeolocationService::GetGeolocationService();
2420 if (!gs) {
2421 return IPC_OK();
2423 gs->NotifyError(errorCode);
2424 return IPC_OK();
2427 mozilla::ipc::IPCResult ContentChild::RecvUpdateDictionaryList(
2428 nsTArray<nsCString>&& aDictionaries) {
2429 mAvailableDictionaries = std::move(aDictionaries);
2430 mozInlineSpellChecker::UpdateCanEnableInlineSpellChecking();
2431 return IPC_OK();
2434 mozilla::ipc::IPCResult ContentChild::RecvUpdateFontList(
2435 dom::SystemFontList&& aFontList) {
2436 mFontList = std::move(aFontList);
2437 if (gfxPlatform::Initialized()) {
2438 gfxPlatform::GetPlatform()->UpdateFontList(true);
2440 return IPC_OK();
2443 mozilla::ipc::IPCResult ContentChild::RecvRebuildFontList(
2444 const bool& aFullRebuild) {
2445 if (gfxPlatform::Initialized()) {
2446 gfxPlatform::GetPlatform()->UpdateFontList(aFullRebuild);
2448 return IPC_OK();
2451 mozilla::ipc::IPCResult ContentChild::RecvFontListShmBlockAdded(
2452 const uint32_t& aGeneration, const uint32_t& aIndex,
2453 SharedMemoryHandle&& aHandle) {
2454 if (gfxPlatform::Initialized()) {
2455 gfxPlatformFontList::PlatformFontList()->ShmBlockAdded(aGeneration, aIndex,
2456 std::move(aHandle));
2458 return IPC_OK();
2461 mozilla::ipc::IPCResult ContentChild::RecvUpdateAppLocales(
2462 nsTArray<nsCString>&& aAppLocales) {
2463 LocaleService::GetInstance()->AssignAppLocales(aAppLocales);
2464 return IPC_OK();
2467 mozilla::ipc::IPCResult ContentChild::RecvUpdateRequestedLocales(
2468 nsTArray<nsCString>&& aRequestedLocales) {
2469 LocaleService::GetInstance()->AssignRequestedLocales(aRequestedLocales);
2470 return IPC_OK();
2473 mozilla::ipc::IPCResult ContentChild::RecvSystemTimezoneChanged() {
2474 nsJSUtils::ResetTimeZone();
2475 return IPC_OK();
2478 mozilla::ipc::IPCResult ContentChild::RecvAddPermission(
2479 const IPC::Permission& permission) {
2480 nsCOMPtr<nsIPermissionManager> permissionManagerIface =
2481 components::PermissionManager::Service();
2482 PermissionManager* permissionManager =
2483 static_cast<PermissionManager*>(permissionManagerIface.get());
2484 MOZ_ASSERT(permissionManager,
2485 "We have no permissionManager in the Content process !");
2487 // note we do not need to force mUserContextId to the default here because
2488 // the permission manager does that internally.
2489 nsAutoCString originNoSuffix;
2490 OriginAttributes attrs;
2491 bool success = attrs.PopulateFromOrigin(permission.origin, originNoSuffix);
2492 NS_ENSURE_TRUE(success, IPC_FAIL_NO_REASON(this));
2494 nsCOMPtr<nsIURI> uri;
2495 nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
2496 NS_ENSURE_SUCCESS(rv, IPC_OK());
2498 nsCOMPtr<nsIPrincipal> principal =
2499 mozilla::BasePrincipal::CreateContentPrincipal(uri, attrs);
2501 // child processes don't care about modification time.
2502 int64_t modificationTime = 0;
2504 permissionManager->AddInternal(
2505 principal, nsCString(permission.type), permission.capability, 0,
2506 permission.expireType, permission.expireTime, modificationTime,
2507 PermissionManager::eNotify, PermissionManager::eNoDBOperation);
2509 return IPC_OK();
2512 mozilla::ipc::IPCResult ContentChild::RecvRemoveAllPermissions() {
2513 nsCOMPtr<nsIPermissionManager> permissionManagerIface =
2514 components::PermissionManager::Service();
2515 PermissionManager* permissionManager =
2516 static_cast<PermissionManager*>(permissionManagerIface.get());
2517 MOZ_ASSERT(permissionManager,
2518 "We have no permissionManager in the Content process !");
2520 permissionManager->RemoveAllFromIPC();
2521 return IPC_OK();
2524 mozilla::ipc::IPCResult ContentChild::RecvFlushMemory(const nsString& reason) {
2525 nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
2526 if (!mShuttingDown && os) {
2527 os->NotifyObservers(nullptr, "memory-pressure", reason.get());
2529 return IPC_OK();
2532 mozilla::ipc::IPCResult ContentChild::RecvActivateA11y(uint64_t aCacheDomains) {
2533 #ifdef ACCESSIBILITY
2534 // Start accessibility in content process if it's running in chrome
2535 // process.
2536 GetOrCreateAccService(nsAccessibilityService::eMainProcess, aCacheDomains);
2537 #endif // ACCESSIBILITY
2538 return IPC_OK();
2541 mozilla::ipc::IPCResult ContentChild::RecvShutdownA11y() {
2542 #ifdef ACCESSIBILITY
2543 // Try to shutdown accessibility in content process if it's shutting down in
2544 // chrome process.
2545 MaybeShutdownAccService(nsAccessibilityService::eMainProcess);
2546 #endif
2547 return IPC_OK();
2550 mozilla::ipc::IPCResult ContentChild::RecvSetCacheDomains(
2551 uint64_t aCacheDomains) {
2552 #ifdef ACCESSIBILITY
2553 nsAccessibilityService* accService = GetAccService();
2554 if (!accService) {
2555 return IPC_FAIL(this, "Accessibility service should exist");
2557 accService->SetCacheDomains(aCacheDomains);
2558 #endif
2559 return IPC_OK();
2562 mozilla::ipc::IPCResult ContentChild::RecvApplicationForeground() {
2563 // Rebroadcast the "application-foreground"
2564 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
2565 if (obs) {
2566 obs->NotifyObservers(nullptr, "application-foreground", nullptr);
2568 return IPC_OK();
2571 mozilla::ipc::IPCResult ContentChild::RecvApplicationBackground() {
2572 // Rebroadcast the "application-background"
2573 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
2574 if (obs) {
2575 obs->NotifyObservers(nullptr, "application-background", nullptr);
2577 return IPC_OK();
2580 mozilla::ipc::IPCResult ContentChild::RecvGarbageCollect() {
2581 // Rebroadcast the "child-gc-request" so that workers will GC.
2582 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
2583 if (obs) {
2584 obs->NotifyObservers(nullptr, "child-gc-request", nullptr);
2586 nsJSContext::GarbageCollectNow(JS::GCReason::DOM_IPC);
2587 return IPC_OK();
2590 mozilla::ipc::IPCResult ContentChild::RecvCycleCollect() {
2591 // Rebroadcast the "child-cc-request" so that workers will CC.
2592 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
2593 if (obs) {
2594 obs->NotifyObservers(nullptr, "child-cc-request", nullptr);
2596 nsJSContext::CycleCollectNow(CCReason::IPC_MESSAGE);
2597 return IPC_OK();
2600 mozilla::ipc::IPCResult ContentChild::RecvUnlinkGhosts() {
2601 #ifdef DEBUG
2602 nsWindowMemoryReporter::UnlinkGhostWindows();
2603 #endif
2604 return IPC_OK();
2607 mozilla::ipc::IPCResult ContentChild::RecvAppInfo(
2608 const nsCString& version, const nsCString& buildID, const nsCString& name,
2609 const nsCString& UAName, const nsCString& ID, const nsCString& vendor,
2610 const nsCString& sourceURL, const nsCString& updateURL) {
2611 mAppInfo.version.Assign(version);
2612 mAppInfo.buildID.Assign(buildID);
2613 mAppInfo.name.Assign(name);
2614 mAppInfo.UAName.Assign(UAName);
2615 mAppInfo.ID.Assign(ID);
2616 mAppInfo.vendor.Assign(vendor);
2617 mAppInfo.sourceURL.Assign(sourceURL);
2618 mAppInfo.updateURL.Assign(updateURL);
2620 return IPC_OK();
2623 mozilla::ipc::IPCResult ContentChild::RecvRemoteType(
2624 const nsCString& aRemoteType, const nsCString& aProfile) {
2625 if (aRemoteType == mRemoteType) {
2626 // Allocation of preallocated processes that are still launching can
2627 // cause this
2628 return IPC_OK();
2631 if (!mRemoteType.IsVoid()) {
2632 // Preallocated processes are type PREALLOC_REMOTE_TYPE; they may not
2633 // become a File: process, or Privileged About Content Process
2634 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
2635 ("Changing remoteType of process %d from %s to %s", getpid(),
2636 mRemoteType.get(), aRemoteType.get()));
2637 // prealloc->anything (but file) or web->web allowed, and no-change
2638 MOZ_RELEASE_ASSERT(mRemoteType == PREALLOC_REMOTE_TYPE &&
2639 aRemoteType != FILE_REMOTE_TYPE &&
2640 aRemoteType != PRIVILEGEDABOUT_REMOTE_TYPE);
2641 } else {
2642 // Initial setting of remote type. Either to 'prealloc' or the actual
2643 // final type (if we didn't use a preallocated process)
2644 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
2645 ("Setting remoteType of process %d to %s", getpid(),
2646 aRemoteType.get()));
2648 if (aRemoteType == PREALLOC_REMOTE_TYPE) {
2649 PreallocInit();
2653 auto remoteTypePrefix = RemoteTypePrefix(aRemoteType);
2655 // Must do before SetProcessName
2656 mRemoteType.Assign(aRemoteType);
2658 // Update the process name so about:memory's process names are more obvious.
2659 if (aRemoteType == FILE_REMOTE_TYPE) {
2660 SetProcessName("file:// Content"_ns, nullptr, &aProfile);
2661 } else if (aRemoteType == EXTENSION_REMOTE_TYPE) {
2662 SetProcessName("WebExtensions"_ns, nullptr, &aProfile);
2663 } else if (aRemoteType == PRIVILEGEDABOUT_REMOTE_TYPE) {
2664 SetProcessName("Privileged Content"_ns, nullptr, &aProfile);
2665 } else if (aRemoteType == PRIVILEGEDMOZILLA_REMOTE_TYPE) {
2666 SetProcessName("Privileged Mozilla"_ns, nullptr, &aProfile);
2667 } else if (aRemoteType == INFERENCE_REMOTE_TYPE) {
2668 SetProcessName("Inference"_ns, nullptr, &aProfile);
2669 } else if (remoteTypePrefix == WITH_COOP_COEP_REMOTE_TYPE) {
2670 // The profiler can sanitize out the eTLD+1
2671 nsDependentCSubstring etld =
2672 Substring(aRemoteType, WITH_COOP_COEP_REMOTE_TYPE.Length() + 1);
2673 #ifdef NIGHTLY_BUILD
2674 SetProcessName("WebCOOP+COEP Content"_ns, &etld, &aProfile);
2675 #else
2676 SetProcessName("Isolated Web Content"_ns, &etld,
2677 &aProfile); // to avoid confusing people
2678 #endif
2679 } else if (remoteTypePrefix == FISSION_WEB_REMOTE_TYPE) {
2680 // The profiler can sanitize out the eTLD+1
2681 nsDependentCSubstring etld =
2682 Substring(aRemoteType, FISSION_WEB_REMOTE_TYPE.Length() + 1);
2683 SetProcessName("Isolated Web Content"_ns, &etld, &aProfile);
2684 } else if (remoteTypePrefix == SERVICEWORKER_REMOTE_TYPE) {
2685 // The profiler can sanitize out the eTLD+1
2686 nsDependentCSubstring etld =
2687 Substring(aRemoteType, SERVICEWORKER_REMOTE_TYPE.Length() + 1);
2688 SetProcessName("Isolated Service Worker"_ns, &etld, &aProfile);
2689 } else {
2690 // else "prealloc" or "web" type -> "Web Content"
2691 SetProcessName("Web Content"_ns, nullptr, &aProfile);
2694 // Turn off Spectre mitigations in isolated web content processes.
2695 if (StaticPrefs::javascript_options_spectre_disable_for_isolated_content() &&
2696 StaticPrefs::browser_opaqueResponseBlocking() &&
2697 (remoteTypePrefix == FISSION_WEB_REMOTE_TYPE ||
2698 remoteTypePrefix == SERVICEWORKER_REMOTE_TYPE ||
2699 remoteTypePrefix == WITH_COOP_COEP_REMOTE_TYPE ||
2700 aRemoteType == PRIVILEGEDABOUT_REMOTE_TYPE ||
2701 aRemoteType == PRIVILEGEDMOZILLA_REMOTE_TYPE)) {
2702 JS::DisableSpectreMitigationsAfterInit();
2705 // Use the prefix to avoid URIs from Fission isolated processes.
2706 CrashReporter::RecordAnnotationNSCString(
2707 CrashReporter::Annotation::RemoteType, remoteTypePrefix);
2709 return IPC_OK();
2712 // A method to initialize anything we need during the preallocation phase
2713 void ContentChild::PreallocInit() {
2714 EnsureNSSInitializedChromeOrContent();
2716 // SetAcceptLanguages() needs to read localized strings (file access),
2717 // which is slow, so do this in prealloc
2718 nsHttpHandler::PresetAcceptLanguages();
2721 // Call RemoteTypePrefix() on the result to remove URIs if you want to use this
2722 // for telemetry.
2723 const nsACString& ContentChild::GetRemoteType() const { return mRemoteType; }
2725 mozilla::ipc::IPCResult ContentChild::RecvInitRemoteWorkerService(
2726 Endpoint<PRemoteWorkerServiceChild>&& aEndpoint) {
2727 RemoteWorkerService::InitializeChild(std::move(aEndpoint));
2728 return IPC_OK();
2731 mozilla::ipc::IPCResult ContentChild::RecvInitBlobURLs(
2732 nsTArray<BlobURLRegistrationData>&& aRegistrations) {
2733 for (uint32_t i = 0; i < aRegistrations.Length(); ++i) {
2734 BlobURLRegistrationData& registration = aRegistrations[i];
2735 RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(registration.blob());
2736 MOZ_ASSERT(blobImpl);
2738 BlobURLProtocolHandler::AddDataEntry(registration.url(),
2739 registration.principal(),
2740 registration.partitionKey(), blobImpl);
2741 // If we have received an already-revoked blobURL, we have to keep it alive
2742 // for a while (see BlobURLProtocolHandler) in order to support pending
2743 // operations such as navigation, download and so on.
2744 if (registration.revoked()) {
2745 BlobURLProtocolHandler::RemoveDataEntry(registration.url(), false);
2749 return IPC_OK();
2752 mozilla::ipc::IPCResult ContentChild::RecvInitJSActorInfos(
2753 nsTArray<JSProcessActorInfo>&& aContentInfos,
2754 nsTArray<JSWindowActorInfo>&& aWindowInfos) {
2755 RefPtr<JSActorService> actSvc = JSActorService::GetSingleton();
2756 actSvc->LoadJSActorInfos(aContentInfos, aWindowInfos);
2757 return IPC_OK();
2760 mozilla::ipc::IPCResult ContentChild::RecvUnregisterJSWindowActor(
2761 const nsCString& aName) {
2762 RefPtr<JSActorService> actSvc = JSActorService::GetSingleton();
2763 actSvc->UnregisterWindowActor(aName);
2764 return IPC_OK();
2767 mozilla::ipc::IPCResult ContentChild::RecvUnregisterJSProcessActor(
2768 const nsCString& aName) {
2769 RefPtr<JSActorService> actSvc = JSActorService::GetSingleton();
2770 actSvc->UnregisterProcessActor(aName);
2771 return IPC_OK();
2774 mozilla::ipc::IPCResult ContentChild::RecvLastPrivateDocShellDestroyed() {
2775 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
2776 obs->NotifyObservers(nullptr, "last-pb-context-exited", nullptr);
2777 return IPC_OK();
2780 mozilla::ipc::IPCResult ContentChild::RecvNotifyProcessPriorityChanged(
2781 const hal::ProcessPriority& aPriority) {
2782 nsCOMPtr<nsIObserverService> os = services::GetObserverService();
2783 NS_ENSURE_TRUE(os, IPC_OK());
2785 RefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
2786 props->SetPropertyAsInt32(u"priority"_ns, static_cast<int32_t>(aPriority));
2788 PROFILER_MARKER("Process Priority", OTHER,
2789 mozilla::MarkerThreadId::MainThread(), ProcessPriorityChange,
2790 ProfilerString8View::WrapNullTerminatedString(
2791 ProcessPriorityToString(mProcessPriority)),
2792 ProfilerString8View::WrapNullTerminatedString(
2793 ProcessPriorityToString(aPriority)));
2795 // Record FOG data before the priority change.
2796 // Ignore the change if it's the first time we set the process priority.
2797 if (mProcessPriority != hal::PROCESS_PRIORITY_UNKNOWN) {
2798 glean::RecordPowerMetrics();
2801 ConfigureThreadPerformanceHints(aPriority);
2803 mProcessPriority = aPriority;
2805 os->NotifyObservers(static_cast<nsIPropertyBag2*>(props),
2806 "ipc:process-priority-changed", nullptr);
2807 if (StaticPrefs::
2808 dom_memory_foreground_content_processes_have_larger_page_cache()) {
2809 if (mProcessPriority >= hal::PROCESS_PRIORITY_FOREGROUND) {
2810 // Note: keep this in sync with the JS shell (js/src/shell/js.cpp).
2811 moz_set_max_dirty_page_modifier(4);
2812 } else if (mProcessPriority == hal::PROCESS_PRIORITY_BACKGROUND) {
2813 moz_set_max_dirty_page_modifier(-2);
2815 #if defined(MOZ_MEMORY)
2816 if (StaticPrefs::dom_memory_memory_pressure_on_background() == 1) {
2817 jemalloc_free_dirty_pages();
2819 #endif
2820 if (StaticPrefs::dom_memory_memory_pressure_on_background() == 2) {
2821 nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService();
2822 obsServ->NotifyObservers(nullptr, "memory-pressure", u"heap-minimize");
2823 } else if (StaticPrefs::dom_memory_memory_pressure_on_background() == 3) {
2824 nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService();
2825 obsServ->NotifyObservers(nullptr, "memory-pressure", u"low-memory");
2828 } else {
2829 moz_set_max_dirty_page_modifier(0);
2833 return IPC_OK();
2836 mozilla::ipc::IPCResult ContentChild::RecvMinimizeMemoryUsage() {
2837 nsCOMPtr<nsIMemoryReporterManager> mgr =
2838 do_GetService("@mozilla.org/memory-reporter-manager;1");
2839 NS_ENSURE_TRUE(mgr, IPC_OK());
2841 Unused << mgr->MinimizeMemoryUsage(/* callback = */ nullptr);
2842 return IPC_OK();
2845 void ContentChild::AddIdleObserver(nsIObserver* aObserver,
2846 uint32_t aIdleTimeInS) {
2847 MOZ_ASSERT(aObserver, "null idle observer");
2848 // Make sure aObserver isn't released while we wait for the parent
2849 aObserver->AddRef();
2850 SendAddIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS);
2851 mIdleObservers.Insert(aObserver);
2854 void ContentChild::RemoveIdleObserver(nsIObserver* aObserver,
2855 uint32_t aIdleTimeInS) {
2856 MOZ_ASSERT(aObserver, "null idle observer");
2857 SendRemoveIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS);
2858 aObserver->Release();
2859 mIdleObservers.Remove(aObserver);
2862 mozilla::ipc::IPCResult ContentChild::RecvNotifyIdleObserver(
2863 const uint64_t& aObserver, const nsCString& aTopic,
2864 const nsString& aTimeStr) {
2865 nsIObserver* observer = reinterpret_cast<nsIObserver*>(aObserver);
2866 if (mIdleObservers.Contains(observer)) {
2867 observer->Observe(nullptr, aTopic.get(), aTimeStr.get());
2868 } else {
2869 NS_WARNING("Received notification for an idle observer that was removed.");
2871 return IPC_OK();
2874 mozilla::ipc::IPCResult ContentChild::RecvLoadAndRegisterSheet(
2875 nsIURI* aURI, const uint32_t& aType) {
2876 if (!aURI) {
2877 return IPC_OK();
2880 nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance();
2881 if (sheetService) {
2882 sheetService->LoadAndRegisterSheet(aURI, aType);
2885 return IPC_OK();
2888 mozilla::ipc::IPCResult ContentChild::RecvUnregisterSheet(
2889 nsIURI* aURI, const uint32_t& aType) {
2890 if (!aURI) {
2891 return IPC_OK();
2894 nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance();
2895 if (sheetService) {
2896 sheetService->UnregisterSheet(aURI, aType);
2899 return IPC_OK();
2902 mozilla::ipc::IPCResult ContentChild::RecvDomainSetChanged(
2903 const uint32_t& aSetType, const uint32_t& aChangeType, nsIURI* aDomain) {
2904 if (aChangeType == ACTIVATE_POLICY) {
2905 if (mPolicy) {
2906 return IPC_OK();
2908 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
2909 MOZ_ASSERT(ssm);
2910 ssm->ActivateDomainPolicyInternal(getter_AddRefs(mPolicy));
2911 if (!mPolicy) {
2912 return IPC_FAIL_NO_REASON(this);
2914 return IPC_OK();
2916 if (!mPolicy) {
2917 MOZ_ASSERT_UNREACHABLE(
2918 "If the domain policy is not active yet,"
2919 " the first message should be ACTIVATE_POLICY");
2920 return IPC_FAIL_NO_REASON(this);
2923 NS_ENSURE_TRUE(mPolicy, IPC_FAIL_NO_REASON(this));
2925 if (aChangeType == DEACTIVATE_POLICY) {
2926 mPolicy->Deactivate();
2927 mPolicy = nullptr;
2928 return IPC_OK();
2931 nsCOMPtr<nsIDomainSet> set;
2932 switch (aSetType) {
2933 case BLOCKLIST:
2934 mPolicy->GetBlocklist(getter_AddRefs(set));
2935 break;
2936 case SUPER_BLOCKLIST:
2937 mPolicy->GetSuperBlocklist(getter_AddRefs(set));
2938 break;
2939 case ALLOWLIST:
2940 mPolicy->GetAllowlist(getter_AddRefs(set));
2941 break;
2942 case SUPER_ALLOWLIST:
2943 mPolicy->GetSuperAllowlist(getter_AddRefs(set));
2944 break;
2945 default:
2946 MOZ_ASSERT_UNREACHABLE("Unexpected setType");
2947 return IPC_FAIL_NO_REASON(this);
2950 MOZ_ASSERT(set);
2952 switch (aChangeType) {
2953 case ADD_DOMAIN:
2954 NS_ENSURE_TRUE(aDomain, IPC_FAIL_NO_REASON(this));
2955 set->Add(aDomain);
2956 break;
2957 case REMOVE_DOMAIN:
2958 NS_ENSURE_TRUE(aDomain, IPC_FAIL_NO_REASON(this));
2959 set->Remove(aDomain);
2960 break;
2961 case CLEAR_DOMAINS:
2962 set->Clear();
2963 break;
2964 default:
2965 MOZ_ASSERT_UNREACHABLE("Unexpected changeType");
2966 return IPC_FAIL_NO_REASON(this);
2969 return IPC_OK();
2972 void ContentChild::StartForceKillTimer() {
2973 if (mForceKillTimer) {
2974 return;
2977 int32_t timeoutSecs = StaticPrefs::dom_ipc_tabs_shutdownTimeoutSecs();
2978 if (timeoutSecs > 0) {
2979 NS_NewTimerWithFuncCallback(getter_AddRefs(mForceKillTimer),
2980 ContentChild::ForceKillTimerCallback, this,
2981 timeoutSecs * 1000, nsITimer::TYPE_ONE_SHOT,
2982 "dom::ContentChild::StartForceKillTimer");
2983 MOZ_ASSERT(mForceKillTimer);
2987 /* static */
2988 void ContentChild::ForceKillTimerCallback(nsITimer* aTimer, void* aClosure) {
2989 ProcessChild::QuickExit();
2992 mozilla::ipc::IPCResult ContentChild::RecvShutdownConfirmedHP() {
2993 ProcessChild::AppendToIPCShutdownStateAnnotation(
2994 "RecvShutdownConfirmedHP entry"_ns);
2996 // Bug 1755376: If we see "RecvShutdownConfirmedHP entry" often in
2997 // bug IPCError_ShutDownKill we might want to anticipate
2998 // ShutdownPhase::AppShutdownConfirmed to start here.
3000 return IPC_OK();
3003 mozilla::ipc::IPCResult ContentChild::RecvShutdown() {
3004 ProcessChild::AppendToIPCShutdownStateAnnotation("RecvShutdown entry"_ns);
3006 // Signal the ongoing shutdown to AppShutdown, this
3007 // will make abort nested SpinEventLoopUntilOrQuit loops
3008 AppShutdown::AdvanceShutdownPhaseWithoutNotify(
3009 ShutdownPhase::AppShutdownConfirmed);
3011 nsCOMPtr<nsIObserverService> os = services::GetObserverService();
3012 if (os) {
3013 ProcessChild::AppendToIPCShutdownStateAnnotation(
3014 "content-child-will-shutdown started"_ns);
3016 os->NotifyObservers(ToSupports(this), "content-child-will-shutdown",
3017 nullptr);
3020 ShutdownInternal();
3021 return IPC_OK();
3024 void ContentChild::ShutdownInternal() {
3025 ProcessChild::AppendToIPCShutdownStateAnnotation("ShutdownInternal entry"_ns);
3027 // If we receive the shutdown message from within a nested event loop, we want
3028 // to wait for that event loop to finish. Otherwise we could prematurely
3029 // terminate an "unload" or "pagehide" event handler (which might be doing a
3030 // sync XHR, for example).
3032 MOZ_ASSERT(NS_IsMainThread());
3033 RefPtr<nsThread> mainThread = nsThreadManager::get().GetCurrentThread();
3034 // Note that we only have to check the recursion count for the current
3035 // cooperative thread. Since the Shutdown message is not labeled with a
3036 // SchedulerGroup, there can be no other cooperative threads doing work while
3037 // we're running.
3038 if (mainThread && mainThread->RecursionDepth() > 1) {
3039 // We're in a nested event loop. Let's delay for an arbitrary period of
3040 // time (100ms) in the hopes that the event loop will have finished by
3041 // then.
3042 GetCurrentSerialEventTarget()->DelayedDispatch(
3043 NewRunnableMethod("dom::ContentChild::RecvShutdown", this,
3044 &ContentChild::ShutdownInternal),
3045 100);
3046 return;
3049 mShuttingDown = true;
3051 #ifdef NIGHTLY_BUILD
3052 BackgroundHangMonitor::UnregisterAnnotator(
3053 PendingInputEventHangAnnotator::sSingleton);
3054 #endif
3056 if (mPolicy) {
3057 mPolicy->Deactivate();
3058 mPolicy = nullptr;
3061 nsCOMPtr<nsIObserverService> os = services::GetObserverService();
3062 if (os) {
3063 ProcessChild::AppendToIPCShutdownStateAnnotation(
3064 "content-child-shutdown started"_ns);
3065 os->NotifyObservers(ToSupports(this), "content-child-shutdown", nullptr);
3068 GetIPCChannel()->SetAbortOnError(false);
3070 if (mProfilerController) {
3071 const bool isProfiling = profiler_is_active();
3072 CrashReporter::RecordAnnotationCString(
3073 CrashReporter::Annotation::ProfilerChildShutdownPhase,
3074 isProfiling ? "Profiling - GrabShutdownProfileAndShutdown"
3075 : "Not profiling - GrabShutdownProfileAndShutdown");
3076 ProfileAndAdditionalInformation shutdownProfileAndAdditionalInformation =
3077 mProfilerController->GrabShutdownProfileAndShutdown();
3078 CrashReporter::RecordAnnotationCString(
3079 CrashReporter::Annotation::ProfilerChildShutdownPhase,
3080 isProfiling ? "Profiling - Destroying ChildProfilerController"
3081 : "Not profiling - Destroying ChildProfilerController");
3082 mProfilerController = nullptr;
3083 CrashReporter::RecordAnnotationCString(
3084 CrashReporter::Annotation::ProfilerChildShutdownPhase,
3085 isProfiling ? "Profiling - SendShutdownProfile (sending)"
3086 : "Not profiling - SendShutdownProfile (sending)");
3087 if (const size_t len = shutdownProfileAndAdditionalInformation.SizeOf();
3088 len >= size_t(IPC::Channel::kMaximumMessageSize)) {
3089 shutdownProfileAndAdditionalInformation.mProfile = nsPrintfCString(
3090 "*Profile from pid %u bigger (%zu) than IPC max (%zu)",
3091 unsigned(profiler_current_process_id().ToNumber()), len,
3092 size_t(IPC::Channel::kMaximumMessageSize));
3094 // Send the shutdown profile to the parent process through our own
3095 // message channel, which we know will survive for long enough.
3096 bool sent =
3097 SendShutdownProfile(shutdownProfileAndAdditionalInformation.mProfile);
3098 CrashReporter::RecordAnnotationCString(
3099 CrashReporter::Annotation::ProfilerChildShutdownPhase,
3100 sent ? (isProfiling ? "Profiling - SendShutdownProfile (sent)"
3101 : "Not profiling - SendShutdownProfile (sent)")
3102 : (isProfiling ? "Profiling - SendShutdownProfile (failed)"
3103 : "Not profiling - SendShutdownProfile (failed)"));
3106 if (PerfStats::GetCollectionMask() != 0) {
3107 SendShutdownPerfStats(PerfStats::CollectLocalPerfStatsJSON());
3110 // Start a timer that will ensure we quickly exit after a reasonable period
3111 // of time. Prevents shutdown hangs after our connection to the parent
3112 // closes or when the parent is too busy to ever kill us.
3113 ProcessChild::AppendToIPCShutdownStateAnnotation("StartForceKillTimer"_ns);
3114 StartForceKillTimer();
3116 ProcessChild::AppendToIPCShutdownStateAnnotation(
3117 "SendFinishShutdown (sending)"_ns);
3119 // Notify the parent that we are done with shutdown. This is sent with high
3120 // priority and will just flag we are done.
3121 Unused << SendNotifyShutdownSuccess();
3123 // Now tell the parent to actually destroy our channel which will make end
3124 // our process. This is expected to be the last event the parent will
3125 // ever process for this ContentChild.
3126 bool sent = SendFinishShutdown();
3128 ProcessChild::AppendToIPCShutdownStateAnnotation(
3129 sent ? "SendFinishShutdown (sent)"_ns : "SendFinishShutdown (failed)"_ns);
3132 mozilla::ipc::IPCResult ContentChild::RecvUpdateWindow(
3133 const uintptr_t& aChildId) {
3134 MOZ_ASSERT(
3135 false,
3136 "ContentChild::RecvUpdateWindow calls unexpected on this platform.");
3137 return IPC_FAIL_NO_REASON(this);
3140 PContentPermissionRequestChild*
3141 ContentChild::AllocPContentPermissionRequestChild(
3142 Span<const PermissionRequest> aRequests, nsIPrincipal* aPrincipal,
3143 nsIPrincipal* aTopLevelPrincipal, const bool& aIsHandlingUserInput,
3144 const bool& aMaybeUnsafePermissionDelegate, const TabId& aTabId) {
3145 MOZ_CRASH("unused");
3146 return nullptr;
3149 bool ContentChild::DeallocPContentPermissionRequestChild(
3150 PContentPermissionRequestChild* actor) {
3151 nsContentPermissionUtils::NotifyRemoveContentPermissionRequestChild(actor);
3152 auto child = static_cast<RemotePermissionRequest*>(actor);
3153 child->IPDLRelease();
3154 return true;
3157 already_AddRefed<PWebBrowserPersistDocumentChild>
3158 ContentChild::AllocPWebBrowserPersistDocumentChild(
3159 PBrowserChild* aBrowser, const MaybeDiscarded<BrowsingContext>& aContext) {
3160 return MakeAndAddRef<WebBrowserPersistDocumentChild>();
3163 mozilla::ipc::IPCResult ContentChild::RecvPWebBrowserPersistDocumentConstructor(
3164 PWebBrowserPersistDocumentChild* aActor, PBrowserChild* aBrowser,
3165 const MaybeDiscarded<BrowsingContext>& aContext) {
3166 if (NS_WARN_IF(!aBrowser)) {
3167 return IPC_FAIL_NO_REASON(this);
3170 if (aContext.IsNullOrDiscarded()) {
3171 aActor->SendInitFailure(NS_ERROR_NO_CONTENT);
3172 return IPC_OK();
3175 nsCOMPtr<Document> foundDoc = aContext.get()->GetDocument();
3177 if (!foundDoc) {
3178 aActor->SendInitFailure(NS_ERROR_NO_CONTENT);
3179 } else {
3180 static_cast<WebBrowserPersistDocumentChild*>(aActor)->Start(foundDoc);
3182 return IPC_OK();
3185 mozilla::ipc::IPCResult ContentChild::RecvPush(const nsCString& aScope,
3186 nsIPrincipal* aPrincipal,
3187 const nsString& aMessageId) {
3188 PushMessageDispatcher dispatcher(aScope, aPrincipal, aMessageId, Nothing());
3189 Unused << NS_WARN_IF(NS_FAILED(dispatcher.NotifyObserversAndWorkers()));
3190 return IPC_OK();
3193 mozilla::ipc::IPCResult ContentChild::RecvPushWithData(
3194 const nsCString& aScope, nsIPrincipal* aPrincipal,
3195 const nsString& aMessageId, nsTArray<uint8_t>&& aData) {
3196 PushMessageDispatcher dispatcher(aScope, aPrincipal, aMessageId,
3197 Some(std::move(aData)));
3198 Unused << NS_WARN_IF(NS_FAILED(dispatcher.NotifyObserversAndWorkers()));
3199 return IPC_OK();
3202 mozilla::ipc::IPCResult ContentChild::RecvPushSubscriptionChange(
3203 const nsCString& aScope, nsIPrincipal* aPrincipal) {
3204 PushSubscriptionChangeDispatcher dispatcher(aScope, aPrincipal);
3205 Unused << NS_WARN_IF(NS_FAILED(dispatcher.NotifyObserversAndWorkers()));
3206 return IPC_OK();
3209 mozilla::ipc::IPCResult ContentChild::RecvPushError(const nsCString& aScope,
3210 nsIPrincipal* aPrincipal,
3211 const nsString& aMessage,
3212 const uint32_t& aFlags) {
3213 PushErrorDispatcher dispatcher(aScope, aPrincipal, aMessage, aFlags);
3214 Unused << NS_WARN_IF(NS_FAILED(dispatcher.NotifyObserversAndWorkers()));
3215 return IPC_OK();
3218 mozilla::ipc::IPCResult
3219 ContentChild::RecvNotifyPushSubscriptionModifiedObservers(
3220 const nsCString& aScope, nsIPrincipal* aPrincipal) {
3221 PushSubscriptionModifiedDispatcher dispatcher(aScope, aPrincipal);
3222 Unused << NS_WARN_IF(NS_FAILED(dispatcher.NotifyObservers()));
3223 return IPC_OK();
3226 mozilla::ipc::IPCResult ContentChild::RecvBlobURLRegistration(
3227 const nsCString& aURI, const IPCBlob& aBlob, nsIPrincipal* aPrincipal,
3228 const nsCString& aPartitionKey) {
3229 RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(aBlob);
3230 MOZ_ASSERT(blobImpl);
3232 BlobURLProtocolHandler::AddDataEntry(aURI, aPrincipal, aPartitionKey,
3233 blobImpl);
3234 return IPC_OK();
3237 mozilla::ipc::IPCResult ContentChild::RecvBlobURLUnregistration(
3238 const nsCString& aURI) {
3239 BlobURLProtocolHandler::RemoveDataEntry(
3240 aURI,
3241 /* aBroadcastToOtherProcesses = */ false);
3242 return IPC_OK();
3245 void ContentChild::CreateGetFilesRequest(const nsAString& aDirectoryPath,
3246 bool aRecursiveFlag, nsID& aUUID,
3247 GetFilesHelperChild* aChild) {
3248 MOZ_ASSERT(aChild);
3249 MOZ_ASSERT(!mGetFilesPendingRequests.Contains(aUUID));
3251 Unused << SendGetFilesRequest(aUUID, aDirectoryPath, aRecursiveFlag);
3252 mGetFilesPendingRequests.InsertOrUpdate(aUUID, RefPtr{aChild});
3255 void ContentChild::DeleteGetFilesRequest(nsID& aUUID,
3256 GetFilesHelperChild* aChild) {
3257 MOZ_ASSERT(aChild);
3258 MOZ_ASSERT(mGetFilesPendingRequests.Contains(aUUID));
3260 Unused << SendDeleteGetFilesRequest(aUUID);
3261 mGetFilesPendingRequests.Remove(aUUID);
3264 mozilla::ipc::IPCResult ContentChild::RecvGetFilesResponse(
3265 const nsID& aUUID, const GetFilesResponseResult& aResult) {
3266 RefPtr<GetFilesHelperChild> child;
3268 // This object can already been deleted in case DeleteGetFilesRequest has
3269 // been called when the response was sending by the parent.
3270 if (!mGetFilesPendingRequests.Remove(aUUID, getter_AddRefs(child))) {
3271 return IPC_OK();
3274 if (aResult.type() == GetFilesResponseResult::TGetFilesResponseFailure) {
3275 child->Finished(aResult.get_GetFilesResponseFailure().errorCode());
3276 } else {
3277 MOZ_ASSERT(aResult.type() ==
3278 GetFilesResponseResult::TGetFilesResponseSuccess);
3280 const nsTArray<IPCBlob>& ipcBlobs =
3281 aResult.get_GetFilesResponseSuccess().blobs();
3283 bool succeeded = true;
3284 for (uint32_t i = 0; succeeded && i < ipcBlobs.Length(); ++i) {
3285 RefPtr<BlobImpl> impl = IPCBlobUtils::Deserialize(ipcBlobs[i]);
3286 succeeded = child->AppendBlobImpl(impl);
3289 child->Finished(succeeded ? NS_OK : NS_ERROR_OUT_OF_MEMORY);
3291 return IPC_OK();
3294 /* static */
3295 void ContentChild::FatalErrorIfNotUsingGPUProcess(const char* const aErrorMsg,
3296 GeckoChildID aChildID) {
3297 // If we're communicating with the same process or the UI process then we
3298 // want to crash normally. Otherwise we want to just warn as the other end
3299 // must be the GPU process and it crashing shouldn't be fatal for us.
3300 if (aChildID == XRE_GetChildID() || aChildID == 0) {
3301 mozilla::ipc::FatalError(aErrorMsg, false);
3302 } else {
3303 nsAutoCString formattedMessage("IPDL error: \"");
3304 formattedMessage.AppendASCII(aErrorMsg);
3305 formattedMessage.AppendLiteral(R"(".)");
3306 NS_WARNING(formattedMessage.get());
3310 PURLClassifierChild* ContentChild::AllocPURLClassifierChild(
3311 nsIPrincipal* aPrincipal, bool* aSuccess) {
3312 *aSuccess = true;
3313 return new URLClassifierChild();
3316 bool ContentChild::DeallocPURLClassifierChild(PURLClassifierChild* aActor) {
3317 MOZ_ASSERT(aActor);
3318 delete aActor;
3319 return true;
3322 PURLClassifierLocalChild* ContentChild::AllocPURLClassifierLocalChild(
3323 nsIURI* aUri, Span<const IPCURLClassifierFeature> aFeatures) {
3324 return new URLClassifierLocalChild();
3327 bool ContentChild::DeallocPURLClassifierLocalChild(
3328 PURLClassifierLocalChild* aActor) {
3329 MOZ_ASSERT(aActor);
3330 delete aActor;
3331 return true;
3334 PSessionStorageObserverChild*
3335 ContentChild::AllocPSessionStorageObserverChild() {
3336 MOZ_CRASH(
3337 "PSessionStorageObserverChild actors should be manually constructed!");
3340 bool ContentChild::DeallocPSessionStorageObserverChild(
3341 PSessionStorageObserverChild* aActor) {
3342 MOZ_ASSERT(aActor);
3344 delete aActor;
3345 return true;
3348 mozilla::ipc::IPCResult ContentChild::RecvProvideAnonymousTemporaryFile(
3349 const uint64_t& aID, const FileDescOrError& aFDOrError) {
3350 mozilla::UniquePtr<AnonymousTemporaryFileCallback> callback;
3351 mPendingAnonymousTemporaryFiles.Remove(aID, &callback);
3352 MOZ_ASSERT(callback);
3354 PRFileDesc* prfile = nullptr;
3355 if (aFDOrError.type() == FileDescOrError::Tnsresult) {
3356 DebugOnly<nsresult> rv = aFDOrError.get_nsresult();
3357 MOZ_ASSERT(NS_FAILED(rv));
3358 } else {
3359 auto rawFD = aFDOrError.get_FileDescriptor().ClonePlatformHandle();
3360 prfile = PR_ImportFile(PROsfd(rawFD.release()));
3362 (*callback)(prfile);
3363 return IPC_OK();
3366 nsresult ContentChild::AsyncOpenAnonymousTemporaryFile(
3367 const AnonymousTemporaryFileCallback& aCallback) {
3368 MOZ_ASSERT(NS_IsMainThread());
3370 static uint64_t id = 0;
3371 auto newID = id++;
3372 if (!SendRequestAnonymousTemporaryFile(newID)) {
3373 return NS_ERROR_FAILURE;
3376 // Remember the association with the callback.
3377 MOZ_ASSERT(!mPendingAnonymousTemporaryFiles.Get(newID));
3378 mPendingAnonymousTemporaryFiles.GetOrInsertNew(newID, aCallback);
3379 return NS_OK;
3382 mozilla::ipc::IPCResult ContentChild::RecvSetPermissionsWithKey(
3383 const nsCString& aPermissionKey, nsTArray<IPC::Permission>&& aPerms) {
3384 RefPtr<PermissionManager> permManager = PermissionManager::GetInstance();
3385 if (permManager) {
3386 permManager->SetPermissionsWithKey(aPermissionKey, aPerms);
3389 return IPC_OK();
3392 mozilla::ipc::IPCResult ContentChild::RecvRefreshScreens(
3393 nsTArray<ScreenDetails>&& aScreens) {
3394 ScreenManager& screenManager = ScreenManager::GetSingleton();
3395 screenManager.Refresh(std::move(aScreens));
3396 return IPC_OK();
3399 mozilla::ipc::IPCResult ContentChild::RecvShareCodeCoverageMutex(
3400 CrossProcessMutexHandle aHandle) {
3401 #ifdef MOZ_CODE_COVERAGE
3402 CodeCoverageHandler::Init(std::move(aHandle));
3403 return IPC_OK();
3404 #else
3405 MOZ_CRASH("Shouldn't receive this message in non-code coverage builds!");
3406 #endif
3409 mozilla::ipc::IPCResult ContentChild::RecvFlushCodeCoverageCounters(
3410 FlushCodeCoverageCountersResolver&& aResolver) {
3411 #ifdef MOZ_CODE_COVERAGE
3412 CodeCoverageHandler::FlushCounters();
3413 aResolver(/* unused */ true);
3414 return IPC_OK();
3415 #else
3416 MOZ_CRASH("Shouldn't receive this message in non-code coverage builds!");
3417 #endif
3420 mozilla::ipc::IPCResult ContentChild::RecvSetInputEventQueueEnabled() {
3421 nsThreadManager::get().EnableMainThreadEventPrioritization();
3422 return IPC_OK();
3425 mozilla::ipc::IPCResult ContentChild::RecvFlushInputEventQueue() {
3426 nsThreadManager::get().FlushInputEventPrioritization();
3427 return IPC_OK();
3430 mozilla::ipc::IPCResult ContentChild::RecvSuspendInputEventQueue() {
3431 nsThreadManager::get().SuspendInputEventPrioritization();
3432 return IPC_OK();
3435 mozilla::ipc::IPCResult ContentChild::RecvResumeInputEventQueue() {
3436 nsThreadManager::get().ResumeInputEventPrioritization();
3437 return IPC_OK();
3440 mozilla::ipc::IPCResult ContentChild::RecvAddDynamicScalars(
3441 nsTArray<DynamicScalarDefinition>&& aDefs) {
3442 TelemetryIPC::AddDynamicScalarDefinitions(aDefs);
3443 return IPC_OK();
3446 mozilla::ipc::IPCResult ContentChild::RecvCrossProcessRedirect(
3447 RedirectToRealChannelArgs&& aArgs,
3448 nsTArray<Endpoint<extensions::PStreamFilterParent>>&& aEndpoints,
3449 CrossProcessRedirectResolver&& aResolve) {
3450 nsCOMPtr<nsILoadInfo> loadInfo;
3451 nsresult rv = mozilla::ipc::LoadInfoArgsToLoadInfo(
3452 aArgs.loadInfo(), NOT_REMOTE_TYPE, getter_AddRefs(loadInfo));
3453 if (NS_FAILED(rv)) {
3454 MOZ_DIAGNOSTIC_CRASH("LoadInfoArgsToLoadInfo failed");
3455 return IPC_OK();
3458 nsCOMPtr<nsIChannel> newChannel;
3459 MOZ_ASSERT((aArgs.loadStateInternalLoadFlags() &
3460 nsDocShell::InternalLoad::INTERNAL_LOAD_FLAGS_IS_SRCDOC) ||
3461 aArgs.srcdocData().IsVoid());
3462 rv = nsDocShell::CreateRealChannelForDocument(
3463 getter_AddRefs(newChannel), aArgs.uri(), loadInfo, nullptr,
3464 aArgs.newLoadFlags(), aArgs.srcdocData(), aArgs.baseUri());
3466 if (RefPtr<HttpBaseChannel> httpChannel = do_QueryObject(newChannel)) {
3467 httpChannel->SetEarlyHints(std::move(aArgs.earlyHints()));
3468 httpChannel->SetEarlyHintLinkType(aArgs.earlyHintLinkType());
3471 // This is used to report any errors back to the parent by calling
3472 // CrossProcessRedirectFinished.
3473 RefPtr<HttpChannelChild> httpChild = do_QueryObject(newChannel);
3474 auto resolve = [=](const nsresult& aRv) {
3475 nsresult rv = aRv;
3476 if (httpChild) {
3477 rv = httpChild->CrossProcessRedirectFinished(rv);
3479 aResolve(rv);
3481 auto scopeExit = MakeScopeExit([&]() { resolve(rv); });
3483 if (NS_FAILED(rv)) {
3484 return IPC_OK();
3487 if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel)) {
3488 rv = httpChannel->SetChannelId(aArgs.channelId());
3490 if (NS_FAILED(rv)) {
3491 return IPC_OK();
3494 rv = newChannel->SetOriginalURI(aArgs.originalURI());
3495 if (NS_FAILED(rv)) {
3496 return IPC_OK();
3499 if (nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal =
3500 do_QueryInterface(newChannel)) {
3501 rv = httpChannelInternal->SetRedirectMode(aArgs.redirectMode());
3503 if (NS_FAILED(rv)) {
3504 return IPC_OK();
3507 if (aArgs.init()) {
3508 HttpBaseChannel::ReplacementChannelConfig config(std::move(*aArgs.init()));
3509 HttpBaseChannel::ConfigureReplacementChannel(
3510 newChannel, config,
3511 HttpBaseChannel::ReplacementReason::DocumentChannel);
3514 if (aArgs.contentDisposition()) {
3515 newChannel->SetContentDisposition(*aArgs.contentDisposition());
3518 if (aArgs.contentDispositionFilename()) {
3519 newChannel->SetContentDispositionFilename(
3520 *aArgs.contentDispositionFilename());
3523 if (nsCOMPtr<nsIChildChannel> childChannel = do_QueryInterface(newChannel)) {
3524 // Connect to the parent if this is a remote channel. If it's entirely
3525 // handled locally, then we'll call AsyncOpen from the docshell when
3526 // we complete the setup
3527 rv = childChannel->ConnectParent(
3528 aArgs.registrarId()); // creates parent channel
3529 if (NS_FAILED(rv)) {
3530 return IPC_OK();
3534 // We need to copy the property bag before signaling that the channel
3535 // is ready so that the nsDocShell can retrieve the history data when called.
3536 if (nsCOMPtr<nsIWritablePropertyBag> bag = do_QueryInterface(newChannel)) {
3537 nsHashPropertyBag::CopyFrom(bag, aArgs.properties());
3540 RefPtr<nsDocShellLoadState> loadState;
3541 rv = nsDocShellLoadState::CreateFromPendingChannel(
3542 newChannel, aArgs.loadIdentifier(), aArgs.registrarId(),
3543 getter_AddRefs(loadState));
3544 if (NS_WARN_IF(NS_FAILED(rv))) {
3545 return IPC_OK();
3547 loadState->SetLoadFlags(aArgs.loadStateExternalLoadFlags());
3548 loadState->SetInternalLoadFlags(aArgs.loadStateInternalLoadFlags());
3549 if (IsValidLoadType(aArgs.loadStateLoadType())) {
3550 loadState->SetLoadType(aArgs.loadStateLoadType());
3553 if (aArgs.loadingSessionHistoryInfo().isSome()) {
3554 loadState->SetLoadingSessionHistoryInfo(
3555 aArgs.loadingSessionHistoryInfo().ref());
3557 if (aArgs.originalUriString().isSome()) {
3558 loadState->SetOriginalURIString(aArgs.originalUriString().ref());
3561 RefPtr<ChildProcessChannelListener> processListener =
3562 ChildProcessChannelListener::GetSingleton();
3563 // The listener will call completeRedirectSetup or asyncOpen on the channel.
3564 processListener->OnChannelReady(loadState, aArgs.loadIdentifier(),
3565 std::move(aEndpoints), aArgs.timing(),
3566 std::move(resolve));
3567 scopeExit.release();
3569 // scopeExit will call CrossProcessRedirectFinished(rv) here
3570 return IPC_OK();
3573 mozilla::ipc::IPCResult ContentChild::RecvStartDelayedAutoplayMediaComponents(
3574 const MaybeDiscarded<BrowsingContext>& aContext) {
3575 if (NS_WARN_IF(aContext.IsNullOrDiscarded())) {
3576 return IPC_OK();
3579 aContext.get()->StartDelayedAutoplayMediaComponents();
3580 return IPC_OK();
3583 mozilla::ipc::IPCResult ContentChild::RecvUpdateMediaControlAction(
3584 const MaybeDiscarded<BrowsingContext>& aContext,
3585 const MediaControlAction& aAction) {
3586 if (NS_WARN_IF(aContext.IsNullOrDiscarded())) {
3587 return IPC_OK();
3590 ContentMediaControlKeyHandler::HandleMediaControlAction(aContext.get(),
3591 aAction);
3592 return IPC_OK();
3595 mozilla::ipc::IPCResult ContentChild::RecvOnAllowAccessFor(
3596 const MaybeDiscarded<BrowsingContext>& aContext,
3597 const nsCString& aTrackingOrigin, uint32_t aCookieBehavior,
3598 const ContentBlockingNotifier::StorageAccessPermissionGrantedReason&
3599 aReason) {
3600 MOZ_ASSERT(!aContext.IsNull(), "Browsing context cannot be null");
3602 StorageAccessAPIHelper::OnAllowAccessFor(
3603 aContext.GetMaybeDiscarded(), aTrackingOrigin, aCookieBehavior, aReason);
3605 return IPC_OK();
3608 mozilla::ipc::IPCResult ContentChild::RecvOnContentBlockingDecision(
3609 const MaybeDiscarded<BrowsingContext>& aContext,
3610 const ContentBlockingNotifier::BlockingDecision& aDecision,
3611 uint32_t aRejectedReason) {
3612 MOZ_ASSERT(!aContext.IsNull(), "Browsing context cannot be null");
3614 nsCOMPtr<nsPIDOMWindowOuter> outer = aContext.get()->GetDOMWindow();
3615 if (!outer) {
3616 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3617 ("ChildIPC: Trying to send a message to a context without a outer "
3618 "window"));
3619 return IPC_OK();
3622 nsCOMPtr<nsPIDOMWindowInner> inner = outer->GetCurrentInnerWindow();
3623 if (!inner) {
3624 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3625 ("ChildIPC: Trying to send a message to a context without a inner "
3626 "window"));
3627 return IPC_OK();
3630 ContentBlockingNotifier::OnDecision(inner, aDecision, aRejectedReason);
3631 return IPC_OK();
3634 #ifdef NIGHTLY_BUILD
3635 void ContentChild::OnChannelReceivedMessage(const Message& aMsg) {
3636 if (nsContentUtils::IsMessageInputEvent(aMsg)) {
3637 mPendingInputEvents++;
3641 PContentChild::Result ContentChild::OnMessageReceived(const Message& aMsg) {
3642 if (nsContentUtils::IsMessageInputEvent(aMsg)) {
3643 DebugOnly<uint32_t> prevEvts = mPendingInputEvents--;
3644 MOZ_ASSERT(prevEvts > 0);
3647 return PContentChild::OnMessageReceived(aMsg);
3650 PContentChild::Result ContentChild::OnMessageReceived(
3651 const Message& aMsg, UniquePtr<Message>& aReply) {
3652 return PContentChild::OnMessageReceived(aMsg, aReply);
3654 #endif
3656 mozilla::ipc::IPCResult ContentChild::RecvCreateBrowsingContext(
3657 uint64_t aGroupId, BrowsingContext::IPCInitializer&& aInit) {
3658 // We can't already have a BrowsingContext with this ID.
3659 if (RefPtr<BrowsingContext> existing = BrowsingContext::Get(aInit.mId)) {
3660 return IPC_FAIL(this, "Browsing context already exists");
3663 RefPtr<WindowContext> parent = WindowContext::GetById(aInit.mParentId);
3664 if (!parent && aInit.mParentId != 0) {
3665 // Handle this case by ignoring the request, as parent must be in the
3666 // process of being discarded.
3667 // In the future it would be nice to avoid sending this message to the child
3668 // at all.
3669 NS_WARNING("Attempt to attach BrowsingContext to discarded parent");
3670 return IPC_OK();
3673 RefPtr<BrowsingContextGroup> group =
3674 BrowsingContextGroup::GetOrCreate(aGroupId);
3675 return BrowsingContext::CreateFromIPC(std::move(aInit), group, nullptr);
3678 mozilla::ipc::IPCResult ContentChild::RecvDiscardBrowsingContext(
3679 const MaybeDiscarded<BrowsingContext>& aContext, bool aDoDiscard,
3680 DiscardBrowsingContextResolver&& aResolve) {
3681 if (BrowsingContext* context = aContext.GetMaybeDiscarded()) {
3682 if (aDoDiscard && !context->IsDiscarded()) {
3683 context->Detach(/* aFromIPC */ true);
3685 context->AddDiscardListener(aResolve);
3686 return IPC_OK();
3689 // Immediately resolve the promise, as we've received the message. This will
3690 // allow the parent process to discard references to this BC.
3691 aResolve(true);
3692 return IPC_OK();
3695 mozilla::ipc::IPCResult ContentChild::RecvRegisterBrowsingContextGroup(
3696 uint64_t aGroupId, nsTArray<SyncedContextInitializer>&& aInits) {
3697 RefPtr<BrowsingContextGroup> group =
3698 BrowsingContextGroup::GetOrCreate(aGroupId);
3700 // Each of the initializers in aInits is sorted in pre-order, so our parent
3701 // should always be available before the element itself.
3702 for (auto& initUnion : aInits) {
3703 switch (initUnion.type()) {
3704 case SyncedContextInitializer::TBrowsingContextInitializer: {
3705 auto& init = initUnion.get_BrowsingContextInitializer();
3706 #ifdef DEBUG
3707 RefPtr<BrowsingContext> existing = BrowsingContext::Get(init.mId);
3708 MOZ_ASSERT(!existing, "BrowsingContext must not exist yet!");
3710 RefPtr<WindowContext> parent = init.GetParent();
3711 MOZ_ASSERT_IF(parent, parent->Group() == group);
3712 #endif
3714 BrowsingContext::CreateFromIPC(std::move(init), group, nullptr);
3715 break;
3717 case SyncedContextInitializer::TWindowContextInitializer: {
3718 auto& init = initUnion.get_WindowContextInitializer();
3719 #ifdef DEBUG
3720 RefPtr<WindowContext> existing =
3721 WindowContext::GetById(init.mInnerWindowId);
3722 MOZ_ASSERT(!existing, "WindowContext must not exist yet!");
3723 RefPtr<BrowsingContext> parent =
3724 BrowsingContext::Get(init.mBrowsingContextId);
3725 MOZ_ASSERT(parent && parent->Group() == group);
3726 #endif
3728 WindowContext::CreateFromIPC(std::move(init));
3729 break;
3731 default:
3732 MOZ_ASSERT_UNREACHABLE();
3736 return IPC_OK();
3739 mozilla::ipc::IPCResult ContentChild::RecvDestroyBrowsingContextGroup(
3740 uint64_t aGroupId) {
3741 if (RefPtr<BrowsingContextGroup> group =
3742 BrowsingContextGroup::GetExisting(aGroupId)) {
3743 group->ChildDestroy();
3745 return IPC_OK();
3748 mozilla::ipc::IPCResult ContentChild::RecvWindowClose(
3749 const MaybeDiscarded<BrowsingContext>& aContext, bool aTrustedCaller) {
3750 if (aContext.IsNullOrDiscarded()) {
3751 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3752 ("ChildIPC: Trying to send a message to dead or detached context"));
3753 return IPC_OK();
3756 nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow();
3757 if (!window) {
3758 MOZ_LOG(
3759 BrowsingContext::GetLog(), LogLevel::Debug,
3760 ("ChildIPC: Trying to send a message to a context without a window"));
3761 return IPC_OK();
3764 // Call `GetDocument()` to force the document and its inner window to be
3765 // created, as it would be forced to be created if this call was being
3766 // performed in-process.
3767 if (NS_WARN_IF(!aContext.get()->GetDocument())) {
3768 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3769 ("ChildIPC: Trying to send a message to a context but document "
3770 "creation failed"));
3771 return IPC_OK();
3774 nsGlobalWindowOuter::Cast(window)->CloseOuter(aTrustedCaller);
3775 return IPC_OK();
3778 mozilla::ipc::IPCResult ContentChild::RecvWindowFocus(
3779 const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType,
3780 uint64_t aActionId) {
3781 if (aContext.IsNullOrDiscarded()) {
3782 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3783 ("ChildIPC: Trying to send a message to dead or detached context"));
3784 return IPC_OK();
3787 nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow();
3788 if (!window) {
3789 MOZ_LOG(
3790 BrowsingContext::GetLog(), LogLevel::Debug,
3791 ("ChildIPC: Trying to send a message to a context without a window"));
3792 return IPC_OK();
3795 // Call `GetDocument()` to force the document and its inner window to be
3796 // created, as it would be forced to be created if this call was being
3797 // performed in-process.
3798 if (NS_WARN_IF(!aContext.get()->GetDocument())) {
3799 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3800 ("ChildIPC: Trying to send a message to a context but document "
3801 "creation failed"));
3802 return IPC_OK();
3805 nsGlobalWindowOuter::Cast(window)->FocusOuter(
3806 aCallerType, /* aFromOtherProcess */ true, aActionId);
3807 return IPC_OK();
3810 mozilla::ipc::IPCResult ContentChild::RecvWindowBlur(
3811 const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType) {
3812 if (aContext.IsNullOrDiscarded()) {
3813 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3814 ("ChildIPC: Trying to send a message to dead or detached context"));
3815 return IPC_OK();
3818 nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow();
3819 if (!window) {
3820 MOZ_LOG(
3821 BrowsingContext::GetLog(), LogLevel::Debug,
3822 ("ChildIPC: Trying to send a message to a context without a window"));
3823 return IPC_OK();
3826 // Call `GetDocument()` to force the document and its inner window to be
3827 // created, as it would be forced to be created if this call was being
3828 // performed in-process.
3829 if (NS_WARN_IF(!aContext.get()->GetDocument())) {
3830 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3831 ("ChildIPC: Trying to send a message to a context but document "
3832 "creation failed"));
3833 return IPC_OK();
3836 nsGlobalWindowOuter::Cast(window)->BlurOuter(aCallerType);
3837 return IPC_OK();
3840 mozilla::ipc::IPCResult ContentChild::RecvRaiseWindow(
3841 const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType,
3842 uint64_t aActionId) {
3843 if (aContext.IsNullOrDiscarded()) {
3844 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3845 ("ChildIPC: Trying to send a message to dead or detached context"));
3846 return IPC_OK();
3849 nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow();
3850 if (!window) {
3851 MOZ_LOG(
3852 BrowsingContext::GetLog(), LogLevel::Debug,
3853 ("ChildIPC: Trying to send a message to a context without a window"));
3854 return IPC_OK();
3857 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
3858 fm->RaiseWindow(window, aCallerType, aActionId);
3860 return IPC_OK();
3863 mozilla::ipc::IPCResult ContentChild::RecvAdjustWindowFocus(
3864 const MaybeDiscarded<BrowsingContext>& aContext, bool aIsVisible,
3865 uint64_t aActionId, bool aShouldClearAncestorFocus,
3866 const MaybeDiscarded<BrowsingContext>& aAncestorBrowsingContextToFocus) {
3867 if (aContext.IsNullOrDiscarded()) {
3868 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3869 ("ChildIPC: Trying to send a message to dead or detached context"));
3870 return IPC_OK();
3873 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
3874 RefPtr<BrowsingContext> bc = aContext.get();
3875 RefPtr<BrowsingContext> ancestor =
3876 aAncestorBrowsingContextToFocus.IsNullOrDiscarded()
3877 ? nullptr
3878 : aAncestorBrowsingContextToFocus.get();
3879 fm->AdjustInProcessWindowFocus(bc, false, aIsVisible, aActionId,
3880 aShouldClearAncestorFocus, ancestor);
3882 return IPC_OK();
3885 mozilla::ipc::IPCResult ContentChild::RecvClearFocus(
3886 const MaybeDiscarded<BrowsingContext>& aContext) {
3887 if (aContext.IsNullOrDiscarded()) {
3888 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3889 ("ChildIPC: Trying to send a message to dead or detached context"));
3890 return IPC_OK();
3893 nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow();
3894 if (!window) {
3895 MOZ_LOG(
3896 BrowsingContext::GetLog(), LogLevel::Debug,
3897 ("ChildIPC: Trying to send a message to a context without a window"));
3898 return IPC_OK();
3901 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
3902 fm->ClearFocus(window);
3904 return IPC_OK();
3907 mozilla::ipc::IPCResult ContentChild::RecvSetFocusedBrowsingContext(
3908 const MaybeDiscarded<BrowsingContext>& aContext, uint64_t aActionId) {
3909 if (aContext.IsNullOrDiscarded()) {
3910 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3911 ("ChildIPC: Trying to send a message to dead or detached context"));
3912 return IPC_OK();
3915 nsFocusManager* fm = nsFocusManager::GetFocusManager();
3916 if (fm) {
3917 fm->SetFocusedBrowsingContextFromOtherProcess(aContext.get(), aActionId);
3919 return IPC_OK();
3922 mozilla::ipc::IPCResult ContentChild::RecvSetActiveBrowsingContext(
3923 const MaybeDiscarded<BrowsingContext>& aContext, uint64_t aActionId) {
3924 if (aContext.IsNullOrDiscarded()) {
3925 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3926 ("ChildIPC: Trying to send a message to dead or detached context"));
3927 return IPC_OK();
3930 nsFocusManager* fm = nsFocusManager::GetFocusManager();
3931 if (fm) {
3932 fm->SetActiveBrowsingContextFromOtherProcess(aContext.get(), aActionId);
3934 return IPC_OK();
3937 mozilla::ipc::IPCResult ContentChild::RecvAbortOrientationPendingPromises(
3938 const MaybeDiscarded<BrowsingContext>& aContext) {
3939 if (aContext.IsNullOrDiscarded()) {
3940 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3941 ("ChildIPC: Trying to send a message to dead or detached context"));
3942 return IPC_OK();
3945 dom::ScreenOrientation::AbortInProcessOrientationPromises(aContext.get());
3946 return IPC_OK();
3949 mozilla::ipc::IPCResult ContentChild::RecvUnsetActiveBrowsingContext(
3950 const MaybeDiscarded<BrowsingContext>& aContext, uint64_t aActionId) {
3951 if (aContext.IsNullOrDiscarded()) {
3952 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3953 ("ChildIPC: Trying to send a message to dead or detached context"));
3954 return IPC_OK();
3957 nsFocusManager* fm = nsFocusManager::GetFocusManager();
3958 if (fm) {
3959 fm->UnsetActiveBrowsingContextFromOtherProcess(aContext.get(), aActionId);
3961 return IPC_OK();
3964 mozilla::ipc::IPCResult ContentChild::RecvSetFocusedElement(
3965 const MaybeDiscarded<BrowsingContext>& aContext, bool aNeedsFocus) {
3966 if (aContext.IsNullOrDiscarded()) {
3967 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3968 ("ChildIPC: Trying to send a message to dead or detached context"));
3969 return IPC_OK();
3972 nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow();
3973 if (!window) {
3974 MOZ_LOG(
3975 BrowsingContext::GetLog(), LogLevel::Debug,
3976 ("ChildIPC: Trying to send a message to a context without a window"));
3977 return IPC_OK();
3980 window->SetFocusedElement(nullptr, 0, aNeedsFocus);
3981 return IPC_OK();
3984 mozilla::ipc::IPCResult ContentChild::RecvFinalizeFocusOuter(
3985 const MaybeDiscarded<BrowsingContext>& aContext, bool aCanFocus,
3986 CallerType aCallerType) {
3987 if (aContext.IsNullOrDiscarded()) {
3988 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3989 ("ChildIPC: Trying to send a message to dead or detached context"));
3990 return IPC_OK();
3993 if (Element* frame = aContext.get()->GetEmbedderElement()) {
3994 nsContentUtils::RequestFrameFocus(*frame, aCanFocus, aCallerType);
3997 return IPC_OK();
4000 mozilla::ipc::IPCResult ContentChild::RecvBlurToChild(
4001 const MaybeDiscarded<BrowsingContext>& aFocusedBrowsingContext,
4002 const MaybeDiscarded<BrowsingContext>& aBrowsingContextToClear,
4003 const MaybeDiscarded<BrowsingContext>& aAncestorBrowsingContextToFocus,
4004 bool aIsLeavingDocument, bool aAdjustWidget, uint64_t aActionId) {
4005 if (aFocusedBrowsingContext.IsNullOrDiscarded()) {
4006 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
4007 ("ChildIPC: Trying to send a message to dead or detached context"));
4008 return IPC_OK();
4011 RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager();
4012 if (MOZ_UNLIKELY(!fm)) {
4013 return IPC_OK();
4016 RefPtr<BrowsingContext> toClear = aBrowsingContextToClear.IsDiscarded()
4017 ? nullptr
4018 : aBrowsingContextToClear.get();
4019 RefPtr<BrowsingContext> toFocus =
4020 aAncestorBrowsingContextToFocus.IsDiscarded()
4021 ? nullptr
4022 : aAncestorBrowsingContextToFocus.get();
4024 RefPtr<BrowsingContext> focusedBrowsingContext =
4025 aFocusedBrowsingContext.get();
4027 fm->BlurFromOtherProcess(focusedBrowsingContext, toClear, toFocus,
4028 aIsLeavingDocument, aAdjustWidget, aActionId);
4029 return IPC_OK();
4032 mozilla::ipc::IPCResult ContentChild::RecvSetupFocusedAndActive(
4033 const MaybeDiscarded<BrowsingContext>& aFocusedBrowsingContext,
4034 uint64_t aActionIdForFocused,
4035 const MaybeDiscarded<BrowsingContext>& aActiveBrowsingContext,
4036 uint64_t aActionIdForActive) {
4037 nsFocusManager* fm = nsFocusManager::GetFocusManager();
4038 if (fm) {
4039 if (!aActiveBrowsingContext.IsNullOrDiscarded()) {
4040 fm->SetActiveBrowsingContextFromOtherProcess(aActiveBrowsingContext.get(),
4041 aActionIdForActive);
4043 if (!aFocusedBrowsingContext.IsNullOrDiscarded()) {
4044 fm->SetFocusedBrowsingContextFromOtherProcess(
4045 aFocusedBrowsingContext.get(), aActionIdForFocused);
4048 return IPC_OK();
4051 mozilla::ipc::IPCResult ContentChild::RecvReviseActiveBrowsingContext(
4052 uint64_t aOldActionId,
4053 const MaybeDiscarded<BrowsingContext>& aActiveBrowsingContext,
4054 uint64_t aNewActionId) {
4055 nsFocusManager* fm = nsFocusManager::GetFocusManager();
4056 if (fm && !aActiveBrowsingContext.IsNullOrDiscarded()) {
4057 fm->ReviseActiveBrowsingContext(aOldActionId, aActiveBrowsingContext.get(),
4058 aNewActionId);
4060 return IPC_OK();
4063 mozilla::ipc::IPCResult ContentChild::RecvReviseFocusedBrowsingContext(
4064 uint64_t aOldActionId,
4065 const MaybeDiscarded<BrowsingContext>& aFocusedBrowsingContext,
4066 uint64_t aNewActionId) {
4067 nsFocusManager* fm = nsFocusManager::GetFocusManager();
4068 if (fm && !aFocusedBrowsingContext.IsNullOrDiscarded()) {
4069 fm->ReviseFocusedBrowsingContext(
4070 aOldActionId, aFocusedBrowsingContext.get(), aNewActionId);
4072 return IPC_OK();
4075 mozilla::ipc::IPCResult ContentChild::RecvMaybeExitFullscreen(
4076 const MaybeDiscarded<BrowsingContext>& aContext) {
4077 if (aContext.IsNullOrDiscarded()) {
4078 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
4079 ("ChildIPC: Trying to send a message to dead or detached context"));
4080 return IPC_OK();
4083 nsIDocShell* shell = aContext.get()->GetDocShell();
4084 if (!shell) {
4085 return IPC_OK();
4088 Document* doc = shell->GetDocument();
4089 if (doc && doc->GetFullscreenElement()) {
4090 Document::AsyncExitFullscreen(doc);
4093 return IPC_OK();
4096 mozilla::ipc::IPCResult ContentChild::RecvWindowPostMessage(
4097 const MaybeDiscarded<BrowsingContext>& aContext,
4098 const ClonedOrErrorMessageData& aMessage, const PostMessageData& aData) {
4099 if (aContext.IsNullOrDiscarded()) {
4100 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
4101 ("ChildIPC: Trying to send a message to dead or detached context"));
4102 return IPC_OK();
4105 RefPtr<nsGlobalWindowOuter> window =
4106 nsGlobalWindowOuter::Cast(aContext.get()->GetDOMWindow());
4107 if (!window) {
4108 MOZ_LOG(
4109 BrowsingContext::GetLog(), LogLevel::Debug,
4110 ("ChildIPC: Trying to send a message to a context without a window"));
4111 return IPC_OK();
4114 nsCOMPtr<nsIPrincipal> providedPrincipal;
4115 if (!window->GetPrincipalForPostMessage(
4116 aData.targetOrigin(), aData.targetOriginURI(),
4117 aData.callerPrincipal(), *aData.subjectPrincipal(),
4118 getter_AddRefs(providedPrincipal))) {
4119 return IPC_OK();
4122 // Call `GetDocument()` to force the document and its inner window to be
4123 // created, as it would be forced to be created if this call was being
4124 // performed in-process.
4125 if (NS_WARN_IF(!aContext.get()->GetDocument())) {
4126 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
4127 ("ChildIPC: Trying to send a message to a context but document "
4128 "creation failed"));
4129 return IPC_OK();
4132 // It's OK if `sourceBc` has already been discarded, so long as we can
4133 // continue to wrap it.
4134 RefPtr<BrowsingContext> sourceBc = aData.source().GetMaybeDiscarded();
4136 // Create and asynchronously dispatch a runnable which will handle actual DOM
4137 // event creation and dispatch.
4138 RefPtr<PostMessageEvent> event =
4139 new PostMessageEvent(sourceBc, aData.origin(), window, providedPrincipal,
4140 aData.innerWindowId(), aData.callerURI(),
4141 aData.scriptLocation(), aData.isFromPrivateWindow());
4142 event->UnpackFrom(aMessage);
4144 event->DispatchToTargetThread(IgnoredErrorResult());
4145 return IPC_OK();
4148 mozilla::ipc::IPCResult ContentChild::RecvCommitBrowsingContextTransaction(
4149 const MaybeDiscarded<BrowsingContext>& aContext,
4150 BrowsingContext::BaseTransaction&& aTransaction, uint64_t aEpoch) {
4151 return aTransaction.CommitFromIPC(aContext, aEpoch, this);
4154 mozilla::ipc::IPCResult ContentChild::RecvCommitWindowContextTransaction(
4155 const MaybeDiscarded<WindowContext>& aContext,
4156 WindowContext::BaseTransaction&& aTransaction, uint64_t aEpoch) {
4157 return aTransaction.CommitFromIPC(aContext, aEpoch, this);
4160 mozilla::ipc::IPCResult ContentChild::RecvCreateWindowContext(
4161 WindowContext::IPCInitializer&& aInit) {
4162 RefPtr<BrowsingContext> bc = BrowsingContext::Get(aInit.mBrowsingContextId);
4163 if (!bc) {
4164 // Handle this case by ignoring the request, as bc must be in the process of
4165 // being discarded.
4166 // In the future it would be nice to avoid sending this message to the child
4167 // at all.
4168 NS_WARNING("Attempt to attach WindowContext to discarded parent");
4169 return IPC_OK();
4172 WindowContext::CreateFromIPC(std::move(aInit));
4173 return IPC_OK();
4176 mozilla::ipc::IPCResult ContentChild::RecvDiscardWindowContext(
4177 uint64_t aContextId, DiscardWindowContextResolver&& aResolve) {
4178 // Resolve immediately to acknowledge call
4179 aResolve(true);
4181 RefPtr<WindowContext> window = WindowContext::GetById(aContextId);
4182 if (NS_WARN_IF(!window) || NS_WARN_IF(window->IsDiscarded())) {
4183 return IPC_OK();
4186 window->Discard();
4187 return IPC_OK();
4190 mozilla::ipc::IPCResult ContentChild::RecvScriptError(
4191 const nsString& aMessage, const nsCString& aSourceName,
4192 const uint32_t& aLineNumber, const uint32_t& aColNumber,
4193 const uint32_t& aFlags, const nsCString& aCategory,
4194 const bool& aFromPrivateWindow, const uint64_t& aInnerWindowId,
4195 const bool& aFromChromeContext) {
4196 nsresult rv = NS_OK;
4197 nsCOMPtr<nsIConsoleService> consoleService =
4198 do_GetService(NS_CONSOLESERVICE_CONTRACTID, &rv);
4199 NS_ENSURE_SUCCESS(rv, IPC_FAIL(this, "Failed to get console service"));
4201 nsCOMPtr<nsIScriptError> scriptError(
4202 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
4203 NS_ENSURE_TRUE(scriptError,
4204 IPC_FAIL(this, "Failed to construct nsIScriptError"));
4206 scriptError->InitWithWindowID(aMessage, aSourceName, aLineNumber, aColNumber,
4207 aFlags, aCategory, aInnerWindowId,
4208 aFromChromeContext);
4209 rv = consoleService->LogMessage(scriptError);
4210 NS_ENSURE_SUCCESS(rv, IPC_FAIL(this, "Failed to log script error"));
4212 return IPC_OK();
4215 mozilla::ipc::IPCResult ContentChild::RecvReportFrameTimingData(
4216 const LoadInfoArgs& loadInfoArgs, const nsString& entryName,
4217 const nsString& initiatorType, UniquePtr<PerformanceTimingData>&& aData) {
4218 if (!aData) {
4219 return IPC_FAIL(this, "aData should not be null");
4222 nsCOMPtr<nsILoadInfo> loadInfo;
4223 nsresult rv = mozilla::ipc::LoadInfoArgsToLoadInfo(
4224 loadInfoArgs, NOT_REMOTE_TYPE, getter_AddRefs(loadInfo));
4225 if (NS_FAILED(rv)) {
4226 MOZ_DIAGNOSTIC_CRASH("LoadInfoArgsToLoadInfo failed");
4227 return IPC_OK();
4230 // It is important to call LoadInfo::GetPerformanceStorage instead of simply
4231 // getting the performance object via the innerWindowID in order to perform
4232 // necessary cross origin checks.
4233 if (PerformanceStorage* storage = loadInfo->GetPerformanceStorage()) {
4234 storage->AddEntry(entryName, initiatorType, std::move(aData));
4236 return IPC_OK();
4239 mozilla::ipc::IPCResult ContentChild::RecvLoadURI(
4240 const MaybeDiscarded<BrowsingContext>& aContext,
4241 nsDocShellLoadState* aLoadState, bool aSetNavigating,
4242 LoadURIResolver&& aResolve) {
4243 auto resolveOnExit = MakeScopeExit([&] { aResolve(true); });
4245 if (aContext.IsNullOrDiscarded()) {
4246 return IPC_OK();
4248 RefPtr<BrowsingContext> context = aContext.get();
4249 if (!context->IsInProcess()) {
4250 // The DocShell has been torn down or the BrowsingContext has changed
4251 // process in the middle of the load request. There's not much we can do at
4252 // this point, so just give up.
4253 return IPC_OK();
4256 context->LoadURI(aLoadState, aSetNavigating);
4258 nsCOMPtr<nsPIDOMWindowOuter> window = context->GetDOMWindow();
4259 BrowserChild* bc = BrowserChild::GetFrom(window);
4260 if (bc) {
4261 bc->NotifyNavigationFinished();
4264 #ifdef MOZ_CRASHREPORTER
4265 if (CrashReporter::GetEnabled()) {
4266 nsCOMPtr<nsIURI> annotationURI;
4268 nsresult rv = NS_MutateURI(aLoadState->URI())
4269 .SetUserPass(""_ns)
4270 .Finalize(annotationURI);
4272 if (NS_FAILED(rv)) {
4273 // Ignore failures on about: URIs.
4274 annotationURI = aLoadState->URI();
4277 CrashReporter::RecordAnnotationNSCString(CrashReporter::Annotation::URL,
4278 annotationURI->GetSpecOrDefault());
4280 #endif
4282 return IPC_OK();
4285 mozilla::ipc::IPCResult ContentChild::RecvInternalLoad(
4286 nsDocShellLoadState* aLoadState) {
4287 if (!aLoadState->Target().IsEmpty() ||
4288 aLoadState->TargetBrowsingContext().IsNull()) {
4289 return IPC_FAIL(this, "must already be retargeted");
4291 if (aLoadState->TargetBrowsingContext().IsDiscarded()) {
4292 return IPC_OK();
4294 RefPtr<BrowsingContext> context = aLoadState->TargetBrowsingContext().get();
4296 context->InternalLoad(aLoadState);
4298 #ifdef MOZ_CRASHREPORTER
4299 if (CrashReporter::GetEnabled()) {
4300 nsCOMPtr<nsIURI> annotationURI;
4302 nsresult rv = NS_MutateURI(aLoadState->URI())
4303 .SetUserPass(""_ns)
4304 .Finalize(annotationURI);
4306 if (NS_FAILED(rv)) {
4307 // Ignore failures on about: URIs.
4308 annotationURI = aLoadState->URI();
4311 CrashReporter::RecordAnnotationNSCString(CrashReporter::Annotation::URL,
4312 annotationURI->GetSpecOrDefault());
4314 #endif
4316 return IPC_OK();
4319 mozilla::ipc::IPCResult ContentChild::RecvDisplayLoadError(
4320 const MaybeDiscarded<BrowsingContext>& aContext, const nsAString& aURI) {
4321 if (aContext.IsNullOrDiscarded()) {
4322 return IPC_OK();
4324 RefPtr<BrowsingContext> context = aContext.get();
4326 context->DisplayLoadError(aURI);
4328 nsCOMPtr<nsPIDOMWindowOuter> window = context->GetDOMWindow();
4329 BrowserChild* bc = BrowserChild::GetFrom(window);
4330 if (bc) {
4331 bc->NotifyNavigationFinished();
4333 return IPC_OK();
4336 mozilla::ipc::IPCResult ContentChild::RecvHistoryCommitIndexAndLength(
4337 const MaybeDiscarded<BrowsingContext>& aContext, const uint32_t& aIndex,
4338 const uint32_t& aLength, const nsID& aChangeID) {
4339 if (!aContext.IsNullOrDiscarded()) {
4340 ChildSHistory* shistory = aContext.get()->GetChildSessionHistory();
4341 if (shistory) {
4342 shistory->SetIndexAndLength(aIndex, aLength, aChangeID);
4345 return IPC_OK();
4348 mozilla::ipc::IPCResult ContentChild::RecvGetLayoutHistoryState(
4349 const MaybeDiscarded<BrowsingContext>& aContext,
4350 GetLayoutHistoryStateResolver&& aResolver) {
4351 nsCOMPtr<nsILayoutHistoryState> state;
4352 nsIDocShell* docShell;
4353 mozilla::Maybe<mozilla::dom::Wireframe> wireframe;
4354 if (!aContext.IsNullOrDiscarded() &&
4355 (docShell = aContext.get()->GetDocShell())) {
4356 docShell->PersistLayoutHistoryState();
4357 docShell->GetLayoutHistoryState(getter_AddRefs(state));
4358 wireframe = static_cast<nsDocShell*>(docShell)->GetWireframe();
4360 aResolver(
4361 std::tuple<nsILayoutHistoryState*, const mozilla::Maybe<Wireframe>&>(
4362 state, wireframe));
4364 return IPC_OK();
4367 mozilla::ipc::IPCResult ContentChild::RecvDispatchLocationChangeEvent(
4368 const MaybeDiscarded<BrowsingContext>& aContext) {
4369 if (!aContext.IsNullOrDiscarded() && aContext.get()->GetDocShell()) {
4370 aContext.get()->GetDocShell()->DispatchLocationChangeEvent();
4372 return IPC_OK();
4375 mozilla::ipc::IPCResult ContentChild::RecvDispatchBeforeUnloadToSubtree(
4376 const MaybeDiscarded<BrowsingContext>& aStartingAt,
4377 DispatchBeforeUnloadToSubtreeResolver&& aResolver) {
4378 if (aStartingAt.IsNullOrDiscarded()) {
4379 aResolver(nsIDocumentViewer::eAllowNavigation);
4380 } else {
4381 DispatchBeforeUnloadToSubtree(aStartingAt.get(), std::move(aResolver));
4383 return IPC_OK();
4386 mozilla::ipc::IPCResult ContentChild::RecvInitNextGenLocalStorageEnabled(
4387 const bool& aEnabled) {
4388 mozilla::dom::RecvInitNextGenLocalStorageEnabled(aEnabled);
4390 return IPC_OK();
4393 /* static */ void ContentChild::DispatchBeforeUnloadToSubtree(
4394 BrowsingContext* aStartingAt,
4395 const DispatchBeforeUnloadToSubtreeResolver& aResolver) {
4396 bool resolved = false;
4398 aStartingAt->PreOrderWalk([&](dom::BrowsingContext* aBC) {
4399 if (aBC->GetDocShell()) {
4400 nsCOMPtr<nsIDocumentViewer> viewer;
4401 aBC->GetDocShell()->GetDocViewer(getter_AddRefs(viewer));
4402 if (viewer &&
4403 viewer->DispatchBeforeUnload() ==
4404 nsIDocumentViewer::eRequestBlockNavigation &&
4405 !resolved) {
4406 // Send our response as soon as we find any blocker, so that we can show
4407 // the permit unload prompt as soon as possible, without giving
4408 // subsequent handlers a chance to delay it.
4409 aResolver(nsIDocumentViewer::eRequestBlockNavigation);
4410 resolved = true;
4415 if (!resolved) {
4416 aResolver(nsIDocumentViewer::eAllowNavigation);
4420 mozilla::ipc::IPCResult ContentChild::RecvGoBack(
4421 const MaybeDiscarded<BrowsingContext>& aContext,
4422 const Maybe<int32_t>& aCancelContentJSEpoch, bool aRequireUserInteraction,
4423 bool aUserActivation) {
4424 if (aContext.IsNullOrDiscarded()) {
4425 return IPC_OK();
4427 BrowsingContext* bc = aContext.get();
4429 if (RefPtr<nsDocShell> docShell = nsDocShell::Cast(bc->GetDocShell())) {
4430 if (aCancelContentJSEpoch) {
4431 docShell->SetCancelContentJSEpoch(*aCancelContentJSEpoch);
4433 docShell->GoBack(aRequireUserInteraction, aUserActivation);
4435 if (BrowserChild* browserChild = BrowserChild::GetFrom(docShell)) {
4436 browserChild->NotifyNavigationFinished();
4440 return IPC_OK();
4443 mozilla::ipc::IPCResult ContentChild::RecvGoForward(
4444 const MaybeDiscarded<BrowsingContext>& aContext,
4445 const Maybe<int32_t>& aCancelContentJSEpoch, bool aRequireUserInteraction,
4446 bool aUserActivation) {
4447 if (aContext.IsNullOrDiscarded()) {
4448 return IPC_OK();
4450 BrowsingContext* bc = aContext.get();
4452 if (RefPtr<nsDocShell> docShell = nsDocShell::Cast(bc->GetDocShell())) {
4453 if (aCancelContentJSEpoch) {
4454 docShell->SetCancelContentJSEpoch(*aCancelContentJSEpoch);
4456 docShell->GoForward(aRequireUserInteraction, aUserActivation);
4458 if (BrowserChild* browserChild = BrowserChild::GetFrom(docShell)) {
4459 browserChild->NotifyNavigationFinished();
4463 return IPC_OK();
4466 mozilla::ipc::IPCResult ContentChild::RecvGoToIndex(
4467 const MaybeDiscarded<BrowsingContext>& aContext, const int32_t& aIndex,
4468 const Maybe<int32_t>& aCancelContentJSEpoch, bool aUserActivation) {
4469 if (aContext.IsNullOrDiscarded()) {
4470 return IPC_OK();
4472 BrowsingContext* bc = aContext.get();
4474 if (RefPtr<nsDocShell> docShell = nsDocShell::Cast(bc->GetDocShell())) {
4475 if (aCancelContentJSEpoch) {
4476 docShell->SetCancelContentJSEpoch(*aCancelContentJSEpoch);
4478 docShell->GotoIndex(aIndex, aUserActivation);
4480 if (BrowserChild* browserChild = BrowserChild::GetFrom(docShell)) {
4481 browserChild->NotifyNavigationFinished();
4485 return IPC_OK();
4488 mozilla::ipc::IPCResult ContentChild::RecvReload(
4489 const MaybeDiscarded<BrowsingContext>& aContext,
4490 const uint32_t aReloadFlags) {
4491 if (aContext.IsNullOrDiscarded()) {
4492 return IPC_OK();
4494 BrowsingContext* bc = aContext.get();
4496 if (RefPtr<nsDocShell> docShell = nsDocShell::Cast(bc->GetDocShell())) {
4497 docShell->Reload(aReloadFlags);
4500 return IPC_OK();
4503 mozilla::ipc::IPCResult ContentChild::RecvStopLoad(
4504 const MaybeDiscarded<BrowsingContext>& aContext,
4505 const uint32_t aStopFlags) {
4506 if (aContext.IsNullOrDiscarded()) {
4507 return IPC_OK();
4509 BrowsingContext* bc = aContext.get();
4511 if (auto* docShell = nsDocShell::Cast(bc->GetDocShell())) {
4512 docShell->Stop(aStopFlags);
4515 return IPC_OK();
4518 #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
4519 mozilla::ipc::IPCResult ContentChild::RecvInitSandboxTesting(
4520 Endpoint<PSandboxTestingChild>&& aEndpoint) {
4521 if (!SandboxTestingChild::Initialize(std::move(aEndpoint))) {
4522 return IPC_FAIL(
4523 this, "InitSandboxTesting failed to initialise the child process.");
4525 return IPC_OK();
4527 #endif
4529 NS_IMETHODIMP ContentChild::GetChildID(uint64_t* aOut) {
4530 *aOut = XRE_GetChildID();
4531 return NS_OK;
4534 NS_IMETHODIMP ContentChild::GetActor(const nsACString& aName, JSContext* aCx,
4535 JSProcessActorChild** retval) {
4536 ErrorResult error;
4537 RefPtr<JSProcessActorChild> actor =
4538 JSActorManager::GetActor(aCx, aName, error)
4539 .downcast<JSProcessActorChild>();
4540 if (error.MaybeSetPendingException(aCx)) {
4541 return NS_ERROR_FAILURE;
4543 actor.forget(retval);
4544 return NS_OK;
4547 NS_IMETHODIMP ContentChild::GetExistingActor(const nsACString& aName,
4548 JSProcessActorChild** retval) {
4549 RefPtr<JSProcessActorChild> actor =
4550 JSActorManager::GetExistingActor(aName).downcast<JSProcessActorChild>();
4551 actor.forget(retval);
4552 return NS_OK;
4555 already_AddRefed<JSActor> ContentChild::InitJSActor(
4556 JS::Handle<JSObject*> aMaybeActor, const nsACString& aName,
4557 ErrorResult& aRv) {
4558 RefPtr<JSProcessActorChild> actor;
4559 if (aMaybeActor.get()) {
4560 aRv = UNWRAP_OBJECT(JSProcessActorChild, aMaybeActor.get(), actor);
4561 if (aRv.Failed()) {
4562 return nullptr;
4564 } else {
4565 actor = new JSProcessActorChild();
4568 MOZ_RELEASE_ASSERT(!actor->Manager(),
4569 "mManager was already initialized once!");
4570 actor->Init(aName, this);
4571 return actor.forget();
4574 IPCResult ContentChild::RecvRawMessage(const JSActorMessageMeta& aMeta,
4575 const Maybe<ClonedMessageData>& aData,
4576 const Maybe<ClonedMessageData>& aStack) {
4577 Maybe<StructuredCloneData> data;
4578 if (aData) {
4579 data.emplace();
4580 data->BorrowFromClonedMessageData(*aData);
4582 Maybe<StructuredCloneData> stack;
4583 if (aStack) {
4584 stack.emplace();
4585 stack->BorrowFromClonedMessageData(*aStack);
4587 ReceiveRawMessage(aMeta, std::move(data), std::move(stack));
4588 return IPC_OK();
4591 NS_IMETHODIMP ContentChild::GetCanSend(bool* aCanSend) {
4592 *aCanSend = CanSend();
4593 return NS_OK;
4596 ContentChild* ContentChild::AsContentChild() { return this; }
4598 JSActorManager* ContentChild::AsJSActorManager() { return this; }
4600 IPCResult ContentChild::RecvFlushFOGData(FlushFOGDataResolver&& aResolver) {
4601 glean::FlushFOGData(std::move(aResolver));
4602 return IPC_OK();
4605 IPCResult ContentChild::RecvUpdateMediaCodecsSupported(
4606 RemoteDecodeIn aLocation, const media::MediaCodecsSupported& aSupported) {
4607 RemoteDecoderManagerChild::SetSupported(aLocation, aSupported);
4609 return IPC_OK();
4612 void ContentChild::ConfigureThreadPerformanceHints(
4613 const hal::ProcessPriority& aPriority) {
4614 if (aPriority >= hal::PROCESS_PRIORITY_FOREGROUND) {
4615 static bool canUsePerformanceHintSession = true;
4616 if (!mPerformanceHintSession && canUsePerformanceHintSession) {
4617 nsTArray<PlatformThreadHandle> threads;
4618 Servo_ThreadPool_GetThreadHandles(&threads);
4619 #ifdef XP_WIN
4620 threads.AppendElement(GetCurrentThread());
4621 #else
4622 threads.AppendElement(pthread_self());
4623 #endif
4625 mPerformanceHintSession = hal::CreatePerformanceHintSession(
4626 threads, GetPerformanceHintTarget(TimeDuration::FromMilliseconds(
4627 nsRefreshDriver::DefaultInterval())));
4629 // Avoid repeatedly attempting to create a session if it is not
4630 // supported.
4631 canUsePerformanceHintSession = mPerformanceHintSession != nullptr;
4634 #ifdef MOZ_WIDGET_ANDROID
4635 // On Android if we are unable to use PerformanceHintManager then fall back
4636 // to setting the stylo threads' affinities to the performant cores. Android
4637 // automatically sets each thread's affinity to all cores when a process is
4638 // foregrounded, and to a subset of cores when the process is backgrounded.
4639 // We must therefore override this each time the process is foregrounded,
4640 // but we don't have to do anything when backgrounded.
4641 if (!mPerformanceHintSession) {
4642 if (const auto& cpuInfo = hal::GetHeterogeneousCpuInfo()) {
4643 // If CPUs are homogeneous there is no point setting affinity.
4644 if (cpuInfo->mBigCpus.Count() != cpuInfo->mTotalNumCpus) {
4645 BitSet<hal::HeterogeneousCpuInfo::MAX_CPUS> cpus = cpuInfo->mBigCpus;
4646 if (cpus.Count() < 2) {
4647 // From testing on a variety of devices it appears using only the
4648 // big cores gives best performance when there are 2 or more big
4649 // cores. If there are fewer than 2 big cores then additionally
4650 // using the medium cores performs better.
4651 cpus |= cpuInfo->mMediumCpus;
4654 static_assert(
4655 hal::HeterogeneousCpuInfo::MAX_CPUS <= CPU_SETSIZE,
4656 "HeterogeneousCpuInfo::MAX_CPUS is too large for CPU_SETSIZE");
4658 cpu_set_t cpuset;
4659 CPU_ZERO(&cpuset);
4660 for (size_t i = 0; i < cpuInfo->mTotalNumCpus; i++) {
4661 if (cpus.Test(i)) {
4662 CPU_SET(i, &cpuset);
4666 // Only set the affinity for the stylo threads, not the main thread.
4667 // Testing showed no difference in performance between the two
4668 // options, and as newly spawned threads automatically inherit their
4669 // parent's affinity mask there may be unintended consequences to
4670 // setting the main thread affinity.
4671 nsTArray<PlatformThreadHandle> threads;
4672 Servo_ThreadPool_GetThreadHandles(&threads);
4673 for (pthread_t thread : threads) {
4674 int ret = sched_setaffinity(pthread_gettid_np(thread),
4675 sizeof(cpu_set_t), &cpuset);
4676 // Occasionally sched_setaffinity fails, presumably due to a race
4677 // between us receiving the process foreground signal and whatever
4678 // is responsible for restricting which processes can use certain
4679 // cores. Trying again in a runnable seems to do the trick, but if
4680 // that still fails it's not the end of the world.
4681 if (ret < 0) {
4682 NS_DispatchToCurrentThread(NS_NewRunnableFunction(
4683 "ContentChild::ConfigureThreadPerformanceHints",
4684 [threads = std::move(threads), cpuset] {
4685 for (pthread_t thread : threads) {
4686 sched_setaffinity(pthread_gettid_np(thread),
4687 sizeof(cpu_set_t), &cpuset);
4689 }));
4690 break;
4696 #endif
4697 } else {
4698 mPerformanceHintSession = nullptr;
4702 } // namespace dom
4704 #if defined(__OpenBSD__) && defined(MOZ_SANDBOX)
4706 static LazyLogModule sPledgeLog("OpenBSDSandbox");
4708 NS_IMETHODIMP
4709 OpenBSDFindPledgeUnveilFilePath(const char* file, nsACString& result) {
4710 struct stat st;
4712 // Allow overriding files in /etc/$MOZ_APP_NAME
4713 result.Assign(nsPrintfCString("/etc/%s/%s", MOZ_APP_NAME, file));
4714 if (stat(PromiseFlatCString(result).get(), &st) == 0) {
4715 return NS_OK;
4718 // Or look in the system default directory
4719 result.Assign(nsPrintfCString(
4720 "/usr/local/lib/%s/browser/defaults/preferences/%s", MOZ_APP_NAME, file));
4721 if (stat(PromiseFlatCString(result).get(), &st) == 0) {
4722 return NS_OK;
4725 errx(1, "can't locate %s", file);
4728 NS_IMETHODIMP
4729 OpenBSDPledgePromises(const nsACString& aPath) {
4730 // Using NS_LOCAL_FILE_CONTRACTID/NS_LOCALFILEINPUTSTREAM_CONTRACTID requires
4731 // a lot of setup before they are supported and we want to pledge early on
4732 // before all of that, so read the file directly
4733 std::ifstream input(PromiseFlatCString(aPath).get());
4735 // Build up one line of pledge promises without comments
4736 nsAutoCString promises;
4737 bool disabled = false;
4738 int linenum = 0;
4739 for (std::string tLine; std::getline(input, tLine);) {
4740 nsAutoCString line(tLine.c_str());
4741 linenum++;
4743 // Cut off any comments at the end of the line, also catches lines
4744 // that are entirely a comment
4745 int32_t hash = line.FindChar('#');
4746 if (hash >= 0) {
4747 line = Substring(line, 0, hash);
4749 line.CompressWhitespace(true, true);
4750 if (line.IsEmpty()) {
4751 continue;
4754 if (linenum == 1 && line.EqualsLiteral("disable")) {
4755 disabled = true;
4756 break;
4759 if (!promises.IsEmpty()) {
4760 promises.Append(" ");
4762 promises.Append(line);
4764 input.close();
4766 if (disabled) {
4767 warnx("%s: disabled", PromiseFlatCString(aPath).get());
4768 } else {
4769 MOZ_LOG(
4770 sPledgeLog, LogLevel::Debug,
4771 ("%s: pledge(%s)\n", PromiseFlatCString(aPath).get(), promises.get()));
4772 if (pledge(promises.get(), nullptr) != 0) {
4773 err(1, "%s: pledge(%s) failed", PromiseFlatCString(aPath).get(),
4774 promises.get());
4778 return NS_OK;
4781 void ExpandUnveilPath(nsAutoCString& path) {
4782 // Expand $XDG_RUNTIME_DIR to the environment variable, or ~/.cache
4783 nsCString xdgRuntimeDir(PR_GetEnv("XDG_RUNTIME_DIR"));
4784 if (xdgRuntimeDir.IsEmpty()) {
4785 xdgRuntimeDir = "~/.cache";
4787 path.ReplaceSubstring("$XDG_RUNTIME_DIR", xdgRuntimeDir.get());
4789 // Expand $XDG_CONFIG_HOME to the environment variable, or ~/.config
4790 nsCString xdgConfigHome(PR_GetEnv("XDG_CONFIG_HOME"));
4791 if (xdgConfigHome.IsEmpty()) {
4792 xdgConfigHome = "~/.config";
4794 path.ReplaceSubstring("$XDG_CONFIG_HOME", xdgConfigHome.get());
4796 // Expand $XDG_CACHE_HOME to the environment variable, or ~/.cache
4797 nsCString xdgCacheHome(PR_GetEnv("XDG_CACHE_HOME"));
4798 if (xdgCacheHome.IsEmpty()) {
4799 xdgCacheHome = "~/.cache";
4801 path.ReplaceSubstring("$XDG_CACHE_HOME", xdgCacheHome.get());
4803 // Expand $XDG_DATA_HOME to the environment variable, or ~/.local/share
4804 nsCString xdgDataHome(PR_GetEnv("XDG_DATA_HOME"));
4805 if (xdgDataHome.IsEmpty()) {
4806 xdgDataHome = "~/.local/share";
4808 path.ReplaceSubstring("$XDG_DATA_HOME", xdgDataHome.get());
4810 // Expand leading ~ to the user's home directory
4811 nsCOMPtr<nsIFile> homeDir;
4812 nsresult rv =
4813 GetSpecialSystemDirectory(Unix_HomeDirectory, getter_AddRefs(homeDir));
4814 if (NS_FAILED(rv)) {
4815 errx(1, "failed getting home directory");
4817 if (path.FindChar('~') == 0) {
4818 nsCString tHome(homeDir->NativePath());
4819 tHome.Append(Substring(path, 1, path.Length() - 1));
4820 path = tHome.get();
4824 void MkdirP(nsAutoCString& path) {
4825 // nsLocalFile::CreateAllAncestors would be nice to use
4827 nsAutoCString tPath("");
4828 for (const nsACString& dir : path.Split('/')) {
4829 struct stat st;
4831 if (dir.IsEmpty()) {
4832 continue;
4835 tPath.Append("/");
4836 tPath.Append(dir);
4838 if (stat(tPath.get(), &st) == -1) {
4839 if (mkdir(tPath.get(), 0700) == -1) {
4840 err(1, "failed mkdir(%s) while MkdirP(%s)",
4841 PromiseFlatCString(tPath).get(), PromiseFlatCString(path).get());
4847 NS_IMETHODIMP
4848 OpenBSDUnveilPaths(const nsACString& uPath, const nsACString& pledgePath) {
4849 // Using NS_LOCAL_FILE_CONTRACTID/NS_LOCALFILEINPUTSTREAM_CONTRACTID requires
4850 // a lot of setup before they are allowed/supported and we want to pledge and
4851 // unveil early on before all of that is setup
4852 std::ifstream input(PromiseFlatCString(uPath).get());
4854 bool disabled = false;
4855 int linenum = 0;
4856 for (std::string tLine; std::getline(input, tLine);) {
4857 nsAutoCString line(tLine.c_str());
4858 linenum++;
4860 // Cut off any comments at the end of the line, also catches lines
4861 // that are entirely a comment
4862 int32_t hash = line.FindChar('#');
4863 if (hash >= 0) {
4864 line = Substring(line, 0, hash);
4866 line.CompressWhitespace(true, true);
4867 if (line.IsEmpty()) {
4868 continue;
4871 if (linenum == 1 && line.EqualsLiteral("disable")) {
4872 disabled = true;
4873 break;
4876 int32_t space = line.FindChar(' ');
4877 if (space <= 0) {
4878 errx(1, "%s: line %d: invalid format", PromiseFlatCString(uPath).get(),
4879 linenum);
4882 nsAutoCString uPath(Substring(line, 0, space));
4883 ExpandUnveilPath(uPath);
4885 nsAutoCString perms(Substring(line, space + 1, line.Length() - space - 1));
4887 MOZ_LOG(sPledgeLog, LogLevel::Debug,
4888 ("%s: unveil(%s, %s)\n", PromiseFlatCString(uPath).get(),
4889 uPath.get(), perms.get()));
4890 if (unveil(uPath.get(), perms.get()) == -1 && errno != ENOENT) {
4891 err(1, "%s: unveil(%s, %s) failed", PromiseFlatCString(uPath).get(),
4892 uPath.get(), perms.get());
4895 input.close();
4897 if (disabled) {
4898 warnx("%s: disabled", PromiseFlatCString(uPath).get());
4899 } else {
4900 struct stat st;
4902 // Only unveil the pledgePath file if it's not already unveiled, otherwise
4903 // some containing directory will lose visibility.
4904 if (stat(PromiseFlatCString(pledgePath).get(), &st) == -1) {
4905 if (errno == ENOENT) {
4906 if (unveil(PromiseFlatCString(pledgePath).get(), "r") == -1) {
4907 err(1, "unveil(%s, r) failed", PromiseFlatCString(pledgePath).get());
4909 } else {
4910 err(1, "stat(%s)", PromiseFlatCString(pledgePath).get());
4915 return NS_OK;
4918 bool StartOpenBSDSandbox(GeckoProcessType type, ipc::SandboxingKind kind) {
4919 nsAutoCString pledgeFile;
4920 nsAutoCString unveilFile;
4921 char binaryPath[MAXPATHLEN];
4923 switch (type) {
4924 case GeckoProcessType_Default: {
4925 OpenBSDFindPledgeUnveilFilePath("pledge.main", pledgeFile);
4926 OpenBSDFindPledgeUnveilFilePath("unveil.main", unveilFile);
4928 // Ensure dconf dir exists before we veil the filesystem
4929 nsAutoCString dConf("$XDG_RUNTIME_DIR/dconf");
4930 ExpandUnveilPath(dConf);
4931 MkdirP(dConf);
4932 break;
4935 case GeckoProcessType_Content:
4936 OpenBSDFindPledgeUnveilFilePath("pledge.content", pledgeFile);
4937 OpenBSDFindPledgeUnveilFilePath("unveil.content", unveilFile);
4938 break;
4940 case GeckoProcessType_GPU:
4941 OpenBSDFindPledgeUnveilFilePath("pledge.gpu", pledgeFile);
4942 OpenBSDFindPledgeUnveilFilePath("unveil.gpu", unveilFile);
4943 break;
4945 case GeckoProcessType_Socket:
4946 OpenBSDFindPledgeUnveilFilePath("pledge.socket", pledgeFile);
4947 OpenBSDFindPledgeUnveilFilePath("unveil.socket", unveilFile);
4948 break;
4950 case GeckoProcessType_RDD:
4951 OpenBSDFindPledgeUnveilFilePath("pledge.rdd", pledgeFile);
4952 OpenBSDFindPledgeUnveilFilePath("unveil.rdd", unveilFile);
4953 break;
4955 case GeckoProcessType_Utility: {
4956 MOZ_RELEASE_ASSERT(kind <= SandboxingKind::COUNT,
4957 "Should define a sandbox");
4958 switch (kind) {
4959 case ipc::SandboxingKind::GENERIC_UTILITY:
4960 default:
4961 OpenBSDFindPledgeUnveilFilePath("pledge.utility", pledgeFile);
4962 OpenBSDFindPledgeUnveilFilePath("unveil.utility", unveilFile);
4963 break;
4965 } break;
4967 default:
4968 MOZ_ASSERT(false, "unknown process type");
4969 return false;
4972 nsresult rv = mozilla::BinaryPath::Get(binaryPath);
4973 if (NS_FAILED(rv)) {
4974 errx(1, "failed to cache binary path ?");
4977 if (NS_WARN_IF(NS_FAILED(OpenBSDUnveilPaths(unveilFile, pledgeFile)))) {
4978 errx(1, "failed reading/parsing %s", unveilFile.get());
4981 if (NS_WARN_IF(NS_FAILED(OpenBSDPledgePromises(pledgeFile)))) {
4982 errx(1, "failed reading/parsing %s", pledgeFile.get());
4985 // Don't overwrite an existing session dbus address, but ensure it is set
4986 if (!PR_GetEnv("DBUS_SESSION_BUS_ADDRESS")) {
4987 PR_SetEnv("DBUS_SESSION_BUS_ADDRESS=");
4990 return true;
4992 #endif
4994 } // namespace mozilla
4996 /* static */
4997 nsIDOMProcessChild* nsIDOMProcessChild::GetSingleton() {
4998 if (XRE_IsContentProcess()) {
4999 return mozilla::dom::ContentChild::GetSingleton();
5001 return mozilla::dom::InProcessChild::Singleton();