Backed out changeset d527094ec903 (bug 1897708) for causing bc failures in browser_Eu...
[gecko.git] / dom / ipc / ContentChild.cpp
blobc445649d70933666b96a5f419379269271629ca8
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/SimpleEnumerator.h"
45 #include "mozilla/SpinEventLoopUntil.h"
46 #include "mozilla/StaticPrefs_browser.h"
47 #include "mozilla/StaticPrefs_dom.h"
48 #include "mozilla/StaticPrefs_fission.h"
49 #include "mozilla/StaticPrefs_javascript.h"
50 #include "mozilla/StaticPrefs_media.h"
51 #include "mozilla/StaticPrefs_threads.h"
52 #include "mozilla/StorageAccessAPIHelper.h"
53 #include "mozilla/TelemetryIPC.h"
54 #include "mozilla/Unused.h"
55 #include "mozilla/WebBrowserPersistDocumentChild.h"
56 #include "mozilla/devtools/HeapSnapshotTempFileHelperChild.h"
57 #include "mozilla/dom/AutoSuppressEventHandlingAndSuspend.h"
58 #include "mozilla/dom/BlobImpl.h"
59 #include "mozilla/dom/BrowserBridgeHost.h"
60 #include "mozilla/dom/BrowsingContext.h"
61 #include "mozilla/dom/BrowsingContextGroup.h"
62 #include "mozilla/dom/ChildProcessChannelListener.h"
63 #include "mozilla/dom/ChildProcessMessageManager.h"
64 #include "mozilla/dom/ClientManager.h"
65 #include "mozilla/dom/ContentParent.h"
66 #include "mozilla/dom/ContentProcessManager.h"
67 #include "mozilla/dom/ContentPlaybackController.h"
68 #include "mozilla/dom/ContentProcessMessageManager.h"
69 #include "mozilla/dom/DataTransfer.h"
70 #include "mozilla/dom/DocGroup.h"
71 #include "mozilla/dom/ExternalHelperAppChild.h"
72 #include "mozilla/dom/GetFilesHelper.h"
73 #include "mozilla/dom/IPCBlobUtils.h"
74 #include "mozilla/dom/InProcessChild.h"
75 #include "mozilla/dom/JSActorService.h"
76 #include "mozilla/dom/JSProcessActorBinding.h"
77 #include "mozilla/dom/JSProcessActorChild.h"
78 #include "mozilla/dom/LSObject.h"
79 #include "mozilla/dom/MemoryReportRequest.h"
80 #include "mozilla/dom/PSessionStorageObserverChild.h"
81 #include "mozilla/dom/PostMessageEvent.h"
82 #include "mozilla/dom/PushNotifier.h"
83 #include "mozilla/dom/RemoteWorkerService.h"
84 #include "mozilla/dom/ScreenOrientation.h"
85 #include "mozilla/dom/ServiceWorkerManager.h"
86 #include "mozilla/dom/SessionStorageManager.h"
87 #include "mozilla/dom/URLClassifierChild.h"
88 #include "mozilla/dom/UserActivation.h"
89 #include "mozilla/dom/WindowGlobalChild.h"
90 #include "mozilla/dom/WorkerDebugger.h"
91 #include "mozilla/dom/WorkerDebuggerManager.h"
92 #include "mozilla/dom/ipc/SharedMap.h"
93 #include "mozilla/extensions/ExtensionsChild.h"
94 #include "mozilla/extensions/StreamFilterParent.h"
95 #include "mozilla/gfx/Logging.h"
96 #include "mozilla/gfx/gfxVars.h"
97 #include "mozilla/hal_sandbox/PHalChild.h"
98 #include "mozilla/intl/L10nRegistry.h"
99 #include "mozilla/intl/LocaleService.h"
100 #include "mozilla/ipc/BackgroundChild.h"
101 #include "mozilla/ipc/Endpoint.h"
102 #include "mozilla/ipc/FileDescriptorUtils.h"
103 #include "mozilla/ipc/GeckoChildProcessHost.h"
104 #include "mozilla/ipc/ProcessChild.h"
105 #include "mozilla/ipc/TestShellChild.h"
106 #include "mozilla/layers/APZChild.h"
107 #include "mozilla/layers/CompositorManagerChild.h"
108 #include "mozilla/layers/ContentProcessController.h"
109 #include "mozilla/layers/ImageBridgeChild.h"
110 #ifdef NS_PRINTING
111 # include "mozilla/layout/RemotePrintJobChild.h"
112 #endif
113 #include "mozilla/loader/ScriptCacheActors.h"
114 #include "mozilla/media/MediaChild.h"
115 #include "mozilla/net/CaptivePortalService.h"
116 #include "mozilla/net/ChildDNSService.h"
117 #include "mozilla/net/CookieServiceChild.h"
118 #include "mozilla/net/DocumentChannelChild.h"
119 #include "mozilla/net/HttpChannelChild.h"
120 #include "mozilla/widget/RemoteLookAndFeel.h"
121 #include "mozilla/widget/ScreenManager.h"
122 #include "mozilla/widget/WidgetMessageUtils.h"
123 #include "nsBaseDragService.h"
124 #include "nsDocShellLoadTypes.h"
125 #include "nsFocusManager.h"
126 #include "nsHttpHandler.h"
127 #include "nsIConsoleService.h"
128 #include "nsIInputStreamChannel.h"
129 #include "nsILayoutHistoryState.h"
130 #include "nsILoadGroup.h"
131 #include "nsIOpenWindowInfo.h"
132 #include "nsISimpleEnumerator.h"
133 #include "nsIStringBundle.h"
134 #include "nsIURIMutator.h"
135 #include "nsQueryObject.h"
136 #include "nsRefreshDriver.h"
137 #include "nsSandboxFlags.h"
138 #include "mozmemory.h"
140 #include "ChildProfilerController.h"
142 #if defined(MOZ_SANDBOX)
143 # include "mozilla/SandboxSettings.h"
144 # if defined(XP_WIN)
145 # include "mozilla/sandboxTarget.h"
146 # include "mozilla/ProcInfo.h"
147 # elif defined(XP_LINUX)
148 # include "CubebUtils.h"
149 # include "mozilla/Sandbox.h"
150 # include "mozilla/SandboxInfo.h"
151 # include "mozilla/SandboxProfilerObserver.h"
152 # elif defined(XP_MACOSX)
153 # include <CoreGraphics/CGError.h>
154 # include "mozilla/Sandbox.h"
155 # elif defined(__OpenBSD__)
156 # include <err.h>
157 # include <sys/stat.h>
158 # include <unistd.h>
160 # include <fstream>
162 # include "BinaryPath.h"
163 # include "SpecialSystemDirectory.h"
164 # include "nsILineInputStream.h"
165 # include "mozilla/ipc/UtilityProcessSandboxing.h"
166 # endif
167 # if defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
168 # include "mozilla/SandboxTestingChild.h"
169 # endif
170 #endif
172 #include "SandboxHal.h"
173 #include "mozInlineSpellChecker.h"
174 #include "mozilla/GlobalStyleSheetCache.h"
175 #include "nsAnonymousTemporaryFile.h"
176 #include "nsCategoryManagerUtils.h"
177 #include "nsClipboardProxy.h"
178 #include "nsContentPermissionHelper.h"
179 #include "nsDebugImpl.h"
180 #include "nsDirectoryService.h"
181 #include "nsDirectoryServiceDefs.h"
182 #include "nsDirectoryServiceUtils.h"
183 #include "nsDocShell.h"
184 #include "nsDocShellLoadState.h"
185 #include "nsHashPropertyBag.h"
186 #include "nsIConsoleListener.h"
187 #include "nsICycleCollectorListener.h"
188 #include "nsIDocShellTreeOwner.h"
189 #include "nsIDocumentViewer.h"
190 #include "nsIDragService.h"
191 #include "nsIInterfaceRequestorUtils.h"
192 #include "nsIMemoryInfoDumper.h"
193 #include "nsIMemoryReporter.h"
194 #include "nsIObserverService.h"
195 #include "nsIOService.h"
196 #include "nsIScriptError.h"
197 #include "nsIScriptSecurityManager.h"
198 #include "nsJSEnvironment.h"
199 #include "nsJSUtils.h"
200 #include "nsMemoryInfoDumper.h"
201 #include "nsServiceManagerUtils.h"
202 #include "nsStyleSheetService.h"
203 #include "nsThreadManager.h"
204 #include "nsXULAppAPI.h"
205 #include "IHistory.h"
206 #include "ReferrerInfo.h"
207 #include "base/message_loop.h"
208 #include "base/process_util.h"
209 #include "base/task.h"
210 #include "mozilla/dom/BlobURLProtocolHandler.h"
211 #include "mozilla/dom/PCycleCollectWithLogsChild.h"
212 #include "mozilla/dom/PerformanceStorage.h"
213 #include "nsChromeRegistryContent.h"
214 #include "nsFrameMessageManager.h"
215 #include "nsNetUtil.h"
216 #include "nsWindowMemoryReporter.h"
218 #ifdef MOZ_WEBRTC
219 # include "jsapi/WebrtcGlobalChild.h"
220 #endif
222 #include "PermissionMessageUtils.h"
223 #include "mozilla/Permission.h"
224 #include "mozilla/PermissionManager.h"
226 #if defined(MOZ_WIDGET_ANDROID)
227 # include "APKOpen.h"
228 # include <sched.h>
229 #endif
231 #ifdef XP_WIN
232 # include <process.h>
233 # define getpid _getpid
234 # include "mozilla/WinDllServices.h"
235 #endif
237 #if defined(XP_MACOSX)
238 # include "nsMacUtilsImpl.h"
239 # include <sys/qos.h>
240 #endif /* XP_MACOSX */
242 #ifdef MOZ_X11
243 # include "mozilla/X11Util.h"
244 #endif
246 #ifdef ACCESSIBILITY
247 # include "nsAccessibilityService.h"
248 # ifdef XP_WIN
249 # include "mozilla/a11y/AccessibleWrap.h"
250 # endif
251 # include "mozilla/a11y/DocAccessible.h"
252 # include "mozilla/a11y/DocManager.h"
253 # include "mozilla/a11y/OuterDocAccessible.h"
254 #endif
256 #include "mozilla/dom/File.h"
257 #include "mozilla/dom/MediaControllerBinding.h"
259 #ifdef MOZ_WEBSPEECH
260 # include "mozilla/dom/PSpeechSynthesisChild.h"
261 #endif
263 #include "ClearOnShutdown.h"
264 #include "DomainPolicy.h"
265 #include "GfxInfoBase.h"
266 #include "MMPrinter.h"
267 #include "mozilla/ipc/ProcessUtils.h"
268 #include "mozilla/ipc/URIUtils.h"
269 #include "VRManagerChild.h"
270 #include "gfxPlatform.h"
271 #include "gfxPlatformFontList.h"
272 #include "mozilla/RemoteSpellCheckEngineChild.h"
273 #include "mozilla/dom/TabContext.h"
274 #include "mozilla/dom/ipc/StructuredCloneData.h"
275 #include "mozilla/ipc/CrashReporterClient.h"
276 #include "mozilla/net/NeckoMessageUtils.h"
277 #include "mozilla/widget/PuppetBidiKeyboard.h"
278 #include "nsContentUtils.h"
279 #include "nsIPrincipal.h"
280 #include "nsString.h"
281 #include "nscore.h" // for NS_FREE_PERMANENT_DATA
282 #include "private/pprio.h"
284 #ifdef MOZ_WIDGET_GTK
285 # include "mozilla/WidgetUtilsGtk.h"
286 # include "nsAppRunner.h"
287 # include <gtk/gtk.h>
288 #endif
290 #ifdef MOZ_CODE_COVERAGE
291 # include "mozilla/CodeCoverageHandler.h"
292 #endif
294 extern mozilla::LazyLogModule gSHIPBFCacheLog;
296 using namespace mozilla;
297 using namespace mozilla::dom::ipc;
298 using namespace mozilla::media;
299 using namespace mozilla::embedding;
300 using namespace mozilla::gmp;
301 using namespace mozilla::hal_sandbox;
302 using namespace mozilla::ipc;
303 using namespace mozilla::intl;
304 using namespace mozilla::layers;
305 using namespace mozilla::layout;
306 using namespace mozilla::net;
307 using namespace mozilla::widget;
308 using mozilla::loader::PScriptCacheChild;
310 namespace geckoprofiler::markers {
311 struct ProcessPriorityChange {
312 static constexpr Span<const char> MarkerTypeName() {
313 return MakeStringSpan("ProcessPriorityChange");
315 static void StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter& aWriter,
316 const ProfilerString8View& aPreviousPriority,
317 const ProfilerString8View& aNewPriority) {
318 aWriter.StringProperty("Before", aPreviousPriority);
319 aWriter.StringProperty("After", aNewPriority);
321 static MarkerSchema MarkerTypeDisplay() {
322 using MS = MarkerSchema;
323 MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable};
324 schema.AddKeyFormat("Before", MS::Format::String);
325 schema.AddKeyFormat("After", MS::Format::String);
326 schema.AddStaticLabelValue("Note",
327 "This is a notification of the priority change "
328 "that was done by the parent process");
329 schema.SetAllLabels(
330 "priority: {marker.data.Before} -> {marker.data.After}");
331 return schema;
335 struct ProcessPriority {
336 static constexpr Span<const char> MarkerTypeName() {
337 return MakeStringSpan("ProcessPriority");
339 static void StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter& aWriter,
340 const ProfilerString8View& aPriority,
341 const ProfilingState& aProfilingState) {
342 aWriter.StringProperty("Priority", aPriority);
343 aWriter.StringProperty("Marker cause",
344 ProfilerString8View::WrapNullTerminatedString(
345 ProfilingStateToString(aProfilingState)));
347 static MarkerSchema MarkerTypeDisplay() {
348 using MS = MarkerSchema;
349 MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable};
350 schema.AddKeyFormat("Priority", MS::Format::String);
351 schema.AddKeyFormat("Marker cause", MS::Format::String);
352 schema.SetAllLabels("priority: {marker.data.Priority}");
353 return schema;
356 } // namespace geckoprofiler::markers
358 namespace mozilla {
359 namespace dom {
361 // IPC sender for remote GC/CC logging.
362 class CycleCollectWithLogsChild final : public PCycleCollectWithLogsChild {
363 public:
364 NS_INLINE_DECL_REFCOUNTING(CycleCollectWithLogsChild)
366 class Sink final : public nsICycleCollectorLogSink {
367 NS_DECL_ISUPPORTS
369 Sink(CycleCollectWithLogsChild* aActor, const FileDescriptor& aGCLog,
370 const FileDescriptor& aCCLog) {
371 mActor = aActor;
372 mGCLog = FileDescriptorToFILE(aGCLog, "w");
373 mCCLog = FileDescriptorToFILE(aCCLog, "w");
376 NS_IMETHOD Open(FILE** aGCLog, FILE** aCCLog) override {
377 if (NS_WARN_IF(!mGCLog) || NS_WARN_IF(!mCCLog)) {
378 return NS_ERROR_FAILURE;
380 *aGCLog = mGCLog;
381 *aCCLog = mCCLog;
382 return NS_OK;
385 NS_IMETHOD CloseGCLog() override {
386 MOZ_ASSERT(mGCLog);
387 fclose(mGCLog);
388 mGCLog = nullptr;
389 mActor->SendCloseGCLog();
390 return NS_OK;
393 NS_IMETHOD CloseCCLog() override {
394 MOZ_ASSERT(mCCLog);
395 fclose(mCCLog);
396 mCCLog = nullptr;
397 mActor->SendCloseCCLog();
398 return NS_OK;
401 NS_IMETHOD GetFilenameIdentifier(nsAString& aIdentifier) override {
402 return UnimplementedProperty();
405 NS_IMETHOD SetFilenameIdentifier(const nsAString& aIdentifier) override {
406 return UnimplementedProperty();
409 NS_IMETHOD GetProcessIdentifier(int32_t* aIdentifier) override {
410 return UnimplementedProperty();
413 NS_IMETHOD SetProcessIdentifier(int32_t aIdentifier) override {
414 return UnimplementedProperty();
417 NS_IMETHOD GetGcLog(nsIFile** aPath) override {
418 return UnimplementedProperty();
421 NS_IMETHOD GetCcLog(nsIFile** aPath) override {
422 return UnimplementedProperty();
425 private:
426 ~Sink() {
427 if (mGCLog) {
428 fclose(mGCLog);
429 mGCLog = nullptr;
431 if (mCCLog) {
432 fclose(mCCLog);
433 mCCLog = nullptr;
435 // The XPCOM refcount drives the IPC lifecycle;
436 Unused << mActor->Send__delete__(mActor);
439 nsresult UnimplementedProperty() {
440 MOZ_ASSERT(false,
441 "This object is a remote GC/CC logger;"
442 " this property isn't meaningful.");
443 return NS_ERROR_UNEXPECTED;
446 RefPtr<CycleCollectWithLogsChild> mActor;
447 FILE* mGCLog;
448 FILE* mCCLog;
451 private:
452 ~CycleCollectWithLogsChild() = default;
455 NS_IMPL_ISUPPORTS(CycleCollectWithLogsChild::Sink, nsICycleCollectorLogSink);
457 class AlertObserver {
458 public:
459 AlertObserver(nsIObserver* aObserver, const nsString& aData)
460 : mObserver(aObserver), mData(aData) {}
462 ~AlertObserver() = default;
464 nsCOMPtr<nsIObserver> mObserver;
465 nsString mData;
468 class ConsoleListener final : public nsIConsoleListener {
469 public:
470 explicit ConsoleListener(ContentChild* aChild) : mChild(aChild) {}
472 NS_DECL_ISUPPORTS
473 NS_DECL_NSICONSOLELISTENER
475 private:
476 ~ConsoleListener() = default;
478 ContentChild* mChild;
479 friend class ContentChild;
482 NS_IMPL_ISUPPORTS(ConsoleListener, nsIConsoleListener)
484 // Before we send the error to the parent process (which
485 // involves copying the memory), truncate any long lines. CSS
486 // errors in particular share the memory for long lines with
487 // repeated errors, but the IPC communication we're about to do
488 // will break that sharing, so we better truncate now.
489 static void TruncateString(nsAString& aString) {
490 if (aString.Length() > 1000) {
491 aString.Truncate(1000);
495 NS_IMETHODIMP
496 ConsoleListener::Observe(nsIConsoleMessage* aMessage) {
497 if (!mChild) {
498 return NS_OK;
501 nsCOMPtr<nsIScriptError> scriptError = do_QueryInterface(aMessage);
502 if (scriptError) {
503 nsAutoString msg, sourceName, sourceLine;
504 nsCString category;
505 uint32_t lineNum, colNum, flags;
506 bool fromPrivateWindow, fromChromeContext;
508 nsresult rv = scriptError->GetErrorMessage(msg);
509 NS_ENSURE_SUCCESS(rv, rv);
510 TruncateString(msg);
511 rv = scriptError->GetSourceName(sourceName);
512 NS_ENSURE_SUCCESS(rv, rv);
513 TruncateString(sourceName);
514 rv = scriptError->GetSourceLine(sourceLine);
515 NS_ENSURE_SUCCESS(rv, rv);
516 TruncateString(sourceLine);
518 rv = scriptError->GetCategory(getter_Copies(category));
519 NS_ENSURE_SUCCESS(rv, rv);
520 rv = scriptError->GetLineNumber(&lineNum);
521 NS_ENSURE_SUCCESS(rv, rv);
522 rv = scriptError->GetColumnNumber(&colNum);
523 NS_ENSURE_SUCCESS(rv, rv);
524 rv = scriptError->GetFlags(&flags);
525 NS_ENSURE_SUCCESS(rv, rv);
526 rv = scriptError->GetIsFromPrivateWindow(&fromPrivateWindow);
527 NS_ENSURE_SUCCESS(rv, rv);
528 rv = scriptError->GetIsFromChromeContext(&fromChromeContext);
529 NS_ENSURE_SUCCESS(rv, rv);
532 AutoJSAPI jsapi;
533 jsapi.Init();
534 JSContext* cx = jsapi.cx();
536 JS::Rooted<JS::Value> stack(cx);
537 rv = scriptError->GetStack(&stack);
538 NS_ENSURE_SUCCESS(rv, rv);
540 if (stack.isObject()) {
541 // Because |stack| might be a cross-compartment wrapper, we can't use it
542 // with JSAutoRealm. Use the stackGlobal for that.
543 JS::Rooted<JS::Value> stackGlobal(cx);
544 rv = scriptError->GetStackGlobal(&stackGlobal);
545 NS_ENSURE_SUCCESS(rv, rv);
547 JSAutoRealm ar(cx, &stackGlobal.toObject());
549 StructuredCloneData data;
550 ErrorResult err;
551 data.Write(cx, stack, err);
552 if (err.Failed()) {
553 return err.StealNSResult();
556 ClonedMessageData cloned;
557 if (!data.BuildClonedMessageData(cloned)) {
558 return NS_ERROR_FAILURE;
561 mChild->SendScriptErrorWithStack(
562 msg, sourceName, sourceLine, lineNum, colNum, flags, category,
563 fromPrivateWindow, fromChromeContext, cloned);
564 return NS_OK;
568 mChild->SendScriptError(msg, sourceName, sourceLine, lineNum, colNum, flags,
569 category, fromPrivateWindow, 0, fromChromeContext);
570 return NS_OK;
573 nsString msg;
574 nsresult rv = aMessage->GetMessageMoz(msg);
575 NS_ENSURE_SUCCESS(rv, rv);
576 mChild->SendConsoleMessage(msg);
577 return NS_OK;
580 #ifdef NIGHTLY_BUILD
582 * The singleton of this class is registered with the BackgroundHangMonitor as
583 * an annotator, so that the hang monitor can record whether or not there were
584 * pending input events when the thread hung.
586 class PendingInputEventHangAnnotator final : public BackgroundHangAnnotator {
587 public:
588 virtual void AnnotateHang(BackgroundHangAnnotations& aAnnotations) override {
589 int32_t pending = ContentChild::GetSingleton()->GetPendingInputEvents();
590 if (pending > 0) {
591 aAnnotations.AddAnnotation(u"PendingInput"_ns, pending);
595 static PendingInputEventHangAnnotator sSingleton;
597 PendingInputEventHangAnnotator PendingInputEventHangAnnotator::sSingleton;
598 #endif
600 class ContentChild::ShutdownCanary final {};
602 ContentChild* ContentChild::sSingleton;
603 StaticAutoPtr<ContentChild::ShutdownCanary> ContentChild::sShutdownCanary;
605 ContentChild::ContentChild()
606 : mID(uint64_t(-1)),
607 mIsForBrowser(false),
608 mIsAlive(true),
609 mShuttingDown(false) {
610 // This process is a content process, so it's clearly running in
611 // multiprocess mode!
612 nsDebugImpl::SetMultiprocessMode("Child");
614 // Our static analysis doesn't allow capturing ref-counted pointers in
615 // lambdas, so we need to hide it in a uintptr_t. This is safe because this
616 // lambda will be destroyed in ~ContentChild().
617 uintptr_t self = reinterpret_cast<uintptr_t>(this);
618 profiler_add_state_change_callback(
619 AllProfilingStates(),
620 [self](ProfilingState aProfilingState) {
621 const ContentChild* selfPtr =
622 reinterpret_cast<const ContentChild*>(self);
623 PROFILER_MARKER("Process Priority", OTHER,
624 mozilla::MarkerThreadId::MainThread(), ProcessPriority,
625 ProfilerString8View::WrapNullTerminatedString(
626 ProcessPriorityToString(selfPtr->mProcessPriority)),
627 aProfilingState);
629 self);
631 // When ContentChild is created, the observer service does not even exist.
632 // When ContentChild::RecvSetXPCOMProcessAttributes is called (the first
633 // IPDL call made on this object), shutdown may have already happened. Thus
634 // we create a canary here that relies upon getting cleared if shutdown
635 // happens without requiring the observer service at this time.
636 if (!sShutdownCanary) {
637 sShutdownCanary = new ShutdownCanary();
638 ClearOnShutdown(&sShutdownCanary, ShutdownPhase::XPCOMShutdown);
642 #ifdef _MSC_VER
643 # pragma warning(push)
644 # pragma warning( \
645 disable : 4722) /* Silence "destructor never returns" warning \
647 #endif
649 ContentChild::~ContentChild() {
650 profiler_remove_state_change_callback(reinterpret_cast<uintptr_t>(this));
652 #ifndef NS_FREE_PERMANENT_DATA
653 MOZ_CRASH("Content Child shouldn't be destroyed.");
654 #endif
657 #ifdef _MSC_VER
658 # pragma warning(pop)
659 #endif
661 NS_INTERFACE_MAP_BEGIN(ContentChild)
662 NS_INTERFACE_MAP_ENTRY(nsIDOMProcessChild)
663 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMProcessChild)
664 NS_INTERFACE_MAP_END
666 mozilla::ipc::IPCResult ContentChild::RecvSetXPCOMProcessAttributes(
667 XPCOMInitData&& aXPCOMInit, const StructuredCloneData& aInitialData,
668 FullLookAndFeel&& aLookAndFeelData, dom::SystemFontList&& aFontList,
669 Maybe<SharedMemoryHandle>&& aSharedUASheetHandle,
670 const uintptr_t& aSharedUASheetAddress,
671 nsTArray<SharedMemoryHandle>&& aSharedFontListBlocks,
672 const bool& aIsReadyForBackgroundProcessing) {
673 if (!sShutdownCanary) {
674 return IPC_OK();
677 mLookAndFeelData = std::move(aLookAndFeelData);
678 mFontList = std::move(aFontList);
679 mSharedFontListBlocks = std::move(aSharedFontListBlocks);
681 gfx::gfxVars::SetValuesForInitialize(aXPCOMInit.gfxNonDefaultVarUpdates());
682 PerfStats::SetCollectionMask(aXPCOMInit.perfStatsMask());
683 InitSharedUASheets(std::move(aSharedUASheetHandle), aSharedUASheetAddress);
684 InitXPCOM(std::move(aXPCOMInit), aInitialData,
685 aIsReadyForBackgroundProcessing);
686 InitGraphicsDeviceData(aXPCOMInit.contentDeviceData());
687 RefPtr<net::ChildDNSService> dnsServiceChild =
688 dont_AddRef(net::ChildDNSService::GetSingleton());
689 if (dnsServiceChild) {
690 dnsServiceChild->SetTRRDomain(aXPCOMInit.trrDomain());
691 dnsServiceChild->SetTRRModeInChild(aXPCOMInit.trrMode(),
692 aXPCOMInit.trrModeFromPref());
694 return IPC_OK();
697 class nsGtkNativeInitRunnable : public Runnable {
698 public:
699 nsGtkNativeInitRunnable() : Runnable("nsGtkNativeInitRunnable") {}
701 NS_IMETHOD Run() override {
702 LookAndFeel::NativeInit();
703 return NS_OK;
707 void ContentChild::Init(mozilla::ipc::UntypedEndpoint&& aEndpoint,
708 const char* aParentBuildID, uint64_t aChildID,
709 bool aIsForBrowser) {
710 #ifdef MOZ_WIDGET_GTK
711 // When running X11 only build we need to pass a display down
712 // to gtk_init because it's not going to use the one from the environment
713 // on its own when deciding which backend to use, and when starting under
714 // XWayland, it may choose to start with the wayland backend
715 // instead of the x11 backend.
716 // The DISPLAY environment variable is normally set by the parent process.
717 // The MOZ_GDK_DISPLAY environment variable is set from nsAppRunner.cpp
718 // when --display is set by the command line.
719 if (!gfxPlatform::IsHeadless()) {
720 const char* display_name = PR_GetEnv("MOZ_GDK_DISPLAY");
721 if (!display_name) {
722 bool waylandEnabled = false;
723 # ifdef MOZ_WAYLAND
724 waylandEnabled = IsWaylandEnabled();
725 # endif
726 if (!waylandEnabled) {
727 display_name = PR_GetEnv("DISPLAY");
730 if (display_name) {
731 int argc = 3;
732 char option_name[] = "--display";
733 char* argv[] = {
734 // argv0 is unused because g_set_prgname() was called in
735 // XRE_InitChildProcess().
736 nullptr, option_name, const_cast<char*>(display_name), nullptr};
737 char** argvp = argv;
738 gtk_init(&argc, &argvp);
739 } else {
740 gtk_init(nullptr, nullptr);
743 #endif
745 #ifdef MOZ_X11
746 if (!gfxPlatform::IsHeadless()) {
747 // Do this after initializing GDK, or GDK will install its own handler.
748 XRE_InstallX11ErrorHandler();
750 #endif
752 MOZ_ASSERT(!sSingleton, "only one ContentChild per child");
754 // Once we start sending IPC messages, we need the thread manager to be
755 // initialized so we can deal with the responses. Do that here before we
756 // try to construct the crash reporter.
757 nsresult rv = nsThreadManager::get().Init();
758 if (NS_WARN_IF(NS_FAILED(rv))) {
759 MOZ_CRASH("Failed to initialize the thread manager in ContentChild::Init");
762 if (!aEndpoint.Bind(this)) {
763 MOZ_CRASH("Bind failed in ContentChild::Init");
765 sSingleton = this;
767 // If communications with the parent have broken down, take the process
768 // down so it's not hanging around.
769 GetIPCChannel()->SetAbortOnError(true);
771 // This must be checked before any IPDL message, which may hit sentinel
772 // errors due to parent and content processes having different
773 // versions.
774 MessageChannel* channel = GetIPCChannel();
775 if (channel && !channel->SendBuildIDsMatchMessage(aParentBuildID)) {
776 // We need to quit this process if the buildID doesn't match the parent's.
777 // This can occur when an update occurred in the background.
778 ProcessChild::QuickExit();
781 #if defined(__OpenBSD__) && defined(MOZ_SANDBOX)
782 StartOpenBSDSandbox(GeckoProcessType_Content);
783 #endif
785 #ifdef MOZ_X11
786 # ifdef MOZ_WIDGET_GTK
787 if (GdkIsX11Display() && !gfxPlatform::IsHeadless()) {
788 // Send the parent our X socket to act as a proxy reference for our X
789 // resources.
790 int xSocketFd = ConnectionNumber(DefaultXDisplay());
791 SendBackUpXResources(FileDescriptor(xSocketFd));
793 # endif
794 #endif
796 CrashReporterClient::InitSingleton(this);
798 mID = aChildID;
799 mIsForBrowser = aIsForBrowser;
801 SetProcessName("Web Content"_ns);
803 #ifdef NIGHTLY_BUILD
804 // NOTE: We have to register the annotator on the main thread, as annotators
805 // only affect a single thread.
806 SchedulerGroup::Dispatch(
807 NS_NewRunnableFunction("RegisterPendingInputEventHangAnnotator", [] {
808 BackgroundHangMonitor::RegisterAnnotator(
809 PendingInputEventHangAnnotator::sSingleton);
810 }));
811 #endif
814 void ContentChild::AddProfileToProcessName(const nsACString& aProfile) {
815 nsCOMPtr<nsIPrincipal> isolationPrincipal =
816 ContentParent::CreateRemoteTypeIsolationPrincipal(mRemoteType);
817 if (isolationPrincipal) {
818 if (isolationPrincipal->OriginAttributesRef().IsPrivateBrowsing()) {
819 return;
823 mProcessName = aProfile + ":"_ns + mProcessName; //<profile_name>:example.com
826 void ContentChild::SetProcessName(const nsACString& aName,
827 const nsACString* aSite,
828 const nsACString* aCurrentProfile) {
829 char* name;
830 if ((name = PR_GetEnv("MOZ_DEBUG_APP_PROCESS")) && aName.EqualsASCII(name)) {
831 #ifdef XP_UNIX
832 printf_stderr("\n\nCHILDCHILDCHILDCHILD\n [%s] debug me @%d\n\n", name,
833 getpid());
834 sleep(30);
835 #elif defined(XP_WIN)
836 // Windows has a decent JIT debugging story, so NS_DebugBreak does the
837 // right thing.
838 NS_DebugBreak(NS_DEBUG_BREAK,
839 "Invoking NS_DebugBreak() to debug child process", nullptr,
840 __FILE__, __LINE__);
841 #endif
844 if (aSite) {
845 profiler_set_process_name(aName, aSite);
846 } else {
847 profiler_set_process_name(aName);
850 mProcessName = aName;
852 // Requires pref flip
853 if (aSite && StaticPrefs::fission_processSiteNames()) {
854 nsCOMPtr<nsIPrincipal> isolationPrincipal =
855 ContentParent::CreateRemoteTypeIsolationPrincipal(mRemoteType);
856 if (isolationPrincipal) {
857 // DEFAULT_PRIVATE_BROWSING_ID is the value when it's not private
858 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
859 ("private = %d, pref = %d",
860 isolationPrincipal->OriginAttributesRef().IsPrivateBrowsing(),
861 StaticPrefs::fission_processPrivateWindowSiteNames()));
862 if (!isolationPrincipal->OriginAttributesRef().IsPrivateBrowsing()
863 #ifdef NIGHTLY_BUILD
864 // Nightly can show site names for private windows, with a second pref
865 || StaticPrefs::fission_processPrivateWindowSiteNames()
866 #endif
868 #if !defined(XP_MACOSX)
869 // Mac doesn't have the 15-character limit Linux does
870 // Sets profiler process name
871 if (isolationPrincipal->SchemeIs("https")) {
872 nsAutoCString schemeless;
873 isolationPrincipal->GetHostPort(schemeless);
874 nsAutoCString originSuffix;
875 isolationPrincipal->GetOriginSuffix(originSuffix);
876 schemeless.Append(originSuffix);
877 mProcessName = schemeless;
878 } else
879 #endif
881 mProcessName = *aSite;
887 if (StaticPrefs::fission_processProfileName() && aCurrentProfile &&
888 !aCurrentProfile->IsEmpty()) {
889 AddProfileToProcessName(*aCurrentProfile);
892 // else private window, don't change process name, or the pref isn't set
893 // mProcessName is always flat (mProcessName == aName)
895 mozilla::ipc::SetThisProcessName(mProcessName.get());
897 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
898 ("Changed name of process %d to %s", getpid(),
899 PromiseFlatCString(mProcessName).get()));
902 static nsresult GetCreateWindowParams(nsIOpenWindowInfo* aOpenWindowInfo,
903 nsDocShellLoadState* aLoadState,
904 bool aForceNoReferrer,
905 nsIReferrerInfo** aReferrerInfo,
906 nsIPrincipal** aTriggeringPrincipal,
907 nsIContentSecurityPolicy** aCsp) {
908 if (!aTriggeringPrincipal || !aCsp) {
909 NS_ERROR("aTriggeringPrincipal || aCsp is null");
910 return NS_ERROR_FAILURE;
913 if (!aReferrerInfo) {
914 NS_ERROR("aReferrerInfo is null");
915 return NS_ERROR_FAILURE;
918 nsCOMPtr<nsIReferrerInfo> referrerInfo;
919 if (aForceNoReferrer) {
920 referrerInfo = new ReferrerInfo(nullptr, ReferrerPolicy::_empty, false);
922 if (aLoadState && !referrerInfo) {
923 referrerInfo = aLoadState->GetReferrerInfo();
926 RefPtr<BrowsingContext> parent = aOpenWindowInfo->GetParent();
927 nsCOMPtr<nsPIDOMWindowOuter> opener =
928 parent ? parent->GetDOMWindow() : nullptr;
929 if (!opener) {
930 nsCOMPtr<nsIPrincipal> nullPrincipal =
931 NullPrincipal::Create(aOpenWindowInfo->GetOriginAttributes());
932 if (!referrerInfo) {
933 referrerInfo = new ReferrerInfo(nullptr, ReferrerPolicy::_empty);
936 referrerInfo.swap(*aReferrerInfo);
937 NS_ADDREF(*aTriggeringPrincipal = nullPrincipal);
938 return NS_OK;
941 nsCOMPtr<Document> doc = opener->GetDoc();
942 NS_ADDREF(*aTriggeringPrincipal = doc->NodePrincipal());
944 nsCOMPtr<nsIContentSecurityPolicy> csp = doc->GetCsp();
945 if (csp) {
946 csp.forget(aCsp);
949 nsCOMPtr<nsIURI> baseURI = doc->GetDocBaseURI();
950 if (!baseURI) {
951 NS_ERROR("Document didn't return a base URI");
952 return NS_ERROR_FAILURE;
955 if (!referrerInfo) {
956 referrerInfo = new ReferrerInfo(*doc);
959 referrerInfo.swap(*aReferrerInfo);
960 return NS_OK;
963 nsresult ContentChild::ProvideWindowCommon(
964 NotNull<BrowserChild*> aTabOpener, nsIOpenWindowInfo* aOpenWindowInfo,
965 uint32_t aChromeFlags, bool aCalledFromJS, nsIURI* aURI,
966 const nsAString& aName, const nsACString& aFeatures,
967 const UserActivation::Modifiers& aModifiers, bool aForceNoOpener,
968 bool aForceNoReferrer, bool aIsPopupRequested,
969 nsDocShellLoadState* aLoadState, bool* aWindowIsNew,
970 BrowsingContext** aReturn) {
971 *aReturn = nullptr;
973 nsAutoCString features(aFeatures);
974 nsAutoString name(aName);
976 nsresult rv;
978 RefPtr<BrowsingContext> parent = aOpenWindowInfo->GetParent();
979 MOZ_DIAGNOSTIC_ASSERT(parent, "We must have a parent BC");
981 // Block the attempt to open a new window if the opening BrowsingContext is
982 // not marked to use remote tabs. This ensures that the newly opened window is
983 // correctly remote.
984 if (NS_WARN_IF(!parent->UseRemoteTabs())) {
985 return NS_ERROR_ABORT;
988 bool useRemoteSubframes =
989 aChromeFlags & nsIWebBrowserChrome::CHROME_FISSION_WINDOW;
991 uint32_t parentSandboxFlags = parent->SandboxFlags();
992 Document* doc = parent->GetDocument();
993 if (doc) {
994 parentSandboxFlags = doc->GetSandboxFlags();
997 // Certain conditions complicate the process of creating the new
998 // BrowsingContext, and prevent us from using the
999 // "CreateWindowInDifferentProcess" codepath.
1000 // * With Fission enabled, process selection will happen during the load, so
1001 // switching processes eagerly will not provide a benefit.
1002 // * Windows created for printing must be created within the current process
1003 // so that a static clone of the source document can be created.
1004 // * Sandboxed popups require the full window creation codepath.
1005 // * Loads with form or POST data require the full window creation codepath.
1006 bool cannotLoadInDifferentProcess =
1007 useRemoteSubframes || aOpenWindowInfo->GetIsForPrinting() ||
1008 (parentSandboxFlags &
1009 SANDBOX_PROPAGATES_TO_AUXILIARY_BROWSING_CONTEXTS) ||
1010 (aLoadState &&
1011 (aLoadState->IsFormSubmission() || aLoadState->PostDataStream()));
1012 if (!cannotLoadInDifferentProcess) {
1013 // If we're in a content process and we have noopener set, there's no reason
1014 // to load in our process, so let's load it elsewhere!
1015 bool loadInDifferentProcess =
1016 aForceNoOpener && StaticPrefs::dom_noopener_newprocess_enabled();
1017 if (loadInDifferentProcess) {
1018 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
1019 nsCOMPtr<nsIContentSecurityPolicy> csp;
1020 nsCOMPtr<nsIReferrerInfo> referrerInfo;
1021 rv = GetCreateWindowParams(aOpenWindowInfo, aLoadState, aForceNoReferrer,
1022 getter_AddRefs(referrerInfo),
1023 getter_AddRefs(triggeringPrincipal),
1024 getter_AddRefs(csp));
1025 if (NS_WARN_IF(NS_FAILED(rv))) {
1026 return rv;
1029 if (name.LowerCaseEqualsLiteral("_blank")) {
1030 name.Truncate();
1033 MOZ_DIAGNOSTIC_ASSERT(!nsContentUtils::IsSpecialName(name));
1035 const bool hasValidUserGestureActivation = [aLoadState, doc] {
1036 if (aLoadState) {
1037 return aLoadState->HasValidUserGestureActivation();
1039 if (doc) {
1040 return doc->HasValidTransientUserGestureActivation();
1042 return false;
1043 }();
1045 const bool textDirectiveUserActivation = [aLoadState, doc] {
1046 if (doc && doc->ConsumeTextDirectiveUserActivation()) {
1047 return true;
1049 if (aLoadState) {
1050 return aLoadState->GetTextDirectiveUserActivation();
1052 return false;
1053 }() || hasValidUserGestureActivation;
1055 Unused << SendCreateWindowInDifferentProcess(
1056 aTabOpener, parent, aChromeFlags, aCalledFromJS,
1057 aOpenWindowInfo->GetIsTopLevelCreatedByWebContent(), aURI, features,
1058 aModifiers, name, triggeringPrincipal, csp, referrerInfo,
1059 aOpenWindowInfo->GetOriginAttributes(), hasValidUserGestureActivation,
1060 textDirectiveUserActivation);
1062 // We return NS_ERROR_ABORT, so that the caller knows that we've abandoned
1063 // the window open as far as it is concerned.
1064 return NS_ERROR_ABORT;
1068 TabId tabId(nsContentUtils::GenerateTabId());
1070 // We need to assign a TabGroup to the PBrowser actor before we send it to the
1071 // parent. Otherwise, the parent could send messages to us before we have a
1072 // proper TabGroup for that actor.
1073 RefPtr<BrowsingContext> openerBC;
1074 if (!aForceNoOpener) {
1075 openerBC = parent;
1078 RefPtr<BrowsingContext> browsingContext = BrowsingContext::CreateDetached(
1079 nullptr, openerBC, nullptr, aName, BrowsingContext::Type::Content,
1080 {.isPopupRequested = aIsPopupRequested,
1081 .topLevelCreatedByWebContent = true});
1082 MOZ_ALWAYS_SUCCEEDS(browsingContext->SetRemoteTabs(true));
1083 MOZ_ALWAYS_SUCCEEDS(browsingContext->SetRemoteSubframes(useRemoteSubframes));
1084 MOZ_ALWAYS_SUCCEEDS(browsingContext->SetOriginAttributes(
1085 aOpenWindowInfo->GetOriginAttributes()));
1087 browsingContext->InitPendingInitialization(true);
1088 auto unsetPending = MakeScopeExit([browsingContext]() {
1089 Unused << browsingContext->SetPendingInitialization(false);
1092 browsingContext->EnsureAttached();
1094 // The initial about:blank document we generate within the nsDocShell will
1095 // almost certainly be replaced at some point. Unfortunately, getting the
1096 // principal right here causes bugs due to frame scripts not getting events
1097 // they expect, due to the real initial about:blank not being created yet.
1099 // For this reason, we intentionally mispredict the initial principal here, so
1100 // that we can act the same as we did before when not predicting a result
1101 // principal. This `PWindowGlobal` will almost immediately be destroyed.
1102 nsCOMPtr<nsIPrincipal> initialPrincipal =
1103 NullPrincipal::Create(browsingContext->OriginAttributesRef());
1104 WindowGlobalInit windowInit = WindowGlobalActor::AboutBlankInitializer(
1105 browsingContext, initialPrincipal);
1107 RefPtr<WindowGlobalChild> windowChild =
1108 WindowGlobalChild::CreateDisconnected(windowInit);
1109 if (NS_WARN_IF(!windowChild)) {
1110 return NS_ERROR_ABORT;
1113 auto newChild = MakeNotNull<RefPtr<BrowserChild>>(
1114 this, tabId, *aTabOpener, browsingContext, aChromeFlags,
1115 /* aIsTopLevel */ true);
1117 if (IsShuttingDown()) {
1118 return NS_ERROR_ABORT;
1121 // Open a remote endpoint for our PBrowser actor.
1122 ManagedEndpoint<PBrowserParent> parentEp = OpenPBrowserEndpoint(newChild);
1123 if (NS_WARN_IF(!parentEp.IsValid())) {
1124 return NS_ERROR_ABORT;
1127 // Open a remote endpoint for our PWindowGlobal actor.
1128 ManagedEndpoint<PWindowGlobalParent> windowParentEp =
1129 newChild->OpenPWindowGlobalEndpoint(windowChild);
1130 if (NS_WARN_IF(!windowParentEp.IsValid())) {
1131 return NS_ERROR_ABORT;
1134 // Tell the parent process to set up its PBrowserParent.
1135 PopupIPCTabContext ipcContext(aTabOpener, 0);
1136 if (NS_WARN_IF(!SendConstructPopupBrowser(
1137 std::move(parentEp), std::move(windowParentEp), tabId, ipcContext,
1138 windowInit, aChromeFlags))) {
1139 return NS_ERROR_ABORT;
1142 windowChild->Init();
1143 auto guardNullWindowGlobal = MakeScopeExit([&] {
1144 if (!windowChild->GetWindowGlobal()) {
1145 windowChild->Destroy();
1149 // Now that |newChild| has had its IPC link established, call |Init| to set it
1150 // up.
1151 // XXX: This MOZ_KnownLive is only necessary because the static analysis can't
1152 // tell that NotNull<RefPtr<BrowserChild>> is a strong pointer.
1153 RefPtr<nsPIDOMWindowOuter> parentWindow =
1154 parent ? parent->GetDOMWindow() : nullptr;
1155 if (NS_FAILED(MOZ_KnownLive(newChild)->Init(parentWindow, windowChild))) {
1156 return NS_ERROR_ABORT;
1159 // Set to true when we're ready to return from this function.
1160 bool ready = false;
1162 // NOTE: Capturing by reference here is safe, as this function won't return
1163 // until one of these callbacks is called.
1164 auto resolve = [&](CreatedWindowInfo&& info) {
1165 MOZ_RELEASE_ASSERT(NS_IsMainThread());
1166 rv = info.rv();
1167 *aWindowIsNew = info.windowOpened();
1168 nsTArray<FrameScriptInfo> frameScripts(std::move(info.frameScripts()));
1169 uint32_t maxTouchPoints = info.maxTouchPoints();
1170 DimensionInfo dimensionInfo = std::move(info.dimensions());
1172 // Once this function exits, we should try to exit the nested event loop.
1173 ready = true;
1175 // NOTE: We have to handle this immediately in the resolve callback in order
1176 // to make sure that we don't process any more IPC messages before returning
1177 // from ProvideWindowCommon.
1179 // Handle the error which we got back from the parent process, if we got
1180 // one.
1181 if (NS_FAILED(rv)) {
1182 return;
1185 if (!*aWindowIsNew) {
1186 rv = NS_ERROR_ABORT;
1187 return;
1190 // If the BrowserChild has been torn down, we don't need to do this anymore.
1191 if (NS_WARN_IF(!newChild->IPCOpen() || newChild->IsDestroyed())) {
1192 rv = NS_ERROR_ABORT;
1193 return;
1196 ParentShowInfo showInfo(u""_ns, /* fakeShowInfo = */ true,
1197 /* isTransparent = */ false,
1198 newChild->WebWidget()->GetDPI(),
1199 newChild->WebWidget()->RoundsWidgetCoordinatesTo(),
1200 newChild->WebWidget()->GetDefaultScale().scale);
1202 newChild->SetMaxTouchPoints(maxTouchPoints);
1204 if (aForceNoOpener || !parent) {
1205 MOZ_DIAGNOSTIC_ASSERT(!browsingContext->HadOriginalOpener());
1206 MOZ_DIAGNOSTIC_ASSERT(browsingContext->GetTopLevelCreatedByWebContent());
1207 MOZ_DIAGNOSTIC_ASSERT(browsingContext->GetOpenerId() == 0);
1208 } else {
1209 MOZ_DIAGNOSTIC_ASSERT(browsingContext->HadOriginalOpener());
1210 MOZ_DIAGNOSTIC_ASSERT(browsingContext->GetTopLevelCreatedByWebContent());
1211 MOZ_DIAGNOSTIC_ASSERT(browsingContext->GetOpenerId() == parent->Id());
1214 // Unfortunately we don't get a window unless we've shown the frame. That's
1215 // pretty bogus; see bug 763602.
1216 newChild->DoFakeShow(showInfo);
1218 newChild->RecvUpdateDimensions(dimensionInfo);
1220 for (size_t i = 0; i < frameScripts.Length(); i++) {
1221 FrameScriptInfo& info = frameScripts[i];
1222 if (!newChild->RecvLoadRemoteScript(info.url(),
1223 info.runInGlobalScope())) {
1224 MOZ_CRASH();
1228 if (xpc::IsInAutomation()) {
1229 if (nsCOMPtr<nsPIDOMWindowOuter> outer =
1230 do_GetInterface(newChild->WebNavigation())) {
1231 nsCOMPtr<nsIObserverService> obs(services::GetObserverService());
1232 obs->NotifyObservers(
1233 outer, "dangerous:test-only:new-browser-child-ready", nullptr);
1237 browsingContext.forget(aReturn);
1240 // NOTE: Capturing by reference here is safe, as this function won't return
1241 // until one of these callbacks is called.
1242 auto reject = [&](ResponseRejectReason) {
1243 MOZ_RELEASE_ASSERT(NS_IsMainThread());
1244 NS_WARNING("windowCreated promise rejected");
1245 rv = NS_ERROR_NOT_AVAILABLE;
1246 ready = true;
1249 // Send down the request to open the window.
1250 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
1251 nsCOMPtr<nsIContentSecurityPolicy> csp;
1252 nsCOMPtr<nsIReferrerInfo> referrerInfo;
1253 rv = GetCreateWindowParams(aOpenWindowInfo, aLoadState, aForceNoReferrer,
1254 getter_AddRefs(referrerInfo),
1255 getter_AddRefs(triggeringPrincipal),
1256 getter_AddRefs(csp));
1257 if (NS_WARN_IF(NS_FAILED(rv))) {
1258 return rv;
1261 SendCreateWindow(
1262 aTabOpener, parent, newChild, aChromeFlags, aCalledFromJS,
1263 aOpenWindowInfo->GetIsForPrinting(),
1264 aOpenWindowInfo->GetIsForWindowDotPrint(),
1265 aOpenWindowInfo->GetIsTopLevelCreatedByWebContent(), aURI, features,
1266 aModifiers, triggeringPrincipal, csp, referrerInfo,
1267 aOpenWindowInfo->GetOriginAttributes(),
1268 aLoadState ? aLoadState->HasValidUserGestureActivation() : false,
1269 aLoadState ? aLoadState->GetTextDirectiveUserActivation() : false,
1270 std::move(resolve), std::move(reject));
1272 // =======================
1273 // Begin Nested Event Loop
1274 // =======================
1276 // We have to wait for a response from SendCreateWindow or with information
1277 // we're going to need to return from this function, So we spin a nested event
1278 // loop until they get back to us.
1281 // Suppress event handling for all contexts in our BrowsingContextGroup so
1282 // that event handlers cannot target our new window while it's still being
1283 // opened. Note that pending events that were suppressed while our blocker
1284 // was active will be dispatched asynchronously from a runnable dispatched
1285 // to the main event loop after this function returns, not immediately when
1286 // we leave this scope.
1287 AutoSuppressEventHandlingAndSuspend seh(browsingContext->Group());
1289 AutoNoJSAPI nojsapi;
1291 // Spin the event loop until we get a response. Callers of this function
1292 // already have to guard against an inner event loop spinning in the
1293 // non-e10s case because of the need to spin one to create a new chrome
1294 // window.
1295 SpinEventLoopUntil("ContentChild::ProvideWindowCommon"_ns,
1296 [&]() { return ready; });
1297 MOZ_RELEASE_ASSERT(ready,
1298 "We are on the main thread, so we should not exit this "
1299 "loop without ready being true.");
1302 // =====================
1303 // End Nested Event Loop
1304 // =====================
1306 // It's possible for our new BrowsingContext to become discarded during the
1307 // nested event loop, in which case we shouldn't return it, since our callers
1308 // will generally not be prepared to deal with that.
1309 if (*aReturn && (*aReturn)->IsDiscarded()) {
1310 NS_RELEASE(*aReturn);
1311 return NS_ERROR_ABORT;
1314 // We should have the results already set by the callbacks.
1315 MOZ_ASSERT_IF(NS_SUCCEEDED(rv), *aReturn);
1316 return rv;
1319 bool ContentChild::IsAlive() const { return mIsAlive; }
1321 bool ContentChild::IsShuttingDown() const { return mShuttingDown; }
1323 void ContentChild::GetProcessName(nsACString& aName) const {
1324 aName = mProcessName;
1327 /* static */
1328 void ContentChild::AppendProcessId(nsACString& aName) {
1329 if (!aName.IsEmpty()) {
1330 aName.Append(' ');
1332 unsigned pid = getpid();
1333 aName.Append(nsPrintfCString("(pid %u)", pid));
1336 void ContentChild::InitGraphicsDeviceData(const ContentDeviceData& aData) {
1337 gfxPlatform::InitChild(aData);
1340 void ContentChild::InitSharedUASheets(Maybe<SharedMemoryHandle>&& aHandle,
1341 uintptr_t aAddress) {
1342 MOZ_ASSERT_IF(!aHandle, !aAddress);
1344 if (!aAddress) {
1345 return;
1348 // Map the shared memory storing the user agent style sheets. Do this as
1349 // early as possible to maximize the chance of being able to map at the
1350 // address we want.
1351 GlobalStyleSheetCache::SetSharedMemory(std::move(*aHandle), aAddress);
1354 void ContentChild::InitXPCOM(
1355 XPCOMInitData&& aXPCOMInit,
1356 const mozilla::dom::ipc::StructuredCloneData& aInitialData,
1357 bool aIsReadyForBackgroundProcessing) {
1358 #ifdef MOZ_WIDGET_GTK
1359 // LookAndFeel::NativeInit takes a long time to run on Linux, here we schedule
1360 // it as soon as possible after BackgroundChild::Startup to give
1361 // it chance to run ahead of ConstructBrowser
1362 nsCOMPtr<nsIRunnable> event = new nsGtkNativeInitRunnable();
1363 NS_DispatchToMainThreadQueue(event.forget(), EventQueuePriority::Idle);
1364 #endif
1366 #if defined(XP_WIN)
1367 // DLL services untrusted modules processing depends on
1368 // BackgroundChild::Startup having been called
1369 RefPtr<DllServices> dllSvc(DllServices::Get());
1370 dllSvc->StartUntrustedModulesProcessor(aIsReadyForBackgroundProcessing);
1371 #endif // defined(XP_WIN)
1373 PBackgroundChild* actorChild = BackgroundChild::GetOrCreateForCurrentThread();
1374 if (NS_WARN_IF(!actorChild)) {
1375 MOZ_ASSERT_UNREACHABLE("PBackground init can't fail at this point");
1376 return;
1379 ClientManager::Startup();
1381 // RemoteWorkerService will be initialized in RecvRemoteType, to avoid to
1382 // register it to the RemoteWorkerManager while it is still a prealloc
1383 // remoteType and defer it to the point the child process is assigned a.
1384 // actual remoteType.
1386 nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
1387 if (!svc) {
1388 NS_WARNING("Couldn't acquire console service");
1389 return;
1392 mConsoleListener = new ConsoleListener(this);
1393 if (NS_FAILED(svc->RegisterListener(mConsoleListener)))
1394 NS_WARNING("Couldn't register console listener for child process");
1396 mAvailableDictionaries = std::move(aXPCOMInit.dictionaries());
1398 RecvSetOffline(aXPCOMInit.isOffline());
1399 RecvSetConnectivity(aXPCOMInit.isConnected());
1401 LocaleService::GetInstance()->AssignAppLocales(aXPCOMInit.appLocales());
1402 LocaleService::GetInstance()->AssignRequestedLocales(
1403 aXPCOMInit.requestedLocales());
1405 L10nRegistry::RegisterFileSourcesFromParentProcess(
1406 aXPCOMInit.l10nFileSources());
1408 RecvSetCaptivePortalState(aXPCOMInit.captivePortalState());
1409 RecvBidiKeyboardNotify(aXPCOMInit.isLangRTL(),
1410 aXPCOMInit.haveBidiKeyboards());
1412 if (aXPCOMInit.domainPolicy().active()) {
1413 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
1414 MOZ_ASSERT(ssm);
1415 ssm->ActivateDomainPolicyInternal(getter_AddRefs(mPolicy));
1416 if (!mPolicy) {
1417 MOZ_CRASH("Failed to activate domain policy.");
1419 mPolicy->ApplyClone(&aXPCOMInit.domainPolicy());
1422 nsCOMPtr<nsIClipboard> clipboard(
1423 do_GetService("@mozilla.org/widget/clipboard;1"));
1424 if (nsCOMPtr<nsIClipboardProxy> clipboardProxy =
1425 do_QueryInterface(clipboard)) {
1426 clipboardProxy->SetCapabilities(aXPCOMInit.clipboardCaps());
1430 AutoJSAPI jsapi;
1431 if (NS_WARN_IF(!jsapi.Init(xpc::PrivilegedJunkScope()))) {
1432 MOZ_CRASH();
1434 ErrorResult rv;
1435 JS::Rooted<JS::Value> data(jsapi.cx());
1436 mozilla::dom::ipc::StructuredCloneData id;
1437 id.Copy(aInitialData);
1438 id.Read(jsapi.cx(), &data, rv);
1439 if (NS_WARN_IF(rv.Failed())) {
1440 MOZ_CRASH();
1442 auto* global = ContentProcessMessageManager::Get();
1443 global->SetInitialProcessData(data);
1446 // The stylesheet cache is not ready yet. Store this URL for future use.
1447 nsCOMPtr<nsIURI> ucsURL = std::move(aXPCOMInit.userContentSheetURL());
1448 GlobalStyleSheetCache::SetUserContentCSSURL(ucsURL);
1450 GfxInfoBase::SetFeatureStatus(std::move(aXPCOMInit.gfxFeatureStatus()));
1452 // Initialize the RemoteDecoderManager thread and its associated PBackground
1453 // channel.
1454 RemoteDecoderManagerChild::Init();
1456 Preferences::RegisterCallbackAndCall(&OnFissionBlocklistPrefChange,
1457 kFissionEnforceBlockList);
1458 Preferences::RegisterCallbackAndCall(&OnFissionBlocklistPrefChange,
1459 kFissionOmitBlockListValues);
1461 // Set the dynamic scalar definitions for this process.
1462 TelemetryIPC::AddDynamicScalarDefinitions(aXPCOMInit.dynamicScalarDefs());
1465 mozilla::ipc::IPCResult ContentChild::RecvRequestMemoryReport(
1466 const uint32_t& aGeneration, const bool& aAnonymize,
1467 const bool& aMinimizeMemoryUsage,
1468 const Maybe<mozilla::ipc::FileDescriptor>& aDMDFile,
1469 const RequestMemoryReportResolver& aResolver) {
1470 nsCString process;
1471 if (aAnonymize || mRemoteType.IsEmpty()) {
1472 GetProcessName(process);
1473 } else {
1474 process = mRemoteType;
1476 AppendProcessId(process);
1477 MOZ_ASSERT(!process.IsEmpty());
1479 MemoryReportRequestClient::Start(
1480 aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, process,
1481 [&](const MemoryReport& aReport) {
1482 Unused << GetSingleton()->SendAddMemoryReport(aReport);
1484 aResolver);
1485 return IPC_OK();
1488 #if defined(XP_WIN)
1489 mozilla::ipc::IPCResult ContentChild::RecvGetUntrustedModulesData(
1490 GetUntrustedModulesDataResolver&& aResolver) {
1491 RefPtr<DllServices> dllSvc(DllServices::Get());
1492 dllSvc->GetUntrustedModulesData()->Then(
1493 GetMainThreadSerialEventTarget(), __func__,
1494 [aResolver](Maybe<UntrustedModulesData>&& aData) {
1495 aResolver(std::move(aData));
1497 [aResolver](nsresult aReason) { aResolver(Nothing()); });
1498 return IPC_OK();
1501 mozilla::ipc::IPCResult ContentChild::RecvUnblockUntrustedModulesThread() {
1502 if (nsCOMPtr<nsIObserverService> obs =
1503 mozilla::services::GetObserverService()) {
1504 obs->NotifyObservers(nullptr, "unblock-untrusted-modules-thread", nullptr);
1506 return IPC_OK();
1508 #endif // defined(XP_WIN)
1510 PCycleCollectWithLogsChild* ContentChild::AllocPCycleCollectWithLogsChild(
1511 const bool& aDumpAllTraces, const FileDescriptor& aGCLog,
1512 const FileDescriptor& aCCLog) {
1513 return do_AddRef(new CycleCollectWithLogsChild()).take();
1516 mozilla::ipc::IPCResult ContentChild::RecvPCycleCollectWithLogsConstructor(
1517 PCycleCollectWithLogsChild* aActor, const bool& aDumpAllTraces,
1518 const FileDescriptor& aGCLog, const FileDescriptor& aCCLog) {
1519 // The sink's destructor is called when the last reference goes away, which
1520 // will cause the actor to be closed down.
1521 auto* actor = static_cast<CycleCollectWithLogsChild*>(aActor);
1522 RefPtr<CycleCollectWithLogsChild::Sink> sink =
1523 new CycleCollectWithLogsChild::Sink(actor, aGCLog, aCCLog);
1525 // Invoke the dumper, which will take a reference to the sink.
1526 nsCOMPtr<nsIMemoryInfoDumper> dumper =
1527 do_GetService("@mozilla.org/memory-info-dumper;1");
1528 dumper->DumpGCAndCCLogsToSink(aDumpAllTraces, sink);
1529 return IPC_OK();
1532 bool ContentChild::DeallocPCycleCollectWithLogsChild(
1533 PCycleCollectWithLogsChild* aActor) {
1534 RefPtr<CycleCollectWithLogsChild> actor =
1535 dont_AddRef(static_cast<CycleCollectWithLogsChild*>(aActor));
1536 return true;
1539 mozilla::ipc::IPCResult ContentChild::RecvInitGMPService(
1540 Endpoint<PGMPServiceChild>&& aGMPService) {
1541 if (!GMPServiceChild::Create(std::move(aGMPService))) {
1542 return IPC_FAIL_NO_REASON(this);
1544 return IPC_OK();
1547 mozilla::ipc::IPCResult ContentChild::RecvInitClipboardContentAnalysis(
1548 Endpoint<PClipboardContentAnalysisChild>&& aEndpoint) {
1549 if (!ClipboardContentAnalysisChild::Create(std::move(aEndpoint))) {
1550 return IPC_FAIL_NO_REASON(this);
1552 return IPC_OK();
1555 mozilla::ipc::IPCResult ContentChild::RecvInitProfiler(
1556 Endpoint<PProfilerChild>&& aEndpoint) {
1557 mProfilerController = ChildProfilerController::Create(std::move(aEndpoint));
1558 return IPC_OK();
1561 mozilla::ipc::IPCResult ContentChild::RecvGMPsChanged(
1562 nsTArray<GMPCapabilityData>&& capabilities) {
1563 GeckoMediaPluginServiceChild::UpdateGMPCapabilities(std::move(capabilities));
1564 return IPC_OK();
1567 mozilla::ipc::IPCResult ContentChild::RecvInitProcessHangMonitor(
1568 Endpoint<PProcessHangMonitorChild>&& aHangMonitor) {
1569 CreateHangMonitorChild(std::move(aHangMonitor));
1570 return IPC_OK();
1573 mozilla::ipc::IPCResult ContentChild::GetResultForRenderingInitFailure(
1574 base::ProcessId aOtherPid) {
1575 if (aOtherPid == base::GetCurrentProcId() || aOtherPid == OtherPid()) {
1576 // If we are talking to ourselves, or the UI process, then that is a fatal
1577 // protocol error.
1578 return IPC_FAIL_NO_REASON(this);
1581 // If we are talking to the GPU process, then we should recover from this on
1582 // the next ContentChild::RecvReinitRendering call.
1583 gfxCriticalNote << "Could not initialize rendering with GPU process";
1584 return IPC_OK();
1587 #if defined(XP_MACOSX)
1588 extern "C" {
1589 void CGSShutdownServerConnections();
1591 #endif
1593 mozilla::ipc::IPCResult ContentChild::RecvInitRendering(
1594 Endpoint<PCompositorManagerChild>&& aCompositor,
1595 Endpoint<PImageBridgeChild>&& aImageBridge,
1596 Endpoint<PVRManagerChild>&& aVRBridge,
1597 Endpoint<PRemoteDecoderManagerChild>&& aVideoManager,
1598 nsTArray<uint32_t>&& namespaces) {
1599 MOZ_ASSERT(namespaces.Length() == 3);
1601 // Note that for all of the methods below, if it can fail, it should only
1602 // return false if the failure is an IPDL error. In such situations,
1603 // ContentChild can reason about whether or not to wait for
1604 // RecvReinitRendering (because we surmised the GPU process crashed), or if it
1605 // should crash itself (because we are actually talking to the UI process). If
1606 // there are localized failures (e.g. failed to spawn a thread), then it
1607 // should MOZ_RELEASE_ASSERT or MOZ_CRASH as necessary instead.
1608 if (!CompositorManagerChild::Init(std::move(aCompositor), namespaces[0])) {
1609 return GetResultForRenderingInitFailure(aCompositor.OtherPid());
1611 if (!CompositorManagerChild::CreateContentCompositorBridge(namespaces[1])) {
1612 return GetResultForRenderingInitFailure(aCompositor.OtherPid());
1614 if (!ImageBridgeChild::InitForContent(std::move(aImageBridge),
1615 namespaces[2])) {
1616 return GetResultForRenderingInitFailure(aImageBridge.OtherPid());
1618 if (!gfx::VRManagerChild::InitForContent(std::move(aVRBridge))) {
1619 return GetResultForRenderingInitFailure(aVRBridge.OtherPid());
1621 RemoteDecoderManagerChild::InitForGPUProcess(std::move(aVideoManager));
1623 #if defined(XP_MACOSX) && !defined(MOZ_SANDBOX)
1624 // Close all current connections to the WindowServer. This ensures that the
1625 // Activity Monitor will not label the content process as "Not responding"
1626 // because it's not running a native event loop. See bug 1384336. When the
1627 // build is configured with sandbox support, this is called during sandbox
1628 // setup.
1629 CGSShutdownServerConnections();
1630 #endif
1632 return IPC_OK();
1635 mozilla::ipc::IPCResult ContentChild::RecvReinitRendering(
1636 Endpoint<PCompositorManagerChild>&& aCompositor,
1637 Endpoint<PImageBridgeChild>&& aImageBridge,
1638 Endpoint<PVRManagerChild>&& aVRBridge,
1639 Endpoint<PRemoteDecoderManagerChild>&& aVideoManager,
1640 nsTArray<uint32_t>&& namespaces) {
1641 MOZ_ASSERT(namespaces.Length() == 3);
1642 nsTArray<RefPtr<BrowserChild>> tabs = BrowserChild::GetAll();
1644 // Re-establish singleton bridges to the compositor.
1645 if (!CompositorManagerChild::Init(std::move(aCompositor), namespaces[0])) {
1646 return GetResultForRenderingInitFailure(aCompositor.OtherPid());
1648 if (!CompositorManagerChild::CreateContentCompositorBridge(namespaces[1])) {
1649 return GetResultForRenderingInitFailure(aCompositor.OtherPid());
1651 if (!ImageBridgeChild::ReinitForContent(std::move(aImageBridge),
1652 namespaces[2])) {
1653 return GetResultForRenderingInitFailure(aImageBridge.OtherPid());
1655 if (!gfx::VRManagerChild::InitForContent(std::move(aVRBridge))) {
1656 return GetResultForRenderingInitFailure(aVRBridge.OtherPid());
1658 gfxPlatform::GetPlatform()->CompositorUpdated();
1660 // Establish new PLayerTransactions.
1661 for (const auto& browserChild : tabs) {
1662 if (browserChild->GetLayersId().IsValid()) {
1663 browserChild->ReinitRendering();
1667 // Notify any observers that the compositor has been reinitialized,
1668 // eg the ZoomConstraintsClients for documents in this process.
1669 // This must occur after the ReinitRendering call above so that the
1670 // APZCTreeManagers have been connected.
1671 nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
1672 if (observerService) {
1673 observerService->NotifyObservers(nullptr, "compositor-reinitialized",
1674 nullptr);
1677 RemoteDecoderManagerChild::InitForGPUProcess(std::move(aVideoManager));
1678 return IPC_OK();
1681 mozilla::ipc::IPCResult ContentChild::RecvReinitRenderingForDeviceReset() {
1682 gfxPlatform::GetPlatform()->CompositorUpdated();
1684 nsTArray<RefPtr<BrowserChild>> tabs = BrowserChild::GetAll();
1685 for (const auto& browserChild : tabs) {
1686 if (browserChild->GetLayersId().IsValid()) {
1687 browserChild->ReinitRenderingForDeviceReset();
1690 return IPC_OK();
1693 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
1694 extern "C" {
1695 CGError CGSSetDenyWindowServerConnections(bool);
1698 static void DisconnectWindowServer(bool aIsSandboxEnabled) {
1699 // Close all current connections to the WindowServer. This ensures that the
1700 // Activity Monitor will not label the content process as "Not responding"
1701 // because it's not running a native event loop. See bug 1384336.
1702 // This is required with or without the sandbox enabled. Until the
1703 // window server is blocked as the policy level, this should be called
1704 // just before CGSSetDenyWindowServerConnections() so there are no
1705 // windowserver connections active when CGSSetDenyWindowServerConnections()
1706 // is called.
1707 CGSShutdownServerConnections();
1709 // Actual security benefits are only achieved when we additionally deny
1710 // future connections using the sandbox policy. WebGL must be remoted if
1711 // the windowserver connections are blocked. WebGL remoting is disabled
1712 // for some tests.
1713 if (aIsSandboxEnabled &&
1714 Preferences::GetBool(
1715 "security.sandbox.content.mac.disconnect-windowserver") &&
1716 Preferences::GetBool("webgl.out-of-process")) {
1717 CGError result = CGSSetDenyWindowServerConnections(true);
1718 MOZ_DIAGNOSTIC_ASSERT(result == kCGErrorSuccess);
1719 # if !MOZ_DIAGNOSTIC_ASSERT_ENABLED
1720 Unused << result;
1721 # endif
1724 #endif
1726 mozilla::ipc::IPCResult ContentChild::RecvSetProcessSandbox(
1727 const Maybe<mozilla::ipc::FileDescriptor>& aBroker) {
1728 // We may want to move the sandbox initialization somewhere else
1729 // at some point; see bug 880808.
1730 #if defined(MOZ_SANDBOX)
1732 bool sandboxEnabled = true;
1733 # if defined(XP_LINUX)
1734 // On Linux, we have to support systems that can't use any sandboxing.
1735 sandboxEnabled = SandboxInfo::Get().CanSandboxContent();
1737 if (sandboxEnabled && !StaticPrefs::media_cubeb_sandbox()) {
1738 // Pre-start audio before sandboxing; see bug 1443612.
1739 Unused << CubebUtils::GetCubeb();
1742 if (sandboxEnabled) {
1743 RegisterProfilerObserversForSandboxProfiler();
1744 sandboxEnabled = SetContentProcessSandbox(
1745 ContentProcessSandboxParams::ForThisProcess(aBroker));
1747 # elif defined(XP_WIN)
1748 if (GetEffectiveContentSandboxLevel() > 7) {
1749 // Library required for timely audio processing.
1750 ::LoadLibraryW(L"avrt.dll");
1751 // Libraries required by Network Security Services (NSS).
1752 ::LoadLibraryW(L"freebl3.dll");
1753 ::LoadLibraryW(L"softokn3.dll");
1754 // Library required by DirectWrite in some fall-back scenarios.
1755 ::LoadLibraryW(L"textshaping.dll");
1756 // Libraries that are required for WMF software encoding.
1757 ::LoadLibraryW(L"mozavcodec.dll");
1758 ::LoadLibraryW(L"mozavutil.dll");
1759 ::LoadLibraryW(L"mfplat.dll");
1760 ::LoadLibraryW(L"mf.dll");
1761 ::LoadLibraryW(L"dxva2.dll");
1762 ::LoadLibraryW(L"evr.dll");
1763 ::LoadLibraryW(L"mfh264enc.dll");
1764 // Cache value that is retrieved from a registry entry.
1765 Unused << GetCpuFrequencyMHz();
1766 # if defined(DEBUG)
1767 // Library used in some debug testing.
1768 ::LoadLibraryW(L"dbghelp.dll");
1769 // Required for WMF shutdown, not required for opt due to quick exit.
1770 ::LoadLibraryW(L"ole32.dll");
1771 # endif
1773 mozilla::SandboxTarget::Instance()->StartSandbox();
1774 # elif defined(XP_MACOSX)
1775 sandboxEnabled = (GetEffectiveContentSandboxLevel() >= 1);
1776 DisconnectWindowServer(sandboxEnabled);
1777 # endif
1779 CrashReporter::RecordAnnotationBool(
1780 CrashReporter::Annotation::ContentSandboxEnabled, sandboxEnabled);
1781 # if defined(XP_LINUX) && !defined(ANDROID)
1782 CrashReporter::RecordAnnotationU32(
1783 CrashReporter::Annotation::ContentSandboxCapabilities,
1784 SandboxInfo::Get().AsInteger());
1785 # endif /* XP_LINUX && !ANDROID */
1786 #endif /* MOZ_SANDBOX */
1788 return IPC_OK();
1791 mozilla::ipc::IPCResult ContentChild::RecvBidiKeyboardNotify(
1792 const bool& aIsLangRTL, const bool& aHaveBidiKeyboards) {
1793 // bidi is always of type PuppetBidiKeyboard* (because in the child, the only
1794 // possible implementation of nsIBidiKeyboard is PuppetBidiKeyboard).
1795 PuppetBidiKeyboard* bidi =
1796 static_cast<PuppetBidiKeyboard*>(nsContentUtils::GetBidiKeyboard());
1797 if (bidi) {
1798 bidi->SetBidiKeyboardInfo(aIsLangRTL, aHaveBidiKeyboards);
1800 return IPC_OK();
1803 static StaticRefPtr<CancelableRunnable> gFirstIdleTask;
1805 static void FirstIdle(void) {
1806 MOZ_ASSERT(gFirstIdleTask);
1807 gFirstIdleTask = nullptr;
1809 ContentChild::GetSingleton()->SendFirstIdle();
1812 mozilla::ipc::IPCResult ContentChild::RecvConstructBrowser(
1813 ManagedEndpoint<PBrowserChild>&& aBrowserEp,
1814 ManagedEndpoint<PWindowGlobalChild>&& aWindowEp, const TabId& aTabId,
1815 const IPCTabContext& aContext, const WindowGlobalInit& aWindowInit,
1816 const uint32_t& aChromeFlags, const ContentParentId& aCpID,
1817 const bool& aIsForBrowser, const bool& aIsTopLevel) {
1818 MOZ_DIAGNOSTIC_ASSERT(!IsShuttingDown());
1820 static bool hasRunOnce = false;
1821 if (!hasRunOnce) {
1822 hasRunOnce = true;
1823 MOZ_ASSERT(!gFirstIdleTask);
1824 RefPtr<CancelableRunnable> firstIdleTask =
1825 NewCancelableRunnableFunction("FirstIdleRunnable", FirstIdle);
1826 gFirstIdleTask = firstIdleTask;
1827 if (NS_FAILED(NS_DispatchToCurrentThreadQueue(firstIdleTask.forget(),
1828 EventQueuePriority::Idle))) {
1829 gFirstIdleTask = nullptr;
1830 hasRunOnce = false;
1834 RefPtr<BrowsingContext> browsingContext =
1835 BrowsingContext::Get(aWindowInit.context().mBrowsingContextId);
1836 if (!browsingContext || browsingContext->IsDiscarded()) {
1837 nsPrintfCString reason("%s initial %s BrowsingContext",
1838 browsingContext ? "discarded" : "missing",
1839 aIsTopLevel ? "top" : "frame");
1840 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Warning, ("%s", reason.get()));
1841 if (!aIsTopLevel) {
1842 // Recover if the BrowsingContext is missing for a new subframe. The
1843 // `ManagedEndpoint` instances will be automatically destroyed.
1844 NS_WARNING(reason.get());
1845 return IPC_OK();
1848 // (these are the only possible values of `reason` at this point)
1849 return browsingContext
1850 ? IPC_FAIL(this, "discarded initial top BrowsingContext")
1851 : IPC_FAIL(this, "missing initial top BrowsingContext");
1854 if (xpc::IsInAutomation() &&
1855 StaticPrefs::
1856 browser_tabs_remote_testOnly_failPBrowserCreation_enabled()) {
1857 nsAutoCString idString;
1858 if (NS_SUCCEEDED(Preferences::GetCString(
1859 "browser.tabs.remote.testOnly.failPBrowserCreation.browsingContext",
1860 idString))) {
1861 nsresult rv = NS_OK;
1862 uint64_t bcid = idString.ToInteger64(&rv);
1863 if (NS_SUCCEEDED(rv) && bcid == browsingContext->Id()) {
1864 NS_WARNING("Injecting artificial PBrowser creation failure");
1865 return IPC_OK();
1870 if (!aWindowInit.isInitialDocument() ||
1871 !NS_IsAboutBlank(aWindowInit.documentURI())) {
1872 return IPC_FAIL(this,
1873 "Logic in CreateDocumentViewerForActor currently requires "
1874 "actors to be initial about:blank documents");
1877 // We'll happily accept any kind of IPCTabContext here; we don't need to
1878 // check that it's of a certain type for security purposes, because we
1879 // believe whatever the parent process tells us.
1880 MaybeInvalidTabContext tc(aContext);
1881 if (!tc.IsValid()) {
1882 NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
1883 "the parent process. (%s) Crashing...",
1884 tc.GetInvalidReason())
1885 .get());
1886 MOZ_CRASH("Invalid TabContext received from the parent process.");
1889 RefPtr<WindowGlobalChild> windowChild =
1890 WindowGlobalChild::CreateDisconnected(aWindowInit);
1891 if (!windowChild) {
1892 return IPC_FAIL(this, "Failed to create initial WindowGlobalChild");
1895 RefPtr<BrowserChild> browserChild =
1896 BrowserChild::Create(this, aTabId, tc.GetTabContext(), browsingContext,
1897 aChromeFlags, aIsTopLevel);
1899 // Bind the created BrowserChild to IPC to actually link the actor.
1900 if (NS_WARN_IF(!BindPBrowserEndpoint(std::move(aBrowserEp), browserChild))) {
1901 return IPC_FAIL(this, "BindPBrowserEndpoint failed");
1904 if (NS_WARN_IF(!browserChild->BindPWindowGlobalEndpoint(std::move(aWindowEp),
1905 windowChild))) {
1906 return IPC_FAIL(this, "BindPWindowGlobalEndpoint failed");
1908 windowChild->Init();
1909 auto guardNullWindowGlobal = MakeScopeExit([&] {
1910 if (!windowChild->GetWindowGlobal()) {
1911 windowChild->Destroy();
1915 // Ensure that a BrowsingContext is set for our BrowserChild before
1916 // running `Init`.
1917 MOZ_RELEASE_ASSERT(browserChild->mBrowsingContext->Id() ==
1918 aWindowInit.context().mBrowsingContextId);
1920 if (NS_WARN_IF(
1921 NS_FAILED(browserChild->Init(/* aOpener */ nullptr, windowChild)))) {
1922 return IPC_FAIL(browserChild, "BrowserChild::Init failed");
1925 nsCOMPtr<nsIObserverService> os = services::GetObserverService();
1926 if (os) {
1927 os->NotifyObservers(static_cast<nsIBrowserChild*>(browserChild),
1928 "tab-child-created", nullptr);
1930 // Notify parent that we are ready to handle input events.
1931 browserChild->SendRemoteIsReadyToHandleInputEvents();
1932 return IPC_OK();
1935 void ContentChild::GetAvailableDictionaries(
1936 nsTArray<nsCString>& aDictionaries) {
1937 aDictionaries = mAvailableDictionaries.Clone();
1940 mozilla::PRemoteSpellcheckEngineChild*
1941 ContentChild::AllocPRemoteSpellcheckEngineChild() {
1942 MOZ_CRASH(
1943 "Default Constructor for PRemoteSpellcheckEngineChild should never be "
1944 "called");
1945 return nullptr;
1948 bool ContentChild::DeallocPRemoteSpellcheckEngineChild(
1949 PRemoteSpellcheckEngineChild* child) {
1950 delete child;
1951 return true;
1954 mozilla::ipc::IPCResult ContentChild::RecvNotifyEmptyHTTPCache() {
1955 MOZ_ASSERT(NS_IsMainThread());
1956 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
1957 obs->NotifyObservers(nullptr, "cacheservice:empty-cache", nullptr);
1958 return IPC_OK();
1961 PHalChild* ContentChild::AllocPHalChild() { return CreateHalChild(); }
1963 bool ContentChild::DeallocPHalChild(PHalChild* aHal) {
1964 delete aHal;
1965 return true;
1968 devtools::PHeapSnapshotTempFileHelperChild*
1969 ContentChild::AllocPHeapSnapshotTempFileHelperChild() {
1970 return devtools::HeapSnapshotTempFileHelperChild::Create();
1973 bool ContentChild::DeallocPHeapSnapshotTempFileHelperChild(
1974 devtools::PHeapSnapshotTempFileHelperChild* aHeapSnapshotHelper) {
1975 delete aHeapSnapshotHelper;
1976 return true;
1979 already_AddRefed<PTestShellChild> ContentChild::AllocPTestShellChild() {
1980 return MakeAndAddRef<TestShellChild>();
1983 mozilla::ipc::IPCResult ContentChild::RecvPTestShellConstructor(
1984 PTestShellChild* actor) {
1985 return IPC_OK();
1988 RefPtr<GenericPromise> ContentChild::UpdateCookieStatus(nsIChannel* aChannel) {
1989 RefPtr<CookieServiceChild> csChild = CookieServiceChild::GetSingleton();
1990 NS_ASSERTION(csChild, "Couldn't get CookieServiceChild");
1992 return csChild->TrackCookieLoad(aChannel);
1995 PScriptCacheChild* ContentChild::AllocPScriptCacheChild(
1996 const FileDescOrError& cacheFile, const bool& wantCacheData) {
1997 return new loader::ScriptCacheChild();
2000 bool ContentChild::DeallocPScriptCacheChild(PScriptCacheChild* cache) {
2001 delete static_cast<loader::ScriptCacheChild*>(cache);
2002 return true;
2005 mozilla::ipc::IPCResult ContentChild::RecvPScriptCacheConstructor(
2006 PScriptCacheChild* actor, const FileDescOrError& cacheFile,
2007 const bool& wantCacheData) {
2008 Maybe<FileDescriptor> fd;
2009 if (cacheFile.type() == cacheFile.TFileDescriptor) {
2010 fd.emplace(cacheFile.get_FileDescriptor());
2013 static_cast<loader::ScriptCacheChild*>(actor)->Init(fd, wantCacheData);
2015 // Some scripts listen for "app-startup" to start. However, in the content
2016 // process, this category runs before the ScriptPreloader is initialized so
2017 // these scripts wouldn't be added to the cache. Instead, if a script needs to
2018 // run on start up in the content process, it should listen for this category.
2019 NS_CreateServicesFromCategory("content-process-ready-for-script", nullptr,
2020 "content-process-ready-for-script", nullptr);
2022 return IPC_OK();
2025 mozilla::ipc::IPCResult ContentChild::RecvNetworkLinkTypeChange(
2026 const uint32_t& aType) {
2027 mNetworkLinkType = aType;
2028 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
2029 if (obs) {
2030 obs->NotifyObservers(nullptr, "contentchild:network-link-type-changed",
2031 nullptr);
2033 return IPC_OK();
2036 mozilla::ipc::IPCResult ContentChild::RecvSocketProcessCrashed() {
2037 nsIOService::IncreaseSocketProcessCrashCount();
2038 return IPC_OK();
2041 PRemotePrintJobChild* ContentChild::AllocPRemotePrintJobChild() {
2042 #ifdef NS_PRINTING
2043 return new RemotePrintJobChild();
2044 #else
2045 return nullptr;
2046 #endif
2049 media::PMediaChild* ContentChild::AllocPMediaChild() {
2050 return media::AllocPMediaChild();
2053 bool ContentChild::DeallocPMediaChild(media::PMediaChild* aActor) {
2054 return media::DeallocPMediaChild(aActor);
2057 PBenchmarkStorageChild* ContentChild::AllocPBenchmarkStorageChild() {
2058 return BenchmarkStorageChild::Instance();
2061 bool ContentChild::DeallocPBenchmarkStorageChild(
2062 PBenchmarkStorageChild* aActor) {
2063 delete aActor;
2064 return true;
2067 #ifdef MOZ_WEBRTC
2068 PWebrtcGlobalChild* ContentChild::AllocPWebrtcGlobalChild() {
2069 auto* child = new WebrtcGlobalChild();
2070 return child;
2073 bool ContentChild::DeallocPWebrtcGlobalChild(PWebrtcGlobalChild* aActor) {
2074 delete static_cast<WebrtcGlobalChild*>(aActor);
2075 return true;
2077 #endif
2079 mozilla::ipc::IPCResult ContentChild::RecvRegisterChrome(
2080 nsTArray<ChromePackage>&& packages,
2081 nsTArray<SubstitutionMapping>&& resources,
2082 nsTArray<OverrideMapping>&& overrides, const nsCString& locale,
2083 const bool& reset) {
2084 nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
2085 nsChromeRegistryContent* chromeRegistry =
2086 static_cast<nsChromeRegistryContent*>(registrySvc.get());
2087 if (!chromeRegistry) {
2088 return IPC_FAIL(this, "ChromeRegistryContent is null!");
2090 chromeRegistry->RegisterRemoteChrome(packages, resources, overrides, locale,
2091 reset);
2092 return IPC_OK();
2095 mozilla::ipc::IPCResult ContentChild::RecvRegisterChromeItem(
2096 const ChromeRegistryItem& item) {
2097 nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
2098 nsChromeRegistryContent* chromeRegistry =
2099 static_cast<nsChromeRegistryContent*>(registrySvc.get());
2100 if (!chromeRegistry) {
2101 return IPC_FAIL(this, "ChromeRegistryContent is null!");
2103 switch (item.type()) {
2104 case ChromeRegistryItem::TChromePackage:
2105 chromeRegistry->RegisterPackage(item.get_ChromePackage());
2106 break;
2108 case ChromeRegistryItem::TOverrideMapping:
2109 chromeRegistry->RegisterOverride(item.get_OverrideMapping());
2110 break;
2112 case ChromeRegistryItem::TSubstitutionMapping:
2113 chromeRegistry->RegisterSubstitution(item.get_SubstitutionMapping());
2114 break;
2116 default:
2117 MOZ_ASSERT(false, "bad chrome item");
2118 return IPC_FAIL_NO_REASON(this);
2121 return IPC_OK();
2123 mozilla::ipc::IPCResult ContentChild::RecvClearStyleSheetCache(
2124 const Maybe<RefPtr<nsIPrincipal>>& aForPrincipal,
2125 const Maybe<nsCString>& aBaseDomain) {
2126 nsIPrincipal* principal =
2127 aForPrincipal ? aForPrincipal.value().get() : nullptr;
2128 const nsCString* baseDomain = aBaseDomain ? aBaseDomain.ptr() : nullptr;
2129 SharedStyleSheetCache::Clear(principal, baseDomain);
2130 return IPC_OK();
2133 mozilla::ipc::IPCResult ContentChild::RecvClearImageCacheFromPrincipal(
2134 nsIPrincipal* aPrincipal) {
2135 imgLoader* loader;
2136 if (aPrincipal->OriginAttributesRef().IsPrivateBrowsing()) {
2137 loader = imgLoader::PrivateBrowsingLoader();
2138 } else {
2139 loader = imgLoader::NormalLoader();
2142 loader->RemoveEntriesInternal(aPrincipal, nullptr);
2143 return IPC_OK();
2146 mozilla::ipc::IPCResult ContentChild::RecvClearImageCacheFromBaseDomain(
2147 const nsCString& aBaseDomain) {
2148 imgLoader::NormalLoader()->RemoveEntriesInternal(nullptr, &aBaseDomain);
2149 imgLoader::PrivateBrowsingLoader()->RemoveEntriesInternal(nullptr,
2150 &aBaseDomain);
2152 return IPC_OK();
2155 mozilla::ipc::IPCResult ContentChild::RecvClearImageCache(
2156 const bool& privateLoader, const bool& chrome) {
2157 imgLoader* loader = privateLoader ? imgLoader::PrivateBrowsingLoader()
2158 : imgLoader::NormalLoader();
2160 loader->ClearCache(chrome);
2161 return IPC_OK();
2164 mozilla::ipc::IPCResult ContentChild::RecvSetOffline(const bool& offline) {
2165 nsCOMPtr<nsIIOService> io(do_GetIOService());
2166 NS_ASSERTION(io, "IO Service can not be null");
2168 io->SetOffline(offline);
2170 return IPC_OK();
2173 mozilla::ipc::IPCResult ContentChild::RecvSetConnectivity(
2174 const bool& connectivity) {
2175 nsCOMPtr<nsIIOService> io(do_GetIOService());
2176 nsCOMPtr<nsIIOServiceInternal> ioInternal(do_QueryInterface(io));
2177 NS_ASSERTION(ioInternal, "IO Service can not be null");
2179 ioInternal->SetConnectivity(connectivity);
2181 return IPC_OK();
2184 mozilla::ipc::IPCResult ContentChild::RecvSetCaptivePortalState(
2185 const int32_t& aState) {
2186 nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID);
2187 if (!cps) {
2188 return IPC_OK();
2191 mozilla::net::CaptivePortalService* portal =
2192 static_cast<mozilla::net::CaptivePortalService*>(cps.get());
2193 portal->SetStateInChild(aState);
2195 return IPC_OK();
2198 mozilla::ipc::IPCResult ContentChild::RecvSetTRRMode(
2199 const nsIDNSService::ResolverMode& mode,
2200 const nsIDNSService::ResolverMode& modeFromPref) {
2201 RefPtr<net::ChildDNSService> dnsServiceChild =
2202 dont_AddRef(net::ChildDNSService::GetSingleton());
2203 if (dnsServiceChild) {
2204 dnsServiceChild->SetTRRModeInChild(mode, modeFromPref);
2206 return IPC_OK();
2209 void ContentChild::ActorDestroy(ActorDestroyReason why) {
2210 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
2211 DestroySandboxProfiler();
2212 #endif
2214 if (mForceKillTimer) {
2215 mForceKillTimer->Cancel();
2216 mForceKillTimer = nullptr;
2219 if (AbnormalShutdown == why) {
2220 NS_WARNING("shutting down early because of crash!");
2221 ProcessChild::QuickExit();
2224 #ifndef NS_FREE_PERMANENT_DATA
2225 // In release builds, there's no point in the content process
2226 // going through the full XPCOM shutdown path, because it doesn't
2227 // keep persistent state.
2228 ProcessChild::QuickExit();
2229 #else
2230 // Destroy our JSProcessActors, and reject any pending queries.
2231 JSActorDidDestroy();
2233 # if defined(XP_WIN)
2234 RefPtr<DllServices> dllSvc(DllServices::Get());
2235 dllSvc->DisableFull();
2236 # endif // defined(XP_WIN)
2238 if (gFirstIdleTask) {
2239 gFirstIdleTask->Cancel();
2240 gFirstIdleTask = nullptr;
2243 BlobURLProtocolHandler::RemoveDataEntries();
2245 mSharedData = nullptr;
2247 mAlertObservers.Clear();
2249 mIdleObservers.Clear();
2251 if (mConsoleListener) {
2252 nsCOMPtr<nsIConsoleService> svc(
2253 do_GetService(NS_CONSOLESERVICE_CONTRACTID));
2254 if (svc) {
2255 svc->UnregisterListener(mConsoleListener);
2256 mConsoleListener->mChild = nullptr;
2259 mIsAlive = false;
2261 CrashReporterClient::DestroySingleton();
2263 XRE_ShutdownChildProcess();
2264 #endif // NS_FREE_PERMANENT_DATA
2267 void ContentChild::ProcessingError(Result aCode, const char* aReason) {
2268 switch (aCode) {
2269 case MsgDropped:
2270 NS_WARNING("MsgDropped in ContentChild");
2271 return;
2273 case MsgNotKnown:
2274 case MsgNotAllowed:
2275 case MsgPayloadError:
2276 case MsgProcessingError:
2277 case MsgRouteError:
2278 case MsgValueError:
2279 break;
2281 default:
2282 MOZ_CRASH("not reached");
2285 CrashReporter::RecordAnnotationCString(
2286 CrashReporter::Annotation::ipc_channel_error, aReason);
2288 MOZ_CRASH("Content child abort due to IPC error");
2291 nsresult ContentChild::AddRemoteAlertObserver(const nsString& aData,
2292 nsIObserver* aObserver) {
2293 NS_ASSERTION(aObserver, "Adding a null observer?");
2294 mAlertObservers.AppendElement(new AlertObserver(aObserver, aData));
2295 return NS_OK;
2298 mozilla::ipc::IPCResult ContentChild::RecvPreferenceUpdate(const Pref& aPref) {
2299 Preferences::SetPreference(aPref);
2300 return IPC_OK();
2303 mozilla::ipc::IPCResult ContentChild::RecvVarUpdate(const GfxVarUpdate& aVar) {
2304 gfx::gfxVars::ApplyUpdate(aVar);
2305 return IPC_OK();
2308 mozilla::ipc::IPCResult ContentChild::RecvUpdatePerfStatsCollectionMask(
2309 const uint64_t& aMask) {
2310 PerfStats::SetCollectionMask(static_cast<PerfStats::MetricMask>(aMask));
2311 return IPC_OK();
2314 mozilla::ipc::IPCResult ContentChild::RecvCollectPerfStatsJSON(
2315 CollectPerfStatsJSONResolver&& aResolver) {
2316 aResolver(PerfStats::CollectLocalPerfStatsJSON());
2317 return IPC_OK();
2320 mozilla::ipc::IPCResult ContentChild::RecvCollectScrollingMetrics(
2321 CollectScrollingMetricsResolver&& aResolver) {
2322 auto metrics = ScrollingMetrics::CollectLocalScrollingMetrics();
2323 using ResolverArgs = std::tuple<const uint32_t&, const uint32_t&>;
2324 aResolver(ResolverArgs(std::get<0>(metrics), std::get<1>(metrics)));
2325 return IPC_OK();
2328 mozilla::ipc::IPCResult ContentChild::RecvNotifyAlertsObserver(
2329 const nsCString& aType, const nsString& aData) {
2330 nsTArray<nsCOMPtr<nsIObserver>> observersToNotify;
2332 mAlertObservers.RemoveElementsBy([&](UniquePtr<AlertObserver>& observer) {
2333 if (!observer->mData.Equals(aData)) {
2334 return false;
2337 // aType == alertfinished, this alert is done and we can remove the
2338 // observer.
2339 observersToNotify.AppendElement(observer->mObserver);
2340 return aType.EqualsLiteral("alertfinished");
2343 for (auto& observer : observersToNotify) {
2344 observer->Observe(nullptr, aType.get(), aData.get());
2347 return IPC_OK();
2350 mozilla::ipc::IPCResult ContentChild::RecvNotifyVisited(
2351 nsTArray<VisitedQueryResult>&& aURIs) {
2352 nsCOMPtr<IHistory> history = components::History::Service();
2353 if (!history) {
2354 return IPC_OK();
2356 for (const VisitedQueryResult& result : aURIs) {
2357 nsCOMPtr<nsIURI> newURI = result.uri();
2358 if (!newURI) {
2359 return IPC_FAIL_NO_REASON(this);
2361 auto status = result.visited() ? IHistory::VisitedStatus::Visited
2362 : IHistory::VisitedStatus::Unvisited;
2363 history->NotifyVisited(newURI, status);
2365 return IPC_OK();
2368 mozilla::ipc::IPCResult ContentChild::RecvThemeChanged(
2369 FullLookAndFeel&& aLookAndFeelData, widget::ThemeChangeKind aKind) {
2370 LookAndFeel::SetData(std::move(aLookAndFeelData));
2371 LookAndFeel::NotifyChangedAllWindows(aKind);
2372 return IPC_OK();
2375 mozilla::ipc::IPCResult ContentChild::RecvLoadProcessScript(
2376 const nsString& aURL) {
2377 auto* global = ContentProcessMessageManager::Get();
2378 if (global && global->LoadScript(aURL)) {
2379 return IPC_OK();
2381 return IPC_FAIL(this, "ContentProcessMessageManager::LoadScript failed");
2384 mozilla::ipc::IPCResult ContentChild::RecvAsyncMessage(
2385 const nsString& aMsg, const ClonedMessageData& aData) {
2386 AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("ContentChild::RecvAsyncMessage",
2387 OTHER, aMsg);
2388 MMPrinter::Print("ContentChild::RecvAsyncMessage", aMsg, aData);
2390 RefPtr<nsFrameMessageManager> cpm =
2391 nsFrameMessageManager::GetChildProcessManager();
2392 if (cpm) {
2393 StructuredCloneData data;
2394 ipc::UnpackClonedMessageData(aData, data);
2395 cpm->ReceiveMessage(cpm, nullptr, aMsg, false, &data, nullptr,
2396 IgnoreErrors());
2398 return IPC_OK();
2401 mozilla::ipc::IPCResult ContentChild::RecvRegisterStringBundles(
2402 nsTArray<mozilla::dom::StringBundleDescriptor>&& aDescriptors) {
2403 nsCOMPtr<nsIStringBundleService> stringBundleService =
2404 components::StringBundle::Service();
2406 for (auto& descriptor : aDescriptors) {
2407 stringBundleService->RegisterContentBundle(
2408 descriptor.bundleURL(), descriptor.mapFile(), descriptor.mapSize());
2411 return IPC_OK();
2414 mozilla::ipc::IPCResult ContentChild::RecvUpdateL10nFileSources(
2415 nsTArray<mozilla::dom::L10nFileSourceDescriptor>&& aDescriptors) {
2416 L10nRegistry::RegisterFileSourcesFromParentProcess(aDescriptors);
2417 return IPC_OK();
2420 mozilla::ipc::IPCResult ContentChild::RecvUpdateSharedData(
2421 const FileDescriptor& aMapFile, const uint32_t& aMapSize,
2422 nsTArray<IPCBlob>&& aBlobs, nsTArray<nsCString>&& aChangedKeys) {
2423 nsTArray<RefPtr<BlobImpl>> blobImpls(aBlobs.Length());
2424 for (auto& ipcBlob : aBlobs) {
2425 blobImpls.AppendElement(IPCBlobUtils::Deserialize(ipcBlob));
2428 if (mSharedData) {
2429 mSharedData->Update(aMapFile, aMapSize, std::move(blobImpls),
2430 std::move(aChangedKeys));
2431 } else {
2432 mSharedData =
2433 new SharedMap(ContentProcessMessageManager::Get()->GetParentObject(),
2434 aMapFile, aMapSize, std::move(blobImpls));
2437 return IPC_OK();
2440 mozilla::ipc::IPCResult ContentChild::RecvFontListChanged() {
2441 gfxPlatformFontList::PlatformFontList()->FontListChanged();
2443 return IPC_OK();
2446 mozilla::ipc::IPCResult ContentChild::RecvForceGlobalReflow(
2447 bool aNeedsReframe) {
2448 gfxPlatform::ForceGlobalReflow(aNeedsReframe ? gfxPlatform::NeedsReframe::Yes
2449 : gfxPlatform::NeedsReframe::No);
2451 return IPC_OK();
2454 mozilla::ipc::IPCResult ContentChild::RecvGeolocationUpdate(
2455 nsIDOMGeoPosition* aPosition) {
2456 RefPtr<nsGeolocationService> gs =
2457 nsGeolocationService::GetGeolocationService();
2458 if (!gs) {
2459 return IPC_OK();
2461 gs->Update(aPosition);
2462 return IPC_OK();
2465 mozilla::ipc::IPCResult ContentChild::RecvGeolocationError(
2466 const uint16_t& errorCode) {
2467 RefPtr<nsGeolocationService> gs =
2468 nsGeolocationService::GetGeolocationService();
2469 if (!gs) {
2470 return IPC_OK();
2472 gs->NotifyError(errorCode);
2473 return IPC_OK();
2476 mozilla::ipc::IPCResult ContentChild::RecvUpdateDictionaryList(
2477 nsTArray<nsCString>&& aDictionaries) {
2478 mAvailableDictionaries = std::move(aDictionaries);
2479 mozInlineSpellChecker::UpdateCanEnableInlineSpellChecking();
2480 return IPC_OK();
2483 mozilla::ipc::IPCResult ContentChild::RecvUpdateFontList(
2484 dom::SystemFontList&& aFontList) {
2485 mFontList = std::move(aFontList);
2486 if (gfxPlatform::Initialized()) {
2487 gfxPlatform::GetPlatform()->UpdateFontList(true);
2489 return IPC_OK();
2492 mozilla::ipc::IPCResult ContentChild::RecvRebuildFontList(
2493 const bool& aFullRebuild) {
2494 if (gfxPlatform::Initialized()) {
2495 gfxPlatform::GetPlatform()->UpdateFontList(aFullRebuild);
2497 return IPC_OK();
2500 mozilla::ipc::IPCResult ContentChild::RecvFontListShmBlockAdded(
2501 const uint32_t& aGeneration, const uint32_t& aIndex,
2502 base::SharedMemoryHandle&& aHandle) {
2503 if (gfxPlatform::Initialized()) {
2504 gfxPlatformFontList::PlatformFontList()->ShmBlockAdded(aGeneration, aIndex,
2505 std::move(aHandle));
2507 return IPC_OK();
2510 mozilla::ipc::IPCResult ContentChild::RecvUpdateAppLocales(
2511 nsTArray<nsCString>&& aAppLocales) {
2512 LocaleService::GetInstance()->AssignAppLocales(aAppLocales);
2513 return IPC_OK();
2516 mozilla::ipc::IPCResult ContentChild::RecvUpdateRequestedLocales(
2517 nsTArray<nsCString>&& aRequestedLocales) {
2518 LocaleService::GetInstance()->AssignRequestedLocales(aRequestedLocales);
2519 return IPC_OK();
2522 mozilla::ipc::IPCResult ContentChild::RecvSystemTimezoneChanged() {
2523 nsJSUtils::ResetTimeZone();
2524 return IPC_OK();
2527 mozilla::ipc::IPCResult ContentChild::RecvAddPermission(
2528 const IPC::Permission& permission) {
2529 nsCOMPtr<nsIPermissionManager> permissionManagerIface =
2530 components::PermissionManager::Service();
2531 PermissionManager* permissionManager =
2532 static_cast<PermissionManager*>(permissionManagerIface.get());
2533 MOZ_ASSERT(permissionManager,
2534 "We have no permissionManager in the Content process !");
2536 // note we do not need to force mUserContextId to the default here because
2537 // the permission manager does that internally.
2538 nsAutoCString originNoSuffix;
2539 OriginAttributes attrs;
2540 bool success = attrs.PopulateFromOrigin(permission.origin, originNoSuffix);
2541 NS_ENSURE_TRUE(success, IPC_FAIL_NO_REASON(this));
2543 nsCOMPtr<nsIURI> uri;
2544 nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
2545 NS_ENSURE_SUCCESS(rv, IPC_OK());
2547 nsCOMPtr<nsIPrincipal> principal =
2548 mozilla::BasePrincipal::CreateContentPrincipal(uri, attrs);
2550 // child processes don't care about modification time.
2551 int64_t modificationTime = 0;
2553 permissionManager->AddInternal(
2554 principal, nsCString(permission.type), permission.capability, 0,
2555 permission.expireType, permission.expireTime, modificationTime,
2556 PermissionManager::eNotify, PermissionManager::eNoDBOperation);
2558 return IPC_OK();
2561 mozilla::ipc::IPCResult ContentChild::RecvRemoveAllPermissions() {
2562 nsCOMPtr<nsIPermissionManager> permissionManagerIface =
2563 components::PermissionManager::Service();
2564 PermissionManager* permissionManager =
2565 static_cast<PermissionManager*>(permissionManagerIface.get());
2566 MOZ_ASSERT(permissionManager,
2567 "We have no permissionManager in the Content process !");
2569 permissionManager->RemoveAllFromIPC();
2570 return IPC_OK();
2573 mozilla::ipc::IPCResult ContentChild::RecvFlushMemory(const nsString& reason) {
2574 nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
2575 if (!mShuttingDown && os) {
2576 os->NotifyObservers(nullptr, "memory-pressure", reason.get());
2578 return IPC_OK();
2581 mozilla::ipc::IPCResult ContentChild::RecvActivateA11y() {
2582 #ifdef ACCESSIBILITY
2583 // Start accessibility in content process if it's running in chrome
2584 // process.
2585 GetOrCreateAccService(nsAccessibilityService::eMainProcess);
2586 #endif // ACCESSIBILITY
2587 return IPC_OK();
2590 mozilla::ipc::IPCResult ContentChild::RecvShutdownA11y() {
2591 #ifdef ACCESSIBILITY
2592 // Try to shutdown accessibility in content process if it's shutting down in
2593 // chrome process.
2594 MaybeShutdownAccService(nsAccessibilityService::eMainProcess);
2595 #endif
2596 return IPC_OK();
2599 mozilla::ipc::IPCResult ContentChild::RecvApplicationForeground() {
2600 // Rebroadcast the "application-foreground"
2601 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
2602 if (obs) {
2603 obs->NotifyObservers(nullptr, "application-foreground", nullptr);
2605 return IPC_OK();
2608 mozilla::ipc::IPCResult ContentChild::RecvApplicationBackground() {
2609 // Rebroadcast the "application-background"
2610 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
2611 if (obs) {
2612 obs->NotifyObservers(nullptr, "application-background", nullptr);
2614 return IPC_OK();
2617 mozilla::ipc::IPCResult ContentChild::RecvGarbageCollect() {
2618 // Rebroadcast the "child-gc-request" so that workers will GC.
2619 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
2620 if (obs) {
2621 obs->NotifyObservers(nullptr, "child-gc-request", nullptr);
2623 nsJSContext::GarbageCollectNow(JS::GCReason::DOM_IPC);
2624 return IPC_OK();
2627 mozilla::ipc::IPCResult ContentChild::RecvCycleCollect() {
2628 // Rebroadcast the "child-cc-request" so that workers will CC.
2629 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
2630 if (obs) {
2631 obs->NotifyObservers(nullptr, "child-cc-request", nullptr);
2633 nsJSContext::CycleCollectNow(CCReason::IPC_MESSAGE);
2634 return IPC_OK();
2637 mozilla::ipc::IPCResult ContentChild::RecvUnlinkGhosts() {
2638 #ifdef DEBUG
2639 nsWindowMemoryReporter::UnlinkGhostWindows();
2640 #endif
2641 return IPC_OK();
2644 mozilla::ipc::IPCResult ContentChild::RecvAppInfo(
2645 const nsCString& version, const nsCString& buildID, const nsCString& name,
2646 const nsCString& UAName, const nsCString& ID, const nsCString& vendor,
2647 const nsCString& sourceURL, const nsCString& updateURL) {
2648 mAppInfo.version.Assign(version);
2649 mAppInfo.buildID.Assign(buildID);
2650 mAppInfo.name.Assign(name);
2651 mAppInfo.UAName.Assign(UAName);
2652 mAppInfo.ID.Assign(ID);
2653 mAppInfo.vendor.Assign(vendor);
2654 mAppInfo.sourceURL.Assign(sourceURL);
2655 mAppInfo.updateURL.Assign(updateURL);
2657 return IPC_OK();
2660 mozilla::ipc::IPCResult ContentChild::RecvRemoteType(
2661 const nsCString& aRemoteType, const nsCString& aProfile) {
2662 if (aRemoteType == mRemoteType) {
2663 // Allocation of preallocated processes that are still launching can
2664 // cause this
2665 return IPC_OK();
2668 if (!mRemoteType.IsVoid()) {
2669 // Preallocated processes are type PREALLOC_REMOTE_TYPE; they may not
2670 // become a File: process, or Privileged About Content Process
2671 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
2672 ("Changing remoteType of process %d from %s to %s", getpid(),
2673 mRemoteType.get(), aRemoteType.get()));
2674 // prealloc->anything (but file) or web->web allowed, and no-change
2675 MOZ_RELEASE_ASSERT(mRemoteType == PREALLOC_REMOTE_TYPE &&
2676 aRemoteType != FILE_REMOTE_TYPE &&
2677 aRemoteType != PRIVILEGEDABOUT_REMOTE_TYPE);
2678 } else {
2679 // Initial setting of remote type. Either to 'prealloc' or the actual
2680 // final type (if we didn't use a preallocated process)
2681 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
2682 ("Setting remoteType of process %d to %s", getpid(),
2683 aRemoteType.get()));
2685 if (aRemoteType == PREALLOC_REMOTE_TYPE) {
2686 PreallocInit();
2690 auto remoteTypePrefix = RemoteTypePrefix(aRemoteType);
2692 // Must do before SetProcessName
2693 mRemoteType.Assign(aRemoteType);
2695 // Update the process name so about:memory's process names are more obvious.
2696 if (aRemoteType == FILE_REMOTE_TYPE) {
2697 SetProcessName("file:// Content"_ns, nullptr, &aProfile);
2698 } else if (aRemoteType == EXTENSION_REMOTE_TYPE) {
2699 SetProcessName("WebExtensions"_ns, nullptr, &aProfile);
2700 } else if (aRemoteType == PRIVILEGEDABOUT_REMOTE_TYPE) {
2701 SetProcessName("Privileged Content"_ns, nullptr, &aProfile);
2702 } else if (aRemoteType == PRIVILEGEDMOZILLA_REMOTE_TYPE) {
2703 SetProcessName("Privileged Mozilla"_ns, nullptr, &aProfile);
2704 } else if (aRemoteType == INFERENCE_REMOTE_TYPE) {
2705 SetProcessName("Inference"_ns, nullptr, &aProfile);
2706 } else if (remoteTypePrefix == WITH_COOP_COEP_REMOTE_TYPE) {
2707 // The profiler can sanitize out the eTLD+1
2708 nsDependentCSubstring etld =
2709 Substring(aRemoteType, WITH_COOP_COEP_REMOTE_TYPE.Length() + 1);
2710 #ifdef NIGHTLY_BUILD
2711 SetProcessName("WebCOOP+COEP Content"_ns, &etld, &aProfile);
2712 #else
2713 SetProcessName("Isolated Web Content"_ns, &etld,
2714 &aProfile); // to avoid confusing people
2715 #endif
2716 } else if (remoteTypePrefix == FISSION_WEB_REMOTE_TYPE) {
2717 // The profiler can sanitize out the eTLD+1
2718 nsDependentCSubstring etld =
2719 Substring(aRemoteType, FISSION_WEB_REMOTE_TYPE.Length() + 1);
2720 SetProcessName("Isolated Web Content"_ns, &etld, &aProfile);
2721 } else if (remoteTypePrefix == SERVICEWORKER_REMOTE_TYPE) {
2722 // The profiler can sanitize out the eTLD+1
2723 nsDependentCSubstring etld =
2724 Substring(aRemoteType, SERVICEWORKER_REMOTE_TYPE.Length() + 1);
2725 SetProcessName("Isolated Service Worker"_ns, &etld, &aProfile);
2726 } else {
2727 // else "prealloc" or "web" type -> "Web Content"
2728 SetProcessName("Web Content"_ns, nullptr, &aProfile);
2731 // Turn off Spectre mitigations in isolated web content processes.
2732 if (StaticPrefs::javascript_options_spectre_disable_for_isolated_content() &&
2733 StaticPrefs::browser_opaqueResponseBlocking() &&
2734 (remoteTypePrefix == FISSION_WEB_REMOTE_TYPE ||
2735 remoteTypePrefix == SERVICEWORKER_REMOTE_TYPE ||
2736 remoteTypePrefix == WITH_COOP_COEP_REMOTE_TYPE ||
2737 aRemoteType == PRIVILEGEDABOUT_REMOTE_TYPE ||
2738 aRemoteType == PRIVILEGEDMOZILLA_REMOTE_TYPE)) {
2739 JS::DisableSpectreMitigationsAfterInit();
2742 // Use the prefix to avoid URIs from Fission isolated processes.
2743 CrashReporter::RecordAnnotationNSCString(
2744 CrashReporter::Annotation::RemoteType, remoteTypePrefix);
2746 return IPC_OK();
2749 // A method to initialize anything we need during the preallocation phase
2750 void ContentChild::PreallocInit() {
2751 EnsureNSSInitializedChromeOrContent();
2753 // SetAcceptLanguages() needs to read localized strings (file access),
2754 // which is slow, so do this in prealloc
2755 nsHttpHandler::PresetAcceptLanguages();
2758 // Call RemoteTypePrefix() on the result to remove URIs if you want to use this
2759 // for telemetry.
2760 const nsACString& ContentChild::GetRemoteType() const { return mRemoteType; }
2762 mozilla::ipc::IPCResult ContentChild::RecvInitRemoteWorkerService(
2763 Endpoint<PRemoteWorkerServiceChild>&& aEndpoint) {
2764 RemoteWorkerService::InitializeChild(std::move(aEndpoint));
2765 return IPC_OK();
2768 mozilla::ipc::IPCResult ContentChild::RecvInitBlobURLs(
2769 nsTArray<BlobURLRegistrationData>&& aRegistrations) {
2770 for (uint32_t i = 0; i < aRegistrations.Length(); ++i) {
2771 BlobURLRegistrationData& registration = aRegistrations[i];
2772 RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(registration.blob());
2773 MOZ_ASSERT(blobImpl);
2775 BlobURLProtocolHandler::AddDataEntry(registration.url(),
2776 registration.principal(),
2777 registration.partitionKey(), blobImpl);
2778 // If we have received an already-revoked blobURL, we have to keep it alive
2779 // for a while (see BlobURLProtocolHandler) in order to support pending
2780 // operations such as navigation, download and so on.
2781 if (registration.revoked()) {
2782 BlobURLProtocolHandler::RemoveDataEntry(registration.url(), false);
2786 return IPC_OK();
2789 mozilla::ipc::IPCResult ContentChild::RecvInitJSActorInfos(
2790 nsTArray<JSProcessActorInfo>&& aContentInfos,
2791 nsTArray<JSWindowActorInfo>&& aWindowInfos) {
2792 RefPtr<JSActorService> actSvc = JSActorService::GetSingleton();
2793 actSvc->LoadJSActorInfos(aContentInfos, aWindowInfos);
2794 return IPC_OK();
2797 mozilla::ipc::IPCResult ContentChild::RecvUnregisterJSWindowActor(
2798 const nsCString& aName) {
2799 RefPtr<JSActorService> actSvc = JSActorService::GetSingleton();
2800 actSvc->UnregisterWindowActor(aName);
2801 return IPC_OK();
2804 mozilla::ipc::IPCResult ContentChild::RecvUnregisterJSProcessActor(
2805 const nsCString& aName) {
2806 RefPtr<JSActorService> actSvc = JSActorService::GetSingleton();
2807 actSvc->UnregisterProcessActor(aName);
2808 return IPC_OK();
2811 mozilla::ipc::IPCResult ContentChild::RecvLastPrivateDocShellDestroyed() {
2812 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
2813 obs->NotifyObservers(nullptr, "last-pb-context-exited", nullptr);
2814 return IPC_OK();
2817 mozilla::ipc::IPCResult ContentChild::RecvNotifyProcessPriorityChanged(
2818 const hal::ProcessPriority& aPriority) {
2819 nsCOMPtr<nsIObserverService> os = services::GetObserverService();
2820 NS_ENSURE_TRUE(os, IPC_OK());
2822 RefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
2823 props->SetPropertyAsInt32(u"priority"_ns, static_cast<int32_t>(aPriority));
2825 PROFILER_MARKER("Process Priority", OTHER,
2826 mozilla::MarkerThreadId::MainThread(), ProcessPriorityChange,
2827 ProfilerString8View::WrapNullTerminatedString(
2828 ProcessPriorityToString(mProcessPriority)),
2829 ProfilerString8View::WrapNullTerminatedString(
2830 ProcessPriorityToString(aPriority)));
2832 // Record FOG data before the priority change.
2833 // Ignore the change if it's the first time we set the process priority.
2834 if (mProcessPriority != hal::PROCESS_PRIORITY_UNKNOWN) {
2835 glean::RecordPowerMetrics();
2838 ConfigureThreadPerformanceHints(aPriority);
2840 mProcessPriority = aPriority;
2842 os->NotifyObservers(static_cast<nsIPropertyBag2*>(props),
2843 "ipc:process-priority-changed", nullptr);
2844 if (StaticPrefs::
2845 dom_memory_foreground_content_processes_have_larger_page_cache()) {
2846 if (mProcessPriority >= hal::PROCESS_PRIORITY_FOREGROUND) {
2847 // Note: keep this in sync with the JS shell (js/src/shell/js.cpp).
2848 moz_set_max_dirty_page_modifier(4);
2849 } else if (mProcessPriority == hal::PROCESS_PRIORITY_BACKGROUND) {
2850 moz_set_max_dirty_page_modifier(-2);
2852 #if defined(MOZ_MEMORY)
2853 if (StaticPrefs::dom_memory_memory_pressure_on_background() == 1) {
2854 jemalloc_free_dirty_pages();
2856 #endif
2857 if (StaticPrefs::dom_memory_memory_pressure_on_background() == 2) {
2858 nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService();
2859 obsServ->NotifyObservers(nullptr, "memory-pressure", u"heap-minimize");
2860 } else if (StaticPrefs::dom_memory_memory_pressure_on_background() == 3) {
2861 nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService();
2862 obsServ->NotifyObservers(nullptr, "memory-pressure", u"low-memory");
2865 } else {
2866 moz_set_max_dirty_page_modifier(0);
2870 return IPC_OK();
2873 mozilla::ipc::IPCResult ContentChild::RecvMinimizeMemoryUsage() {
2874 nsCOMPtr<nsIMemoryReporterManager> mgr =
2875 do_GetService("@mozilla.org/memory-reporter-manager;1");
2876 NS_ENSURE_TRUE(mgr, IPC_OK());
2878 Unused << mgr->MinimizeMemoryUsage(/* callback = */ nullptr);
2879 return IPC_OK();
2882 void ContentChild::AddIdleObserver(nsIObserver* aObserver,
2883 uint32_t aIdleTimeInS) {
2884 MOZ_ASSERT(aObserver, "null idle observer");
2885 // Make sure aObserver isn't released while we wait for the parent
2886 aObserver->AddRef();
2887 SendAddIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS);
2888 mIdleObservers.Insert(aObserver);
2891 void ContentChild::RemoveIdleObserver(nsIObserver* aObserver,
2892 uint32_t aIdleTimeInS) {
2893 MOZ_ASSERT(aObserver, "null idle observer");
2894 SendRemoveIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS);
2895 aObserver->Release();
2896 mIdleObservers.Remove(aObserver);
2899 mozilla::ipc::IPCResult ContentChild::RecvNotifyIdleObserver(
2900 const uint64_t& aObserver, const nsCString& aTopic,
2901 const nsString& aTimeStr) {
2902 nsIObserver* observer = reinterpret_cast<nsIObserver*>(aObserver);
2903 if (mIdleObservers.Contains(observer)) {
2904 observer->Observe(nullptr, aTopic.get(), aTimeStr.get());
2905 } else {
2906 NS_WARNING("Received notification for an idle observer that was removed.");
2908 return IPC_OK();
2911 mozilla::ipc::IPCResult ContentChild::RecvLoadAndRegisterSheet(
2912 nsIURI* aURI, const uint32_t& aType) {
2913 if (!aURI) {
2914 return IPC_OK();
2917 nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance();
2918 if (sheetService) {
2919 sheetService->LoadAndRegisterSheet(aURI, aType);
2922 return IPC_OK();
2925 mozilla::ipc::IPCResult ContentChild::RecvUnregisterSheet(
2926 nsIURI* aURI, const uint32_t& aType) {
2927 if (!aURI) {
2928 return IPC_OK();
2931 nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance();
2932 if (sheetService) {
2933 sheetService->UnregisterSheet(aURI, aType);
2936 return IPC_OK();
2939 mozilla::ipc::IPCResult ContentChild::RecvDomainSetChanged(
2940 const uint32_t& aSetType, const uint32_t& aChangeType, nsIURI* aDomain) {
2941 if (aChangeType == ACTIVATE_POLICY) {
2942 if (mPolicy) {
2943 return IPC_OK();
2945 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
2946 MOZ_ASSERT(ssm);
2947 ssm->ActivateDomainPolicyInternal(getter_AddRefs(mPolicy));
2948 if (!mPolicy) {
2949 return IPC_FAIL_NO_REASON(this);
2951 return IPC_OK();
2953 if (!mPolicy) {
2954 MOZ_ASSERT_UNREACHABLE(
2955 "If the domain policy is not active yet,"
2956 " the first message should be ACTIVATE_POLICY");
2957 return IPC_FAIL_NO_REASON(this);
2960 NS_ENSURE_TRUE(mPolicy, IPC_FAIL_NO_REASON(this));
2962 if (aChangeType == DEACTIVATE_POLICY) {
2963 mPolicy->Deactivate();
2964 mPolicy = nullptr;
2965 return IPC_OK();
2968 nsCOMPtr<nsIDomainSet> set;
2969 switch (aSetType) {
2970 case BLOCKLIST:
2971 mPolicy->GetBlocklist(getter_AddRefs(set));
2972 break;
2973 case SUPER_BLOCKLIST:
2974 mPolicy->GetSuperBlocklist(getter_AddRefs(set));
2975 break;
2976 case ALLOWLIST:
2977 mPolicy->GetAllowlist(getter_AddRefs(set));
2978 break;
2979 case SUPER_ALLOWLIST:
2980 mPolicy->GetSuperAllowlist(getter_AddRefs(set));
2981 break;
2982 default:
2983 MOZ_ASSERT_UNREACHABLE("Unexpected setType");
2984 return IPC_FAIL_NO_REASON(this);
2987 MOZ_ASSERT(set);
2989 switch (aChangeType) {
2990 case ADD_DOMAIN:
2991 NS_ENSURE_TRUE(aDomain, IPC_FAIL_NO_REASON(this));
2992 set->Add(aDomain);
2993 break;
2994 case REMOVE_DOMAIN:
2995 NS_ENSURE_TRUE(aDomain, IPC_FAIL_NO_REASON(this));
2996 set->Remove(aDomain);
2997 break;
2998 case CLEAR_DOMAINS:
2999 set->Clear();
3000 break;
3001 default:
3002 MOZ_ASSERT_UNREACHABLE("Unexpected changeType");
3003 return IPC_FAIL_NO_REASON(this);
3006 return IPC_OK();
3009 void ContentChild::StartForceKillTimer() {
3010 if (mForceKillTimer) {
3011 return;
3014 int32_t timeoutSecs = StaticPrefs::dom_ipc_tabs_shutdownTimeoutSecs();
3015 if (timeoutSecs > 0) {
3016 NS_NewTimerWithFuncCallback(getter_AddRefs(mForceKillTimer),
3017 ContentChild::ForceKillTimerCallback, this,
3018 timeoutSecs * 1000, nsITimer::TYPE_ONE_SHOT,
3019 "dom::ContentChild::StartForceKillTimer");
3020 MOZ_ASSERT(mForceKillTimer);
3024 /* static */
3025 void ContentChild::ForceKillTimerCallback(nsITimer* aTimer, void* aClosure) {
3026 ProcessChild::QuickExit();
3029 mozilla::ipc::IPCResult ContentChild::RecvShutdownConfirmedHP() {
3030 ProcessChild::AppendToIPCShutdownStateAnnotation(
3031 "RecvShutdownConfirmedHP entry"_ns);
3033 // Bug 1755376: If we see "RecvShutdownConfirmedHP entry" often in
3034 // bug IPCError_ShutDownKill we might want to anticipate
3035 // ShutdownPhase::AppShutdownConfirmed to start here.
3037 return IPC_OK();
3040 mozilla::ipc::IPCResult ContentChild::RecvShutdown() {
3041 ProcessChild::AppendToIPCShutdownStateAnnotation("RecvShutdown entry"_ns);
3043 // Signal the ongoing shutdown to AppShutdown, this
3044 // will make abort nested SpinEventLoopUntilOrQuit loops
3045 AppShutdown::AdvanceShutdownPhaseWithoutNotify(
3046 ShutdownPhase::AppShutdownConfirmed);
3048 nsCOMPtr<nsIObserverService> os = services::GetObserverService();
3049 if (os) {
3050 ProcessChild::AppendToIPCShutdownStateAnnotation(
3051 "content-child-will-shutdown started"_ns);
3053 os->NotifyObservers(ToSupports(this), "content-child-will-shutdown",
3054 nullptr);
3057 ShutdownInternal();
3058 return IPC_OK();
3061 void ContentChild::ShutdownInternal() {
3062 ProcessChild::AppendToIPCShutdownStateAnnotation("ShutdownInternal entry"_ns);
3064 // If we receive the shutdown message from within a nested event loop, we want
3065 // to wait for that event loop to finish. Otherwise we could prematurely
3066 // terminate an "unload" or "pagehide" event handler (which might be doing a
3067 // sync XHR, for example).
3069 MOZ_ASSERT(NS_IsMainThread());
3070 RefPtr<nsThread> mainThread = nsThreadManager::get().GetCurrentThread();
3071 // Note that we only have to check the recursion count for the current
3072 // cooperative thread. Since the Shutdown message is not labeled with a
3073 // SchedulerGroup, there can be no other cooperative threads doing work while
3074 // we're running.
3075 if (mainThread && mainThread->RecursionDepth() > 1) {
3076 // We're in a nested event loop. Let's delay for an arbitrary period of
3077 // time (100ms) in the hopes that the event loop will have finished by
3078 // then.
3079 GetCurrentSerialEventTarget()->DelayedDispatch(
3080 NewRunnableMethod("dom::ContentChild::RecvShutdown", this,
3081 &ContentChild::ShutdownInternal),
3082 100);
3083 return;
3086 mShuttingDown = true;
3088 #ifdef NIGHTLY_BUILD
3089 BackgroundHangMonitor::UnregisterAnnotator(
3090 PendingInputEventHangAnnotator::sSingleton);
3091 #endif
3093 if (mPolicy) {
3094 mPolicy->Deactivate();
3095 mPolicy = nullptr;
3098 nsCOMPtr<nsIObserverService> os = services::GetObserverService();
3099 if (os) {
3100 ProcessChild::AppendToIPCShutdownStateAnnotation(
3101 "content-child-shutdown started"_ns);
3102 os->NotifyObservers(ToSupports(this), "content-child-shutdown", nullptr);
3105 GetIPCChannel()->SetAbortOnError(false);
3107 if (mProfilerController) {
3108 const bool isProfiling = profiler_is_active();
3109 CrashReporter::RecordAnnotationCString(
3110 CrashReporter::Annotation::ProfilerChildShutdownPhase,
3111 isProfiling ? "Profiling - GrabShutdownProfileAndShutdown"
3112 : "Not profiling - GrabShutdownProfileAndShutdown");
3113 ProfileAndAdditionalInformation shutdownProfileAndAdditionalInformation =
3114 mProfilerController->GrabShutdownProfileAndShutdown();
3115 CrashReporter::RecordAnnotationCString(
3116 CrashReporter::Annotation::ProfilerChildShutdownPhase,
3117 isProfiling ? "Profiling - Destroying ChildProfilerController"
3118 : "Not profiling - Destroying ChildProfilerController");
3119 mProfilerController = nullptr;
3120 CrashReporter::RecordAnnotationCString(
3121 CrashReporter::Annotation::ProfilerChildShutdownPhase,
3122 isProfiling ? "Profiling - SendShutdownProfile (sending)"
3123 : "Not profiling - SendShutdownProfile (sending)");
3124 if (const size_t len = shutdownProfileAndAdditionalInformation.SizeOf();
3125 len >= size_t(IPC::Channel::kMaximumMessageSize)) {
3126 shutdownProfileAndAdditionalInformation.mProfile = nsPrintfCString(
3127 "*Profile from pid %u bigger (%zu) than IPC max (%zu)",
3128 unsigned(profiler_current_process_id().ToNumber()), len,
3129 size_t(IPC::Channel::kMaximumMessageSize));
3131 // Send the shutdown profile to the parent process through our own
3132 // message channel, which we know will survive for long enough.
3133 bool sent =
3134 SendShutdownProfile(shutdownProfileAndAdditionalInformation.mProfile);
3135 CrashReporter::RecordAnnotationCString(
3136 CrashReporter::Annotation::ProfilerChildShutdownPhase,
3137 sent ? (isProfiling ? "Profiling - SendShutdownProfile (sent)"
3138 : "Not profiling - SendShutdownProfile (sent)")
3139 : (isProfiling ? "Profiling - SendShutdownProfile (failed)"
3140 : "Not profiling - SendShutdownProfile (failed)"));
3143 if (PerfStats::GetCollectionMask() != 0) {
3144 SendShutdownPerfStats(PerfStats::CollectLocalPerfStatsJSON());
3147 // Start a timer that will ensure we quickly exit after a reasonable period
3148 // of time. Prevents shutdown hangs after our connection to the parent
3149 // closes or when the parent is too busy to ever kill us.
3150 ProcessChild::AppendToIPCShutdownStateAnnotation("StartForceKillTimer"_ns);
3151 StartForceKillTimer();
3153 ProcessChild::AppendToIPCShutdownStateAnnotation(
3154 "SendFinishShutdown (sending)"_ns);
3156 // Notify the parent that we are done with shutdown. This is sent with high
3157 // priority and will just flag we are done.
3158 Unused << SendNotifyShutdownSuccess();
3160 // Now tell the parent to actually destroy our channel which will make end
3161 // our process. This is expected to be the last event the parent will
3162 // ever process for this ContentChild.
3163 bool sent = SendFinishShutdown();
3165 ProcessChild::AppendToIPCShutdownStateAnnotation(
3166 sent ? "SendFinishShutdown (sent)"_ns : "SendFinishShutdown (failed)"_ns);
3169 mozilla::ipc::IPCResult ContentChild::RecvUpdateWindow(
3170 const uintptr_t& aChildId) {
3171 MOZ_ASSERT(
3172 false,
3173 "ContentChild::RecvUpdateWindow calls unexpected on this platform.");
3174 return IPC_FAIL_NO_REASON(this);
3177 PContentPermissionRequestChild*
3178 ContentChild::AllocPContentPermissionRequestChild(
3179 Span<const PermissionRequest> aRequests, nsIPrincipal* aPrincipal,
3180 nsIPrincipal* aTopLevelPrincipal, const bool& aIsHandlingUserInput,
3181 const bool& aMaybeUnsafePermissionDelegate, const TabId& aTabId) {
3182 MOZ_CRASH("unused");
3183 return nullptr;
3186 bool ContentChild::DeallocPContentPermissionRequestChild(
3187 PContentPermissionRequestChild* actor) {
3188 nsContentPermissionUtils::NotifyRemoveContentPermissionRequestChild(actor);
3189 auto child = static_cast<RemotePermissionRequest*>(actor);
3190 child->IPDLRelease();
3191 return true;
3194 already_AddRefed<PWebBrowserPersistDocumentChild>
3195 ContentChild::AllocPWebBrowserPersistDocumentChild(
3196 PBrowserChild* aBrowser, const MaybeDiscarded<BrowsingContext>& aContext) {
3197 return MakeAndAddRef<WebBrowserPersistDocumentChild>();
3200 mozilla::ipc::IPCResult ContentChild::RecvPWebBrowserPersistDocumentConstructor(
3201 PWebBrowserPersistDocumentChild* aActor, PBrowserChild* aBrowser,
3202 const MaybeDiscarded<BrowsingContext>& aContext) {
3203 if (NS_WARN_IF(!aBrowser)) {
3204 return IPC_FAIL_NO_REASON(this);
3207 if (aContext.IsNullOrDiscarded()) {
3208 aActor->SendInitFailure(NS_ERROR_NO_CONTENT);
3209 return IPC_OK();
3212 nsCOMPtr<Document> foundDoc = aContext.get()->GetDocument();
3214 if (!foundDoc) {
3215 aActor->SendInitFailure(NS_ERROR_NO_CONTENT);
3216 } else {
3217 static_cast<WebBrowserPersistDocumentChild*>(aActor)->Start(foundDoc);
3219 return IPC_OK();
3222 mozilla::ipc::IPCResult ContentChild::RecvPush(const nsCString& aScope,
3223 nsIPrincipal* aPrincipal,
3224 const nsString& aMessageId) {
3225 PushMessageDispatcher dispatcher(aScope, aPrincipal, aMessageId, Nothing());
3226 Unused << NS_WARN_IF(NS_FAILED(dispatcher.NotifyObserversAndWorkers()));
3227 return IPC_OK();
3230 mozilla::ipc::IPCResult ContentChild::RecvPushWithData(
3231 const nsCString& aScope, nsIPrincipal* aPrincipal,
3232 const nsString& aMessageId, nsTArray<uint8_t>&& aData) {
3233 PushMessageDispatcher dispatcher(aScope, aPrincipal, aMessageId,
3234 Some(std::move(aData)));
3235 Unused << NS_WARN_IF(NS_FAILED(dispatcher.NotifyObserversAndWorkers()));
3236 return IPC_OK();
3239 mozilla::ipc::IPCResult ContentChild::RecvPushSubscriptionChange(
3240 const nsCString& aScope, nsIPrincipal* aPrincipal) {
3241 PushSubscriptionChangeDispatcher dispatcher(aScope, aPrincipal);
3242 Unused << NS_WARN_IF(NS_FAILED(dispatcher.NotifyObserversAndWorkers()));
3243 return IPC_OK();
3246 mozilla::ipc::IPCResult ContentChild::RecvPushError(const nsCString& aScope,
3247 nsIPrincipal* aPrincipal,
3248 const nsString& aMessage,
3249 const uint32_t& aFlags) {
3250 PushErrorDispatcher dispatcher(aScope, aPrincipal, aMessage, aFlags);
3251 Unused << NS_WARN_IF(NS_FAILED(dispatcher.NotifyObserversAndWorkers()));
3252 return IPC_OK();
3255 mozilla::ipc::IPCResult
3256 ContentChild::RecvNotifyPushSubscriptionModifiedObservers(
3257 const nsCString& aScope, nsIPrincipal* aPrincipal) {
3258 PushSubscriptionModifiedDispatcher dispatcher(aScope, aPrincipal);
3259 Unused << NS_WARN_IF(NS_FAILED(dispatcher.NotifyObservers()));
3260 return IPC_OK();
3263 mozilla::ipc::IPCResult ContentChild::RecvBlobURLRegistration(
3264 const nsCString& aURI, const IPCBlob& aBlob, nsIPrincipal* aPrincipal,
3265 const nsCString& aPartitionKey) {
3266 RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(aBlob);
3267 MOZ_ASSERT(blobImpl);
3269 BlobURLProtocolHandler::AddDataEntry(aURI, aPrincipal, aPartitionKey,
3270 blobImpl);
3271 return IPC_OK();
3274 mozilla::ipc::IPCResult ContentChild::RecvBlobURLUnregistration(
3275 const nsCString& aURI) {
3276 BlobURLProtocolHandler::RemoveDataEntry(
3277 aURI,
3278 /* aBroadcastToOtherProcesses = */ false);
3279 return IPC_OK();
3282 void ContentChild::CreateGetFilesRequest(const nsAString& aDirectoryPath,
3283 bool aRecursiveFlag, nsID& aUUID,
3284 GetFilesHelperChild* aChild) {
3285 MOZ_ASSERT(aChild);
3286 MOZ_ASSERT(!mGetFilesPendingRequests.Contains(aUUID));
3288 Unused << SendGetFilesRequest(aUUID, aDirectoryPath, aRecursiveFlag);
3289 mGetFilesPendingRequests.InsertOrUpdate(aUUID, RefPtr{aChild});
3292 void ContentChild::DeleteGetFilesRequest(nsID& aUUID,
3293 GetFilesHelperChild* aChild) {
3294 MOZ_ASSERT(aChild);
3295 MOZ_ASSERT(mGetFilesPendingRequests.Contains(aUUID));
3297 Unused << SendDeleteGetFilesRequest(aUUID);
3298 mGetFilesPendingRequests.Remove(aUUID);
3301 mozilla::ipc::IPCResult ContentChild::RecvGetFilesResponse(
3302 const nsID& aUUID, const GetFilesResponseResult& aResult) {
3303 RefPtr<GetFilesHelperChild> child;
3305 // This object can already been deleted in case DeleteGetFilesRequest has
3306 // been called when the response was sending by the parent.
3307 if (!mGetFilesPendingRequests.Remove(aUUID, getter_AddRefs(child))) {
3308 return IPC_OK();
3311 if (aResult.type() == GetFilesResponseResult::TGetFilesResponseFailure) {
3312 child->Finished(aResult.get_GetFilesResponseFailure().errorCode());
3313 } else {
3314 MOZ_ASSERT(aResult.type() ==
3315 GetFilesResponseResult::TGetFilesResponseSuccess);
3317 const nsTArray<IPCBlob>& ipcBlobs =
3318 aResult.get_GetFilesResponseSuccess().blobs();
3320 bool succeeded = true;
3321 for (uint32_t i = 0; succeeded && i < ipcBlobs.Length(); ++i) {
3322 RefPtr<BlobImpl> impl = IPCBlobUtils::Deserialize(ipcBlobs[i]);
3323 succeeded = child->AppendBlobImpl(impl);
3326 child->Finished(succeeded ? NS_OK : NS_ERROR_OUT_OF_MEMORY);
3328 return IPC_OK();
3331 /* static */
3332 void ContentChild::FatalErrorIfNotUsingGPUProcess(const char* const aErrorMsg,
3333 base::ProcessId aOtherPid) {
3334 // If we're communicating with the same process or the UI process then we
3335 // want to crash normally. Otherwise we want to just warn as the other end
3336 // must be the GPU process and it crashing shouldn't be fatal for us.
3337 if (aOtherPid == base::GetCurrentProcId() ||
3338 (GetSingleton() && GetSingleton()->OtherPid() == aOtherPid)) {
3339 mozilla::ipc::FatalError(aErrorMsg, false);
3340 } else {
3341 nsAutoCString formattedMessage("IPDL error: \"");
3342 formattedMessage.AppendASCII(aErrorMsg);
3343 formattedMessage.AppendLiteral(R"(".)");
3344 NS_WARNING(formattedMessage.get());
3348 PURLClassifierChild* ContentChild::AllocPURLClassifierChild(
3349 nsIPrincipal* aPrincipal, bool* aSuccess) {
3350 *aSuccess = true;
3351 return new URLClassifierChild();
3354 bool ContentChild::DeallocPURLClassifierChild(PURLClassifierChild* aActor) {
3355 MOZ_ASSERT(aActor);
3356 delete aActor;
3357 return true;
3360 PURLClassifierLocalChild* ContentChild::AllocPURLClassifierLocalChild(
3361 nsIURI* aUri, Span<const IPCURLClassifierFeature> aFeatures) {
3362 return new URLClassifierLocalChild();
3365 bool ContentChild::DeallocPURLClassifierLocalChild(
3366 PURLClassifierLocalChild* aActor) {
3367 MOZ_ASSERT(aActor);
3368 delete aActor;
3369 return true;
3372 PSessionStorageObserverChild*
3373 ContentChild::AllocPSessionStorageObserverChild() {
3374 MOZ_CRASH(
3375 "PSessionStorageObserverChild actors should be manually constructed!");
3378 bool ContentChild::DeallocPSessionStorageObserverChild(
3379 PSessionStorageObserverChild* aActor) {
3380 MOZ_ASSERT(aActor);
3382 delete aActor;
3383 return true;
3386 mozilla::ipc::IPCResult ContentChild::RecvProvideAnonymousTemporaryFile(
3387 const uint64_t& aID, const FileDescOrError& aFDOrError) {
3388 mozilla::UniquePtr<AnonymousTemporaryFileCallback> callback;
3389 mPendingAnonymousTemporaryFiles.Remove(aID, &callback);
3390 MOZ_ASSERT(callback);
3392 PRFileDesc* prfile = nullptr;
3393 if (aFDOrError.type() == FileDescOrError::Tnsresult) {
3394 DebugOnly<nsresult> rv = aFDOrError.get_nsresult();
3395 MOZ_ASSERT(NS_FAILED(rv));
3396 } else {
3397 auto rawFD = aFDOrError.get_FileDescriptor().ClonePlatformHandle();
3398 prfile = PR_ImportFile(PROsfd(rawFD.release()));
3400 (*callback)(prfile);
3401 return IPC_OK();
3404 nsresult ContentChild::AsyncOpenAnonymousTemporaryFile(
3405 const AnonymousTemporaryFileCallback& aCallback) {
3406 MOZ_ASSERT(NS_IsMainThread());
3408 static uint64_t id = 0;
3409 auto newID = id++;
3410 if (!SendRequestAnonymousTemporaryFile(newID)) {
3411 return NS_ERROR_FAILURE;
3414 // Remember the association with the callback.
3415 MOZ_ASSERT(!mPendingAnonymousTemporaryFiles.Get(newID));
3416 mPendingAnonymousTemporaryFiles.GetOrInsertNew(newID, aCallback);
3417 return NS_OK;
3420 mozilla::ipc::IPCResult ContentChild::RecvSetPermissionsWithKey(
3421 const nsCString& aPermissionKey, nsTArray<IPC::Permission>&& aPerms) {
3422 RefPtr<PermissionManager> permManager = PermissionManager::GetInstance();
3423 if (permManager) {
3424 permManager->SetPermissionsWithKey(aPermissionKey, aPerms);
3427 return IPC_OK();
3430 mozilla::ipc::IPCResult ContentChild::RecvRefreshScreens(
3431 nsTArray<ScreenDetails>&& aScreens) {
3432 ScreenManager& screenManager = ScreenManager::GetSingleton();
3433 screenManager.Refresh(std::move(aScreens));
3434 return IPC_OK();
3437 mozilla::ipc::IPCResult ContentChild::RecvShareCodeCoverageMutex(
3438 CrossProcessMutexHandle aHandle) {
3439 #ifdef MOZ_CODE_COVERAGE
3440 CodeCoverageHandler::Init(std::move(aHandle));
3441 return IPC_OK();
3442 #else
3443 MOZ_CRASH("Shouldn't receive this message in non-code coverage builds!");
3444 #endif
3447 mozilla::ipc::IPCResult ContentChild::RecvFlushCodeCoverageCounters(
3448 FlushCodeCoverageCountersResolver&& aResolver) {
3449 #ifdef MOZ_CODE_COVERAGE
3450 CodeCoverageHandler::FlushCounters();
3451 aResolver(/* unused */ true);
3452 return IPC_OK();
3453 #else
3454 MOZ_CRASH("Shouldn't receive this message in non-code coverage builds!");
3455 #endif
3458 mozilla::ipc::IPCResult ContentChild::RecvSetInputEventQueueEnabled() {
3459 nsThreadManager::get().EnableMainThreadEventPrioritization();
3460 return IPC_OK();
3463 mozilla::ipc::IPCResult ContentChild::RecvFlushInputEventQueue() {
3464 nsThreadManager::get().FlushInputEventPrioritization();
3465 return IPC_OK();
3468 mozilla::ipc::IPCResult ContentChild::RecvSuspendInputEventQueue() {
3469 nsThreadManager::get().SuspendInputEventPrioritization();
3470 return IPC_OK();
3473 mozilla::ipc::IPCResult ContentChild::RecvResumeInputEventQueue() {
3474 nsThreadManager::get().ResumeInputEventPrioritization();
3475 return IPC_OK();
3478 mozilla::ipc::IPCResult ContentChild::RecvAddDynamicScalars(
3479 nsTArray<DynamicScalarDefinition>&& aDefs) {
3480 TelemetryIPC::AddDynamicScalarDefinitions(aDefs);
3481 return IPC_OK();
3484 mozilla::ipc::IPCResult ContentChild::RecvCrossProcessRedirect(
3485 RedirectToRealChannelArgs&& aArgs,
3486 nsTArray<Endpoint<extensions::PStreamFilterParent>>&& aEndpoints,
3487 CrossProcessRedirectResolver&& aResolve) {
3488 nsCOMPtr<nsILoadInfo> loadInfo;
3489 nsresult rv = mozilla::ipc::LoadInfoArgsToLoadInfo(
3490 aArgs.loadInfo(), NOT_REMOTE_TYPE, getter_AddRefs(loadInfo));
3491 if (NS_FAILED(rv)) {
3492 MOZ_DIAGNOSTIC_ASSERT(false, "LoadInfoArgsToLoadInfo failed");
3493 return IPC_OK();
3496 nsCOMPtr<nsIChannel> newChannel;
3497 MOZ_ASSERT((aArgs.loadStateInternalLoadFlags() &
3498 nsDocShell::InternalLoad::INTERNAL_LOAD_FLAGS_IS_SRCDOC) ||
3499 aArgs.srcdocData().IsVoid());
3500 rv = nsDocShell::CreateRealChannelForDocument(
3501 getter_AddRefs(newChannel), aArgs.uri(), loadInfo, nullptr,
3502 aArgs.newLoadFlags(), aArgs.srcdocData(), aArgs.baseUri());
3504 if (RefPtr<HttpBaseChannel> httpChannel = do_QueryObject(newChannel)) {
3505 httpChannel->SetEarlyHints(std::move(aArgs.earlyHints()));
3506 httpChannel->SetEarlyHintLinkType(aArgs.earlyHintLinkType());
3509 // This is used to report any errors back to the parent by calling
3510 // CrossProcessRedirectFinished.
3511 RefPtr<HttpChannelChild> httpChild = do_QueryObject(newChannel);
3512 auto resolve = [=](const nsresult& aRv) {
3513 nsresult rv = aRv;
3514 if (httpChild) {
3515 rv = httpChild->CrossProcessRedirectFinished(rv);
3517 aResolve(rv);
3519 auto scopeExit = MakeScopeExit([&]() { resolve(rv); });
3521 if (NS_FAILED(rv)) {
3522 return IPC_OK();
3525 if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel)) {
3526 rv = httpChannel->SetChannelId(aArgs.channelId());
3528 if (NS_FAILED(rv)) {
3529 return IPC_OK();
3532 rv = newChannel->SetOriginalURI(aArgs.originalURI());
3533 if (NS_FAILED(rv)) {
3534 return IPC_OK();
3537 if (nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal =
3538 do_QueryInterface(newChannel)) {
3539 rv = httpChannelInternal->SetRedirectMode(aArgs.redirectMode());
3541 if (NS_FAILED(rv)) {
3542 return IPC_OK();
3545 if (aArgs.init()) {
3546 HttpBaseChannel::ReplacementChannelConfig config(std::move(*aArgs.init()));
3547 HttpBaseChannel::ConfigureReplacementChannel(
3548 newChannel, config,
3549 HttpBaseChannel::ReplacementReason::DocumentChannel);
3552 if (aArgs.contentDisposition()) {
3553 newChannel->SetContentDisposition(*aArgs.contentDisposition());
3556 if (aArgs.contentDispositionFilename()) {
3557 newChannel->SetContentDispositionFilename(
3558 *aArgs.contentDispositionFilename());
3561 if (nsCOMPtr<nsIChildChannel> childChannel = do_QueryInterface(newChannel)) {
3562 // Connect to the parent if this is a remote channel. If it's entirely
3563 // handled locally, then we'll call AsyncOpen from the docshell when
3564 // we complete the setup
3565 rv = childChannel->ConnectParent(
3566 aArgs.registrarId()); // creates parent channel
3567 if (NS_FAILED(rv)) {
3568 return IPC_OK();
3572 // We need to copy the property bag before signaling that the channel
3573 // is ready so that the nsDocShell can retrieve the history data when called.
3574 if (nsCOMPtr<nsIWritablePropertyBag> bag = do_QueryInterface(newChannel)) {
3575 nsHashPropertyBag::CopyFrom(bag, aArgs.properties());
3578 RefPtr<nsDocShellLoadState> loadState;
3579 rv = nsDocShellLoadState::CreateFromPendingChannel(
3580 newChannel, aArgs.loadIdentifier(), aArgs.registrarId(),
3581 getter_AddRefs(loadState));
3582 if (NS_WARN_IF(NS_FAILED(rv))) {
3583 return IPC_OK();
3585 loadState->SetLoadFlags(aArgs.loadStateExternalLoadFlags());
3586 loadState->SetInternalLoadFlags(aArgs.loadStateInternalLoadFlags());
3587 if (IsValidLoadType(aArgs.loadStateLoadType())) {
3588 loadState->SetLoadType(aArgs.loadStateLoadType());
3591 if (aArgs.loadingSessionHistoryInfo().isSome()) {
3592 loadState->SetLoadingSessionHistoryInfo(
3593 aArgs.loadingSessionHistoryInfo().ref());
3595 if (aArgs.originalUriString().isSome()) {
3596 loadState->SetOriginalURIString(aArgs.originalUriString().ref());
3599 RefPtr<ChildProcessChannelListener> processListener =
3600 ChildProcessChannelListener::GetSingleton();
3601 // The listener will call completeRedirectSetup or asyncOpen on the channel.
3602 processListener->OnChannelReady(loadState, aArgs.loadIdentifier(),
3603 std::move(aEndpoints), aArgs.timing(),
3604 std::move(resolve));
3605 scopeExit.release();
3607 // scopeExit will call CrossProcessRedirectFinished(rv) here
3608 return IPC_OK();
3611 mozilla::ipc::IPCResult ContentChild::RecvStartDelayedAutoplayMediaComponents(
3612 const MaybeDiscarded<BrowsingContext>& aContext) {
3613 if (NS_WARN_IF(aContext.IsNullOrDiscarded())) {
3614 return IPC_OK();
3617 aContext.get()->StartDelayedAutoplayMediaComponents();
3618 return IPC_OK();
3621 mozilla::ipc::IPCResult ContentChild::RecvUpdateMediaControlAction(
3622 const MaybeDiscarded<BrowsingContext>& aContext,
3623 const MediaControlAction& aAction) {
3624 if (NS_WARN_IF(aContext.IsNullOrDiscarded())) {
3625 return IPC_OK();
3628 ContentMediaControlKeyHandler::HandleMediaControlAction(aContext.get(),
3629 aAction);
3630 return IPC_OK();
3633 mozilla::ipc::IPCResult ContentChild::RecvOnAllowAccessFor(
3634 const MaybeDiscarded<BrowsingContext>& aContext,
3635 const nsCString& aTrackingOrigin, uint32_t aCookieBehavior,
3636 const ContentBlockingNotifier::StorageAccessPermissionGrantedReason&
3637 aReason) {
3638 MOZ_ASSERT(!aContext.IsNull(), "Browsing context cannot be null");
3640 StorageAccessAPIHelper::OnAllowAccessFor(
3641 aContext.GetMaybeDiscarded(), aTrackingOrigin, aCookieBehavior, aReason);
3643 return IPC_OK();
3646 mozilla::ipc::IPCResult ContentChild::RecvOnContentBlockingDecision(
3647 const MaybeDiscarded<BrowsingContext>& aContext,
3648 const ContentBlockingNotifier::BlockingDecision& aDecision,
3649 uint32_t aRejectedReason) {
3650 MOZ_ASSERT(!aContext.IsNull(), "Browsing context cannot be null");
3652 nsCOMPtr<nsPIDOMWindowOuter> outer = aContext.get()->GetDOMWindow();
3653 if (!outer) {
3654 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3655 ("ChildIPC: Trying to send a message to a context without a outer "
3656 "window"));
3657 return IPC_OK();
3660 nsCOMPtr<nsPIDOMWindowInner> inner = outer->GetCurrentInnerWindow();
3661 if (!inner) {
3662 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3663 ("ChildIPC: Trying to send a message to a context without a inner "
3664 "window"));
3665 return IPC_OK();
3668 ContentBlockingNotifier::OnDecision(inner, aDecision, aRejectedReason);
3669 return IPC_OK();
3672 #ifdef NIGHTLY_BUILD
3673 void ContentChild::OnChannelReceivedMessage(const Message& aMsg) {
3674 if (nsContentUtils::IsMessageInputEvent(aMsg)) {
3675 mPendingInputEvents++;
3679 PContentChild::Result ContentChild::OnMessageReceived(const Message& aMsg) {
3680 if (nsContentUtils::IsMessageInputEvent(aMsg)) {
3681 DebugOnly<uint32_t> prevEvts = mPendingInputEvents--;
3682 MOZ_ASSERT(prevEvts > 0);
3685 return PContentChild::OnMessageReceived(aMsg);
3688 PContentChild::Result ContentChild::OnMessageReceived(
3689 const Message& aMsg, UniquePtr<Message>& aReply) {
3690 return PContentChild::OnMessageReceived(aMsg, aReply);
3692 #endif
3694 mozilla::ipc::IPCResult ContentChild::RecvCreateBrowsingContext(
3695 uint64_t aGroupId, BrowsingContext::IPCInitializer&& aInit) {
3696 // We can't already have a BrowsingContext with this ID.
3697 if (RefPtr<BrowsingContext> existing = BrowsingContext::Get(aInit.mId)) {
3698 return IPC_FAIL(this, "Browsing context already exists");
3701 RefPtr<WindowContext> parent = WindowContext::GetById(aInit.mParentId);
3702 if (!parent && aInit.mParentId != 0) {
3703 // Handle this case by ignoring the request, as parent must be in the
3704 // process of being discarded.
3705 // In the future it would be nice to avoid sending this message to the child
3706 // at all.
3707 NS_WARNING("Attempt to attach BrowsingContext to discarded parent");
3708 return IPC_OK();
3711 RefPtr<BrowsingContextGroup> group =
3712 BrowsingContextGroup::GetOrCreate(aGroupId);
3713 return BrowsingContext::CreateFromIPC(std::move(aInit), group, nullptr);
3716 mozilla::ipc::IPCResult ContentChild::RecvDiscardBrowsingContext(
3717 const MaybeDiscarded<BrowsingContext>& aContext, bool aDoDiscard,
3718 DiscardBrowsingContextResolver&& aResolve) {
3719 if (BrowsingContext* context = aContext.GetMaybeDiscarded()) {
3720 if (aDoDiscard && !context->IsDiscarded()) {
3721 context->Detach(/* aFromIPC */ true);
3723 context->AddDiscardListener(aResolve);
3724 return IPC_OK();
3727 // Immediately resolve the promise, as we've received the message. This will
3728 // allow the parent process to discard references to this BC.
3729 aResolve(true);
3730 return IPC_OK();
3733 mozilla::ipc::IPCResult ContentChild::RecvRegisterBrowsingContextGroup(
3734 uint64_t aGroupId, nsTArray<SyncedContextInitializer>&& aInits) {
3735 RefPtr<BrowsingContextGroup> group =
3736 BrowsingContextGroup::GetOrCreate(aGroupId);
3738 // Each of the initializers in aInits is sorted in pre-order, so our parent
3739 // should always be available before the element itself.
3740 for (auto& initUnion : aInits) {
3741 switch (initUnion.type()) {
3742 case SyncedContextInitializer::TBrowsingContextInitializer: {
3743 auto& init = initUnion.get_BrowsingContextInitializer();
3744 #ifdef DEBUG
3745 RefPtr<BrowsingContext> existing = BrowsingContext::Get(init.mId);
3746 MOZ_ASSERT(!existing, "BrowsingContext must not exist yet!");
3748 RefPtr<WindowContext> parent = init.GetParent();
3749 MOZ_ASSERT_IF(parent, parent->Group() == group);
3750 #endif
3752 BrowsingContext::CreateFromIPC(std::move(init), group, nullptr);
3753 break;
3755 case SyncedContextInitializer::TWindowContextInitializer: {
3756 auto& init = initUnion.get_WindowContextInitializer();
3757 #ifdef DEBUG
3758 RefPtr<WindowContext> existing =
3759 WindowContext::GetById(init.mInnerWindowId);
3760 MOZ_ASSERT(!existing, "WindowContext must not exist yet!");
3761 RefPtr<BrowsingContext> parent =
3762 BrowsingContext::Get(init.mBrowsingContextId);
3763 MOZ_ASSERT(parent && parent->Group() == group);
3764 #endif
3766 WindowContext::CreateFromIPC(std::move(init));
3767 break;
3769 default:
3770 MOZ_ASSERT_UNREACHABLE();
3774 return IPC_OK();
3777 mozilla::ipc::IPCResult ContentChild::RecvDestroyBrowsingContextGroup(
3778 uint64_t aGroupId) {
3779 if (RefPtr<BrowsingContextGroup> group =
3780 BrowsingContextGroup::GetExisting(aGroupId)) {
3781 group->ChildDestroy();
3783 return IPC_OK();
3786 mozilla::ipc::IPCResult ContentChild::RecvWindowClose(
3787 const MaybeDiscarded<BrowsingContext>& aContext, bool aTrustedCaller) {
3788 if (aContext.IsNullOrDiscarded()) {
3789 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3790 ("ChildIPC: Trying to send a message to dead or detached context"));
3791 return IPC_OK();
3794 nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow();
3795 if (!window) {
3796 MOZ_LOG(
3797 BrowsingContext::GetLog(), LogLevel::Debug,
3798 ("ChildIPC: Trying to send a message to a context without a window"));
3799 return IPC_OK();
3802 // Call `GetDocument()` to force the document and its inner window to be
3803 // created, as it would be forced to be created if this call was being
3804 // performed in-process.
3805 if (NS_WARN_IF(!aContext.get()->GetDocument())) {
3806 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3807 ("ChildIPC: Trying to send a message to a context but document "
3808 "creation failed"));
3809 return IPC_OK();
3812 nsGlobalWindowOuter::Cast(window)->CloseOuter(aTrustedCaller);
3813 return IPC_OK();
3816 mozilla::ipc::IPCResult ContentChild::RecvWindowFocus(
3817 const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType,
3818 uint64_t aActionId) {
3819 if (aContext.IsNullOrDiscarded()) {
3820 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3821 ("ChildIPC: Trying to send a message to dead or detached context"));
3822 return IPC_OK();
3825 nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow();
3826 if (!window) {
3827 MOZ_LOG(
3828 BrowsingContext::GetLog(), LogLevel::Debug,
3829 ("ChildIPC: Trying to send a message to a context without a window"));
3830 return IPC_OK();
3833 // Call `GetDocument()` to force the document and its inner window to be
3834 // created, as it would be forced to be created if this call was being
3835 // performed in-process.
3836 if (NS_WARN_IF(!aContext.get()->GetDocument())) {
3837 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3838 ("ChildIPC: Trying to send a message to a context but document "
3839 "creation failed"));
3840 return IPC_OK();
3843 nsGlobalWindowOuter::Cast(window)->FocusOuter(
3844 aCallerType, /* aFromOtherProcess */ true, aActionId);
3845 return IPC_OK();
3848 mozilla::ipc::IPCResult ContentChild::RecvWindowBlur(
3849 const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType) {
3850 if (aContext.IsNullOrDiscarded()) {
3851 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3852 ("ChildIPC: Trying to send a message to dead or detached context"));
3853 return IPC_OK();
3856 nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow();
3857 if (!window) {
3858 MOZ_LOG(
3859 BrowsingContext::GetLog(), LogLevel::Debug,
3860 ("ChildIPC: Trying to send a message to a context without a window"));
3861 return IPC_OK();
3864 // Call `GetDocument()` to force the document and its inner window to be
3865 // created, as it would be forced to be created if this call was being
3866 // performed in-process.
3867 if (NS_WARN_IF(!aContext.get()->GetDocument())) {
3868 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3869 ("ChildIPC: Trying to send a message to a context but document "
3870 "creation failed"));
3871 return IPC_OK();
3874 nsGlobalWindowOuter::Cast(window)->BlurOuter(aCallerType);
3875 return IPC_OK();
3878 mozilla::ipc::IPCResult ContentChild::RecvRaiseWindow(
3879 const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType,
3880 uint64_t aActionId) {
3881 if (aContext.IsNullOrDiscarded()) {
3882 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3883 ("ChildIPC: Trying to send a message to dead or detached context"));
3884 return IPC_OK();
3887 nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow();
3888 if (!window) {
3889 MOZ_LOG(
3890 BrowsingContext::GetLog(), LogLevel::Debug,
3891 ("ChildIPC: Trying to send a message to a context without a window"));
3892 return IPC_OK();
3895 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
3896 fm->RaiseWindow(window, aCallerType, aActionId);
3898 return IPC_OK();
3901 mozilla::ipc::IPCResult ContentChild::RecvAdjustWindowFocus(
3902 const MaybeDiscarded<BrowsingContext>& aContext, bool aIsVisible,
3903 uint64_t aActionId, bool aShouldClearAncestorFocus,
3904 const MaybeDiscarded<BrowsingContext>& aAncestorBrowsingContextToFocus) {
3905 if (aContext.IsNullOrDiscarded()) {
3906 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3907 ("ChildIPC: Trying to send a message to dead or detached context"));
3908 return IPC_OK();
3911 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
3912 RefPtr<BrowsingContext> bc = aContext.get();
3913 RefPtr<BrowsingContext> ancestor =
3914 aAncestorBrowsingContextToFocus.IsNullOrDiscarded()
3915 ? nullptr
3916 : aAncestorBrowsingContextToFocus.get();
3917 fm->AdjustInProcessWindowFocus(bc, false, aIsVisible, aActionId,
3918 aShouldClearAncestorFocus, ancestor);
3920 return IPC_OK();
3923 mozilla::ipc::IPCResult ContentChild::RecvClearFocus(
3924 const MaybeDiscarded<BrowsingContext>& aContext) {
3925 if (aContext.IsNullOrDiscarded()) {
3926 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3927 ("ChildIPC: Trying to send a message to dead or detached context"));
3928 return IPC_OK();
3931 nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow();
3932 if (!window) {
3933 MOZ_LOG(
3934 BrowsingContext::GetLog(), LogLevel::Debug,
3935 ("ChildIPC: Trying to send a message to a context without a window"));
3936 return IPC_OK();
3939 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
3940 fm->ClearFocus(window);
3942 return IPC_OK();
3945 mozilla::ipc::IPCResult ContentChild::RecvSetFocusedBrowsingContext(
3946 const MaybeDiscarded<BrowsingContext>& aContext, uint64_t aActionId) {
3947 if (aContext.IsNullOrDiscarded()) {
3948 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3949 ("ChildIPC: Trying to send a message to dead or detached context"));
3950 return IPC_OK();
3953 nsFocusManager* fm = nsFocusManager::GetFocusManager();
3954 if (fm) {
3955 fm->SetFocusedBrowsingContextFromOtherProcess(aContext.get(), aActionId);
3957 return IPC_OK();
3960 mozilla::ipc::IPCResult ContentChild::RecvSetActiveBrowsingContext(
3961 const MaybeDiscarded<BrowsingContext>& aContext, uint64_t aActionId) {
3962 if (aContext.IsNullOrDiscarded()) {
3963 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3964 ("ChildIPC: Trying to send a message to dead or detached context"));
3965 return IPC_OK();
3968 nsFocusManager* fm = nsFocusManager::GetFocusManager();
3969 if (fm) {
3970 fm->SetActiveBrowsingContextFromOtherProcess(aContext.get(), aActionId);
3972 return IPC_OK();
3975 mozilla::ipc::IPCResult ContentChild::RecvAbortOrientationPendingPromises(
3976 const MaybeDiscarded<BrowsingContext>& aContext) {
3977 if (aContext.IsNullOrDiscarded()) {
3978 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3979 ("ChildIPC: Trying to send a message to dead or detached context"));
3980 return IPC_OK();
3983 dom::ScreenOrientation::AbortInProcessOrientationPromises(aContext.get());
3984 return IPC_OK();
3987 mozilla::ipc::IPCResult ContentChild::RecvUnsetActiveBrowsingContext(
3988 const MaybeDiscarded<BrowsingContext>& aContext, uint64_t aActionId) {
3989 if (aContext.IsNullOrDiscarded()) {
3990 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
3991 ("ChildIPC: Trying to send a message to dead or detached context"));
3992 return IPC_OK();
3995 nsFocusManager* fm = nsFocusManager::GetFocusManager();
3996 if (fm) {
3997 fm->UnsetActiveBrowsingContextFromOtherProcess(aContext.get(), aActionId);
3999 return IPC_OK();
4002 mozilla::ipc::IPCResult ContentChild::RecvSetFocusedElement(
4003 const MaybeDiscarded<BrowsingContext>& aContext, bool aNeedsFocus) {
4004 if (aContext.IsNullOrDiscarded()) {
4005 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
4006 ("ChildIPC: Trying to send a message to dead or detached context"));
4007 return IPC_OK();
4010 nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow();
4011 if (!window) {
4012 MOZ_LOG(
4013 BrowsingContext::GetLog(), LogLevel::Debug,
4014 ("ChildIPC: Trying to send a message to a context without a window"));
4015 return IPC_OK();
4018 window->SetFocusedElement(nullptr, 0, aNeedsFocus);
4019 return IPC_OK();
4022 mozilla::ipc::IPCResult ContentChild::RecvFinalizeFocusOuter(
4023 const MaybeDiscarded<BrowsingContext>& aContext, bool aCanFocus,
4024 CallerType aCallerType) {
4025 if (aContext.IsNullOrDiscarded()) {
4026 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
4027 ("ChildIPC: Trying to send a message to dead or detached context"));
4028 return IPC_OK();
4031 if (Element* frame = aContext.get()->GetEmbedderElement()) {
4032 nsContentUtils::RequestFrameFocus(*frame, aCanFocus, aCallerType);
4035 return IPC_OK();
4038 mozilla::ipc::IPCResult ContentChild::RecvBlurToChild(
4039 const MaybeDiscarded<BrowsingContext>& aFocusedBrowsingContext,
4040 const MaybeDiscarded<BrowsingContext>& aBrowsingContextToClear,
4041 const MaybeDiscarded<BrowsingContext>& aAncestorBrowsingContextToFocus,
4042 bool aIsLeavingDocument, bool aAdjustWidget, uint64_t aActionId) {
4043 if (aFocusedBrowsingContext.IsNullOrDiscarded()) {
4044 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
4045 ("ChildIPC: Trying to send a message to dead or detached context"));
4046 return IPC_OK();
4049 RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager();
4050 if (MOZ_UNLIKELY(!fm)) {
4051 return IPC_OK();
4054 RefPtr<BrowsingContext> toClear = aBrowsingContextToClear.IsDiscarded()
4055 ? nullptr
4056 : aBrowsingContextToClear.get();
4057 RefPtr<BrowsingContext> toFocus =
4058 aAncestorBrowsingContextToFocus.IsDiscarded()
4059 ? nullptr
4060 : aAncestorBrowsingContextToFocus.get();
4062 RefPtr<BrowsingContext> focusedBrowsingContext =
4063 aFocusedBrowsingContext.get();
4065 fm->BlurFromOtherProcess(focusedBrowsingContext, toClear, toFocus,
4066 aIsLeavingDocument, aAdjustWidget, aActionId);
4067 return IPC_OK();
4070 mozilla::ipc::IPCResult ContentChild::RecvSetupFocusedAndActive(
4071 const MaybeDiscarded<BrowsingContext>& aFocusedBrowsingContext,
4072 uint64_t aActionIdForFocused,
4073 const MaybeDiscarded<BrowsingContext>& aActiveBrowsingContext,
4074 uint64_t aActionIdForActive) {
4075 nsFocusManager* fm = nsFocusManager::GetFocusManager();
4076 if (fm) {
4077 if (!aActiveBrowsingContext.IsNullOrDiscarded()) {
4078 fm->SetActiveBrowsingContextFromOtherProcess(aActiveBrowsingContext.get(),
4079 aActionIdForActive);
4081 if (!aFocusedBrowsingContext.IsNullOrDiscarded()) {
4082 fm->SetFocusedBrowsingContextFromOtherProcess(
4083 aFocusedBrowsingContext.get(), aActionIdForFocused);
4086 return IPC_OK();
4089 mozilla::ipc::IPCResult ContentChild::RecvReviseActiveBrowsingContext(
4090 uint64_t aOldActionId,
4091 const MaybeDiscarded<BrowsingContext>& aActiveBrowsingContext,
4092 uint64_t aNewActionId) {
4093 nsFocusManager* fm = nsFocusManager::GetFocusManager();
4094 if (fm && !aActiveBrowsingContext.IsNullOrDiscarded()) {
4095 fm->ReviseActiveBrowsingContext(aOldActionId, aActiveBrowsingContext.get(),
4096 aNewActionId);
4098 return IPC_OK();
4101 mozilla::ipc::IPCResult ContentChild::RecvReviseFocusedBrowsingContext(
4102 uint64_t aOldActionId,
4103 const MaybeDiscarded<BrowsingContext>& aFocusedBrowsingContext,
4104 uint64_t aNewActionId) {
4105 nsFocusManager* fm = nsFocusManager::GetFocusManager();
4106 if (fm && !aFocusedBrowsingContext.IsNullOrDiscarded()) {
4107 fm->ReviseFocusedBrowsingContext(
4108 aOldActionId, aFocusedBrowsingContext.get(), aNewActionId);
4110 return IPC_OK();
4113 mozilla::ipc::IPCResult ContentChild::RecvMaybeExitFullscreen(
4114 const MaybeDiscarded<BrowsingContext>& aContext) {
4115 if (aContext.IsNullOrDiscarded()) {
4116 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
4117 ("ChildIPC: Trying to send a message to dead or detached context"));
4118 return IPC_OK();
4121 nsIDocShell* shell = aContext.get()->GetDocShell();
4122 if (!shell) {
4123 return IPC_OK();
4126 Document* doc = shell->GetDocument();
4127 if (doc && doc->GetFullscreenElement()) {
4128 Document::AsyncExitFullscreen(doc);
4131 return IPC_OK();
4134 mozilla::ipc::IPCResult ContentChild::RecvWindowPostMessage(
4135 const MaybeDiscarded<BrowsingContext>& aContext,
4136 const ClonedOrErrorMessageData& aMessage, const PostMessageData& aData) {
4137 if (aContext.IsNullOrDiscarded()) {
4138 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
4139 ("ChildIPC: Trying to send a message to dead or detached context"));
4140 return IPC_OK();
4143 RefPtr<nsGlobalWindowOuter> window =
4144 nsGlobalWindowOuter::Cast(aContext.get()->GetDOMWindow());
4145 if (!window) {
4146 MOZ_LOG(
4147 BrowsingContext::GetLog(), LogLevel::Debug,
4148 ("ChildIPC: Trying to send a message to a context without a window"));
4149 return IPC_OK();
4152 nsCOMPtr<nsIPrincipal> providedPrincipal;
4153 if (!window->GetPrincipalForPostMessage(
4154 aData.targetOrigin(), aData.targetOriginURI(),
4155 aData.callerPrincipal(), *aData.subjectPrincipal(),
4156 getter_AddRefs(providedPrincipal))) {
4157 return IPC_OK();
4160 // Call `GetDocument()` to force the document and its inner window to be
4161 // created, as it would be forced to be created if this call was being
4162 // performed in-process.
4163 if (NS_WARN_IF(!aContext.get()->GetDocument())) {
4164 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
4165 ("ChildIPC: Trying to send a message to a context but document "
4166 "creation failed"));
4167 return IPC_OK();
4170 // It's OK if `sourceBc` has already been discarded, so long as we can
4171 // continue to wrap it.
4172 RefPtr<BrowsingContext> sourceBc = aData.source().GetMaybeDiscarded();
4174 // Create and asynchronously dispatch a runnable which will handle actual DOM
4175 // event creation and dispatch.
4176 RefPtr<PostMessageEvent> event =
4177 new PostMessageEvent(sourceBc, aData.origin(), window, providedPrincipal,
4178 aData.innerWindowId(), aData.callerURI(),
4179 aData.scriptLocation(), aData.isFromPrivateWindow());
4180 event->UnpackFrom(aMessage);
4182 event->DispatchToTargetThread(IgnoredErrorResult());
4183 return IPC_OK();
4186 mozilla::ipc::IPCResult ContentChild::RecvCommitBrowsingContextTransaction(
4187 const MaybeDiscarded<BrowsingContext>& aContext,
4188 BrowsingContext::BaseTransaction&& aTransaction, uint64_t aEpoch) {
4189 return aTransaction.CommitFromIPC(aContext, aEpoch, this);
4192 mozilla::ipc::IPCResult ContentChild::RecvCommitWindowContextTransaction(
4193 const MaybeDiscarded<WindowContext>& aContext,
4194 WindowContext::BaseTransaction&& aTransaction, uint64_t aEpoch) {
4195 return aTransaction.CommitFromIPC(aContext, aEpoch, this);
4198 mozilla::ipc::IPCResult ContentChild::RecvCreateWindowContext(
4199 WindowContext::IPCInitializer&& aInit) {
4200 RefPtr<BrowsingContext> bc = BrowsingContext::Get(aInit.mBrowsingContextId);
4201 if (!bc) {
4202 // Handle this case by ignoring the request, as bc must be in the process of
4203 // being discarded.
4204 // In the future it would be nice to avoid sending this message to the child
4205 // at all.
4206 NS_WARNING("Attempt to attach WindowContext to discarded parent");
4207 return IPC_OK();
4210 WindowContext::CreateFromIPC(std::move(aInit));
4211 return IPC_OK();
4214 mozilla::ipc::IPCResult ContentChild::RecvDiscardWindowContext(
4215 uint64_t aContextId, DiscardWindowContextResolver&& aResolve) {
4216 // Resolve immediately to acknowledge call
4217 aResolve(true);
4219 RefPtr<WindowContext> window = WindowContext::GetById(aContextId);
4220 if (NS_WARN_IF(!window) || NS_WARN_IF(window->IsDiscarded())) {
4221 return IPC_OK();
4224 window->Discard();
4225 return IPC_OK();
4228 mozilla::ipc::IPCResult ContentChild::RecvScriptError(
4229 const nsString& aMessage, const nsString& aSourceName,
4230 const nsString& aSourceLine, const uint32_t& aLineNumber,
4231 const uint32_t& aColNumber, const uint32_t& aFlags,
4232 const nsCString& aCategory, const bool& aFromPrivateWindow,
4233 const uint64_t& aInnerWindowId, const bool& aFromChromeContext) {
4234 nsresult rv = NS_OK;
4235 nsCOMPtr<nsIConsoleService> consoleService =
4236 do_GetService(NS_CONSOLESERVICE_CONTRACTID, &rv);
4237 NS_ENSURE_SUCCESS(rv, IPC_FAIL(this, "Failed to get console service"));
4239 nsCOMPtr<nsIScriptError> scriptError(
4240 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
4241 NS_ENSURE_TRUE(scriptError,
4242 IPC_FAIL(this, "Failed to construct nsIScriptError"));
4244 scriptError->InitWithWindowID(aMessage, aSourceName, aSourceLine, aLineNumber,
4245 aColNumber, aFlags, aCategory, aInnerWindowId,
4246 aFromChromeContext);
4247 rv = consoleService->LogMessage(scriptError);
4248 NS_ENSURE_SUCCESS(rv, IPC_FAIL(this, "Failed to log script error"));
4250 return IPC_OK();
4253 mozilla::ipc::IPCResult ContentChild::RecvReportFrameTimingData(
4254 const LoadInfoArgs& loadInfoArgs, const nsString& entryName,
4255 const nsString& initiatorType, UniquePtr<PerformanceTimingData>&& aData) {
4256 if (!aData) {
4257 return IPC_FAIL(this, "aData should not be null");
4260 nsCOMPtr<nsILoadInfo> loadInfo;
4261 nsresult rv = mozilla::ipc::LoadInfoArgsToLoadInfo(
4262 loadInfoArgs, NOT_REMOTE_TYPE, getter_AddRefs(loadInfo));
4263 if (NS_FAILED(rv)) {
4264 MOZ_DIAGNOSTIC_ASSERT(false, "LoadInfoArgsToLoadInfo failed");
4265 return IPC_OK();
4268 // It is important to call LoadInfo::GetPerformanceStorage instead of simply
4269 // getting the performance object via the innerWindowID in order to perform
4270 // necessary cross origin checks.
4271 if (PerformanceStorage* storage = loadInfo->GetPerformanceStorage()) {
4272 storage->AddEntry(entryName, initiatorType, std::move(aData));
4274 return IPC_OK();
4277 mozilla::ipc::IPCResult ContentChild::RecvLoadURI(
4278 const MaybeDiscarded<BrowsingContext>& aContext,
4279 nsDocShellLoadState* aLoadState, bool aSetNavigating,
4280 LoadURIResolver&& aResolve) {
4281 auto resolveOnExit = MakeScopeExit([&] { aResolve(true); });
4283 if (aContext.IsNullOrDiscarded()) {
4284 return IPC_OK();
4286 RefPtr<BrowsingContext> context = aContext.get();
4287 if (!context->IsInProcess()) {
4288 // The DocShell has been torn down or the BrowsingContext has changed
4289 // process in the middle of the load request. There's not much we can do at
4290 // this point, so just give up.
4291 return IPC_OK();
4294 context->LoadURI(aLoadState, aSetNavigating);
4296 nsCOMPtr<nsPIDOMWindowOuter> window = context->GetDOMWindow();
4297 BrowserChild* bc = BrowserChild::GetFrom(window);
4298 if (bc) {
4299 bc->NotifyNavigationFinished();
4302 #ifdef MOZ_CRASHREPORTER
4303 if (CrashReporter::GetEnabled()) {
4304 nsCOMPtr<nsIURI> annotationURI;
4306 nsresult rv = NS_MutateURI(aLoadState->URI())
4307 .SetUserPass(""_ns)
4308 .Finalize(annotationURI);
4310 if (NS_FAILED(rv)) {
4311 // Ignore failures on about: URIs.
4312 annotationURI = aLoadState->URI();
4315 CrashReporter::RecordAnnotationNSCString(CrashReporter::Annotation::URL,
4316 annotationURI->GetSpecOrDefault());
4318 #endif
4320 return IPC_OK();
4323 mozilla::ipc::IPCResult ContentChild::RecvInternalLoad(
4324 nsDocShellLoadState* aLoadState) {
4325 if (!aLoadState->Target().IsEmpty() ||
4326 aLoadState->TargetBrowsingContext().IsNull()) {
4327 return IPC_FAIL(this, "must already be retargeted");
4329 if (aLoadState->TargetBrowsingContext().IsDiscarded()) {
4330 return IPC_OK();
4332 RefPtr<BrowsingContext> context = aLoadState->TargetBrowsingContext().get();
4334 context->InternalLoad(aLoadState);
4336 #ifdef MOZ_CRASHREPORTER
4337 if (CrashReporter::GetEnabled()) {
4338 nsCOMPtr<nsIURI> annotationURI;
4340 nsresult rv = NS_MutateURI(aLoadState->URI())
4341 .SetUserPass(""_ns)
4342 .Finalize(annotationURI);
4344 if (NS_FAILED(rv)) {
4345 // Ignore failures on about: URIs.
4346 annotationURI = aLoadState->URI();
4349 CrashReporter::RecordAnnotationNSCString(CrashReporter::Annotation::URL,
4350 annotationURI->GetSpecOrDefault());
4352 #endif
4354 return IPC_OK();
4357 mozilla::ipc::IPCResult ContentChild::RecvDisplayLoadError(
4358 const MaybeDiscarded<BrowsingContext>& aContext, const nsAString& aURI) {
4359 if (aContext.IsNullOrDiscarded()) {
4360 return IPC_OK();
4362 RefPtr<BrowsingContext> context = aContext.get();
4364 context->DisplayLoadError(aURI);
4366 nsCOMPtr<nsPIDOMWindowOuter> window = context->GetDOMWindow();
4367 BrowserChild* bc = BrowserChild::GetFrom(window);
4368 if (bc) {
4369 bc->NotifyNavigationFinished();
4371 return IPC_OK();
4374 mozilla::ipc::IPCResult ContentChild::RecvHistoryCommitIndexAndLength(
4375 const MaybeDiscarded<BrowsingContext>& aContext, const uint32_t& aIndex,
4376 const uint32_t& aLength, const nsID& aChangeID) {
4377 if (!aContext.IsNullOrDiscarded()) {
4378 ChildSHistory* shistory = aContext.get()->GetChildSessionHistory();
4379 if (shistory) {
4380 shistory->SetIndexAndLength(aIndex, aLength, aChangeID);
4383 return IPC_OK();
4386 mozilla::ipc::IPCResult ContentChild::RecvGetLayoutHistoryState(
4387 const MaybeDiscarded<BrowsingContext>& aContext,
4388 GetLayoutHistoryStateResolver&& aResolver) {
4389 nsCOMPtr<nsILayoutHistoryState> state;
4390 nsIDocShell* docShell;
4391 mozilla::Maybe<mozilla::dom::Wireframe> wireframe;
4392 if (!aContext.IsNullOrDiscarded() &&
4393 (docShell = aContext.get()->GetDocShell())) {
4394 docShell->PersistLayoutHistoryState();
4395 docShell->GetLayoutHistoryState(getter_AddRefs(state));
4396 wireframe = static_cast<nsDocShell*>(docShell)->GetWireframe();
4398 aResolver(
4399 std::tuple<nsILayoutHistoryState*, const mozilla::Maybe<Wireframe>&>(
4400 state, wireframe));
4402 return IPC_OK();
4405 mozilla::ipc::IPCResult ContentChild::RecvDispatchLocationChangeEvent(
4406 const MaybeDiscarded<BrowsingContext>& aContext) {
4407 if (!aContext.IsNullOrDiscarded() && aContext.get()->GetDocShell()) {
4408 aContext.get()->GetDocShell()->DispatchLocationChangeEvent();
4410 return IPC_OK();
4413 mozilla::ipc::IPCResult ContentChild::RecvDispatchBeforeUnloadToSubtree(
4414 const MaybeDiscarded<BrowsingContext>& aStartingAt,
4415 DispatchBeforeUnloadToSubtreeResolver&& aResolver) {
4416 if (aStartingAt.IsNullOrDiscarded()) {
4417 aResolver(nsIDocumentViewer::eAllowNavigation);
4418 } else {
4419 DispatchBeforeUnloadToSubtree(aStartingAt.get(), std::move(aResolver));
4421 return IPC_OK();
4424 mozilla::ipc::IPCResult ContentChild::RecvInitNextGenLocalStorageEnabled(
4425 const bool& aEnabled) {
4426 mozilla::dom::RecvInitNextGenLocalStorageEnabled(aEnabled);
4428 return IPC_OK();
4431 /* static */ void ContentChild::DispatchBeforeUnloadToSubtree(
4432 BrowsingContext* aStartingAt,
4433 const DispatchBeforeUnloadToSubtreeResolver& aResolver) {
4434 bool resolved = false;
4436 aStartingAt->PreOrderWalk([&](dom::BrowsingContext* aBC) {
4437 if (aBC->GetDocShell()) {
4438 nsCOMPtr<nsIDocumentViewer> viewer;
4439 aBC->GetDocShell()->GetDocViewer(getter_AddRefs(viewer));
4440 if (viewer &&
4441 viewer->DispatchBeforeUnload() ==
4442 nsIDocumentViewer::eRequestBlockNavigation &&
4443 !resolved) {
4444 // Send our response as soon as we find any blocker, so that we can show
4445 // the permit unload prompt as soon as possible, without giving
4446 // subsequent handlers a chance to delay it.
4447 aResolver(nsIDocumentViewer::eRequestBlockNavigation);
4448 resolved = true;
4453 if (!resolved) {
4454 aResolver(nsIDocumentViewer::eAllowNavigation);
4458 mozilla::ipc::IPCResult ContentChild::RecvGoBack(
4459 const MaybeDiscarded<BrowsingContext>& aContext,
4460 const Maybe<int32_t>& aCancelContentJSEpoch, bool aRequireUserInteraction,
4461 bool aUserActivation) {
4462 if (aContext.IsNullOrDiscarded()) {
4463 return IPC_OK();
4465 BrowsingContext* bc = aContext.get();
4467 if (RefPtr<nsDocShell> docShell = nsDocShell::Cast(bc->GetDocShell())) {
4468 if (aCancelContentJSEpoch) {
4469 docShell->SetCancelContentJSEpoch(*aCancelContentJSEpoch);
4471 docShell->GoBack(aRequireUserInteraction, aUserActivation);
4473 if (BrowserChild* browserChild = BrowserChild::GetFrom(docShell)) {
4474 browserChild->NotifyNavigationFinished();
4478 return IPC_OK();
4481 mozilla::ipc::IPCResult ContentChild::RecvGoForward(
4482 const MaybeDiscarded<BrowsingContext>& aContext,
4483 const Maybe<int32_t>& aCancelContentJSEpoch, bool aRequireUserInteraction,
4484 bool aUserActivation) {
4485 if (aContext.IsNullOrDiscarded()) {
4486 return IPC_OK();
4488 BrowsingContext* bc = aContext.get();
4490 if (RefPtr<nsDocShell> docShell = nsDocShell::Cast(bc->GetDocShell())) {
4491 if (aCancelContentJSEpoch) {
4492 docShell->SetCancelContentJSEpoch(*aCancelContentJSEpoch);
4494 docShell->GoForward(aRequireUserInteraction, aUserActivation);
4496 if (BrowserChild* browserChild = BrowserChild::GetFrom(docShell)) {
4497 browserChild->NotifyNavigationFinished();
4501 return IPC_OK();
4504 mozilla::ipc::IPCResult ContentChild::RecvGoToIndex(
4505 const MaybeDiscarded<BrowsingContext>& aContext, const int32_t& aIndex,
4506 const Maybe<int32_t>& aCancelContentJSEpoch, bool aUserActivation) {
4507 if (aContext.IsNullOrDiscarded()) {
4508 return IPC_OK();
4510 BrowsingContext* bc = aContext.get();
4512 if (RefPtr<nsDocShell> docShell = nsDocShell::Cast(bc->GetDocShell())) {
4513 if (aCancelContentJSEpoch) {
4514 docShell->SetCancelContentJSEpoch(*aCancelContentJSEpoch);
4516 docShell->GotoIndex(aIndex, aUserActivation);
4518 if (BrowserChild* browserChild = BrowserChild::GetFrom(docShell)) {
4519 browserChild->NotifyNavigationFinished();
4523 return IPC_OK();
4526 mozilla::ipc::IPCResult ContentChild::RecvReload(
4527 const MaybeDiscarded<BrowsingContext>& aContext,
4528 const uint32_t aReloadFlags) {
4529 if (aContext.IsNullOrDiscarded()) {
4530 return IPC_OK();
4532 BrowsingContext* bc = aContext.get();
4534 if (RefPtr<nsDocShell> docShell = nsDocShell::Cast(bc->GetDocShell())) {
4535 docShell->Reload(aReloadFlags);
4538 return IPC_OK();
4541 mozilla::ipc::IPCResult ContentChild::RecvStopLoad(
4542 const MaybeDiscarded<BrowsingContext>& aContext,
4543 const uint32_t aStopFlags) {
4544 if (aContext.IsNullOrDiscarded()) {
4545 return IPC_OK();
4547 BrowsingContext* bc = aContext.get();
4549 if (auto* docShell = nsDocShell::Cast(bc->GetDocShell())) {
4550 docShell->Stop(aStopFlags);
4553 return IPC_OK();
4556 #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
4557 mozilla::ipc::IPCResult ContentChild::RecvInitSandboxTesting(
4558 Endpoint<PSandboxTestingChild>&& aEndpoint) {
4559 if (!SandboxTestingChild::Initialize(std::move(aEndpoint))) {
4560 return IPC_FAIL(
4561 this, "InitSandboxTesting failed to initialise the child process.");
4563 return IPC_OK();
4565 #endif
4567 NS_IMETHODIMP ContentChild::GetChildID(uint64_t* aOut) {
4568 *aOut = mID;
4569 return NS_OK;
4572 NS_IMETHODIMP ContentChild::GetActor(const nsACString& aName, JSContext* aCx,
4573 JSProcessActorChild** retval) {
4574 ErrorResult error;
4575 RefPtr<JSProcessActorChild> actor =
4576 JSActorManager::GetActor(aCx, aName, error)
4577 .downcast<JSProcessActorChild>();
4578 if (error.MaybeSetPendingException(aCx)) {
4579 return NS_ERROR_FAILURE;
4581 actor.forget(retval);
4582 return NS_OK;
4585 NS_IMETHODIMP ContentChild::GetExistingActor(const nsACString& aName,
4586 JSProcessActorChild** retval) {
4587 RefPtr<JSProcessActorChild> actor =
4588 JSActorManager::GetExistingActor(aName).downcast<JSProcessActorChild>();
4589 actor.forget(retval);
4590 return NS_OK;
4593 already_AddRefed<JSActor> ContentChild::InitJSActor(
4594 JS::Handle<JSObject*> aMaybeActor, const nsACString& aName,
4595 ErrorResult& aRv) {
4596 RefPtr<JSProcessActorChild> actor;
4597 if (aMaybeActor.get()) {
4598 aRv = UNWRAP_OBJECT(JSProcessActorChild, aMaybeActor.get(), actor);
4599 if (aRv.Failed()) {
4600 return nullptr;
4602 } else {
4603 actor = new JSProcessActorChild();
4606 MOZ_RELEASE_ASSERT(!actor->Manager(),
4607 "mManager was already initialized once!");
4608 actor->Init(aName, this);
4609 return actor.forget();
4612 IPCResult ContentChild::RecvRawMessage(const JSActorMessageMeta& aMeta,
4613 const Maybe<ClonedMessageData>& aData,
4614 const Maybe<ClonedMessageData>& aStack) {
4615 Maybe<StructuredCloneData> data;
4616 if (aData) {
4617 data.emplace();
4618 data->BorrowFromClonedMessageData(*aData);
4620 Maybe<StructuredCloneData> stack;
4621 if (aStack) {
4622 stack.emplace();
4623 stack->BorrowFromClonedMessageData(*aStack);
4625 ReceiveRawMessage(aMeta, std::move(data), std::move(stack));
4626 return IPC_OK();
4629 NS_IMETHODIMP ContentChild::GetCanSend(bool* aCanSend) {
4630 *aCanSend = CanSend();
4631 return NS_OK;
4634 ContentChild* ContentChild::AsContentChild() { return this; }
4636 JSActorManager* ContentChild::AsJSActorManager() { return this; }
4638 IPCResult ContentChild::RecvFlushFOGData(FlushFOGDataResolver&& aResolver) {
4639 glean::FlushFOGData(std::move(aResolver));
4640 return IPC_OK();
4643 IPCResult ContentChild::RecvUpdateMediaCodecsSupported(
4644 RemoteDecodeIn aLocation, const media::MediaCodecsSupported& aSupported) {
4645 RemoteDecoderManagerChild::SetSupported(aLocation, aSupported);
4647 return IPC_OK();
4650 void ContentChild::ConfigureThreadPerformanceHints(
4651 const hal::ProcessPriority& aPriority) {
4652 if (aPriority >= hal::PROCESS_PRIORITY_FOREGROUND) {
4653 static bool canUsePerformanceHintSession = true;
4654 if (!mPerformanceHintSession && canUsePerformanceHintSession) {
4655 nsTArray<PlatformThreadHandle> threads;
4656 Servo_ThreadPool_GetThreadHandles(&threads);
4657 #ifdef XP_WIN
4658 threads.AppendElement(GetCurrentThread());
4659 #else
4660 threads.AppendElement(pthread_self());
4661 #endif
4663 mPerformanceHintSession = hal::CreatePerformanceHintSession(
4664 threads, GetPerformanceHintTarget(TimeDuration::FromMilliseconds(
4665 nsRefreshDriver::DefaultInterval())));
4667 // Avoid repeatedly attempting to create a session if it is not
4668 // supported.
4669 canUsePerformanceHintSession = mPerformanceHintSession != nullptr;
4672 #ifdef MOZ_WIDGET_ANDROID
4673 // On Android if we are unable to use PerformanceHintManager then fall back
4674 // to setting the stylo threads' affinities to the performant cores. Android
4675 // automatically sets each thread's affinity to all cores when a process is
4676 // foregrounded, and to a subset of cores when the process is backgrounded.
4677 // We must therefore override this each time the process is foregrounded,
4678 // but we don't have to do anything when backgrounded.
4679 if (!mPerformanceHintSession) {
4680 if (const auto& cpuInfo = hal::GetHeterogeneousCpuInfo()) {
4681 // If CPUs are homogeneous there is no point setting affinity.
4682 if (cpuInfo->mBigCpus.Count() != cpuInfo->mTotalNumCpus) {
4683 BitSet<hal::HeterogeneousCpuInfo::MAX_CPUS> cpus = cpuInfo->mBigCpus;
4684 if (cpus.Count() < 2) {
4685 // From testing on a variety of devices it appears using only the
4686 // big cores gives best performance when there are 2 or more big
4687 // cores. If there are fewer than 2 big cores then additionally
4688 // using the medium cores performs better.
4689 cpus |= cpuInfo->mMediumCpus;
4692 static_assert(
4693 hal::HeterogeneousCpuInfo::MAX_CPUS <= CPU_SETSIZE,
4694 "HeterogeneousCpuInfo::MAX_CPUS is too large for CPU_SETSIZE");
4696 cpu_set_t cpuset;
4697 CPU_ZERO(&cpuset);
4698 for (size_t i = 0; i < cpuInfo->mTotalNumCpus; i++) {
4699 if (cpus.Test(i)) {
4700 CPU_SET(i, &cpuset);
4704 // Only set the affinity for the stylo threads, not the main thread.
4705 // Testing showed no difference in performance between the two
4706 // options, and as newly spawned threads automatically inherit their
4707 // parent's affinity mask there may be unintended consequences to
4708 // setting the main thread affinity.
4709 nsTArray<PlatformThreadHandle> threads;
4710 Servo_ThreadPool_GetThreadHandles(&threads);
4711 for (pthread_t thread : threads) {
4712 int ret = sched_setaffinity(pthread_gettid_np(thread),
4713 sizeof(cpu_set_t), &cpuset);
4714 // Occasionally sched_setaffinity fails, presumably due to a race
4715 // between us receiving the process foreground signal and whatever
4716 // is responsible for restricting which processes can use certain
4717 // cores. Trying again in a runnable seems to do the trick, but if
4718 // that still fails it's not the end of the world.
4719 if (ret < 0) {
4720 NS_DispatchToCurrentThread(NS_NewRunnableFunction(
4721 "ContentChild::ConfigureThreadPerformanceHints",
4722 [threads = std::move(threads), cpuset] {
4723 for (pthread_t thread : threads) {
4724 sched_setaffinity(pthread_gettid_np(thread),
4725 sizeof(cpu_set_t), &cpuset);
4727 }));
4728 break;
4734 #endif
4735 } else {
4736 mPerformanceHintSession = nullptr;
4740 } // namespace dom
4742 #if defined(__OpenBSD__) && defined(MOZ_SANDBOX)
4744 static LazyLogModule sPledgeLog("OpenBSDSandbox");
4746 NS_IMETHODIMP
4747 OpenBSDFindPledgeUnveilFilePath(const char* file, nsACString& result) {
4748 struct stat st;
4750 // Allow overriding files in /etc/$MOZ_APP_NAME
4751 result.Assign(nsPrintfCString("/etc/%s/%s", MOZ_APP_NAME, file));
4752 if (stat(PromiseFlatCString(result).get(), &st) == 0) {
4753 return NS_OK;
4756 // Or look in the system default directory
4757 result.Assign(nsPrintfCString(
4758 "/usr/local/lib/%s/browser/defaults/preferences/%s", MOZ_APP_NAME, file));
4759 if (stat(PromiseFlatCString(result).get(), &st) == 0) {
4760 return NS_OK;
4763 errx(1, "can't locate %s", file);
4766 NS_IMETHODIMP
4767 OpenBSDPledgePromises(const nsACString& aPath) {
4768 // Using NS_LOCAL_FILE_CONTRACTID/NS_LOCALFILEINPUTSTREAM_CONTRACTID requires
4769 // a lot of setup before they are supported and we want to pledge early on
4770 // before all of that, so read the file directly
4771 std::ifstream input(PromiseFlatCString(aPath).get());
4773 // Build up one line of pledge promises without comments
4774 nsAutoCString promises;
4775 bool disabled = false;
4776 int linenum = 0;
4777 for (std::string tLine; std::getline(input, tLine);) {
4778 nsAutoCString line(tLine.c_str());
4779 linenum++;
4781 // Cut off any comments at the end of the line, also catches lines
4782 // that are entirely a comment
4783 int32_t hash = line.FindChar('#');
4784 if (hash >= 0) {
4785 line = Substring(line, 0, hash);
4787 line.CompressWhitespace(true, true);
4788 if (line.IsEmpty()) {
4789 continue;
4792 if (linenum == 1 && line.EqualsLiteral("disable")) {
4793 disabled = true;
4794 break;
4797 if (!promises.IsEmpty()) {
4798 promises.Append(" ");
4800 promises.Append(line);
4802 input.close();
4804 if (disabled) {
4805 warnx("%s: disabled", PromiseFlatCString(aPath).get());
4806 } else {
4807 MOZ_LOG(
4808 sPledgeLog, LogLevel::Debug,
4809 ("%s: pledge(%s)\n", PromiseFlatCString(aPath).get(), promises.get()));
4810 if (pledge(promises.get(), nullptr) != 0) {
4811 err(1, "%s: pledge(%s) failed", PromiseFlatCString(aPath).get(),
4812 promises.get());
4816 return NS_OK;
4819 void ExpandUnveilPath(nsAutoCString& path) {
4820 // Expand $XDG_RUNTIME_DIR to the environment variable, or ~/.cache
4821 nsCString xdgRuntimeDir(PR_GetEnv("XDG_RUNTIME_DIR"));
4822 if (xdgRuntimeDir.IsEmpty()) {
4823 xdgRuntimeDir = "~/.cache";
4825 path.ReplaceSubstring("$XDG_RUNTIME_DIR", xdgRuntimeDir.get());
4827 // Expand $XDG_CONFIG_HOME to the environment variable, or ~/.config
4828 nsCString xdgConfigHome(PR_GetEnv("XDG_CONFIG_HOME"));
4829 if (xdgConfigHome.IsEmpty()) {
4830 xdgConfigHome = "~/.config";
4832 path.ReplaceSubstring("$XDG_CONFIG_HOME", xdgConfigHome.get());
4834 // Expand $XDG_CACHE_HOME to the environment variable, or ~/.cache
4835 nsCString xdgCacheHome(PR_GetEnv("XDG_CACHE_HOME"));
4836 if (xdgCacheHome.IsEmpty()) {
4837 xdgCacheHome = "~/.cache";
4839 path.ReplaceSubstring("$XDG_CACHE_HOME", xdgCacheHome.get());
4841 // Expand $XDG_DATA_HOME to the environment variable, or ~/.local/share
4842 nsCString xdgDataHome(PR_GetEnv("XDG_DATA_HOME"));
4843 if (xdgDataHome.IsEmpty()) {
4844 xdgDataHome = "~/.local/share";
4846 path.ReplaceSubstring("$XDG_DATA_HOME", xdgDataHome.get());
4848 // Expand leading ~ to the user's home directory
4849 nsCOMPtr<nsIFile> homeDir;
4850 nsresult rv =
4851 GetSpecialSystemDirectory(Unix_HomeDirectory, getter_AddRefs(homeDir));
4852 if (NS_FAILED(rv)) {
4853 errx(1, "failed getting home directory");
4855 if (path.FindChar('~') == 0) {
4856 nsCString tHome(homeDir->NativePath());
4857 tHome.Append(Substring(path, 1, path.Length() - 1));
4858 path = tHome.get();
4862 void MkdirP(nsAutoCString& path) {
4863 // nsLocalFile::CreateAllAncestors would be nice to use
4865 nsAutoCString tPath("");
4866 for (const nsACString& dir : path.Split('/')) {
4867 struct stat st;
4869 if (dir.IsEmpty()) {
4870 continue;
4873 tPath.Append("/");
4874 tPath.Append(dir);
4876 if (stat(tPath.get(), &st) == -1) {
4877 if (mkdir(tPath.get(), 0700) == -1) {
4878 err(1, "failed mkdir(%s) while MkdirP(%s)",
4879 PromiseFlatCString(tPath).get(), PromiseFlatCString(path).get());
4885 NS_IMETHODIMP
4886 OpenBSDUnveilPaths(const nsACString& uPath, const nsACString& pledgePath) {
4887 // Using NS_LOCAL_FILE_CONTRACTID/NS_LOCALFILEINPUTSTREAM_CONTRACTID requires
4888 // a lot of setup before they are allowed/supported and we want to pledge and
4889 // unveil early on before all of that is setup
4890 std::ifstream input(PromiseFlatCString(uPath).get());
4892 bool disabled = false;
4893 int linenum = 0;
4894 for (std::string tLine; std::getline(input, tLine);) {
4895 nsAutoCString line(tLine.c_str());
4896 linenum++;
4898 // Cut off any comments at the end of the line, also catches lines
4899 // that are entirely a comment
4900 int32_t hash = line.FindChar('#');
4901 if (hash >= 0) {
4902 line = Substring(line, 0, hash);
4904 line.CompressWhitespace(true, true);
4905 if (line.IsEmpty()) {
4906 continue;
4909 if (linenum == 1 && line.EqualsLiteral("disable")) {
4910 disabled = true;
4911 break;
4914 int32_t space = line.FindChar(' ');
4915 if (space <= 0) {
4916 errx(1, "%s: line %d: invalid format", PromiseFlatCString(uPath).get(),
4917 linenum);
4920 nsAutoCString uPath(Substring(line, 0, space));
4921 ExpandUnveilPath(uPath);
4923 nsAutoCString perms(Substring(line, space + 1, line.Length() - space - 1));
4925 MOZ_LOG(sPledgeLog, LogLevel::Debug,
4926 ("%s: unveil(%s, %s)\n", PromiseFlatCString(uPath).get(),
4927 uPath.get(), perms.get()));
4928 if (unveil(uPath.get(), perms.get()) == -1 && errno != ENOENT) {
4929 err(1, "%s: unveil(%s, %s) failed", PromiseFlatCString(uPath).get(),
4930 uPath.get(), perms.get());
4933 input.close();
4935 if (disabled) {
4936 warnx("%s: disabled", PromiseFlatCString(uPath).get());
4937 } else {
4938 struct stat st;
4940 // Only unveil the pledgePath file if it's not already unveiled, otherwise
4941 // some containing directory will lose visibility.
4942 if (stat(PromiseFlatCString(pledgePath).get(), &st) == -1) {
4943 if (errno == ENOENT) {
4944 if (unveil(PromiseFlatCString(pledgePath).get(), "r") == -1) {
4945 err(1, "unveil(%s, r) failed", PromiseFlatCString(pledgePath).get());
4947 } else {
4948 err(1, "stat(%s)", PromiseFlatCString(pledgePath).get());
4953 return NS_OK;
4956 bool StartOpenBSDSandbox(GeckoProcessType type, ipc::SandboxingKind kind) {
4957 nsAutoCString pledgeFile;
4958 nsAutoCString unveilFile;
4959 char binaryPath[MAXPATHLEN];
4961 switch (type) {
4962 case GeckoProcessType_Default: {
4963 OpenBSDFindPledgeUnveilFilePath("pledge.main", pledgeFile);
4964 OpenBSDFindPledgeUnveilFilePath("unveil.main", unveilFile);
4966 // Ensure dconf dir exists before we veil the filesystem
4967 nsAutoCString dConf("$XDG_RUNTIME_DIR/dconf");
4968 ExpandUnveilPath(dConf);
4969 MkdirP(dConf);
4970 break;
4973 case GeckoProcessType_Content:
4974 OpenBSDFindPledgeUnveilFilePath("pledge.content", pledgeFile);
4975 OpenBSDFindPledgeUnveilFilePath("unveil.content", unveilFile);
4976 break;
4978 case GeckoProcessType_GPU:
4979 OpenBSDFindPledgeUnveilFilePath("pledge.gpu", pledgeFile);
4980 OpenBSDFindPledgeUnveilFilePath("unveil.gpu", unveilFile);
4981 break;
4983 case GeckoProcessType_Socket:
4984 OpenBSDFindPledgeUnveilFilePath("pledge.socket", pledgeFile);
4985 OpenBSDFindPledgeUnveilFilePath("unveil.socket", unveilFile);
4986 break;
4988 case GeckoProcessType_RDD:
4989 OpenBSDFindPledgeUnveilFilePath("pledge.rdd", pledgeFile);
4990 OpenBSDFindPledgeUnveilFilePath("unveil.rdd", unveilFile);
4991 break;
4993 case GeckoProcessType_Utility: {
4994 MOZ_RELEASE_ASSERT(kind <= SandboxingKind::COUNT,
4995 "Should define a sandbox");
4996 switch (kind) {
4997 case ipc::SandboxingKind::GENERIC_UTILITY:
4998 default:
4999 OpenBSDFindPledgeUnveilFilePath("pledge.utility", pledgeFile);
5000 OpenBSDFindPledgeUnveilFilePath("unveil.utility", unveilFile);
5001 break;
5003 } break;
5005 default:
5006 MOZ_ASSERT(false, "unknown process type");
5007 return false;
5010 nsresult rv = mozilla::BinaryPath::Get(binaryPath);
5011 if (NS_FAILED(rv)) {
5012 errx(1, "failed to cache binary path ?");
5015 if (NS_WARN_IF(NS_FAILED(OpenBSDUnveilPaths(unveilFile, pledgeFile)))) {
5016 errx(1, "failed reading/parsing %s", unveilFile.get());
5019 if (NS_WARN_IF(NS_FAILED(OpenBSDPledgePromises(pledgeFile)))) {
5020 errx(1, "failed reading/parsing %s", pledgeFile.get());
5023 // Don't overwrite an existing session dbus address, but ensure it is set
5024 if (!PR_GetEnv("DBUS_SESSION_BUS_ADDRESS")) {
5025 PR_SetEnv("DBUS_SESSION_BUS_ADDRESS=");
5028 return true;
5030 #endif
5032 } // namespace mozilla
5034 /* static */
5035 nsIDOMProcessChild* nsIDOMProcessChild::GetSingleton() {
5036 if (XRE_IsContentProcess()) {
5037 return mozilla::dom::ContentChild::GetSingleton();
5039 return mozilla::dom::InProcessChild::Singleton();