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 #include "mozilla/AppShutdown.h"
8 #include "mozilla/DebugOnly.h"
10 #include "base/basictypes.h"
11 #include "base/shared_memory.h"
13 #include "ContentParent.h"
14 #include "mozilla/ipc/ProcessUtils.h"
15 #include "mozilla/CmdLineAndEnvUtils.h"
16 #include "BrowserParent.h"
18 #include "chrome/common/process_watcher.h"
19 #include "mozilla/Result.h"
20 #include "mozilla/Services.h"
21 #include "mozilla/XREAppData.h"
22 #include "nsComponentManagerUtils.h"
23 #include "nsIBrowserDOMWindow.h"
24 #include "nsIPrivateAttributionService.h"
26 #include "GMPServiceParent.h"
27 #include "HandlerServiceParent.h"
32 #include "ContentProcessManager.h"
33 #include "GeckoProfiler.h"
34 #include "Geolocation.h"
35 #include "GfxInfoBase.h"
36 #include "MMPrinter.h"
37 #include "PreallocatedProcessManager.h"
38 #include "ProcessPriorityManager.h"
39 #include "ProfilerParent.h"
40 #include "SandboxHal.h"
41 #include "SourceSurfaceRawData.h"
42 #include "mozilla/ipc/URIUtils.h"
43 #include "gfxPlatform.h"
44 #include "gfxPlatformFontList.h"
45 #include "nsDNSService2.h"
46 #include "nsPIDNSService.h"
47 #include "mozilla/AntiTrackingUtils.h"
48 #include "mozilla/AppShutdown.h"
49 #include "mozilla/AutoRestore.h"
50 #include "mozilla/BasePrincipal.h"
51 #include "mozilla/BenchmarkStorageParent.h"
52 #include "mozilla/Casting.h"
53 #include "mozilla/ClearOnShutdown.h"
54 #include "mozilla/ClipboardReadRequestParent.h"
55 #include "mozilla/ClipboardWriteRequestParent.h"
56 #include "mozilla/ContentBlockingUserInteraction.h"
57 #include "mozilla/FOGIPC.h"
58 #include "mozilla/GlobalStyleSheetCache.h"
59 #include "mozilla/GeckoArgs.h"
60 #include "mozilla/HangDetails.h"
61 #include "mozilla/LookAndFeel.h"
62 #include "mozilla/Maybe.h"
63 #include "mozilla/NullPrincipal.h"
64 #include "mozilla/Preferences.h"
65 #include "mozilla/PresShell.h"
66 #include "mozilla/ProcessHangMonitor.h"
67 #include "mozilla/ProcessHangMonitorIPC.h"
68 #include "mozilla/ProfilerLabels.h"
69 #include "mozilla/ProfilerMarkers.h"
70 #include "mozilla/RecursiveMutex.h"
71 #include "mozilla/ScopeExit.h"
72 #include "mozilla/ScriptPreloader.h"
73 #include "mozilla/Components.h"
74 #include "mozilla/Sprintf.h"
75 #include "mozilla/StaticPrefs_dom.h"
76 #include "mozilla/StaticPrefs_fission.h"
77 #include "mozilla/StaticPrefs_media.h"
78 #include "mozilla/StaticPrefs_network.h"
79 #include "mozilla/StaticPrefs_threads.h"
80 #include "mozilla/StaticPrefs_widget.h"
81 #include "mozilla/StorageAccessAPIHelper.h"
82 #include "mozilla/StyleSheet.h"
83 #include "mozilla/StyleSheetInlines.h"
84 #include "mozilla/TaskController.h"
85 #include "mozilla/Telemetry.h"
86 #include "mozilla/TelemetryIPC.h"
87 #include "mozilla/ThreadSafety.h"
88 #include "mozilla/Unused.h"
89 #include "mozilla/WebBrowserPersistDocumentParent.h"
90 #include "mozilla/devtools/HeapSnapshotTempFileHelperParent.h"
91 #include "mozilla/dom/BlobURLProtocolHandler.h"
92 #include "mozilla/dom/BrowserHost.h"
93 #include "mozilla/dom/BrowsingContext.h"
94 #include "mozilla/dom/BrowsingContextGroup.h"
95 #include "mozilla/dom/CancelContentJSOptionsBinding.h"
96 #include "mozilla/dom/CanonicalBrowsingContext.h"
97 #include "mozilla/dom/ClientManager.h"
98 #include "mozilla/dom/ContentChild.h"
99 #include "mozilla/dom/DataTransfer.h"
100 #include "mozilla/dom/Document.h"
101 #include "mozilla/dom/Element.h"
102 #include "mozilla/dom/ExternalHelperAppParent.h"
103 #include "mozilla/dom/File.h"
104 #include "mozilla/dom/FileSystemSecurity.h"
105 #include "mozilla/dom/GeolocationBinding.h"
106 #include "mozilla/dom/GeolocationPositionError.h"
107 #include "mozilla/dom/GetFilesHelper.h"
108 #include "mozilla/dom/IPCBlobUtils.h"
109 #include "mozilla/dom/JSActorService.h"
110 #include "mozilla/dom/JSProcessActorBinding.h"
111 #include "mozilla/dom/LocalStorageCommon.h"
112 #include "mozilla/dom/MediaController.h"
113 #include "mozilla/dom/MemoryReportRequest.h"
114 #include "mozilla/dom/MediaStatusManager.h"
115 #include "mozilla/dom/Notification.h"
116 #include "mozilla/dom/PContentPermissionRequestParent.h"
117 #include "mozilla/dom/PCycleCollectWithLogsParent.h"
118 #include "mozilla/dom/ParentProcessMessageManager.h"
119 #include "mozilla/dom/Permissions.h"
120 #include "mozilla/dom/ProcessMessageManager.h"
121 #include "mozilla/dom/PushNotifier.h"
122 #include "mozilla/dom/RemoteWorkerServiceParent.h"
123 #include "mozilla/dom/ServiceWorkerManager.h"
124 #include "mozilla/dom/ServiceWorkerRegistrar.h"
125 #include "mozilla/dom/ServiceWorkerUtils.h"
126 #include "mozilla/dom/SessionHistoryEntry.h"
127 #include "mozilla/dom/SessionStorageManager.h"
128 #include "mozilla/dom/StorageIPC.h"
129 #include "mozilla/dom/UserActivation.h"
130 #include "mozilla/dom/URLClassifierParent.h"
131 #include "mozilla/dom/WindowGlobalParent.h"
132 #include "mozilla/dom/ipc/SharedMap.h"
133 #include "mozilla/dom/ipc/StructuredCloneData.h"
134 #include "mozilla/dom/nsMixedContentBlocker.h"
135 #include "mozilla/dom/power/PowerManagerService.h"
136 #include "mozilla/dom/quota/QuotaManagerService.h"
137 #include "mozilla/extensions/ExtensionsParent.h"
138 #include "mozilla/extensions/StreamFilterParent.h"
139 #include "mozilla/gfx/GPUProcessManager.h"
140 #include "mozilla/gfx/gfxVars.h"
141 #include "mozilla/glean/GleanPings.h"
142 #include "mozilla/hal_sandbox/PHalParent.h"
143 #include "mozilla/intl/L10nRegistry.h"
144 #include "mozilla/intl/LocaleService.h"
145 #include "mozilla/ipc/BackgroundChild.h"
146 #include "mozilla/ipc/BackgroundParent.h"
147 #include "mozilla/ipc/ByteBuf.h"
148 #include "mozilla/ipc/CrashReporterHost.h"
149 #include "mozilla/ipc/Endpoint.h"
150 #include "mozilla/ipc/FileDescriptorUtils.h"
151 #include "mozilla/ipc/IPCStreamUtils.h"
152 #include "mozilla/ipc/TestShellParent.h"
153 #include "mozilla/layers/CompositorThread.h"
154 #include "mozilla/layers/ImageBridgeParent.h"
155 #include "mozilla/layers/LayerTreeOwnerTracker.h"
156 #include "mozilla/layers/PAPZParent.h"
157 #include "mozilla/loader/ScriptCacheActors.h"
158 #include "mozilla/media/MediaParent.h"
159 #include "mozilla/mozSpellChecker.h"
160 #include "mozilla/net/CookieServiceParent.h"
161 #include "mozilla/net/NeckoMessageUtils.h"
162 #include "mozilla/net/NeckoParent.h"
163 #include "mozilla/net/PCookieServiceParent.h"
164 #include "mozilla/net/CookieKey.h"
165 #include "mozilla/net/TRRService.h"
166 #include "mozilla/TelemetryComms.h"
167 #include "mozilla/TelemetryEventEnums.h"
168 #include "mozilla/RemoteLazyInputStreamParent.h"
169 #include "mozilla/widget/RemoteLookAndFeel.h"
170 #include "mozilla/widget/ScreenManager.h"
171 #include "mozilla/widget/TextRecognition.h"
172 #include "nsAnonymousTemporaryFile.h"
173 #include "nsAppRunner.h"
174 #include "nsCExternalHandlerService.h"
175 #include "nsCOMPtr.h"
176 #include "nsChromeRegistryChrome.h"
177 #include "nsConsoleMessage.h"
178 #include "nsConsoleService.h"
179 #include "nsContentPermissionHelper.h"
180 #include "nsContentUtils.h"
182 #include "nsDebugImpl.h"
183 #include "nsDirectoryServiceDefs.h"
184 #include "nsDocShell.h"
185 #include "nsEmbedCID.h"
186 #include "nsFocusManager.h"
187 #include "nsFrameLoader.h"
188 #include "nsFrameMessageManager.h"
189 #include "nsGlobalWindowOuter.h"
190 #include "nsHashPropertyBag.h"
191 #include "nsHyphenationManager.h"
192 #include "nsIAlertsService.h"
193 #include "nsIAppShell.h"
194 #include "nsIAppWindow.h"
195 #include "nsIAsyncInputStream.h"
196 #include "nsIBidiKeyboard.h"
197 #include "nsICaptivePortalService.h"
198 #include "nsICertOverrideService.h"
199 #include "nsIClipboard.h"
200 #include "nsIContentAnalysis.h"
201 #include "nsIContentSecurityPolicy.h"
202 #include "nsICookie.h"
203 #include "nsICrashService.h"
204 #include "nsICycleCollectorListener.h"
205 #include "nsIDocShell.h"
206 #include "nsIDocShellTreeOwner.h"
207 #include "nsIDragService.h"
208 #include "nsIExternalProtocolService.h"
209 #include "nsIGfxInfo.h"
210 #include "nsIUserIdleService.h"
211 #include "nsIInterfaceRequestorUtils.h"
212 #include "nsILocalStorageManager.h"
213 #include "nsIMemoryInfoDumper.h"
214 #include "nsIMemoryReporter.h"
215 #include "nsINetworkLinkService.h"
216 #include "nsIObserverService.h"
217 #include "nsIParentChannel.h"
218 #include "nsIScriptError.h"
219 #include "nsIScriptSecurityManager.h"
220 #include "nsIServiceWorkerManager.h"
221 #include "nsISiteSecurityService.h"
222 #include "nsIStringBundle.h"
223 #include "nsITimer.h"
225 #include "nsIWebBrowserChrome.h"
226 #include "nsIX509Cert.h"
227 #include "nsIXULRuntime.h"
228 #include "nsICookieNotification.h"
229 #if defined(MOZ_WIDGET_GTK) || defined(XP_WIN)
230 # include "nsIconChannel.h"
232 #include "nsMemoryInfoDumper.h"
233 #include "nsMemoryReporterManager.h"
234 #include "nsOpenURIInFrameParams.h"
235 #include "nsPIWindowWatcher.h"
236 #include "nsQueryObject.h"
237 #include "nsReadableUtils.h"
238 #include "nsSHistory.h"
239 #include "nsScriptError.h"
240 #include "nsServiceManagerUtils.h"
241 #include "nsStreamUtils.h"
242 #include "nsStyleSheetService.h"
243 #include "nsThread.h"
244 #include "nsThreadUtils.h"
245 #include "nsWidgetsCID.h"
246 #include "nsWindowWatcher.h"
249 #include "private/pprio.h"
250 #include "xpcpublic.h"
251 #include "nsOpenWindowInfo.h"
252 #include "nsFrameLoaderOwner.h"
255 # include "jsapi/WebrtcGlobalParent.h"
258 #if defined(XP_MACOSX)
259 # include "nsMacUtilsImpl.h"
260 # include "mozilla/AvailableMemoryWatcher.h"
263 #if defined(ANDROID) || defined(LINUX)
264 # include "nsSystemInfo.h"
267 #if defined(XP_LINUX)
268 # include "mozilla/Hal.h"
272 # include "gfxAndroidPlatform.h"
275 #include "mozilla/PermissionManager.h"
277 #ifdef MOZ_WIDGET_ANDROID
278 # include "AndroidBridge.h"
279 # include "mozilla/java/GeckoProcessManagerWrappers.h"
280 # include "mozilla/java/GeckoProcessTypeWrappers.h"
283 #ifdef MOZ_WIDGET_GTK
284 # include <gdk/gdk.h>
285 # include "mozilla/WidgetUtilsGtk.h"
288 #include "mozilla/RemoteSpellCheckEngineParent.h"
293 # include "mozilla/dom/SpeechSynthesisParent.h"
296 #if defined(MOZ_SANDBOX)
297 # include "mozilla/SandboxSettings.h"
298 # if defined(XP_LINUX)
299 # include "mozilla/SandboxInfo.h"
300 # include "mozilla/SandboxBroker.h"
301 # include "mozilla/SandboxBrokerPolicyFactory.h"
303 # if defined(XP_MACOSX)
304 # include "mozilla/Sandbox.h"
309 # include "mozilla/widget/AudioSession.h"
310 # include "mozilla/WinDllServices.h"
313 #ifdef MOZ_CODE_COVERAGE
314 # include "mozilla/CodeCoverageHandler.h"
317 #ifdef FUZZING_SNAPSHOT
318 # include "mozilla/fuzzing/IPCFuzzController.h"
321 #ifdef ENABLE_WEBDRIVER
322 # include "nsIMarionette.h"
323 # include "nsIRemoteAgent.h"
326 // For VP9Benchmark::sBenchmarkFpsPref
327 #include "Benchmark.h"
329 #include "mozilla/RemoteDecodeUtils.h"
330 #include "nsIToolkitProfileService.h"
331 #include "nsIToolkitProfile.h"
333 static NS_DEFINE_CID(kCClipboardCID
, NS_CLIPBOARD_CID
);
335 using base::KillProcess
;
337 using namespace CrashReporter
;
338 using namespace mozilla::dom::power
;
339 using namespace mozilla::media
;
340 using namespace mozilla::embedding
;
341 using namespace mozilla::gfx
;
342 using namespace mozilla::gmp
;
343 using namespace mozilla::hal
;
344 using namespace mozilla::ipc
;
345 using namespace mozilla::intl
;
346 using namespace mozilla::layers
;
347 using namespace mozilla::layout
;
348 using namespace mozilla::net
;
349 using namespace mozilla::psm
;
350 using namespace mozilla::widget
;
351 using namespace mozilla::Telemetry
;
352 using mozilla::loader::PScriptCacheParent
;
353 using mozilla::Telemetry::ProcessID
;
355 extern mozilla::LazyLogModule gFocusLog
;
357 #define LOGFOCUS(args) MOZ_LOG(gFocusLog, mozilla::LogLevel::Debug, args)
359 extern mozilla::LazyLogModule sPDMLog
;
360 #define LOGPDM(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
363 namespace CubebUtils
{
364 extern FileDescriptor
CreateAudioIPCConnection();
369 LazyLogModule
gProcessLog("Process");
371 static std::map
<RemoteDecodeIn
, media::MediaCodecsSupported
> sCodecsSupported
;
374 uint32_t ContentParent::sMaxContentProcesses
= 0;
377 LogModule
* ContentParent::GetLog() { return gProcessLog
; }
380 uint32_t ContentParent::sPageLoadEventCounter
= 0;
382 #define NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC "ipc:network:set-offline"
383 #define NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC "ipc:network:set-connectivity"
385 // IPC receiver for remote GC/CC logging.
386 class CycleCollectWithLogsParent final
: public PCycleCollectWithLogsParent
{
388 MOZ_COUNTED_DTOR(CycleCollectWithLogsParent
)
390 static bool AllocAndSendConstructor(ContentParent
* aManager
,
392 nsICycleCollectorLogSink
* aSink
,
393 nsIDumpGCAndCCLogsCallback
* aCallback
) {
394 CycleCollectWithLogsParent
* actor
;
399 actor
= new CycleCollectWithLogsParent(aSink
, aCallback
);
400 rv
= actor
->mSink
->Open(&gcLog
, &ccLog
);
401 if (NS_WARN_IF(NS_FAILED(rv
))) {
406 return aManager
->SendPCycleCollectWithLogsConstructor(
407 actor
, aDumpAllTraces
, FILEToFileDescriptor(gcLog
),
408 FILEToFileDescriptor(ccLog
));
412 virtual mozilla::ipc::IPCResult
RecvCloseGCLog() override
{
413 Unused
<< mSink
->CloseGCLog();
417 virtual mozilla::ipc::IPCResult
RecvCloseCCLog() override
{
418 Unused
<< mSink
->CloseCCLog();
422 virtual mozilla::ipc::IPCResult
Recv__delete__() override
{
423 // Report completion to mCallback only on successful
424 // completion of the protocol.
425 nsCOMPtr
<nsIFile
> gcLog
, ccLog
;
426 mSink
->GetGcLog(getter_AddRefs(gcLog
));
427 mSink
->GetCcLog(getter_AddRefs(ccLog
));
428 Unused
<< mCallback
->OnDump(gcLog
, ccLog
, /* parent = */ false);
432 virtual void ActorDestroy(ActorDestroyReason aReason
) override
{
433 // If the actor is unexpectedly destroyed, we deliberately
434 // don't call Close[GC]CLog on the sink, because the logs may
435 // be incomplete. See also the nsCycleCollectorLogSinkToFile
436 // implementaiton of those methods, and its destructor.
439 CycleCollectWithLogsParent(nsICycleCollectorLogSink
* aSink
,
440 nsIDumpGCAndCCLogsCallback
* aCallback
)
441 : mSink(aSink
), mCallback(aCallback
) {
442 MOZ_COUNT_CTOR(CycleCollectWithLogsParent
);
445 nsCOMPtr
<nsICycleCollectorLogSink
> mSink
;
446 nsCOMPtr
<nsIDumpGCAndCCLogsCallback
> mCallback
;
449 // A memory reporter for ContentParent objects themselves.
450 class ContentParentsMemoryReporter final
: public nsIMemoryReporter
{
451 ~ContentParentsMemoryReporter() = default;
455 NS_DECL_NSIMEMORYREPORTER
458 NS_IMPL_ISUPPORTS(ContentParentsMemoryReporter
, nsIMemoryReporter
)
461 ContentParentsMemoryReporter::CollectReports(
462 nsIHandleReportCallback
* aHandleReport
, nsISupports
* aData
,
464 AutoTArray
<ContentParent
*, 16> cps
;
465 ContentParent::GetAllEvenIfDead(cps
);
467 for (uint32_t i
= 0; i
< cps
.Length(); i
++) {
468 ContentParent
* cp
= cps
[i
];
469 MessageChannel
* channel
= cp
->GetIPCChannel();
471 nsString friendlyName
;
472 cp
->FriendlyName(friendlyName
, aAnonymize
);
475 nsrefcnt refcnt
= cp
->Release();
477 const char* channelStr
= "no channel";
478 uint32_t numQueuedMessages
= 0;
480 if (channel
->IsClosed()) {
481 channelStr
= "closed channel";
483 channelStr
= "open channel";
486 0; // XXX was channel->Unsound_NumQueuedMessages(); Bug 1754876
489 nsPrintfCString
path(
490 "queued-ipc-messages/content-parent"
491 "(%s, pid=%d, %s, 0x%p, refcnt=%" PRIuPTR
")",
492 NS_ConvertUTF16toUTF8(friendlyName
).get(), cp
->Pid(), channelStr
,
493 static_cast<nsIObserver
*>(cp
), refcnt
);
495 constexpr auto desc
=
496 "The number of unset IPC messages held in this ContentParent's "
497 "channel. A large value here might indicate that we're leaking "
498 "messages. Similarly, a ContentParent object for a process that's no "
499 "longer running could indicate that we're leaking ContentParents."_ns
;
501 aHandleReport
->Callback(/* process */ ""_ns
, path
, KIND_OTHER
, UNITS_COUNT
,
502 numQueuedMessages
, desc
, aData
);
508 // A hashtable (by type) of processes/ContentParents. This includes
509 // processes that are in the Preallocator cache (which would be type
510 // 'prealloc'), and recycled processes ('web' and in the future
511 // eTLD+1-locked) processes).
512 nsClassHashtable
<nsCStringHashKey
, nsTArray
<ContentParent
*>>*
513 ContentParent::sBrowserContentParents
;
517 uint64_t ComputeLoadedOriginHash(nsIPrincipal
* aPrincipal
) {
518 uint32_t originNoSuffix
=
519 BasePrincipal::Cast(aPrincipal
)->GetOriginNoSuffixHash();
520 uint32_t originSuffix
=
521 BasePrincipal::Cast(aPrincipal
)->GetOriginSuffixHash();
523 return ((uint64_t)originNoSuffix
) << 32 | originSuffix
;
526 ProcessID
GetTelemetryProcessID(const nsACString
& remoteType
) {
527 // OOP WebExtensions run in a content process.
528 // For Telemetry though we want to break out collected data from the
529 // WebExtensions process into a separate bucket, to make sure we can analyze
530 // it separately and avoid skewing normal content process metrics.
531 return remoteType
== EXTENSION_REMOTE_TYPE
? ProcessID::Extension
532 : ProcessID::Content
;
535 } // anonymous namespace
537 StaticAutoPtr
<LinkedList
<ContentParent
>> ContentParent::sContentParents
;
538 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
539 StaticAutoPtr
<SandboxBrokerPolicyFactory
>
540 ContentParent::sSandboxBrokerPolicyFactory
;
542 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
543 StaticAutoPtr
<std::vector
<std::string
>> ContentParent::sMacSandboxParams
;
546 // Set to true when the first content process gets created.
547 static bool sCreatedFirstContentProcess
= false;
549 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
550 // True when we're running the process selection code, and do not expect to
551 // enter code paths where processes may die.
552 static bool sInProcessSelector
= false;
555 // The first content child has ID 1, so the chrome process can have ID 0.
556 static uint64_t gContentChildID
= 1;
558 static const char* sObserverTopics
[] = {
559 NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC
,
560 NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC
,
561 NS_IPC_CAPTIVE_PORTAL_SET_STATE
,
562 "application-background",
563 "application-foreground",
568 "child-ghost-request",
569 "last-pb-context-exited",
570 "file-watcher-update",
572 "a11y-init-or-shutdown",
574 "cacheservice:empty-cache",
575 "intl:app-locales-changed",
576 "intl:requested-locales-changed",
578 "private-cookie-changed",
579 NS_NETWORK_LINK_TYPE_TOPIC
,
580 NS_NETWORK_TRR_MODE_CHANGED_TOPIC
,
581 "network:socket-process-crashed",
582 DEFAULT_TIMEZONE_CHANGED_OBSERVER_TOPIC
,
585 void ContentParent_NotifyUpdatedDictionaries() {
586 ContentParent::NotifyUpdatedDictionaries();
589 // PreallocateProcess is called by the PreallocatedProcessManager.
590 // ContentParent then takes this process back within GetNewOrUsedBrowserProcess.
591 /*static*/ UniqueContentParentKeepAlive
ContentParent::MakePreallocProcess() {
592 RefPtr
<ContentParent
> process
= new ContentParent(PREALLOC_REMOTE_TYPE
);
593 if (NS_WARN_IF(!process
->BeginSubprocessLaunch(PROCESS_PRIORITY_PREALLOC
))) {
594 process
->LaunchSubprocessReject();
597 return process
->AddKeepAlive(/* aBrowserId */ 0);
601 void ContentParent::StartUp() {
602 // FIXME Bug 1023701 - Stop using ContentParent static methods in
604 if (!XRE_IsParentProcess()) {
608 // From this point on, NS_WARNING, NS_ASSERTION, etc. should print out the
609 // PID along with the warning.
610 nsDebugImpl::SetMultiprocessMode("Parent");
612 // Note: This reporter measures all ContentParents.
613 RegisterStrongMemoryReporter(new ContentParentsMemoryReporter());
615 BackgroundChild::Startup();
616 ClientManager::Startup();
618 Preferences::RegisterCallbackAndCall(&OnFissionBlocklistPrefChange
,
619 kFissionEnforceBlockList
);
620 Preferences::RegisterCallbackAndCall(&OnFissionBlocklistPrefChange
,
621 kFissionOmitBlockListValues
);
623 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
624 sSandboxBrokerPolicyFactory
= new SandboxBrokerPolicyFactory();
627 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
628 sMacSandboxParams
= new std::vector
<std::string
>();
633 void ContentParent::ShutDown() {
634 // For the most, we rely on normal process shutdown and
635 // ClearOnShutdown() to clean up our state.
637 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
638 sSandboxBrokerPolicyFactory
= nullptr;
641 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
642 sMacSandboxParams
= nullptr;
647 uint32_t ContentParent::GetPoolSize(const nsACString
& aContentProcessType
) {
648 if (!sBrowserContentParents
) {
652 nsTArray
<ContentParent
*>* parents
=
653 sBrowserContentParents
->Get(aContentProcessType
);
655 return parents
? parents
->Length() : 0;
658 /*static*/ nsTArray
<ContentParent
*>& ContentParent::GetOrCreatePool(
659 const nsACString
& aContentProcessType
) {
660 if (!sBrowserContentParents
) {
661 sBrowserContentParents
=
662 new nsClassHashtable
<nsCStringHashKey
, nsTArray
<ContentParent
*>>;
665 return *sBrowserContentParents
->GetOrInsertNew(aContentProcessType
);
668 nsDependentCSubstring
RemoteTypePrefix(const nsACString
& aContentProcessType
) {
669 // The suffix after a `=` in a remoteType is dynamic, and used to control the
670 // process pool to use.
671 int32_t equalIdx
= aContentProcessType
.FindChar(L
'=');
672 if (equalIdx
== kNotFound
) {
673 equalIdx
= aContentProcessType
.Length();
675 return StringHead(aContentProcessType
, equalIdx
);
678 bool IsWebRemoteType(const nsACString
& aContentProcessType
) {
679 // Note: matches webIsolated, web, and webCOOP+COEP types.
680 return StringBeginsWith(aContentProcessType
, DEFAULT_REMOTE_TYPE
);
683 bool IsWebCoopCoepRemoteType(const nsACString
& aContentProcessType
) {
684 return StringBeginsWith(aContentProcessType
,
685 WITH_COOP_COEP_REMOTE_TYPE_PREFIX
);
688 bool IsExtensionRemoteType(const nsACString
& aContentProcessType
) {
689 return aContentProcessType
== EXTENSION_REMOTE_TYPE
;
693 uint32_t ContentParent::GetMaxProcessCount(
694 const nsACString
& aContentProcessType
) {
695 // Max process count is based only on the prefix.
696 const nsDependentCSubstring processTypePrefix
=
697 RemoteTypePrefix(aContentProcessType
);
699 // Check for the default remote type of "web", as it uses different prefs.
700 if (processTypePrefix
== DEFAULT_REMOTE_TYPE
) {
701 return GetMaxWebProcessCount();
704 // Read the pref controling this remote type. `dom.ipc.processCount` is not
705 // used as a fallback, as it is intended to control the number of "web"
706 // content processes, checked in `mozilla::GetMaxWebProcessCount()`.
707 nsAutoCString
processCountPref("dom.ipc.processCount.");
708 processCountPref
.Append(processTypePrefix
);
710 int32_t maxContentParents
= Preferences::GetInt(processCountPref
.get(), 1);
711 if (maxContentParents
< 1) {
712 maxContentParents
= 1;
715 return static_cast<uint32_t>(maxContentParents
);
719 bool ContentParent::IsMaxProcessCountReached(
720 const nsACString
& aContentProcessType
) {
721 return GetPoolSize(aContentProcessType
) >=
722 GetMaxProcessCount(aContentProcessType
);
725 // Really more ReleaseUnneededProcesses()
727 void ContentParent::ReleaseCachedProcesses() {
728 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
729 ("ReleaseCachedProcesses:"));
730 if (!sBrowserContentParents
) {
735 for (const auto& cps
: *sBrowserContentParents
) {
736 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
737 ("%s: %zu processes", PromiseFlatCString(cps
.GetKey()).get(),
738 cps
.GetData()->Length()));
742 // First let's collect all processes and keep a grip.
743 AutoTArray
<RefPtr
<ContentParent
>, 32> fixArray
;
744 for (const auto& contentParents
: sBrowserContentParents
->Values()) {
745 for (auto* cp
: *contentParents
) {
746 fixArray
.AppendElement(cp
);
750 for (const auto& cp
: fixArray
) {
751 if (cp
->MaybeBeginShutDown(/* aIgnoreKeepAlivePref */ true)) {
752 // Make sure that this process is no longer accessible from JS by its
754 cp
->ShutDownMessageManager();
760 already_AddRefed
<ContentParent
> ContentParent::MinTabSelect(
761 const nsTArray
<ContentParent
*>& aContentParents
, int32_t aMaxContentParents
,
762 uint64_t aBrowserId
) {
763 uint32_t maxSelectable
=
764 std::min(static_cast<uint32_t>(aContentParents
.Length()),
765 static_cast<uint32_t>(aMaxContentParents
));
766 uint32_t min
= INT_MAX
;
767 RefPtr
<ContentParent
> candidate
;
769 for (uint32_t i
= 0; i
< maxSelectable
; i
++) {
770 ContentParent
* p
= aContentParents
[i
];
771 MOZ_DIAGNOSTIC_ASSERT(!p
->IsDead());
772 if (p
->IsShuttingDown()) {
776 // Check how many other tabs are already hosted by this process. Ignore
777 // keepalives without a BrowserId as well as keepalives corresponding to
778 // `aBrowserId` when doing this calculation.
779 ThreadsafeContentParentHandle
* handle
= p
->ThreadsafeHandle();
780 RecursiveMutexAutoLock
lock(handle
->mMutex
);
781 uint32_t keepAliveCount
= handle
->mKeepAlivesPerBrowserId
.Count();
782 if (handle
->mKeepAlivesPerBrowserId
.Contains(0)) {
785 if (aBrowserId
!= 0 &&
786 handle
->mKeepAlivesPerBrowserId
.Contains(aBrowserId
)) {
790 if (keepAliveCount
< min
) {
792 min
= keepAliveCount
;
796 // If all current processes have at least one tab and we have not yet reached
797 // the maximum, use a new process.
799 aContentParents
.Length() < static_cast<uint32_t>(aMaxContentParents
)) {
803 // Otherwise we return candidate.
804 return candidate
.forget();
808 already_AddRefed
<nsIPrincipal
>
809 ContentParent::CreateRemoteTypeIsolationPrincipal(
810 const nsACString
& aRemoteType
) {
811 if ((RemoteTypePrefix(aRemoteType
) != FISSION_WEB_REMOTE_TYPE
) &&
812 !StringBeginsWith(aRemoteType
, WITH_COOP_COEP_REMOTE_TYPE_PREFIX
)) {
816 int32_t offset
= aRemoteType
.FindChar('=') + 1;
817 MOZ_ASSERT(offset
> 1, "can not extract origin from that remote type");
818 nsAutoCString
origin(
819 Substring(aRemoteType
, offset
, aRemoteType
.Length() - offset
));
821 nsIScriptSecurityManager
* ssm
= nsContentUtils::GetSecurityManager();
822 nsCOMPtr
<nsIPrincipal
> principal
;
823 ssm
->CreateContentPrincipalFromOrigin(origin
, getter_AddRefs(principal
));
824 return principal
.forget();
828 UniqueContentParentKeepAlive
ContentParent::GetUsedBrowserProcess(
829 const nsACString
& aRemoteType
, nsTArray
<ContentParent
*>& aContentParents
,
830 uint32_t aMaxContentParents
, bool aPreferUsed
, ProcessPriority aPriority
,
831 uint64_t aBrowserId
) {
832 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
833 AutoRestore
ar(sInProcessSelector
);
834 sInProcessSelector
= true;
837 uint32_t numberOfParents
= aContentParents
.Length();
838 if (aPreferUsed
&& numberOfParents
) {
839 // If we prefer re-using existing content processes, we don't want to create
840 // a new process, and instead re-use an existing one, so pretend the process
841 // limit is at the current number of processes.
842 aMaxContentParents
= numberOfParents
;
845 // Use MinTabSelect to choose a content process unless content process re-use
846 // has been disabled.
847 RefPtr
<ContentParent
> selected
;
848 if (!StaticPrefs::dom_ipc_disableContentProcessReuse() &&
850 MinTabSelect(aContentParents
, aMaxContentParents
, aBrowserId
))) {
851 if (profiler_thread_is_being_profiled_for_markers()) {
852 nsPrintfCString
marker("Reused process %u",
853 (unsigned int)selected
->ChildID());
854 PROFILER_MARKER_TEXT("Process", DOM
, {}, marker
);
856 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
857 ("GetUsedProcess: Reused process %p (%d) for %s", selected
.get(),
858 (unsigned int)selected
->ChildID(),
859 PromiseFlatCString(aRemoteType
).get()));
860 selected
->AssertAlive();
861 return selected
->AddKeepAlive(aBrowserId
);
864 // Try to take a preallocated process except for certain remote types.
865 // Note: this process may not have finished launching yet
866 UniqueContentParentKeepAlive preallocated
;
867 if (aRemoteType
!= FILE_REMOTE_TYPE
&&
868 aRemoteType
!= PRIVILEGEDABOUT_REMOTE_TYPE
&&
869 aRemoteType
!= EXTENSION_REMOTE_TYPE
&& // Bug 1638119
870 (preallocated
= PreallocatedProcessManager::Take(aRemoteType
))) {
871 MOZ_DIAGNOSTIC_ASSERT(preallocated
->GetRemoteType() ==
872 PREALLOC_REMOTE_TYPE
);
873 preallocated
->AssertAlive();
875 if (profiler_thread_is_being_profiled_for_markers()) {
876 nsPrintfCString
marker(
877 "Assigned preallocated process %u%s",
878 (unsigned int)preallocated
->ChildID(),
879 preallocated
->IsLaunching() ? " (still launching)" : "");
880 PROFILER_MARKER_TEXT("Process", DOM
, {}, marker
);
882 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
883 ("Adopted preallocated process %p for type %s%s",
884 preallocated
.get(), PromiseFlatCString(aRemoteType
).get(),
885 preallocated
->IsLaunching() ? " (still launching)" : ""));
887 // This ensures that the preallocator won't shut down the process once
888 // it finishes starting
889 preallocated
->mRemoteType
.Assign(aRemoteType
);
891 RecursiveMutexAutoLock
lock(preallocated
->mThreadsafeHandle
->mMutex
);
892 preallocated
->mThreadsafeHandle
->mRemoteType
= preallocated
->mRemoteType
;
894 preallocated
->mRemoteTypeIsolationPrincipal
=
895 CreateRemoteTypeIsolationPrincipal(aRemoteType
);
896 preallocated
->mActivateTS
= TimeStamp::Now();
897 preallocated
->AddToPool(aContentParents
);
899 // rare, but will happen
900 if (!preallocated
->IsLaunching()) {
901 // Specialize this process for the appropriate remote type, and activate
904 Unused
<< preallocated
->SendRemoteType(preallocated
->mRemoteType
,
905 preallocated
->mProfile
);
907 preallocated
->StartRemoteWorkerService();
909 nsCOMPtr
<nsIObserverService
> obs
=
910 mozilla::services::GetObserverService();
913 cpId
.AppendInt(static_cast<uint64_t>(preallocated
->ChildID()));
914 obs
->NotifyObservers(static_cast<nsIObserver
*>(preallocated
.get()),
915 "process-type-set", cpId
.get());
916 preallocated
->AssertAlive();
919 // NOTE: Make sure to return a keepalive for the requested aBrowserId. The
920 // keepalive used by the preallocated process manager will be released upon
922 return preallocated
->AddKeepAlive(aBrowserId
);
929 UniqueContentParentKeepAlive
ContentParent::GetNewOrUsedLaunchingBrowserProcess(
930 const nsACString
& aRemoteType
, BrowsingContextGroup
* aGroup
,
931 ProcessPriority aPriority
, bool aPreferUsed
, uint64_t aBrowserId
) {
932 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
933 ("GetNewOrUsedProcess for type %s",
934 PromiseFlatCString(aRemoteType
).get()));
936 // Fallback check (we really want our callers to avoid this).
937 if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed
)) {
938 MOZ_DIAGNOSTIC_ASSERT(
939 false, "Late attempt to GetNewOrUsedLaunchingBrowserProcess!");
943 // If we have an existing host process attached to this BrowsingContextGroup,
944 // always return it, as we can never have multiple host processes within a
945 // single BrowsingContextGroup.
946 UniqueContentParentKeepAlive contentParent
;
948 if (RefPtr
<ContentParent
> candidate
= aGroup
->GetHostProcess(aRemoteType
)) {
949 Unused
<< NS_WARN_IF(candidate
->IsShuttingDown());
950 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
951 ("GetNewOrUsedProcess: Existing host process %p (launching %d)",
952 candidate
.get(), candidate
->IsLaunching()));
953 contentParent
= candidate
->TryAddKeepAlive(aBrowserId
);
957 nsTArray
<ContentParent
*>& contentParents
= GetOrCreatePool(aRemoteType
);
959 if (!contentParent
) {
960 // No host process. Let's try to re-use an existing process.
961 uint32_t maxContentParents
= GetMaxProcessCount(aRemoteType
);
964 GetUsedBrowserProcess(aRemoteType
, contentParents
, maxContentParents
,
965 aPreferUsed
, aPriority
, aBrowserId
);
968 if (!contentParent
) {
969 // No reusable process. Let's create and launch one.
970 // The life cycle will be set to `LifecycleState::LAUNCHING`.
971 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
972 ("Launching new process immediately for type %s",
973 PromiseFlatCString(aRemoteType
).get()));
975 RefPtr
<ContentParent
> newCp
= new ContentParent(aRemoteType
);
976 if (NS_WARN_IF(!newCp
->BeginSubprocessLaunch(aPriority
))) {
977 // Launch aborted because of shutdown. Bailout.
978 newCp
->LaunchSubprocessReject();
981 contentParent
= newCp
->AddKeepAlive(aBrowserId
);
983 // Until the new process is ready let's not allow to start up any
984 // preallocated processes. The blocker will be removed once we receive
985 // the first idle message.
986 contentParent
->mIsAPreallocBlocker
= true;
987 PreallocatedProcessManager::AddBlocker(aRemoteType
, contentParent
.get());
989 // Store this process for future reuse.
990 contentParent
->AddToPool(contentParents
);
993 ContentParent::GetLog(), LogLevel::Debug
,
994 ("GetNewOrUsedProcess: new immediate process %p", contentParent
.get()));
996 // else we have an existing or preallocated process (which may be
999 contentParent
->AssertAlive();
1001 aGroup
->EnsureHostProcess(contentParent
.get());
1003 return contentParent
;
1007 RefPtr
<ContentParent::LaunchPromise
>
1008 ContentParent::GetNewOrUsedBrowserProcessAsync(const nsACString
& aRemoteType
,
1009 BrowsingContextGroup
* aGroup
,
1010 ProcessPriority aPriority
,
1012 uint64_t aBrowserId
) {
1013 // Obtain a `ContentParent` launched asynchronously.
1014 UniqueContentParentKeepAlive contentParent
=
1015 GetNewOrUsedLaunchingBrowserProcess(aRemoteType
, aGroup
, aPriority
,
1016 aPreferUsed
, aBrowserId
);
1017 if (!contentParent
) {
1018 // In case of launch error, stop here.
1019 return LaunchPromise::CreateAndReject(NS_ERROR_ILLEGAL_DURING_SHUTDOWN
,
1022 return contentParent
->WaitForLaunchAsync(aPriority
, aBrowserId
);
1026 UniqueContentParentKeepAlive
ContentParent::GetNewOrUsedBrowserProcess(
1027 const nsACString
& aRemoteType
, BrowsingContextGroup
* aGroup
,
1028 ProcessPriority aPriority
, bool aPreferUsed
, uint64_t aBrowserId
) {
1029 UniqueContentParentKeepAlive contentParent
=
1030 GetNewOrUsedLaunchingBrowserProcess(aRemoteType
, aGroup
, aPriority
,
1031 aPreferUsed
, aBrowserId
);
1032 if (!contentParent
|| !contentParent
->WaitForLaunchSync(aPriority
)) {
1033 // In case of launch error, stop here.
1036 return contentParent
;
1039 RefPtr
<ContentParent::LaunchPromise
> ContentParent::WaitForLaunchAsync(
1040 ProcessPriority aPriority
, uint64_t aBrowserId
) {
1041 MOZ_DIAGNOSTIC_ASSERT(!IsDead());
1042 UniqueContentParentKeepAlive self
= AddKeepAlive(aBrowserId
);
1044 if (!IsLaunching()) {
1045 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
1046 ("WaitForLaunchAsync: launched"));
1047 return LaunchPromise::CreateAndResolve(std::move(self
), __func__
);
1050 // We've started an async content process launch.
1051 Telemetry::Accumulate(Telemetry::CONTENT_PROCESS_LAUNCH_IS_SYNC
, 0);
1053 // We have located a process that hasn't finished initializing, then attempt
1054 // to finish initializing. Both `LaunchSubprocessResolve` and
1055 // `LaunchSubprocessReject` are safe to call multiple times if we race with
1056 // other `WaitForLaunchAsync` callbacks.
1057 return mSubprocess
->WhenProcessHandleReady()->Then(
1058 GetCurrentSerialEventTarget(), __func__
,
1059 [self
= std::move(self
), aPriority
](
1060 const ProcessHandlePromise::ResolveOrRejectValue
& aValue
) mutable {
1061 if (aValue
.IsResolve() &&
1062 self
->LaunchSubprocessResolve(/* aIsSync = */ false, aPriority
)) {
1063 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
1064 ("WaitForLaunchAsync: async, now launched"));
1065 self
->mActivateTS
= TimeStamp::Now();
1066 return LaunchPromise::CreateAndResolve(std::move(self
), __func__
);
1069 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
1070 ("WaitForLaunchAsync: async, rejected"));
1071 self
->LaunchSubprocessReject();
1072 return LaunchPromise::CreateAndReject(NS_ERROR_FAILURE
, __func__
);
1076 bool ContentParent::WaitForLaunchSync(ProcessPriority aPriority
) {
1077 MOZ_DIAGNOSTIC_ASSERT(!IsDead());
1078 if (!IsLaunching()) {
1082 // We've started a sync content process launch.
1083 Telemetry::Accumulate(Telemetry::CONTENT_PROCESS_LAUNCH_IS_SYNC
, 1);
1085 // We're a process which hasn't finished initializing. We may be racing
1086 // against whoever launched it (and whoever else is already racing). Since
1087 // we're sync, we win the race and finish the initialization.
1088 bool launchSuccess
= mSubprocess
->WaitForProcessHandle();
1089 if (launchSuccess
&&
1090 LaunchSubprocessResolve(/* aIsSync = */ true, aPriority
)) {
1091 mActivateTS
= TimeStamp::Now();
1094 // In case of failure.
1095 LaunchSubprocessReject();
1099 static nsIDocShell
* GetOpenerDocShellHelper(Element
* aFrameElement
) {
1100 // Propagate the private-browsing status of the element's parent
1101 // docshell to the remote docshell, via the chrome flags.
1102 MOZ_ASSERT(aFrameElement
);
1103 nsPIDOMWindowOuter
* win
= aFrameElement
->OwnerDoc()->GetWindow();
1105 NS_WARNING("Remote frame has no window");
1108 nsIDocShell
* docShell
= win
->GetDocShell();
1110 NS_WARNING("Remote frame has no docshell");
1117 mozilla::ipc::IPCResult
ContentParent::RecvCreateGMPService() {
1118 Endpoint
<PGMPServiceParent
> parent
;
1119 Endpoint
<PGMPServiceChild
> child
;
1122 return IPC_FAIL(this, "GMP Service already created");
1126 rv
= PGMPService::CreateEndpoints(base::GetCurrentProcId(), OtherPid(),
1128 if (NS_FAILED(rv
)) {
1129 return IPC_FAIL(this, "CreateEndpoints failed");
1132 if (!GMPServiceParent::Create(std::move(parent
))) {
1133 return IPC_FAIL(this, "GMPServiceParent::Create failed");
1136 if (!SendInitGMPService(std::move(child
))) {
1137 return IPC_FAIL(this, "SendInitGMPService failed");
1145 IPCResult
ContentParent::RecvAttributionEvent(
1146 const nsACString
& aHost
, PrivateAttributionImpressionType aType
,
1147 uint32_t aIndex
, const nsAString
& aAd
, const nsACString
& aTargetHost
) {
1148 nsCOMPtr
<nsIPrivateAttributionService
> pa
=
1149 components::PrivateAttribution::Service();
1150 if (NS_WARN_IF(!pa
)) {
1153 pa
->OnAttributionEvent(aHost
, GetEnumString(aType
), aIndex
, aAd
, aTargetHost
);
1157 IPCResult
ContentParent::RecvAttributionConversion(
1158 const nsACString
& aHost
, const nsAString
& aTask
, uint32_t aHistogramSize
,
1159 const Maybe
<uint32_t>& aLoopbackDays
,
1160 const Maybe
<PrivateAttributionImpressionType
>& aImpressionType
,
1161 const nsTArray
<nsString
>& aAds
, const nsTArray
<nsCString
>& aSourceHosts
) {
1162 nsCOMPtr
<nsIPrivateAttributionService
> pa
=
1163 components::PrivateAttribution::Service();
1164 if (NS_WARN_IF(!pa
)) {
1167 pa
->OnAttributionConversion(
1168 aHost
, aTask
, aHistogramSize
, aLoopbackDays
.valueOr(0),
1169 aImpressionType
? GetEnumString(*aImpressionType
) : EmptyCString(), aAds
,
1174 Atomic
<bool, mozilla::Relaxed
> sContentParentTelemetryEventEnabled(false);
1177 void ContentParent::LogAndAssertFailedPrincipalValidationInfo(
1178 nsIPrincipal
* aPrincipal
, const char* aMethod
) {
1179 // nsContentSecurityManager may also enable this same event, but that's okay
1180 if (!sContentParentTelemetryEventEnabled
.exchange(true)) {
1181 sContentParentTelemetryEventEnabled
= true;
1182 Telemetry::SetEventRecordingEnabled("security"_ns
, true);
1186 nsAutoCString principalScheme
, principalType
, spec
;
1187 CopyableTArray
<EventExtraEntry
> extra(2);
1190 principalType
.AssignLiteral("NullPtr");
1191 } else if (aPrincipal
->IsSystemPrincipal()) {
1192 principalType
.AssignLiteral("SystemPrincipal");
1193 } else if (aPrincipal
->GetIsExpandedPrincipal()) {
1194 principalType
.AssignLiteral("ExpandedPrincipal");
1195 } else if (aPrincipal
->GetIsContentPrincipal()) {
1196 principalType
.AssignLiteral("ContentPrincipal");
1197 aPrincipal
->GetSpec(spec
);
1198 aPrincipal
->GetScheme(principalScheme
);
1200 extra
.AppendElement(EventExtraEntry
{"scheme"_ns
, principalScheme
});
1202 principalType
.AssignLiteral("Unknown");
1205 extra
.AppendElement(EventExtraEntry
{"principalType"_ns
, principalType
});
1207 // Do not send telemetry when chrome-debugging is enabled
1208 bool isChromeDebuggingEnabled
=
1209 Preferences::GetBool("devtools.chrome.enabled", false);
1210 if (!isChromeDebuggingEnabled
) {
1211 Telemetry::EventID eventType
=
1212 Telemetry::EventID::Security_Fissionprincipals_Contentparent
;
1213 Telemetry::RecordEvent(eventType
, mozilla::Some(aMethod
),
1214 mozilla::Some(extra
));
1219 ContentParent::GetLog(), LogLevel::Error
,
1220 (" Receiving unexpected Principal (%s) within %s",
1221 aPrincipal
&& aPrincipal
->GetIsContentPrincipal() ? spec
.get()
1222 : principalType
.get(),
1226 // Not only log but also ensure we do not receive an unexpected
1227 // principal when running in debug mode.
1228 MOZ_ASSERT(false, "Receiving unexpected Principal");
1232 bool ContentParent::ValidatePrincipal(
1233 nsIPrincipal
* aPrincipal
,
1234 const EnumSet
<ValidatePrincipalOptions
>& aOptions
) {
1235 // If the pref says we should not validate, then there is nothing to do
1236 if (!StaticPrefs::dom_security_enforceIPCBasedPrincipalVetting()) {
1240 // If there is no principal, then there is nothing to validate!
1242 return aOptions
.contains(ValidatePrincipalOptions::AllowNullPtr
);
1245 // We currently do not track relationships between specific null principals
1246 // and content processes, so we can not validate much here - just allow all
1247 // null principals we see because they are generally safe anyway!
1248 if (aPrincipal
->GetIsNullPrincipal()) {
1252 // Only allow the system principal if the passed in options flags
1253 // request permitting the system principal.
1254 if (aPrincipal
->IsSystemPrincipal()) {
1255 return aOptions
.contains(ValidatePrincipalOptions::AllowSystem
);
1258 // XXXckerschb: we should eliminate the resource carve-out here and always
1259 // validate the Principal, see Bug 1686200: Investigate Principal for pdf.js
1260 if (aPrincipal
->SchemeIs("resource")) {
1264 // Validate each inner principal individually, allowing us to catch expanded
1265 // principals containing the system principal, etc.
1266 if (aPrincipal
->GetIsExpandedPrincipal()) {
1267 if (!aOptions
.contains(ValidatePrincipalOptions::AllowExpanded
)) {
1270 // FIXME: There are more constraints on expanded principals in-practice,
1271 // such as the structure of extension expanded principals. This may need
1272 // to be investigated more in the future.
1273 nsCOMPtr
<nsIExpandedPrincipal
> expandedPrincipal
=
1274 do_QueryInterface(aPrincipal
);
1275 const auto& allowList
= expandedPrincipal
->AllowList();
1276 for (const auto& innerPrincipal
: allowList
) {
1277 if (!ValidatePrincipal(innerPrincipal
, aOptions
)) {
1284 // A URI with a file:// scheme can never load in a non-file content process
1285 // due to sandboxing.
1286 if (aPrincipal
->SchemeIs("file")) {
1287 // If we don't support a separate 'file' process, then we can return here.
1288 if (!StaticPrefs::browser_tabs_remote_separateFileUriProcess()) {
1291 return mRemoteType
== FILE_REMOTE_TYPE
;
1294 if (aPrincipal
->SchemeIs("about")) {
1296 if (NS_FAILED(aPrincipal
->GetAboutModuleFlags(&flags
))) {
1300 // Block principals for about: URIs which can't load in this process.
1301 if (!(flags
& (nsIAboutModule::URI_CAN_LOAD_IN_CHILD
|
1302 nsIAboutModule::URI_MUST_LOAD_IN_CHILD
))) {
1305 if (flags
& nsIAboutModule::URI_MUST_LOAD_IN_EXTENSION_PROCESS
) {
1306 return mRemoteType
== EXTENSION_REMOTE_TYPE
;
1311 if (!mRemoteTypeIsolationPrincipal
||
1312 RemoteTypePrefix(mRemoteType
) != FISSION_WEB_REMOTE_TYPE
) {
1316 // Web content can contain extension content frames, so a content process may
1317 // send us an extension's principal.
1318 auto* addonPolicy
= BasePrincipal::Cast(aPrincipal
)->AddonPolicy();
1323 // Ensure that the expected site-origin matches the one specified by our
1324 // mRemoteTypeIsolationPrincipal.
1325 nsAutoCString siteOriginNoSuffix
;
1326 if (NS_FAILED(aPrincipal
->GetSiteOriginNoSuffix(siteOriginNoSuffix
))) {
1329 nsAutoCString remoteTypeSiteOriginNoSuffix
;
1330 if (NS_FAILED(mRemoteTypeIsolationPrincipal
->GetSiteOriginNoSuffix(
1331 remoteTypeSiteOriginNoSuffix
))) {
1335 return remoteTypeSiteOriginNoSuffix
.Equals(siteOriginNoSuffix
);
1339 already_AddRefed
<RemoteBrowser
> ContentParent::CreateBrowser(
1340 const TabContext
& aContext
, Element
* aFrameElement
,
1341 const nsACString
& aRemoteType
, BrowsingContext
* aBrowsingContext
,
1342 ContentParent
* aOpenerContentParent
) {
1343 AUTO_PROFILER_LABEL("ContentParent::CreateBrowser", OTHER
);
1345 MOZ_DIAGNOSTIC_ASSERT(
1346 !aBrowsingContext
->Canonical()->GetBrowserParent(),
1347 "BrowsingContext must not have BrowserParent, or have previous "
1348 "BrowserParent cleared");
1350 // Don't bother creating new content browsers after entering shutdown. This
1351 // could lead to starting a new content process, which may significantly delay
1352 // shutdown, and the content is unlikely to be displayed.
1353 if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed
)) {
1354 NS_WARNING("Ignoring remote browser creation request during shutdown");
1358 nsAutoCString
remoteType(aRemoteType
);
1359 if (remoteType
.IsEmpty()) {
1360 remoteType
= DEFAULT_REMOTE_TYPE
;
1363 TabId
tabId(nsContentUtils::GenerateTabId());
1365 nsIDocShell
* docShell
= GetOpenerDocShellHelper(aFrameElement
);
1368 openerTabId
= BrowserParent::GetTabIdFrom(docShell
);
1371 // Hold a KeepAlive on our ContentParent throughout this function. Once the
1372 // `BrowserParent` has been created, it can be cleared, as that BrowserParent
1373 // will establish its own KeepAlive.
1374 UniqueContentParentKeepAlive constructorSender
;
1375 MOZ_RELEASE_ASSERT(XRE_IsParentProcess(),
1376 "Cannot allocate BrowserParent in content process");
1377 if (aOpenerContentParent
&& !aOpenerContentParent
->IsShuttingDown()) {
1379 aOpenerContentParent
->AddKeepAlive(aBrowsingContext
->BrowserId());
1381 constructorSender
= GetNewOrUsedBrowserProcess(
1382 remoteType
, aBrowsingContext
->Group(), PROCESS_PRIORITY_FOREGROUND
,
1383 /* aPreferUsed */ false,
1384 /* aBrowserId */ aBrowsingContext
->BrowserId());
1385 if (!constructorSender
) {
1390 aBrowsingContext
->SetEmbedderElement(aFrameElement
);
1392 // Ensure that the process which we're using to launch is set as the host
1393 // process for this BrowsingContextGroup.
1394 aBrowsingContext
->Group()->EnsureHostProcess(constructorSender
.get());
1396 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
1397 docShell
->GetTreeOwner(getter_AddRefs(treeOwner
));
1402 nsCOMPtr
<nsIWebBrowserChrome
> wbc
= do_GetInterface(treeOwner
);
1406 uint32_t chromeFlags
= 0;
1407 wbc
->GetChromeFlags(&chromeFlags
);
1409 nsCOMPtr
<nsILoadContext
> loadContext
= do_QueryInterface(docShell
);
1410 if (loadContext
&& loadContext
->UsePrivateBrowsing()) {
1411 chromeFlags
|= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW
;
1413 if (loadContext
&& loadContext
->UseRemoteTabs()) {
1414 chromeFlags
|= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW
;
1416 if (loadContext
&& loadContext
->UseRemoteSubframes()) {
1417 chromeFlags
|= nsIWebBrowserChrome::CHROME_FISSION_WINDOW
;
1424 aBrowsingContext
->Canonical()->SetOwnerProcessId(
1425 constructorSender
->ChildID());
1427 RefPtr
<BrowserParent
> browserParent
=
1428 new BrowserParent(constructorSender
.get(), tabId
, aContext
,
1429 aBrowsingContext
->Canonical(), chromeFlags
);
1431 // Open a remote endpoint for our PBrowser actor.
1432 ManagedEndpoint
<PBrowserChild
> childEp
=
1433 constructorSender
->OpenPBrowserEndpoint(browserParent
);
1434 if (NS_WARN_IF(!childEp
.IsValid())) {
1438 ContentProcessManager
* cpm
= ContentProcessManager::GetSingleton();
1439 if (NS_WARN_IF(!cpm
)) {
1442 cpm
->RegisterRemoteFrame(browserParent
);
1444 nsCOMPtr
<nsIPrincipal
> initialPrincipal
=
1445 NullPrincipal::Create(aBrowsingContext
->OriginAttributesRef());
1446 WindowGlobalInit windowInit
= WindowGlobalActor::AboutBlankInitializer(
1447 aBrowsingContext
, initialPrincipal
);
1449 RefPtr
<WindowGlobalParent
> windowParent
=
1450 WindowGlobalParent::CreateDisconnected(windowInit
);
1451 if (NS_WARN_IF(!windowParent
)) {
1455 // Open a remote endpoint for the initial PWindowGlobal actor.
1456 ManagedEndpoint
<PWindowGlobalChild
> windowEp
=
1457 browserParent
->OpenPWindowGlobalEndpoint(windowParent
);
1458 if (NS_WARN_IF(!windowEp
.IsValid())) {
1462 // Tell the content process to set up its PBrowserChild.
1463 bool ok
= constructorSender
->SendConstructBrowser(
1464 std::move(childEp
), std::move(windowEp
), tabId
,
1465 aContext
.AsIPCTabContext(), windowInit
, chromeFlags
,
1466 constructorSender
->ChildID(), constructorSender
->IsForBrowser(),
1467 /* aIsTopLevel */ true);
1468 if (NS_WARN_IF(!ok
)) {
1472 // Ensure that we're marked as the current BrowserParent on our
1473 // CanonicalBrowsingContext.
1474 aBrowsingContext
->Canonical()->SetCurrentBrowserParent(browserParent
);
1476 windowParent
->Init();
1478 RefPtr
<BrowserHost
> browserHost
= new BrowserHost(browserParent
);
1479 browserParent
->SetOwnerElement(aFrameElement
);
1480 return browserHost
.forget();
1483 void ContentParent::GetAll(nsTArray
<ContentParent
*>& aArray
) {
1486 for (auto* cp
: AllProcesses(eLive
)) {
1487 aArray
.AppendElement(cp
);
1491 void ContentParent::GetAllEvenIfDead(nsTArray
<ContentParent
*>& aArray
) {
1494 for (auto* cp
: AllProcesses(eAll
)) {
1495 aArray
.AppendElement(cp
);
1499 void ContentParent::BroadcastStringBundle(
1500 const StringBundleDescriptor
& aBundle
) {
1501 AutoTArray
<StringBundleDescriptor
, 1> array
;
1502 array
.AppendElement(aBundle
);
1504 for (auto* cp
: AllProcesses(eLive
)) {
1505 Unused
<< cp
->SendRegisterStringBundles(array
);
1509 void ContentParent::BroadcastFontListChanged() {
1510 for (auto* cp
: AllProcesses(eLive
)) {
1511 Unused
<< cp
->SendFontListChanged();
1515 void ContentParent::BroadcastShmBlockAdded(uint32_t aGeneration
,
1517 auto* pfl
= gfxPlatformFontList::PlatformFontList();
1518 for (auto* cp
: AllProcesses(eLive
)) {
1519 base::SharedMemoryHandle handle
=
1520 pfl
->ShareShmBlockToProcess(aIndex
, cp
->Pid());
1521 if (handle
== base::SharedMemory::NULLHandle()) {
1522 // If something went wrong here, we just skip it; the child will need to
1523 // request the block as needed, at some performance cost.
1526 Unused
<< cp
->SendFontListShmBlockAdded(aGeneration
, aIndex
,
1531 void ContentParent::BroadcastThemeUpdate(widget::ThemeChangeKind aKind
) {
1532 const FullLookAndFeel
& lnf
= *RemoteLookAndFeel::ExtractData();
1533 for (auto* cp
: AllProcesses(eLive
)) {
1534 Unused
<< cp
->SendThemeChanged(lnf
, aKind
);
1539 void ContentParent::BroadcastMediaCodecsSupportedUpdate(
1540 RemoteDecodeIn aLocation
, const media::MediaCodecsSupported
& aSupported
) {
1541 // Update processes and print the support info from the given location.
1542 sCodecsSupported
[aLocation
] = aSupported
;
1543 for (auto* cp
: AllProcesses(eAll
)) {
1544 Unused
<< cp
->SendUpdateMediaCodecsSupported(aLocation
, aSupported
);
1546 nsCString supportString
;
1547 media::MCSInfo::GetMediaCodecsSupportedString(supportString
, aSupported
);
1548 LOGPDM("Broadcast support from '%s', support=%s",
1549 RemoteDecodeInToStr(aLocation
), supportString
.get());
1551 // Merge incoming support with existing support list from other locations
1552 media::MCSInfo::AddSupport(aSupported
);
1553 auto fullSupport
= media::MCSInfo::GetSupport();
1555 // Generate + save FULL support string for display in about:support
1556 supportString
.Truncate();
1557 media::MCSInfo::GetMediaCodecsSupportedString(supportString
, fullSupport
);
1558 gfx::gfxVars::SetCodecSupportInfo(supportString
);
1561 const nsACString
& ContentParent::GetRemoteType() const { return mRemoteType
; }
1563 static StaticRefPtr
<nsIAsyncShutdownClient
> sXPCOMShutdownClient
;
1564 static StaticRefPtr
<nsIAsyncShutdownClient
> sProfileBeforeChangeClient
;
1565 static StaticRefPtr
<nsIAsyncShutdownClient
> sQuitApplicationGrantedClient
;
1567 void ContentParent::Init() {
1568 MOZ_ASSERT(sXPCOMShutdownClient
);
1570 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
1572 size_t length
= ArrayLength(sObserverTopics
);
1573 for (size_t i
= 0; i
< length
; ++i
) {
1574 obs
->AddObserver(this, sObserverTopics
[i
], false);
1580 cpId
.AppendInt(static_cast<uint64_t>(this->ChildID()));
1581 obs
->NotifyObservers(static_cast<nsIObserver
*>(this), "ipc:content-created",
1585 #ifdef ACCESSIBILITY
1586 // If accessibility is running in chrome process then start it in content
1588 if (GetAccService()) {
1589 Unused
<< SendActivateA11y();
1591 #endif // #ifdef ACCESSIBILITY
1593 Unused
<< SendInitProfiler(ProfilerParent::CreateForProcess(OtherPid()));
1595 RefPtr
<GeckoMediaPluginServiceParent
> gmps(
1596 GeckoMediaPluginServiceParent::GetSingleton());
1598 gmps
->UpdateContentProcessGMPCapabilities(this);
1601 // Flush any pref updates that happened during launch and weren't
1602 // included in the blobs set up in BeginSubprocessLaunch.
1603 for (const Pref
& pref
: mQueuedPrefs
) {
1604 Unused
<< NS_WARN_IF(!SendPreferenceUpdate(pref
));
1606 mQueuedPrefs
.Clear();
1608 Unused
<< SendInitNextGenLocalStorageEnabled(NextGenLocalStorageEnabled());
1611 void ContentParent::AsyncSendShutDownMessage() {
1612 MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose
,
1613 ("AsyncSendShutDownMessage %p", this));
1614 MOZ_ASSERT(NS_IsMainThread());
1616 // In the case of normal shutdown, send a shutdown message to child to
1617 // allow it to perform shutdown tasks.
1618 GetCurrentSerialEventTarget()->Dispatch(NewRunnableMethod
<ShutDownMethod
>(
1619 "dom::ContentParent::ShutDownProcess", this,
1620 &ContentParent::ShutDownProcess
, SEND_SHUTDOWN_MESSAGE
));
1623 void MaybeLogBlockShutdownDiagnostics(ContentParent
* aSelf
, const char* aMsg
,
1624 const char* aFile
, int32_t aLine
) {
1625 #if defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED)
1626 if (aSelf
->IsBlockingShutdown()) {
1627 MOZ_LOG(ContentParent::GetLog(), LogLevel::Info
,
1628 ("ContentParent: id=%p pid=%d - %s at %s(%d)", aSelf
, aSelf
->Pid(),
1629 aMsg
, aFile
, aLine
));
1639 bool ContentParent::ShutDownProcess(ShutDownMethod aMethod
) {
1640 bool result
= false;
1641 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
1642 ("ShutDownProcess: %p", this));
1643 // NB: must MarkAsDead() here so that this isn't accidentally
1644 // returned from Get*() while in the midst of shutdown.
1647 // Shutting down by sending a shutdown message works differently than the
1648 // other methods. We first call Shutdown() in the child. After the child is
1649 // ready, it calls FinishShutdown() on us. Then we close the channel.
1650 if (aMethod
== SEND_SHUTDOWN_MESSAGE
) {
1651 if (!mShutdownPending
) {
1653 // Stop sending input events with input priority when shutting down.
1654 SetInputPriorityEventEnabled(false);
1655 // If we did not earlier, let's signal the shutdown to JS now.
1656 SignalImpendingShutdownToContentJS();
1658 // Adjust the QoS priorities for shutdown, if they exist.
1659 if (StaticPrefs::threads_use_low_power_enabled() &&
1661 threads_lower_mainthread_priority_in_background_enabled()) {
1662 SetMainThreadQoSPriority(nsIThread::QOS_PRIORITY_NORMAL
);
1665 // Send a high priority announcement first. If this fails, SendShutdown
1667 Unused
<< SendShutdownConfirmedHP();
1668 // Send the definite message with normal priority.
1669 if (SendShutdown()) {
1670 MaybeLogBlockShutdownDiagnostics(
1671 this, "ShutDownProcess: Sent shutdown message.", __FILE__
,
1673 mShutdownPending
= true;
1674 // We start the kill timer only after we asked our process to
1676 StartForceKillTimer();
1679 MaybeLogBlockShutdownDiagnostics(
1680 this, "ShutDownProcess: !!! Send shutdown message failed! !!!",
1681 __FILE__
, __LINE__
);
1684 MaybeLogBlockShutdownDiagnostics(
1685 this, "ShutDownProcess: !!! !CanSend !!!", __FILE__
, __LINE__
);
1688 MaybeLogBlockShutdownDiagnostics(
1689 this, "ShutDownProcess: Shutdown already pending.", __FILE__
,
1694 // If call was not successful, the channel must have been broken
1695 // somehow, and we will clean up the error in ActorDestroy.
1699 using mozilla::dom::quota::QuotaManagerService
;
1701 if (QuotaManagerService
* qms
= QuotaManagerService::GetOrCreate()) {
1702 qms
->AbortOperationsForProcess(mChildID
);
1705 if (aMethod
== CLOSE_CHANNEL
) {
1706 if (!mCalledClose
) {
1707 MaybeLogBlockShutdownDiagnostics(
1708 this, "ShutDownProcess: Closing channel.", __FILE__
, __LINE__
);
1709 // Close() can only be called once: It kicks off the destruction sequence.
1710 mCalledClose
= true;
1716 // A ContentParent object might not get freed until after XPCOM shutdown has
1717 // shut down the cycle collector. But by then it's too late to release any
1718 // CC'ed objects, so we need to null them out here, while we still can. See
1720 ShutDownMessageManager();
1724 mozilla::ipc::IPCResult
ContentParent::RecvNotifyShutdownSuccess() {
1725 if (!mShutdownPending
) {
1726 return IPC_FAIL(this, "RecvNotifyShutdownSuccess without mShutdownPending");
1729 mIsNotifiedShutdownSuccess
= true;
1734 mozilla::ipc::IPCResult
ContentParent::RecvFinishShutdown() {
1735 if (!mShutdownPending
) {
1736 return IPC_FAIL(this, "RecvFinishShutdown without mShutdownPending");
1739 // At this point, we already called ShutDownProcess once with
1740 // SEND_SHUTDOWN_MESSAGE. To actually close the channel, we call
1741 // ShutDownProcess again with CLOSE_CHANNEL.
1743 MaybeLogBlockShutdownDiagnostics(
1744 this, "RecvFinishShutdown: Channel already closed.", __FILE__
,
1748 ShutDownProcess(CLOSE_CHANNEL
);
1752 void ContentParent::ShutDownMessageManager() {
1753 if (!mMessageManager
) {
1757 mMessageManager
->SetOsPid(-1);
1758 mMessageManager
->Disconnect();
1759 mMessageManager
= nullptr;
1762 void ContentParent::AddToPool(nsTArray
<ContentParent
*>& aPool
) {
1763 MOZ_DIAGNOSTIC_ASSERT(!mIsInPool
);
1765 MOZ_DIAGNOSTIC_ASSERT(!mCalledKillHard
);
1766 aPool
.AppendElement(this);
1770 void ContentParent::RemoveFromPool(nsTArray
<ContentParent
*>& aPool
) {
1771 MOZ_DIAGNOSTIC_ASSERT(mIsInPool
);
1772 aPool
.RemoveElement(this);
1776 void ContentParent::AssertNotInPool() {
1777 MOZ_RELEASE_ASSERT(!mIsInPool
);
1779 MOZ_RELEASE_ASSERT(!sBrowserContentParents
||
1780 !sBrowserContentParents
->Contains(mRemoteType
) ||
1781 !sBrowserContentParents
->Get(mRemoteType
)->Contains(this));
1783 for (const auto& group
: mGroups
) {
1784 MOZ_RELEASE_ASSERT(group
->GetHostProcess(mRemoteType
) != this,
1785 "still a host process for one of our groups?");
1789 void ContentParent::AssertAlive() {
1790 MOZ_DIAGNOSTIC_ASSERT(!mIsSignaledImpendingShutdown
);
1791 MOZ_DIAGNOSTIC_ASSERT(!IsDead());
1794 void ContentParent::RemoveFromList() {
1796 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1802 // Ensure that this BrowsingContextGroup is no longer used to host new
1803 // documents from any associated BrowsingContextGroups. It may become a host
1804 // again in the future, if it is restored to the pool.
1805 for (const auto& group
: mGroups
) {
1806 group
->RemoveHostProcess(this);
1809 if (sBrowserContentParents
) {
1810 if (auto entry
= sBrowserContentParents
->Lookup(mRemoteType
)) {
1811 const auto& contentParents
= entry
.Data();
1812 RemoveFromPool(*contentParents
);
1813 if (contentParents
->IsEmpty()) {
1817 if (sBrowserContentParents
->IsEmpty()) {
1818 delete sBrowserContentParents
;
1819 sBrowserContentParents
= nullptr;
1824 void ContentParent::MarkAsDead() {
1825 MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose
,
1826 ("Marking ContentProcess %p as dead", this));
1827 MOZ_DIAGNOSTIC_ASSERT(!sInProcessSelector
);
1830 // Flag shutdown has started for us to our threadsafe handle.
1832 // Depending on how we get here, the lock might or might not be set.
1833 RecursiveMutexAutoLock
lock(mThreadsafeHandle
->mMutex
);
1835 mThreadsafeHandle
->mShutdownStarted
= true;
1838 // Prevent this process from being re-used.
1839 PreallocatedProcessManager::Erase(this);
1841 #if defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_PROFILE_GENERATE)
1843 // We're intentionally killing the content process at this point to ensure
1844 // that we never have a "dead" content process sitting around and occupying
1845 // an Android Service.
1847 // The exception is in MOZ_PROFILE_GENERATE builds where we must allow the
1848 // process to shutdown cleanly so that profile data can be dumped. This is
1849 // okay as we will not reach our process limit during the profile run.
1850 nsCOMPtr
<nsIEventTarget
> launcherThread(GetIPCLauncher());
1851 MOZ_ASSERT(launcherThread
);
1853 auto procType
= java::GeckoProcessType::CONTENT();
1855 java::GeckoProcessManager::Selector::New(procType
, OtherPid());
1857 launcherThread
->Dispatch(NS_NewRunnableFunction(
1858 "ContentParent::MarkAsDead",
1860 java::GeckoProcessManager::Selector::GlobalRef(selector
)]() {
1861 java::GeckoProcessManager::ShutdownProcess(selector
);
1866 mLifecycleState
= LifecycleState::DEAD
;
1869 void ContentParent::ProcessingError(Result aCode
, const char* aReason
) {
1870 if (MsgDropped
== aCode
) {
1873 // Other errors are big deals.
1878 GetIPCChannel()->InduceConnectionError();
1882 void ContentParent::ActorDestroy(ActorDestroyReason why
) {
1883 #ifdef FUZZING_SNAPSHOT
1884 MOZ_FUZZING_IPC_DROP_PEER("ContentParent::ActorDestroy");
1887 // Gather process lifetime telemetry.
1888 if (StringBeginsWith(mRemoteType
, WEB_REMOTE_TYPE
) ||
1889 mRemoteType
== FILE_REMOTE_TYPE
|| mRemoteType
== EXTENSION_REMOTE_TYPE
) {
1890 TimeDuration runtime
= TimeStamp::Now() - mActivateTS
;
1891 Telemetry::Accumulate(Telemetry::PROCESS_LIFETIME
,
1892 uint64_t(runtime
.ToSeconds()));
1895 if (mSendShutdownTimer
) {
1896 mSendShutdownTimer
->Cancel();
1897 mSendShutdownTimer
= nullptr;
1899 if (mForceKillTimer
) {
1900 mForceKillTimer
->Cancel();
1901 mForceKillTimer
= nullptr;
1904 // Signal shutdown completion regardless of error state, so we can
1905 // finish waiting in the xpcom-shutdown/profile-before-change observer.
1906 RemoveShutdownBlockers();
1908 if (mHangMonitorActor
) {
1909 ProcessHangMonitor::RemoveProcess(mHangMonitorActor
);
1910 mHangMonitorActor
= nullptr;
1913 RefPtr
<FileSystemSecurity
> fss
= FileSystemSecurity::Get();
1915 fss
->Forget(ChildID());
1918 if (why
== NormalShutdown
&& !mCalledClose
) {
1919 // If we shut down normally but haven't called Close, assume somebody
1920 // else called Close on us. In that case, we still need to call
1921 // ShutDownProcess below to perform other necessary clean up.
1922 mCalledClose
= true;
1925 // Make sure we always clean up.
1926 ShutDownProcess(CLOSE_CHANNEL
);
1928 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
1930 size_t length
= ArrayLength(sObserverTopics
);
1931 for (size_t i
= 0; i
< length
; ++i
) {
1932 obs
->RemoveObserver(static_cast<nsIObserver
*>(this), sObserverTopics
[i
]);
1936 // remove the global remote preferences observers
1937 Preferences::RemoveObserver(this, "");
1938 gfxVars::RemoveReceiver(this);
1940 if (GPUProcessManager
* gpu
= GPUProcessManager::Get()) {
1941 // Note: the manager could have shutdown already.
1942 gpu
->RemoveListener(this);
1945 RecvRemoveGeolocationListener();
1947 // Destroy our JSProcessActors, and reject any pending queries.
1948 JSActorDidDestroy();
1951 RefPtr
<nsHashPropertyBag
> props
= new nsHashPropertyBag();
1953 props
->SetPropertyAsUint64(u
"childID"_ns
, mChildID
);
1955 if (AbnormalShutdown
== why
) {
1956 Telemetry::Accumulate(Telemetry::SUBPROCESS_ABNORMAL_ABORT
, "content"_ns
,
1959 props
->SetPropertyAsBool(u
"abnormal"_ns
, true);
1961 nsAutoString dumpID
;
1962 // There's a window in which child processes can crash
1963 // after IPC is established, but before a crash reporter
1965 if (mCrashReporter
) {
1966 // if mCreatedPairedMinidumps is true, we've already generated
1967 // parent/child dumps for desktop crashes.
1968 if (!mCreatedPairedMinidumps
) {
1969 #if defined(XP_MACOSX)
1970 RefPtr
<nsAvailableMemoryWatcherBase
> memWatcher
;
1971 memWatcher
= nsAvailableMemoryWatcherBase::GetSingleton();
1972 memWatcher
->AddChildAnnotations(mCrashReporter
);
1975 mCrashReporter
->GenerateCrashReport(OtherPid());
1978 if (mCrashReporter
->HasMinidump()) {
1979 dumpID
= mCrashReporter
->MinidumpID();
1982 HandleOrphanedMinidump(&dumpID
);
1985 if (!dumpID
.IsEmpty()) {
1986 props
->SetPropertyAsAString(u
"dumpID"_ns
, dumpID
);
1990 cpId
.AppendInt(static_cast<uint64_t>(this->ChildID()));
1991 obs
->NotifyObservers((nsIPropertyBag2
*)props
, "ipc:content-shutdown",
1995 // Remove any and all idle listeners.
1996 if (mIdleListeners
.Length() > 0) {
1997 nsCOMPtr
<nsIUserIdleService
> idleService
=
1998 do_GetService("@mozilla.org/widget/useridleservice;1");
2000 RefPtr
<ParentIdleListener
> listener
;
2001 for (const auto& lentry
: mIdleListeners
) {
2002 listener
= static_cast<ParentIdleListener
*>(lentry
.get());
2003 idleService
->RemoveIdleObserver(listener
, listener
->mTime
);
2006 mIdleListeners
.Clear();
2009 MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose
,
2010 ("destroying Subprocess in ActorDestroy: ContentParent %p "
2011 "mSubprocess %p handle %" PRIuPTR
,
2013 mSubprocess
? (uintptr_t)mSubprocess
->GetChildProcessHandle() : -1));
2014 // FIXME (bug 1520997): does this really need an additional dispatch?
2015 if (GetCurrentSerialEventTarget()) {
2016 GetCurrentSerialEventTarget()->Dispatch(NS_NewRunnableFunction(
2017 "DelayedDeleteSubprocessRunnable", [subprocess
= mSubprocess
] {
2018 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
2019 ("destroyed Subprocess in ActorDestroy: Subprocess %p handle "
2022 subprocess
? (uintptr_t)subprocess
->GetChildProcessHandle()
2024 subprocess
->Destroy();
2027 mSubprocess
= nullptr;
2029 ContentProcessManager
* cpm
= ContentProcessManager::GetSingleton();
2031 cpm
->RemoveContentProcess(this->ChildID());
2034 if (mDriverCrashGuard
) {
2035 mDriverCrashGuard
->NotifyCrashed();
2038 // Unregister all the BlobURLs registered by the ContentChild.
2039 for (uint32_t i
= 0; i
< mBlobURLs
.Length(); ++i
) {
2040 BlobURLProtocolHandler::RemoveDataEntry(mBlobURLs
[i
]);
2045 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2049 // As this process is going away, ensure that every BrowsingContext hosted by
2050 // it has been detached, and every BrowsingContextGroup has been fully
2052 BrowsingContext::DiscardFromContentParent(this);
2054 const nsTHashSet
<RefPtr
<BrowsingContextGroup
>> groups
= std::move(mGroups
);
2055 for (const auto& group
: groups
) {
2056 group
->Unsubscribe(this);
2058 MOZ_DIAGNOSTIC_ASSERT(mGroups
.IsEmpty());
2060 mPendingLoadStates
.Clear();
2063 UniqueContentParentKeepAlive
ContentParent::TryAddKeepAlive(
2064 uint64_t aBrowserId
) {
2065 return UniqueContentParentKeepAliveFromThreadsafe(
2066 mThreadsafeHandle
->TryAddKeepAlive(aBrowserId
));
2069 UniqueContentParentKeepAlive
ContentParent::AddKeepAlive(uint64_t aBrowserId
) {
2070 UniqueContentParentKeepAlive keepAlive
= TryAddKeepAlive(aBrowserId
);
2071 MOZ_DIAGNOSTIC_ASSERT(keepAlive
, "ContentParent is already dead");
2075 void ContentParent::RemoveKeepAlive(uint64_t aBrowserId
) {
2076 AssertIsOnMainThread();
2079 RecursiveMutexAutoLock
lock(mThreadsafeHandle
->mMutex
);
2080 auto entry
= mThreadsafeHandle
->mKeepAlivesPerBrowserId
.Lookup(aBrowserId
);
2081 MOZ_RELEASE_ASSERT(entry
, "No KeepAlive for this BrowserId");
2082 if (!--entry
.Data()) {
2087 MaybeBeginShutDown();
2090 bool ContentParent::MaybeBeginShutDown(bool aIgnoreKeepAlivePref
) {
2091 AssertIsOnMainThread();
2094 RecursiveMutexAutoLock
lock(mThreadsafeHandle
->mMutex
);
2095 // If we still have keepalives or are still launching, we're not shutting
2097 if (IsLaunching() ||
2098 !mThreadsafeHandle
->mKeepAlivesPerBrowserId
.IsEmpty()) {
2102 // If we're not in main process shutdown, we might want to keep some content
2103 // processes alive for performance reasons (e.g. test runs and privileged
2104 // content process for some about: pages). We don't want to alter behavior
2105 // if the pref is not set, so default to 0.
2106 if (!aIgnoreKeepAlivePref
&& mIsInPool
&&
2107 !AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed
)) {
2108 auto* contentParents
= sBrowserContentParents
->Get(mRemoteType
);
2111 "mIsInPool, yet no entry for mRemoteType in sBrowserContentParents?");
2113 nsAutoCString
keepAlivePref("dom.ipc.keepProcessesAlive.");
2114 if (StringBeginsWith(mRemoteType
, FISSION_WEB_REMOTE_TYPE
) &&
2115 xpc::IsInAutomation()) {
2116 keepAlivePref
.Append(FISSION_WEB_REMOTE_TYPE
);
2117 keepAlivePref
.AppendLiteral(".perOrigin");
2119 keepAlivePref
.Append(mRemoteType
);
2122 int32_t processesToKeepAlive
= 0;
2123 if (NS_SUCCEEDED(Preferences::GetInt(keepAlivePref
.get(),
2124 &processesToKeepAlive
)) &&
2125 contentParents
->Length() <=
2126 static_cast<size_t>(processesToKeepAlive
)) {
2127 // We're keeping this process alive even though there are no keepalives
2128 // for it due to the keepalive pref.
2133 // We're not keeping this process alive, begin shutdown.
2134 mThreadsafeHandle
->mShutdownStarted
= true;
2138 SignalImpendingShutdownToContentJS();
2140 if (ManagedPBrowserParent().Count() > 0) {
2141 // We still have PBrowser instances which have not been shut down.
2142 // Wait for them to be destroyed before we follow-through and shut down this
2143 // process, but start a shutdown timer to kill them if this takes too long.
2144 StartSendShutdownTimer();
2146 // All tabs are dead, we can fully begin shutting down.
2147 AsyncSendShutDownMessage();
2152 void ContentParent::StartSendShutdownTimer() {
2153 if (mSendShutdownTimer
|| !CanSend()) {
2157 uint32_t timeoutSecs
= StaticPrefs::dom_ipc_tabs_shutdownTimeoutSecs();
2158 if (timeoutSecs
> 0) {
2159 NS_NewTimerWithFuncCallback(getter_AddRefs(mSendShutdownTimer
),
2160 ContentParent::SendShutdownTimerCallback
, this,
2161 timeoutSecs
* 1000, nsITimer::TYPE_ONE_SHOT
,
2162 "dom::ContentParent::StartSendShutdownTimer");
2163 MOZ_ASSERT(mSendShutdownTimer
);
2167 void ContentParent::StartForceKillTimer() {
2168 if (mForceKillTimer
|| !CanSend()) {
2172 uint32_t timeoutSecs
= StaticPrefs::dom_ipc_tabs_shutdownTimeoutSecs();
2173 if (timeoutSecs
> 0) {
2174 NS_NewTimerWithFuncCallback(getter_AddRefs(mForceKillTimer
),
2175 ContentParent::ForceKillTimerCallback
, this,
2176 timeoutSecs
* 1000, nsITimer::TYPE_ONE_SHOT
,
2177 "dom::ContentParent::StartForceKillTimer");
2178 MOZ_ASSERT(mForceKillTimer
);
2182 TestShellParent
* ContentParent::CreateTestShell() {
2183 RefPtr
<TestShellParent
> actor
= new TestShellParent();
2184 if (!SendPTestShellConstructor(actor
)) {
2190 bool ContentParent::DestroyTestShell(TestShellParent
* aTestShell
) {
2191 return PTestShellParent::Send__delete__(aTestShell
);
2194 TestShellParent
* ContentParent::GetTestShellSingleton() {
2195 PTestShellParent
* p
= LoneManagedOrNullAsserts(ManagedPTestShellParent());
2196 return static_cast<TestShellParent
*>(p
);
2199 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
2200 // Append the sandbox command line parameters that are not static. i.e.,
2201 // parameters that can be different for different child processes.
2202 void ContentParent::AppendDynamicSandboxParams(
2203 std::vector
<std::string
>& aArgs
) {
2204 // For file content processes
2205 if (GetRemoteType() == FILE_REMOTE_TYPE
) {
2206 MacSandboxInfo::AppendFileAccessParam(aArgs
, true);
2210 // Generate the static sandbox command line parameters and store
2211 // them in the provided params vector to be used each time a new
2212 // content process is launched.
2213 static void CacheSandboxParams(std::vector
<std::string
>& aCachedParams
) {
2214 // This must only be called once and we should
2215 // be starting with an empty list of parameters.
2216 MOZ_ASSERT(aCachedParams
.empty());
2218 MacSandboxInfo info
;
2219 info
.type
= MacSandboxType_Content
;
2220 info
.level
= GetEffectiveContentSandboxLevel();
2223 if (Preferences::GetBool("security.sandbox.logging.enabled") ||
2224 PR_GetEnv("MOZ_SANDBOX_LOGGING")) {
2225 info
.shouldLog
= true;
2229 if (!StaticPrefs::media_cubeb_sandbox()) {
2230 info
.hasAudio
= true;
2233 // Window server access. If the disconnect-windowserver pref is not
2234 // "true" or out-of-process WebGL is not enabled, allow window server
2235 // access in the sandbox policy.
2236 if (!Preferences::GetBool(
2237 "security.sandbox.content.mac.disconnect-windowserver") ||
2238 !Preferences::GetBool("webgl.out-of-process")) {
2239 info
.hasWindowServer
= true;
2242 // .app path (normalized)
2243 nsAutoCString appPath
;
2244 if (!nsMacUtilsImpl::GetAppPath(appPath
)) {
2245 MOZ_CRASH("Failed to get app dir paths");
2247 info
.appPath
= appPath
.get();
2249 // TESTING_READ_PATH1
2250 nsAutoCString testingReadPath1
;
2251 Preferences::GetCString("security.sandbox.content.mac.testing_read_path1",
2253 if (!testingReadPath1
.IsEmpty()) {
2254 info
.testingReadPath1
= testingReadPath1
.get();
2257 // TESTING_READ_PATH2
2258 nsAutoCString testingReadPath2
;
2259 Preferences::GetCString("security.sandbox.content.mac.testing_read_path2",
2261 if (!testingReadPath2
.IsEmpty()) {
2262 info
.testingReadPath2
= testingReadPath2
.get();
2265 // TESTING_READ_PATH3, TESTING_READ_PATH4. In non-packaged builds,
2266 // these are used to whitelist the repo dir and object dir respectively.
2268 if (!mozilla::IsPackagedBuild()) {
2270 nsCOMPtr
<nsIFile
> repoDir
;
2271 rv
= nsMacUtilsImpl::GetRepoDir(getter_AddRefs(repoDir
));
2272 if (NS_FAILED(rv
)) {
2273 MOZ_CRASH("Failed to get path to repo dir");
2275 nsCString repoDirPath
;
2276 Unused
<< repoDir
->GetNativePath(repoDirPath
);
2277 info
.testingReadPath3
= repoDirPath
.get();
2280 nsCOMPtr
<nsIFile
> objDir
;
2281 rv
= nsMacUtilsImpl::GetObjDir(getter_AddRefs(objDir
));
2282 if (NS_FAILED(rv
)) {
2283 MOZ_CRASH("Failed to get path to build object dir");
2285 nsCString objDirPath
;
2286 Unused
<< objDir
->GetNativePath(objDirPath
);
2287 info
.testingReadPath4
= objDirPath
.get();
2292 // For bloat/leak logging or when a content process dies intentionally
2293 // (|NoteIntentionalCrash|) for tests, it wants to log that it did this.
2294 // Allow writing to this location.
2295 nsAutoCString bloatLogDirPath
;
2296 if (NS_SUCCEEDED(nsMacUtilsImpl::GetBloatLogDir(bloatLogDirPath
))) {
2297 info
.debugWriteDir
= bloatLogDirPath
.get();
2301 info
.AppendAsParams(aCachedParams
);
2304 // Append sandboxing command line parameters.
2305 void ContentParent::AppendSandboxParams(std::vector
<std::string
>& aArgs
) {
2306 MOZ_ASSERT(sMacSandboxParams
!= nullptr);
2308 // An empty sMacSandboxParams indicates this is the
2309 // first invocation and we don't have cached params yet.
2310 if (sMacSandboxParams
->empty()) {
2311 CacheSandboxParams(*sMacSandboxParams
);
2312 MOZ_ASSERT(!sMacSandboxParams
->empty());
2315 // Append cached arguments.
2316 aArgs
.insert(aArgs
.end(), sMacSandboxParams
->begin(),
2317 sMacSandboxParams
->end());
2319 // Append remaining arguments.
2320 AppendDynamicSandboxParams(aArgs
);
2322 #endif // XP_MACOSX && MOZ_SANDBOX
2324 bool ContentParent::BeginSubprocessLaunch(ProcessPriority aPriority
) {
2325 AUTO_PROFILER_LABEL("ContentParent::LaunchSubprocess", OTHER
);
2327 // Ensure we will not rush through our shutdown phases while launching.
2328 // LaunchSubprocessReject will remove them in case of failure,
2329 // otherwise ActorDestroy will take care.
2330 AddShutdownBlockers();
2332 if (!ContentProcessManager::GetSingleton()) {
2333 MOZ_ASSERT(false, "Unable to acquire ContentProcessManager singleton!");
2337 std::vector
<std::string
> extraArgs
;
2338 geckoargs::sChildID
.Put(mChildID
, extraArgs
);
2339 geckoargs::sIsForBrowser
.Put(IsForBrowser(), extraArgs
);
2340 geckoargs::sNotForBrowser
.Put(!IsForBrowser(), extraArgs
);
2342 // Prefs information is passed via anonymous shared memory to avoid bloating
2343 // the command line.
2345 // Instantiate the pref serializer. It will be cleaned up in
2346 // `LaunchSubprocessReject`/`LaunchSubprocessResolve`.
2347 mPrefSerializer
= MakeUnique
<mozilla::ipc::SharedPreferenceSerializer
>();
2348 if (!mPrefSerializer
->SerializeToSharedMemory(GeckoProcessType_Content
,
2350 NS_WARNING("SharedPreferenceSerializer::SerializeToSharedMemory failed");
2354 mPrefSerializer
->AddSharedPrefCmdLineArgs(*mSubprocess
, extraArgs
);
2356 // The JS engine does some computation during the initialization which can be
2357 // shared across processes. We add command line arguments to pass a file
2358 // handle and its content length, to minimize the startup time of content
2360 ::mozilla::ipc::ExportSharedJSInit(*mSubprocess
, extraArgs
);
2362 // Register ContentParent as an observer for changes to any pref
2363 // whose prefix matches the empty string, i.e. all of them. The
2364 // observation starts here in order to capture pref updates that
2365 // happen during async launch.
2366 Preferences::AddStrongObserver(this, "");
2369 geckoargs::sSafeMode
.Put(extraArgs
);
2372 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
2373 if (IsContentSandboxEnabled()) {
2374 AppendSandboxParams(extraArgs
);
2375 mSubprocess
->DisableOSActivityMode();
2379 nsCString
parentBuildID(mozilla::PlatformBuildID());
2380 geckoargs::sParentBuildID
.Put(parentBuildID
.get(), extraArgs
);
2382 #ifdef MOZ_WIDGET_GTK
2383 // This is X11-only pending a solution for WebGL in Wayland mode.
2384 if (StaticPrefs::dom_ipc_avoid_gtk() && widget::GdkIsX11Display()) {
2385 mSubprocess
->SetEnv("MOZ_HEADLESS", "1");
2389 mLaunchYieldTS
= TimeStamp::Now();
2390 return mSubprocess
->AsyncLaunch(std::move(extraArgs
));
2393 void ContentParent::LaunchSubprocessReject() {
2394 NS_WARNING("failed to launch child in the parent");
2395 MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose
,
2396 ("failed to launch child in the parent"));
2397 // Now that communication with the child is complete, we can cleanup
2398 // the preference serializer.
2399 mPrefSerializer
= nullptr;
2400 if (mIsAPreallocBlocker
) {
2401 PreallocatedProcessManager::RemoveBlocker(mRemoteType
, this);
2402 mIsAPreallocBlocker
= false;
2405 RemoveShutdownBlockers();
2408 bool ContentParent::LaunchSubprocessResolve(bool aIsSync
,
2409 ProcessPriority aPriority
) {
2410 AUTO_PROFILER_LABEL("ContentParent::LaunchSubprocess::resolve", OTHER
);
2412 if (mLaunchResolved
) {
2413 // We've already been called, return.
2414 MOZ_ASSERT(sCreatedFirstContentProcess
);
2415 MOZ_ASSERT(!mPrefSerializer
);
2416 MOZ_ASSERT(mLifecycleState
!= LifecycleState::LAUNCHING
);
2417 return mLaunchResolvedOk
;
2419 mLaunchResolved
= true;
2421 // Now that communication with the child is complete, we can cleanup
2422 // the preference serializer.
2423 mPrefSerializer
= nullptr;
2425 const auto launchResumeTS
= TimeStamp::Now();
2426 if (profiler_thread_is_being_profiled_for_markers()) {
2427 nsPrintfCString
marker("Process start%s for %u",
2428 mIsAPreallocBlocker
? " (immediate)" : "",
2429 (unsigned int)ChildID());
2430 PROFILER_MARKER_TEXT(
2431 mIsAPreallocBlocker
? ProfilerString8View("Process Immediate Launch")
2432 : ProfilerString8View("Process Launch"),
2433 DOM
, MarkerTiming::Interval(mLaunchTS
, launchResumeTS
), marker
);
2436 if (!sCreatedFirstContentProcess
) {
2437 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
2438 obs
->NotifyObservers(nullptr, "ipc:first-content-process-created", nullptr);
2439 sCreatedFirstContentProcess
= true;
2442 mSubprocess
->TakeInitialEndpoint().Bind(this);
2444 ContentProcessManager
* cpm
= ContentProcessManager::GetSingleton();
2446 NS_WARNING("immediately shutting-down caused by our shutdown");
2447 ShutDownProcess(SEND_SHUTDOWN_MESSAGE
);
2450 cpm
->AddContentProcess(this);
2452 #ifdef MOZ_CODE_COVERAGE
2453 Unused
<< SendShareCodeCoverageMutex(
2454 CodeCoverageHandler::Get()->GetMutexHandle());
2457 // We must be in the LAUNCHING state still. If we've somehow already been
2458 // marked as DEAD, fail the process launch, and immediately begin tearing down
2459 // the content process.
2461 NS_WARNING("immediately shutting-down already-dead process");
2462 ShutDownProcess(SEND_SHUTDOWN_MESSAGE
);
2465 MOZ_ASSERT(mLifecycleState
== LifecycleState::LAUNCHING
);
2466 mLifecycleState
= LifecycleState::ALIVE
;
2468 if (!InitInternal(aPriority
)) {
2469 NS_WARNING("failed to initialize child in the parent");
2470 // We've already called Open() by this point, so we need to close the
2471 // channel to avoid leaking the process.
2472 ShutDownProcess(SEND_SHUTDOWN_MESSAGE
);
2476 mHangMonitorActor
= ProcessHangMonitor::AddProcess(this);
2478 // Set a reply timeout for CPOWs.
2479 SetReplyTimeoutMs(StaticPrefs::dom_ipc_cpow_timeout());
2481 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
2484 cpId
.AppendInt(static_cast<uint64_t>(this->ChildID()));
2485 obs
->NotifyObservers(static_cast<nsIObserver
*>(this),
2486 "ipc:content-initializing", cpId
.get());
2491 mLifecycleState
= LifecycleState::INITIALIZED
;
2494 Telemetry::AccumulateTimeDelta(Telemetry::CONTENT_PROCESS_SYNC_LAUNCH_MS
,
2497 Telemetry::AccumulateTimeDelta(Telemetry::CONTENT_PROCESS_LAUNCH_TOTAL_MS
,
2500 Telemetry::Accumulate(
2501 Telemetry::CONTENT_PROCESS_LAUNCH_MAINTHREAD_MS
,
2502 static_cast<uint32_t>(
2503 ((mLaunchYieldTS
- mLaunchTS
) + (TimeStamp::Now() - launchResumeTS
))
2504 .ToMilliseconds()));
2507 mLaunchResolvedOk
= true;
2511 ContentParent::ContentParent(const nsACString
& aRemoteType
)
2512 : mSubprocess(nullptr),
2513 mLaunchTS(TimeStamp::Now()),
2514 mLaunchYieldTS(mLaunchTS
),
2515 mActivateTS(mLaunchTS
),
2516 mIsAPreallocBlocker(false),
2517 mRemoteType(aRemoteType
),
2518 mChildID(gContentChildID
++),
2519 mGeolocationWatchID(-1),
2521 new ThreadsafeContentParentHandle(this, mChildID
, mRemoteType
)),
2522 mLifecycleState(LifecycleState::LAUNCHING
),
2523 mIsForBrowser(!mRemoteType
.IsEmpty()),
2524 mCalledClose(false),
2525 mCalledKillHard(false),
2526 mCreatedPairedMinidumps(false),
2527 mShutdownPending(false),
2528 mLaunchResolved(false),
2529 mLaunchResolvedOk(false),
2530 mIsRemoteInputEventQueueEnabled(false),
2531 mIsInputPriorityEventEnabled(false),
2534 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2535 mBlockShutdownCalled(false),
2537 mHangMonitorActor(nullptr) {
2538 mRemoteTypeIsolationPrincipal
=
2539 CreateRemoteTypeIsolationPrincipal(aRemoteType
);
2541 // Insert ourselves into the global linked list of ContentParent objects.
2542 if (!sContentParents
) {
2543 sContentParents
= new LinkedList
<ContentParent
>();
2545 sContentParents
->insertBack(this);
2547 mMessageManager
= nsFrameMessageManager::NewProcessMessageManager(true);
2550 // Request Windows message deferral behavior on our side of the PContent
2551 // channel. Generally only applies to the situation where we get caught in
2552 // a deadlock with the plugin process when sending CPOWs.
2553 GetIPCChannel()->SetChannelFlags(
2554 MessageChannel::REQUIRE_DEFERRED_MESSAGE_PROTECTION
);
2557 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
2558 bool isFile
= mRemoteType
== FILE_REMOTE_TYPE
;
2559 mSubprocess
= new GeckoChildProcessHost(GeckoProcessType_Content
, isFile
);
2560 MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose
,
2561 ("CreateSubprocess: ContentParent %p mSubprocess %p handle %" PRIuPTR
,
2563 mSubprocess
? (uintptr_t)mSubprocess
->GetChildProcessHandle() : -1));
2566 ContentParent::~ContentParent() {
2567 if (mSendShutdownTimer
) {
2568 mSendShutdownTimer
->Cancel();
2570 if (mForceKillTimer
) {
2571 mForceKillTimer
->Cancel();
2574 AssertIsOnMainThread();
2576 // Clear the weak reference from the threadsafe handle back to this actor.
2577 mThreadsafeHandle
->mWeakActor
= nullptr;
2579 if (mIsAPreallocBlocker
) {
2580 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
2581 ("Removing blocker on ContentProcess destruction"));
2582 PreallocatedProcessManager::RemoveBlocker(mRemoteType
, this);
2583 mIsAPreallocBlocker
= false;
2586 // We should be removed from all these lists in ActorDestroy.
2589 // Normally mSubprocess is destroyed in ActorDestroy, but that won't
2590 // happen if the process wasn't launched or if it failed to launch.
2593 ContentParent::GetLog(), LogLevel::Verbose
,
2594 ("DestroySubprocess: ContentParent %p mSubprocess %p handle %" PRIuPTR
,
2596 mSubprocess
? (uintptr_t)mSubprocess
->GetChildProcessHandle() : -1));
2597 mSubprocess
->Destroy();
2601 bool ContentParent::InitInternal(ProcessPriority aInitialPriority
) {
2602 // We can't access the locale service after shutdown has started. Since we
2603 // can't init the process without it, and since we're going to be canceling
2604 // whatever load attempt that initiated this process creation anyway, just
2605 // bail out now if shutdown has already started.
2606 if (PastShutdownPhase(ShutdownPhase::XPCOMShutdown
)) {
2610 XPCOMInitData xpcomInit
;
2612 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
2613 ("ContentParent::InitInternal: %p", (void*)this));
2614 nsCOMPtr
<nsIIOService
> io(do_GetIOService());
2615 MOZ_ASSERT(io
, "No IO service?");
2616 DebugOnly
<nsresult
> rv
= io
->GetOffline(&xpcomInit
.isOffline());
2617 MOZ_ASSERT(NS_SUCCEEDED(rv
), "Failed getting offline?");
2619 rv
= io
->GetConnectivity(&xpcomInit
.isConnected());
2620 MOZ_ASSERT(NS_SUCCEEDED(rv
), "Failed getting connectivity?");
2622 xpcomInit
.captivePortalState() = nsICaptivePortalService::UNKNOWN
;
2623 nsCOMPtr
<nsICaptivePortalService
> cps
=
2624 do_GetService(NS_CAPTIVEPORTAL_CONTRACTID
);
2626 cps
->GetState(&xpcomInit
.captivePortalState());
2629 if (StaticPrefs::fission_processProfileName()) {
2630 nsCOMPtr
<nsIToolkitProfileService
> profileSvc
=
2631 do_GetService(NS_PROFILESERVICE_CONTRACTID
);
2633 nsCOMPtr
<nsIToolkitProfile
> currentProfile
;
2635 profileSvc
->GetCurrentProfile(getter_AddRefs(currentProfile
));
2636 if (NS_SUCCEEDED(rv
) && currentProfile
) {
2637 currentProfile
->GetName(mProfile
);
2642 nsIBidiKeyboard
* bidi
= nsContentUtils::GetBidiKeyboard();
2644 xpcomInit
.isLangRTL() = false;
2645 xpcomInit
.haveBidiKeyboards() = false;
2647 bidi
->IsLangRTL(&xpcomInit
.isLangRTL());
2648 bidi
->GetHaveBidiKeyboards(&xpcomInit
.haveBidiKeyboards());
2651 RefPtr
<mozSpellChecker
> spellChecker(mozSpellChecker::Create());
2652 MOZ_ASSERT(spellChecker
, "No spell checker?");
2654 spellChecker
->GetDictionaryList(&xpcomInit
.dictionaries());
2656 LocaleService::GetInstance()->GetAppLocalesAsBCP47(xpcomInit
.appLocales());
2657 LocaleService::GetInstance()->GetRequestedLocales(
2658 xpcomInit
.requestedLocales());
2660 L10nRegistry::GetParentProcessFileSourceDescriptors(
2661 xpcomInit
.l10nFileSources());
2663 nsCOMPtr
<nsIClipboard
> clipboard(
2664 do_GetService("@mozilla.org/widget/clipboard;1"));
2665 MOZ_ASSERT(clipboard
, "No clipboard?");
2667 clipboard
->IsClipboardTypeSupported(nsIClipboard::kGlobalClipboard
),
2668 "We should always support the global clipboard.");
2670 xpcomInit
.clipboardCaps().supportsSelectionClipboard() =
2671 clipboard
->IsClipboardTypeSupported(nsIClipboard::kSelectionClipboard
);
2673 xpcomInit
.clipboardCaps().supportsFindClipboard() =
2674 clipboard
->IsClipboardTypeSupported(nsIClipboard::kFindClipboard
);
2676 xpcomInit
.clipboardCaps().supportsSelectionCache() =
2677 clipboard
->IsClipboardTypeSupported(nsIClipboard::kSelectionCache
);
2679 // Let's copy the domain policy from the parent to the child (if it's active).
2680 StructuredCloneData initialData
;
2681 nsIScriptSecurityManager
* ssm
= nsContentUtils::GetSecurityManager();
2683 ssm
->CloneDomainPolicy(&xpcomInit
.domainPolicy());
2685 if (ParentProcessMessageManager
* mm
=
2686 nsFrameMessageManager::sParentProcessManager
) {
2688 if (NS_WARN_IF(!jsapi
.Init(xpc::PrivilegedJunkScope()))) {
2691 JS::Rooted
<JS::Value
> init(jsapi
.cx());
2692 // We'll crash on failure, so use a IgnoredErrorResult (which also
2693 // auto-suppresses exceptions).
2694 IgnoredErrorResult rv
;
2695 mm
->GetInitialProcessData(jsapi
.cx(), &init
, rv
);
2696 if (NS_WARN_IF(rv
.Failed())) {
2700 initialData
.Write(jsapi
.cx(), init
, rv
);
2701 if (NS_WARN_IF(rv
.Failed())) {
2706 // This is only implemented (returns a non-empty list) by MacOSX and Linux
2708 SystemFontList fontList
;
2709 gfxPlatform::GetPlatform()->ReadSystemFontList(&fontList
);
2711 const FullLookAndFeel
& lnf
= *RemoteLookAndFeel::ExtractData();
2713 // If the shared fontlist is in use, collect its shmem block handles to pass
2715 nsTArray
<SharedMemoryHandle
> sharedFontListBlocks
;
2716 gfxPlatformFontList::PlatformFontList()->ShareFontListToProcess(
2717 &sharedFontListBlocks
, OtherPid());
2719 // Content processes have no permission to access profile directory, so we
2720 // send the file URL instead.
2721 auto* sheetCache
= GlobalStyleSheetCache::Singleton();
2722 if (StyleSheet
* ucs
= sheetCache
->GetUserContentSheet()) {
2723 xpcomInit
.userContentSheetURL() = ucs
->GetSheetURI();
2725 xpcomInit
.userContentSheetURL() = nullptr;
2728 // 1. Build ContentDeviceData first, as it may affect some gfxVars.
2729 gfxPlatform::GetPlatform()->BuildContentDeviceData(
2730 &xpcomInit
.contentDeviceData());
2731 // 2. Gather non-default gfxVars.
2732 xpcomInit
.gfxNonDefaultVarUpdates() = gfxVars::FetchNonDefaultVars();
2733 // 3. Start listening for gfxVars updates, to notify content process later on.
2734 gfxVars::AddReceiver(this);
2736 nsCOMPtr
<nsIGfxInfo
> gfxInfo
= components::GfxInfo::Service();
2738 GfxInfoBase
* gfxInfoRaw
= static_cast<GfxInfoBase
*>(gfxInfo
.get());
2739 xpcomInit
.gfxFeatureStatus() = gfxInfoRaw
->GetAllFeatures();
2742 // Send the dynamic scalar definitions to the new process.
2743 TelemetryIPC::GetDynamicScalarDefinitions(xpcomInit
.dynamicScalarDefs());
2745 for (auto const& [location
, supported
] : sCodecsSupported
) {
2746 Unused
<< SendUpdateMediaCodecsSupported(location
, supported
);
2749 // Must send screen info before send initialData
2750 ScreenManager
& screenManager
= ScreenManager::GetSingleton();
2751 screenManager
.CopyScreensToRemote(this);
2753 // Send the UA sheet shared memory buffer and the address it is mapped at.
2754 Maybe
<SharedMemoryHandle
> sharedUASheetHandle
;
2755 uintptr_t sharedUASheetAddress
= sheetCache
->GetSharedMemoryAddress();
2757 if (SharedMemoryHandle handle
= sheetCache
->CloneHandle()) {
2758 sharedUASheetHandle
.emplace(std::move(handle
));
2760 sharedUASheetAddress
= 0;
2763 bool isReadyForBackgroundProcessing
= false;
2765 RefPtr
<DllServices
> dllSvc(DllServices::Get());
2766 isReadyForBackgroundProcessing
= dllSvc
->IsReadyForBackgroundProcessing();
2769 xpcomInit
.perfStatsMask() = PerfStats::GetCollectionMask();
2771 nsCOMPtr
<nsIDNSService
> dns
= do_GetService(NS_DNSSERVICE_CONTRACTID
);
2772 dns
->GetTrrDomain(xpcomInit
.trrDomain());
2774 nsIDNSService::ResolverMode mode
;
2775 dns
->GetCurrentTrrMode(&mode
);
2776 xpcomInit
.trrMode() = mode
;
2777 xpcomInit
.trrModeFromPref() =
2778 static_cast<nsIDNSService::ResolverMode
>(StaticPrefs::network_trr_mode());
2780 Unused
<< SendSetXPCOMProcessAttributes(
2781 xpcomInit
, initialData
, lnf
, fontList
, std::move(sharedUASheetHandle
),
2782 sharedUASheetAddress
, std::move(sharedFontListBlocks
),
2783 isReadyForBackgroundProcessing
);
2785 ipc::WritableSharedMap
* sharedData
=
2786 nsFrameMessageManager::sParentProcessManager
->SharedData();
2787 sharedData
->Flush();
2788 sharedData
->SendTo(this);
2790 nsCOMPtr
<nsIChromeRegistry
> registrySvc
= nsChromeRegistry::GetService();
2791 nsChromeRegistryChrome
* chromeRegistry
=
2792 static_cast<nsChromeRegistryChrome
*>(registrySvc
.get());
2793 chromeRegistry
->SendRegisteredChrome(this);
2795 nsCOMPtr
<nsIStringBundleService
> stringBundleService
=
2796 components::StringBundle::Service();
2797 stringBundleService
->SendContentBundles(this);
2800 nsCString
version(gAppData
->version
);
2801 nsCString
buildID(gAppData
->buildID
);
2802 nsCString
name(gAppData
->name
);
2803 nsCString
UAName(gAppData
->UAName
);
2804 nsCString
ID(gAppData
->ID
);
2805 nsCString
vendor(gAppData
->vendor
);
2806 nsCString
sourceURL(gAppData
->sourceURL
);
2807 nsCString
updateURL(gAppData
->updateURL
);
2809 // Sending all information to content process.
2810 Unused
<< SendAppInfo(version
, buildID
, name
, UAName
, ID
, vendor
, sourceURL
,
2814 // Send the child its remote type. On Mac, this needs to be sent prior
2815 // to the message we send to enable the Sandbox (SendStartProcessSandbox)
2816 // because different remote types require different sandbox privileges.
2818 Unused
<< SendRemoteType(mRemoteType
, mProfile
);
2820 if (mRemoteType
!= PREALLOC_REMOTE_TYPE
) {
2821 StartRemoteWorkerService();
2824 ScriptPreloader::InitContentChild(*this);
2826 // Initialize the message manager (and load delayed scripts) now that we
2827 // have established communications with the child.
2828 mMessageManager
->InitWithCallback(this);
2829 mMessageManager
->SetOsPid(Pid());
2831 // Set the subprocess's priority. We do this early on because we're likely
2832 // /lowering/ the process's CPU and memory priority, which it has inherited
2833 // from this process.
2835 // This call can cause us to send IPC messages to the child process, so it
2836 // must come after the Open() call above.
2837 ProcessPriorityManager::SetProcessPriority(this, aInitialPriority
);
2839 // NB: internally, this will send an IPC message to the child
2840 // process to get it to create the CompositorBridgeChild. This
2841 // message goes through the regular IPC queue for this
2842 // channel, so delivery will happen-before any other messages
2843 // we send. The CompositorBridgeChild must be created before any
2844 // PBrowsers are created, because they rely on the Compositor
2845 // already being around. (Creation is async, so can't happen
2847 GPUProcessManager
* gpm
= GPUProcessManager::Get();
2849 Endpoint
<PCompositorManagerChild
> compositor
;
2850 Endpoint
<PImageBridgeChild
> imageBridge
;
2851 Endpoint
<PVRManagerChild
> vrBridge
;
2852 Endpoint
<PRemoteDecoderManagerChild
> videoManager
;
2853 AutoTArray
<uint32_t, 3> namespaces
;
2855 if (!gpm
->CreateContentBridges(OtherPid(), &compositor
, &imageBridge
,
2856 &vrBridge
, &videoManager
, mChildID
,
2858 // This can fail if we've already started shutting down the compositor
2859 // thread. See Bug 1562763 comment 8.
2860 MOZ_ASSERT(AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdown
));
2864 Unused
<< SendInitRendering(std::move(compositor
), std::move(imageBridge
),
2865 std::move(vrBridge
), std::move(videoManager
),
2868 gpm
->AddListener(this);
2870 nsStyleSheetService
* sheetService
= nsStyleSheetService::GetInstance();
2872 // This looks like a lot of work, but in a normal browser session we just
2875 // The URIs of the Gecko and Servo sheets should be the same, so it
2876 // shouldn't matter which we look at.
2878 for (StyleSheet
* sheet
: *sheetService
->AgentStyleSheets()) {
2879 Unused
<< SendLoadAndRegisterSheet(sheet
->GetSheetURI(),
2880 nsIStyleSheetService::AGENT_SHEET
);
2883 for (StyleSheet
* sheet
: *sheetService
->UserStyleSheets()) {
2884 Unused
<< SendLoadAndRegisterSheet(sheet
->GetSheetURI(),
2885 nsIStyleSheetService::USER_SHEET
);
2888 for (StyleSheet
* sheet
: *sheetService
->AuthorStyleSheets()) {
2889 Unused
<< SendLoadAndRegisterSheet(sheet
->GetSheetURI(),
2890 nsIStyleSheetService::AUTHOR_SHEET
);
2895 bool shouldSandbox
= true;
2896 Maybe
<FileDescriptor
> brokerFd
;
2897 // XXX: Checking the pref here makes it possible to enable/disable sandboxing
2898 // during an active session. Currently the pref is only used for testing
2899 // purpose. If the decision is made to permanently rely on the pref, this
2900 // should be changed so that it is required to restart firefox for the change
2901 // of value to take effect. Always send SetProcessSandbox message on macOS.
2902 # if !defined(XP_MACOSX)
2903 shouldSandbox
= IsContentSandboxEnabled();
2907 if (shouldSandbox
) {
2908 MOZ_ASSERT(!mSandboxBroker
);
2909 bool isFileProcess
= mRemoteType
== FILE_REMOTE_TYPE
;
2910 UniquePtr
<SandboxBroker::Policy
> policy
=
2911 sSandboxBrokerPolicyFactory
->GetContentPolicy(Pid(), isFileProcess
);
2913 brokerFd
= Some(FileDescriptor());
2915 SandboxBroker::Create(std::move(policy
), Pid(), brokerFd
.ref());
2916 if (!mSandboxBroker
) {
2917 KillHard("SandboxBroker::Create failed");
2920 MOZ_ASSERT(brokerFd
.ref().IsValid());
2924 if (shouldSandbox
&& !SendSetProcessSandbox(brokerFd
)) {
2925 KillHard("SandboxInitFailed");
2929 // Ensure that the default set of permissions are avaliable in the content
2930 // process before we try to load any URIs in it.
2932 // NOTE: All default permissions has to be transmitted to the child process
2933 // before the blob urls in the for loop below (See Bug 1738713 comment 12).
2934 EnsurePermissionsByKey(""_ns
, ""_ns
);
2937 nsTArray
<BlobURLRegistrationData
> registrations
;
2938 BlobURLProtocolHandler::ForEachBlobURL([&](BlobImpl
* aBlobImpl
,
2939 nsIPrincipal
* aPrincipal
,
2940 const nsCString
& aPartitionKey
,
2941 const nsACString
& aURI
,
2943 // We send all moz-extension Blob URL's to all content processes
2944 // because content scripts mean that a moz-extension can live in any
2945 // process. Same thing for system principal Blob URLs. Content Blob
2946 // URL's are sent for content principals on-demand by
2947 // AboutToLoadHttpDocumentForChild and RemoteWorkerManager.
2948 if (!BlobURLProtocolHandler::IsBlobURLBroadcastPrincipal(aPrincipal
)) {
2953 nsresult rv
= IPCBlobUtils::Serialize(aBlobImpl
, ipcBlob
);
2954 if (NS_WARN_IF(NS_FAILED(rv
))) {
2958 registrations
.AppendElement(
2959 BlobURLRegistrationData(nsCString(aURI
), ipcBlob
, aPrincipal
,
2960 nsCString(aPartitionKey
), aRevoked
));
2962 rv
= TransmitPermissionsForPrincipal(aPrincipal
);
2963 Unused
<< NS_WARN_IF(NS_FAILED(rv
));
2967 if (!registrations
.IsEmpty()) {
2968 Unused
<< SendInitBlobURLs(registrations
);
2972 // Send down { Parent, Window }ActorOptions at startup to content process.
2973 RefPtr
<JSActorService
> actorSvc
= JSActorService::GetSingleton();
2975 nsTArray
<JSProcessActorInfo
> contentInfos
;
2976 actorSvc
->GetJSProcessActorInfos(contentInfos
);
2978 nsTArray
<JSWindowActorInfo
> windowInfos
;
2979 actorSvc
->GetJSWindowActorInfos(windowInfos
);
2981 Unused
<< SendInitJSActorInfos(contentInfos
, windowInfos
);
2984 // Begin subscribing to any BrowsingContextGroups which were hosted by this
2985 // process before it finished launching.
2986 for (const auto& group
: mGroups
) {
2987 group
->Subscribe(this);
2990 MaybeEnableRemoteInputEventQueue();
2995 bool ContentParent::IsAlive() const {
2996 return mLifecycleState
== LifecycleState::ALIVE
||
2997 mLifecycleState
== LifecycleState::INITIALIZED
;
3000 bool ContentParent::IsInitialized() const {
3001 return mLifecycleState
== LifecycleState::INITIALIZED
;
3004 int32_t ContentParent::Pid() const {
3008 auto pid
= mSubprocess
->GetChildProcessId();
3012 return ReleaseAssertedCast
<int32_t>(pid
);
3015 void ContentParent::OnCompositorUnexpectedShutdown() {
3016 GPUProcessManager
* gpm
= GPUProcessManager::Get();
3018 Endpoint
<PCompositorManagerChild
> compositor
;
3019 Endpoint
<PImageBridgeChild
> imageBridge
;
3020 Endpoint
<PVRManagerChild
> vrBridge
;
3021 Endpoint
<PRemoteDecoderManagerChild
> videoManager
;
3022 AutoTArray
<uint32_t, 3> namespaces
;
3024 if (!gpm
->CreateContentBridges(OtherPid(), &compositor
, &imageBridge
,
3025 &vrBridge
, &videoManager
, mChildID
,
3027 MOZ_ASSERT(AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdown
));
3031 Unused
<< SendReinitRendering(std::move(compositor
), std::move(imageBridge
),
3032 std::move(vrBridge
), std::move(videoManager
),
3036 void ContentParent::OnCompositorDeviceReset() {
3037 Unused
<< SendReinitRenderingForDeviceReset();
3040 void ContentParent::MaybeEnableRemoteInputEventQueue() {
3041 MOZ_ASSERT(!mIsRemoteInputEventQueueEnabled
);
3042 if (!IsInputEventQueueSupported()) {
3045 mIsRemoteInputEventQueueEnabled
= true;
3046 Unused
<< SendSetInputEventQueueEnabled();
3047 SetInputPriorityEventEnabled(true);
3050 void ContentParent::SetInputPriorityEventEnabled(bool aEnabled
) {
3051 if (!IsInputEventQueueSupported() || !mIsRemoteInputEventQueueEnabled
||
3052 mIsInputPriorityEventEnabled
== aEnabled
) {
3055 mIsInputPriorityEventEnabled
= aEnabled
;
3056 // Send IPC messages to flush the pending events in the input event queue and
3057 // the normal event queue. See PContent.ipdl for more details.
3058 Unused
<< SendSuspendInputEventQueue();
3059 Unused
<< SendFlushInputEventQueue();
3060 Unused
<< SendResumeInputEventQueue();
3064 bool ContentParent::IsInputEventQueueSupported() {
3065 static bool sSupported
= false;
3066 static bool sInitialized
= false;
3067 if (!sInitialized
) {
3068 MOZ_ASSERT(Preferences::IsServiceAvailable());
3069 sSupported
= Preferences::GetBool("input_event_queue.supported", false);
3070 sInitialized
= true;
3075 void ContentParent::OnVarChanged(const GfxVarUpdate
& aVar
) {
3079 Unused
<< SendVarUpdate(aVar
);
3082 mozilla::ipc::IPCResult
ContentParent::RecvSetClipboard(
3083 const IPCTransferable
& aTransferable
, const int32_t& aWhichClipboard
,
3084 const MaybeDiscarded
<WindowContext
>& aRequestingWindowContext
) {
3085 // aRequestingPrincipal is allowed to be nullptr here.
3087 if (!ValidatePrincipal(aTransferable
.dataPrincipal(),
3088 {ValidatePrincipalOptions::AllowNullPtr
,
3089 ValidatePrincipalOptions::AllowExpanded
,
3090 ValidatePrincipalOptions::AllowSystem
})) {
3091 LogAndAssertFailedPrincipalValidationInfo(aTransferable
.dataPrincipal(),
3096 nsCOMPtr
<nsIClipboard
> clipboard(do_GetService(kCClipboardCID
, &rv
));
3097 NS_ENSURE_SUCCESS(rv
, IPC_OK());
3099 nsCOMPtr
<nsITransferable
> trans
=
3100 do_CreateInstance("@mozilla.org/widget/transferable;1", &rv
);
3101 NS_ENSURE_SUCCESS(rv
, IPC_OK());
3102 trans
->Init(nullptr);
3104 rv
= nsContentUtils::IPCTransferableToTransferable(
3105 aTransferable
, true /* aAddDataFlavor */, trans
,
3106 true /* aFilterUnknownFlavors */);
3107 NS_ENSURE_SUCCESS(rv
, IPC_OK());
3109 // OK if this is null
3110 RefPtr
<WindowGlobalParent
> window
;
3111 if (!aRequestingWindowContext
.IsDiscarded()) {
3112 window
= aRequestingWindowContext
.get_canonical();
3114 clipboard
->SetData(trans
, nullptr, aWhichClipboard
, window
);
3120 static Result
<nsCOMPtr
<nsITransferable
>, nsresult
> CreateTransferable(
3121 const nsTArray
<nsCString
>& aTypes
) {
3123 nsCOMPtr
<nsITransferable
> trans
=
3124 do_CreateInstance("@mozilla.org/widget/transferable;1", &rv
);
3125 if (NS_FAILED(rv
)) {
3129 MOZ_TRY(trans
->Init(nullptr));
3130 // The private flag is only used to prevent the data from being cached to the
3131 // disk. The flag is not exported to the IPCDataTransfer object.
3132 // The flag is set because we are not sure whether the clipboard data is used
3133 // in a private browsing context. The transferable is only used in this scope,
3134 // so the cache would not reduce memory consumption anyway.
3135 trans
->SetIsPrivateData(true);
3136 // Fill out flavors for transferable
3137 for (uint32_t t
= 0; t
< aTypes
.Length(); t
++) {
3138 MOZ_TRY(trans
->AddDataFlavor(aTypes
[t
].get()));
3141 return std::move(trans
);
3144 } // anonymous namespace
3146 mozilla::ipc::IPCResult
ContentParent::RecvGetClipboard(
3147 nsTArray
<nsCString
>&& aTypes
, const int32_t& aWhichClipboard
,
3148 const MaybeDiscarded
<WindowContext
>& aRequestingWindowContext
,
3149 IPCTransferableDataOrError
* aTransferableDataOrError
) {
3151 // We expect content processes to always pass a non-null window so Content
3152 // Analysis can analyze it. (if Content Analysis is active)
3153 // There may be some cases when a window is closing, etc., in
3154 // which case returning no clipboard content should not be a problem.
3155 if (aRequestingWindowContext
.IsDiscarded()) {
3157 "discarded window passed to RecvGetClipboard(); returning no clipboard "
3159 *aTransferableDataOrError
= NS_ERROR_FAILURE
;
3162 if (aRequestingWindowContext
.IsNull()) {
3163 return IPC_FAIL(this, "passed null window to RecvGetClipboard()");
3165 RefPtr
<WindowGlobalParent
> window
= aRequestingWindowContext
.get_canonical();
3166 // Retrieve clipboard
3167 nsCOMPtr
<nsIClipboard
> clipboard(do_GetService(kCClipboardCID
, &rv
));
3168 if (NS_FAILED(rv
)) {
3169 *aTransferableDataOrError
= rv
;
3173 // Create transferable
3174 auto result
= CreateTransferable(aTypes
);
3175 if (result
.isErr()) {
3176 *aTransferableDataOrError
= result
.unwrapErr();
3180 // Get data from clipboard
3181 nsCOMPtr
<nsITransferable
> trans
= result
.unwrap();
3182 rv
= clipboard
->GetData(trans
, aWhichClipboard
, window
);
3183 if (NS_FAILED(rv
)) {
3184 *aTransferableDataOrError
= rv
;
3188 IPCTransferableData transferableData
;
3189 nsContentUtils::TransferableToIPCTransferableData(
3190 trans
, &transferableData
, true /* aInSyncMessage */, this);
3191 *aTransferableDataOrError
= std::move(transferableData
);
3195 mozilla::ipc::IPCResult
ContentParent::RecvEmptyClipboard(
3196 const int32_t& aWhichClipboard
) {
3198 nsCOMPtr
<nsIClipboard
> clipboard(do_GetService(kCClipboardCID
, &rv
));
3199 NS_ENSURE_SUCCESS(rv
, IPC_OK());
3201 clipboard
->EmptyClipboard(aWhichClipboard
);
3206 mozilla::ipc::IPCResult
ContentParent::RecvClipboardHasType(
3207 nsTArray
<nsCString
>&& aTypes
, const int32_t& aWhichClipboard
,
3210 nsCOMPtr
<nsIClipboard
> clipboard(do_GetService(kCClipboardCID
, &rv
));
3211 NS_ENSURE_SUCCESS(rv
, IPC_OK());
3213 clipboard
->HasDataMatchingFlavors(aTypes
, aWhichClipboard
, aHasType
);
3220 static Result
<ClipboardReadRequest
, nsresult
> CreateClipboardReadRequest(
3221 ContentParent
& aContentParent
,
3222 nsIClipboardDataSnapshot
& aClipboardDataSnapshot
) {
3223 nsTArray
<nsCString
> flavors
;
3224 nsresult rv
= aClipboardDataSnapshot
.GetFlavorList(flavors
);
3225 if (NS_FAILED(rv
)) {
3229 auto requestParent
= MakeNotNull
<RefPtr
<ClipboardReadRequestParent
>>(
3230 &aContentParent
, &aClipboardDataSnapshot
);
3232 // Open a remote endpoint for our PClipboardReadRequest actor.
3233 ManagedEndpoint
<PClipboardReadRequestChild
> childEndpoint
=
3234 aContentParent
.OpenPClipboardReadRequestEndpoint(requestParent
);
3235 if (NS_WARN_IF(!childEndpoint
.IsValid())) {
3236 return Err(NS_ERROR_FAILURE
);
3239 return ClipboardReadRequest(std::move(childEndpoint
), std::move(flavors
));
3242 class ClipboardGetCallback final
: public nsIClipboardGetDataSnapshotCallback
{
3244 ClipboardGetCallback(
3245 ContentParent
* aContentParent
,
3246 ContentParent::GetClipboardDataSnapshotResolver
&& aResolver
)
3247 : mContentParent(aContentParent
), mResolver(std::move(aResolver
)) {}
3249 // This object will never be held by a cycle-collected object, so it doesn't
3250 // need to be cycle-collected despite holding alive cycle-collected objects.
3253 // nsIClipboardGetDataSnapshotCallback
3254 NS_IMETHOD
OnSuccess(
3255 nsIClipboardDataSnapshot
* aClipboardDataSnapshot
) override
{
3256 MOZ_ASSERT(mContentParent
);
3257 MOZ_ASSERT(aClipboardDataSnapshot
);
3260 CreateClipboardReadRequest(*mContentParent
, *aClipboardDataSnapshot
);
3261 if (result
.isErr()) {
3262 return OnError(result
.unwrapErr());
3265 mResolver(result
.unwrap());
3269 NS_IMETHOD
OnError(nsresult aResult
) override
{
3275 ~ClipboardGetCallback() = default;
3277 RefPtr
<ContentParent
> mContentParent
;
3278 ContentParent::GetClipboardDataSnapshotResolver mResolver
;
3281 NS_IMPL_ISUPPORTS(ClipboardGetCallback
, nsIClipboardGetDataSnapshotCallback
)
3285 mozilla::ipc::IPCResult
ContentParent::RecvGetClipboardDataSnapshot(
3286 nsTArray
<nsCString
>&& aTypes
, const int32_t& aWhichClipboard
,
3287 const MaybeDiscarded
<WindowContext
>& aRequestingWindowContext
,
3288 mozilla::NotNull
<nsIPrincipal
*> aRequestingPrincipal
,
3289 GetClipboardDataSnapshotResolver
&& aResolver
) {
3290 if (!ValidatePrincipal(aRequestingPrincipal
,
3291 {ValidatePrincipalOptions::AllowSystem
,
3292 ValidatePrincipalOptions::AllowExpanded
})) {
3293 LogAndAssertFailedPrincipalValidationInfo(aRequestingPrincipal
, __func__
);
3296 // If the requesting context has been discarded, cancel the paste.
3297 if (aRequestingWindowContext
.IsDiscarded()) {
3298 aResolver(NS_ERROR_NOT_AVAILABLE
);
3302 RefPtr
<WindowGlobalParent
> requestingWindow
=
3303 aRequestingWindowContext
.get_canonical();
3304 if (requestingWindow
&& requestingWindow
->GetContentParent() != this) {
3306 this, "attempt to paste into WindowContext loaded in another process");
3310 // Retrieve clipboard
3311 nsCOMPtr
<nsIClipboard
> clipboard(do_GetService(kCClipboardCID
, &rv
));
3312 if (NS_FAILED(rv
)) {
3317 auto callback
= MakeRefPtr
<ClipboardGetCallback
>(this, std::move(aResolver
));
3318 rv
= clipboard
->GetDataSnapshot(aTypes
, aWhichClipboard
, requestingWindow
,
3319 aRequestingPrincipal
, callback
);
3320 if (NS_FAILED(rv
)) {
3321 callback
->OnError(rv
);
3328 mozilla::ipc::IPCResult
ContentParent::RecvGetClipboardDataSnapshotSync(
3329 nsTArray
<nsCString
>&& aTypes
, const int32_t& aWhichClipboard
,
3330 const MaybeDiscarded
<WindowContext
>& aRequestingWindowContext
,
3331 ClipboardReadRequestOrError
* aRequestOrError
) {
3332 // If the requesting context has been discarded, cancel the paste.
3333 if (aRequestingWindowContext
.IsDiscarded()) {
3334 *aRequestOrError
= NS_ERROR_FAILURE
;
3338 RefPtr
<WindowGlobalParent
> requestingWindow
=
3339 aRequestingWindowContext
.get_canonical();
3340 if (requestingWindow
&& requestingWindow
->GetContentParent() != this) {
3342 this, "attempt to paste into WindowContext loaded in another process");
3345 nsCOMPtr
<nsIClipboard
> clipboard(do_GetService(kCClipboardCID
));
3347 *aRequestOrError
= NS_ERROR_FAILURE
;
3351 nsCOMPtr
<nsIClipboardDataSnapshot
> clipboardDataSnapshot
;
3353 clipboard
->GetDataSnapshotSync(aTypes
, aWhichClipboard
, requestingWindow
,
3354 getter_AddRefs(clipboardDataSnapshot
));
3355 if (NS_FAILED(rv
)) {
3356 *aRequestOrError
= rv
;
3360 auto result
= CreateClipboardReadRequest(*this, *clipboardDataSnapshot
);
3361 if (result
.isErr()) {
3362 *aRequestOrError
= result
.unwrapErr();
3366 *aRequestOrError
= result
.unwrap();
3370 already_AddRefed
<PClipboardWriteRequestParent
>
3371 ContentParent::AllocPClipboardWriteRequestParent(
3372 const int32_t& aClipboardType
,
3373 const MaybeDiscarded
<WindowContext
>& aSettingWindowContext
) {
3374 WindowContext
* settingWindowContext
= nullptr;
3375 if (!aSettingWindowContext
.IsDiscarded()) {
3376 settingWindowContext
= aSettingWindowContext
.get();
3378 RefPtr
<ClipboardWriteRequestParent
> request
=
3379 MakeAndAddRef
<ClipboardWriteRequestParent
>(this);
3380 request
->Init(aClipboardType
, settingWindowContext
);
3381 return request
.forget();
3384 mozilla::ipc::IPCResult
ContentParent::RecvGetIconForExtension(
3385 const nsACString
& aFileExt
, const uint32_t& aIconSize
,
3386 nsTArray
<uint8_t>* bits
) {
3387 #ifdef MOZ_WIDGET_ANDROID
3388 NS_ASSERTION(AndroidBridge::Bridge() != nullptr,
3389 "AndroidBridge is not available");
3390 if (AndroidBridge::Bridge() == nullptr) {
3391 // Do not fail - just no icon will be shown
3395 bits
->AppendElements(aIconSize
* aIconSize
* 4);
3397 AndroidBridge::Bridge()->GetIconForExtension(aFileExt
, aIconSize
,
3403 mozilla::ipc::IPCResult
ContentParent::RecvFirstIdle() {
3404 // When the ContentChild goes idle, it sends us a FirstIdle message
3405 // which we use as a good time to signal the PreallocatedProcessManager
3406 // that it can start allocating processes from now on.
3407 if (mIsAPreallocBlocker
) {
3409 ContentParent::GetLog(), LogLevel::Verbose
,
3410 ("RecvFirstIdle %p: Removing Blocker for %s", this, mRemoteType
.get()));
3411 PreallocatedProcessManager::RemoveBlocker(mRemoteType
, this);
3412 mIsAPreallocBlocker
= false;
3417 already_AddRefed
<nsDocShellLoadState
> ContentParent::TakePendingLoadStateForId(
3418 uint64_t aLoadIdentifier
) {
3419 return mPendingLoadStates
.Extract(aLoadIdentifier
).valueOr(nullptr).forget();
3422 void ContentParent::StorePendingLoadState(nsDocShellLoadState
* aLoadState
) {
3423 MOZ_DIAGNOSTIC_ASSERT(
3424 !mPendingLoadStates
.Contains(aLoadState
->GetLoadIdentifier()),
3425 "The same nsDocShellLoadState was sent to the same content process "
3426 "twice? This will mess with cross-process tracking of loads");
3427 mPendingLoadStates
.InsertOrUpdate(aLoadState
->GetLoadIdentifier(),
3431 mozilla::ipc::IPCResult
ContentParent::RecvCleanupPendingLoadState(
3432 uint64_t aLoadIdentifier
) {
3433 mPendingLoadStates
.Remove(aLoadIdentifier
);
3437 // We want ContentParent to show up in CC logs for debugging purposes, but we
3438 // don't actually cycle collect it.
3439 NS_IMPL_CYCLE_COLLECTION_0(ContentParent
)
3441 NS_IMPL_CYCLE_COLLECTING_ADDREF(ContentParent
)
3442 NS_IMPL_CYCLE_COLLECTING_RELEASE(ContentParent
)
3444 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ContentParent
)
3445 NS_INTERFACE_MAP_ENTRY_CONCRETE(ContentParent
)
3446 NS_INTERFACE_MAP_ENTRY(nsIDOMProcessParent
)
3447 NS_INTERFACE_MAP_ENTRY(nsIObserver
)
3448 NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionCallback
)
3449 NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionErrorCallback
)
3450 NS_INTERFACE_MAP_ENTRY(nsIAsyncShutdownBlocker
)
3451 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor
)
3452 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDOMProcessParent
)
3453 NS_INTERFACE_MAP_END
3455 class RequestContentJSInterruptRunnable final
: public Runnable
{
3457 explicit RequestContentJSInterruptRunnable(PProcessHangMonitorParent
* aActor
)
3458 : Runnable("dom::RequestContentJSInterruptRunnable"),
3459 mHangMonitorActor(aActor
) {}
3461 NS_IMETHOD
Run() override
{
3462 MOZ_ASSERT(mHangMonitorActor
);
3463 Unused
<< mHangMonitorActor
->SendRequestContentJSInterrupt();
3469 // The end-of-life of ContentParent::mHangMonitorActor is bound to
3470 // ContentParent::ActorDestroy and then HangMonitorParent::Shutdown
3471 // dispatches a shutdown runnable to this queue and waits for it to be
3472 // executed. So the runnable needs not to care about keeping it alive,
3473 // as it is surely dispatched earlier than the
3474 // HangMonitorParent::ShutdownOnThread.
3475 RefPtr
<PProcessHangMonitorParent
> mHangMonitorActor
;
3478 void ContentParent::SignalImpendingShutdownToContentJS() {
3479 if (!mIsSignaledImpendingShutdown
&&
3480 !AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdown
)) {
3481 MaybeLogBlockShutdownDiagnostics(
3482 this, "BlockShutdown: NotifyImpendingShutdown.", __FILE__
, __LINE__
);
3483 NotifyImpendingShutdown();
3484 mIsSignaledImpendingShutdown
= true;
3485 if (mHangMonitorActor
&&
3486 StaticPrefs::dom_abort_script_on_child_shutdown()) {
3487 MaybeLogBlockShutdownDiagnostics(
3488 this, "BlockShutdown: RequestContentJSInterrupt.", __FILE__
,
3490 RefPtr
<RequestContentJSInterruptRunnable
> r
=
3491 new RequestContentJSInterruptRunnable(mHangMonitorActor
);
3492 ProcessHangMonitor::Get()->Dispatch(r
.forget());
3497 // Async shutdown blocker
3499 ContentParent::BlockShutdown(nsIAsyncShutdownClient
* aClient
) {
3500 if (!AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdown
)) {
3501 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
3502 mBlockShutdownCalled
= true;
3504 // Our real shutdown has not yet started. Just notify the impending
3505 // shutdown and eventually cancel content JS.
3506 SignalImpendingShutdownToContentJS();
3507 // This will make our process unusable for normal content, so we need to
3508 // ensure we won't get re-used by GetUsedBrowserProcess as we have not yet
3510 PreallocatedProcessManager::Erase(this);
3512 if (sQuitApplicationGrantedClient
) {
3513 Unused
<< sQuitApplicationGrantedClient
->RemoveBlocker(this);
3515 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
3516 mBlockShutdownCalled
= false;
3521 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
3522 // We register two final shutdown blockers and both would call us, but if
3523 // things go well we will unregister both as (delayed) reaction to the first
3524 // call we get and thus never receive a second call. Thus we believe that we
3525 // will get called only once except for quit-application-granted, which is
3527 MOZ_ASSERT(!mBlockShutdownCalled
);
3528 mBlockShutdownCalled
= true;
3532 MaybeLogBlockShutdownDiagnostics(this, "BlockShutdown: CanSend.", __FILE__
,
3535 // Make sure that our process will get scheduled.
3536 ProcessPriorityManager::SetProcessPriority(this,
3537 PROCESS_PRIORITY_FOREGROUND
);
3538 // The normal shutdown sequence is to send a shutdown message
3539 // to the child and then just wait for ActorDestroy which will
3540 // cleanup everything and remove our blockers.
3541 if (!ShutDownProcess(SEND_SHUTDOWN_MESSAGE
)) {
3542 KillHard("Failed to send Shutdown message. Destroying the process...");
3545 } else if (IsLaunching()) {
3546 MaybeLogBlockShutdownDiagnostics(
3547 this, "BlockShutdown: !CanSend && IsLaunching.", __FILE__
, __LINE__
);
3549 // If we get here while we are launching, we must wait for the child to
3550 // be able to react on our commands. Mark this process as dead. This
3551 // will make bail out LaunchSubprocessResolve and kick off the normal
3552 // shutdown sequence.
3555 MOZ_ASSERT(IsDead());
3557 MaybeLogBlockShutdownDiagnostics(
3558 this, "BlockShutdown: !!! !CanSend && !IsLaunching && !IsDead !!!",
3559 __FILE__
, __LINE__
);
3561 MaybeLogBlockShutdownDiagnostics(
3562 this, "BlockShutdown: !CanSend && !IsLaunching && IsDead.", __FILE__
,
3565 // Nothing left we can do. We must assume that we race with an ongoing
3566 // process shutdown, such that we can expect our shutdown blockers to be
3567 // removed normally.
3574 ContentParent::GetName(nsAString
& aName
) {
3575 aName
.AssignLiteral("ContentParent:");
3576 aName
.AppendPrintf(" id=%p", this);
3581 ContentParent::GetState(nsIPropertyBag
** aResult
) {
3582 auto props
= MakeRefPtr
<nsHashPropertyBag
>();
3583 props
->SetPropertyAsACString(u
"remoteTypePrefix"_ns
,
3584 RemoteTypePrefix(mRemoteType
));
3585 *aResult
= props
.forget().downcast
<nsIWritablePropertyBag
>().take();
3589 static void InitShutdownClients() {
3590 if (!sXPCOMShutdownClient
) {
3592 nsCOMPtr
<nsIAsyncShutdownService
> svc
= services::GetAsyncShutdownService();
3597 nsCOMPtr
<nsIAsyncShutdownClient
> client
;
3598 // TODO: It seems as if getPhase from AsyncShutdown.sys.mjs does not check
3599 // if we are beyond our phase already. See bug 1762840.
3600 if (!AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMWillShutdown
)) {
3601 rv
= svc
->GetXpcomWillShutdown(getter_AddRefs(client
));
3602 if (NS_SUCCEEDED(rv
)) {
3603 sXPCOMShutdownClient
= client
.forget();
3604 ClearOnShutdown(&sXPCOMShutdownClient
);
3607 if (!AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdown
)) {
3608 rv
= svc
->GetProfileBeforeChange(getter_AddRefs(client
));
3609 if (NS_SUCCEEDED(rv
)) {
3610 sProfileBeforeChangeClient
= client
.forget();
3611 ClearOnShutdown(&sProfileBeforeChangeClient
);
3614 // TODO: ShutdownPhase::AppShutdownConfirmed is not mapping to
3615 // QuitApplicationGranted, see bug 1762840 comment 4.
3616 if (!AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed
)) {
3617 rv
= svc
->GetQuitApplicationGranted(getter_AddRefs(client
));
3618 if (NS_SUCCEEDED(rv
)) {
3619 sQuitApplicationGrantedClient
= client
.forget();
3620 ClearOnShutdown(&sQuitApplicationGrantedClient
);
3626 void ContentParent::AddShutdownBlockers() {
3627 InitShutdownClients();
3628 MOZ_ASSERT(sXPCOMShutdownClient
);
3629 MOZ_ASSERT(sProfileBeforeChangeClient
);
3631 if (sXPCOMShutdownClient
) {
3632 sXPCOMShutdownClient
->AddBlocker(
3633 this, NS_LITERAL_STRING_FROM_CSTRING(__FILE__
), __LINE__
, u
""_ns
);
3635 if (sProfileBeforeChangeClient
) {
3636 sProfileBeforeChangeClient
->AddBlocker(
3637 this, NS_LITERAL_STRING_FROM_CSTRING(__FILE__
), __LINE__
, u
""_ns
);
3639 if (sQuitApplicationGrantedClient
) {
3640 sQuitApplicationGrantedClient
->AddBlocker(
3641 this, NS_LITERAL_STRING_FROM_CSTRING(__FILE__
), __LINE__
, u
""_ns
);
3645 void ContentParent::RemoveShutdownBlockers() {
3646 MOZ_ASSERT(sXPCOMShutdownClient
);
3647 MOZ_ASSERT(sProfileBeforeChangeClient
);
3649 MaybeLogBlockShutdownDiagnostics(this, "RemoveShutdownBlockers", __FILE__
,
3651 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
3652 mBlockShutdownCalled
= false;
3655 if (sXPCOMShutdownClient
) {
3656 Unused
<< sXPCOMShutdownClient
->RemoveBlocker(this);
3658 if (sProfileBeforeChangeClient
) {
3659 Unused
<< sProfileBeforeChangeClient
->RemoveBlocker(this);
3661 if (sQuitApplicationGrantedClient
) {
3662 Unused
<< sQuitApplicationGrantedClient
->RemoveBlocker(this);
3667 ContentParent::Observe(nsISupports
* aSubject
, const char* aTopic
,
3668 const char16_t
* aData
) {
3669 if (IsDead() || !mSubprocess
) {
3673 if (!strcmp(aTopic
, "nsPref:changed")) {
3674 // We know prefs are ASCII here.
3675 NS_LossyConvertUTF16toASCII
strData(aData
);
3677 Pref
pref(strData
, /* isLocked */ false,
3678 /* isSanitized */ false, Nothing(), Nothing());
3680 Preferences::GetPreference(&pref
, GeckoProcessType_Content
,
3683 // This check is a bit of a hack. We want to avoid sending excessive
3684 // preference updates to subprocesses for performance reasons, but we
3685 // currently don't have a great mechanism for doing so. (See Bug 1819714)
3686 // We're going to hijack the sanitization mechanism to accomplish our goal
3687 // but it imposes the following complications:
3688 // 1) It doesn't avoid sending anything to other (non-web-content)
3689 // subprocesses so we're not getting any perf gains there
3690 // 2) It confuses the subprocesses w.r.t. sanitization. The point of
3691 // sending a preference update of a sanitized preference is so that
3692 // content process knows when it's asked to resolve a sanitized
3693 // preference, and it can send telemetry and/or crash. With this
3694 // change, a sanitized pref that is created during the browser session
3695 // will not be sent to the content process, and therefore the content
3696 // process won't know it should telemetry/crash on access - it'll just
3697 // silently fail to resolve it. After browser restart, the sanitized
3698 // pref will be populated into the content process via the shared pref
3699 // map and _then_ if it is accessed, the content process will crash.
3700 // We're seeing good telemetry/crash rates right now, so we're okay with
3702 if (pref
.isSanitized()) {
3706 if (IsInitialized()) {
3707 MOZ_ASSERT(mQueuedPrefs
.IsEmpty());
3708 if (!SendPreferenceUpdate(pref
)) {
3709 return NS_ERROR_NOT_AVAILABLE
;
3712 MOZ_ASSERT(!IsDead());
3713 mQueuedPrefs
.AppendElement(pref
);
3723 // listening for memory pressure event
3724 if (!strcmp(aTopic
, "memory-pressure")) {
3725 Unused
<< SendFlushMemory(nsDependentString(aData
));
3726 } else if (!strcmp(aTopic
, "application-background")) {
3727 Unused
<< SendApplicationBackground();
3728 } else if (!strcmp(aTopic
, "application-foreground")) {
3729 Unused
<< SendApplicationForeground();
3730 } else if (!strcmp(aTopic
, NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC
)) {
3731 NS_ConvertUTF16toUTF8
dataStr(aData
);
3732 const char* offline
= dataStr
.get();
3733 if (!SendSetOffline(!strcmp(offline
, "true"))) {
3734 return NS_ERROR_NOT_AVAILABLE
;
3736 } else if (!strcmp(aTopic
, NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC
)) {
3737 if (!SendSetConnectivity(u
"true"_ns
.Equals(aData
))) {
3738 return NS_ERROR_NOT_AVAILABLE
;
3740 } else if (!strcmp(aTopic
, NS_IPC_CAPTIVE_PORTAL_SET_STATE
)) {
3741 nsCOMPtr
<nsICaptivePortalService
> cps
= do_QueryInterface(aSubject
);
3742 MOZ_ASSERT(cps
, "Should QI to a captive portal service");
3744 return NS_ERROR_FAILURE
;
3747 cps
->GetState(&state
);
3748 if (!SendSetCaptivePortalState(state
)) {
3749 return NS_ERROR_NOT_AVAILABLE
;
3752 // listening for alert notifications
3753 else if (!strcmp(aTopic
, "alertfinished") ||
3754 !strcmp(aTopic
, "alertclickcallback") ||
3755 !strcmp(aTopic
, "alertshow") ||
3756 !strcmp(aTopic
, "alertdisablecallback") ||
3757 !strcmp(aTopic
, "alertsettingscallback")) {
3758 if (!SendNotifyAlertsObserver(nsDependentCString(aTopic
),
3759 nsDependentString(aData
))) {
3760 return NS_ERROR_NOT_AVAILABLE
;
3762 } else if (!strcmp(aTopic
, "child-gc-request")) {
3763 Unused
<< SendGarbageCollect();
3764 } else if (!strcmp(aTopic
, "child-cc-request")) {
3765 Unused
<< SendCycleCollect();
3766 } else if (!strcmp(aTopic
, "child-mmu-request")) {
3767 Unused
<< SendMinimizeMemoryUsage();
3768 } else if (!strcmp(aTopic
, "child-ghost-request")) {
3769 Unused
<< SendUnlinkGhosts();
3770 } else if (!strcmp(aTopic
, "last-pb-context-exited")) {
3771 Unused
<< SendLastPrivateDocShellDestroyed();
3773 #ifdef ACCESSIBILITY
3774 else if (aData
&& !strcmp(aTopic
, "a11y-init-or-shutdown")) {
3775 if (*aData
== '1') {
3776 // Make sure accessibility is running in content process when
3777 // accessibility gets initiated in chrome process.
3778 Unused
<< SendActivateA11y();
3780 // If possible, shut down accessibility in content process when
3781 // accessibility gets shutdown in chrome process.
3782 Unused
<< SendShutdownA11y();
3786 else if (!strcmp(aTopic
, "cacheservice:empty-cache")) {
3787 Unused
<< SendNotifyEmptyHTTPCache();
3788 } else if (!strcmp(aTopic
, "intl:app-locales-changed")) {
3789 nsTArray
<nsCString
> appLocales
;
3790 LocaleService::GetInstance()->GetAppLocalesAsBCP47(appLocales
);
3791 Unused
<< SendUpdateAppLocales(appLocales
);
3792 } else if (!strcmp(aTopic
, "intl:requested-locales-changed")) {
3793 nsTArray
<nsCString
> requestedLocales
;
3794 LocaleService::GetInstance()->GetRequestedLocales(requestedLocales
);
3795 Unused
<< SendUpdateRequestedLocales(requestedLocales
);
3796 } else if (!strcmp(aTopic
, "cookie-changed") ||
3797 !strcmp(aTopic
, "private-cookie-changed")) {
3798 MOZ_ASSERT(aSubject
, "cookie changed notification must have subject.");
3799 nsCOMPtr
<nsICookieNotification
> notification
= do_QueryInterface(aSubject
);
3800 MOZ_ASSERT(notification
,
3801 "cookie changed notification must have nsICookieNotification.");
3802 nsICookieNotification::Action action
= notification
->GetAction();
3804 PNeckoParent
* neckoParent
= LoneManagedOrNullAsserts(ManagedPNeckoParent());
3808 PCookieServiceParent
* csParent
=
3809 LoneManagedOrNullAsserts(neckoParent
->ManagedPCookieServiceParent());
3813 auto* cs
= static_cast<CookieServiceParent
*>(csParent
);
3814 if (action
== nsICookieNotification::COOKIES_BATCH_DELETED
) {
3815 nsCOMPtr
<nsIArray
> cookieList
;
3816 DebugOnly
<nsresult
> rv
=
3817 notification
->GetBatchDeletedCookies(getter_AddRefs(cookieList
));
3818 NS_ASSERTION(NS_SUCCEEDED(rv
) && cookieList
, "couldn't get cookie list");
3819 cs
->RemoveBatchDeletedCookies(cookieList
);
3823 if (action
== nsICookieNotification::ALL_COOKIES_CLEARED
) {
3828 // Do not push these cookie updates to the same process they originated
3830 if (cs
->ProcessingCookie()) {
3834 nsCOMPtr
<nsICookie
> xpcCookie
;
3835 DebugOnly
<nsresult
> rv
= notification
->GetCookie(getter_AddRefs(xpcCookie
));
3836 NS_ASSERTION(NS_SUCCEEDED(rv
) && xpcCookie
, "couldn't get cookie");
3838 // only broadcast the cookie change to content processes that need it
3839 const Cookie
& cookie
= xpcCookie
->AsCookie();
3841 // do not send cookie if content process does not have similar cookie
3842 if (!cs
->ContentProcessHasCookie(cookie
)) {
3846 if (action
== nsICookieNotification::COOKIE_DELETED
) {
3847 cs
->RemoveCookie(cookie
);
3848 } else if (action
== nsICookieNotification::COOKIE_ADDED
||
3849 action
== nsICookieNotification::COOKIE_CHANGED
) {
3850 cs
->AddCookie(cookie
);
3852 } else if (!strcmp(aTopic
, NS_NETWORK_LINK_TYPE_TOPIC
)) {
3853 UpdateNetworkLinkType();
3854 } else if (!strcmp(aTopic
, "network:socket-process-crashed")) {
3855 Unused
<< SendSocketProcessCrashed();
3856 } else if (!strcmp(aTopic
, DEFAULT_TIMEZONE_CHANGED_OBSERVER_TOPIC
)) {
3857 Unused
<< SendSystemTimezoneChanged();
3858 } else if (!strcmp(aTopic
, NS_NETWORK_TRR_MODE_CHANGED_TOPIC
)) {
3859 nsCOMPtr
<nsIDNSService
> dns
= do_GetService(NS_DNSSERVICE_CONTRACTID
);
3860 nsIDNSService::ResolverMode mode
;
3861 dns
->GetCurrentTrrMode(&mode
);
3862 Unused
<< SendSetTRRMode(mode
, static_cast<nsIDNSService::ResolverMode
>(
3863 StaticPrefs::network_trr_mode()));
3869 void ContentParent::UpdateNetworkLinkType() {
3871 nsCOMPtr
<nsINetworkLinkService
> nls
=
3872 do_GetService(NS_NETWORK_LINK_SERVICE_CONTRACTID
, &rv
);
3873 if (NS_FAILED(rv
)) {
3877 uint32_t linkType
= nsINetworkLinkService::LINK_TYPE_UNKNOWN
;
3878 rv
= nls
->GetLinkType(&linkType
);
3879 if (NS_FAILED(rv
)) {
3883 Unused
<< SendNetworkLinkTypeChange(linkType
);
3887 ContentParent::GetInterface(const nsIID
& aIID
, void** aResult
) {
3888 NS_ENSURE_ARG_POINTER(aResult
);
3890 if (aIID
.Equals(NS_GET_IID(nsIMessageSender
))) {
3891 nsCOMPtr
<nsIMessageSender
> mm
= GetMessageManager();
3896 return NS_NOINTERFACE
;
3899 mozilla::ipc::IPCResult
ContentParent::RecvInitBackground(
3900 Endpoint
<PBackgroundStarterParent
>&& aEndpoint
) {
3901 if (!BackgroundParent::AllocStarter(this, std::move(aEndpoint
))) {
3902 NS_WARNING("BackgroundParent::Alloc failed");
3908 bool ContentParent::CanOpenBrowser(const IPCTabContext
& aContext
) {
3909 // (PopupIPCTabContext lets the child process prove that it has access to
3910 // the app it's trying to open.)
3911 // On e10s we also allow UnsafeTabContext to allow service workers to open
3912 // windows. This is enforced in MaybeInvalidTabContext.
3913 if (aContext
.type() != IPCTabContext::TPopupIPCTabContext
) {
3914 MOZ_CRASH_UNLESS_FUZZING(
3915 "Unexpected IPCTabContext type. Aborting AllocPBrowserParent.");
3919 if (aContext
.type() == IPCTabContext::TPopupIPCTabContext
) {
3920 const PopupIPCTabContext
& popupContext
= aContext
.get_PopupIPCTabContext();
3922 auto* opener
= BrowserParent::GetFrom(popupContext
.opener().AsParent());
3924 MOZ_CRASH_UNLESS_FUZZING(
3925 "Got null opener from child; aborting AllocPBrowserParent.");
3930 MaybeInvalidTabContext
tc(aContext
);
3931 if (!tc
.IsValid()) {
3932 NS_ERROR(nsPrintfCString("Child passed us an invalid TabContext. (%s) "
3933 "Aborting AllocPBrowserParent.",
3934 tc
.GetInvalidReason())
3942 static bool CloneIsLegal(ContentParent
* aCp
, CanonicalBrowsingContext
& aSource
,
3943 CanonicalBrowsingContext
& aTarget
) {
3944 // Source and target must be in the same BCG
3945 if (NS_WARN_IF(aSource
.Group() != aTarget
.Group())) {
3948 // The source and target must be in different toplevel <browser>s
3949 if (NS_WARN_IF(aSource
.Top() == aTarget
.Top())) {
3953 // Neither source nor target must be toplevel.
3954 if (NS_WARN_IF(aSource
.IsTop()) || NS_WARN_IF(aTarget
.IsTop())) {
3958 // Both should be embedded by the same process.
3959 auto* sourceEmbedder
= aSource
.GetParentWindowContext();
3960 if (NS_WARN_IF(!sourceEmbedder
) ||
3961 NS_WARN_IF(sourceEmbedder
->GetContentParent() != aCp
)) {
3965 auto* targetEmbedder
= aTarget
.GetParentWindowContext();
3966 if (NS_WARN_IF(!targetEmbedder
) ||
3967 NS_WARN_IF(targetEmbedder
->GetContentParent() != aCp
)) {
3975 mozilla::ipc::IPCResult
ContentParent::RecvCloneDocumentTreeInto(
3976 const MaybeDiscarded
<BrowsingContext
>& aSource
,
3977 const MaybeDiscarded
<BrowsingContext
>& aTarget
, PrintData
&& aPrintData
) {
3978 if (aSource
.IsNullOrDiscarded() || aTarget
.IsNullOrDiscarded()) {
3982 if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed
)) {
3983 // All existing processes have potentially been slated for removal already,
3984 // such that any subsequent call to GetNewOrUsedLaunchingBrowserProcess
3985 // (normally supposed to find an existing process here) will try to create
3986 // a new process (but fail) that nobody would ever really use. Let's avoid
3987 // this together with the expensive CloneDocumentTreeInto operation.
3991 auto* source
= aSource
.get_canonical();
3992 auto* target
= aTarget
.get_canonical();
3994 if (!CloneIsLegal(this, *source
, *target
)) {
3995 return IPC_FAIL(this, "Illegal subframe clone");
3998 ContentParent
* cp
= source
->GetContentParent();
3999 if (NS_WARN_IF(!cp
)) {
4003 if (NS_WARN_IF(cp
->GetRemoteType() == GetRemoteType())) {
4004 // Wanted to switch to a target browsing context that's already local again.
4005 // See bug 1676996 for how this can happen.
4007 // Dropping the switch on the floor seems fine for this case, though we
4008 // could also try to clone the local document.
4010 // If the remote type matches & it's in the same group (which was confirmed
4011 // by CloneIsLegal), it must be the exact same process.
4012 MOZ_DIAGNOSTIC_ASSERT(cp
== this);
4016 target
->CloneDocumentTreeInto(source
, cp
->GetRemoteType(),
4017 std::move(aPrintData
));
4021 mozilla::ipc::IPCResult
ContentParent::RecvUpdateRemotePrintSettings(
4022 const MaybeDiscarded
<BrowsingContext
>& aTarget
, PrintData
&& aPrintData
) {
4023 if (aTarget
.IsNullOrDiscarded()) {
4027 auto* target
= aTarget
.get_canonical();
4028 auto* bp
= target
->GetBrowserParent();
4029 if (NS_WARN_IF(!bp
)) {
4033 Unused
<< bp
->SendUpdateRemotePrintSettings(aPrintData
);
4037 mozilla::ipc::IPCResult
ContentParent::RecvConstructPopupBrowser(
4038 ManagedEndpoint
<PBrowserParent
>&& aBrowserEp
,
4039 ManagedEndpoint
<PWindowGlobalParent
>&& aWindowEp
, const TabId
& aTabId
,
4040 const IPCTabContext
& aContext
, const WindowGlobalInit
& aInitialWindowInit
,
4041 const uint32_t& aChromeFlags
) {
4042 MOZ_ASSERT(XRE_IsParentProcess());
4044 if (!CanOpenBrowser(aContext
)) {
4045 return IPC_FAIL(this, "CanOpenBrowser Failed");
4048 RefPtr
<CanonicalBrowsingContext
> browsingContext
=
4049 CanonicalBrowsingContext::Get(
4050 aInitialWindowInit
.context().mBrowsingContextId
);
4051 if (!browsingContext
|| browsingContext
->IsDiscarded()) {
4052 return IPC_FAIL(this, "Null or discarded initial BrowsingContext");
4054 if (!aInitialWindowInit
.principal()) {
4055 return IPC_FAIL(this, "Cannot create without valid initial principal");
4058 if (!ValidatePrincipal(aInitialWindowInit
.principal())) {
4059 LogAndAssertFailedPrincipalValidationInfo(aInitialWindowInit
.principal(),
4063 if (browsingContext
->GetBrowserParent()) {
4064 return IPC_FAIL(this, "BrowsingContext already has a BrowserParent");
4067 uint32_t chromeFlags
= aChromeFlags
;
4068 TabId
openerTabId(0);
4069 ContentParentId
openerCpId(0);
4070 if (aContext
.type() == IPCTabContext::TPopupIPCTabContext
) {
4071 // CanOpenBrowser has ensured that the IPCTabContext is of
4072 // type PopupIPCTabContext, and that the opener BrowserParent is
4074 const PopupIPCTabContext
& popupContext
= aContext
.get_PopupIPCTabContext();
4075 auto* opener
= BrowserParent::GetFrom(popupContext
.opener().AsParent());
4076 openerTabId
= opener
->GetTabId();
4077 openerCpId
= opener
->Manager()->ChildID();
4079 // We must ensure that the private browsing and remoteness flags
4080 // match those of the opener.
4081 nsCOMPtr
<nsILoadContext
> loadContext
= opener
->GetLoadContext();
4083 return IPC_FAIL(this, "Missing Opener LoadContext");
4085 if (loadContext
->UsePrivateBrowsing()) {
4086 chromeFlags
|= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW
;
4088 if (loadContext
->UseRemoteSubframes()) {
4089 chromeFlags
|= nsIWebBrowserChrome::CHROME_FISSION_WINDOW
;
4093 // And because we're allocating a remote browser, of course the
4094 // window is remote.
4095 chromeFlags
|= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW
;
4097 if (NS_WARN_IF(!browsingContext
->IsOwnedByProcess(ChildID()))) {
4098 return IPC_FAIL(this, "BrowsingContext Owned by Incorrect Process!");
4101 MaybeInvalidTabContext
tc(aContext
);
4102 MOZ_ASSERT(tc
.IsValid());
4104 RefPtr
<WindowGlobalParent
> initialWindow
=
4105 WindowGlobalParent::CreateDisconnected(aInitialWindowInit
);
4106 if (!initialWindow
) {
4107 return IPC_FAIL(this, "Failed to create WindowGlobalParent");
4110 auto parent
= MakeRefPtr
<BrowserParent
>(this, aTabId
, tc
.GetTabContext(),
4111 browsingContext
, chromeFlags
);
4113 // Bind the created BrowserParent to IPC to actually link the actor.
4114 if (NS_WARN_IF(!BindPBrowserEndpoint(std::move(aBrowserEp
), parent
))) {
4115 return IPC_FAIL(this, "BindPBrowserEndpoint failed");
4118 // XXX: Why are we checking these requirements? It seems we should register
4119 // the created frame unconditionally?
4120 if (openerTabId
> 0) {
4121 // The creation of PBrowser was triggered from content process through
4123 // We need to register remote frame with the child generated tab id.
4124 auto* cpm
= ContentProcessManager::GetSingleton();
4125 if (!cpm
|| !cpm
->RegisterRemoteFrame(parent
)) {
4126 return IPC_FAIL(this, "RegisterRemoteFrame Failed");
4130 if (NS_WARN_IF(!parent
->BindPWindowGlobalEndpoint(std::move(aWindowEp
),
4132 return IPC_FAIL(this, "BindPWindowGlobalEndpoint failed");
4135 browsingContext
->SetCurrentBrowserParent(parent
);
4137 initialWindow
->Init();
4139 // When enabling input event prioritization, input events may preempt other
4140 // normal priority IPC messages. To prevent the input events preempt
4141 // PBrowserConstructor, we use an IPC 'RemoteIsReadyToHandleInputEvents' to
4142 // notify parent that BrowserChild is created. In this case, PBrowser is
4143 // initiated from content so that we can set BrowserParent as ready to handle
4145 parent
->SetReadyToHandleInputEvents();
4149 mozilla::PRemoteSpellcheckEngineParent
*
4150 ContentParent::AllocPRemoteSpellcheckEngineParent() {
4151 mozilla::RemoteSpellcheckEngineParent
* parent
=
4152 new mozilla::RemoteSpellcheckEngineParent();
4156 bool ContentParent::DeallocPRemoteSpellcheckEngineParent(
4157 PRemoteSpellcheckEngineParent
* parent
) {
4163 void ContentParent::SendShutdownTimerCallback(nsITimer
* aTimer
,
4165 auto* self
= static_cast<ContentParent
*>(aClosure
);
4166 self
->AsyncSendShutDownMessage();
4170 void ContentParent::ForceKillTimerCallback(nsITimer
* aTimer
, void* aClosure
) {
4171 // We don't want to time out the content process during XPCShell tests. This
4172 // is the easiest way to ensure that.
4173 if (PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR")) {
4177 auto* self
= static_cast<ContentParent
*>(aClosure
);
4178 self
->KillHard("ShutDownKill");
4181 void ContentParent::GeneratePairedMinidump(const char* aReason
) {
4182 // We're about to kill the child process associated with this content.
4183 // Something has gone wrong to get us here, so we generate a minidump
4184 // of the parent and child for submission to the crash server unless we're
4185 // already shutting down.
4186 if (mCrashReporter
&&
4187 !AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed
) &&
4188 StaticPrefs::dom_ipc_tabs_createKillHardCrashReports_AtStartup()) {
4189 // GeneratePairedMinidump creates two minidumps for us - the main
4190 // one is for the content process we're about to kill, and the other
4191 // one is for the main browser process. That second one is the extra
4192 // minidump tagging along, so we have to tell the crash reporter that
4193 // it exists and is being appended.
4194 nsAutoCString
additionalDumps("browser");
4195 mCrashReporter
->AddAnnotationNSCString(
4196 CrashReporter::Annotation::additional_minidumps
, additionalDumps
);
4197 nsDependentCString
reason(aReason
);
4198 mCrashReporter
->AddAnnotationNSCString(
4199 CrashReporter::Annotation::ipc_channel_error
, reason
);
4201 // Generate the report and insert into the queue for submittal.
4202 if (mCrashReporter
->GenerateMinidumpAndPair(mSubprocess
, "browser"_ns
)) {
4203 mCrashReporter
->FinalizeCrashReport();
4204 mCreatedPairedMinidumps
= true;
4209 void ContentParent::HandleOrphanedMinidump(nsString
* aDumpId
) {
4210 if (CrashReporter::FinalizeOrphanedMinidump(
4211 OtherPid(), GeckoProcessType_Content
, aDumpId
)) {
4212 CrashReporterHost::RecordCrash(GeckoProcessType_Content
,
4213 nsICrashService::CRASH_TYPE_CRASH
, *aDumpId
);
4215 NS_WARNING(nsPrintfCString("content process pid = %" PRIPID
4216 " crashed without leaving a minidump behind",
4222 // WARNING: aReason appears in telemetry, so any new value passed in requires
4224 void ContentParent::KillHard(const char* aReason
) {
4225 AUTO_PROFILER_LABEL("ContentParent::KillHard", OTHER
);
4227 // On Windows, calling KillHard multiple times causes problems - the
4228 // process handle becomes invalid on the first call, causing a second call
4229 // to crash our process - more details in bug 890840.
4230 if (mCalledKillHard
) {
4233 mCalledKillHard
= true;
4234 if (mSendShutdownTimer
) {
4235 mSendShutdownTimer
->Cancel();
4236 mSendShutdownTimer
= nullptr;
4238 if (mForceKillTimer
) {
4239 mForceKillTimer
->Cancel();
4240 mForceKillTimer
= nullptr;
4243 RemoveShutdownBlockers();
4244 nsCString reason
= nsDependentCString(aReason
);
4246 // If we find mIsNotifiedShutdownSuccess there is no reason to blame this
4247 // content process, most probably our parent process is just slow in
4248 // processing its own main thread queue.
4249 if (!mIsNotifiedShutdownSuccess
) {
4250 GeneratePairedMinidump(aReason
);
4252 reason
= nsDependentCString("KillHard after IsNotifiedShutdownSuccess.");
4254 Telemetry::Accumulate(Telemetry::SUBPROCESS_KILL_HARD
, reason
, 1);
4256 ProcessHandle otherProcessHandle
;
4257 if (!base::OpenProcessHandle(OtherPid(), &otherProcessHandle
)) {
4258 NS_ERROR("Failed to open child process when attempting kill.");
4260 GetIPCChannel()->InduceConnectionError();
4265 if (!KillProcess(otherProcessHandle
, base::PROCESS_END_KILLED_BY_USER
)) {
4266 if (mCrashReporter
) {
4267 mCrashReporter
->DeleteCrashReport();
4269 NS_WARNING("failed to kill subprocess!");
4274 ContentParent::GetLog(), LogLevel::Verbose
,
4275 ("KillHard Subprocess(%s): ContentParent %p mSubprocess %p handle "
4277 aReason
, this, mSubprocess
,
4278 mSubprocess
? (uintptr_t)mSubprocess
->GetChildProcessHandle() : -1));
4279 mSubprocess
->SetAlreadyDead();
4282 // After we've killed the remote process, also ensure we induce a connection
4283 // error in the IPC channel to immediately stop all IPC communication on this
4286 GetIPCChannel()->InduceConnectionError();
4289 // EnsureProcessTerminated has responsibilty for closing otherProcessHandle.
4290 XRE_GetIOMessageLoop()->PostTask(
4291 NewRunnableFunction("EnsureProcessTerminatedRunnable",
4292 &ProcessWatcher::EnsureProcessTerminated
,
4293 otherProcessHandle
, /*force=*/true));
4296 void ContentParent::FriendlyName(nsAString
& aName
, bool aAnonymize
) {
4298 if (mIsForBrowser
) {
4299 aName
.AssignLiteral("Browser");
4300 } else if (aAnonymize
) {
4301 aName
.AssignLiteral("<anonymized-name>");
4303 aName
.AssignLiteral("???");
4307 mozilla::ipc::IPCResult
ContentParent::RecvInitCrashReporter(
4308 const NativeThreadId
& aThreadId
) {
4310 MakeUnique
<CrashReporterHost
>(GeckoProcessType_Content
, aThreadId
);
4315 hal_sandbox::PHalParent
* ContentParent::AllocPHalParent() {
4316 return hal_sandbox::CreateHalParent();
4319 bool ContentParent::DeallocPHalParent(hal_sandbox::PHalParent
* aHal
) {
4324 devtools::PHeapSnapshotTempFileHelperParent
*
4325 ContentParent::AllocPHeapSnapshotTempFileHelperParent() {
4326 return devtools::HeapSnapshotTempFileHelperParent::Create();
4329 bool ContentParent::DeallocPHeapSnapshotTempFileHelperParent(
4330 devtools::PHeapSnapshotTempFileHelperParent
* aHeapSnapshotHelper
) {
4331 delete aHeapSnapshotHelper
;
4335 bool ContentParent::SendRequestMemoryReport(
4336 const uint32_t& aGeneration
, const bool& aAnonymize
,
4337 const bool& aMinimizeMemoryUsage
, const Maybe
<FileDescriptor
>& aDMDFile
) {
4338 // This automatically cancels the previous request.
4339 mMemoryReportRequest
= MakeUnique
<MemoryReportRequestHost
>(aGeneration
);
4340 // If we run the callback in response to a reply, then by definition |this|
4341 // is still alive, so the ref pointer is redundant, but it seems easier
4342 // to hold a strong reference than to worry about that.
4343 RefPtr
<ContentParent
> self(this);
4344 PContentParent::SendRequestMemoryReport(
4345 aGeneration
, aAnonymize
, aMinimizeMemoryUsage
, aDMDFile
,
4346 [&, self
](const uint32_t& aGeneration2
) {
4347 if (self
->mMemoryReportRequest
) {
4348 self
->mMemoryReportRequest
->Finish(aGeneration2
);
4349 self
->mMemoryReportRequest
= nullptr;
4352 [&, self
](mozilla::ipc::ResponseRejectReason
) {
4353 self
->mMemoryReportRequest
= nullptr;
4358 mozilla::ipc::IPCResult
ContentParent::RecvAddMemoryReport(
4359 const MemoryReport
& aReport
) {
4360 if (mMemoryReportRequest
) {
4361 mMemoryReportRequest
->RecvReport(aReport
);
4366 PCycleCollectWithLogsParent
* ContentParent::AllocPCycleCollectWithLogsParent(
4367 const bool& aDumpAllTraces
, const FileDescriptor
& aGCLog
,
4368 const FileDescriptor
& aCCLog
) {
4369 MOZ_CRASH("Don't call this; use ContentParent::CycleCollectWithLogs");
4372 bool ContentParent::DeallocPCycleCollectWithLogsParent(
4373 PCycleCollectWithLogsParent
* aActor
) {
4378 bool ContentParent::CycleCollectWithLogs(
4379 bool aDumpAllTraces
, nsICycleCollectorLogSink
* aSink
,
4380 nsIDumpGCAndCCLogsCallback
* aCallback
) {
4381 return CycleCollectWithLogsParent::AllocAndSendConstructor(
4382 this, aDumpAllTraces
, aSink
, aCallback
);
4385 PScriptCacheParent
* ContentParent::AllocPScriptCacheParent(
4386 const FileDescOrError
& cacheFile
, const bool& wantCacheData
) {
4387 return new loader::ScriptCacheParent(wantCacheData
);
4390 bool ContentParent::DeallocPScriptCacheParent(PScriptCacheParent
* cache
) {
4391 delete static_cast<loader::ScriptCacheParent
*>(cache
);
4395 already_AddRefed
<PNeckoParent
> ContentParent::AllocPNeckoParent() {
4396 RefPtr
<NeckoParent
> actor
= new NeckoParent();
4397 return actor
.forget();
4400 mozilla::ipc::IPCResult
ContentParent::RecvInitStreamFilter(
4401 const uint64_t& aChannelId
, const nsAString
& aAddonId
,
4402 InitStreamFilterResolver
&& aResolver
) {
4403 extensions::StreamFilterParent::Create(this, aChannelId
, aAddonId
)
4405 GetCurrentSerialEventTarget(), __func__
,
4406 [aResolver
](mozilla::ipc::Endpoint
<PStreamFilterChild
>&& aEndpoint
) {
4407 aResolver(std::move(aEndpoint
));
4409 [aResolver
](bool aDummy
) {
4410 aResolver(mozilla::ipc::Endpoint
<PStreamFilterChild
>());
4416 mozilla::ipc::IPCResult
ContentParent::RecvAddSecurityState(
4417 const MaybeDiscarded
<WindowContext
>& aContext
, uint32_t aStateFlags
) {
4418 if (aContext
.IsNullOrDiscarded()) {
4422 aContext
.get()->AddSecurityState(aStateFlags
);
4426 already_AddRefed
<PExternalHelperAppParent
>
4427 ContentParent::AllocPExternalHelperAppParent(
4428 nsIURI
* uri
, const mozilla::net::LoadInfoArgs
& aLoadInfoArgs
,
4429 const nsACString
& aMimeContentType
, const nsACString
& aContentDisposition
,
4430 const uint32_t& aContentDispositionHint
,
4431 const nsAString
& aContentDispositionFilename
, const bool& aForceSave
,
4432 const int64_t& aContentLength
, const bool& aWasFileChannel
,
4433 nsIURI
* aReferrer
, const MaybeDiscarded
<BrowsingContext
>& aContext
,
4434 const bool& aShouldCloseWindow
) {
4435 RefPtr
<ExternalHelperAppParent
> parent
= new ExternalHelperAppParent(
4436 uri
, aContentLength
, aWasFileChannel
, aContentDisposition
,
4437 aContentDispositionHint
, aContentDispositionFilename
);
4438 return parent
.forget();
4441 mozilla::ipc::IPCResult
ContentParent::RecvPExternalHelperAppConstructor(
4442 PExternalHelperAppParent
* actor
, nsIURI
* uri
,
4443 const LoadInfoArgs
& loadInfoArgs
, const nsACString
& aMimeContentType
,
4444 const nsACString
& aContentDisposition
,
4445 const uint32_t& aContentDispositionHint
,
4446 const nsAString
& aContentDispositionFilename
, const bool& aForceSave
,
4447 const int64_t& aContentLength
, const bool& aWasFileChannel
,
4448 nsIURI
* aReferrer
, const MaybeDiscarded
<BrowsingContext
>& aContext
,
4449 const bool& aShouldCloseWindow
) {
4450 BrowsingContext
* context
= aContext
.IsDiscarded() ? nullptr : aContext
.get();
4451 if (!static_cast<ExternalHelperAppParent
*>(actor
)->Init(
4452 loadInfoArgs
, aMimeContentType
, aForceSave
, aReferrer
, context
,
4453 aShouldCloseWindow
)) {
4454 return IPC_FAIL(this, "Init failed.");
4459 already_AddRefed
<PHandlerServiceParent
>
4460 ContentParent::AllocPHandlerServiceParent() {
4461 RefPtr
<HandlerServiceParent
> actor
= new HandlerServiceParent();
4462 return actor
.forget();
4465 media::PMediaParent
* ContentParent::AllocPMediaParent() {
4466 return media::AllocPMediaParent();
4469 bool ContentParent::DeallocPMediaParent(media::PMediaParent
* aActor
) {
4470 return media::DeallocPMediaParent(aActor
);
4473 PBenchmarkStorageParent
* ContentParent::AllocPBenchmarkStorageParent() {
4474 return new BenchmarkStorageParent
;
4477 bool ContentParent::DeallocPBenchmarkStorageParent(
4478 PBenchmarkStorageParent
* aActor
) {
4483 #ifdef MOZ_WEBSPEECH
4484 already_AddRefed
<PSpeechSynthesisParent
>
4485 ContentParent::AllocPSpeechSynthesisParent() {
4486 if (!StaticPrefs::media_webspeech_synth_enabled()) {
4489 RefPtr
<SpeechSynthesisParent
> actor
= new SpeechSynthesisParent();
4490 return actor
.forget();
4493 mozilla::ipc::IPCResult
ContentParent::RecvPSpeechSynthesisConstructor(
4494 PSpeechSynthesisParent
* aActor
) {
4495 if (!static_cast<SpeechSynthesisParent
*>(aActor
)->SendInit()) {
4496 return IPC_FAIL(this, "SpeechSynthesisParent::SendInit failed.");
4502 mozilla::ipc::IPCResult
ContentParent::RecvStartVisitedQueries(
4503 const nsTArray
<RefPtr
<nsIURI
>>& aUris
) {
4504 nsCOMPtr
<IHistory
> history
= components::History::Service();
4508 for (const auto& uri
: aUris
) {
4509 if (NS_WARN_IF(!uri
)) {
4512 history
->ScheduleVisitedQuery(uri
, this);
4517 mozilla::ipc::IPCResult
ContentParent::RecvSetURITitle(nsIURI
* uri
,
4518 const nsAString
& title
) {
4520 return IPC_FAIL(this, "uri must not be null.");
4522 nsCOMPtr
<IHistory
> history
= components::History::Service();
4524 history
->SetURITitle(uri
, title
);
4529 mozilla::ipc::IPCResult
ContentParent::RecvIsSecureURI(
4530 nsIURI
* aURI
, const OriginAttributes
& aOriginAttributes
,
4531 bool* aIsSecureURI
) {
4532 nsCOMPtr
<nsISiteSecurityService
> sss(do_GetService(NS_SSSERVICE_CONTRACTID
));
4534 return IPC_FAIL(this, "Failed to get nsISiteSecurityService.");
4537 return IPC_FAIL(this, "aURI must not be null.");
4539 nsresult rv
= sss
->IsSecureURI(aURI
, aOriginAttributes
, aIsSecureURI
);
4540 if (NS_FAILED(rv
)) {
4541 return IPC_FAIL(this, "IsSecureURI failed.");
4546 mozilla::ipc::IPCResult
ContentParent::RecvAccumulateMixedContentHSTS(
4547 nsIURI
* aURI
, const bool& aActive
,
4548 const OriginAttributes
& aOriginAttributes
) {
4550 return IPC_FAIL(this, "aURI must not be null.");
4552 nsMixedContentBlocker::AccumulateMixedContentHSTS(aURI
, aActive
,
4557 mozilla::ipc::IPCResult
ContentParent::RecvLoadURIExternal(
4558 nsIURI
* uri
, nsIPrincipal
* aTriggeringPrincipal
,
4559 nsIPrincipal
* aRedirectPrincipal
,
4560 const MaybeDiscarded
<BrowsingContext
>& aContext
,
4561 bool aWasExternallyTriggered
, bool aHasValidUserGestureActivation
) {
4562 if (aContext
.IsDiscarded()) {
4566 nsCOMPtr
<nsIExternalProtocolService
> extProtService(
4567 do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID
));
4568 if (!extProtService
) {
4573 return IPC_FAIL(this, "uri must not be null.");
4576 BrowsingContext
* bc
= aContext
.get();
4577 extProtService
->LoadURI(uri
, aTriggeringPrincipal
, aRedirectPrincipal
, bc
,
4578 aWasExternallyTriggered
,
4579 aHasValidUserGestureActivation
);
4583 mozilla::ipc::IPCResult
ContentParent::RecvExtProtocolChannelConnectParent(
4584 const uint64_t& registrarId
) {
4587 // First get the real channel created before redirect on the parent.
4588 nsCOMPtr
<nsIChannel
> channel
;
4589 rv
= NS_LinkRedirectChannels(registrarId
, nullptr, getter_AddRefs(channel
));
4590 NS_ENSURE_SUCCESS(rv
, IPC_OK());
4592 nsCOMPtr
<nsIParentChannel
> parent
= do_QueryInterface(channel
, &rv
);
4593 NS_ENSURE_SUCCESS(rv
, IPC_OK());
4595 // The channel itself is its own (faked) parent, link it.
4596 rv
= NS_LinkRedirectChannels(registrarId
, parent
, getter_AddRefs(channel
));
4597 NS_ENSURE_SUCCESS(rv
, IPC_OK());
4599 // Signal the parent channel that it's a redirect-to parent. This will
4600 // make AsyncOpen on it do nothing (what we want).
4601 // Yes, this is a bit of a hack, but I don't think it's necessary to invent
4602 // a new interface just to set this flag on the channel.
4603 parent
->SetParentListener(nullptr);
4608 mozilla::ipc::IPCResult
ContentParent::RecvShowAlert(
4609 nsIAlertNotification
* aAlert
) {
4611 return IPC_FAIL(this, "aAlert must not be null.");
4613 nsCOMPtr
<nsIAlertsService
> sysAlerts(components::Alerts::Service());
4615 sysAlerts
->ShowAlert(aAlert
, this);
4620 mozilla::ipc::IPCResult
ContentParent::RecvCloseAlert(const nsAString
& aName
,
4621 bool aContextClosed
) {
4622 nsCOMPtr
<nsIAlertsService
> sysAlerts(components::Alerts::Service());
4624 sysAlerts
->CloseAlert(aName
, aContextClosed
);
4630 mozilla::ipc::IPCResult
ContentParent::RecvDisableNotifications(
4631 nsIPrincipal
* aPrincipal
) {
4633 return IPC_FAIL(this, "No principal");
4636 if (!ValidatePrincipal(aPrincipal
)) {
4637 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
4639 Unused
<< Notification::RemovePermission(aPrincipal
);
4643 mozilla::ipc::IPCResult
ContentParent::RecvOpenNotificationSettings(
4644 nsIPrincipal
* aPrincipal
) {
4646 return IPC_FAIL(this, "No principal");
4649 if (!ValidatePrincipal(aPrincipal
)) {
4650 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
4652 Unused
<< Notification::OpenSettings(aPrincipal
);
4656 mozilla::ipc::IPCResult
ContentParent::RecvNotificationEvent(
4657 const nsAString
& aType
, const NotificationEventData
& aData
) {
4658 nsCOMPtr
<nsIServiceWorkerManager
> swm
=
4659 mozilla::components::ServiceWorkerManager::Service();
4660 if (NS_WARN_IF(!swm
)) {
4661 // Probably shouldn't happen, but no need to crash the child process.
4665 if (aType
.EqualsLiteral("click")) {
4666 nsresult rv
= swm
->SendNotificationClickEvent(
4667 aData
.originSuffix(), aData
.scope(), aData
.ID(), aData
.title(),
4668 aData
.dir(), aData
.lang(), aData
.body(), aData
.tag(), aData
.icon(),
4669 aData
.data(), aData
.behavior());
4670 Unused
<< NS_WARN_IF(NS_FAILED(rv
));
4672 MOZ_ASSERT(aType
.EqualsLiteral("close"));
4673 nsresult rv
= swm
->SendNotificationCloseEvent(
4674 aData
.originSuffix(), aData
.scope(), aData
.ID(), aData
.title(),
4675 aData
.dir(), aData
.lang(), aData
.body(), aData
.tag(), aData
.icon(),
4676 aData
.data(), aData
.behavior());
4677 Unused
<< NS_WARN_IF(NS_FAILED(rv
));
4683 mozilla::ipc::IPCResult
ContentParent::RecvSyncMessage(
4684 const nsAString
& aMsg
, const ClonedMessageData
& aData
,
4685 nsTArray
<StructuredCloneData
>* aRetvals
) {
4686 AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("ContentParent::RecvSyncMessage",
4688 MMPrinter::Print("ContentParent::RecvSyncMessage", aMsg
, aData
);
4690 RefPtr
<nsFrameMessageManager
> ppm
= mMessageManager
;
4692 ipc::StructuredCloneData data
;
4693 ipc::UnpackClonedMessageData(aData
, data
);
4695 ppm
->ReceiveMessage(ppm
, nullptr, aMsg
, true, &data
, aRetvals
,
4701 mozilla::ipc::IPCResult
ContentParent::RecvAsyncMessage(
4702 const nsAString
& aMsg
, const ClonedMessageData
& aData
) {
4703 AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("ContentParent::RecvAsyncMessage",
4705 MMPrinter::Print("ContentParent::RecvAsyncMessage", aMsg
, aData
);
4707 RefPtr
<nsFrameMessageManager
> ppm
= mMessageManager
;
4709 ipc::StructuredCloneData data
;
4710 ipc::UnpackClonedMessageData(aData
, data
);
4712 ppm
->ReceiveMessage(ppm
, nullptr, aMsg
, false, &data
, nullptr,
4719 static int32_t AddGeolocationListener(
4720 nsIDOMGeoPositionCallback
* watcher
,
4721 nsIDOMGeoPositionErrorCallback
* errorCallBack
, bool highAccuracy
) {
4722 RefPtr
<Geolocation
> geo
= Geolocation::NonWindowSingleton();
4724 UniquePtr
<PositionOptions
> options
= MakeUnique
<PositionOptions
>();
4725 options
->mTimeout
= 0;
4726 options
->mMaximumAge
= 0;
4727 options
->mEnableHighAccuracy
= highAccuracy
;
4728 return geo
->WatchPosition(watcher
, errorCallBack
, std::move(options
));
4731 mozilla::ipc::IPCResult
ContentParent::RecvAddGeolocationListener(
4732 const bool& aHighAccuracy
) {
4733 // To ensure no geolocation updates are skipped, we always force the
4734 // creation of a new listener.
4735 RecvRemoveGeolocationListener();
4736 mGeolocationWatchID
= AddGeolocationListener(this, this, aHighAccuracy
);
4740 mozilla::ipc::IPCResult
ContentParent::RecvRemoveGeolocationListener() {
4741 if (mGeolocationWatchID
!= -1) {
4742 RefPtr
<Geolocation
> geo
= Geolocation::NonWindowSingleton();
4744 geo
->ClearWatch(mGeolocationWatchID
);
4746 mGeolocationWatchID
= -1;
4751 mozilla::ipc::IPCResult
ContentParent::RecvSetGeolocationHigherAccuracy(
4752 const bool& aEnable
) {
4753 // This should never be called without a listener already present,
4754 // so this check allows us to forgo securing privileges.
4755 if (mGeolocationWatchID
!= -1) {
4756 RecvRemoveGeolocationListener();
4757 mGeolocationWatchID
= AddGeolocationListener(this, this, aEnable
);
4763 ContentParent::HandleEvent(nsIDOMGeoPosition
* postion
) {
4764 Unused
<< SendGeolocationUpdate(postion
);
4769 ContentParent::HandleEvent(GeolocationPositionError
* positionError
) {
4770 Unused
<< SendGeolocationError(positionError
->Code());
4774 mozilla::ipc::IPCResult
ContentParent::RecvConsoleMessage(
4775 const nsAString
& aMessage
) {
4777 nsCOMPtr
<nsIConsoleService
> consoleService
=
4778 do_GetService(NS_CONSOLESERVICE_CONTRACTID
, &rv
);
4779 if (NS_SUCCEEDED(rv
)) {
4780 RefPtr
<nsConsoleMessage
> msg(new nsConsoleMessage(aMessage
));
4781 msg
->SetIsForwardedFromContentProcess(true);
4782 consoleService
->LogMessageWithMode(msg
, nsIConsoleService::SuppressLog
);
4787 mozilla::ipc::IPCResult
ContentParent::RecvReportFrameTimingData(
4788 const LoadInfoArgs
& loadInfoArgs
, const nsAString
& entryName
,
4789 const nsAString
& initiatorType
, UniquePtr
<PerformanceTimingData
>&& aData
) {
4791 return IPC_FAIL(this, "aData should not be null");
4794 RefPtr
<WindowGlobalParent
> parent
=
4795 WindowGlobalParent::GetByInnerWindowId(loadInfoArgs
.innerWindowID());
4796 if (!parent
|| !parent
->GetContentParent()) {
4800 MOZ_ASSERT(parent
->GetContentParent() != this,
4801 "No need to bounce around if in the same process");
4803 Unused
<< parent
->GetContentParent()->SendReportFrameTimingData(
4804 loadInfoArgs
, entryName
, initiatorType
, aData
);
4808 mozilla::ipc::IPCResult
ContentParent::RecvScriptError(
4809 const nsAString
& aMessage
, const nsAString
& aSourceName
,
4810 const nsAString
& aSourceLine
, const uint32_t& aLineNumber
,
4811 const uint32_t& aColNumber
, const uint32_t& aFlags
,
4812 const nsACString
& aCategory
, const bool& aIsFromPrivateWindow
,
4813 const uint64_t& aInnerWindowId
, const bool& aIsFromChromeContext
) {
4814 return RecvScriptErrorInternal(aMessage
, aSourceName
, aSourceLine
,
4815 aLineNumber
, aColNumber
, aFlags
, aCategory
,
4816 aIsFromPrivateWindow
, aIsFromChromeContext
);
4819 mozilla::ipc::IPCResult
ContentParent::RecvScriptErrorWithStack(
4820 const nsAString
& aMessage
, const nsAString
& aSourceName
,
4821 const nsAString
& aSourceLine
, const uint32_t& aLineNumber
,
4822 const uint32_t& aColNumber
, const uint32_t& aFlags
,
4823 const nsACString
& aCategory
, const bool& aIsFromPrivateWindow
,
4824 const bool& aIsFromChromeContext
, const ClonedMessageData
& aStack
) {
4825 return RecvScriptErrorInternal(
4826 aMessage
, aSourceName
, aSourceLine
, aLineNumber
, aColNumber
, aFlags
,
4827 aCategory
, aIsFromPrivateWindow
, aIsFromChromeContext
, &aStack
);
4830 mozilla::ipc::IPCResult
ContentParent::RecvScriptErrorInternal(
4831 const nsAString
& aMessage
, const nsAString
& aSourceName
,
4832 const nsAString
& aSourceLine
, const uint32_t& aLineNumber
,
4833 const uint32_t& aColNumber
, const uint32_t& aFlags
,
4834 const nsACString
& aCategory
, const bool& aIsFromPrivateWindow
,
4835 const bool& aIsFromChromeContext
, const ClonedMessageData
* aStack
) {
4837 nsCOMPtr
<nsIConsoleService
> consoleService
=
4838 do_GetService(NS_CONSOLESERVICE_CONTRACTID
, &rv
);
4839 if (NS_FAILED(rv
)) {
4843 nsCOMPtr
<nsIScriptError
> msg
;
4846 StructuredCloneData data
;
4847 UnpackClonedMessageData(*aStack
, data
);
4850 if (NS_WARN_IF(!jsapi
.Init(xpc::PrivilegedJunkScope()))) {
4853 JSContext
* cx
= jsapi
.cx();
4855 JS::Rooted
<JS::Value
> stack(cx
);
4857 data
.Read(cx
, &stack
, rv
);
4858 if (rv
.Failed() || !stack
.isObject()) {
4859 rv
.SuppressException();
4863 JS::Rooted
<JSObject
*> stackObj(cx
, &stack
.toObject());
4864 if (!JS::IsUnwrappedSavedFrame(stackObj
)) {
4865 return IPC_FAIL(this, "Unexpected object");
4868 JS::Rooted
<JSObject
*> stackGlobal(cx
, JS::GetNonCCWObjectGlobal(stackObj
));
4869 msg
= new nsScriptErrorWithStack(JS::NothingHandleValue
, stackObj
,
4872 msg
= new nsScriptError();
4875 rv
= msg
->Init(aMessage
, aSourceName
, aSourceLine
, aLineNumber
, aColNumber
,
4876 aFlags
, aCategory
, aIsFromPrivateWindow
, aIsFromChromeContext
);
4877 if (NS_FAILED(rv
)) return IPC_OK();
4879 msg
->SetIsForwardedFromContentProcess(true);
4881 consoleService
->LogMessageWithMode(msg
, nsIConsoleService::SuppressLog
);
4885 bool ContentParent::DoLoadMessageManagerScript(const nsAString
& aURL
,
4886 bool aRunInGlobalScope
) {
4887 MOZ_ASSERT(!aRunInGlobalScope
);
4888 return SendLoadProcessScript(aURL
);
4891 nsresult
ContentParent::DoSendAsyncMessage(const nsAString
& aMessage
,
4892 StructuredCloneData
& aData
) {
4893 ClonedMessageData data
;
4894 if (!BuildClonedMessageData(aData
, data
)) {
4895 return NS_ERROR_DOM_DATA_CLONE_ERR
;
4897 if (!SendAsyncMessage(aMessage
, data
)) {
4898 return NS_ERROR_UNEXPECTED
;
4903 mozilla::ipc::IPCResult
ContentParent::RecvCopyFavicon(
4904 nsIURI
* aOldURI
, nsIURI
* aNewURI
, const bool& aInPrivateBrowsing
) {
4906 return IPC_FAIL(this, "aOldURI should not be null");
4909 return IPC_FAIL(this, "aNewURI should not be null");
4912 nsDocShell::CopyFavicon(aOldURI
, aNewURI
, aInPrivateBrowsing
);
4916 mozilla::ipc::IPCResult
ContentParent::RecvFindImageText(
4917 IPCImage
&& aImage
, nsTArray
<nsCString
>&& aLanguages
,
4918 FindImageTextResolver
&& aResolver
) {
4919 if (!TextRecognition::IsSupported() ||
4920 !Preferences::GetBool("dom.text-recognition.enabled")) {
4921 return IPC_FAIL(this, "Text recognition not available.");
4924 RefPtr
<DataSourceSurface
> surf
= nsContentUtils::IPCImageToSurface(aImage
);
4926 aResolver(TextRecognitionResultOrError("Failed to read image"_ns
));
4929 TextRecognition::FindText(*surf
, aLanguages
)
4931 GetCurrentSerialEventTarget(), __func__
,
4932 [resolver
= std::move(aResolver
)](
4933 TextRecognition::NativePromise::ResolveOrRejectValue
&& aValue
) {
4934 if (aValue
.IsResolve()) {
4935 resolver(TextRecognitionResultOrError(aValue
.ResolveValue()));
4937 resolver(TextRecognitionResultOrError(aValue
.RejectValue()));
4943 bool ContentParent::ShouldContinueFromReplyTimeout() {
4944 RefPtr
<ProcessHangMonitor
> monitor
= ProcessHangMonitor::Get();
4945 return !monitor
|| !monitor
->ShouldTimeOutCPOWs();
4948 mozilla::ipc::IPCResult
ContentParent::RecvAddIdleObserver(
4949 const uint64_t& aObserverId
, const uint32_t& aIdleTimeInS
) {
4951 nsCOMPtr
<nsIUserIdleService
> idleService
=
4952 do_GetService("@mozilla.org/widget/useridleservice;1", &rv
);
4953 NS_ENSURE_SUCCESS(rv
, IPC_FAIL(this, "Failed to get UserIdleService."));
4955 RefPtr
<ParentIdleListener
> listener
=
4956 new ParentIdleListener(this, aObserverId
, aIdleTimeInS
);
4957 rv
= idleService
->AddIdleObserver(listener
, aIdleTimeInS
);
4958 NS_ENSURE_SUCCESS(rv
, IPC_FAIL(this, "AddIdleObserver failed."));
4959 mIdleListeners
.AppendElement(listener
);
4963 mozilla::ipc::IPCResult
ContentParent::RecvRemoveIdleObserver(
4964 const uint64_t& aObserverId
, const uint32_t& aIdleTimeInS
) {
4965 RefPtr
<ParentIdleListener
> listener
;
4966 for (int32_t i
= mIdleListeners
.Length() - 1; i
>= 0; --i
) {
4967 listener
= static_cast<ParentIdleListener
*>(mIdleListeners
[i
].get());
4968 if (listener
->mObserver
== aObserverId
&& listener
->mTime
== aIdleTimeInS
) {
4970 nsCOMPtr
<nsIUserIdleService
> idleService
=
4971 do_GetService("@mozilla.org/widget/useridleservice;1", &rv
);
4972 NS_ENSURE_SUCCESS(rv
, IPC_FAIL(this, "Failed to get UserIdleService."));
4973 idleService
->RemoveIdleObserver(listener
, aIdleTimeInS
);
4974 mIdleListeners
.RemoveElementAt(i
);
4981 mozilla::ipc::IPCResult
ContentParent::RecvBackUpXResources(
4982 const FileDescriptor
& aXSocketFd
) {
4984 MOZ_CRASH("This message only makes sense on X11 platforms");
4986 MOZ_ASSERT(!mChildXSocketFdDup
, "Already backed up X resources??");
4987 if (aXSocketFd
.IsValid()) {
4988 mChildXSocketFdDup
= aXSocketFd
.ClonePlatformHandle();
4994 class AnonymousTemporaryFileRequestor final
: public Runnable
{
4996 AnonymousTemporaryFileRequestor(ContentParent
* aCP
, const uint64_t& aID
)
4997 : Runnable("dom::AnonymousTemporaryFileRequestor"),
5003 NS_IMETHOD
Run() override
{
5004 if (NS_IsMainThread()) {
5005 FileDescOrError result
;
5006 if (NS_WARN_IF(NS_FAILED(mRv
))) {
5007 // Returning false will kill the child process; instead
5008 // propagate the error and let the child handle it.
5011 result
= FileDescriptor(FileDescriptor::PlatformHandleType(
5012 PR_FileDesc2NativeHandle(mPRFD
)));
5013 // The FileDescriptor object owns a duplicate of the file handle; we
5014 // must close the original (and clean up the NSPR descriptor).
5017 Unused
<< mCP
->SendProvideAnonymousTemporaryFile(mID
, result
);
5018 // It's important to release this reference while wr're on the main
5022 mRv
= NS_OpenAnonymousTemporaryFile(&mPRFD
);
5023 NS_DispatchToMainThread(this);
5029 RefPtr
<ContentParent
> mCP
;
5035 mozilla::ipc::IPCResult
ContentParent::RecvRequestAnonymousTemporaryFile(
5036 const uint64_t& aID
) {
5037 // Make sure to send a callback to the child if we bail out early.
5038 nsresult rv
= NS_OK
;
5039 RefPtr
<ContentParent
> self(this);
5040 auto autoNotifyChildOnError
= MakeScopeExit([&, self
]() {
5041 if (NS_FAILED(rv
)) {
5042 FileDescOrError
result(rv
);
5043 Unused
<< self
->SendProvideAnonymousTemporaryFile(aID
, result
);
5047 // We use a helper runnable to open the anonymous temporary file on the IO
5048 // thread. The same runnable will call us back on the main thread when the
5049 // file has been opened.
5050 nsCOMPtr
<nsIEventTarget
> target
=
5051 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID
, &rv
);
5056 rv
= target
->Dispatch(new AnonymousTemporaryFileRequestor(this, aID
),
5057 NS_DISPATCH_NORMAL
);
5058 if (NS_WARN_IF(NS_FAILED(rv
))) {
5066 mozilla::ipc::IPCResult
ContentParent::RecvCreateAudioIPCConnection(
5067 CreateAudioIPCConnectionResolver
&& aResolver
) {
5068 FileDescriptor fd
= CubebUtils::CreateAudioIPCConnection();
5069 FileDescOrError result
;
5073 result
= NS_ERROR_FAILURE
;
5079 already_AddRefed
<extensions::PExtensionsParent
>
5080 ContentParent::AllocPExtensionsParent() {
5081 return MakeAndAddRef
<extensions::ExtensionsParent
>();
5084 void ContentParent::NotifyUpdatedDictionaries() {
5085 RefPtr
<mozSpellChecker
> spellChecker(mozSpellChecker::Create());
5086 MOZ_ASSERT(spellChecker
, "No spell checker?");
5088 nsTArray
<nsCString
> dictionaries
;
5089 spellChecker
->GetDictionaryList(&dictionaries
);
5091 for (auto* cp
: AllProcesses(eLive
)) {
5092 Unused
<< cp
->SendUpdateDictionaryList(dictionaries
);
5096 void ContentParent::NotifyUpdatedFonts(bool aFullRebuild
) {
5097 if (gfxPlatformFontList::PlatformFontList()->SharedFontList()) {
5098 for (auto* cp
: AllProcesses(eLive
)) {
5099 Unused
<< cp
->SendRebuildFontList(aFullRebuild
);
5104 SystemFontList fontList
;
5105 gfxPlatform::GetPlatform()->ReadSystemFontList(&fontList
);
5107 for (auto* cp
: AllProcesses(eLive
)) {
5108 Unused
<< cp
->SendUpdateFontList(fontList
);
5113 PWebrtcGlobalParent
* ContentParent::AllocPWebrtcGlobalParent() {
5114 return WebrtcGlobalParent::Alloc();
5117 bool ContentParent::DeallocPWebrtcGlobalParent(PWebrtcGlobalParent
* aActor
) {
5118 WebrtcGlobalParent::Dealloc(static_cast<WebrtcGlobalParent
*>(aActor
));
5123 void ContentParent::GetIPCTransferableData(
5124 nsIDragSession
* aSession
, BrowserParent
* aParent
,
5125 nsTArray
<IPCTransferableData
>& aIPCTransferables
) {
5126 RefPtr
<DataTransfer
> transfer
= aSession
->GetDataTransfer();
5128 // Pass eDrop to get DataTransfer with external
5129 // drag formats cached.
5130 transfer
= new DataTransfer(nullptr, eDrop
, true, -1);
5131 aSession
->SetDataTransfer(transfer
);
5133 // Note, even though this fills the DataTransfer object with
5134 // external data, the data is usually transfered over IPC lazily when
5136 transfer
->FillAllExternalData();
5137 nsCOMPtr
<nsILoadContext
> lc
= aParent
? aParent
->GetLoadContext() : nullptr;
5138 nsCOMPtr
<nsIArray
> transferables
= transfer
->GetTransferables(lc
);
5139 nsContentUtils::TransferablesToIPCTransferableDatas(
5140 transferables
, aIPCTransferables
, false, this);
5143 void ContentParent::MaybeInvokeDragSession(BrowserParent
* aParent
,
5144 EventMessage aMessage
) {
5145 // dnd uses IPCBlob to transfer data to the content process and the IPC
5146 // message is sent as normal priority. When sending input events with input
5147 // priority, the message may be preempted by the later dnd events. To make
5148 // sure the input events and the blob message are processed in time order
5149 // on the content process, we temporarily send the input events with normal
5150 // priority when there is an active dnd session.
5151 SetInputPriorityEventEnabled(false);
5153 nsCOMPtr
<nsIDragService
> dragService
=
5154 do_GetService("@mozilla.org/widget/dragservice;1");
5159 if (dragService
->MaybeAddChildProcess(this)) {
5160 nsCOMPtr
<nsIDragSession
> session
;
5161 dragService
->GetCurrentSession(getter_AddRefs(session
));
5163 // We need to send transferable data to child process.
5164 nsTArray
<IPCTransferableData
> ipcTransferables
;
5165 GetIPCTransferableData(session
, aParent
, ipcTransferables
);
5167 session
->GetDragAction(&action
);
5169 RefPtr
<WindowContext
> sourceWC
;
5170 session
->GetSourceWindowContext(getter_AddRefs(sourceWC
));
5171 RefPtr
<WindowContext
> sourceTopWC
;
5172 session
->GetSourceTopWindowContext(getter_AddRefs(sourceTopWC
));
5173 mozilla::Unused
<< SendInvokeDragSession(
5174 sourceWC
, sourceTopWC
, std::move(ipcTransferables
), action
);
5179 if (dragService
->MustUpdateDataTransfer(aMessage
)) {
5180 nsCOMPtr
<nsIDragSession
> session
;
5181 dragService
->GetCurrentSession(getter_AddRefs(session
));
5183 // We need to send transferable data to child process.
5184 nsTArray
<IPCTransferableData
> ipcTransferables
;
5185 GetIPCTransferableData(session
, aParent
, ipcTransferables
);
5186 mozilla::Unused
<< SendUpdateDragSession(std::move(ipcTransferables
),
5192 mozilla::ipc::IPCResult
ContentParent::RecvUpdateDropEffect(
5193 const uint32_t& aDragAction
, const uint32_t& aDropEffect
) {
5194 nsCOMPtr
<nsIDragSession
> dragSession
= nsContentUtils::GetDragSession();
5196 dragSession
->SetDragAction(aDragAction
);
5197 RefPtr
<DataTransfer
> dt
= dragSession
->GetDataTransfer();
5199 dt
->SetDropEffectInt(aDropEffect
);
5201 dragSession
->UpdateDragEffect();
5206 PContentPermissionRequestParent
*
5207 ContentParent::AllocPContentPermissionRequestParent(
5208 const nsTArray
<PermissionRequest
>& aRequests
, nsIPrincipal
* aPrincipal
,
5209 nsIPrincipal
* aTopLevelPrincipal
, const bool& aIsHandlingUserInput
,
5210 const bool& aMaybeUnsafePermissionDelegate
, const TabId
& aTabId
) {
5211 RefPtr
<BrowserParent
> tp
;
5212 ContentProcessManager
* cpm
= ContentProcessManager::GetSingleton();
5215 cpm
->GetTopLevelBrowserParentByProcessAndTabId(this->ChildID(), aTabId
);
5221 nsIPrincipal
* topPrincipal
= aTopLevelPrincipal
;
5222 if (!topPrincipal
) {
5223 nsCOMPtr
<nsIPrincipal
> principal
= tp
->GetContentPrincipal();
5224 topPrincipal
= principal
;
5226 return nsContentPermissionUtils::CreateContentPermissionRequestParent(
5227 aRequests
, tp
->GetOwnerElement(), aPrincipal
, topPrincipal
,
5228 aIsHandlingUserInput
, aMaybeUnsafePermissionDelegate
, aTabId
);
5231 bool ContentParent::DeallocPContentPermissionRequestParent(
5232 PContentPermissionRequestParent
* actor
) {
5233 nsContentPermissionUtils::NotifyRemoveContentPermissionRequestParent(actor
);
5238 already_AddRefed
<PWebBrowserPersistDocumentParent
>
5239 ContentParent::AllocPWebBrowserPersistDocumentParent(
5240 PBrowserParent
* aBrowser
, const MaybeDiscarded
<BrowsingContext
>& aContext
) {
5241 return MakeAndAddRef
<WebBrowserPersistDocumentParent
>();
5244 mozilla::ipc::IPCResult
ContentParent::CommonCreateWindow(
5245 PBrowserParent
* aThisTab
, BrowsingContext
& aParent
, bool aSetOpener
,
5246 const uint32_t& aChromeFlags
, const bool& aCalledFromJS
,
5247 const bool& aForPrinting
, const bool& aForWindowDotPrint
,
5248 const bool& aIsTopLevelCreatedByWebContent
, nsIURI
* aURIToLoad
,
5249 const nsACString
& aFeatures
, const UserActivation::Modifiers
& aModifiers
,
5250 BrowserParent
* aNextRemoteBrowser
, const nsAString
& aName
,
5251 nsresult
& aResult
, nsCOMPtr
<nsIRemoteTab
>& aNewRemoteTab
,
5252 bool* aWindowIsNew
, int32_t& aOpenLocation
,
5253 nsIPrincipal
* aTriggeringPrincipal
, nsIReferrerInfo
* aReferrerInfo
,
5254 bool aLoadURI
, nsIContentSecurityPolicy
* aCsp
,
5255 const OriginAttributes
& aOriginAttributes
, bool aUserActivation
,
5256 bool aTextDirectiveUserActivation
) {
5257 // The content process should never be in charge of computing whether or
5258 // not a window should be private - the parent will do that.
5259 const uint32_t badFlags
= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW
|
5260 nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW
|
5261 nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME
;
5262 if (!!(aChromeFlags
& badFlags
)) {
5263 return IPC_FAIL(this, "Forbidden aChromeFlags passed");
5266 RefPtr
<nsOpenWindowInfo
> openInfo
= new nsOpenWindowInfo();
5267 openInfo
->mForceNoOpener
= !aSetOpener
;
5268 openInfo
->mParent
= &aParent
;
5269 openInfo
->mIsRemote
= true;
5270 openInfo
->mIsForPrinting
= aForPrinting
;
5271 openInfo
->mIsForWindowDotPrint
= aForWindowDotPrint
;
5272 openInfo
->mNextRemoteBrowser
= aNextRemoteBrowser
;
5273 openInfo
->mOriginAttributes
= aOriginAttributes
;
5274 openInfo
->mIsTopLevelCreatedByWebContent
= aIsTopLevelCreatedByWebContent
;
5275 openInfo
->mHasValidUserGestureActivation
= aUserActivation
;
5276 openInfo
->mTextDirectiveUserActivation
= aTextDirectiveUserActivation
;
5278 MOZ_ASSERT_IF(aForWindowDotPrint
, aForPrinting
);
5280 RefPtr
<BrowserParent
> topParent
= BrowserParent::GetFrom(aThisTab
);
5281 while (topParent
&& topParent
->GetBrowserBridgeParent()) {
5282 topParent
= topParent
->GetBrowserBridgeParent()->Manager();
5284 RefPtr
<BrowserHost
> thisBrowserHost
=
5285 topParent
? topParent
->GetBrowserHost() : nullptr;
5286 MOZ_ASSERT_IF(topParent
, thisBrowserHost
);
5287 RefPtr
<BrowsingContext
> topBC
=
5288 topParent
? topParent
->GetBrowsingContext() : nullptr;
5289 MOZ_ASSERT_IF(topParent
, topBC
);
5291 // The content process should have set its remote and fission flags correctly.
5293 if ((!!(aChromeFlags
& nsIWebBrowserChrome::CHROME_REMOTE_WINDOW
) !=
5294 topBC
->UseRemoteTabs()) ||
5295 (!!(aChromeFlags
& nsIWebBrowserChrome::CHROME_FISSION_WINDOW
) !=
5296 topBC
->UseRemoteSubframes())) {
5297 return IPC_FAIL(this, "Unexpected aChromeFlags passed");
5300 if (!aOriginAttributes
.EqualsIgnoringFPD(topBC
->OriginAttributesRef())) {
5301 return IPC_FAIL(this, "Passed-in OriginAttributes does not match opener");
5305 nsCOMPtr
<nsIContent
> frame
;
5307 frame
= topParent
->GetOwnerElement();
5310 nsCOMPtr
<nsPIDOMWindowOuter
> outerWin
;
5312 outerWin
= frame
->OwnerDoc()->GetWindow();
5314 // If our chrome window is in the process of closing, don't try to open a
5316 if (outerWin
&& outerWin
->Closed()) {
5321 nsCOMPtr
<nsIBrowserDOMWindow
> browserDOMWin
;
5323 browserDOMWin
= topParent
->GetBrowserDOMWindow();
5326 // If we haven't found a chrome window to open in, just use the most recently
5329 outerWin
= nsContentUtils::GetMostRecentNonPBWindow();
5330 if (NS_WARN_IF(!outerWin
)) {
5331 aResult
= NS_ERROR_FAILURE
;
5335 if (nsGlobalWindowOuter::Cast(outerWin
)->IsChromeWindow()) {
5337 nsGlobalWindowOuter::Cast(outerWin
)->GetBrowserDOMWindow();
5341 aOpenLocation
= nsWindowWatcher::GetWindowOpenLocation(
5342 outerWin
, aChromeFlags
, aModifiers
, aCalledFromJS
, aForPrinting
);
5344 MOZ_ASSERT(aOpenLocation
== nsIBrowserDOMWindow::OPEN_NEWTAB
||
5345 aOpenLocation
== nsIBrowserDOMWindow::OPEN_NEWTAB_BACKGROUND
||
5346 aOpenLocation
== nsIBrowserDOMWindow::OPEN_NEWWINDOW
||
5347 aOpenLocation
== nsIBrowserDOMWindow::OPEN_PRINT_BROWSER
);
5349 if (NS_WARN_IF(!browserDOMWin
)) {
5350 // Opening in the same window or headless requires an nsIBrowserDOMWindow.
5351 aOpenLocation
= nsIBrowserDOMWindow::OPEN_NEWWINDOW
;
5354 if (aOpenLocation
== nsIBrowserDOMWindow::OPEN_NEWTAB
||
5355 aOpenLocation
== nsIBrowserDOMWindow::OPEN_NEWTAB_BACKGROUND
||
5356 aOpenLocation
== nsIBrowserDOMWindow::OPEN_PRINT_BROWSER
) {
5357 RefPtr
<Element
> openerElement
= do_QueryObject(frame
);
5359 nsCOMPtr
<nsIOpenURIInFrameParams
> params
=
5360 new nsOpenURIInFrameParams(openInfo
, openerElement
);
5361 params
->SetReferrerInfo(aReferrerInfo
);
5362 MOZ_ASSERT(aTriggeringPrincipal
, "need a valid triggeringPrincipal");
5363 params
->SetTriggeringPrincipal(aTriggeringPrincipal
);
5364 params
->SetCsp(aCsp
);
5369 aResult
= browserDOMWin
->OpenURIInFrame(aURIToLoad
, params
, aOpenLocation
,
5370 nsIBrowserDOMWindow::OPEN_NEW
,
5371 aName
, getter_AddRefs(el
));
5373 aResult
= browserDOMWin
->CreateContentWindowInFrame(
5374 aURIToLoad
, params
, aOpenLocation
, nsIBrowserDOMWindow::OPEN_NEW
,
5375 aName
, getter_AddRefs(el
));
5377 RefPtr
<nsFrameLoaderOwner
> frameLoaderOwner
= do_QueryObject(el
);
5378 if (NS_SUCCEEDED(aResult
) && frameLoaderOwner
) {
5379 RefPtr
<nsFrameLoader
> frameLoader
= frameLoaderOwner
->GetFrameLoader();
5381 aNewRemoteTab
= frameLoader
->GetRemoteTab();
5382 // At this point, it's possible the inserted frameloader hasn't gone
5383 // through layout yet. To ensure that the dimensions that we send down
5384 // when telling the frameloader to display will be correct (instead of
5385 // falling back to a 10x10 default), we force layout if necessary to get
5386 // the most up-to-date dimensions. See bug 1358712 for details.
5387 frameLoader
->ForceLayoutIfNecessary();
5389 } else if (NS_SUCCEEDED(aResult
) && !frameLoaderOwner
) {
5390 // Fall through to the normal window opening code path when there is no
5391 // window which we can open a new tab in.
5392 aOpenLocation
= nsIBrowserDOMWindow::OPEN_NEWWINDOW
;
5394 *aWindowIsNew
= false;
5397 // If we didn't retarget our window open into a new window, we should return
5399 if (aOpenLocation
!= nsIBrowserDOMWindow::OPEN_NEWWINDOW
) {
5404 nsCOMPtr
<nsPIWindowWatcher
> pwwatch
=
5405 do_GetService(NS_WINDOWWATCHER_CONTRACTID
, &aResult
);
5406 if (NS_WARN_IF(NS_FAILED(aResult
))) {
5410 WindowFeatures features
;
5411 features
.Tokenize(aFeatures
);
5413 aResult
= pwwatch
->OpenWindowWithRemoteTab(
5414 thisBrowserHost
, features
, aModifiers
, aCalledFromJS
, aParent
.FullZoom(),
5415 openInfo
, getter_AddRefs(aNewRemoteTab
));
5416 if (NS_WARN_IF(NS_FAILED(aResult
))) {
5420 MOZ_ASSERT(aNewRemoteTab
);
5421 RefPtr
<BrowserHost
> newBrowserHost
= BrowserHost::GetFrom(aNewRemoteTab
);
5422 RefPtr
<BrowserParent
> newBrowserParent
= newBrowserHost
->GetActor();
5424 // At this point, it's possible the inserted frameloader hasn't gone through
5425 // layout yet. To ensure that the dimensions that we send down when telling
5426 // the frameloader to display will be correct (instead of falling back to a
5427 // 10x10 default), we force layout if necessary to get the most up-to-date
5428 // dimensions. See bug 1358712 for details.
5429 nsCOMPtr
<Element
> frameElement
= newBrowserHost
->GetOwnerElement();
5430 MOZ_ASSERT(frameElement
);
5431 if (nsWindowWatcher::HaveSpecifiedSize(features
)) {
5432 // We want to flush the layout anyway because of the resize to the specified
5433 // size. (Bug 1793605).
5434 RefPtr
<Document
> chromeDoc
= frameElement
->OwnerDoc();
5435 MOZ_ASSERT(chromeDoc
);
5436 chromeDoc
->FlushPendingNotifications(FlushType::Layout
);
5438 RefPtr
<nsFrameLoaderOwner
> frameLoaderOwner
= do_QueryObject(frameElement
);
5439 MOZ_ASSERT(frameLoaderOwner
);
5440 RefPtr
<nsFrameLoader
> frameLoader
= frameLoaderOwner
->GetFrameLoader();
5441 MOZ_ASSERT(frameLoader
);
5442 frameLoader
->ForceLayoutIfNecessary();
5445 // If we were passed a name for the window which would override the default,
5446 // we should send it down to the new tab.
5447 if (nsContentUtils::IsOverridingWindowName(aName
)) {
5448 MOZ_ALWAYS_SUCCEEDS(newBrowserHost
->GetBrowsingContext()->SetName(aName
));
5451 MOZ_ASSERT(newBrowserHost
->GetBrowsingContext()->OriginAttributesRef() ==
5454 if (aURIToLoad
&& aLoadURI
) {
5455 nsCOMPtr
<mozIDOMWindowProxy
> openerWindow
;
5456 if (aSetOpener
&& topParent
) {
5457 openerWindow
= topParent
->GetParentWindowOuter();
5459 nsCOMPtr
<nsIBrowserDOMWindow
> newBrowserDOMWin
=
5460 newBrowserParent
->GetBrowserDOMWindow();
5461 if (NS_WARN_IF(!newBrowserDOMWin
)) {
5462 aResult
= NS_ERROR_ABORT
;
5465 RefPtr
<BrowsingContext
> bc
;
5466 aResult
= newBrowserDOMWin
->OpenURI(
5467 aURIToLoad
, openInfo
, nsIBrowserDOMWindow::OPEN_CURRENTWINDOW
,
5468 nsIBrowserDOMWindow::OPEN_NEW
, aTriggeringPrincipal
, aCsp
,
5469 getter_AddRefs(bc
));
5475 mozilla::ipc::IPCResult
ContentParent::RecvCreateWindow(
5476 PBrowserParent
* aThisTab
, const MaybeDiscarded
<BrowsingContext
>& aParent
,
5477 PBrowserParent
* aNewTab
, const uint32_t& aChromeFlags
,
5478 const bool& aCalledFromJS
, const bool& aForPrinting
,
5479 const bool& aForWindowDotPrint
, const bool& aIsTopLevelCreatedByWebContent
,
5480 nsIURI
* aURIToLoad
, const nsACString
& aFeatures
,
5481 const UserActivation::Modifiers
& aModifiers
,
5482 nsIPrincipal
* aTriggeringPrincipal
, nsIContentSecurityPolicy
* aCsp
,
5483 nsIReferrerInfo
* aReferrerInfo
, const OriginAttributes
& aOriginAttributes
,
5484 bool aUserActivation
, bool aTextDirectiveUserActivation
,
5485 CreateWindowResolver
&& aResolve
) {
5486 if (!aTriggeringPrincipal
) {
5487 return IPC_FAIL(this, "No principal");
5490 if (!ValidatePrincipal(aTriggeringPrincipal
)) {
5491 LogAndAssertFailedPrincipalValidationInfo(aTriggeringPrincipal
, __func__
);
5494 nsresult rv
= NS_OK
;
5495 CreatedWindowInfo cwi
;
5497 // We always expect to open a new window here. If we don't, it's an error.
5498 cwi
.windowOpened() = true;
5499 cwi
.maxTouchPoints() = 0;
5501 // Make sure to resolve the resolver when this function exits, even if we
5502 // failed to generate a valid response.
5503 auto resolveOnExit
= MakeScopeExit([&] {
5504 // Copy over the nsresult, and then resolve.
5509 RefPtr
<BrowserParent
> thisTab
= BrowserParent::GetFrom(aThisTab
);
5510 RefPtr
<BrowserParent
> newTab
= BrowserParent::GetFrom(aNewTab
);
5513 auto destroyNewTabOnError
= MakeScopeExit([&] {
5514 // We always expect to open a new window here. If we don't, it's an error.
5515 if (!cwi
.windowOpened() || NS_FAILED(rv
)) {
5522 // Don't continue to try to create a new window if we've been fully discarded.
5523 RefPtr
<BrowsingContext
> parent
= aParent
.GetMaybeDiscarded();
5524 if (NS_WARN_IF(!parent
)) {
5525 rv
= NS_ERROR_FAILURE
;
5529 // Validate that our new BrowsingContext looks as we would expect it.
5530 RefPtr
<BrowsingContext
> newBC
= newTab
->GetBrowsingContext();
5532 return IPC_FAIL(this, "Missing BrowsingContext for new tab");
5535 uint64_t newBCOpenerId
= newBC
->GetOpenerId();
5536 if (newBCOpenerId
!= 0 && parent
->Id() != newBCOpenerId
) {
5537 return IPC_FAIL(this, "Invalid opener BrowsingContext for new tab");
5539 if (newBC
->GetParent() != nullptr) {
5540 return IPC_FAIL(this,
5541 "Unexpected non-toplevel BrowsingContext for new tab");
5543 if (!!(aChromeFlags
& nsIWebBrowserChrome::CHROME_REMOTE_WINDOW
) !=
5544 newBC
->UseRemoteTabs() ||
5545 !!(aChromeFlags
& nsIWebBrowserChrome::CHROME_FISSION_WINDOW
) !=
5546 newBC
->UseRemoteSubframes()) {
5547 return IPC_FAIL(this, "Unexpected aChromeFlags passed");
5549 if (!aOriginAttributes
.EqualsIgnoringFPD(newBC
->OriginAttributesRef())) {
5550 return IPC_FAIL(this, "Opened tab has mismatched OriginAttributes");
5553 if (thisTab
&& BrowserParent::GetFrom(thisTab
)->GetBrowsingContext()) {
5554 BrowsingContext
* thisTabBC
= thisTab
->GetBrowsingContext();
5555 if (thisTabBC
->UseRemoteTabs() != newBC
->UseRemoteTabs() ||
5556 thisTabBC
->UseRemoteSubframes() != newBC
->UseRemoteSubframes() ||
5557 thisTabBC
->UsePrivateBrowsing() != newBC
->UsePrivateBrowsing()) {
5558 return IPC_FAIL(this, "New BrowsingContext has mismatched LoadContext");
5561 BrowserParent::AutoUseNewTab
aunt(newTab
);
5563 nsCOMPtr
<nsIRemoteTab
> newRemoteTab
;
5564 int32_t openLocation
= nsIBrowserDOMWindow::OPEN_NEWWINDOW
;
5565 mozilla::ipc::IPCResult ipcResult
= CommonCreateWindow(
5566 aThisTab
, *parent
, newBCOpenerId
!= 0, aChromeFlags
, aCalledFromJS
,
5567 aForPrinting
, aForWindowDotPrint
, aIsTopLevelCreatedByWebContent
,
5568 aURIToLoad
, aFeatures
, aModifiers
, newTab
, VoidString(), rv
, newRemoteTab
,
5569 &cwi
.windowOpened(), openLocation
, aTriggeringPrincipal
, aReferrerInfo
,
5570 /* aLoadUri = */ false, aCsp
, aOriginAttributes
, aUserActivation
,
5571 aTextDirectiveUserActivation
);
5576 if (NS_WARN_IF(NS_FAILED(rv
)) || !newRemoteTab
) {
5580 MOZ_ASSERT(BrowserHost::GetFrom(newRemoteTab
.get()) ==
5581 newTab
->GetBrowserHost());
5583 // This used to happen in the child - there may now be a better place to
5585 MOZ_ALWAYS_SUCCEEDS(newBC
->SetHasSiblings(
5586 openLocation
== nsIBrowserDOMWindow::OPEN_NEWTAB
||
5587 openLocation
== nsIBrowserDOMWindow::OPEN_NEWTAB_BACKGROUND
));
5589 newTab
->SwapFrameScriptsFrom(cwi
.frameScripts());
5590 newTab
->MaybeShowFrame();
5592 nsCOMPtr
<nsIWidget
> widget
= newTab
->GetWidget();
5594 cwi
.dimensions() = newTab
->GetDimensionInfo();
5597 cwi
.maxTouchPoints() = newTab
->GetMaxTouchPoints();
5602 mozilla::ipc::IPCResult
ContentParent::RecvCreateWindowInDifferentProcess(
5603 PBrowserParent
* aThisTab
, const MaybeDiscarded
<BrowsingContext
>& aParent
,
5604 const uint32_t& aChromeFlags
, const bool& aCalledFromJS
,
5605 const bool& aIsTopLevelCreatedByWebContent
, nsIURI
* aURIToLoad
,
5606 const nsACString
& aFeatures
, const UserActivation::Modifiers
& aModifiers
,
5607 const nsAString
& aName
, nsIPrincipal
* aTriggeringPrincipal
,
5608 nsIContentSecurityPolicy
* aCsp
, nsIReferrerInfo
* aReferrerInfo
,
5609 const OriginAttributes
& aOriginAttributes
, bool aUserActivation
,
5610 bool aTextDirectiveUserActivation
) {
5611 MOZ_DIAGNOSTIC_ASSERT(!nsContentUtils::IsSpecialName(aName
));
5613 // Don't continue to try to create a new window if we've been fully discarded.
5614 RefPtr
<BrowsingContext
> parent
= aParent
.GetMaybeDiscarded();
5615 if (NS_WARN_IF(!parent
)) {
5619 nsCOMPtr
<nsIRemoteTab
> newRemoteTab
;
5621 int32_t openLocation
= nsIBrowserDOMWindow::OPEN_NEWWINDOW
;
5623 // If we have enough data, check the schemes of the loader and loadee
5624 // to make sure they make sense.
5625 if (aURIToLoad
&& aURIToLoad
->SchemeIs("file") &&
5626 GetRemoteType() != FILE_REMOTE_TYPE
&&
5627 Preferences::GetBool("browser.tabs.remote.enforceRemoteTypeRestrictions",
5629 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
5631 nsAutoCString uriToLoadStr
;
5632 nsAutoCString triggeringUriStr
;
5633 aURIToLoad
->GetAsciiSpec(uriToLoadStr
);
5634 aTriggeringPrincipal
->GetAsciiSpec(triggeringUriStr
);
5636 NS_WARNING(nsPrintfCString(
5637 "RecvCreateWindowInDifferentProcess blocked loading file "
5638 "scheme from non-file remotetype: %s tried to load %s",
5639 triggeringUriStr
.get(), uriToLoadStr
.get())
5643 "RecvCreateWindowInDifferentProcess blocked loading improper scheme");
5649 mozilla::ipc::IPCResult ipcResult
= CommonCreateWindow(
5650 aThisTab
, *parent
, /* aSetOpener = */ false, aChromeFlags
, aCalledFromJS
,
5651 /* aForPrinting = */ false,
5652 /* aForWindowDotPrint = */ false, aIsTopLevelCreatedByWebContent
,
5653 aURIToLoad
, aFeatures
, aModifiers
,
5654 /* aNextRemoteBrowser = */ nullptr, aName
, rv
, newRemoteTab
, &windowIsNew
,
5655 openLocation
, aTriggeringPrincipal
, aReferrerInfo
,
5656 /* aLoadUri = */ true, aCsp
, aOriginAttributes
, aUserActivation
,
5657 aTextDirectiveUserActivation
);
5662 if (NS_FAILED(rv
)) {
5663 NS_WARNING("Call to CommonCreateWindow failed.");
5669 mozilla::ipc::IPCResult
ContentParent::RecvShutdownProfile(
5670 const nsACString
& aProfile
) {
5671 profiler_received_exit_profile(aProfile
);
5675 mozilla::ipc::IPCResult
ContentParent::RecvShutdownPerfStats(
5676 const nsACString
& aPerfStats
) {
5677 PerfStats::StorePerfStats(this, aPerfStats
);
5681 mozilla::ipc::IPCResult
ContentParent::RecvGetFontListShmBlock(
5682 const uint32_t& aGeneration
, const uint32_t& aIndex
,
5683 base::SharedMemoryHandle
* aOut
) {
5684 auto* fontList
= gfxPlatformFontList::PlatformFontList();
5685 MOZ_RELEASE_ASSERT(fontList
, "gfxPlatformFontList not initialized?");
5686 fontList
->ShareFontListShmBlockToProcess(aGeneration
, aIndex
, Pid(), aOut
);
5690 mozilla::ipc::IPCResult
ContentParent::RecvInitializeFamily(
5691 const uint32_t& aGeneration
, const uint32_t& aFamilyIndex
,
5692 const bool& aLoadCmaps
) {
5693 auto* fontList
= gfxPlatformFontList::PlatformFontList();
5694 MOZ_RELEASE_ASSERT(fontList
, "gfxPlatformFontList not initialized?");
5695 fontList
->InitializeFamily(aGeneration
, aFamilyIndex
, aLoadCmaps
);
5699 mozilla::ipc::IPCResult
ContentParent::RecvSetCharacterMap(
5700 const uint32_t& aGeneration
, const uint32_t& aFamilyIndex
,
5701 const bool& aAlias
, const uint32_t& aFaceIndex
,
5702 const gfxSparseBitSet
& aMap
) {
5703 auto* fontList
= gfxPlatformFontList::PlatformFontList();
5704 MOZ_RELEASE_ASSERT(fontList
, "gfxPlatformFontList not initialized?");
5705 fontList
->SetCharacterMap(aGeneration
, aFamilyIndex
, aAlias
, aFaceIndex
,
5710 mozilla::ipc::IPCResult
ContentParent::RecvInitOtherFamilyNames(
5711 const uint32_t& aGeneration
, const bool& aDefer
, bool* aLoaded
) {
5712 auto* fontList
= gfxPlatformFontList::PlatformFontList();
5713 MOZ_RELEASE_ASSERT(fontList
, "gfxPlatformFontList not initialized?");
5714 *aLoaded
= fontList
->InitOtherFamilyNames(aGeneration
, aDefer
);
5718 mozilla::ipc::IPCResult
ContentParent::RecvSetupFamilyCharMap(
5719 const uint32_t& aGeneration
, const uint32_t& aIndex
, const bool& aAlias
) {
5720 auto* fontList
= gfxPlatformFontList::PlatformFontList();
5721 MOZ_RELEASE_ASSERT(fontList
, "gfxPlatformFontList not initialized?");
5722 fontList
->SetupFamilyCharMap(aGeneration
, aIndex
, aAlias
);
5726 mozilla::ipc::IPCResult
ContentParent::RecvStartCmapLoading(
5727 const uint32_t& aGeneration
, const uint32_t& aStartIndex
) {
5728 auto* fontList
= gfxPlatformFontList::PlatformFontList();
5729 MOZ_RELEASE_ASSERT(fontList
, "gfxPlatformFontList not initialized?");
5730 fontList
->StartCmapLoading(aGeneration
, aStartIndex
);
5734 mozilla::ipc::IPCResult
ContentParent::RecvGetHyphDict(
5735 nsIURI
* aURI
, base::SharedMemoryHandle
* aOutHandle
, uint32_t* aOutSize
) {
5737 return IPC_FAIL(this, "aURI must not be null.");
5739 nsHyphenationManager::Instance()->ShareHyphDictToProcess(
5740 aURI
, Pid(), aOutHandle
, aOutSize
);
5744 mozilla::ipc::IPCResult
ContentParent::RecvGraphicsError(
5745 const nsACString
& aError
) {
5746 if (gfx::LogForwarder
* lf
= gfx::Factory::GetLogForwarder()) {
5747 std::stringstream message
;
5748 message
<< "CP+" << aError
;
5749 lf
->UpdateStringsVector(message
.str());
5754 mozilla::ipc::IPCResult
ContentParent::RecvBeginDriverCrashGuard(
5755 const uint32_t& aGuardType
, bool* aOutCrashed
) {
5756 // Only one driver crash guard should be active at a time, per-process.
5757 MOZ_ASSERT(!mDriverCrashGuard
);
5759 UniquePtr
<gfx::DriverCrashGuard
> guard
;
5760 switch (gfx::CrashGuardType(aGuardType
)) {
5761 case gfx::CrashGuardType::D3D11Layers
:
5762 guard
= MakeUnique
<gfx::D3D11LayersCrashGuard
>(this);
5764 case gfx::CrashGuardType::GLContext
:
5765 guard
= MakeUnique
<gfx::GLContextCrashGuard
>(this);
5767 case gfx::CrashGuardType::WMFVPXVideo
:
5768 guard
= MakeUnique
<gfx::WMFVPXVideoCrashGuard
>(this);
5771 return IPC_FAIL(this, "unknown crash guard type");
5774 if (guard
->Crashed()) {
5775 *aOutCrashed
= true;
5779 *aOutCrashed
= false;
5780 mDriverCrashGuard
= std::move(guard
);
5784 mozilla::ipc::IPCResult
ContentParent::RecvEndDriverCrashGuard(
5785 const uint32_t& aGuardType
) {
5786 mDriverCrashGuard
= nullptr;
5790 mozilla::ipc::IPCResult
ContentParent::RecvNotifyBenchmarkResult(
5791 const nsAString
& aCodecName
, const uint32_t& aDecodeFPS
)
5794 if (aCodecName
.EqualsLiteral("VP9")) {
5795 Preferences::SetUint(VP9Benchmark::sBenchmarkFpsPref
, aDecodeFPS
);
5796 Preferences::SetUint(VP9Benchmark::sBenchmarkFpsVersionCheck
,
5797 VP9Benchmark::sBenchmarkVersionID
);
5802 mozilla::ipc::IPCResult
ContentParent::RecvNotifyPushObservers(
5803 const nsACString
& aScope
, nsIPrincipal
* aPrincipal
,
5804 const nsAString
& aMessageId
) {
5806 return IPC_FAIL(this, "No principal");
5809 if (!ValidatePrincipal(aPrincipal
)) {
5810 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
5812 PushMessageDispatcher
dispatcher(aScope
, aPrincipal
, aMessageId
, Nothing());
5813 Unused
<< NS_WARN_IF(NS_FAILED(dispatcher
.NotifyObserversAndWorkers()));
5817 mozilla::ipc::IPCResult
ContentParent::RecvNotifyPushObserversWithData(
5818 const nsACString
& aScope
, nsIPrincipal
* aPrincipal
,
5819 const nsAString
& aMessageId
, nsTArray
<uint8_t>&& aData
) {
5821 return IPC_FAIL(this, "No principal");
5824 if (!ValidatePrincipal(aPrincipal
)) {
5825 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
5827 PushMessageDispatcher
dispatcher(aScope
, aPrincipal
, aMessageId
,
5828 Some(std::move(aData
)));
5829 Unused
<< NS_WARN_IF(NS_FAILED(dispatcher
.NotifyObserversAndWorkers()));
5833 mozilla::ipc::IPCResult
5834 ContentParent::RecvNotifyPushSubscriptionChangeObservers(
5835 const nsACString
& aScope
, nsIPrincipal
* aPrincipal
) {
5837 return IPC_FAIL(this, "No principal");
5840 if (!ValidatePrincipal(aPrincipal
)) {
5841 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
5843 PushSubscriptionChangeDispatcher
dispatcher(aScope
, aPrincipal
);
5844 Unused
<< NS_WARN_IF(NS_FAILED(dispatcher
.NotifyObserversAndWorkers()));
5848 mozilla::ipc::IPCResult
ContentParent::RecvPushError(const nsACString
& aScope
,
5849 nsIPrincipal
* aPrincipal
,
5850 const nsAString
& aMessage
,
5851 const uint32_t& aFlags
) {
5853 return IPC_FAIL(this, "No principal");
5856 if (!ValidatePrincipal(aPrincipal
)) {
5857 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
5859 PushErrorDispatcher
dispatcher(aScope
, aPrincipal
, aMessage
, aFlags
);
5860 Unused
<< NS_WARN_IF(NS_FAILED(dispatcher
.NotifyObserversAndWorkers()));
5864 mozilla::ipc::IPCResult
5865 ContentParent::RecvNotifyPushSubscriptionModifiedObservers(
5866 const nsACString
& aScope
, nsIPrincipal
* aPrincipal
) {
5868 return IPC_FAIL(this, "No principal");
5871 if (!ValidatePrincipal(aPrincipal
)) {
5872 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
5874 PushSubscriptionModifiedDispatcher
dispatcher(aScope
, aPrincipal
);
5875 Unused
<< NS_WARN_IF(NS_FAILED(dispatcher
.NotifyObservers()));
5880 void ContentParent::BroadcastBlobURLRegistration(const nsACString
& aURI
,
5881 BlobImpl
* aBlobImpl
,
5882 nsIPrincipal
* aPrincipal
,
5883 const nsCString
& aPartitionKey
,
5884 ContentParent
* aIgnoreThisCP
) {
5885 uint64_t originHash
= ComputeLoadedOriginHash(aPrincipal
);
5888 BlobURLProtocolHandler::IsBlobURLBroadcastPrincipal(aPrincipal
);
5890 nsCString
uri(aURI
);
5892 for (auto* cp
: AllProcesses(eLive
)) {
5893 if (cp
!= aIgnoreThisCP
) {
5894 if (!toBeSent
&& !cp
->mLoadedOriginHashes
.Contains(originHash
)) {
5898 nsresult rv
= cp
->TransmitPermissionsForPrincipal(aPrincipal
);
5899 if (NS_WARN_IF(NS_FAILED(rv
))) {
5904 rv
= IPCBlobUtils::Serialize(aBlobImpl
, ipcBlob
);
5905 if (NS_WARN_IF(NS_FAILED(rv
))) {
5909 Unused
<< cp
->SendBlobURLRegistration(uri
, ipcBlob
, aPrincipal
,
5916 void ContentParent::BroadcastBlobURLUnregistration(
5917 const nsACString
& aURI
, nsIPrincipal
* aPrincipal
,
5918 ContentParent
* aIgnoreThisCP
) {
5919 uint64_t originHash
= ComputeLoadedOriginHash(aPrincipal
);
5922 BlobURLProtocolHandler::IsBlobURLBroadcastPrincipal(aPrincipal
);
5924 nsCString
uri(aURI
);
5926 for (auto* cp
: AllProcesses(eLive
)) {
5927 if (cp
!= aIgnoreThisCP
&&
5928 (toBeSent
|| cp
->mLoadedOriginHashes
.Contains(originHash
))) {
5929 Unused
<< cp
->SendBlobURLUnregistration(uri
);
5934 mozilla::ipc::IPCResult
ContentParent::RecvStoreAndBroadcastBlobURLRegistration(
5935 const nsACString
& aURI
, const IPCBlob
& aBlob
, nsIPrincipal
* aPrincipal
,
5936 const nsCString
& aPartitionKey
) {
5938 return IPC_FAIL(this, "No principal");
5941 if (!ValidatePrincipal(aPrincipal
, {ValidatePrincipalOptions::AllowSystem
})) {
5942 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
5944 RefPtr
<BlobImpl
> blobImpl
= IPCBlobUtils::Deserialize(aBlob
);
5945 if (NS_WARN_IF(!blobImpl
)) {
5946 return IPC_FAIL(this, "Blob deserialization failed.");
5949 BlobURLProtocolHandler::AddDataEntry(aURI
, aPrincipal
, aPartitionKey
,
5951 BroadcastBlobURLRegistration(aURI
, blobImpl
, aPrincipal
, aPartitionKey
, this);
5953 // We want to store this blobURL, so we can unregister it if the child
5955 mBlobURLs
.AppendElement(aURI
);
5960 mozilla::ipc::IPCResult
5961 ContentParent::RecvUnstoreAndBroadcastBlobURLUnregistration(
5962 const nsACString
& aURI
, nsIPrincipal
* aPrincipal
) {
5964 return IPC_FAIL(this, "No principal");
5967 if (!ValidatePrincipal(aPrincipal
, {ValidatePrincipalOptions::AllowSystem
})) {
5968 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
5970 BlobURLProtocolHandler::RemoveDataEntry(aURI
, false /* Don't broadcast */);
5971 BroadcastBlobURLUnregistration(aURI
, aPrincipal
, this);
5972 mBlobURLs
.RemoveElement(aURI
);
5976 mozilla::ipc::IPCResult
ContentParent::RecvGetFilesRequest(
5977 const nsID
& aID
, const nsAString
& aDirectoryPath
,
5978 const bool& aRecursiveFlag
) {
5979 MOZ_ASSERT(!mGetFilesPendingRequests
.GetWeak(aID
));
5981 if (!mozilla::Preferences::GetBool("dom.filesystem.pathcheck.disabled",
5983 RefPtr
<FileSystemSecurity
> fss
= FileSystemSecurity::Get();
5985 return IPC_FAIL(this, "Failed to get FileSystemSecurity.");
5988 if (!fss
->ContentProcessHasAccessTo(ChildID(), aDirectoryPath
)) {
5989 return IPC_FAIL(this, "ContentProcessHasAccessTo failed.");
5994 RefPtr
<GetFilesHelper
> helper
= GetFilesHelperParent::Create(
5995 aID
, aDirectoryPath
, aRecursiveFlag
, this, rv
);
5997 if (NS_WARN_IF(rv
.Failed())) {
5998 if (!SendGetFilesResponse(aID
,
5999 GetFilesResponseFailure(rv
.StealNSResult()))) {
6000 return IPC_FAIL(this, "SendGetFilesResponse failed.");
6005 mGetFilesPendingRequests
.InsertOrUpdate(aID
, std::move(helper
));
6009 mozilla::ipc::IPCResult
ContentParent::RecvDeleteGetFilesRequest(
6011 mGetFilesPendingRequests
.Remove(aID
);
6015 void ContentParent::SendGetFilesResponseAndForget(
6016 const nsID
& aID
, const GetFilesResponseResult
& aResult
) {
6017 if (mGetFilesPendingRequests
.Remove(aID
)) {
6018 Unused
<< SendGetFilesResponse(aID
, aResult
);
6022 void ContentParent::PaintTabWhileInterruptingJS(BrowserParent
* aBrowserParent
) {
6023 if (!mHangMonitorActor
) {
6026 ProcessHangMonitor::PaintWhileInterruptingJS(mHangMonitorActor
,
6030 void ContentParent::UnloadLayersWhileInterruptingJS(
6031 BrowserParent
* aBrowserParent
) {
6032 if (!mHangMonitorActor
) {
6035 ProcessHangMonitor::UnloadLayersWhileInterruptingJS(mHangMonitorActor
,
6039 void ContentParent::CancelContentJSExecutionIfRunning(
6040 BrowserParent
* aBrowserParent
, nsIRemoteTab::NavigationType aNavigationType
,
6041 const CancelContentJSOptions
& aCancelContentJSOptions
) {
6042 if (!mHangMonitorActor
) {
6046 ProcessHangMonitor::CancelContentJSExecutionIfRunning(
6047 mHangMonitorActor
, aBrowserParent
, aNavigationType
,
6048 aCancelContentJSOptions
);
6051 void ContentParent::SetMainThreadQoSPriority(
6052 nsIThread::QoSPriority aQoSPriority
) {
6053 if (!mHangMonitorActor
) {
6057 ProcessHangMonitor::SetMainThreadQoSPriority(mHangMonitorActor
, aQoSPriority
);
6060 void ContentParent::UpdateCookieStatus(nsIChannel
* aChannel
) {
6061 PNeckoParent
* neckoParent
= LoneManagedOrNullAsserts(ManagedPNeckoParent());
6062 PCookieServiceParent
* csParent
=
6063 LoneManagedOrNullAsserts(neckoParent
->ManagedPCookieServiceParent());
6065 auto* cs
= static_cast<CookieServiceParent
*>(csParent
);
6066 cs
->TrackCookieLoad(aChannel
);
6070 nsresult
ContentParent::AboutToLoadHttpDocumentForChild(
6071 nsIChannel
* aChannel
, bool* aShouldWaitForPermissionCookieUpdate
) {
6072 MOZ_ASSERT(aChannel
);
6074 if (aShouldWaitForPermissionCookieUpdate
) {
6075 *aShouldWaitForPermissionCookieUpdate
= false;
6079 bool isDocument
= aChannel
->IsDocument();
6081 // We may be looking at a nsIHttpChannel which has isMainDocumentChannel set
6082 // (e.g. the internal http channel for a view-source: load.).
6083 nsCOMPtr
<nsIHttpChannel
> httpChannel
= do_QueryInterface(aChannel
);
6085 rv
= httpChannel
->GetIsMainDocumentChannel(&isDocument
);
6086 NS_ENSURE_SUCCESS(rv
, rv
);
6093 // Get the principal for the channel result, so that we can get the permission
6094 // key for the document which will be created from this response.
6095 nsIScriptSecurityManager
* ssm
= nsContentUtils::GetSecurityManager();
6096 if (NS_WARN_IF(!ssm
)) {
6097 return NS_ERROR_FAILURE
;
6100 nsCOMPtr
<nsIPrincipal
> principal
;
6101 nsCOMPtr
<nsIPrincipal
> partitionedPrincipal
;
6102 rv
= ssm
->GetChannelResultPrincipals(aChannel
, getter_AddRefs(principal
),
6103 getter_AddRefs(partitionedPrincipal
));
6104 NS_ENSURE_SUCCESS(rv
, rv
);
6106 // Let the caller know we're going to send main thread IPC for updating
6107 // permisssions/cookies.
6108 if (aShouldWaitForPermissionCookieUpdate
) {
6109 *aShouldWaitForPermissionCookieUpdate
= true;
6112 TransmitBlobURLsForPrincipal(principal
);
6114 // Tranmit permissions for both regular and partitioned principal so that the
6115 // content process can get permissions for the partitioned principal. For
6116 // example, the desk-notification permission for a partitioned service worker.
6117 rv
= TransmitPermissionsForPrincipal(principal
);
6118 NS_ENSURE_SUCCESS(rv
, rv
);
6120 rv
= TransmitPermissionsForPrincipal(partitionedPrincipal
);
6121 NS_ENSURE_SUCCESS(rv
, rv
);
6123 nsLoadFlags newLoadFlags
;
6124 aChannel
->GetLoadFlags(&newLoadFlags
);
6125 if (newLoadFlags
& nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE
) {
6126 UpdateCookieStatus(aChannel
);
6129 RefPtr
<nsILoadInfo
> loadInfo
= aChannel
->LoadInfo();
6130 RefPtr
<BrowsingContext
> browsingContext
;
6131 rv
= loadInfo
->GetTargetBrowsingContext(getter_AddRefs(browsingContext
));
6132 NS_ENSURE_SUCCESS(rv
, rv
);
6134 if (!NextGenLocalStorageEnabled()) {
6138 if (principal
->GetIsContentPrincipal()) {
6139 nsCOMPtr
<nsILocalStorageManager
> lsm
=
6140 do_GetService("@mozilla.org/dom/localStorage-manager;1");
6141 if (NS_WARN_IF(!lsm
)) {
6142 return NS_ERROR_FAILURE
;
6145 nsCOMPtr
<nsIPrincipal
> storagePrincipal
;
6146 rv
= ssm
->GetChannelResultStoragePrincipal(
6147 aChannel
, getter_AddRefs(storagePrincipal
));
6148 NS_ENSURE_SUCCESS(rv
, rv
);
6150 RefPtr
<Promise
> dummy
;
6151 rv
= lsm
->Preload(storagePrincipal
, nullptr, getter_AddRefs(dummy
));
6152 if (NS_FAILED(rv
)) {
6153 NS_WARNING("Failed to preload local storage!");
6160 nsresult
ContentParent::TransmitPermissionsForPrincipal(
6161 nsIPrincipal
* aPrincipal
) {
6162 // Create the key, and send it down to the content process.
6163 nsTArray
<std::pair
<nsCString
, nsCString
>> pairs
=
6164 PermissionManager::GetAllKeysForPrincipal(aPrincipal
);
6165 MOZ_ASSERT(pairs
.Length() >= 1);
6166 for (auto& pair
: pairs
) {
6167 EnsurePermissionsByKey(pair
.first
, pair
.second
);
6170 // We need to add the Site to the secondary keys of interest here.
6171 // This allows site-scoped permission updates to propogate when the
6172 // port is non-standard.
6173 nsAutoCString siteKey
;
6175 PermissionManager::GetKeyForPrincipal(aPrincipal
, false, true, siteKey
);
6176 if (NS_SUCCEEDED(rv
) && !siteKey
.IsEmpty()) {
6177 mActiveSecondaryPermissionKeys
.EnsureInserted(siteKey
);
6183 void ContentParent::TransmitBlobURLsForPrincipal(nsIPrincipal
* aPrincipal
) {
6184 // If we're already broadcasting BlobURLs with this principal, we don't need
6185 // to send them here.
6186 if (BlobURLProtocolHandler::IsBlobURLBroadcastPrincipal(aPrincipal
)) {
6190 // We shouldn't have any Blob URLs with expanded principals, so transmit URLs
6191 // for each principal in the AllowList instead.
6192 if (nsCOMPtr
<nsIExpandedPrincipal
> ep
= do_QueryInterface(aPrincipal
)) {
6193 for (const auto& prin
: ep
->AllowList()) {
6194 TransmitBlobURLsForPrincipal(prin
);
6199 uint64_t originHash
= ComputeLoadedOriginHash(aPrincipal
);
6201 if (!mLoadedOriginHashes
.Contains(originHash
)) {
6202 mLoadedOriginHashes
.AppendElement(originHash
);
6204 nsTArray
<BlobURLRegistrationData
> registrations
;
6205 BlobURLProtocolHandler::ForEachBlobURL(
6206 [&](BlobImpl
* aBlobImpl
, nsIPrincipal
* aBlobPrincipal
,
6207 const nsCString
& aPartitionKey
, const nsACString
& aURI
,
6209 // This check uses `ComputeLoadedOriginHash` to compare, rather than
6210 // doing the more accurate `Equals` check, as it needs to match the
6211 // behaviour of the logic to broadcast new registrations.
6212 if (originHash
!= ComputeLoadedOriginHash(aBlobPrincipal
)) {
6217 nsresult rv
= IPCBlobUtils::Serialize(aBlobImpl
, ipcBlob
);
6218 if (NS_WARN_IF(NS_FAILED(rv
))) {
6222 registrations
.AppendElement(
6223 BlobURLRegistrationData(nsCString(aURI
), ipcBlob
, aPrincipal
,
6224 nsCString(aPartitionKey
), aRevoked
));
6226 rv
= TransmitPermissionsForPrincipal(aBlobPrincipal
);
6227 Unused
<< NS_WARN_IF(NS_FAILED(rv
));
6231 if (!registrations
.IsEmpty()) {
6232 Unused
<< SendInitBlobURLs(registrations
);
6237 void ContentParent::TransmitBlobDataIfBlobURL(nsIURI
* aURI
) {
6240 nsCOMPtr
<nsIPrincipal
> principal
;
6241 if (BlobURLProtocolHandler::GetBlobURLPrincipal(aURI
,
6242 getter_AddRefs(principal
))) {
6243 TransmitBlobURLsForPrincipal(principal
);
6247 void ContentParent::EnsurePermissionsByKey(const nsACString
& aKey
,
6248 const nsACString
& aOrigin
) {
6249 // NOTE: Make sure to initialize the permission manager before updating the
6250 // mActivePermissionKeys list. If the permission manager is being initialized
6251 // by this call to GetPermissionManager, and we've added the key to
6252 // mActivePermissionKeys, then the permission manager will send down a
6253 // SendAddPermission before receiving the SendSetPermissionsWithKey message.
6254 RefPtr
<PermissionManager
> permManager
= PermissionManager::GetInstance();
6259 if (!mActivePermissionKeys
.EnsureInserted(aKey
)) {
6263 nsTArray
<IPC::Permission
> perms
;
6264 if (permManager
->GetPermissionsFromOriginOrKey(aOrigin
, aKey
, perms
)) {
6265 Unused
<< SendSetPermissionsWithKey(aKey
, perms
);
6269 bool ContentParent::NeedsPermissionsUpdate(
6270 const nsACString
& aPermissionKey
) const {
6271 return mActivePermissionKeys
.Contains(aPermissionKey
);
6274 bool ContentParent::NeedsSecondaryKeyPermissionsUpdate(
6275 const nsACString
& aPermissionKey
) const {
6276 return mActiveSecondaryPermissionKeys
.Contains(aPermissionKey
);
6279 mozilla::ipc::IPCResult
ContentParent::RecvAccumulateChildHistograms(
6280 nsTArray
<HistogramAccumulation
>&& aAccumulations
) {
6281 TelemetryIPC::AccumulateChildHistograms(GetTelemetryProcessID(mRemoteType
),
6286 mozilla::ipc::IPCResult
ContentParent::RecvAccumulateChildKeyedHistograms(
6287 nsTArray
<KeyedHistogramAccumulation
>&& aAccumulations
) {
6288 TelemetryIPC::AccumulateChildKeyedHistograms(
6289 GetTelemetryProcessID(mRemoteType
), aAccumulations
);
6293 mozilla::ipc::IPCResult
ContentParent::RecvUpdateChildScalars(
6294 nsTArray
<ScalarAction
>&& aScalarActions
) {
6295 TelemetryIPC::UpdateChildScalars(GetTelemetryProcessID(mRemoteType
),
6300 mozilla::ipc::IPCResult
ContentParent::RecvUpdateChildKeyedScalars(
6301 nsTArray
<KeyedScalarAction
>&& aScalarActions
) {
6302 TelemetryIPC::UpdateChildKeyedScalars(GetTelemetryProcessID(mRemoteType
),
6307 mozilla::ipc::IPCResult
ContentParent::RecvRecordChildEvents(
6308 nsTArray
<mozilla::Telemetry::ChildEventData
>&& aEvents
) {
6309 TelemetryIPC::RecordChildEvents(GetTelemetryProcessID(mRemoteType
), aEvents
);
6313 mozilla::ipc::IPCResult
ContentParent::RecvRecordDiscardedData(
6314 const mozilla::Telemetry::DiscardedData
& aDiscardedData
) {
6315 TelemetryIPC::RecordDiscardedData(GetTelemetryProcessID(mRemoteType
),
6320 static bool WebdriverRunning() {
6321 #ifdef ENABLE_WEBDRIVER
6322 nsCOMPtr
<nsIMarionette
> marionette
= do_GetService(NS_MARIONETTE_CONTRACTID
);
6324 bool marionetteRunning
= false;
6325 marionette
->GetRunning(&marionetteRunning
);
6326 if (marionetteRunning
) {
6331 nsCOMPtr
<nsIRemoteAgent
> agent
= do_GetService(NS_REMOTEAGENT_CONTRACTID
);
6333 bool remoteAgentRunning
= false;
6334 agent
->GetRunning(&remoteAgentRunning
);
6335 if (remoteAgentRunning
) {
6344 mozilla::ipc::IPCResult
ContentParent::RecvRecordPageLoadEvent(
6345 mozilla::glean::perf::PageLoadExtra
&& aPageLoadEventExtra
) {
6346 // Check whether a webdriver is running.
6347 aPageLoadEventExtra
.usingWebdriver
= mozilla::Some(WebdriverRunning());
6348 mozilla::glean::perf::page_load
.Record(mozilla::Some(aPageLoadEventExtra
));
6350 // Send the PageLoadPing after every 30 page loads, or on startup.
6351 if (++sPageLoadEventCounter
>= 30) {
6352 NS_SUCCEEDED(NS_DispatchToMainThreadQueue(
6353 NS_NewRunnableFunction(
6354 "PageLoadPingIdleTask",
6355 [] { mozilla::glean_pings::Pageload
.Submit("threshold"_ns
); }),
6356 EventQueuePriority::Idle
));
6357 sPageLoadEventCounter
= 0;
6363 //////////////////////////////////////////////////////////////////
6364 // PURLClassifierParent
6366 PURLClassifierParent
* ContentParent::AllocPURLClassifierParent(
6367 nsIPrincipal
* aPrincipal
, bool* aSuccess
) {
6368 MOZ_ASSERT(NS_IsMainThread());
6371 RefPtr
<URLClassifierParent
> actor
= new URLClassifierParent();
6372 return actor
.forget().take();
6375 mozilla::ipc::IPCResult
ContentParent::RecvPURLClassifierConstructor(
6376 PURLClassifierParent
* aActor
, nsIPrincipal
* aPrincipal
, bool* aSuccess
) {
6377 MOZ_ASSERT(NS_IsMainThread());
6381 auto* actor
= static_cast<URLClassifierParent
*>(aActor
);
6382 nsCOMPtr
<nsIPrincipal
> principal(aPrincipal
);
6384 actor
->ClassificationFailed();
6387 if (!ValidatePrincipal(aPrincipal
)) {
6388 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
6390 return actor
->StartClassify(principal
, aSuccess
);
6393 bool ContentParent::DeallocPURLClassifierParent(PURLClassifierParent
* aActor
) {
6394 MOZ_ASSERT(NS_IsMainThread());
6397 RefPtr
<URLClassifierParent
> actor
=
6398 dont_AddRef(static_cast<URLClassifierParent
*>(aActor
));
6402 //////////////////////////////////////////////////////////////////
6403 // PURLClassifierLocalParent
6405 PURLClassifierLocalParent
* ContentParent::AllocPURLClassifierLocalParent(
6406 nsIURI
* aURI
, const nsTArray
<IPCURLClassifierFeature
>& aFeatures
) {
6407 MOZ_ASSERT(NS_IsMainThread());
6409 RefPtr
<URLClassifierLocalParent
> actor
= new URLClassifierLocalParent();
6410 return actor
.forget().take();
6413 mozilla::ipc::IPCResult
ContentParent::RecvPURLClassifierLocalConstructor(
6414 PURLClassifierLocalParent
* aActor
, nsIURI
* aURI
,
6415 nsTArray
<IPCURLClassifierFeature
>&& aFeatures
) {
6416 MOZ_ASSERT(NS_IsMainThread());
6419 nsTArray
<IPCURLClassifierFeature
> features
= std::move(aFeatures
);
6422 return IPC_FAIL(this, "aURI should not be null");
6425 auto* actor
= static_cast<URLClassifierLocalParent
*>(aActor
);
6426 return actor
->StartClassify(aURI
, features
);
6429 bool ContentParent::DeallocPURLClassifierLocalParent(
6430 PURLClassifierLocalParent
* aActor
) {
6431 MOZ_ASSERT(NS_IsMainThread());
6434 RefPtr
<URLClassifierLocalParent
> actor
=
6435 dont_AddRef(static_cast<URLClassifierLocalParent
*>(aActor
));
6439 PSessionStorageObserverParent
*
6440 ContentParent::AllocPSessionStorageObserverParent() {
6441 MOZ_ASSERT(NS_IsMainThread());
6443 return mozilla::dom::AllocPSessionStorageObserverParent();
6446 mozilla::ipc::IPCResult
ContentParent::RecvPSessionStorageObserverConstructor(
6447 PSessionStorageObserverParent
* aActor
) {
6448 MOZ_ASSERT(NS_IsMainThread());
6451 if (!mozilla::dom::RecvPSessionStorageObserverConstructor(aActor
)) {
6452 return IPC_FAIL(this, "RecvPSessionStorageObserverConstructor failed.");
6457 bool ContentParent::DeallocPSessionStorageObserverParent(
6458 PSessionStorageObserverParent
* aActor
) {
6459 MOZ_ASSERT(NS_IsMainThread());
6462 return mozilla::dom::DeallocPSessionStorageObserverParent(aActor
);
6465 mozilla::ipc::IPCResult
ContentParent::RecvBHRThreadHang(
6466 const HangDetails
& aHangDetails
) {
6467 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
6469 // Copy the HangDetails recieved over the network into a nsIHangDetails, and
6470 // then fire our own observer notification.
6471 // XXX: We should be able to avoid this potentially expensive copy here by
6472 // moving our deserialized argument.
6473 nsCOMPtr
<nsIHangDetails
> hangDetails
=
6474 new nsHangDetails(HangDetails(aHangDetails
), PersistedToDisk::No
);
6475 obs
->NotifyObservers(hangDetails
, "bhr-thread-hang", nullptr);
6480 mozilla::ipc::IPCResult
ContentParent::RecvAddCertException(
6481 nsIX509Cert
* aCert
, const nsACString
& aHostName
, int32_t aPort
,
6482 const OriginAttributes
& aOriginAttributes
, bool aIsTemporary
,
6483 AddCertExceptionResolver
&& aResolver
) {
6484 nsCOMPtr
<nsICertOverrideService
> overrideService
=
6485 do_GetService(NS_CERTOVERRIDE_CONTRACTID
);
6486 if (!overrideService
) {
6487 aResolver(NS_ERROR_FAILURE
);
6490 nsresult rv
= overrideService
->RememberValidityOverride(
6491 aHostName
, aPort
, aOriginAttributes
, aCert
, aIsTemporary
);
6496 mozilla::ipc::IPCResult
6497 ContentParent::RecvAutomaticStorageAccessPermissionCanBeGranted(
6498 nsIPrincipal
* aPrincipal
,
6499 AutomaticStorageAccessPermissionCanBeGrantedResolver
&& aResolver
) {
6501 return IPC_FAIL(this, "No principal");
6504 if (!ValidatePrincipal(aPrincipal
)) {
6505 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
6507 aResolver(Document::AutomaticStorageAccessPermissionCanBeGranted(aPrincipal
));
6511 mozilla::ipc::IPCResult
6512 ContentParent::RecvStorageAccessPermissionGrantedForOrigin(
6513 uint64_t aTopLevelWindowId
,
6514 const MaybeDiscarded
<BrowsingContext
>& aParentContext
,
6515 nsIPrincipal
* aTrackingPrincipal
, const nsACString
& aTrackingOrigin
,
6516 const int& aAllowMode
,
6517 const Maybe
<ContentBlockingNotifier::StorageAccessPermissionGrantedReason
>&
6519 const bool& aFrameOnly
,
6520 StorageAccessPermissionGrantedForOriginResolver
&& aResolver
) {
6521 if (aParentContext
.IsNullOrDiscarded()) {
6525 if (!aTrackingPrincipal
) {
6526 return IPC_FAIL(this, "No principal");
6529 // We only report here if we cannot report the console directly in the content
6530 // process. In that case, the `aReason` would be given a value. Otherwise, it
6533 ContentBlockingNotifier::ReportUnblockingToConsole(
6534 aParentContext
.get_canonical(), NS_ConvertUTF8toUTF16(aTrackingOrigin
),
6538 StorageAccessAPIHelper::SaveAccessForOriginOnParentProcess(
6539 aTopLevelWindowId
, aParentContext
.get_canonical(), aTrackingPrincipal
,
6540 aAllowMode
, aFrameOnly
)
6541 ->Then(GetCurrentSerialEventTarget(), __func__
,
6542 [aResolver
= std::move(aResolver
)](
6543 StorageAccessAPIHelper::ParentAccessGrantPromise::
6544 ResolveOrRejectValue
&& aValue
) {
6546 aValue
.IsResolve() && NS_SUCCEEDED(aValue
.ResolveValue());
6552 mozilla::ipc::IPCResult
ContentParent::RecvCompleteAllowAccessFor(
6553 const MaybeDiscarded
<BrowsingContext
>& aParentContext
,
6554 uint64_t aTopLevelWindowId
, nsIPrincipal
* aTrackingPrincipal
,
6555 const nsACString
& aTrackingOrigin
, uint32_t aCookieBehavior
,
6556 const ContentBlockingNotifier::StorageAccessPermissionGrantedReason
&
6558 CompleteAllowAccessForResolver
&& aResolver
) {
6559 if (aParentContext
.IsNullOrDiscarded()) {
6563 StorageAccessAPIHelper::CompleteAllowAccessForOnParentProcess(
6564 aParentContext
.get_canonical(), aTopLevelWindowId
, aTrackingPrincipal
,
6565 aTrackingOrigin
, aCookieBehavior
, aReason
, nullptr)
6566 ->Then(GetCurrentSerialEventTarget(), __func__
,
6567 [aResolver
= std::move(aResolver
)](
6568 StorageAccessAPIHelper::StorageAccessPermissionGrantPromise::
6569 ResolveOrRejectValue
&& aValue
) {
6570 Maybe
<StorageAccessPromptChoices
> choice
;
6571 if (aValue
.IsResolve()) {
6572 choice
.emplace(static_cast<StorageAccessPromptChoices
>(
6573 aValue
.ResolveValue()));
6580 mozilla::ipc::IPCResult
ContentParent::RecvSetAllowStorageAccessRequestFlag(
6581 nsIPrincipal
* aEmbeddedPrincipal
, nsIURI
* aEmbeddingOrigin
,
6582 SetAllowStorageAccessRequestFlagResolver
&& aResolver
) {
6583 MOZ_ASSERT(aEmbeddedPrincipal
);
6584 MOZ_ASSERT(aEmbeddingOrigin
);
6586 if (!aEmbeddedPrincipal
|| !aEmbeddingOrigin
) {
6591 // Get the permission manager and build the key.
6592 RefPtr
<PermissionManager
> permManager
= PermissionManager::GetInstance();
6597 nsCOMPtr
<nsIURI
> embeddedURI
= aEmbeddedPrincipal
->GetURI();
6598 nsCString permissionKey
;
6599 bool success
= AntiTrackingUtils::CreateStorageRequestPermissionKey(
6600 embeddedURI
, permissionKey
);
6606 // Set the permission to ALLOW for a prefence specified amount of seconds.
6607 // Time units are inconsistent, be careful
6608 int64_t when
= (PR_Now() / PR_USEC_PER_MSEC
) +
6609 StaticPrefs::dom_storage_access_forward_declared_lifetime() *
6611 nsCOMPtr
<nsIPrincipal
> principal
= BasePrincipal::CreateContentPrincipal(
6612 aEmbeddingOrigin
, aEmbeddedPrincipal
->OriginAttributesRef());
6613 nsresult rv
= permManager
->AddFromPrincipal(
6614 principal
, permissionKey
, nsIPermissionManager::ALLOW_ACTION
,
6615 nsIPermissionManager::EXPIRE_TIME
, when
);
6616 if (NS_FAILED(rv
)) {
6621 // Resolve with success if we set the permission.
6626 mozilla::ipc::IPCResult
ContentParent::RecvTestAllowStorageAccessRequestFlag(
6627 nsIPrincipal
* aEmbeddingPrincipal
, nsIURI
* aEmbeddedOrigin
,
6628 TestAllowStorageAccessRequestFlagResolver
&& aResolver
) {
6629 MOZ_ASSERT(aEmbeddingPrincipal
);
6630 MOZ_ASSERT(aEmbeddedOrigin
);
6632 // Get the permission manager and build the key.
6633 RefPtr
<PermissionManager
> permManager
= PermissionManager::GetInstance();
6638 nsCString requestPermissionKey
;
6639 bool success
= AntiTrackingUtils::CreateStorageRequestPermissionKey(
6640 aEmbeddedOrigin
, requestPermissionKey
);
6646 // Get the permission and resolve false if it is not set to ALLOW.
6647 uint32_t access
= nsIPermissionManager::UNKNOWN_ACTION
;
6648 nsresult rv
= permManager
->TestPermissionFromPrincipal(
6649 aEmbeddingPrincipal
, requestPermissionKey
, &access
);
6650 if (NS_FAILED(rv
)) {
6654 if (access
!= nsIPermissionManager::ALLOW_ACTION
) {
6659 // Remove the permission, failing if the permission manager fails
6660 rv
= permManager
->RemoveFromPrincipal(aEmbeddingPrincipal
,
6661 requestPermissionKey
);
6662 if (NS_FAILED(rv
)) {
6667 // At this point, signal to our caller that the permission was set
6672 mozilla::ipc::IPCResult
ContentParent::RecvStoreUserInteractionAsPermission(
6673 nsIPrincipal
* aPrincipal
) {
6675 return IPC_FAIL(this, "No principal");
6678 if (!ValidatePrincipal(aPrincipal
)) {
6679 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
6681 ContentBlockingUserInteraction::Observe(aPrincipal
);
6685 mozilla::ipc::IPCResult
ContentParent::RecvTestCookiePermissionDecided(
6686 const MaybeDiscarded
<BrowsingContext
>& aContext
, nsIPrincipal
* aPrincipal
,
6687 const TestCookiePermissionDecidedResolver
&& aResolver
) {
6688 if (aContext
.IsNullOrDiscarded()) {
6693 return IPC_FAIL(this, "No principal");
6696 RefPtr
<WindowGlobalParent
> wgp
=
6697 aContext
.get_canonical()->GetCurrentWindowGlobal();
6698 nsCOMPtr
<nsICookieJarSettings
> cjs
= wgp
->CookieJarSettings();
6700 Maybe
<bool> result
=
6701 StorageAccessAPIHelper::CheckCookiesPermittedDecidesStorageAccessAPI(
6707 mozilla::ipc::IPCResult
ContentParent::RecvTestStorageAccessPermission(
6708 nsIPrincipal
* aEmbeddingPrincipal
, const nsCString
& aEmbeddedOrigin
,
6709 const TestStorageAccessPermissionResolver
&& aResolver
) {
6710 // Get the permission manager and build the key.
6711 RefPtr
<PermissionManager
> permManager
= PermissionManager::GetInstance();
6713 aResolver(Nothing());
6716 nsCString requestPermissionKey
;
6717 AntiTrackingUtils::CreateStoragePermissionKey(aEmbeddedOrigin
,
6718 requestPermissionKey
);
6720 // Test the permission
6721 uint32_t access
= nsIPermissionManager::UNKNOWN_ACTION
;
6722 nsresult rv
= permManager
->TestPermissionFromPrincipal(
6723 aEmbeddingPrincipal
, requestPermissionKey
, &access
);
6724 if (NS_FAILED(rv
)) {
6725 aResolver(Nothing());
6728 if (access
== nsIPermissionManager::ALLOW_ACTION
) {
6729 aResolver(Some(true));
6730 } else if (access
== nsIPermissionManager::DENY_ACTION
) {
6731 aResolver(Some(false));
6733 aResolver(Nothing());
6739 mozilla::ipc::IPCResult
ContentParent::RecvNotifyMediaPlaybackChanged(
6740 const MaybeDiscarded
<BrowsingContext
>& aContext
,
6741 MediaPlaybackState aState
) {
6742 if (aContext
.IsNullOrDiscarded()) {
6745 if (RefPtr
<IMediaInfoUpdater
> updater
=
6746 aContext
.get_canonical()->GetMediaController()) {
6747 updater
->NotifyMediaPlaybackChanged(aContext
.ContextId(), aState
);
6752 mozilla::ipc::IPCResult
ContentParent::RecvNotifyMediaAudibleChanged(
6753 const MaybeDiscarded
<BrowsingContext
>& aContext
, MediaAudibleState aState
) {
6754 if (aContext
.IsNullOrDiscarded()) {
6757 if (RefPtr
<IMediaInfoUpdater
> updater
=
6758 aContext
.get_canonical()->GetMediaController()) {
6759 updater
->NotifyMediaAudibleChanged(aContext
.ContextId(), aState
);
6764 mozilla::ipc::IPCResult
ContentParent::RecvNotifyPictureInPictureModeChanged(
6765 const MaybeDiscarded
<BrowsingContext
>& aContext
, bool aEnabled
) {
6766 if (aContext
.IsNullOrDiscarded()) {
6769 if (RefPtr
<MediaController
> controller
=
6770 aContext
.get_canonical()->GetMediaController()) {
6771 controller
->SetIsInPictureInPictureMode(aContext
.ContextId(), aEnabled
);
6776 mozilla::ipc::IPCResult
ContentParent::RecvAbortOtherOrientationPendingPromises(
6777 const MaybeDiscarded
<BrowsingContext
>& aContext
) {
6778 if (aContext
.IsNullOrDiscarded()) {
6782 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
6784 context
->Group()->EachOtherParent(this, [&](ContentParent
* aParent
) {
6785 Unused
<< aParent
->SendAbortOrientationPendingPromises(context
);
6791 mozilla::ipc::IPCResult
ContentParent::RecvNotifyMediaSessionUpdated(
6792 const MaybeDiscarded
<BrowsingContext
>& aContext
, bool aIsCreated
) {
6793 if (aContext
.IsNullOrDiscarded()) {
6797 RefPtr
<IMediaInfoUpdater
> updater
=
6798 aContext
.get_canonical()->GetMediaController();
6803 updater
->NotifySessionCreated(aContext
->Id());
6805 updater
->NotifySessionDestroyed(aContext
->Id());
6810 mozilla::ipc::IPCResult
ContentParent::RecvNotifyUpdateMediaMetadata(
6811 const MaybeDiscarded
<BrowsingContext
>& aContext
,
6812 const Maybe
<MediaMetadataBase
>& aMetadata
) {
6813 if (aContext
.IsNullOrDiscarded()) {
6816 if (RefPtr
<IMediaInfoUpdater
> updater
=
6817 aContext
.get_canonical()->GetMediaController()) {
6818 updater
->UpdateMetadata(aContext
.ContextId(), aMetadata
);
6823 mozilla::ipc::IPCResult
6824 ContentParent::RecvNotifyMediaSessionPlaybackStateChanged(
6825 const MaybeDiscarded
<BrowsingContext
>& aContext
,
6826 MediaSessionPlaybackState aPlaybackState
) {
6827 if (aContext
.IsNullOrDiscarded()) {
6830 if (RefPtr
<IMediaInfoUpdater
> updater
=
6831 aContext
.get_canonical()->GetMediaController()) {
6832 updater
->SetDeclaredPlaybackState(aContext
.ContextId(), aPlaybackState
);
6837 mozilla::ipc::IPCResult
6838 ContentParent::RecvNotifyMediaSessionSupportedActionChanged(
6839 const MaybeDiscarded
<BrowsingContext
>& aContext
, MediaSessionAction aAction
,
6841 if (aContext
.IsNullOrDiscarded()) {
6844 RefPtr
<IMediaInfoUpdater
> updater
=
6845 aContext
.get_canonical()->GetMediaController();
6850 updater
->EnableAction(aContext
.ContextId(), aAction
);
6852 updater
->DisableAction(aContext
.ContextId(), aAction
);
6857 mozilla::ipc::IPCResult
ContentParent::RecvNotifyMediaFullScreenState(
6858 const MaybeDiscarded
<BrowsingContext
>& aContext
, bool aIsInFullScreen
) {
6859 if (aContext
.IsNullOrDiscarded()) {
6862 if (RefPtr
<IMediaInfoUpdater
> updater
=
6863 aContext
.get_canonical()->GetMediaController()) {
6864 updater
->NotifyMediaFullScreenState(aContext
.ContextId(), aIsInFullScreen
);
6869 mozilla::ipc::IPCResult
ContentParent::RecvNotifyPositionStateChanged(
6870 const MaybeDiscarded
<BrowsingContext
>& aContext
,
6871 const Maybe
<PositionState
>& aState
) {
6872 if (aContext
.IsNullOrDiscarded()) {
6875 if (RefPtr
<IMediaInfoUpdater
> updater
=
6876 aContext
.get_canonical()->GetMediaController()) {
6877 updater
->UpdatePositionState(aContext
.ContextId(), aState
);
6882 mozilla::ipc::IPCResult
ContentParent::RecvNotifyGuessedPositionStateChanged(
6883 const MaybeDiscarded
<BrowsingContext
>& aContext
, const nsID
& aMediaId
,
6884 const Maybe
<PositionState
>& aState
) {
6885 if (aContext
.IsNullOrDiscarded()) {
6888 if (RefPtr
<IMediaInfoUpdater
> updater
=
6889 aContext
.get_canonical()->GetMediaController()) {
6890 updater
->UpdateGuessedPositionState(aContext
.ContextId(), aMediaId
, aState
);
6895 mozilla::ipc::IPCResult
ContentParent::RecvAddOrRemovePageAwakeRequest(
6896 const MaybeDiscarded
<BrowsingContext
>& aContext
,
6897 const bool& aShouldAddCount
) {
6898 if (aContext
.IsNullOrDiscarded()) {
6901 if (aShouldAddCount
) {
6902 aContext
.get_canonical()->AddPageAwakeRequest();
6904 aContext
.get_canonical()->RemovePageAwakeRequest();
6910 mozilla::ipc::IPCResult
ContentParent::RecvGetModulesTrust(
6911 ModulePaths
&& aModPaths
, bool aRunAtNormalPriority
,
6912 GetModulesTrustResolver
&& aResolver
) {
6913 RefPtr
<DllServices
> dllSvc(DllServices::Get());
6914 dllSvc
->GetModulesTrust(std::move(aModPaths
), aRunAtNormalPriority
)
6916 GetMainThreadSerialEventTarget(), __func__
,
6917 [aResolver
](ModulesMapResult
&& aResult
) {
6918 aResolver(Some(ModulesMapResult(std::move(aResult
))));
6920 [aResolver
](nsresult aRv
) { aResolver(Nothing()); });
6923 #endif // defined(XP_WIN)
6925 mozilla::ipc::IPCResult
ContentParent::RecvCreateBrowsingContext(
6926 uint64_t aGroupId
, BrowsingContext::IPCInitializer
&& aInit
) {
6927 RefPtr
<WindowGlobalParent
> parent
;
6928 if (aInit
.mParentId
!= 0) {
6929 parent
= WindowGlobalParent::GetByInnerWindowId(aInit
.mParentId
);
6931 return IPC_FAIL(this, "Parent doesn't exist in parent process");
6935 if (parent
&& parent
->GetContentParent() != this) {
6936 // We're trying attach a child BrowsingContext to a parent
6937 // WindowContext in another process. This is illegal since the
6938 // only thing that could create that child BrowsingContext is the parent
6939 // window's process.
6940 return IPC_FAIL(this,
6941 "Must create BrowsingContext from the parent's process");
6944 RefPtr
<BrowsingContext
> opener
;
6945 if (aInit
.GetOpenerId() != 0) {
6946 opener
= BrowsingContext::Get(aInit
.GetOpenerId());
6948 return IPC_FAIL(this, "Opener doesn't exist in parent process");
6952 RefPtr
<BrowsingContext
> child
= BrowsingContext::Get(aInit
.mId
);
6954 // This is highly suspicious. BrowsingContexts should only be created once,
6955 // so finding one indicates that someone is doing something they shouldn't.
6956 return IPC_FAIL(this, "A BrowsingContext with this ID already exists");
6959 // Ensure that the passed-in BrowsingContextGroup is valid.
6960 RefPtr
<BrowsingContextGroup
> group
=
6961 BrowsingContextGroup::GetOrCreate(aGroupId
);
6963 if (parent
->Group()->Id() != aGroupId
) {
6964 return IPC_FAIL(this, "Parent has different group ID");
6966 if (parent
->IsDiscarded()) {
6967 return IPC_FAIL(this, "Parent is discarded");
6969 if (parent
->Group() != group
) {
6970 return IPC_FAIL(this, "Parent has different group object");
6973 if (opener
&& opener
->Group() != group
) {
6974 if (opener
->Group()->Id() != aGroupId
) {
6975 return IPC_FAIL(this, "Opener has different group ID");
6977 return IPC_FAIL(this, "Opener has different group object");
6979 if (!parent
&& !opener
&& !group
->Toplevels().IsEmpty()) {
6980 return IPC_FAIL(this, "Unrelated context from child in stale group");
6983 return BrowsingContext::CreateFromIPC(std::move(aInit
), group
, this);
6986 bool ContentParent::CheckBrowsingContextEmbedder(CanonicalBrowsingContext
* aBC
,
6987 const char* aOperation
) const {
6988 if (!aBC
->IsEmbeddedInProcess(ChildID())) {
6989 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Warning
,
6990 ("ParentIPC: Trying to %s out of process context 0x%08" PRIx64
,
6991 aOperation
, aBC
->Id()));
6997 mozilla::ipc::IPCResult
ContentParent::RecvDiscardBrowsingContext(
6998 const MaybeDiscarded
<BrowsingContext
>& aContext
, bool aDoDiscard
,
6999 DiscardBrowsingContextResolver
&& aResolve
) {
7000 if (CanonicalBrowsingContext
* context
=
7001 CanonicalBrowsingContext::Cast(aContext
.GetMaybeDiscarded())) {
7002 if (aDoDiscard
&& !context
->IsDiscarded()) {
7003 if (!CheckBrowsingContextEmbedder(context
, "discard")) {
7004 return IPC_FAIL(this, "Illegal Discard attempt");
7007 context
->Detach(/* aFromIPC */ true);
7009 context
->AddFinalDiscardListener(aResolve
);
7013 // Resolve the promise, as we've received and handled the message. This will
7014 // allow the content process to fully-discard references to this BC.
7019 mozilla::ipc::IPCResult
ContentParent::RecvWindowClose(
7020 const MaybeDiscarded
<BrowsingContext
>& aContext
, bool aTrustedCaller
) {
7021 if (aContext
.IsNullOrDiscarded()) {
7023 BrowsingContext::GetLog(), LogLevel::Debug
,
7024 ("ParentIPC: Trying to send a message to dead or detached context"));
7027 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7029 // FIXME Need to check that the sending process has access to the unit of
7031 // browsing contexts of bc.
7033 if (ContentParent
* cp
= context
->GetContentParent()) {
7034 Unused
<< cp
->SendWindowClose(context
, aTrustedCaller
);
7039 mozilla::ipc::IPCResult
ContentParent::RecvWindowFocus(
7040 const MaybeDiscarded
<BrowsingContext
>& aContext
, CallerType aCallerType
,
7041 uint64_t aActionId
) {
7042 if (aContext
.IsNullOrDiscarded()) {
7044 BrowsingContext::GetLog(), LogLevel::Debug
,
7045 ("ParentIPC: Trying to send a message to dead or detached context"));
7048 LOGFOCUS(("ContentParent::RecvWindowFocus actionid: %" PRIu64
, aActionId
));
7049 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7051 if (ContentParent
* cp
= context
->GetContentParent()) {
7052 Unused
<< cp
->SendWindowFocus(context
, aCallerType
, aActionId
);
7057 mozilla::ipc::IPCResult
ContentParent::RecvWindowBlur(
7058 const MaybeDiscarded
<BrowsingContext
>& aContext
, CallerType aCallerType
) {
7059 if (aContext
.IsNullOrDiscarded()) {
7061 BrowsingContext::GetLog(), LogLevel::Debug
,
7062 ("ParentIPC: Trying to send a message to dead or detached context"));
7065 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7067 if (ContentParent
* cp
= context
->GetContentParent()) {
7068 Unused
<< cp
->SendWindowBlur(context
, aCallerType
);
7073 mozilla::ipc::IPCResult
ContentParent::RecvRaiseWindow(
7074 const MaybeDiscarded
<BrowsingContext
>& aContext
, CallerType aCallerType
,
7075 uint64_t aActionId
) {
7076 if (aContext
.IsNullOrDiscarded()) {
7078 BrowsingContext::GetLog(), LogLevel::Debug
,
7079 ("ParentIPC: Trying to send a message to dead or detached context"));
7082 LOGFOCUS(("ContentParent::RecvRaiseWindow actionid: %" PRIu64
, aActionId
));
7084 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7086 if (ContentParent
* cp
= context
->GetContentParent()) {
7087 Unused
<< cp
->SendRaiseWindow(context
, aCallerType
, aActionId
);
7092 mozilla::ipc::IPCResult
ContentParent::RecvAdjustWindowFocus(
7093 const MaybeDiscarded
<BrowsingContext
>& aContext
, bool aIsVisible
,
7094 uint64_t aActionId
, bool aShouldClearFocus
,
7095 const MaybeDiscarded
<BrowsingContext
>& aAncestorBrowsingContextToFocus
) {
7096 if (aContext
.IsNullOrDiscarded()) {
7098 BrowsingContext::GetLog(), LogLevel::Debug
,
7099 ("ParentIPC: Trying to send a message to dead or detached context"));
7103 ("ContentParent::RecvAdjustWindowFocus isVisible %d actionid: %" PRIu64
,
7104 aIsVisible
, aActionId
));
7106 nsTHashMap
<nsPtrHashKey
<ContentParent
>, bool> processes(2);
7107 processes
.InsertOrUpdate(this, true);
7109 ContentProcessManager
* cpm
= ContentProcessManager::GetSingleton();
7111 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7113 BrowsingContext
* parent
= context
->GetParent();
7118 CanonicalBrowsingContext
* canonicalParent
= parent
->Canonical();
7119 ContentParent
* cp
= cpm
->GetContentProcessById(
7120 ContentParentId(canonicalParent
->OwnerProcessId()));
7121 if (cp
&& !processes
.Get(cp
)) {
7122 Unused
<< cp
->SendAdjustWindowFocus(context
, aIsVisible
, aActionId
,
7124 aAncestorBrowsingContextToFocus
);
7125 processes
.InsertOrUpdate(cp
, true);
7127 context
= canonicalParent
;
7133 mozilla::ipc::IPCResult
ContentParent::RecvClearFocus(
7134 const MaybeDiscarded
<BrowsingContext
>& aContext
) {
7135 if (aContext
.IsNullOrDiscarded()) {
7137 BrowsingContext::GetLog(), LogLevel::Debug
,
7138 ("ParentIPC: Trying to send a message to dead or detached context"));
7141 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7143 if (ContentParent
* cp
= context
->GetContentParent()) {
7144 Unused
<< cp
->SendClearFocus(context
);
7149 mozilla::ipc::IPCResult
ContentParent::RecvSetFocusedBrowsingContext(
7150 const MaybeDiscarded
<BrowsingContext
>& aContext
, uint64_t aActionId
) {
7151 if (aContext
.IsNullOrDiscarded()) {
7153 BrowsingContext::GetLog(), LogLevel::Debug
,
7154 ("ParentIPC: Trying to send a message to dead or detached context"));
7157 LOGFOCUS(("ContentParent::RecvSetFocusedBrowsingContext actionid: %" PRIu64
,
7159 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7161 nsFocusManager
* fm
= nsFocusManager::GetFocusManager();
7166 if (!fm
->SetFocusedBrowsingContextInChrome(context
, aActionId
)) {
7168 "Ignoring out-of-sequence attempt [%p] to set focused browsing context "
7171 Unused
<< SendReviseFocusedBrowsingContext(
7172 aActionId
, fm
->GetFocusedBrowsingContextInChrome(),
7173 fm
->GetActionIdForFocusedBrowsingContextInChrome());
7177 BrowserParent::UpdateFocusFromBrowsingContext();
7179 context
->Group()->EachOtherParent(this, [&](ContentParent
* aParent
) {
7180 Unused
<< aParent
->SendSetFocusedBrowsingContext(context
, aActionId
);
7186 mozilla::ipc::IPCResult
ContentParent::RecvSetActiveBrowsingContext(
7187 const MaybeDiscarded
<BrowsingContext
>& aContext
, uint64_t aActionId
) {
7188 if (aContext
.IsNullOrDiscarded()) {
7190 BrowsingContext::GetLog(), LogLevel::Debug
,
7191 ("ParentIPC: Trying to send a message to dead or detached context"));
7194 LOGFOCUS(("ContentParent::RecvSetActiveBrowsingContext actionid: %" PRIu64
,
7196 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7198 nsFocusManager
* fm
= nsFocusManager::GetFocusManager();
7203 if (!fm
->SetActiveBrowsingContextInChrome(context
, aActionId
)) {
7205 ("Ignoring out-of-sequence attempt [%p] to set active browsing context "
7208 Unused
<< SendReviseActiveBrowsingContext(
7209 aActionId
, fm
->GetActiveBrowsingContextInChrome(),
7210 fm
->GetActionIdForActiveBrowsingContextInChrome());
7214 context
->Group()->EachOtherParent(this, [&](ContentParent
* aParent
) {
7215 Unused
<< aParent
->SendSetActiveBrowsingContext(context
, aActionId
);
7221 mozilla::ipc::IPCResult
ContentParent::RecvUnsetActiveBrowsingContext(
7222 const MaybeDiscarded
<BrowsingContext
>& aContext
, uint64_t aActionId
) {
7223 if (aContext
.IsNullOrDiscarded()) {
7225 BrowsingContext::GetLog(), LogLevel::Debug
,
7226 ("ParentIPC: Trying to send a message to dead or detached context"));
7229 LOGFOCUS(("ContentParent::RecvUnsetActiveBrowsingContext actionid: %" PRIu64
,
7231 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7233 nsFocusManager
* fm
= nsFocusManager::GetFocusManager();
7238 if (!fm
->SetActiveBrowsingContextInChrome(nullptr, aActionId
)) {
7240 ("Ignoring out-of-sequence attempt to unset active browsing context in "
7243 Unused
<< SendReviseActiveBrowsingContext(
7244 aActionId
, fm
->GetActiveBrowsingContextInChrome(),
7245 fm
->GetActionIdForActiveBrowsingContextInChrome());
7249 context
->Group()->EachOtherParent(this, [&](ContentParent
* aParent
) {
7250 Unused
<< aParent
->SendUnsetActiveBrowsingContext(context
, aActionId
);
7256 mozilla::ipc::IPCResult
ContentParent::RecvSetFocusedElement(
7257 const MaybeDiscarded
<BrowsingContext
>& aContext
, bool aNeedsFocus
) {
7258 if (aContext
.IsNullOrDiscarded()) {
7260 BrowsingContext::GetLog(), LogLevel::Debug
,
7261 ("ParentIPC: Trying to send a message to dead or detached context"));
7264 LOGFOCUS(("ContentParent::RecvSetFocusedElement"));
7265 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7267 if (ContentParent
* cp
= context
->GetContentParent()) {
7268 Unused
<< cp
->SendSetFocusedElement(context
, aNeedsFocus
);
7273 mozilla::ipc::IPCResult
ContentParent::RecvFinalizeFocusOuter(
7274 const MaybeDiscarded
<BrowsingContext
>& aContext
, bool aCanFocus
,
7275 CallerType aCallerType
) {
7276 if (aContext
.IsNullOrDiscarded()) {
7278 BrowsingContext::GetLog(), LogLevel::Debug
,
7279 ("ParentIPC: Trying to send a message to dead or detached context"));
7282 LOGFOCUS(("ContentParent::RecvFinalizeFocusOuter"));
7283 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7284 ContentProcessManager
* cpm
= ContentProcessManager::GetSingleton();
7286 ContentParent
* cp
= cpm
->GetContentProcessById(
7287 ContentParentId(context
->EmbedderProcessId()));
7289 Unused
<< cp
->SendFinalizeFocusOuter(context
, aCanFocus
, aCallerType
);
7295 mozilla::ipc::IPCResult
ContentParent::RecvInsertNewFocusActionId(
7296 uint64_t aActionId
) {
7297 LOGFOCUS(("ContentParent::RecvInsertNewFocusActionId actionid: %" PRIu64
,
7299 nsFocusManager
* fm
= nsFocusManager::GetFocusManager();
7301 fm
->InsertNewFocusActionId(aActionId
);
7306 mozilla::ipc::IPCResult
ContentParent::RecvBlurToParent(
7307 const MaybeDiscarded
<BrowsingContext
>& aFocusedBrowsingContext
,
7308 const MaybeDiscarded
<BrowsingContext
>& aBrowsingContextToClear
,
7309 const MaybeDiscarded
<BrowsingContext
>& aAncestorBrowsingContextToFocus
,
7310 bool aIsLeavingDocument
, bool aAdjustWidget
,
7311 bool aBrowsingContextToClearHandled
,
7312 bool aAncestorBrowsingContextToFocusHandled
, uint64_t aActionId
) {
7313 if (aFocusedBrowsingContext
.IsNullOrDiscarded()) {
7315 BrowsingContext::GetLog(), LogLevel::Debug
,
7316 ("ParentIPC: Trying to send a message to dead or detached context"));
7321 ("ContentParent::RecvBlurToParent isLeavingDocument %d adjustWidget %d "
7322 "browsingContextToClearHandled %d ancestorBrowsingContextToFocusHandled "
7323 "%d actionid: %" PRIu64
,
7324 aIsLeavingDocument
, aAdjustWidget
, aBrowsingContextToClearHandled
,
7325 aAncestorBrowsingContextToFocusHandled
, aActionId
));
7327 CanonicalBrowsingContext
* focusedBrowsingContext
=
7328 aFocusedBrowsingContext
.get_canonical();
7330 // If aBrowsingContextToClear and aAncestorBrowsingContextToFocusHandled
7331 // didn't get handled in the process that sent this IPC message and they
7332 // aren't in the same process as aFocusedBrowsingContext, we need to split
7333 // off their handling here and use SendSetFocusedElement to send them
7334 // elsewhere than the blurring itself.
7336 bool ancestorDifferent
=
7337 (!aAncestorBrowsingContextToFocusHandled
&&
7338 !aAncestorBrowsingContextToFocus
.IsNullOrDiscarded() &&
7339 (focusedBrowsingContext
->OwnerProcessId() !=
7340 aAncestorBrowsingContextToFocus
.get_canonical()->OwnerProcessId()));
7341 if (!aBrowsingContextToClearHandled
&&
7342 !aBrowsingContextToClear
.IsNullOrDiscarded() &&
7343 (focusedBrowsingContext
->OwnerProcessId() !=
7344 aBrowsingContextToClear
.get_canonical()->OwnerProcessId())) {
7345 MOZ_RELEASE_ASSERT(!ancestorDifferent
,
7346 "This combination is not supposed to happen.");
7347 if (ContentParent
* cp
=
7348 aBrowsingContextToClear
.get_canonical()->GetContentParent()) {
7349 Unused
<< cp
->SendSetFocusedElement(aBrowsingContextToClear
, false);
7351 } else if (ancestorDifferent
) {
7352 if (ContentParent
* cp
= aAncestorBrowsingContextToFocus
.get_canonical()
7353 ->GetContentParent()) {
7354 Unused
<< cp
->SendSetFocusedElement(aAncestorBrowsingContextToFocus
,
7359 if (ContentParent
* cp
= focusedBrowsingContext
->GetContentParent()) {
7360 Unused
<< cp
->SendBlurToChild(aFocusedBrowsingContext
,
7361 aBrowsingContextToClear
,
7362 aAncestorBrowsingContextToFocus
,
7363 aIsLeavingDocument
, aAdjustWidget
, aActionId
);
7369 mozilla::ipc::IPCResult
ContentParent::RecvMaybeExitFullscreen(
7370 const MaybeDiscarded
<BrowsingContext
>& aContext
) {
7371 if (aContext
.IsNullOrDiscarded()) {
7373 BrowsingContext::GetLog(), LogLevel::Debug
,
7374 ("ParentIPC: Trying to send a message to dead or detached context"));
7377 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7379 if (ContentParent
* cp
= context
->GetContentParent()) {
7380 Unused
<< cp
->SendMaybeExitFullscreen(context
);
7386 mozilla::ipc::IPCResult
ContentParent::RecvWindowPostMessage(
7387 const MaybeDiscarded
<BrowsingContext
>& aContext
,
7388 const ClonedOrErrorMessageData
& aMessage
, const PostMessageData
& aData
) {
7389 if (aContext
.IsNullOrDiscarded()) {
7391 BrowsingContext::GetLog(), LogLevel::Debug
,
7392 ("ParentIPC: Trying to send a message to dead or detached context"));
7395 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7397 if (aData
.source().IsDiscarded()) {
7399 BrowsingContext::GetLog(), LogLevel::Debug
,
7400 ("ParentIPC: Trying to send a message from dead or detached context"));
7404 RefPtr
<ContentParent
> cp
= context
->GetContentParent();
7406 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug
,
7407 ("ParentIPC: Trying to send PostMessage to dead content process"));
7411 ClonedOrErrorMessageData message
;
7412 StructuredCloneData messageFromChild
;
7413 if (aMessage
.type() == ClonedOrErrorMessageData::TClonedMessageData
) {
7414 UnpackClonedMessageData(aMessage
, messageFromChild
);
7416 ClonedMessageData clonedMessageData
;
7417 if (BuildClonedMessageData(messageFromChild
, clonedMessageData
)) {
7418 message
= std::move(clonedMessageData
);
7421 message
= ErrorMessageData();
7424 MOZ_ASSERT(aMessage
.type() == ClonedOrErrorMessageData::TErrorMessageData
);
7425 message
= ErrorMessageData();
7428 Unused
<< cp
->SendWindowPostMessage(context
, message
, aData
);
7432 void ContentParent::AddBrowsingContextGroup(BrowsingContextGroup
* aGroup
) {
7433 MOZ_DIAGNOSTIC_ASSERT(aGroup
);
7434 // Ensure that the group has been inserted, and if we're not launching
7435 // anymore, also begin subscribing. Launching processes will be subscribed if
7436 // they finish launching in `LaunchSubprocessResolve`.
7437 if (mGroups
.EnsureInserted(aGroup
) && !IsLaunching()) {
7438 aGroup
->Subscribe(this);
7442 void ContentParent::RemoveBrowsingContextGroup(BrowsingContextGroup
* aGroup
) {
7443 MOZ_DIAGNOSTIC_ASSERT(aGroup
);
7444 // Remove the group from our list. This is called from the
7445 // BrowsingContextGroup when unsubscribing, so we don't need to do it here.
7446 if (mGroups
.EnsureRemoved(aGroup
) && CanSend()) {
7447 // If we're removing the entry for the first time, tell the content process
7448 // to clean up the group.
7449 Unused
<< SendDestroyBrowsingContextGroup(aGroup
->Id());
7453 mozilla::ipc::IPCResult
ContentParent::RecvCommitBrowsingContextTransaction(
7454 const MaybeDiscarded
<BrowsingContext
>& aContext
,
7455 BrowsingContext::BaseTransaction
&& aTransaction
, uint64_t aEpoch
) {
7456 // Record the new BrowsingContextFieldEpoch associated with this transaction.
7457 // This should be done unconditionally, so that we're always in-sync.
7459 // The order the parent process receives transactions is considered the
7460 // "canonical" ordering, so we don't need to worry about doing any
7461 // epoch-related validation.
7462 MOZ_ASSERT(aEpoch
== mBrowsingContextFieldEpoch
+ 1,
7463 "Child process skipped an epoch?");
7464 mBrowsingContextFieldEpoch
= aEpoch
;
7466 return aTransaction
.CommitFromIPC(aContext
, this);
7469 mozilla::ipc::IPCResult
ContentParent::RecvBlobURLDataRequest(
7470 const nsACString
& aBlobURL
, nsIPrincipal
* aTriggeringPrincipal
,
7471 nsIPrincipal
* aLoadingPrincipal
, const OriginAttributes
& aOriginAttributes
,
7472 uint64_t aInnerWindowId
, const nsCString
& aPartitionKey
,
7473 BlobURLDataRequestResolver
&& aResolver
) {
7474 RefPtr
<BlobImpl
> blobImpl
;
7476 // Since revoked blobs are also retrieved, it is possible that the blob no
7477 // longer exists (due to the 5 second timeout) when execution reaches here
7478 if (!BlobURLProtocolHandler::GetDataEntry(
7479 aBlobURL
, getter_AddRefs(blobImpl
), aLoadingPrincipal
,
7480 aTriggeringPrincipal
, aOriginAttributes
, aInnerWindowId
,
7481 aPartitionKey
, true /* AlsoIfRevoked */)) {
7482 aResolver(NS_ERROR_DOM_BAD_URI
);
7487 nsresult rv
= IPCBlobUtils::Serialize(blobImpl
, ipcBlob
);
7489 if (NS_WARN_IF(NS_FAILED(rv
))) {
7498 mozilla::ipc::IPCResult
ContentParent::RecvReportServiceWorkerShutdownProgress(
7499 uint32_t aShutdownStateId
, ServiceWorkerShutdownState::Progress aProgress
) {
7500 RefPtr
<ServiceWorkerManager
> swm
= ServiceWorkerManager::GetInstance();
7501 MOZ_RELEASE_ASSERT(swm
, "ServiceWorkers should shutdown before SWM.");
7503 swm
->ReportServiceWorkerShutdownProgress(aShutdownStateId
, aProgress
);
7508 mozilla::ipc::IPCResult
ContentParent::RecvNotifyOnHistoryReload(
7509 const MaybeDiscarded
<BrowsingContext
>& aContext
, const bool& aForceReload
,
7510 NotifyOnHistoryReloadResolver
&& aResolver
) {
7511 bool canReload
= false;
7512 Maybe
<NotNull
<RefPtr
<nsDocShellLoadState
>>> loadState
;
7513 Maybe
<bool> reloadActiveEntry
;
7514 if (!aContext
.IsNullOrDiscarded()) {
7515 aContext
.get_canonical()->NotifyOnHistoryReload(
7516 aForceReload
, canReload
, loadState
, reloadActiveEntry
);
7519 std::tuple
<const bool&,
7520 const Maybe
<NotNull
<RefPtr
<nsDocShellLoadState
>>>&,
7521 const Maybe
<bool>&>(canReload
, loadState
, reloadActiveEntry
));
7525 mozilla::ipc::IPCResult
ContentParent::RecvHistoryCommit(
7526 const MaybeDiscarded
<BrowsingContext
>& aContext
, const uint64_t& aLoadID
,
7527 const nsID
& aChangeID
, const uint32_t& aLoadType
, const bool& aPersist
,
7528 const bool& aCloneEntryChildren
, const bool& aChannelExpired
,
7529 const uint32_t& aCacheKey
) {
7530 if (!aContext
.IsDiscarded()) {
7531 CanonicalBrowsingContext
* canonical
= aContext
.get_canonical();
7534 this, "Could not get canonical. aContext.get_canonical() fails.");
7536 canonical
->SessionHistoryCommit(aLoadID
, aChangeID
, aLoadType
, aPersist
,
7537 aCloneEntryChildren
, aChannelExpired
,
7543 mozilla::ipc::IPCResult
ContentParent::RecvHistoryGo(
7544 const MaybeDiscarded
<BrowsingContext
>& aContext
, int32_t aOffset
,
7545 uint64_t aHistoryEpoch
, bool aRequireUserInteraction
, bool aUserActivation
,
7546 HistoryGoResolver
&& aResolveRequestedIndex
) {
7547 if (!aContext
.IsNullOrDiscarded()) {
7548 RefPtr
<CanonicalBrowsingContext
> canonical
= aContext
.get_canonical();
7549 aResolveRequestedIndex(
7550 canonical
->HistoryGo(aOffset
, aHistoryEpoch
, aRequireUserInteraction
,
7551 aUserActivation
, Some(ChildID())));
7556 mozilla::ipc::IPCResult
ContentParent::RecvSynchronizeLayoutHistoryState(
7557 const MaybeDiscarded
<BrowsingContext
>& aContext
,
7558 nsILayoutHistoryState
* aState
) {
7559 if (aContext
.IsNull()) {
7563 BrowsingContext
* bc
= aContext
.GetMaybeDiscarded();
7567 SessionHistoryEntry
* entry
= bc
->Canonical()->GetActiveSessionHistoryEntry();
7569 entry
->SetLayoutHistoryState(aState
);
7574 mozilla::ipc::IPCResult
ContentParent::RecvSessionHistoryEntryTitle(
7575 const MaybeDiscarded
<BrowsingContext
>& aContext
, const nsAString
& aTitle
) {
7576 if (aContext
.IsNullOrDiscarded()) {
7580 SessionHistoryEntry
* entry
=
7581 aContext
.get_canonical()->GetActiveSessionHistoryEntry();
7583 entry
->SetTitle(aTitle
);
7588 mozilla::ipc::IPCResult
7589 ContentParent::RecvSessionHistoryEntryScrollRestorationIsManual(
7590 const MaybeDiscarded
<BrowsingContext
>& aContext
, const bool& aIsManual
) {
7591 if (aContext
.IsNullOrDiscarded()) {
7595 SessionHistoryEntry
* entry
=
7596 aContext
.get_canonical()->GetActiveSessionHistoryEntry();
7598 entry
->SetScrollRestorationIsManual(aIsManual
);
7603 mozilla::ipc::IPCResult
ContentParent::RecvSessionHistoryEntryScrollPosition(
7604 const MaybeDiscarded
<BrowsingContext
>& aContext
, const int32_t& aX
,
7605 const int32_t& aY
) {
7606 if (aContext
.IsNullOrDiscarded()) {
7610 SessionHistoryEntry
* entry
=
7611 aContext
.get_canonical()->GetActiveSessionHistoryEntry();
7613 entry
->SetScrollPosition(aX
, aY
);
7618 mozilla::ipc::IPCResult
7619 ContentParent::RecvSessionHistoryEntryStoreWindowNameInContiguousEntries(
7620 const MaybeDiscarded
<BrowsingContext
>& aContext
, const nsAString
& aName
) {
7621 if (aContext
.IsNullOrDiscarded()) {
7625 // Per https://html.spec.whatwg.org/#history-traversal 4.2.1, we need to set
7626 // the name to all contiguous entries. This has to be called before
7627 // CanonicalBrowsingContext::SessionHistoryCommit(), so the active entry is
7628 // still the old entry that we want to set.
7630 SessionHistoryEntry
* entry
=
7631 aContext
.get_canonical()->GetActiveSessionHistoryEntry();
7634 nsSHistory::WalkContiguousEntries(
7635 entry
, [&](nsISHEntry
* aEntry
) { aEntry
->SetName(aName
); });
7641 mozilla::ipc::IPCResult
ContentParent::RecvSessionHistoryEntryCacheKey(
7642 const MaybeDiscarded
<BrowsingContext
>& aContext
,
7643 const uint32_t& aCacheKey
) {
7644 if (aContext
.IsNullOrDiscarded()) {
7648 SessionHistoryEntry
* entry
=
7649 aContext
.get_canonical()->GetActiveSessionHistoryEntry();
7651 entry
->SetCacheKey(aCacheKey
);
7656 mozilla::ipc::IPCResult
ContentParent::RecvSessionHistoryEntryWireframe(
7657 const MaybeDiscarded
<BrowsingContext
>& aContext
,
7658 const Wireframe
& aWireframe
) {
7659 if (aContext
.IsNull()) {
7663 BrowsingContext
* bc
= aContext
.GetMaybeDiscarded();
7668 SessionHistoryEntry
* entry
= bc
->Canonical()->GetActiveSessionHistoryEntry();
7670 entry
->SetWireframe(Some(aWireframe
));
7675 mozilla::ipc::IPCResult
7676 ContentParent::RecvGetLoadingSessionHistoryInfoFromParent(
7677 const MaybeDiscarded
<BrowsingContext
>& aContext
,
7678 GetLoadingSessionHistoryInfoFromParentResolver
&& aResolver
) {
7679 if (aContext
.IsNullOrDiscarded()) {
7683 Maybe
<LoadingSessionHistoryInfo
> info
;
7684 aContext
.get_canonical()->GetLoadingSessionHistoryInfoFromParent(info
);
7690 mozilla::ipc::IPCResult
ContentParent::RecvRemoveFromBFCache(
7691 const MaybeDiscarded
<BrowsingContext
>& aContext
) {
7692 if (aContext
.IsNullOrDiscarded()) {
7696 nsCOMPtr
<nsFrameLoaderOwner
> owner
=
7697 do_QueryInterface(aContext
.get_canonical()->GetEmbedderElement());
7702 RefPtr
<nsFrameLoader
> frameLoader
= owner
->GetFrameLoader();
7703 if (!frameLoader
|| !frameLoader
->GetMaybePendingBrowsingContext()) {
7707 nsCOMPtr
<nsISHistory
> shistory
= frameLoader
->GetMaybePendingBrowsingContext()
7709 ->GetSessionHistory();
7714 uint32_t count
= shistory
->GetCount();
7715 for (uint32_t i
= 0; i
< count
; ++i
) {
7716 nsCOMPtr
<nsISHEntry
> entry
;
7717 shistory
->GetEntryAtIndex(i
, getter_AddRefs(entry
));
7718 nsCOMPtr
<SessionHistoryEntry
> she
= do_QueryInterface(entry
);
7720 if (RefPtr
<nsFrameLoader
> frameLoader
= she
->GetFrameLoader()) {
7721 if (frameLoader
->GetMaybePendingBrowsingContext() == aContext
.get()) {
7722 she
->SetFrameLoader(nullptr);
7723 frameLoader
->Destroy();
7733 mozilla::ipc::IPCResult
ContentParent::RecvSetActiveSessionHistoryEntry(
7734 const MaybeDiscarded
<BrowsingContext
>& aContext
,
7735 const Maybe
<nsPoint
>& aPreviousScrollPos
, SessionHistoryInfo
&& aInfo
,
7736 uint32_t aLoadType
, uint32_t aUpdatedCacheKey
, const nsID
& aChangeID
) {
7737 if (!aContext
.IsNullOrDiscarded()) {
7738 aContext
.get_canonical()->SetActiveSessionHistoryEntry(
7739 aPreviousScrollPos
, &aInfo
, aLoadType
, aUpdatedCacheKey
, aChangeID
);
7744 mozilla::ipc::IPCResult
ContentParent::RecvReplaceActiveSessionHistoryEntry(
7745 const MaybeDiscarded
<BrowsingContext
>& aContext
,
7746 SessionHistoryInfo
&& aInfo
) {
7747 if (!aContext
.IsNullOrDiscarded()) {
7748 aContext
.get_canonical()->ReplaceActiveSessionHistoryEntry(&aInfo
);
7753 mozilla::ipc::IPCResult
7754 ContentParent::RecvRemoveDynEntriesFromActiveSessionHistoryEntry(
7755 const MaybeDiscarded
<BrowsingContext
>& aContext
) {
7756 if (!aContext
.IsNullOrDiscarded()) {
7757 aContext
.get_canonical()->RemoveDynEntriesFromActiveSessionHistoryEntry();
7762 mozilla::ipc::IPCResult
ContentParent::RecvRemoveFromSessionHistory(
7763 const MaybeDiscarded
<BrowsingContext
>& aContext
, const nsID
& aChangeID
) {
7764 if (!aContext
.IsNullOrDiscarded()) {
7765 aContext
.get_canonical()->RemoveFromSessionHistory(aChangeID
);
7770 mozilla::ipc::IPCResult
ContentParent::RecvHistoryReload(
7771 const MaybeDiscarded
<BrowsingContext
>& aContext
,
7772 const uint32_t aReloadFlags
) {
7773 if (!aContext
.IsNullOrDiscarded()) {
7774 nsCOMPtr
<nsISHistory
> shistory
=
7775 aContext
.get_canonical()->GetSessionHistory();
7777 shistory
->Reload(aReloadFlags
);
7783 mozilla::ipc::IPCResult
ContentParent::RecvCommitWindowContextTransaction(
7784 const MaybeDiscarded
<WindowContext
>& aContext
,
7785 WindowContext::BaseTransaction
&& aTransaction
, uint64_t aEpoch
) {
7786 // Record the new BrowsingContextFieldEpoch associated with this transaction.
7787 // This should be done unconditionally, so that we're always in-sync.
7789 // The order the parent process receives transactions is considered the
7790 // "canonical" ordering, so we don't need to worry about doing any
7791 // epoch-related validation.
7792 MOZ_ASSERT(aEpoch
== mBrowsingContextFieldEpoch
+ 1,
7793 "Child process skipped an epoch?");
7794 mBrowsingContextFieldEpoch
= aEpoch
;
7796 return aTransaction
.CommitFromIPC(aContext
, this);
7799 NS_IMETHODIMP
ContentParent::GetChildID(uint64_t* aOut
) {
7800 *aOut
= this->ChildID();
7804 NS_IMETHODIMP
ContentParent::GetOsPid(int32_t* aOut
) {
7809 NS_IMETHODIMP
ContentParent::GetRemoteType(nsACString
& aRemoteType
) {
7810 aRemoteType
= GetRemoteType();
7814 void ContentParent::StartRemoteWorkerService() {
7815 MOZ_ASSERT(!mRemoteWorkerServiceActor
);
7816 MOZ_ASSERT(mRemoteType
!= PREALLOC_REMOTE_TYPE
);
7818 Endpoint
<PRemoteWorkerServiceChild
> childEp
;
7819 mRemoteWorkerServiceActor
=
7820 RemoteWorkerServiceParent::CreateForProcess(this, &childEp
);
7821 if (mRemoteWorkerServiceActor
) {
7822 Unused
<< SendInitRemoteWorkerService(std::move(childEp
));
7826 IPCResult
ContentParent::RecvRawMessage(
7827 const JSActorMessageMeta
& aMeta
, const Maybe
<ClonedMessageData
>& aData
,
7828 const Maybe
<ClonedMessageData
>& aStack
) {
7829 Maybe
<StructuredCloneData
> data
;
7832 data
->BorrowFromClonedMessageData(*aData
);
7834 Maybe
<StructuredCloneData
> stack
;
7837 stack
->BorrowFromClonedMessageData(*aStack
);
7839 MMPrinter::Print("ContentParent::RecvRawMessage", aMeta
.actorName(),
7840 aMeta
.messageName(), aData
);
7841 ReceiveRawMessage(aMeta
, std::move(data
), std::move(stack
));
7845 NS_IMETHODIMP
ContentParent::GetActor(const nsACString
& aName
, JSContext
* aCx
,
7846 JSProcessActorParent
** retval
) {
7848 RefPtr
<JSProcessActorParent
> actor
=
7849 JSActorManager::GetActor(aCx
, aName
, error
)
7850 .downcast
<JSProcessActorParent
>();
7851 if (error
.MaybeSetPendingException(aCx
)) {
7852 return NS_ERROR_FAILURE
;
7854 actor
.forget(retval
);
7858 NS_IMETHODIMP
ContentParent::GetExistingActor(const nsACString
& aName
,
7859 JSProcessActorParent
** retval
) {
7860 RefPtr
<JSProcessActorParent
> actor
=
7861 JSActorManager::GetExistingActor(aName
).downcast
<JSProcessActorParent
>();
7862 actor
.forget(retval
);
7866 already_AddRefed
<JSActor
> ContentParent::InitJSActor(
7867 JS::Handle
<JSObject
*> aMaybeActor
, const nsACString
& aName
,
7869 RefPtr
<JSProcessActorParent
> actor
;
7870 if (aMaybeActor
.get()) {
7871 aRv
= UNWRAP_OBJECT(JSProcessActorParent
, aMaybeActor
.get(), actor
);
7876 actor
= new JSProcessActorParent();
7879 MOZ_RELEASE_ASSERT(!actor
->Manager(),
7880 "mManager was already initialized once!");
7881 actor
->Init(aName
, this);
7882 return actor
.forget();
7885 IPCResult
ContentParent::RecvFOGData(ByteBuf
&& buf
) {
7886 glean::FOGData(std::move(buf
));
7890 mozilla::ipc::IPCResult
ContentParent::RecvSetContainerFeaturePolicy(
7891 const MaybeDiscardedBrowsingContext
& aContainerContext
,
7892 MaybeFeaturePolicyInfo
&& aContainerFeaturePolicyInfo
) {
7893 if (aContainerContext
.IsNullOrDiscarded()) {
7897 auto* context
= aContainerContext
.get_canonical();
7898 context
->SetContainerFeaturePolicy(std::move(aContainerFeaturePolicyInfo
));
7903 NS_IMETHODIMP
ContentParent::GetCanSend(bool* aCanSend
) {
7904 *aCanSend
= CanSend();
7908 ContentParent
* ContentParent::AsContentParent() { return this; }
7910 JSActorManager
* ContentParent::AsJSActorManager() { return this; }
7912 IPCResult
ContentParent::RecvGetSystemIcon(nsIURI
* aURI
,
7913 GetSystemIconResolver
&& aResolver
) {
7914 using ResolverArgs
= std::tuple
<const nsresult
&, mozilla::Maybe
<ByteBuf
>&&>;
7917 Maybe
<ByteBuf
> bytebuf
= Nothing();
7918 aResolver(ResolverArgs(NS_ERROR_NULL_POINTER
, std::move(bytebuf
)));
7922 #if defined(MOZ_WIDGET_GTK)
7923 Maybe
<ByteBuf
> bytebuf
= Some(ByteBuf
{});
7924 nsresult rv
= nsIconChannel::GetIcon(aURI
, bytebuf
.ptr());
7925 if (NS_WARN_IF(NS_FAILED(rv
))) {
7926 bytebuf
= Nothing();
7928 aResolver(ResolverArgs(rv
, std::move(bytebuf
)));
7930 #elif defined(XP_WIN)
7931 nsIconChannel::GetIconAsync(aURI
)->Then(
7932 GetCurrentSerialEventTarget(), __func__
,
7933 [aResolver
](ByteBuf
&& aByteBuf
) {
7934 Maybe
<ByteBuf
> bytebuf
= Some(std::move(aByteBuf
));
7935 aResolver(ResolverArgs(NS_OK
, std::move(bytebuf
)));
7937 [aResolver
](nsresult aErr
) {
7938 Maybe
<ByteBuf
> bytebuf
= Nothing();
7939 aResolver(ResolverArgs(aErr
, std::move(bytebuf
)));
7944 "This message is currently implemented only on GTK and Windows "
7949 #ifdef FUZZING_SNAPSHOT
7950 IPCResult
ContentParent::RecvSignalFuzzingReady() {
7951 // No action needed here, we already observe this message directly
7952 // on the channel and act accordingly.
7957 nsCString
ThreadsafeContentParentHandle::GetRemoteType() {
7958 RecursiveMutexAutoLock
lock(mMutex
);
7962 UniqueThreadsafeContentParentKeepAlive
7963 ThreadsafeContentParentHandle::TryAddKeepAlive(uint64_t aBrowserId
) {
7964 RecursiveMutexAutoLock
lock(mMutex
);
7965 // If shutdown has already started, we can't keep this ContentParent alive
7967 if (mShutdownStarted
) {
7971 // Otherwise, ensure there is an entry for this BrowserId, and increment it.
7972 ++mKeepAlivesPerBrowserId
.LookupOrInsert(aBrowserId
, 0);
7973 return UniqueThreadsafeContentParentKeepAlive
{do_AddRef(this).take(),
7974 {.mBrowserId
= aBrowserId
}};
7978 } // namespace mozilla
7980 NS_IMPL_ISUPPORTS(ParentIdleListener
, nsIObserver
)
7983 ParentIdleListener::Observe(nsISupports
*, const char* aTopic
,
7984 const char16_t
* aData
) {
7985 mozilla::Unused
<< mParent
->SendNotifyIdleObserver(
7986 mObserver
, nsDependentCString(aTopic
), nsDependentString(aData
));