1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifdef MOZ_WIDGET_ANDROID
8 # include "AndroidDecoderModule.h"
11 #include "mozilla/AppShutdown.h"
12 #include "mozilla/DebugOnly.h"
14 #include "base/basictypes.h"
15 #include "base/shared_memory.h"
17 #include "ContentParent.h"
18 #include "mozilla/ipc/ProcessUtils.h"
19 #include "mozilla/CmdLineAndEnvUtils.h"
20 #include "BrowserParent.h"
22 #include "chrome/common/process_watcher.h"
23 #include "mozilla/Result.h"
24 #include "mozilla/XREAppData.h"
25 #include "nsComponentManagerUtils.h"
26 #include "nsIBrowserDOMWindow.h"
28 #include "GMPServiceParent.h"
29 #include "HandlerServiceParent.h"
34 #include "ContentProcessManager.h"
35 #include "GeckoProfiler.h"
36 #include "Geolocation.h"
37 #include "GfxInfoBase.h"
38 #include "MMPrinter.h"
39 #include "PreallocatedProcessManager.h"
40 #include "ProcessPriorityManager.h"
41 #include "ProfilerParent.h"
42 #include "SandboxHal.h"
43 #include "SourceSurfaceRawData.h"
44 #include "mozilla/ipc/URIUtils.h"
45 #include "gfxPlatform.h"
46 #include "gfxPlatformFontList.h"
47 #include "nsDNSService2.h"
48 #include "nsPIDNSService.h"
49 #include "mozilla/AntiTrackingUtils.h"
50 #include "mozilla/AppShutdown.h"
51 #include "mozilla/AutoRestore.h"
52 #include "mozilla/BasePrincipal.h"
53 #include "mozilla/BenchmarkStorageParent.h"
54 #include "mozilla/Casting.h"
55 #include "mozilla/ClearOnShutdown.h"
56 #include "mozilla/ClipboardReadRequestParent.h"
57 #include "mozilla/ClipboardWriteRequestParent.h"
58 #include "mozilla/ContentBlockingUserInteraction.h"
59 #include "mozilla/FOGIPC.h"
60 #include "mozilla/GlobalStyleSheetCache.h"
61 #include "mozilla/GeckoArgs.h"
62 #include "mozilla/HangDetails.h"
63 #include "mozilla/LookAndFeel.h"
64 #include "mozilla/Maybe.h"
65 #include "mozilla/NullPrincipal.h"
66 #include "mozilla/Preferences.h"
67 #include "mozilla/PresShell.h"
68 #include "mozilla/ProcessHangMonitor.h"
69 #include "mozilla/ProcessHangMonitorIPC.h"
70 #include "mozilla/ProfilerLabels.h"
71 #include "mozilla/ProfilerMarkers.h"
72 #include "mozilla/RecursiveMutex.h"
73 #include "mozilla/ScopeExit.h"
74 #include "mozilla/ScriptPreloader.h"
75 #include "mozilla/Components.h"
76 #include "mozilla/Sprintf.h"
77 #include "mozilla/StaticPrefs_dom.h"
78 #include "mozilla/StaticPrefs_fission.h"
79 #include "mozilla/StaticPrefs_media.h"
80 #include "mozilla/StaticPrefs_network.h"
81 #include "mozilla/StaticPrefs_threads.h"
82 #include "mozilla/StaticPrefs_widget.h"
83 #include "mozilla/StorageAccessAPIHelper.h"
84 #include "mozilla/StyleSheet.h"
85 #include "mozilla/StyleSheetInlines.h"
86 #include "mozilla/TaskController.h"
87 #include "mozilla/Telemetry.h"
88 #include "mozilla/TelemetryIPC.h"
89 #include "mozilla/ThreadSafety.h"
90 #include "mozilla/Unused.h"
91 #include "mozilla/WebBrowserPersistDocumentParent.h"
92 #include "mozilla/devtools/HeapSnapshotTempFileHelperParent.h"
93 #include "mozilla/dom/BlobURLProtocolHandler.h"
94 #include "mozilla/dom/BrowserHost.h"
95 #include "mozilla/dom/BrowsingContext.h"
96 #include "mozilla/dom/BrowsingContextGroup.h"
97 #include "mozilla/dom/CancelContentJSOptionsBinding.h"
98 #include "mozilla/dom/CanonicalBrowsingContext.h"
99 #include "mozilla/dom/ClientManager.h"
100 #include "mozilla/dom/ContentChild.h"
101 #include "mozilla/dom/DataTransfer.h"
102 #include "mozilla/dom/Document.h"
103 #include "mozilla/dom/Element.h"
104 #include "mozilla/dom/ExternalHelperAppParent.h"
105 #include "mozilla/dom/File.h"
106 #include "mozilla/dom/FileSystemSecurity.h"
107 #include "mozilla/dom/GeolocationBinding.h"
108 #include "mozilla/dom/GeolocationPositionError.h"
109 #include "mozilla/dom/GetFilesHelper.h"
110 #include "mozilla/dom/IPCBlobUtils.h"
111 #include "mozilla/dom/JSActorService.h"
112 #include "mozilla/dom/JSProcessActorBinding.h"
113 #include "mozilla/dom/LocalStorageCommon.h"
114 #include "mozilla/dom/MediaController.h"
115 #include "mozilla/dom/MemoryReportRequest.h"
116 #include "mozilla/dom/MediaStatusManager.h"
117 #include "mozilla/dom/Notification.h"
118 #include "mozilla/dom/PContentPermissionRequestParent.h"
119 #include "mozilla/dom/PCycleCollectWithLogsParent.h"
120 #include "mozilla/dom/ParentProcessMessageManager.h"
121 #include "mozilla/dom/Permissions.h"
122 #include "mozilla/dom/ProcessMessageManager.h"
123 #include "mozilla/dom/PushNotifier.h"
124 #include "mozilla/dom/ServiceWorkerManager.h"
125 #include "mozilla/dom/ServiceWorkerRegistrar.h"
126 #include "mozilla/dom/ServiceWorkerUtils.h"
127 #include "mozilla/dom/SessionHistoryEntry.h"
128 #include "mozilla/dom/SessionStorageManager.h"
129 #include "mozilla/dom/StorageIPC.h"
130 #include "mozilla/dom/UserActivation.h"
131 #include "mozilla/dom/URLClassifierParent.h"
132 #include "mozilla/dom/WindowGlobalParent.h"
133 #include "mozilla/dom/ipc/SharedMap.h"
134 #include "mozilla/dom/ipc/StructuredCloneData.h"
135 #include "mozilla/dom/nsMixedContentBlocker.h"
136 #include "mozilla/dom/power/PowerManagerService.h"
137 #include "mozilla/dom/quota/QuotaManagerService.h"
138 #include "mozilla/extensions/ExtensionsParent.h"
139 #include "mozilla/extensions/StreamFilterParent.h"
140 #include "mozilla/gfx/GPUProcessManager.h"
141 #include "mozilla/gfx/gfxVars.h"
142 #include "mozilla/glean/GleanPings.h"
143 #include "mozilla/hal_sandbox/PHalParent.h"
144 #include "mozilla/intl/L10nRegistry.h"
145 #include "mozilla/intl/LocaleService.h"
146 #include "mozilla/ipc/BackgroundChild.h"
147 #include "mozilla/ipc/BackgroundParent.h"
148 #include "mozilla/ipc/ByteBuf.h"
149 #include "mozilla/ipc/CrashReporterHost.h"
150 #include "mozilla/ipc/Endpoint.h"
151 #include "mozilla/ipc/FileDescriptorUtils.h"
152 #include "mozilla/ipc/IPCStreamUtils.h"
153 #include "mozilla/ipc/TestShellParent.h"
154 #include "mozilla/layers/CompositorThread.h"
155 #include "mozilla/layers/ImageBridgeParent.h"
156 #include "mozilla/layers/LayerTreeOwnerTracker.h"
157 #include "mozilla/layers/PAPZParent.h"
158 #include "mozilla/loader/ScriptCacheActors.h"
159 #include "mozilla/media/MediaParent.h"
160 #include "mozilla/mozSpellChecker.h"
161 #include "mozilla/net/CookieServiceParent.h"
162 #include "mozilla/net/NeckoMessageUtils.h"
163 #include "mozilla/net/NeckoParent.h"
164 #include "mozilla/net/PCookieServiceParent.h"
165 #include "mozilla/net/CookieKey.h"
166 #include "mozilla/net/TRRService.h"
167 #include "mozilla/TelemetryComms.h"
168 #include "mozilla/TelemetryEventEnums.h"
169 #include "mozilla/RemoteLazyInputStreamParent.h"
170 #include "mozilla/widget/RemoteLookAndFeel.h"
171 #include "mozilla/widget/ScreenManager.h"
172 #include "mozilla/widget/TextRecognition.h"
173 #include "nsAnonymousTemporaryFile.h"
174 #include "nsAppRunner.h"
175 #include "nsCExternalHandlerService.h"
176 #include "nsCOMPtr.h"
177 #include "nsChromeRegistryChrome.h"
178 #include "nsConsoleMessage.h"
179 #include "nsConsoleService.h"
180 #include "nsContentPermissionHelper.h"
181 #include "nsContentUtils.h"
183 #include "nsDebugImpl.h"
184 #include "nsDirectoryServiceDefs.h"
185 #include "nsDocShell.h"
186 #include "nsEmbedCID.h"
187 #include "nsFocusManager.h"
188 #include "nsFrameLoader.h"
189 #include "nsFrameMessageManager.h"
190 #include "nsGlobalWindowOuter.h"
191 #include "nsHashPropertyBag.h"
192 #include "nsHyphenationManager.h"
193 #include "nsIAlertsService.h"
194 #include "nsIAppShell.h"
195 #include "nsIAppWindow.h"
196 #include "nsIAsyncInputStream.h"
197 #include "nsIBidiKeyboard.h"
198 #include "nsICaptivePortalService.h"
199 #include "nsICertOverrideService.h"
200 #include "nsIClipboard.h"
201 #include "nsIContentAnalysis.h"
202 #include "nsIContentProcess.h"
203 #include "nsIContentSecurityPolicy.h"
204 #include "nsICookie.h"
205 #include "nsICrashService.h"
206 #include "nsICycleCollectorListener.h"
207 #include "nsIDocShell.h"
208 #include "nsIDocShellTreeOwner.h"
209 #include "nsIDragService.h"
210 #include "nsIExternalProtocolService.h"
211 #include "nsIGfxInfo.h"
212 #include "nsIUserIdleService.h"
213 #include "nsIInterfaceRequestorUtils.h"
214 #include "nsILocalStorageManager.h"
215 #include "nsIMemoryInfoDumper.h"
216 #include "nsIMemoryReporter.h"
217 #include "nsINetworkLinkService.h"
218 #include "nsIObserverService.h"
219 #include "nsIParentChannel.h"
220 #include "nsIScriptError.h"
221 #include "nsIScriptSecurityManager.h"
222 #include "nsIServiceWorkerManager.h"
223 #include "nsISiteSecurityService.h"
224 #include "nsIStringBundle.h"
225 #include "nsITimer.h"
227 #include "nsIWebBrowserChrome.h"
228 #include "nsIX509Cert.h"
229 #include "nsIXULRuntime.h"
230 #include "nsICookieNotification.h"
231 #if defined(MOZ_WIDGET_GTK) || defined(XP_WIN)
232 # include "nsIconChannel.h"
234 #include "nsMemoryInfoDumper.h"
235 #include "nsMemoryReporterManager.h"
236 #include "nsOpenURIInFrameParams.h"
237 #include "nsPIWindowWatcher.h"
238 #include "nsQueryObject.h"
239 #include "nsReadableUtils.h"
240 #include "nsSHistory.h"
241 #include "nsScriptError.h"
242 #include "nsServiceManagerUtils.h"
243 #include "nsStreamUtils.h"
244 #include "nsStyleSheetService.h"
245 #include "nsThread.h"
246 #include "nsThreadUtils.h"
247 #include "nsWidgetsCID.h"
248 #include "nsWindowWatcher.h"
251 #include "private/pprio.h"
252 #include "xpcpublic.h"
253 #include "nsOpenWindowInfo.h"
254 #include "nsFrameLoaderOwner.h"
257 # include "jsapi/WebrtcGlobalParent.h"
260 #if defined(XP_MACOSX)
261 # include "nsMacUtilsImpl.h"
262 # include "mozilla/AvailableMemoryWatcher.h"
265 #if defined(ANDROID) || defined(LINUX)
266 # include "nsSystemInfo.h"
269 #if defined(XP_LINUX)
270 # include "mozilla/Hal.h"
274 # include "gfxAndroidPlatform.h"
277 #include "mozilla/PermissionManager.h"
279 #ifdef MOZ_WIDGET_ANDROID
280 # include "AndroidBridge.h"
281 # include "mozilla/java/GeckoProcessManagerWrappers.h"
282 # include "mozilla/java/GeckoProcessTypeWrappers.h"
285 #ifdef MOZ_WIDGET_GTK
286 # include <gdk/gdk.h>
287 # include "mozilla/WidgetUtilsGtk.h"
290 #include "mozilla/RemoteSpellCheckEngineParent.h"
295 # include "mozilla/dom/SpeechSynthesisParent.h"
298 #if defined(MOZ_SANDBOX)
299 # include "mozilla/SandboxSettings.h"
300 # if defined(XP_LINUX)
301 # include "mozilla/SandboxInfo.h"
302 # include "mozilla/SandboxBroker.h"
303 # include "mozilla/SandboxBrokerPolicyFactory.h"
305 # if defined(XP_MACOSX)
306 # include "mozilla/Sandbox.h"
311 # include "mozilla/widget/AudioSession.h"
312 # include "mozilla/WinDllServices.h"
315 #ifdef MOZ_CODE_COVERAGE
316 # include "mozilla/CodeCoverageHandler.h"
319 #ifdef FUZZING_SNAPSHOT
320 # include "mozilla/fuzzing/IPCFuzzController.h"
323 // For VP9Benchmark::sBenchmarkFpsPref
324 #include "Benchmark.h"
326 #include "mozilla/RemoteDecodeUtils.h"
327 #include "nsIToolkitProfileService.h"
328 #include "nsIToolkitProfile.h"
330 static NS_DEFINE_CID(kCClipboardCID
, NS_CLIPBOARD_CID
);
332 using base::KillProcess
;
334 using namespace CrashReporter
;
335 using namespace mozilla::dom::power
;
336 using namespace mozilla::media
;
337 using namespace mozilla::embedding
;
338 using namespace mozilla::gfx
;
339 using namespace mozilla::gmp
;
340 using namespace mozilla::hal
;
341 using namespace mozilla::ipc
;
342 using namespace mozilla::intl
;
343 using namespace mozilla::layers
;
344 using namespace mozilla::layout
;
345 using namespace mozilla::net
;
346 using namespace mozilla::psm
;
347 using namespace mozilla::widget
;
348 using namespace mozilla::Telemetry
;
349 using mozilla::loader::PScriptCacheParent
;
350 using mozilla::Telemetry::ProcessID
;
352 extern mozilla::LazyLogModule gFocusLog
;
354 #define LOGFOCUS(args) MOZ_LOG(gFocusLog, mozilla::LogLevel::Debug, args)
356 extern mozilla::LazyLogModule sPDMLog
;
357 #define LOGPDM(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
360 namespace CubebUtils
{
361 extern FileDescriptor
CreateAudioIPCConnection();
366 LazyLogModule
gProcessLog("Process");
368 static std::map
<RemoteDecodeIn
, media::MediaCodecsSupported
> sCodecsSupported
;
371 uint32_t ContentParent::sMaxContentProcesses
= 0;
374 LogModule
* ContentParent::GetLog() { return gProcessLog
; }
377 uint32_t ContentParent::sPageLoadEventCounter
= 0;
379 #define NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC "ipc:network:set-offline"
380 #define NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC "ipc:network:set-connectivity"
382 // IPC receiver for remote GC/CC logging.
383 class CycleCollectWithLogsParent final
: public PCycleCollectWithLogsParent
{
385 MOZ_COUNTED_DTOR(CycleCollectWithLogsParent
)
387 static bool AllocAndSendConstructor(ContentParent
* aManager
,
389 nsICycleCollectorLogSink
* aSink
,
390 nsIDumpGCAndCCLogsCallback
* aCallback
) {
391 CycleCollectWithLogsParent
* actor
;
396 actor
= new CycleCollectWithLogsParent(aSink
, aCallback
);
397 rv
= actor
->mSink
->Open(&gcLog
, &ccLog
);
398 if (NS_WARN_IF(NS_FAILED(rv
))) {
403 return aManager
->SendPCycleCollectWithLogsConstructor(
404 actor
, aDumpAllTraces
, FILEToFileDescriptor(gcLog
),
405 FILEToFileDescriptor(ccLog
));
409 virtual mozilla::ipc::IPCResult
RecvCloseGCLog() override
{
410 Unused
<< mSink
->CloseGCLog();
414 virtual mozilla::ipc::IPCResult
RecvCloseCCLog() override
{
415 Unused
<< mSink
->CloseCCLog();
419 virtual mozilla::ipc::IPCResult
Recv__delete__() override
{
420 // Report completion to mCallback only on successful
421 // completion of the protocol.
422 nsCOMPtr
<nsIFile
> gcLog
, ccLog
;
423 mSink
->GetGcLog(getter_AddRefs(gcLog
));
424 mSink
->GetCcLog(getter_AddRefs(ccLog
));
425 Unused
<< mCallback
->OnDump(gcLog
, ccLog
, /* parent = */ false);
429 virtual void ActorDestroy(ActorDestroyReason aReason
) override
{
430 // If the actor is unexpectedly destroyed, we deliberately
431 // don't call Close[GC]CLog on the sink, because the logs may
432 // be incomplete. See also the nsCycleCollectorLogSinkToFile
433 // implementaiton of those methods, and its destructor.
436 CycleCollectWithLogsParent(nsICycleCollectorLogSink
* aSink
,
437 nsIDumpGCAndCCLogsCallback
* aCallback
)
438 : mSink(aSink
), mCallback(aCallback
) {
439 MOZ_COUNT_CTOR(CycleCollectWithLogsParent
);
442 nsCOMPtr
<nsICycleCollectorLogSink
> mSink
;
443 nsCOMPtr
<nsIDumpGCAndCCLogsCallback
> mCallback
;
446 // A memory reporter for ContentParent objects themselves.
447 class ContentParentsMemoryReporter final
: public nsIMemoryReporter
{
448 ~ContentParentsMemoryReporter() = default;
452 NS_DECL_NSIMEMORYREPORTER
455 NS_IMPL_ISUPPORTS(ContentParentsMemoryReporter
, nsIMemoryReporter
)
458 ContentParentsMemoryReporter::CollectReports(
459 nsIHandleReportCallback
* aHandleReport
, nsISupports
* aData
,
461 AutoTArray
<ContentParent
*, 16> cps
;
462 ContentParent::GetAllEvenIfDead(cps
);
464 for (uint32_t i
= 0; i
< cps
.Length(); i
++) {
465 ContentParent
* cp
= cps
[i
];
466 MessageChannel
* channel
= cp
->GetIPCChannel();
468 nsString friendlyName
;
469 cp
->FriendlyName(friendlyName
, aAnonymize
);
472 nsrefcnt refcnt
= cp
->Release();
474 const char* channelStr
= "no channel";
475 uint32_t numQueuedMessages
= 0;
477 if (channel
->IsClosed()) {
478 channelStr
= "closed channel";
480 channelStr
= "open channel";
483 0; // XXX was channel->Unsound_NumQueuedMessages(); Bug 1754876
486 nsPrintfCString
path(
487 "queued-ipc-messages/content-parent"
488 "(%s, pid=%d, %s, 0x%p, refcnt=%" PRIuPTR
")",
489 NS_ConvertUTF16toUTF8(friendlyName
).get(), cp
->Pid(), channelStr
,
490 static_cast<nsIObserver
*>(cp
), refcnt
);
492 constexpr auto desc
=
493 "The number of unset IPC messages held in this ContentParent's "
494 "channel. A large value here might indicate that we're leaking "
495 "messages. Similarly, a ContentParent object for a process that's no "
496 "longer running could indicate that we're leaking ContentParents."_ns
;
498 aHandleReport
->Callback(/* process */ ""_ns
, path
, KIND_OTHER
, UNITS_COUNT
,
499 numQueuedMessages
, desc
, aData
);
505 // A hashtable (by type) of processes/ContentParents. This includes
506 // processes that are in the Preallocator cache (which would be type
507 // 'prealloc'), and recycled processes ('web' and in the future
508 // eTLD+1-locked) processes).
509 nsClassHashtable
<nsCStringHashKey
, nsTArray
<ContentParent
*>>*
510 ContentParent::sBrowserContentParents
;
514 uint64_t ComputeLoadedOriginHash(nsIPrincipal
* aPrincipal
) {
515 uint32_t originNoSuffix
=
516 BasePrincipal::Cast(aPrincipal
)->GetOriginNoSuffixHash();
517 uint32_t originSuffix
=
518 BasePrincipal::Cast(aPrincipal
)->GetOriginSuffixHash();
520 return ((uint64_t)originNoSuffix
) << 32 | originSuffix
;
523 class ScriptableCPInfo final
: public nsIContentProcessInfo
{
525 explicit ScriptableCPInfo(ContentParent
* aParent
) : mContentParent(aParent
) {
526 MOZ_ASSERT(mContentParent
);
530 NS_DECL_NSICONTENTPROCESSINFO
532 void ProcessDied() { mContentParent
= nullptr; }
535 ~ScriptableCPInfo() { MOZ_ASSERT(!mContentParent
, "must call ProcessDied"); }
537 ContentParent
* mContentParent
;
540 NS_IMPL_ISUPPORTS(ScriptableCPInfo
, nsIContentProcessInfo
)
543 ScriptableCPInfo::GetIsAlive(bool* aIsAlive
) {
544 *aIsAlive
= mContentParent
!= nullptr;
549 ScriptableCPInfo::GetProcessId(int32_t* aPID
) {
550 if (!mContentParent
) {
552 return NS_ERROR_NOT_INITIALIZED
;
555 *aPID
= mContentParent
->Pid();
557 return NS_ERROR_FAILURE
;
564 ScriptableCPInfo::GetTabCount(int32_t* aTabCount
) {
565 if (!mContentParent
) {
566 return NS_ERROR_NOT_INITIALIZED
;
569 ContentProcessManager
* cpm
= ContentProcessManager::GetSingleton();
570 *aTabCount
= cpm
->GetBrowserParentCountByProcessId(mContentParent
->ChildID());
576 ScriptableCPInfo::GetMessageManager(nsISupports
** aMessenger
) {
577 *aMessenger
= nullptr;
578 if (!mContentParent
) {
579 return NS_ERROR_NOT_INITIALIZED
;
582 RefPtr
<ProcessMessageManager
> manager
= mContentParent
->GetMessageManager();
583 manager
.forget(aMessenger
);
587 ProcessID
GetTelemetryProcessID(const nsACString
& remoteType
) {
588 // OOP WebExtensions run in a content process.
589 // For Telemetry though we want to break out collected data from the
590 // WebExtensions process into a separate bucket, to make sure we can analyze
591 // it separately and avoid skewing normal content process metrics.
592 return remoteType
== EXTENSION_REMOTE_TYPE
? ProcessID::Extension
593 : ProcessID::Content
;
596 } // anonymous namespace
598 StaticAutoPtr
<LinkedList
<ContentParent
>> ContentParent::sContentParents
;
599 StaticRefPtr
<ContentParent
> ContentParent::sRecycledE10SProcess
;
600 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
601 StaticAutoPtr
<SandboxBrokerPolicyFactory
>
602 ContentParent::sSandboxBrokerPolicyFactory
;
604 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
605 StaticAutoPtr
<std::vector
<std::string
>> ContentParent::sMacSandboxParams
;
608 // Set to true when the first content process gets created.
609 static bool sCreatedFirstContentProcess
= false;
611 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
612 // True when we're running the process selection code, and do not expect to
613 // enter code paths where processes may die.
614 static bool sInProcessSelector
= false;
617 // The first content child has ID 1, so the chrome process can have ID 0.
618 static uint64_t gContentChildID
= 1;
620 static const char* sObserverTopics
[] = {
621 NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC
,
622 NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC
,
623 NS_IPC_CAPTIVE_PORTAL_SET_STATE
,
624 "application-background",
625 "application-foreground",
630 "child-ghost-request",
631 "last-pb-context-exited",
632 "file-watcher-update",
634 "a11y-init-or-shutdown",
636 "cacheservice:empty-cache",
637 "intl:app-locales-changed",
638 "intl:requested-locales-changed",
640 "private-cookie-changed",
641 NS_NETWORK_LINK_TYPE_TOPIC
,
642 NS_NETWORK_TRR_MODE_CHANGED_TOPIC
,
643 "network:socket-process-crashed",
644 DEFAULT_TIMEZONE_CHANGED_OBSERVER_TOPIC
,
647 void ContentParent_NotifyUpdatedDictionaries() {
648 ContentParent::NotifyUpdatedDictionaries();
651 // PreallocateProcess is called by the PreallocatedProcessManager.
652 // ContentParent then takes this process back within GetNewOrUsedBrowserProcess.
653 /*static*/ already_AddRefed
<ContentParent
>
654 ContentParent::MakePreallocProcess() {
655 RefPtr
<ContentParent
> process
= new ContentParent(PREALLOC_REMOTE_TYPE
);
656 return process
.forget();
660 void ContentParent::StartUp() {
661 // FIXME Bug 1023701 - Stop using ContentParent static methods in
663 if (!XRE_IsParentProcess()) {
667 // From this point on, NS_WARNING, NS_ASSERTION, etc. should print out the
668 // PID along with the warning.
669 nsDebugImpl::SetMultiprocessMode("Parent");
671 // Note: This reporter measures all ContentParents.
672 RegisterStrongMemoryReporter(new ContentParentsMemoryReporter());
674 BackgroundChild::Startup();
675 ClientManager::Startup();
677 Preferences::RegisterCallbackAndCall(&OnFissionBlocklistPrefChange
,
678 kFissionEnforceBlockList
);
679 Preferences::RegisterCallbackAndCall(&OnFissionBlocklistPrefChange
,
680 kFissionOmitBlockListValues
);
682 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
683 sSandboxBrokerPolicyFactory
= new SandboxBrokerPolicyFactory();
686 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
687 sMacSandboxParams
= new std::vector
<std::string
>();
692 void ContentParent::ShutDown() {
693 // For the most, we rely on normal process shutdown and
694 // ClearOnShutdown() to clean up our state.
696 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
697 sSandboxBrokerPolicyFactory
= nullptr;
700 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
701 sMacSandboxParams
= nullptr;
706 uint32_t ContentParent::GetPoolSize(const nsACString
& aContentProcessType
) {
707 if (!sBrowserContentParents
) {
711 nsTArray
<ContentParent
*>* parents
=
712 sBrowserContentParents
->Get(aContentProcessType
);
714 return parents
? parents
->Length() : 0;
717 /*static*/ nsTArray
<ContentParent
*>& ContentParent::GetOrCreatePool(
718 const nsACString
& aContentProcessType
) {
719 if (!sBrowserContentParents
) {
720 sBrowserContentParents
=
721 new nsClassHashtable
<nsCStringHashKey
, nsTArray
<ContentParent
*>>;
724 return *sBrowserContentParents
->GetOrInsertNew(aContentProcessType
);
727 const nsDependentCSubstring
RemoteTypePrefix(
728 const nsACString
& aContentProcessType
) {
729 // The suffix after a `=` in a remoteType is dynamic, and used to control the
730 // process pool to use.
731 int32_t equalIdx
= aContentProcessType
.FindChar(L
'=');
732 if (equalIdx
== kNotFound
) {
733 equalIdx
= aContentProcessType
.Length();
735 return StringHead(aContentProcessType
, equalIdx
);
738 bool IsWebRemoteType(const nsACString
& aContentProcessType
) {
739 // Note: matches webIsolated, web, and webCOOP+COEP types.
740 return StringBeginsWith(aContentProcessType
, DEFAULT_REMOTE_TYPE
);
743 bool IsWebCoopCoepRemoteType(const nsACString
& aContentProcessType
) {
744 return StringBeginsWith(aContentProcessType
,
745 WITH_COOP_COEP_REMOTE_TYPE_PREFIX
);
748 bool IsExtensionRemoteType(const nsACString
& aContentProcessType
) {
749 return aContentProcessType
== EXTENSION_REMOTE_TYPE
;
753 uint32_t ContentParent::GetMaxProcessCount(
754 const nsACString
& aContentProcessType
) {
755 // Max process count is based only on the prefix.
756 const nsDependentCSubstring processTypePrefix
=
757 RemoteTypePrefix(aContentProcessType
);
759 // Check for the default remote type of "web", as it uses different prefs.
760 if (processTypePrefix
== DEFAULT_REMOTE_TYPE
) {
761 return GetMaxWebProcessCount();
764 // Read the pref controling this remote type. `dom.ipc.processCount` is not
765 // used as a fallback, as it is intended to control the number of "web"
766 // content processes, checked in `mozilla::GetMaxWebProcessCount()`.
767 nsAutoCString
processCountPref("dom.ipc.processCount.");
768 processCountPref
.Append(processTypePrefix
);
770 int32_t maxContentParents
= Preferences::GetInt(processCountPref
.get(), 1);
771 if (maxContentParents
< 1) {
772 maxContentParents
= 1;
775 return static_cast<uint32_t>(maxContentParents
);
779 bool ContentParent::IsMaxProcessCountReached(
780 const nsACString
& aContentProcessType
) {
781 return GetPoolSize(aContentProcessType
) >=
782 GetMaxProcessCount(aContentProcessType
);
785 // Really more ReleaseUnneededProcesses()
787 void ContentParent::ReleaseCachedProcesses() {
788 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
789 ("ReleaseCachedProcesses:"));
790 if (!sBrowserContentParents
) {
795 for (const auto& cps
: *sBrowserContentParents
) {
796 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
797 ("%s: %zu processes", PromiseFlatCString(cps
.GetKey()).get(),
798 cps
.GetData()->Length()));
802 // First let's collect all processes and keep a grip.
803 AutoTArray
<RefPtr
<ContentParent
>, 32> fixArray
;
804 for (const auto& contentParents
: sBrowserContentParents
->Values()) {
805 for (auto* cp
: *contentParents
) {
806 fixArray
.AppendElement(cp
);
810 for (const auto& cp
: fixArray
) {
811 // Ensure the process cannot be claimed between check and MarkAsDead.
812 RecursiveMutexAutoLock
lock(cp
->ThreadsafeHandleMutex());
814 if (cp
->ManagedPBrowserParent().Count() == 0 && !cp
->HasActiveWorker() &&
815 cp
->mRemoteType
== DEFAULT_REMOTE_TYPE
) {
816 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
817 (" Shutdown %p (%s)", cp
.get(), cp
->mRemoteType
.get()));
819 PreallocatedProcessManager::Erase(cp
);
820 // Make sure we don't select this process for new tabs or workers.
822 // Start a soft shutdown.
823 cp
->ShutDownProcess(SEND_SHUTDOWN_MESSAGE
);
824 // Make sure that this process is no longer accessible from JS by its
826 cp
->ShutDownMessageManager();
828 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
829 (" Skipping %p (%s), count %d, HasActiveWorker %d", cp
.get(),
830 cp
->mRemoteType
.get(), cp
->ManagedPBrowserParent().Count(),
831 cp
->HasActiveWorker()));
837 already_AddRefed
<ContentParent
> ContentParent::MinTabSelect(
838 const nsTArray
<ContentParent
*>& aContentParents
,
839 int32_t aMaxContentParents
) {
840 uint32_t maxSelectable
=
841 std::min(static_cast<uint32_t>(aContentParents
.Length()),
842 static_cast<uint32_t>(aMaxContentParents
));
843 uint32_t min
= INT_MAX
;
844 RefPtr
<ContentParent
> candidate
;
845 ContentProcessManager
* cpm
= ContentProcessManager::GetSingleton();
847 for (uint32_t i
= 0; i
< maxSelectable
; i
++) {
848 ContentParent
* p
= aContentParents
[i
];
849 MOZ_DIAGNOSTIC_ASSERT(!p
->IsDead());
851 // Ignore processes that were slated for removal but not yet removed from
852 // the pool (see also GetUsedBrowserProcess and BlockShutdown).
853 if (!p
->IsShuttingDown()) {
854 uint32_t tabCount
= cpm
->GetBrowserParentCountByProcessId(p
->ChildID());
855 if (tabCount
< min
) {
862 // If all current processes have at least one tab and we have not yet reached
863 // the maximum, use a new process.
865 aContentParents
.Length() < static_cast<uint32_t>(aMaxContentParents
)) {
869 // Otherwise we return candidate.
870 return candidate
.forget();
874 already_AddRefed
<nsIPrincipal
>
875 ContentParent::CreateRemoteTypeIsolationPrincipal(
876 const nsACString
& aRemoteType
) {
877 if ((RemoteTypePrefix(aRemoteType
) != FISSION_WEB_REMOTE_TYPE
) &&
878 !StringBeginsWith(aRemoteType
, WITH_COOP_COEP_REMOTE_TYPE_PREFIX
)) {
882 int32_t offset
= aRemoteType
.FindChar('=') + 1;
883 MOZ_ASSERT(offset
> 1, "can not extract origin from that remote type");
884 nsAutoCString
origin(
885 Substring(aRemoteType
, offset
, aRemoteType
.Length() - offset
));
887 nsIScriptSecurityManager
* ssm
= nsContentUtils::GetSecurityManager();
888 nsCOMPtr
<nsIPrincipal
> principal
;
889 ssm
->CreateContentPrincipalFromOrigin(origin
, getter_AddRefs(principal
));
890 return principal
.forget();
894 already_AddRefed
<ContentParent
> ContentParent::GetUsedBrowserProcess(
895 const nsACString
& aRemoteType
, nsTArray
<ContentParent
*>& aContentParents
,
896 uint32_t aMaxContentParents
, bool aPreferUsed
, ProcessPriority aPriority
) {
897 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
898 AutoRestore
ar(sInProcessSelector
);
899 sInProcessSelector
= true;
902 uint32_t numberOfParents
= aContentParents
.Length();
903 nsTArray
<RefPtr
<nsIContentProcessInfo
>> infos(numberOfParents
);
904 for (auto* cp
: aContentParents
) {
905 infos
.AppendElement(cp
->mScriptableHelper
);
908 if (aPreferUsed
&& numberOfParents
) {
909 // If we prefer re-using existing content processes, we don't want to create
910 // a new process, and instead re-use an existing one, so pretend the process
911 // limit is at the current number of processes.
912 aMaxContentParents
= numberOfParents
;
915 nsCOMPtr
<nsIContentProcessProvider
> cpp
=
916 do_GetService("@mozilla.org/ipc/processselector;1");
918 if (cpp
&& NS_SUCCEEDED(cpp
->ProvideProcess(aRemoteType
, infos
,
919 aMaxContentParents
, &index
))) {
920 // If the provider returned an existing ContentParent, use that one.
921 if (0 <= index
&& static_cast<uint32_t>(index
) <= aMaxContentParents
) {
922 RefPtr
<ContentParent
> retval
= aContentParents
[index
];
923 // Ignore processes that were slated for removal but not yet removed from
925 if (!retval
->IsShuttingDown()) {
926 if (profiler_thread_is_being_profiled_for_markers()) {
927 nsPrintfCString
marker("Reused process %u",
928 (unsigned int)retval
->ChildID());
929 PROFILER_MARKER_TEXT("Process", DOM
, {}, marker
);
931 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
932 ("GetUsedProcess: Reused process %p (%u) for %s", retval
.get(),
933 (unsigned int)retval
->ChildID(),
934 PromiseFlatCString(aRemoteType
).get()));
935 retval
->AssertAlive();
936 retval
->StopRecyclingE10SOnly(true);
937 return retval
.forget();
941 // If there was a problem with the JS chooser, fall back to a random
943 NS_WARNING("nsIContentProcessProvider failed to return a process");
944 RefPtr
<ContentParent
> random
;
945 if ((random
= MinTabSelect(aContentParents
, aMaxContentParents
))) {
946 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
947 ("GetUsedProcess: Reused random process %p (%d) for %s",
948 random
.get(), (unsigned int)random
->ChildID(),
949 PromiseFlatCString(aRemoteType
).get()));
950 random
->AssertAlive();
951 random
->StopRecyclingE10SOnly(true);
952 return random
.forget();
956 // If we are loading into the "web" remote type, are choosing to launch a new
957 // tab, and have a recycled E10S process, we should launch into that process.
958 if (aRemoteType
== DEFAULT_REMOTE_TYPE
&& sRecycledE10SProcess
) {
959 RefPtr
<ContentParent
> recycled
= sRecycledE10SProcess
;
960 MOZ_DIAGNOSTIC_ASSERT(recycled
->GetRemoteType() == DEFAULT_REMOTE_TYPE
);
961 recycled
->AssertAlive();
962 recycled
->StopRecyclingE10SOnly(true);
963 if (profiler_thread_is_being_profiled_for_markers()) {
964 nsPrintfCString
marker("Recycled process %u (%p)",
965 (unsigned int)recycled
->ChildID(), recycled
.get());
966 PROFILER_MARKER_TEXT("Process", DOM
, {}, marker
);
968 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
969 ("Recycled process %p", recycled
.get()));
971 return recycled
.forget();
974 // Try to take a preallocated process except for certain remote types.
975 // Note: this process may not have finished launching yet
976 RefPtr
<ContentParent
> preallocated
;
977 if (aRemoteType
!= FILE_REMOTE_TYPE
&&
978 aRemoteType
!= PRIVILEGEDABOUT_REMOTE_TYPE
&&
979 aRemoteType
!= EXTENSION_REMOTE_TYPE
&& // Bug 1638119
980 (preallocated
= PreallocatedProcessManager::Take(aRemoteType
))) {
981 MOZ_DIAGNOSTIC_ASSERT(preallocated
->GetRemoteType() ==
982 PREALLOC_REMOTE_TYPE
);
983 MOZ_DIAGNOSTIC_ASSERT(sRecycledE10SProcess
!= preallocated
);
984 preallocated
->AssertAlive();
986 if (profiler_thread_is_being_profiled_for_markers()) {
987 nsPrintfCString
marker(
988 "Assigned preallocated process %u%s",
989 (unsigned int)preallocated
->ChildID(),
990 preallocated
->IsLaunching() ? " (still launching)" : "");
991 PROFILER_MARKER_TEXT("Process", DOM
, {}, marker
);
993 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
994 ("Adopted preallocated process %p for type %s%s",
995 preallocated
.get(), PromiseFlatCString(aRemoteType
).get(),
996 preallocated
->IsLaunching() ? " (still launching)" : ""));
998 // This ensures that the preallocator won't shut down the process once
999 // it finishes starting
1000 preallocated
->mRemoteType
.Assign(aRemoteType
);
1002 RecursiveMutexAutoLock
lock(preallocated
->mThreadsafeHandle
->mMutex
);
1003 preallocated
->mThreadsafeHandle
->mRemoteType
= preallocated
->mRemoteType
;
1005 preallocated
->mRemoteTypeIsolationPrincipal
=
1006 CreateRemoteTypeIsolationPrincipal(aRemoteType
);
1007 preallocated
->mActivateTS
= TimeStamp::Now();
1008 preallocated
->AddToPool(aContentParents
);
1010 // rare, but will happen
1011 if (!preallocated
->IsLaunching()) {
1012 // Specialize this process for the appropriate remote type, and activate
1015 Unused
<< preallocated
->SendRemoteType(preallocated
->mRemoteType
,
1016 preallocated
->mProfile
);
1018 nsCOMPtr
<nsIObserverService
> obs
=
1019 mozilla::services::GetObserverService();
1022 cpId
.AppendInt(static_cast<uint64_t>(preallocated
->ChildID()));
1023 obs
->NotifyObservers(static_cast<nsIObserver
*>(preallocated
),
1024 "process-type-set", cpId
.get());
1025 preallocated
->AssertAlive();
1028 return preallocated
.forget();
1035 already_AddRefed
<ContentParent
>
1036 ContentParent::GetNewOrUsedLaunchingBrowserProcess(
1037 const nsACString
& aRemoteType
, BrowsingContextGroup
* aGroup
,
1038 ProcessPriority aPriority
, bool aPreferUsed
) {
1039 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
1040 ("GetNewOrUsedProcess for type %s",
1041 PromiseFlatCString(aRemoteType
).get()));
1043 // Fallback check (we really want our callers to avoid this).
1044 if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed
)) {
1045 MOZ_DIAGNOSTIC_ASSERT(
1046 false, "Late attempt to GetNewOrUsedLaunchingBrowserProcess!");
1050 // If we have an existing host process attached to this BrowsingContextGroup,
1051 // always return it, as we can never have multiple host processes within a
1052 // single BrowsingContextGroup.
1053 RefPtr
<ContentParent
> contentParent
;
1055 contentParent
= aGroup
->GetHostProcess(aRemoteType
);
1056 Unused
<< NS_WARN_IF(contentParent
&& contentParent
->IsShuttingDown());
1057 if (contentParent
&& !contentParent
->IsShuttingDown()) {
1058 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
1059 ("GetNewOrUsedProcess: Existing host process %p (launching %d)",
1060 contentParent
.get(), contentParent
->IsLaunching()));
1061 contentParent
->AssertAlive();
1062 contentParent
->StopRecyclingE10SOnly(true);
1063 return contentParent
.forget();
1067 nsTArray
<ContentParent
*>& contentParents
= GetOrCreatePool(aRemoteType
);
1068 uint32_t maxContentParents
= GetMaxProcessCount(aRemoteType
);
1070 // Let's try and reuse an existing process.
1071 contentParent
= GetUsedBrowserProcess(
1072 aRemoteType
, contentParents
, maxContentParents
, aPreferUsed
, aPriority
);
1074 if (!contentParent
) {
1075 // No reusable process. Let's create and launch one.
1076 // The life cycle will be set to `LifecycleState::LAUNCHING`.
1077 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
1078 ("Launching new process immediately for type %s",
1079 PromiseFlatCString(aRemoteType
).get()));
1081 contentParent
= new ContentParent(aRemoteType
);
1082 if (NS_WARN_IF(!contentParent
->BeginSubprocessLaunch(aPriority
))) {
1083 // Launch aborted because of shutdown. Bailout.
1084 contentParent
->LaunchSubprocessReject();
1087 // Until the new process is ready let's not allow to start up any
1088 // preallocated processes. The blocker will be removed once we receive
1089 // the first idle message.
1090 contentParent
->mIsAPreallocBlocker
= true;
1091 PreallocatedProcessManager::AddBlocker(aRemoteType
, contentParent
);
1093 // Store this process for future reuse.
1094 contentParent
->AddToPool(contentParents
);
1097 ContentParent::GetLog(), LogLevel::Debug
,
1098 ("GetNewOrUsedProcess: new immediate process %p", contentParent
.get()));
1100 // else we have an existing or preallocated process (which may be
1103 contentParent
->AssertAlive();
1104 contentParent
->StopRecyclingE10SOnly(true);
1106 aGroup
->EnsureHostProcess(contentParent
);
1108 return contentParent
.forget();
1112 RefPtr
<ContentParent::LaunchPromise
>
1113 ContentParent::GetNewOrUsedBrowserProcessAsync(const nsACString
& aRemoteType
,
1114 BrowsingContextGroup
* aGroup
,
1115 ProcessPriority aPriority
,
1117 // Obtain a `ContentParent` launched asynchronously.
1118 RefPtr
<ContentParent
> contentParent
= GetNewOrUsedLaunchingBrowserProcess(
1119 aRemoteType
, aGroup
, aPriority
, aPreferUsed
);
1120 if (!contentParent
) {
1121 // In case of launch error, stop here.
1122 return LaunchPromise::CreateAndReject(NS_ERROR_ILLEGAL_DURING_SHUTDOWN
,
1125 return contentParent
->WaitForLaunchAsync(aPriority
);
1129 already_AddRefed
<ContentParent
> ContentParent::GetNewOrUsedBrowserProcess(
1130 const nsACString
& aRemoteType
, BrowsingContextGroup
* aGroup
,
1131 ProcessPriority aPriority
, bool aPreferUsed
) {
1132 RefPtr
<ContentParent
> contentParent
= GetNewOrUsedLaunchingBrowserProcess(
1133 aRemoteType
, aGroup
, aPriority
, aPreferUsed
);
1134 if (!contentParent
|| !contentParent
->WaitForLaunchSync(aPriority
)) {
1135 // In case of launch error, stop here.
1138 return contentParent
.forget();
1141 RefPtr
<ContentParent::LaunchPromise
> ContentParent::WaitForLaunchAsync(
1142 ProcessPriority aPriority
) {
1143 MOZ_DIAGNOSTIC_ASSERT(!IsDead());
1144 if (!IsLaunching()) {
1145 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
1146 ("WaitForLaunchAsync: launched"));
1147 return LaunchPromise::CreateAndResolve(this, __func__
);
1150 // We've started an async content process launch.
1151 Telemetry::Accumulate(Telemetry::CONTENT_PROCESS_LAUNCH_IS_SYNC
, 0);
1153 // We have located a process that hasn't finished initializing, then attempt
1154 // to finish initializing. Both `LaunchSubprocessResolve` and
1155 // `LaunchSubprocessReject` are safe to call multiple times if we race with
1156 // other `WaitForLaunchAsync` callbacks.
1157 return mSubprocess
->WhenProcessHandleReady()->Then(
1158 GetCurrentSerialEventTarget(), __func__
,
1159 [self
= RefPtr
{this}, aPriority
]() {
1160 if (self
->LaunchSubprocessResolve(/* aIsSync = */ false, aPriority
)) {
1161 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
1162 ("WaitForLaunchAsync: async, now launched"));
1163 self
->mActivateTS
= TimeStamp::Now();
1164 return LaunchPromise::CreateAndResolve(self
, __func__
);
1167 self
->LaunchSubprocessReject();
1168 return LaunchPromise::CreateAndReject(NS_ERROR_INVALID_ARG
, __func__
);
1170 [self
= RefPtr
{this}]() {
1171 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
1172 ("WaitForLaunchAsync: async, rejected"));
1173 self
->LaunchSubprocessReject();
1174 return LaunchPromise::CreateAndReject(NS_ERROR_FAILURE
, __func__
);
1178 bool ContentParent::WaitForLaunchSync(ProcessPriority aPriority
) {
1179 MOZ_DIAGNOSTIC_ASSERT(!IsDead());
1180 if (!IsLaunching()) {
1184 // We've started a sync content process launch.
1185 Telemetry::Accumulate(Telemetry::CONTENT_PROCESS_LAUNCH_IS_SYNC
, 1);
1187 // We're a process which hasn't finished initializing. We may be racing
1188 // against whoever launched it (and whoever else is already racing). Since
1189 // we're sync, we win the race and finish the initialization.
1190 bool launchSuccess
= mSubprocess
->WaitForProcessHandle();
1191 if (launchSuccess
&&
1192 LaunchSubprocessResolve(/* aIsSync = */ true, aPriority
)) {
1193 mActivateTS
= TimeStamp::Now();
1196 // In case of failure.
1197 LaunchSubprocessReject();
1201 static nsIDocShell
* GetOpenerDocShellHelper(Element
* aFrameElement
) {
1202 // Propagate the private-browsing status of the element's parent
1203 // docshell to the remote docshell, via the chrome flags.
1204 MOZ_ASSERT(aFrameElement
);
1205 nsPIDOMWindowOuter
* win
= aFrameElement
->OwnerDoc()->GetWindow();
1207 NS_WARNING("Remote frame has no window");
1210 nsIDocShell
* docShell
= win
->GetDocShell();
1212 NS_WARNING("Remote frame has no docshell");
1219 mozilla::ipc::IPCResult
ContentParent::RecvCreateGMPService() {
1220 Endpoint
<PGMPServiceParent
> parent
;
1221 Endpoint
<PGMPServiceChild
> child
;
1224 return IPC_FAIL(this, "GMP Service already created");
1228 rv
= PGMPService::CreateEndpoints(base::GetCurrentProcId(), OtherPid(),
1230 if (NS_FAILED(rv
)) {
1231 return IPC_FAIL(this, "CreateEndpoints failed");
1234 if (!GMPServiceParent::Create(std::move(parent
))) {
1235 return IPC_FAIL(this, "GMPServiceParent::Create failed");
1238 if (!SendInitGMPService(std::move(child
))) {
1239 return IPC_FAIL(this, "SendInitGMPService failed");
1247 Atomic
<bool, mozilla::Relaxed
> sContentParentTelemetryEventEnabled(false);
1250 void ContentParent::LogAndAssertFailedPrincipalValidationInfo(
1251 nsIPrincipal
* aPrincipal
, const char* aMethod
) {
1252 // nsContentSecurityManager may also enable this same event, but that's okay
1253 if (!sContentParentTelemetryEventEnabled
.exchange(true)) {
1254 sContentParentTelemetryEventEnabled
= true;
1255 Telemetry::SetEventRecordingEnabled("security"_ns
, true);
1259 nsAutoCString principalScheme
, principalType
, spec
;
1260 CopyableTArray
<EventExtraEntry
> extra(2);
1263 principalType
.AssignLiteral("NullPtr");
1264 } else if (aPrincipal
->IsSystemPrincipal()) {
1265 principalType
.AssignLiteral("SystemPrincipal");
1266 } else if (aPrincipal
->GetIsExpandedPrincipal()) {
1267 principalType
.AssignLiteral("ExpandedPrincipal");
1268 } else if (aPrincipal
->GetIsContentPrincipal()) {
1269 principalType
.AssignLiteral("ContentPrincipal");
1270 aPrincipal
->GetSpec(spec
);
1271 aPrincipal
->GetScheme(principalScheme
);
1273 extra
.AppendElement(EventExtraEntry
{"scheme"_ns
, principalScheme
});
1275 principalType
.AssignLiteral("Unknown");
1278 extra
.AppendElement(EventExtraEntry
{"principalType"_ns
, principalType
});
1280 // Do not send telemetry when chrome-debugging is enabled
1281 bool isChromeDebuggingEnabled
=
1282 Preferences::GetBool("devtools.chrome.enabled", false);
1283 if (!isChromeDebuggingEnabled
) {
1284 Telemetry::EventID eventType
=
1285 Telemetry::EventID::Security_Fissionprincipals_Contentparent
;
1286 Telemetry::RecordEvent(eventType
, mozilla::Some(aMethod
),
1287 mozilla::Some(extra
));
1292 ContentParent::GetLog(), LogLevel::Error
,
1293 (" Receiving unexpected Principal (%s) within %s",
1294 aPrincipal
&& aPrincipal
->GetIsContentPrincipal() ? spec
.get()
1295 : principalType
.get(),
1299 // Not only log but also ensure we do not receive an unexpected
1300 // principal when running in debug mode.
1301 MOZ_ASSERT(false, "Receiving unexpected Principal");
1305 bool ContentParent::ValidatePrincipal(
1306 nsIPrincipal
* aPrincipal
,
1307 const EnumSet
<ValidatePrincipalOptions
>& aOptions
) {
1308 // If the pref says we should not validate, then there is nothing to do
1309 if (!StaticPrefs::dom_security_enforceIPCBasedPrincipalVetting()) {
1313 // If there is no principal, then there is nothing to validate!
1315 return aOptions
.contains(ValidatePrincipalOptions::AllowNullPtr
);
1318 // We currently do not track relationships between specific null principals
1319 // and content processes, so we can not validate much here - just allow all
1320 // null principals we see because they are generally safe anyway!
1321 if (aPrincipal
->GetIsNullPrincipal()) {
1325 // Only allow the system principal if the passed in options flags
1326 // request permitting the system principal.
1327 if (aPrincipal
->IsSystemPrincipal()) {
1328 return aOptions
.contains(ValidatePrincipalOptions::AllowSystem
);
1331 // XXXckerschb: we should eliminate the resource carve-out here and always
1332 // validate the Principal, see Bug 1686200: Investigate Principal for pdf.js
1333 if (aPrincipal
->SchemeIs("resource")) {
1337 // Validate each inner principal individually, allowing us to catch expanded
1338 // principals containing the system principal, etc.
1339 if (aPrincipal
->GetIsExpandedPrincipal()) {
1340 if (!aOptions
.contains(ValidatePrincipalOptions::AllowExpanded
)) {
1343 // FIXME: There are more constraints on expanded principals in-practice,
1344 // such as the structure of extension expanded principals. This may need
1345 // to be investigated more in the future.
1346 nsCOMPtr
<nsIExpandedPrincipal
> expandedPrincipal
=
1347 do_QueryInterface(aPrincipal
);
1348 const auto& allowList
= expandedPrincipal
->AllowList();
1349 for (const auto& innerPrincipal
: allowList
) {
1350 if (!ValidatePrincipal(innerPrincipal
, aOptions
)) {
1357 // A URI with a file:// scheme can never load in a non-file content process
1358 // due to sandboxing.
1359 if (aPrincipal
->SchemeIs("file")) {
1360 // If we don't support a separate 'file' process, then we can return here.
1361 if (!StaticPrefs::browser_tabs_remote_separateFileUriProcess()) {
1364 return mRemoteType
== FILE_REMOTE_TYPE
;
1367 if (aPrincipal
->SchemeIs("about")) {
1369 if (NS_FAILED(aPrincipal
->GetAboutModuleFlags(&flags
))) {
1373 // Block principals for about: URIs which can't load in this process.
1374 if (!(flags
& (nsIAboutModule::URI_CAN_LOAD_IN_CHILD
|
1375 nsIAboutModule::URI_MUST_LOAD_IN_CHILD
))) {
1378 if (flags
& nsIAboutModule::URI_MUST_LOAD_IN_EXTENSION_PROCESS
) {
1379 return mRemoteType
== EXTENSION_REMOTE_TYPE
;
1384 if (!mRemoteTypeIsolationPrincipal
||
1385 RemoteTypePrefix(mRemoteType
) != FISSION_WEB_REMOTE_TYPE
) {
1389 // Web content can contain extension content frames, so a content process may
1390 // send us an extension's principal.
1391 auto* addonPolicy
= BasePrincipal::Cast(aPrincipal
)->AddonPolicy();
1396 // Ensure that the expected site-origin matches the one specified by our
1397 // mRemoteTypeIsolationPrincipal.
1398 nsAutoCString siteOriginNoSuffix
;
1399 if (NS_FAILED(aPrincipal
->GetSiteOriginNoSuffix(siteOriginNoSuffix
))) {
1402 nsAutoCString remoteTypeSiteOriginNoSuffix
;
1403 if (NS_FAILED(mRemoteTypeIsolationPrincipal
->GetSiteOriginNoSuffix(
1404 remoteTypeSiteOriginNoSuffix
))) {
1408 return remoteTypeSiteOriginNoSuffix
.Equals(siteOriginNoSuffix
);
1412 already_AddRefed
<RemoteBrowser
> ContentParent::CreateBrowser(
1413 const TabContext
& aContext
, Element
* aFrameElement
,
1414 const nsACString
& aRemoteType
, BrowsingContext
* aBrowsingContext
,
1415 ContentParent
* aOpenerContentParent
) {
1416 AUTO_PROFILER_LABEL("ContentParent::CreateBrowser", OTHER
);
1418 MOZ_DIAGNOSTIC_ASSERT(
1419 !aBrowsingContext
->Canonical()->GetBrowserParent(),
1420 "BrowsingContext must not have BrowserParent, or have previous "
1421 "BrowserParent cleared");
1423 // Don't bother creating new content browsers after entering shutdown. This
1424 // could lead to starting a new content process, which may significantly delay
1425 // shutdown, and the content is unlikely to be displayed.
1426 if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed
)) {
1427 NS_WARNING("Ignoring remote browser creation request during shutdown");
1431 nsAutoCString
remoteType(aRemoteType
);
1432 if (remoteType
.IsEmpty()) {
1433 remoteType
= DEFAULT_REMOTE_TYPE
;
1436 TabId
tabId(nsContentUtils::GenerateTabId());
1438 nsIDocShell
* docShell
= GetOpenerDocShellHelper(aFrameElement
);
1441 openerTabId
= BrowserParent::GetTabIdFrom(docShell
);
1444 RefPtr
<ContentParent
> constructorSender
;
1445 MOZ_RELEASE_ASSERT(XRE_IsParentProcess(),
1446 "Cannot allocate BrowserParent in content process");
1447 if (aOpenerContentParent
&& !aOpenerContentParent
->IsShuttingDown()) {
1448 constructorSender
= aOpenerContentParent
;
1450 constructorSender
= GetNewOrUsedBrowserProcess(
1451 remoteType
, aBrowsingContext
->Group(), PROCESS_PRIORITY_FOREGROUND
);
1452 if (!constructorSender
) {
1457 aBrowsingContext
->SetEmbedderElement(aFrameElement
);
1459 // Ensure that the process which we're using to launch is set as the host
1460 // process for this BrowsingContextGroup.
1461 aBrowsingContext
->Group()->EnsureHostProcess(constructorSender
);
1463 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
1464 docShell
->GetTreeOwner(getter_AddRefs(treeOwner
));
1469 nsCOMPtr
<nsIWebBrowserChrome
> wbc
= do_GetInterface(treeOwner
);
1473 uint32_t chromeFlags
= 0;
1474 wbc
->GetChromeFlags(&chromeFlags
);
1476 nsCOMPtr
<nsILoadContext
> loadContext
= do_QueryInterface(docShell
);
1477 if (loadContext
&& loadContext
->UsePrivateBrowsing()) {
1478 chromeFlags
|= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW
;
1480 if (loadContext
&& loadContext
->UseRemoteTabs()) {
1481 chromeFlags
|= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW
;
1483 if (loadContext
&& loadContext
->UseRemoteSubframes()) {
1484 chromeFlags
|= nsIWebBrowserChrome::CHROME_FISSION_WINDOW
;
1491 aBrowsingContext
->Canonical()->SetOwnerProcessId(
1492 constructorSender
->ChildID());
1494 RefPtr
<BrowserParent
> browserParent
=
1495 new BrowserParent(constructorSender
, tabId
, aContext
,
1496 aBrowsingContext
->Canonical(), chromeFlags
);
1498 // Open a remote endpoint for our PBrowser actor.
1499 ManagedEndpoint
<PBrowserChild
> childEp
=
1500 constructorSender
->OpenPBrowserEndpoint(browserParent
);
1501 if (NS_WARN_IF(!childEp
.IsValid())) {
1505 ContentProcessManager
* cpm
= ContentProcessManager::GetSingleton();
1506 if (NS_WARN_IF(!cpm
)) {
1509 cpm
->RegisterRemoteFrame(browserParent
);
1511 nsCOMPtr
<nsIPrincipal
> initialPrincipal
=
1512 NullPrincipal::Create(aBrowsingContext
->OriginAttributesRef());
1513 WindowGlobalInit windowInit
= WindowGlobalActor::AboutBlankInitializer(
1514 aBrowsingContext
, initialPrincipal
);
1516 RefPtr
<WindowGlobalParent
> windowParent
=
1517 WindowGlobalParent::CreateDisconnected(windowInit
);
1518 if (NS_WARN_IF(!windowParent
)) {
1522 // Open a remote endpoint for the initial PWindowGlobal actor.
1523 ManagedEndpoint
<PWindowGlobalChild
> windowEp
=
1524 browserParent
->OpenPWindowGlobalEndpoint(windowParent
);
1525 if (NS_WARN_IF(!windowEp
.IsValid())) {
1529 // Tell the content process to set up its PBrowserChild.
1530 bool ok
= constructorSender
->SendConstructBrowser(
1531 std::move(childEp
), std::move(windowEp
), tabId
,
1532 aContext
.AsIPCTabContext(), windowInit
, chromeFlags
,
1533 constructorSender
->ChildID(), constructorSender
->IsForBrowser(),
1534 /* aIsTopLevel */ true);
1535 if (NS_WARN_IF(!ok
)) {
1539 // Ensure that we're marked as the current BrowserParent on our
1540 // CanonicalBrowsingContext.
1541 aBrowsingContext
->Canonical()->SetCurrentBrowserParent(browserParent
);
1543 windowParent
->Init();
1545 RefPtr
<BrowserHost
> browserHost
= new BrowserHost(browserParent
);
1546 browserParent
->SetOwnerElement(aFrameElement
);
1547 return browserHost
.forget();
1550 void ContentParent::GetAll(nsTArray
<ContentParent
*>& aArray
) {
1553 for (auto* cp
: AllProcesses(eLive
)) {
1554 aArray
.AppendElement(cp
);
1558 void ContentParent::GetAllEvenIfDead(nsTArray
<ContentParent
*>& aArray
) {
1561 for (auto* cp
: AllProcesses(eAll
)) {
1562 aArray
.AppendElement(cp
);
1566 void ContentParent::BroadcastStringBundle(
1567 const StringBundleDescriptor
& aBundle
) {
1568 AutoTArray
<StringBundleDescriptor
, 1> array
;
1569 array
.AppendElement(aBundle
);
1571 for (auto* cp
: AllProcesses(eLive
)) {
1572 Unused
<< cp
->SendRegisterStringBundles(array
);
1576 void ContentParent::BroadcastFontListChanged() {
1577 for (auto* cp
: AllProcesses(eLive
)) {
1578 Unused
<< cp
->SendFontListChanged();
1582 void ContentParent::BroadcastShmBlockAdded(uint32_t aGeneration
,
1584 auto* pfl
= gfxPlatformFontList::PlatformFontList();
1585 for (auto* cp
: AllProcesses(eLive
)) {
1586 base::SharedMemoryHandle handle
=
1587 pfl
->ShareShmBlockToProcess(aIndex
, cp
->Pid());
1588 if (handle
== base::SharedMemory::NULLHandle()) {
1589 // If something went wrong here, we just skip it; the child will need to
1590 // request the block as needed, at some performance cost.
1593 Unused
<< cp
->SendFontListShmBlockAdded(aGeneration
, aIndex
,
1598 void ContentParent::BroadcastThemeUpdate(widget::ThemeChangeKind aKind
) {
1599 const FullLookAndFeel
& lnf
= *RemoteLookAndFeel::ExtractData();
1600 for (auto* cp
: AllProcesses(eLive
)) {
1601 Unused
<< cp
->SendThemeChanged(lnf
, aKind
);
1606 void ContentParent::BroadcastMediaCodecsSupportedUpdate(
1607 RemoteDecodeIn aLocation
, const media::MediaCodecsSupported
& aSupported
) {
1608 // Update processes and print the support info from the given location.
1609 sCodecsSupported
[aLocation
] = aSupported
;
1610 for (auto* cp
: AllProcesses(eAll
)) {
1611 Unused
<< cp
->SendUpdateMediaCodecsSupported(aLocation
, aSupported
);
1613 nsCString supportString
;
1614 media::MCSInfo::GetMediaCodecsSupportedString(supportString
, aSupported
);
1615 LOGPDM("Broadcast support from '%s', support=%s",
1616 RemoteDecodeInToStr(aLocation
), supportString
.get());
1618 // Merge incoming support with existing support list from other locations
1619 media::MCSInfo::AddSupport(aSupported
);
1620 auto fullSupport
= media::MCSInfo::GetSupport();
1622 // Generate + save FULL support string for display in about:support
1623 supportString
.Truncate();
1624 media::MCSInfo::GetMediaCodecsSupportedString(supportString
, fullSupport
);
1625 gfx::gfxVars::SetCodecSupportInfo(supportString
);
1628 const nsACString
& ContentParent::GetRemoteType() const { return mRemoteType
; }
1630 static StaticRefPtr
<nsIAsyncShutdownClient
> sXPCOMShutdownClient
;
1631 static StaticRefPtr
<nsIAsyncShutdownClient
> sProfileBeforeChangeClient
;
1632 static StaticRefPtr
<nsIAsyncShutdownClient
> sQuitApplicationGrantedClient
;
1634 void ContentParent::Init() {
1635 MOZ_ASSERT(sXPCOMShutdownClient
);
1637 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
1639 size_t length
= ArrayLength(sObserverTopics
);
1640 for (size_t i
= 0; i
< length
; ++i
) {
1641 obs
->AddObserver(this, sObserverTopics
[i
], false);
1647 cpId
.AppendInt(static_cast<uint64_t>(this->ChildID()));
1648 obs
->NotifyObservers(static_cast<nsIObserver
*>(this), "ipc:content-created",
1652 #ifdef ACCESSIBILITY
1653 // If accessibility is running in chrome process then start it in content
1655 if (GetAccService()) {
1656 Unused
<< SendActivateA11y();
1658 #endif // #ifdef ACCESSIBILITY
1660 Unused
<< SendInitProfiler(ProfilerParent::CreateForProcess(OtherPid()));
1662 RefPtr
<GeckoMediaPluginServiceParent
> gmps(
1663 GeckoMediaPluginServiceParent::GetSingleton());
1665 gmps
->UpdateContentProcessGMPCapabilities(this);
1668 // Flush any pref updates that happened during launch and weren't
1669 // included in the blobs set up in BeginSubprocessLaunch.
1670 for (const Pref
& pref
: mQueuedPrefs
) {
1671 Unused
<< NS_WARN_IF(!SendPreferenceUpdate(pref
));
1673 mQueuedPrefs
.Clear();
1675 Unused
<< SendInitNextGenLocalStorageEnabled(NextGenLocalStorageEnabled());
1678 // Note that for E10S we can get a false here that will be overruled by
1679 // TryToRecycleE10SOnly as late as MaybeBeginShutdown. We cannot really
1680 // foresee its result here.
1681 bool ContentParent::CheckTabDestroyWillKeepAlive(
1682 uint32_t aExpectedBrowserCount
) {
1683 return ManagedPBrowserParent().Count() != aExpectedBrowserCount
||
1684 ShouldKeepProcessAlive();
1687 RecursiveMutex
& ContentParent::ThreadsafeHandleMutex() {
1688 return mThreadsafeHandle
->mMutex
;
1691 void ContentParent::NotifyTabWillDestroy() {
1692 if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed
)
1693 #if !defined(MOZ_WIDGET_ANDROID)
1694 /* on Android we keep processes alive more agressively, see
1695 NotifyTabDestroying where we omit MaybeBeginShutdown */
1696 || (/* we cannot trust CheckTabDestroyWillKeepAlive in E10S mode */
1697 mozilla::FissionAutostart() &&
1698 !CheckTabDestroyWillKeepAlive(mNumDestroyingTabs
+ 1))
1701 // Once we notify the impending shutdown, the content process will stop
1702 // to process content JS on interrupt (among other things), so we need to
1703 // be sure that the process will not be re-used after this point.
1704 // The inverse is harmless, that is if we decide later to shut it down
1705 // but did not notify here, it will be just notified later (but in rare
1706 // cases too late to avoid a hang).
1707 NotifyImpendingShutdown();
1708 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1709 mNotifiedImpendingShutdownOnTabWillDestroy
= true;
1714 void ContentParent::MaybeBeginShutDown(uint32_t aExpectedBrowserCount
,
1715 bool aSendShutDown
) {
1716 MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose
,
1717 ("MaybeBeginShutdown %p, %u vs %u", this,
1718 ManagedPBrowserParent().Count(), aExpectedBrowserCount
));
1719 MOZ_ASSERT(NS_IsMainThread());
1721 // We need to lock our mutex here to ensure the state does not change
1722 // between the check and the MarkAsDead.
1723 // Note that if we come through BrowserParent::Destroy our mutex is
1725 // TODO: We want to get rid of the ThreadsafeHandle, see bug 1683595.
1726 RecursiveMutexAutoLock
lock(mThreadsafeHandle
->mMutex
);
1728 // Both CheckTabDestroyWillKeepAlive and TryToRecycleE10SOnly will return
1729 // false if IsInOrBeyond(AppShutdownConfirmed), so if the parent shuts
1730 // down we will always shutdown the child.
1731 if (CheckTabDestroyWillKeepAlive(aExpectedBrowserCount
) ||
1732 TryToRecycleE10SOnly()) {
1737 ContentParent::GetLog(), LogLevel::Debug
,
1738 ("Beginning ContentParent Shutdown %p (%s)", this, mRemoteType
.get()));
1740 // We're dying now, prevent anything from re-using this process.
1742 SignalImpendingShutdownToContentJS();
1744 if (aSendShutDown
) {
1745 AsyncSendShutDownMessage();
1747 // aSendShutDown is false only when we get called from
1748 // NotifyTabDestroying where we expect a subsequent call from
1749 // NotifyTabDestroyed triggered by a Browser actor destroy
1750 // roundtrip through the content process that might never arrive.
1751 StartSendShutdownTimer();
1755 void ContentParent::AsyncSendShutDownMessage() {
1756 MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose
,
1757 ("AsyncSendShutDownMessage %p", this));
1758 MOZ_ASSERT(NS_IsMainThread());
1759 MOZ_ASSERT(sRecycledE10SProcess
!= this);
1761 // In the case of normal shutdown, send a shutdown message to child to
1762 // allow it to perform shutdown tasks.
1763 GetCurrentSerialEventTarget()->Dispatch(NewRunnableMethod
<ShutDownMethod
>(
1764 "dom::ContentParent::ShutDownProcess", this,
1765 &ContentParent::ShutDownProcess
, SEND_SHUTDOWN_MESSAGE
));
1768 void MaybeLogBlockShutdownDiagnostics(ContentParent
* aSelf
, const char* aMsg
,
1769 const char* aFile
, int32_t aLine
) {
1770 #if defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED)
1771 if (aSelf
->IsBlockingShutdown()) {
1772 MOZ_LOG(ContentParent::GetLog(), LogLevel::Info
,
1773 ("ContentParent: id=%p pid=%d - %s at %s(%d)", aSelf
, aSelf
->Pid(),
1774 aMsg
, aFile
, aLine
));
1784 bool ContentParent::ShutDownProcess(ShutDownMethod aMethod
) {
1785 bool result
= false;
1786 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
1787 ("ShutDownProcess: %p", this));
1788 // NB: must MarkAsDead() here so that this isn't accidentally
1789 // returned from Get*() while in the midst of shutdown.
1792 // Shutting down by sending a shutdown message works differently than the
1793 // other methods. We first call Shutdown() in the child. After the child is
1794 // ready, it calls FinishShutdown() on us. Then we close the channel.
1795 if (aMethod
== SEND_SHUTDOWN_MESSAGE
) {
1796 if (!mShutdownPending
) {
1798 // Stop sending input events with input priority when shutting down.
1799 SetInputPriorityEventEnabled(false);
1800 // If we did not earlier, let's signal the shutdown to JS now.
1801 SignalImpendingShutdownToContentJS();
1803 // Adjust the QoS priorities for shutdown, if they exist.
1804 if (StaticPrefs::threads_use_low_power_enabled() &&
1806 threads_lower_mainthread_priority_in_background_enabled()) {
1807 SetMainThreadQoSPriority(nsIThread::QOS_PRIORITY_NORMAL
);
1810 // Send a high priority announcement first. If this fails, SendShutdown
1812 Unused
<< SendShutdownConfirmedHP();
1813 // Send the definite message with normal priority.
1814 if (SendShutdown()) {
1815 MaybeLogBlockShutdownDiagnostics(
1816 this, "ShutDownProcess: Sent shutdown message.", __FILE__
,
1818 mShutdownPending
= true;
1819 // We start the kill timer only after we asked our process to
1821 StartForceKillTimer();
1824 MaybeLogBlockShutdownDiagnostics(
1825 this, "ShutDownProcess: !!! Send shutdown message failed! !!!",
1826 __FILE__
, __LINE__
);
1829 MaybeLogBlockShutdownDiagnostics(
1830 this, "ShutDownProcess: !!! !CanSend !!!", __FILE__
, __LINE__
);
1833 MaybeLogBlockShutdownDiagnostics(
1834 this, "ShutDownProcess: Shutdown already pending.", __FILE__
,
1839 // If call was not successful, the channel must have been broken
1840 // somehow, and we will clean up the error in ActorDestroy.
1844 using mozilla::dom::quota::QuotaManagerService
;
1846 if (QuotaManagerService
* qms
= QuotaManagerService::GetOrCreate()) {
1847 qms
->AbortOperationsForProcess(mChildID
);
1850 if (aMethod
== CLOSE_CHANNEL
) {
1851 if (!mCalledClose
) {
1852 MaybeLogBlockShutdownDiagnostics(
1853 this, "ShutDownProcess: Closing channel.", __FILE__
, __LINE__
);
1854 // Close() can only be called once: It kicks off the destruction sequence.
1855 mCalledClose
= true;
1861 // A ContentParent object might not get freed until after XPCOM shutdown has
1862 // shut down the cycle collector. But by then it's too late to release any
1863 // CC'ed objects, so we need to null them out here, while we still can. See
1865 ShutDownMessageManager();
1869 mozilla::ipc::IPCResult
ContentParent::RecvNotifyShutdownSuccess() {
1870 if (!mShutdownPending
) {
1871 return IPC_FAIL(this, "RecvNotifyShutdownSuccess without mShutdownPending");
1874 mIsNotifiedShutdownSuccess
= true;
1879 mozilla::ipc::IPCResult
ContentParent::RecvFinishShutdown() {
1880 if (!mShutdownPending
) {
1881 return IPC_FAIL(this, "RecvFinishShutdown without mShutdownPending");
1884 // At this point, we already called ShutDownProcess once with
1885 // SEND_SHUTDOWN_MESSAGE. To actually close the channel, we call
1886 // ShutDownProcess again with CLOSE_CHANNEL.
1888 MaybeLogBlockShutdownDiagnostics(
1889 this, "RecvFinishShutdown: Channel already closed.", __FILE__
,
1893 ShutDownProcess(CLOSE_CHANNEL
);
1897 void ContentParent::ShutDownMessageManager() {
1898 if (!mMessageManager
) {
1902 mMessageManager
->SetOsPid(-1);
1903 mMessageManager
->Disconnect();
1904 mMessageManager
= nullptr;
1907 void ContentParent::AddToPool(nsTArray
<ContentParent
*>& aPool
) {
1908 MOZ_DIAGNOSTIC_ASSERT(!mIsInPool
);
1910 MOZ_DIAGNOSTIC_ASSERT(!mCalledKillHard
);
1911 aPool
.AppendElement(this);
1915 void ContentParent::RemoveFromPool(nsTArray
<ContentParent
*>& aPool
) {
1916 MOZ_DIAGNOSTIC_ASSERT(mIsInPool
);
1917 aPool
.RemoveElement(this);
1921 void ContentParent::AssertNotInPool() {
1922 MOZ_RELEASE_ASSERT(!mIsInPool
);
1924 MOZ_RELEASE_ASSERT(sRecycledE10SProcess
!= this);
1925 MOZ_RELEASE_ASSERT(!sBrowserContentParents
||
1926 !sBrowserContentParents
->Contains(mRemoteType
) ||
1927 !sBrowserContentParents
->Get(mRemoteType
)->Contains(this));
1929 for (const auto& group
: mGroups
) {
1930 MOZ_RELEASE_ASSERT(group
->GetHostProcess(mRemoteType
) != this,
1931 "still a host process for one of our groups?");
1935 void ContentParent::AssertAlive() {
1936 MOZ_DIAGNOSTIC_ASSERT(!mNotifiedImpendingShutdownOnTabWillDestroy
);
1937 MOZ_DIAGNOSTIC_ASSERT(!mIsSignaledImpendingShutdown
);
1938 MOZ_DIAGNOSTIC_ASSERT(!IsDead());
1941 void ContentParent::RemoveFromList() {
1943 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1949 // Ensure that this BrowsingContextGroup is no longer used to host new
1950 // documents from any associated BrowsingContextGroups. It may become a host
1951 // again in the future, if it is restored to the pool.
1952 for (const auto& group
: mGroups
) {
1953 group
->RemoveHostProcess(this);
1956 StopRecyclingE10SOnly(/* aForeground */ false);
1958 if (sBrowserContentParents
) {
1959 if (auto entry
= sBrowserContentParents
->Lookup(mRemoteType
)) {
1960 const auto& contentParents
= entry
.Data();
1961 RemoveFromPool(*contentParents
);
1962 if (contentParents
->IsEmpty()) {
1966 if (sBrowserContentParents
->IsEmpty()) {
1967 delete sBrowserContentParents
;
1968 sBrowserContentParents
= nullptr;
1973 void ContentParent::MarkAsDead() {
1974 MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose
,
1975 ("Marking ContentProcess %p as dead", this));
1976 MOZ_DIAGNOSTIC_ASSERT(!sInProcessSelector
);
1979 // Flag shutdown has started for us to our threadsafe handle.
1981 // Depending on how we get here, the lock might or might not be set.
1982 RecursiveMutexAutoLock
lock(mThreadsafeHandle
->mMutex
);
1984 mThreadsafeHandle
->mShutdownStarted
= true;
1987 // Prevent this process from being re-used.
1988 PreallocatedProcessManager::Erase(this);
1989 StopRecyclingE10SOnly(false);
1991 #if defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_PROFILE_GENERATE)
1993 // We're intentionally killing the content process at this point to ensure
1994 // that we never have a "dead" content process sitting around and occupying
1995 // an Android Service.
1997 // The exception is in MOZ_PROFILE_GENERATE builds where we must allow the
1998 // process to shutdown cleanly so that profile data can be dumped. This is
1999 // okay as we will not reach our process limit during the profile run.
2000 nsCOMPtr
<nsIEventTarget
> launcherThread(GetIPCLauncher());
2001 MOZ_ASSERT(launcherThread
);
2003 auto procType
= java::GeckoProcessType::CONTENT();
2005 java::GeckoProcessManager::Selector::New(procType
, OtherPid());
2007 launcherThread
->Dispatch(NS_NewRunnableFunction(
2008 "ContentParent::MarkAsDead",
2010 java::GeckoProcessManager::Selector::GlobalRef(selector
)]() {
2011 java::GeckoProcessManager::ShutdownProcess(selector
);
2016 if (mScriptableHelper
) {
2017 static_cast<ScriptableCPInfo
*>(mScriptableHelper
.get())->ProcessDied();
2018 mScriptableHelper
= nullptr;
2021 mLifecycleState
= LifecycleState::DEAD
;
2024 void ContentParent::OnChannelError() {
2025 RefPtr
<ContentParent
> kungFuDeathGrip(this);
2026 PContentParent::OnChannelError();
2029 void ContentParent::ProcessingError(Result aCode
, const char* aReason
) {
2030 if (MsgDropped
== aCode
) {
2033 // Other errors are big deals.
2038 GetIPCChannel()->InduceConnectionError();
2042 void ContentParent::ActorDestroy(ActorDestroyReason why
) {
2043 #ifdef FUZZING_SNAPSHOT
2044 MOZ_FUZZING_IPC_DROP_PEER("ContentParent::ActorDestroy");
2047 if (mSendShutdownTimer
) {
2048 mSendShutdownTimer
->Cancel();
2049 mSendShutdownTimer
= nullptr;
2051 if (mForceKillTimer
) {
2052 mForceKillTimer
->Cancel();
2053 mForceKillTimer
= nullptr;
2056 // Signal shutdown completion regardless of error state, so we can
2057 // finish waiting in the xpcom-shutdown/profile-before-change observer.
2058 RemoveShutdownBlockers();
2060 if (mHangMonitorActor
) {
2061 ProcessHangMonitor::RemoveProcess(mHangMonitorActor
);
2062 mHangMonitorActor
= nullptr;
2065 RefPtr
<FileSystemSecurity
> fss
= FileSystemSecurity::Get();
2067 fss
->Forget(ChildID());
2070 if (why
== NormalShutdown
&& !mCalledClose
) {
2071 // If we shut down normally but haven't called Close, assume somebody
2072 // else called Close on us. In that case, we still need to call
2073 // ShutDownProcess below to perform other necessary clean up.
2074 mCalledClose
= true;
2077 // Make sure we always clean up.
2078 ShutDownProcess(CLOSE_CHANNEL
);
2080 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
2082 size_t length
= ArrayLength(sObserverTopics
);
2083 for (size_t i
= 0; i
< length
; ++i
) {
2084 obs
->RemoveObserver(static_cast<nsIObserver
*>(this), sObserverTopics
[i
]);
2088 // remove the global remote preferences observers
2089 Preferences::RemoveObserver(this, "");
2090 gfxVars::RemoveReceiver(this);
2092 if (GPUProcessManager
* gpu
= GPUProcessManager::Get()) {
2093 // Note: the manager could have shutdown already.
2094 gpu
->RemoveListener(this);
2097 RecvRemoveGeolocationListener();
2099 // Destroy our JSProcessActors, and reject any pending queries.
2100 JSActorDidDestroy();
2103 RefPtr
<nsHashPropertyBag
> props
= new nsHashPropertyBag();
2105 props
->SetPropertyAsUint64(u
"childID"_ns
, mChildID
);
2107 if (AbnormalShutdown
== why
) {
2108 Telemetry::Accumulate(Telemetry::SUBPROCESS_ABNORMAL_ABORT
, "content"_ns
,
2111 props
->SetPropertyAsBool(u
"abnormal"_ns
, true);
2113 nsAutoString dumpID
;
2114 // There's a window in which child processes can crash
2115 // after IPC is established, but before a crash reporter
2117 if (mCrashReporter
) {
2118 // if mCreatedPairedMinidumps is true, we've already generated
2119 // parent/child dumps for desktop crashes.
2120 if (!mCreatedPairedMinidumps
) {
2121 #if defined(XP_MACOSX)
2122 RefPtr
<nsAvailableMemoryWatcherBase
> memWatcher
;
2123 memWatcher
= nsAvailableMemoryWatcherBase::GetSingleton();
2124 memWatcher
->AddChildAnnotations(mCrashReporter
);
2127 mCrashReporter
->GenerateCrashReport(OtherPid());
2130 if (mCrashReporter
->HasMinidump()) {
2131 dumpID
= mCrashReporter
->MinidumpID();
2134 HandleOrphanedMinidump(&dumpID
);
2137 if (!dumpID
.IsEmpty()) {
2138 props
->SetPropertyAsAString(u
"dumpID"_ns
, dumpID
);
2142 cpId
.AppendInt(static_cast<uint64_t>(this->ChildID()));
2143 obs
->NotifyObservers((nsIPropertyBag2
*)props
, "ipc:content-shutdown",
2147 // Remove any and all idle listeners.
2148 if (mIdleListeners
.Length() > 0) {
2149 nsCOMPtr
<nsIUserIdleService
> idleService
=
2150 do_GetService("@mozilla.org/widget/useridleservice;1");
2152 RefPtr
<ParentIdleListener
> listener
;
2153 for (const auto& lentry
: mIdleListeners
) {
2154 listener
= static_cast<ParentIdleListener
*>(lentry
.get());
2155 idleService
->RemoveIdleObserver(listener
, listener
->mTime
);
2158 mIdleListeners
.Clear();
2161 MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose
,
2162 ("destroying Subprocess in ActorDestroy: ContentParent %p "
2163 "mSubprocess %p handle %" PRIuPTR
,
2165 mSubprocess
? (uintptr_t)mSubprocess
->GetChildProcessHandle() : -1));
2166 // FIXME (bug 1520997): does this really need an additional dispatch?
2167 if (GetCurrentSerialEventTarget()) {
2168 GetCurrentSerialEventTarget()->Dispatch(NS_NewRunnableFunction(
2169 "DelayedDeleteSubprocessRunnable", [subprocess
= mSubprocess
] {
2170 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
2171 ("destroyed Subprocess in ActorDestroy: Subprocess %p handle "
2174 subprocess
? (uintptr_t)subprocess
->GetChildProcessHandle()
2176 subprocess
->Destroy();
2179 mSubprocess
= nullptr;
2181 ContentProcessManager
* cpm
= ContentProcessManager::GetSingleton();
2183 cpm
->RemoveContentProcess(this->ChildID());
2186 if (mDriverCrashGuard
) {
2187 mDriverCrashGuard
->NotifyCrashed();
2190 // Unregister all the BlobURLs registered by the ContentChild.
2191 for (uint32_t i
= 0; i
< mBlobURLs
.Length(); ++i
) {
2192 BlobURLProtocolHandler::RemoveDataEntry(mBlobURLs
[i
]);
2197 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2201 // As this process is going away, ensure that every BrowsingContext hosted by
2202 // it has been detached, and every BrowsingContextGroup has been fully
2204 BrowsingContext::DiscardFromContentParent(this);
2206 const nsTHashSet
<RefPtr
<BrowsingContextGroup
>> groups
= std::move(mGroups
);
2207 for (const auto& group
: groups
) {
2208 group
->Unsubscribe(this);
2210 MOZ_DIAGNOSTIC_ASSERT(mGroups
.IsEmpty());
2212 mPendingLoadStates
.Clear();
2215 bool ContentParent::TryToRecycleE10SOnly() {
2216 // Only try to recycle "web" content processes, as other remote types are
2217 // generally more unique, and cannot be effectively re-used. This is disabled
2218 // with Fission, as "web" content processes are no longer frequently used.
2220 // Disabling the process pre-allocator will also disable process recycling,
2221 // allowing for more consistent process counts under testing.
2222 if (mRemoteType
!= DEFAULT_REMOTE_TYPE
|| mozilla::FissionAutostart() ||
2223 !PreallocatedProcessManager::Enabled()) {
2227 // This life time check should be replaced by a memory health check (memory
2228 // usage + fragmentation).
2230 // Note that this is specifically to help with edge cases that rapidly
2231 // create-and-destroy processes
2232 const double kMaxLifeSpan
= 5;
2234 ContentParent::GetLog(), LogLevel::Debug
,
2235 ("TryToRecycle ContentProcess %p (%u) with lifespan %f seconds", this,
2236 (unsigned int)ChildID(), (TimeStamp::Now() - mActivateTS
).ToSeconds()));
2238 if (mCalledKillHard
|| !IsAlive() ||
2239 (TimeStamp::Now() - mActivateTS
).ToSeconds() > kMaxLifeSpan
) {
2240 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
2241 ("TryToRecycle did not recycle %p", this));
2243 // It's possible that the process was already cached, and we're being called
2244 // from a different path, and we're now past kMaxLifeSpan (or some other).
2245 // Ensure that if we're going to kill this process we don't recycle it.
2246 StopRecyclingE10SOnly(/* aForeground */ false);
2250 if (!sRecycledE10SProcess
) {
2251 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
2252 ("TryToRecycle began recycling %p", this));
2253 sRecycledE10SProcess
= this;
2255 ProcessPriorityManager::SetProcessPriority(this,
2256 PROCESS_PRIORITY_BACKGROUND
);
2260 if (sRecycledE10SProcess
== this) {
2261 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
2262 ("TryToRecycle continue recycling %p", this));
2266 // Some other process is already being recycled, just shut this one down.
2267 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
2268 ("TryToRecycle did not recycle %p (already recycling %p)", this,
2269 sRecycledE10SProcess
.get()));
2273 void ContentParent::StopRecyclingE10SOnly(bool aForeground
) {
2274 if (sRecycledE10SProcess
!= this) {
2278 sRecycledE10SProcess
= nullptr;
2280 ProcessPriorityManager::SetProcessPriority(this,
2281 PROCESS_PRIORITY_FOREGROUND
);
2285 bool ContentParent::HasActiveWorker() {
2286 // If we have active workers, we need to stay alive.
2288 // Most of the times we'll get here with the mutex acquired, but still.
2289 RecursiveMutexAutoLock
lock(mThreadsafeHandle
->mMutex
);
2290 if (mThreadsafeHandle
->mRemoteWorkerActorCount
) {
2297 bool ContentParent::ShouldKeepProcessAlive() {
2298 if (HasActiveWorker()) {
2302 if (mNumKeepaliveCalls
> 0) {
2306 if (IsLaunching()) {
2310 // If we have already been marked as dead, don't prevent shutdown.
2315 // If everything is going down, there is no need to keep us alive, neither.
2316 if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed
)) {
2320 if (!sBrowserContentParents
) {
2324 auto contentParents
= sBrowserContentParents
->Get(mRemoteType
);
2325 if (!contentParents
) {
2329 // We might want to keep some content processes alive for performance reasons.
2330 // e.g. test runs and privileged content process for some about: pages.
2331 // We don't want to alter behavior if the pref is not set, so default to 0.
2332 int32_t processesToKeepAlive
= 0;
2334 nsAutoCString
keepAlivePref("dom.ipc.keepProcessesAlive.");
2336 if (StringBeginsWith(mRemoteType
, FISSION_WEB_REMOTE_TYPE
) &&
2337 xpc::IsInAutomation()) {
2338 keepAlivePref
.Append(FISSION_WEB_REMOTE_TYPE
);
2339 keepAlivePref
.AppendLiteral(".perOrigin");
2341 keepAlivePref
.Append(mRemoteType
);
2344 Preferences::GetInt(keepAlivePref
.get(), &processesToKeepAlive
))) {
2348 int32_t numberOfAliveProcesses
= contentParents
->Length();
2350 return numberOfAliveProcesses
<= processesToKeepAlive
;
2353 void ContentParent::NotifyTabDestroying() {
2354 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
2355 ("NotifyTabDestroying %p:", this));
2356 // There can be more than one PBrowser for a given app process
2357 // because of popup windows. PBrowsers can also destroy
2358 // concurrently. When all the PBrowsers are destroying, kick off
2359 // another task to ensure the child process *really* shuts down,
2360 // even if the PBrowsers themselves never finish destroying.
2361 ++mNumDestroyingTabs
;
2364 * We intentionally skip this code on Android:
2365 * 1. Android has a fixed upper bound on the number of content processes, so
2366 * we prefer to re-use them whenever possible (as opposed to letting an
2367 * old process wind down while we launch a new one).
2368 * 2. GeckoView always hard-kills content processes (and if it does not,
2369 * Android itself will), so we don't concern ourselves with the ForceKill
2372 #if !defined(MOZ_WIDGET_ANDROID)
2373 MaybeBeginShutDown(/* aExpectedBrowserCount */ mNumDestroyingTabs
,
2374 /* aSendShutDown */ false);
2375 #endif // !defined(MOZ_WIDGET_ANDROID)
2378 void ContentParent::AddKeepAlive() {
2380 // Something wants to keep this content process alive.
2381 ++mNumKeepaliveCalls
;
2384 void ContentParent::RemoveKeepAlive() {
2385 MOZ_DIAGNOSTIC_ASSERT(mNumKeepaliveCalls
> 0);
2386 --mNumKeepaliveCalls
;
2388 MaybeBeginShutDown();
2391 void ContentParent::StartSendShutdownTimer() {
2392 if (mSendShutdownTimer
|| !CanSend()) {
2396 uint32_t timeoutSecs
= StaticPrefs::dom_ipc_tabs_shutdownTimeoutSecs();
2397 if (timeoutSecs
> 0) {
2398 NS_NewTimerWithFuncCallback(getter_AddRefs(mSendShutdownTimer
),
2399 ContentParent::SendShutdownTimerCallback
, this,
2400 timeoutSecs
* 1000, nsITimer::TYPE_ONE_SHOT
,
2401 "dom::ContentParent::StartSendShutdownTimer");
2402 MOZ_ASSERT(mSendShutdownTimer
);
2406 void ContentParent::StartForceKillTimer() {
2407 if (mForceKillTimer
|| !CanSend()) {
2411 uint32_t timeoutSecs
= StaticPrefs::dom_ipc_tabs_shutdownTimeoutSecs();
2412 if (timeoutSecs
> 0) {
2413 NS_NewTimerWithFuncCallback(getter_AddRefs(mForceKillTimer
),
2414 ContentParent::ForceKillTimerCallback
, this,
2415 timeoutSecs
* 1000, nsITimer::TYPE_ONE_SHOT
,
2416 "dom::ContentParent::StartForceKillTimer");
2417 MOZ_ASSERT(mForceKillTimer
);
2421 void ContentParent::NotifyTabDestroyed(const TabId
& aTabId
,
2422 bool aNotifiedDestroying
) {
2423 if (aNotifiedDestroying
) {
2424 --mNumDestroyingTabs
;
2427 nsTArray
<PContentPermissionRequestParent
*> parentArray
=
2428 nsContentPermissionUtils::GetContentPermissionRequestParentById(aTabId
);
2430 // Need to close undeleted ContentPermissionRequestParents before tab is
2432 for (auto& permissionRequestParent
: parentArray
) {
2433 Unused
<< PContentPermissionRequestParent::Send__delete__(
2434 permissionRequestParent
);
2437 // There can be more than one PBrowser for a given app process
2438 // because of popup windows. When the last one closes, shut
2440 MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose
,
2441 ("NotifyTabDestroyed %p", this));
2443 MaybeBeginShutDown(/* aExpectedBrowserCount */ 1);
2446 TestShellParent
* ContentParent::CreateTestShell() {
2447 RefPtr
<TestShellParent
> actor
= new TestShellParent();
2448 if (!SendPTestShellConstructor(actor
)) {
2454 bool ContentParent::DestroyTestShell(TestShellParent
* aTestShell
) {
2455 return PTestShellParent::Send__delete__(aTestShell
);
2458 TestShellParent
* ContentParent::GetTestShellSingleton() {
2459 PTestShellParent
* p
= LoneManagedOrNullAsserts(ManagedPTestShellParent());
2460 return static_cast<TestShellParent
*>(p
);
2463 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
2464 // Append the sandbox command line parameters that are not static. i.e.,
2465 // parameters that can be different for different child processes.
2466 void ContentParent::AppendDynamicSandboxParams(
2467 std::vector
<std::string
>& aArgs
) {
2468 // For file content processes
2469 if (GetRemoteType() == FILE_REMOTE_TYPE
) {
2470 MacSandboxInfo::AppendFileAccessParam(aArgs
, true);
2474 // Generate the static sandbox command line parameters and store
2475 // them in the provided params vector to be used each time a new
2476 // content process is launched.
2477 static void CacheSandboxParams(std::vector
<std::string
>& aCachedParams
) {
2478 // This must only be called once and we should
2479 // be starting with an empty list of parameters.
2480 MOZ_ASSERT(aCachedParams
.empty());
2482 MacSandboxInfo info
;
2483 info
.type
= MacSandboxType_Content
;
2484 info
.level
= GetEffectiveContentSandboxLevel();
2487 if (Preferences::GetBool("security.sandbox.logging.enabled") ||
2488 PR_GetEnv("MOZ_SANDBOX_LOGGING")) {
2489 info
.shouldLog
= true;
2493 if (!StaticPrefs::media_cubeb_sandbox()) {
2494 info
.hasAudio
= true;
2497 // Window server access. If the disconnect-windowserver pref is not
2498 // "true" or out-of-process WebGL is not enabled, allow window server
2499 // access in the sandbox policy.
2500 if (!Preferences::GetBool(
2501 "security.sandbox.content.mac.disconnect-windowserver") ||
2502 !Preferences::GetBool("webgl.out-of-process")) {
2503 info
.hasWindowServer
= true;
2506 // .app path (normalized)
2507 nsAutoCString appPath
;
2508 if (!nsMacUtilsImpl::GetAppPath(appPath
)) {
2509 MOZ_CRASH("Failed to get app dir paths");
2511 info
.appPath
= appPath
.get();
2513 // TESTING_READ_PATH1
2514 nsAutoCString testingReadPath1
;
2515 Preferences::GetCString("security.sandbox.content.mac.testing_read_path1",
2517 if (!testingReadPath1
.IsEmpty()) {
2518 info
.testingReadPath1
= testingReadPath1
.get();
2521 // TESTING_READ_PATH2
2522 nsAutoCString testingReadPath2
;
2523 Preferences::GetCString("security.sandbox.content.mac.testing_read_path2",
2525 if (!testingReadPath2
.IsEmpty()) {
2526 info
.testingReadPath2
= testingReadPath2
.get();
2529 // TESTING_READ_PATH3, TESTING_READ_PATH4. In non-packaged builds,
2530 // these are used to whitelist the repo dir and object dir respectively.
2532 if (!mozilla::IsPackagedBuild()) {
2534 nsCOMPtr
<nsIFile
> repoDir
;
2535 rv
= nsMacUtilsImpl::GetRepoDir(getter_AddRefs(repoDir
));
2536 if (NS_FAILED(rv
)) {
2537 MOZ_CRASH("Failed to get path to repo dir");
2539 nsCString repoDirPath
;
2540 Unused
<< repoDir
->GetNativePath(repoDirPath
);
2541 info
.testingReadPath3
= repoDirPath
.get();
2544 nsCOMPtr
<nsIFile
> objDir
;
2545 rv
= nsMacUtilsImpl::GetObjDir(getter_AddRefs(objDir
));
2546 if (NS_FAILED(rv
)) {
2547 MOZ_CRASH("Failed to get path to build object dir");
2549 nsCString objDirPath
;
2550 Unused
<< objDir
->GetNativePath(objDirPath
);
2551 info
.testingReadPath4
= objDirPath
.get();
2556 // For bloat/leak logging or when a content process dies intentionally
2557 // (|NoteIntentionalCrash|) for tests, it wants to log that it did this.
2558 // Allow writing to this location.
2559 nsAutoCString bloatLogDirPath
;
2560 if (NS_SUCCEEDED(nsMacUtilsImpl::GetBloatLogDir(bloatLogDirPath
))) {
2561 info
.debugWriteDir
= bloatLogDirPath
.get();
2565 info
.AppendAsParams(aCachedParams
);
2568 // Append sandboxing command line parameters.
2569 void ContentParent::AppendSandboxParams(std::vector
<std::string
>& aArgs
) {
2570 MOZ_ASSERT(sMacSandboxParams
!= nullptr);
2572 // An empty sMacSandboxParams indicates this is the
2573 // first invocation and we don't have cached params yet.
2574 if (sMacSandboxParams
->empty()) {
2575 CacheSandboxParams(*sMacSandboxParams
);
2576 MOZ_ASSERT(!sMacSandboxParams
->empty());
2579 // Append cached arguments.
2580 aArgs
.insert(aArgs
.end(), sMacSandboxParams
->begin(),
2581 sMacSandboxParams
->end());
2583 // Append remaining arguments.
2584 AppendDynamicSandboxParams(aArgs
);
2586 #endif // XP_MACOSX && MOZ_SANDBOX
2588 bool ContentParent::BeginSubprocessLaunch(ProcessPriority aPriority
) {
2589 AUTO_PROFILER_LABEL("ContentParent::LaunchSubprocess", OTHER
);
2591 // Ensure we will not rush through our shutdown phases while launching.
2592 // LaunchSubprocessReject will remove them in case of failure,
2593 // otherwise ActorDestroy will take care.
2594 AddShutdownBlockers();
2596 if (!ContentProcessManager::GetSingleton()) {
2597 MOZ_ASSERT(false, "Unable to acquire ContentProcessManager singleton!");
2601 std::vector
<std::string
> extraArgs
;
2602 geckoargs::sChildID
.Put(mChildID
, extraArgs
);
2603 geckoargs::sIsForBrowser
.Put(IsForBrowser(), extraArgs
);
2604 geckoargs::sNotForBrowser
.Put(!IsForBrowser(), extraArgs
);
2606 // Prefs information is passed via anonymous shared memory to avoid bloating
2607 // the command line.
2609 // Instantiate the pref serializer. It will be cleaned up in
2610 // `LaunchSubprocessReject`/`LaunchSubprocessResolve`.
2611 mPrefSerializer
= MakeUnique
<mozilla::ipc::SharedPreferenceSerializer
>();
2612 if (!mPrefSerializer
->SerializeToSharedMemory(GeckoProcessType_Content
,
2614 NS_WARNING("SharedPreferenceSerializer::SerializeToSharedMemory failed");
2618 mPrefSerializer
->AddSharedPrefCmdLineArgs(*mSubprocess
, extraArgs
);
2620 // The JS engine does some computation during the initialization which can be
2621 // shared across processes. We add command line arguments to pass a file
2622 // handle and its content length, to minimize the startup time of content
2624 ::mozilla::ipc::ExportSharedJSInit(*mSubprocess
, extraArgs
);
2626 // Register ContentParent as an observer for changes to any pref
2627 // whose prefix matches the empty string, i.e. all of them. The
2628 // observation starts here in order to capture pref updates that
2629 // happen during async launch.
2630 Preferences::AddStrongObserver(this, "");
2633 geckoargs::sSafeMode
.Put(extraArgs
);
2636 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
2637 if (IsContentSandboxEnabled()) {
2638 AppendSandboxParams(extraArgs
);
2639 mSubprocess
->DisableOSActivityMode();
2643 nsCString
parentBuildID(mozilla::PlatformBuildID());
2644 geckoargs::sParentBuildID
.Put(parentBuildID
.get(), extraArgs
);
2646 #ifdef MOZ_WIDGET_GTK
2647 // This is X11-only pending a solution for WebGL in Wayland mode.
2648 if (StaticPrefs::dom_ipc_avoid_gtk() &&
2649 StaticPrefs::widget_non_native_theme_enabled() &&
2650 widget::GdkIsX11Display()) {
2651 mSubprocess
->SetEnv("MOZ_HEADLESS", "1");
2655 mLaunchYieldTS
= TimeStamp::Now();
2656 return mSubprocess
->AsyncLaunch(std::move(extraArgs
));
2659 void ContentParent::LaunchSubprocessReject() {
2660 NS_WARNING("failed to launch child in the parent");
2661 MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose
,
2662 ("failed to launch child in the parent"));
2663 // Now that communication with the child is complete, we can cleanup
2664 // the preference serializer.
2665 mPrefSerializer
= nullptr;
2666 if (mIsAPreallocBlocker
) {
2667 PreallocatedProcessManager::RemoveBlocker(mRemoteType
, this);
2668 mIsAPreallocBlocker
= false;
2671 RemoveShutdownBlockers();
2674 bool ContentParent::LaunchSubprocessResolve(bool aIsSync
,
2675 ProcessPriority aPriority
) {
2676 AUTO_PROFILER_LABEL("ContentParent::LaunchSubprocess::resolve", OTHER
);
2678 if (mLaunchResolved
) {
2679 // We've already been called, return.
2680 MOZ_ASSERT(sCreatedFirstContentProcess
);
2681 MOZ_ASSERT(!mPrefSerializer
);
2682 MOZ_ASSERT(mLifecycleState
!= LifecycleState::LAUNCHING
);
2683 return mLaunchResolvedOk
;
2685 mLaunchResolved
= true;
2687 // Now that communication with the child is complete, we can cleanup
2688 // the preference serializer.
2689 mPrefSerializer
= nullptr;
2691 const auto launchResumeTS
= TimeStamp::Now();
2692 if (profiler_thread_is_being_profiled_for_markers()) {
2693 nsPrintfCString
marker("Process start%s for %u",
2694 mIsAPreallocBlocker
? " (immediate)" : "",
2695 (unsigned int)ChildID());
2696 PROFILER_MARKER_TEXT(
2697 mIsAPreallocBlocker
? ProfilerString8View("Process Immediate Launch")
2698 : ProfilerString8View("Process Launch"),
2699 DOM
, MarkerTiming::Interval(mLaunchTS
, launchResumeTS
), marker
);
2702 if (!sCreatedFirstContentProcess
) {
2703 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
2704 obs
->NotifyObservers(nullptr, "ipc:first-content-process-created", nullptr);
2705 sCreatedFirstContentProcess
= true;
2708 mSubprocess
->TakeInitialEndpoint().Bind(this);
2710 ContentProcessManager
* cpm
= ContentProcessManager::GetSingleton();
2712 NS_WARNING("immediately shutting-down caused by our shutdown");
2713 ShutDownProcess(SEND_SHUTDOWN_MESSAGE
);
2716 cpm
->AddContentProcess(this);
2718 #ifdef MOZ_CODE_COVERAGE
2719 Unused
<< SendShareCodeCoverageMutex(
2720 CodeCoverageHandler::Get()->GetMutexHandle());
2723 // We must be in the LAUNCHING state still. If we've somehow already been
2724 // marked as DEAD, fail the process launch, and immediately begin tearing down
2725 // the content process.
2727 NS_WARNING("immediately shutting-down already-dead process");
2728 ShutDownProcess(SEND_SHUTDOWN_MESSAGE
);
2731 MOZ_ASSERT(mLifecycleState
== LifecycleState::LAUNCHING
);
2732 mLifecycleState
= LifecycleState::ALIVE
;
2734 if (!InitInternal(aPriority
)) {
2735 NS_WARNING("failed to initialize child in the parent");
2736 // We've already called Open() by this point, so we need to close the
2737 // channel to avoid leaking the process.
2738 ShutDownProcess(SEND_SHUTDOWN_MESSAGE
);
2742 mHangMonitorActor
= ProcessHangMonitor::AddProcess(this);
2744 // Set a reply timeout for CPOWs.
2745 SetReplyTimeoutMs(StaticPrefs::dom_ipc_cpow_timeout());
2747 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
2750 cpId
.AppendInt(static_cast<uint64_t>(this->ChildID()));
2751 obs
->NotifyObservers(static_cast<nsIObserver
*>(this),
2752 "ipc:content-initializing", cpId
.get());
2757 mLifecycleState
= LifecycleState::INITIALIZED
;
2760 Telemetry::AccumulateTimeDelta(Telemetry::CONTENT_PROCESS_SYNC_LAUNCH_MS
,
2763 Telemetry::AccumulateTimeDelta(Telemetry::CONTENT_PROCESS_LAUNCH_TOTAL_MS
,
2766 Telemetry::Accumulate(
2767 Telemetry::CONTENT_PROCESS_LAUNCH_MAINTHREAD_MS
,
2768 static_cast<uint32_t>(
2769 ((mLaunchYieldTS
- mLaunchTS
) + (TimeStamp::Now() - launchResumeTS
))
2770 .ToMilliseconds()));
2773 mLaunchResolvedOk
= true;
2777 bool ContentParent::LaunchSubprocessSync(
2778 hal::ProcessPriority aInitialPriority
) {
2779 // We've started a sync content process launch.
2780 Telemetry::Accumulate(Telemetry::CONTENT_PROCESS_LAUNCH_IS_SYNC
, 1);
2782 if (BeginSubprocessLaunch(aInitialPriority
)) {
2783 const bool ok
= mSubprocess
->WaitForProcessHandle();
2784 if (ok
&& LaunchSubprocessResolve(/* aIsSync = */ true, aInitialPriority
)) {
2788 LaunchSubprocessReject();
2792 RefPtr
<ContentParent::LaunchPromise
> ContentParent::LaunchSubprocessAsync(
2793 hal::ProcessPriority aInitialPriority
) {
2794 // We've started an async content process launch.
2795 Telemetry::Accumulate(Telemetry::CONTENT_PROCESS_LAUNCH_IS_SYNC
, 0);
2797 if (!BeginSubprocessLaunch(aInitialPriority
)) {
2798 // Launch aborted because of shutdown. Bailout.
2799 LaunchSubprocessReject();
2800 return LaunchPromise::CreateAndReject(NS_ERROR_ILLEGAL_DURING_SHUTDOWN
,
2804 // Otherwise, wait until the process is ready.
2805 RefPtr
<ProcessHandlePromise
> ready
= mSubprocess
->WhenProcessHandleReady();
2806 RefPtr
<ContentParent
> self
= this;
2807 mLaunchYieldTS
= TimeStamp::Now();
2810 GetCurrentSerialEventTarget(), __func__
,
2811 [self
, aInitialPriority
](
2812 const ProcessHandlePromise::ResolveOrRejectValue
& aValue
) {
2813 if (aValue
.IsResolve() &&
2814 self
->LaunchSubprocessResolve(/* aIsSync = */ false,
2815 aInitialPriority
)) {
2816 return LaunchPromise::CreateAndResolve(self
, __func__
);
2818 self
->LaunchSubprocessReject();
2819 return LaunchPromise::CreateAndReject(NS_ERROR_FAILURE
, __func__
);
2823 ContentParent::ContentParent(const nsACString
& aRemoteType
)
2824 : mSubprocess(nullptr),
2825 mLaunchTS(TimeStamp::Now()),
2826 mLaunchYieldTS(mLaunchTS
),
2827 mActivateTS(mLaunchTS
),
2828 mIsAPreallocBlocker(false),
2829 mRemoteType(aRemoteType
),
2830 mChildID(gContentChildID
++),
2831 mGeolocationWatchID(-1),
2833 new ThreadsafeContentParentHandle(this, mChildID
, mRemoteType
)),
2834 mNumDestroyingTabs(0),
2835 mNumKeepaliveCalls(0),
2836 mLifecycleState(LifecycleState::LAUNCHING
),
2837 mIsForBrowser(!mRemoteType
.IsEmpty()),
2838 mCalledClose(false),
2839 mCalledKillHard(false),
2840 mCreatedPairedMinidumps(false),
2841 mShutdownPending(false),
2842 mLaunchResolved(false),
2843 mLaunchResolvedOk(false),
2844 mIsRemoteInputEventQueueEnabled(false),
2845 mIsInputPriorityEventEnabled(false),
2848 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
2849 mBlockShutdownCalled(false),
2851 mHangMonitorActor(nullptr) {
2852 mRemoteTypeIsolationPrincipal
=
2853 CreateRemoteTypeIsolationPrincipal(aRemoteType
);
2855 // Insert ourselves into the global linked list of ContentParent objects.
2856 if (!sContentParents
) {
2857 sContentParents
= new LinkedList
<ContentParent
>();
2859 sContentParents
->insertBack(this);
2861 mMessageManager
= nsFrameMessageManager::NewProcessMessageManager(true);
2864 // Request Windows message deferral behavior on our side of the PContent
2865 // channel. Generally only applies to the situation where we get caught in
2866 // a deadlock with the plugin process when sending CPOWs.
2867 GetIPCChannel()->SetChannelFlags(
2868 MessageChannel::REQUIRE_DEFERRED_MESSAGE_PROTECTION
);
2871 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
2872 bool isFile
= mRemoteType
== FILE_REMOTE_TYPE
;
2873 mSubprocess
= new GeckoChildProcessHost(GeckoProcessType_Content
, isFile
);
2874 MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose
,
2875 ("CreateSubprocess: ContentParent %p mSubprocess %p handle %" PRIuPTR
,
2877 mSubprocess
? (uintptr_t)mSubprocess
->GetChildProcessHandle() : -1));
2879 // This is safe to do in the constructor, as it doesn't take a strong
2881 mScriptableHelper
= new ScriptableCPInfo(this);
2884 ContentParent::~ContentParent() {
2885 if (mSendShutdownTimer
) {
2886 mSendShutdownTimer
->Cancel();
2888 if (mForceKillTimer
) {
2889 mForceKillTimer
->Cancel();
2892 AssertIsOnMainThread();
2894 // Clear the weak reference from the threadsafe handle back to this actor.
2895 mThreadsafeHandle
->mWeakActor
= nullptr;
2897 if (mIsAPreallocBlocker
) {
2898 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
2899 ("Removing blocker on ContentProcess destruction"));
2900 PreallocatedProcessManager::RemoveBlocker(mRemoteType
, this);
2901 mIsAPreallocBlocker
= false;
2904 // We should be removed from all these lists in ActorDestroy.
2907 // Normally mSubprocess is destroyed in ActorDestroy, but that won't
2908 // happen if the process wasn't launched or if it failed to launch.
2911 ContentParent::GetLog(), LogLevel::Verbose
,
2912 ("DestroySubprocess: ContentParent %p mSubprocess %p handle %" PRIuPTR
,
2914 mSubprocess
? (uintptr_t)mSubprocess
->GetChildProcessHandle() : -1));
2915 mSubprocess
->Destroy();
2918 // Make sure to clear the connection from `mScriptableHelper` if it hasn't
2919 // been cleared yet.
2920 if (mScriptableHelper
) {
2921 static_cast<ScriptableCPInfo
*>(mScriptableHelper
.get())->ProcessDied();
2922 mScriptableHelper
= nullptr;
2926 bool ContentParent::InitInternal(ProcessPriority aInitialPriority
) {
2927 // We can't access the locale service after shutdown has started. Since we
2928 // can't init the process without it, and since we're going to be canceling
2929 // whatever load attempt that initiated this process creation anyway, just
2930 // bail out now if shutdown has already started.
2931 if (PastShutdownPhase(ShutdownPhase::XPCOMShutdown
)) {
2935 XPCOMInitData xpcomInit
;
2937 MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug
,
2938 ("ContentParent::InitInternal: %p", (void*)this));
2939 nsCOMPtr
<nsIIOService
> io(do_GetIOService());
2940 MOZ_ASSERT(io
, "No IO service?");
2941 DebugOnly
<nsresult
> rv
= io
->GetOffline(&xpcomInit
.isOffline());
2942 MOZ_ASSERT(NS_SUCCEEDED(rv
), "Failed getting offline?");
2944 rv
= io
->GetConnectivity(&xpcomInit
.isConnected());
2945 MOZ_ASSERT(NS_SUCCEEDED(rv
), "Failed getting connectivity?");
2947 xpcomInit
.captivePortalState() = nsICaptivePortalService::UNKNOWN
;
2948 nsCOMPtr
<nsICaptivePortalService
> cps
=
2949 do_GetService(NS_CAPTIVEPORTAL_CONTRACTID
);
2951 cps
->GetState(&xpcomInit
.captivePortalState());
2954 if (StaticPrefs::fission_processProfileName()) {
2955 nsCOMPtr
<nsIToolkitProfileService
> profileSvc
=
2956 do_GetService(NS_PROFILESERVICE_CONTRACTID
);
2958 nsCOMPtr
<nsIToolkitProfile
> currentProfile
;
2960 profileSvc
->GetCurrentProfile(getter_AddRefs(currentProfile
));
2961 if (NS_SUCCEEDED(rv
) && currentProfile
) {
2962 currentProfile
->GetName(mProfile
);
2967 nsIBidiKeyboard
* bidi
= nsContentUtils::GetBidiKeyboard();
2969 xpcomInit
.isLangRTL() = false;
2970 xpcomInit
.haveBidiKeyboards() = false;
2972 bidi
->IsLangRTL(&xpcomInit
.isLangRTL());
2973 bidi
->GetHaveBidiKeyboards(&xpcomInit
.haveBidiKeyboards());
2976 RefPtr
<mozSpellChecker
> spellChecker(mozSpellChecker::Create());
2977 MOZ_ASSERT(spellChecker
, "No spell checker?");
2979 spellChecker
->GetDictionaryList(&xpcomInit
.dictionaries());
2981 LocaleService::GetInstance()->GetAppLocalesAsBCP47(xpcomInit
.appLocales());
2982 LocaleService::GetInstance()->GetRequestedLocales(
2983 xpcomInit
.requestedLocales());
2985 L10nRegistry::GetParentProcessFileSourceDescriptors(
2986 xpcomInit
.l10nFileSources());
2988 nsCOMPtr
<nsIClipboard
> clipboard(
2989 do_GetService("@mozilla.org/widget/clipboard;1"));
2990 MOZ_ASSERT(clipboard
, "No clipboard?");
2992 clipboard
->IsClipboardTypeSupported(nsIClipboard::kGlobalClipboard
),
2993 "We should always support the global clipboard.");
2995 xpcomInit
.clipboardCaps().supportsSelectionClipboard() =
2996 clipboard
->IsClipboardTypeSupported(nsIClipboard::kSelectionClipboard
);
2998 xpcomInit
.clipboardCaps().supportsFindClipboard() =
2999 clipboard
->IsClipboardTypeSupported(nsIClipboard::kFindClipboard
);
3001 xpcomInit
.clipboardCaps().supportsSelectionCache() =
3002 clipboard
->IsClipboardTypeSupported(nsIClipboard::kSelectionCache
);
3004 // Let's copy the domain policy from the parent to the child (if it's active).
3005 StructuredCloneData initialData
;
3006 nsIScriptSecurityManager
* ssm
= nsContentUtils::GetSecurityManager();
3008 ssm
->CloneDomainPolicy(&xpcomInit
.domainPolicy());
3010 if (ParentProcessMessageManager
* mm
=
3011 nsFrameMessageManager::sParentProcessManager
) {
3013 if (NS_WARN_IF(!jsapi
.Init(xpc::PrivilegedJunkScope()))) {
3016 JS::Rooted
<JS::Value
> init(jsapi
.cx());
3017 // We'll crash on failure, so use a IgnoredErrorResult (which also
3018 // auto-suppresses exceptions).
3019 IgnoredErrorResult rv
;
3020 mm
->GetInitialProcessData(jsapi
.cx(), &init
, rv
);
3021 if (NS_WARN_IF(rv
.Failed())) {
3025 initialData
.Write(jsapi
.cx(), init
, rv
);
3026 if (NS_WARN_IF(rv
.Failed())) {
3031 // This is only implemented (returns a non-empty list) by MacOSX and Linux
3033 SystemFontList fontList
;
3034 gfxPlatform::GetPlatform()->ReadSystemFontList(&fontList
);
3036 const FullLookAndFeel
& lnf
= *RemoteLookAndFeel::ExtractData();
3038 // If the shared fontlist is in use, collect its shmem block handles to pass
3040 nsTArray
<SharedMemoryHandle
> sharedFontListBlocks
;
3041 gfxPlatformFontList::PlatformFontList()->ShareFontListToProcess(
3042 &sharedFontListBlocks
, OtherPid());
3044 // Content processes have no permission to access profile directory, so we
3045 // send the file URL instead.
3046 auto* sheetCache
= GlobalStyleSheetCache::Singleton();
3047 if (StyleSheet
* ucs
= sheetCache
->GetUserContentSheet()) {
3048 xpcomInit
.userContentSheetURL() = ucs
->GetSheetURI();
3050 xpcomInit
.userContentSheetURL() = nullptr;
3053 // 1. Build ContentDeviceData first, as it may affect some gfxVars.
3054 gfxPlatform::GetPlatform()->BuildContentDeviceData(
3055 &xpcomInit
.contentDeviceData());
3056 // 2. Gather non-default gfxVars.
3057 xpcomInit
.gfxNonDefaultVarUpdates() = gfxVars::FetchNonDefaultVars();
3058 // 3. Start listening for gfxVars updates, to notify content process later on.
3059 gfxVars::AddReceiver(this);
3061 nsCOMPtr
<nsIGfxInfo
> gfxInfo
= components::GfxInfo::Service();
3063 GfxInfoBase
* gfxInfoRaw
= static_cast<GfxInfoBase
*>(gfxInfo
.get());
3064 xpcomInit
.gfxFeatureStatus() = gfxInfoRaw
->GetAllFeatures();
3067 // Send the dynamic scalar definitions to the new process.
3068 TelemetryIPC::GetDynamicScalarDefinitions(xpcomInit
.dynamicScalarDefs());
3070 for (auto const& [location
, supported
] : sCodecsSupported
) {
3071 Unused
<< SendUpdateMediaCodecsSupported(location
, supported
);
3074 #ifdef MOZ_WIDGET_ANDROID
3075 if (!(StaticPrefs::media_utility_process_enabled() &&
3076 StaticPrefs::media_utility_android_media_codec_enabled())) {
3077 Unused
<< SendDecoderSupportedMimeTypes(
3078 AndroidDecoderModule::GetSupportedMimeTypesPrefixed());
3082 // Must send screen info before send initialData
3083 ScreenManager
& screenManager
= ScreenManager::GetSingleton();
3084 screenManager
.CopyScreensToRemote(this);
3086 // Send the UA sheet shared memory buffer and the address it is mapped at.
3087 Maybe
<SharedMemoryHandle
> sharedUASheetHandle
;
3088 uintptr_t sharedUASheetAddress
= sheetCache
->GetSharedMemoryAddress();
3090 if (SharedMemoryHandle handle
= sheetCache
->CloneHandle()) {
3091 sharedUASheetHandle
.emplace(std::move(handle
));
3093 sharedUASheetAddress
= 0;
3096 bool isReadyForBackgroundProcessing
= false;
3098 RefPtr
<DllServices
> dllSvc(DllServices::Get());
3099 isReadyForBackgroundProcessing
= dllSvc
->IsReadyForBackgroundProcessing();
3102 xpcomInit
.perfStatsMask() = PerfStats::GetCollectionMask();
3104 nsCOMPtr
<nsIDNSService
> dns
= do_GetService(NS_DNSSERVICE_CONTRACTID
);
3105 dns
->GetTrrDomain(xpcomInit
.trrDomain());
3107 nsIDNSService::ResolverMode mode
;
3108 dns
->GetCurrentTrrMode(&mode
);
3109 xpcomInit
.trrMode() = mode
;
3110 xpcomInit
.trrModeFromPref() =
3111 static_cast<nsIDNSService::ResolverMode
>(StaticPrefs::network_trr_mode());
3113 Unused
<< SendSetXPCOMProcessAttributes(
3114 xpcomInit
, initialData
, lnf
, fontList
, std::move(sharedUASheetHandle
),
3115 sharedUASheetAddress
, std::move(sharedFontListBlocks
),
3116 isReadyForBackgroundProcessing
);
3118 ipc::WritableSharedMap
* sharedData
=
3119 nsFrameMessageManager::sParentProcessManager
->SharedData();
3120 sharedData
->Flush();
3121 sharedData
->SendTo(this);
3123 nsCOMPtr
<nsIChromeRegistry
> registrySvc
= nsChromeRegistry::GetService();
3124 nsChromeRegistryChrome
* chromeRegistry
=
3125 static_cast<nsChromeRegistryChrome
*>(registrySvc
.get());
3126 chromeRegistry
->SendRegisteredChrome(this);
3128 nsCOMPtr
<nsIStringBundleService
> stringBundleService
=
3129 components::StringBundle::Service();
3130 stringBundleService
->SendContentBundles(this);
3133 nsCString
version(gAppData
->version
);
3134 nsCString
buildID(gAppData
->buildID
);
3135 nsCString
name(gAppData
->name
);
3136 nsCString
UAName(gAppData
->UAName
);
3137 nsCString
ID(gAppData
->ID
);
3138 nsCString
vendor(gAppData
->vendor
);
3139 nsCString
sourceURL(gAppData
->sourceURL
);
3140 nsCString
updateURL(gAppData
->updateURL
);
3142 // Sending all information to content process.
3143 Unused
<< SendAppInfo(version
, buildID
, name
, UAName
, ID
, vendor
, sourceURL
,
3147 // Send the child its remote type. On Mac, this needs to be sent prior
3148 // to the message we send to enable the Sandbox (SendStartProcessSandbox)
3149 // because different remote types require different sandbox privileges.
3151 Unused
<< SendRemoteType(mRemoteType
, mProfile
);
3153 ScriptPreloader::InitContentChild(*this);
3155 // Initialize the message manager (and load delayed scripts) now that we
3156 // have established communications with the child.
3157 mMessageManager
->InitWithCallback(this);
3158 mMessageManager
->SetOsPid(Pid());
3160 // Set the subprocess's priority. We do this early on because we're likely
3161 // /lowering/ the process's CPU and memory priority, which it has inherited
3162 // from this process.
3164 // This call can cause us to send IPC messages to the child process, so it
3165 // must come after the Open() call above.
3166 ProcessPriorityManager::SetProcessPriority(this, aInitialPriority
);
3168 // NB: internally, this will send an IPC message to the child
3169 // process to get it to create the CompositorBridgeChild. This
3170 // message goes through the regular IPC queue for this
3171 // channel, so delivery will happen-before any other messages
3172 // we send. The CompositorBridgeChild must be created before any
3173 // PBrowsers are created, because they rely on the Compositor
3174 // already being around. (Creation is async, so can't happen
3176 GPUProcessManager
* gpm
= GPUProcessManager::Get();
3178 Endpoint
<PCompositorManagerChild
> compositor
;
3179 Endpoint
<PImageBridgeChild
> imageBridge
;
3180 Endpoint
<PVRManagerChild
> vrBridge
;
3181 Endpoint
<PRemoteDecoderManagerChild
> videoManager
;
3182 AutoTArray
<uint32_t, 3> namespaces
;
3184 if (!gpm
->CreateContentBridges(OtherPid(), &compositor
, &imageBridge
,
3185 &vrBridge
, &videoManager
, mChildID
,
3187 // This can fail if we've already started shutting down the compositor
3188 // thread. See Bug 1562763 comment 8.
3189 MOZ_ASSERT(AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdown
));
3193 Unused
<< SendInitRendering(std::move(compositor
), std::move(imageBridge
),
3194 std::move(vrBridge
), std::move(videoManager
),
3197 gpm
->AddListener(this);
3199 nsStyleSheetService
* sheetService
= nsStyleSheetService::GetInstance();
3201 // This looks like a lot of work, but in a normal browser session we just
3204 // The URIs of the Gecko and Servo sheets should be the same, so it
3205 // shouldn't matter which we look at.
3207 for (StyleSheet
* sheet
: *sheetService
->AgentStyleSheets()) {
3208 Unused
<< SendLoadAndRegisterSheet(sheet
->GetSheetURI(),
3209 nsIStyleSheetService::AGENT_SHEET
);
3212 for (StyleSheet
* sheet
: *sheetService
->UserStyleSheets()) {
3213 Unused
<< SendLoadAndRegisterSheet(sheet
->GetSheetURI(),
3214 nsIStyleSheetService::USER_SHEET
);
3217 for (StyleSheet
* sheet
: *sheetService
->AuthorStyleSheets()) {
3218 Unused
<< SendLoadAndRegisterSheet(sheet
->GetSheetURI(),
3219 nsIStyleSheetService::AUTHOR_SHEET
);
3224 bool shouldSandbox
= true;
3225 Maybe
<FileDescriptor
> brokerFd
;
3226 // XXX: Checking the pref here makes it possible to enable/disable sandboxing
3227 // during an active session. Currently the pref is only used for testing
3228 // purpose. If the decision is made to permanently rely on the pref, this
3229 // should be changed so that it is required to restart firefox for the change
3230 // of value to take effect. Always send SetProcessSandbox message on macOS.
3231 # if !defined(XP_MACOSX)
3232 shouldSandbox
= IsContentSandboxEnabled();
3236 if (shouldSandbox
) {
3237 MOZ_ASSERT(!mSandboxBroker
);
3238 bool isFileProcess
= mRemoteType
== FILE_REMOTE_TYPE
;
3239 UniquePtr
<SandboxBroker::Policy
> policy
=
3240 sSandboxBrokerPolicyFactory
->GetContentPolicy(Pid(), isFileProcess
);
3242 brokerFd
= Some(FileDescriptor());
3244 SandboxBroker::Create(std::move(policy
), Pid(), brokerFd
.ref());
3245 if (!mSandboxBroker
) {
3246 KillHard("SandboxBroker::Create failed");
3249 MOZ_ASSERT(brokerFd
.ref().IsValid());
3253 if (shouldSandbox
&& !SendSetProcessSandbox(brokerFd
)) {
3254 KillHard("SandboxInitFailed");
3258 // Ensure that the default set of permissions are avaliable in the content
3259 // process before we try to load any URIs in it.
3261 // NOTE: All default permissions has to be transmitted to the child process
3262 // before the blob urls in the for loop below (See Bug 1738713 comment 12).
3263 EnsurePermissionsByKey(""_ns
, ""_ns
);
3266 nsTArray
<BlobURLRegistrationData
> registrations
;
3267 BlobURLProtocolHandler::ForEachBlobURL([&](BlobImpl
* aBlobImpl
,
3268 nsIPrincipal
* aPrincipal
,
3269 const nsCString
& aPartitionKey
,
3270 const nsACString
& aURI
,
3272 // We send all moz-extension Blob URL's to all content processes
3273 // because content scripts mean that a moz-extension can live in any
3274 // process. Same thing for system principal Blob URLs. Content Blob
3275 // URL's are sent for content principals on-demand by
3276 // AboutToLoadHttpDocumentForChild and RemoteWorkerManager.
3277 if (!BlobURLProtocolHandler::IsBlobURLBroadcastPrincipal(aPrincipal
)) {
3282 nsresult rv
= IPCBlobUtils::Serialize(aBlobImpl
, ipcBlob
);
3283 if (NS_WARN_IF(NS_FAILED(rv
))) {
3287 registrations
.AppendElement(
3288 BlobURLRegistrationData(nsCString(aURI
), ipcBlob
, aPrincipal
,
3289 nsCString(aPartitionKey
), aRevoked
));
3291 rv
= TransmitPermissionsForPrincipal(aPrincipal
);
3292 Unused
<< NS_WARN_IF(NS_FAILED(rv
));
3296 if (!registrations
.IsEmpty()) {
3297 Unused
<< SendInitBlobURLs(registrations
);
3301 // Send down { Parent, Window }ActorOptions at startup to content process.
3302 RefPtr
<JSActorService
> actorSvc
= JSActorService::GetSingleton();
3304 nsTArray
<JSProcessActorInfo
> contentInfos
;
3305 actorSvc
->GetJSProcessActorInfos(contentInfos
);
3307 nsTArray
<JSWindowActorInfo
> windowInfos
;
3308 actorSvc
->GetJSWindowActorInfos(windowInfos
);
3310 Unused
<< SendInitJSActorInfos(contentInfos
, windowInfos
);
3313 // Begin subscribing to any BrowsingContextGroups which were hosted by this
3314 // process before it finished launching.
3315 for (const auto& group
: mGroups
) {
3316 group
->Subscribe(this);
3319 MaybeEnableRemoteInputEventQueue();
3324 bool ContentParent::IsAlive() const {
3325 return mLifecycleState
== LifecycleState::ALIVE
||
3326 mLifecycleState
== LifecycleState::INITIALIZED
;
3329 bool ContentParent::IsInitialized() const {
3330 return mLifecycleState
== LifecycleState::INITIALIZED
;
3333 int32_t ContentParent::Pid() const {
3337 auto pid
= mSubprocess
->GetChildProcessId();
3341 return ReleaseAssertedCast
<int32_t>(pid
);
3344 void ContentParent::OnCompositorUnexpectedShutdown() {
3345 GPUProcessManager
* gpm
= GPUProcessManager::Get();
3347 Endpoint
<PCompositorManagerChild
> compositor
;
3348 Endpoint
<PImageBridgeChild
> imageBridge
;
3349 Endpoint
<PVRManagerChild
> vrBridge
;
3350 Endpoint
<PRemoteDecoderManagerChild
> videoManager
;
3351 AutoTArray
<uint32_t, 3> namespaces
;
3353 if (!gpm
->CreateContentBridges(OtherPid(), &compositor
, &imageBridge
,
3354 &vrBridge
, &videoManager
, mChildID
,
3356 MOZ_ASSERT(AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdown
));
3360 Unused
<< SendReinitRendering(std::move(compositor
), std::move(imageBridge
),
3361 std::move(vrBridge
), std::move(videoManager
),
3365 void ContentParent::OnCompositorDeviceReset() {
3366 Unused
<< SendReinitRenderingForDeviceReset();
3369 void ContentParent::MaybeEnableRemoteInputEventQueue() {
3370 MOZ_ASSERT(!mIsRemoteInputEventQueueEnabled
);
3371 if (!IsInputEventQueueSupported()) {
3374 mIsRemoteInputEventQueueEnabled
= true;
3375 Unused
<< SendSetInputEventQueueEnabled();
3376 SetInputPriorityEventEnabled(true);
3379 void ContentParent::SetInputPriorityEventEnabled(bool aEnabled
) {
3380 if (!IsInputEventQueueSupported() || !mIsRemoteInputEventQueueEnabled
||
3381 mIsInputPriorityEventEnabled
== aEnabled
) {
3384 mIsInputPriorityEventEnabled
= aEnabled
;
3385 // Send IPC messages to flush the pending events in the input event queue and
3386 // the normal event queue. See PContent.ipdl for more details.
3387 Unused
<< SendSuspendInputEventQueue();
3388 Unused
<< SendFlushInputEventQueue();
3389 Unused
<< SendResumeInputEventQueue();
3393 bool ContentParent::IsInputEventQueueSupported() {
3394 static bool sSupported
= false;
3395 static bool sInitialized
= false;
3396 if (!sInitialized
) {
3397 MOZ_ASSERT(Preferences::IsServiceAvailable());
3398 sSupported
= Preferences::GetBool("input_event_queue.supported", false);
3399 sInitialized
= true;
3404 void ContentParent::OnVarChanged(const GfxVarUpdate
& aVar
) {
3408 Unused
<< SendVarUpdate(aVar
);
3411 mozilla::ipc::IPCResult
ContentParent::RecvSetClipboard(
3412 const IPCTransferable
& aTransferable
, const int32_t& aWhichClipboard
) {
3413 // aRequestingPrincipal is allowed to be nullptr here.
3415 if (!ValidatePrincipal(aTransferable
.requestingPrincipal(),
3416 {ValidatePrincipalOptions::AllowNullPtr
,
3417 ValidatePrincipalOptions::AllowExpanded
,
3418 ValidatePrincipalOptions::AllowSystem
})) {
3419 LogAndAssertFailedPrincipalValidationInfo(
3420 aTransferable
.requestingPrincipal(), __func__
);
3424 nsCOMPtr
<nsIClipboard
> clipboard(do_GetService(kCClipboardCID
, &rv
));
3425 NS_ENSURE_SUCCESS(rv
, IPC_OK());
3427 nsCOMPtr
<nsITransferable
> trans
=
3428 do_CreateInstance("@mozilla.org/widget/transferable;1", &rv
);
3429 NS_ENSURE_SUCCESS(rv
, IPC_OK());
3430 trans
->Init(nullptr);
3432 rv
= nsContentUtils::IPCTransferableToTransferable(
3433 aTransferable
, true /* aAddDataFlavor */, trans
,
3434 true /* aFilterUnknownFlavors */);
3435 NS_ENSURE_SUCCESS(rv
, IPC_OK());
3437 clipboard
->SetData(trans
, nullptr, aWhichClipboard
);
3443 static Result
<nsCOMPtr
<nsITransferable
>, nsresult
> CreateTransferable(
3444 const nsTArray
<nsCString
>& aTypes
) {
3446 nsCOMPtr
<nsITransferable
> trans
=
3447 do_CreateInstance("@mozilla.org/widget/transferable;1", &rv
);
3448 if (NS_FAILED(rv
)) {
3452 MOZ_TRY(trans
->Init(nullptr));
3453 // The private flag is only used to prevent the data from being cached to the
3454 // disk. The flag is not exported to the IPCDataTransfer object.
3455 // The flag is set because we are not sure whether the clipboard data is used
3456 // in a private browsing context. The transferable is only used in this scope,
3457 // so the cache would not reduce memory consumption anyway.
3458 trans
->SetIsPrivateData(true);
3459 // Fill out flavors for transferable
3460 for (uint32_t t
= 0; t
< aTypes
.Length(); t
++) {
3461 MOZ_TRY(trans
->AddDataFlavor(aTypes
[t
].get()));
3464 return std::move(trans
);
3467 } // anonymous namespace
3469 mozilla::ipc::IPCResult
ContentParent::RecvGetClipboard(
3470 nsTArray
<nsCString
>&& aTypes
, const int32_t& aWhichClipboard
,
3471 const MaybeDiscarded
<WindowContext
>& aRequestingWindowContext
,
3472 IPCTransferableData
* aTransferableData
) {
3474 // We expect content processes to always pass a non-null window so Content
3475 // Analysis can analyze it. (if Content Analysis is active)
3476 // There may be some cases when a window is closing, etc., in
3477 // which case returning no clipboard content should not be a problem.
3478 if (aRequestingWindowContext
.IsDiscarded()) {
3480 "discarded window passed to RecvGetClipboard(); returning no clipboard "
3484 if (aRequestingWindowContext
.IsNull()) {
3485 return IPC_FAIL(this, "passed null window to RecvGetClipboard()");
3487 RefPtr
<WindowGlobalParent
> window
= aRequestingWindowContext
.get_canonical();
3488 // Retrieve clipboard
3489 nsCOMPtr
<nsIClipboard
> clipboard(do_GetService(kCClipboardCID
, &rv
));
3490 if (NS_FAILED(rv
)) {
3494 // Create transferable
3495 auto result
= CreateTransferable(aTypes
);
3496 if (result
.isErr()) {
3500 // Get data from clipboard
3501 nsCOMPtr
<nsITransferable
> trans
= result
.unwrap();
3502 clipboard
->GetData(trans
, aWhichClipboard
, window
);
3504 nsContentUtils::TransferableToIPCTransferableData(
3505 trans
, aTransferableData
, true /* aInSyncMessage */, this);
3509 mozilla::ipc::IPCResult
ContentParent::RecvEmptyClipboard(
3510 const int32_t& aWhichClipboard
) {
3512 nsCOMPtr
<nsIClipboard
> clipboard(do_GetService(kCClipboardCID
, &rv
));
3513 NS_ENSURE_SUCCESS(rv
, IPC_OK());
3515 clipboard
->EmptyClipboard(aWhichClipboard
);
3520 mozilla::ipc::IPCResult
ContentParent::RecvClipboardHasType(
3521 nsTArray
<nsCString
>&& aTypes
, const int32_t& aWhichClipboard
,
3524 nsCOMPtr
<nsIClipboard
> clipboard(do_GetService(kCClipboardCID
, &rv
));
3525 NS_ENSURE_SUCCESS(rv
, IPC_OK());
3527 clipboard
->HasDataMatchingFlavors(aTypes
, aWhichClipboard
, aHasType
);
3534 static Result
<ClipboardReadRequest
, nsresult
> CreateClipboardReadRequest(
3535 ContentParent
& aContentParent
,
3536 nsIAsyncGetClipboardData
& aAsyncGetClipboardData
) {
3537 nsTArray
<nsCString
> flavors
;
3538 nsresult rv
= aAsyncGetClipboardData
.GetFlavorList(flavors
);
3539 if (NS_FAILED(rv
)) {
3543 auto requestParent
= MakeNotNull
<RefPtr
<ClipboardReadRequestParent
>>(
3544 &aContentParent
, &aAsyncGetClipboardData
);
3546 // Open a remote endpoint for our PClipboardReadRequest actor.
3547 ManagedEndpoint
<PClipboardReadRequestChild
> childEndpoint
=
3548 aContentParent
.OpenPClipboardReadRequestEndpoint(requestParent
);
3549 if (NS_WARN_IF(!childEndpoint
.IsValid())) {
3550 return Err(NS_ERROR_FAILURE
);
3553 return ClipboardReadRequest(std::move(childEndpoint
), std::move(flavors
));
3556 class ClipboardGetCallback final
: public nsIAsyncClipboardGetCallback
{
3558 ClipboardGetCallback(ContentParent
* aContentParent
,
3559 ContentParent::GetClipboardAsyncResolver
&& aResolver
)
3560 : mContentParent(aContentParent
), mResolver(std::move(aResolver
)) {}
3562 // This object will never be held by a cycle-collected object, so it doesn't
3563 // need to be cycle-collected despite holding alive cycle-collected objects.
3566 // nsIAsyncClipboardGetCallback
3567 NS_IMETHOD
OnSuccess(
3568 nsIAsyncGetClipboardData
* aAsyncGetClipboardData
) override
{
3569 MOZ_ASSERT(mContentParent
);
3570 MOZ_ASSERT(aAsyncGetClipboardData
);
3573 CreateClipboardReadRequest(*mContentParent
, *aAsyncGetClipboardData
);
3574 if (result
.isErr()) {
3575 return OnError(result
.unwrapErr());
3578 mResolver(result
.unwrap());
3582 NS_IMETHOD
OnError(nsresult aResult
) override
{
3588 ~ClipboardGetCallback() = default;
3590 RefPtr
<ContentParent
> mContentParent
;
3591 ContentParent::GetClipboardAsyncResolver mResolver
;
3594 NS_IMPL_ISUPPORTS(ClipboardGetCallback
, nsIAsyncClipboardGetCallback
)
3598 mozilla::ipc::IPCResult
ContentParent::RecvGetClipboardAsync(
3599 nsTArray
<nsCString
>&& aTypes
, const int32_t& aWhichClipboard
,
3600 const MaybeDiscarded
<WindowContext
>& aRequestingWindowContext
,
3601 mozilla::NotNull
<nsIPrincipal
*> aRequestingPrincipal
,
3602 GetClipboardAsyncResolver
&& aResolver
) {
3603 if (!ValidatePrincipal(aRequestingPrincipal
,
3604 {ValidatePrincipalOptions::AllowSystem
,
3605 ValidatePrincipalOptions::AllowExpanded
})) {
3606 LogAndAssertFailedPrincipalValidationInfo(aRequestingPrincipal
, __func__
);
3609 // If the requesting context has been discarded, cancel the paste.
3610 if (aRequestingWindowContext
.IsDiscarded()) {
3611 aResolver(NS_ERROR_NOT_AVAILABLE
);
3615 RefPtr
<WindowGlobalParent
> requestingWindow
=
3616 aRequestingWindowContext
.get_canonical();
3617 if (requestingWindow
&& requestingWindow
->GetContentParent() != this) {
3619 this, "attempt to paste into WindowContext loaded in another process");
3623 // Retrieve clipboard
3624 nsCOMPtr
<nsIClipboard
> clipboard(do_GetService(kCClipboardCID
, &rv
));
3625 if (NS_FAILED(rv
)) {
3630 auto callback
= MakeRefPtr
<ClipboardGetCallback
>(this, std::move(aResolver
));
3631 rv
= clipboard
->AsyncGetData(aTypes
, aWhichClipboard
, requestingWindow
,
3632 aRequestingPrincipal
, callback
);
3633 if (NS_FAILED(rv
)) {
3634 callback
->OnError(rv
);
3641 mozilla::ipc::IPCResult
ContentParent::RecvGetClipboardDataSnapshotSync(
3642 nsTArray
<nsCString
>&& aTypes
, const int32_t& aWhichClipboard
,
3643 const MaybeDiscarded
<WindowContext
>& aRequestingWindowContext
,
3644 ClipboardReadRequestOrError
* aRequestOrError
) {
3645 // If the requesting context has been discarded, cancel the paste.
3646 if (aRequestingWindowContext
.IsDiscarded()) {
3647 *aRequestOrError
= NS_ERROR_FAILURE
;
3651 RefPtr
<WindowGlobalParent
> requestingWindow
=
3652 aRequestingWindowContext
.get_canonical();
3653 if (requestingWindow
&& requestingWindow
->GetContentParent() != this) {
3655 this, "attempt to paste into WindowContext loaded in another process");
3658 nsCOMPtr
<nsIClipboard
> clipboard(do_GetService(kCClipboardCID
));
3660 *aRequestOrError
= NS_ERROR_FAILURE
;
3664 nsCOMPtr
<nsIAsyncGetClipboardData
> asyncGetClipboardData
;
3666 clipboard
->GetDataSnapshotSync(aTypes
, aWhichClipboard
, requestingWindow
,
3667 getter_AddRefs(asyncGetClipboardData
));
3668 if (NS_FAILED(rv
)) {
3669 *aRequestOrError
= rv
;
3673 auto result
= CreateClipboardReadRequest(*this, *asyncGetClipboardData
);
3674 if (result
.isErr()) {
3675 *aRequestOrError
= result
.unwrapErr();
3679 *aRequestOrError
= result
.unwrap();
3683 already_AddRefed
<PClipboardWriteRequestParent
>
3684 ContentParent::AllocPClipboardWriteRequestParent(
3685 const int32_t& aClipboardType
) {
3686 RefPtr
<ClipboardWriteRequestParent
> request
=
3687 MakeAndAddRef
<ClipboardWriteRequestParent
>(this);
3688 request
->Init(aClipboardType
);
3689 return request
.forget();
3692 mozilla::ipc::IPCResult
ContentParent::RecvGetIconForExtension(
3693 const nsACString
& aFileExt
, const uint32_t& aIconSize
,
3694 nsTArray
<uint8_t>* bits
) {
3695 #ifdef MOZ_WIDGET_ANDROID
3696 NS_ASSERTION(AndroidBridge::Bridge() != nullptr,
3697 "AndroidBridge is not available");
3698 if (AndroidBridge::Bridge() == nullptr) {
3699 // Do not fail - just no icon will be shown
3703 bits
->AppendElements(aIconSize
* aIconSize
* 4);
3705 AndroidBridge::Bridge()->GetIconForExtension(aFileExt
, aIconSize
,
3711 mozilla::ipc::IPCResult
ContentParent::RecvFirstIdle() {
3712 // When the ContentChild goes idle, it sends us a FirstIdle message
3713 // which we use as a good time to signal the PreallocatedProcessManager
3714 // that it can start allocating processes from now on.
3715 if (mIsAPreallocBlocker
) {
3717 ContentParent::GetLog(), LogLevel::Verbose
,
3718 ("RecvFirstIdle %p: Removing Blocker for %s", this, mRemoteType
.get()));
3719 PreallocatedProcessManager::RemoveBlocker(mRemoteType
, this);
3720 mIsAPreallocBlocker
= false;
3725 already_AddRefed
<nsDocShellLoadState
> ContentParent::TakePendingLoadStateForId(
3726 uint64_t aLoadIdentifier
) {
3727 return mPendingLoadStates
.Extract(aLoadIdentifier
).valueOr(nullptr).forget();
3730 void ContentParent::StorePendingLoadState(nsDocShellLoadState
* aLoadState
) {
3731 MOZ_DIAGNOSTIC_ASSERT(
3732 !mPendingLoadStates
.Contains(aLoadState
->GetLoadIdentifier()),
3733 "The same nsDocShellLoadState was sent to the same content process "
3734 "twice? This will mess with cross-process tracking of loads");
3735 mPendingLoadStates
.InsertOrUpdate(aLoadState
->GetLoadIdentifier(),
3739 mozilla::ipc::IPCResult
ContentParent::RecvCleanupPendingLoadState(
3740 uint64_t aLoadIdentifier
) {
3741 mPendingLoadStates
.Remove(aLoadIdentifier
);
3745 // We want ContentParent to show up in CC logs for debugging purposes, but we
3746 // don't actually cycle collect it.
3747 NS_IMPL_CYCLE_COLLECTION_0(ContentParent
)
3749 NS_IMPL_CYCLE_COLLECTING_ADDREF(ContentParent
)
3750 NS_IMPL_CYCLE_COLLECTING_RELEASE(ContentParent
)
3752 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ContentParent
)
3753 NS_INTERFACE_MAP_ENTRY_CONCRETE(ContentParent
)
3754 NS_INTERFACE_MAP_ENTRY(nsIDOMProcessParent
)
3755 NS_INTERFACE_MAP_ENTRY(nsIObserver
)
3756 NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionCallback
)
3757 NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionErrorCallback
)
3758 NS_INTERFACE_MAP_ENTRY(nsIAsyncShutdownBlocker
)
3759 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor
)
3760 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDOMProcessParent
)
3761 NS_INTERFACE_MAP_END
3763 class RequestContentJSInterruptRunnable final
: public Runnable
{
3765 explicit RequestContentJSInterruptRunnable(PProcessHangMonitorParent
* aActor
)
3766 : Runnable("dom::RequestContentJSInterruptRunnable"),
3767 mHangMonitorActor(aActor
) {}
3769 NS_IMETHOD
Run() override
{
3770 MOZ_ASSERT(mHangMonitorActor
);
3771 Unused
<< mHangMonitorActor
->SendRequestContentJSInterrupt();
3777 // The end-of-life of ContentParent::mHangMonitorActor is bound to
3778 // ContentParent::ActorDestroy and then HangMonitorParent::Shutdown
3779 // dispatches a shutdown runnable to this queue and waits for it to be
3780 // executed. So the runnable needs not to care about keeping it alive,
3781 // as it is surely dispatched earlier than the
3782 // HangMonitorParent::ShutdownOnThread.
3783 RefPtr
<PProcessHangMonitorParent
> mHangMonitorActor
;
3786 void ContentParent::SignalImpendingShutdownToContentJS() {
3787 if (!mIsSignaledImpendingShutdown
&&
3788 !AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdown
)) {
3789 MaybeLogBlockShutdownDiagnostics(
3790 this, "BlockShutdown: NotifyImpendingShutdown.", __FILE__
, __LINE__
);
3791 NotifyImpendingShutdown();
3792 mIsSignaledImpendingShutdown
= true;
3793 if (mHangMonitorActor
&&
3794 StaticPrefs::dom_abort_script_on_child_shutdown()) {
3795 MaybeLogBlockShutdownDiagnostics(
3796 this, "BlockShutdown: RequestContentJSInterrupt.", __FILE__
,
3798 RefPtr
<RequestContentJSInterruptRunnable
> r
=
3799 new RequestContentJSInterruptRunnable(mHangMonitorActor
);
3800 ProcessHangMonitor::Get()->Dispatch(r
.forget());
3805 // Async shutdown blocker
3807 ContentParent::BlockShutdown(nsIAsyncShutdownClient
* aClient
) {
3808 if (!AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdown
)) {
3809 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
3810 mBlockShutdownCalled
= true;
3812 // Our real shutdown has not yet started. Just notify the impending
3813 // shutdown and eventually cancel content JS.
3814 SignalImpendingShutdownToContentJS();
3815 // This will make our process unusable for normal content, so we need to
3816 // ensure we won't get re-used by GetUsedBrowserProcess as we have not yet
3818 PreallocatedProcessManager::Erase(this);
3819 StopRecyclingE10SOnly(false);
3821 if (sQuitApplicationGrantedClient
) {
3822 Unused
<< sQuitApplicationGrantedClient
->RemoveBlocker(this);
3824 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
3825 mBlockShutdownCalled
= false;
3830 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
3831 // We register two final shutdown blockers and both would call us, but if
3832 // things go well we will unregister both as (delayed) reaction to the first
3833 // call we get and thus never receive a second call. Thus we believe that we
3834 // will get called only once except for quit-application-granted, which is
3836 MOZ_ASSERT(!mBlockShutdownCalled
);
3837 mBlockShutdownCalled
= true;
3841 MaybeLogBlockShutdownDiagnostics(this, "BlockShutdown: CanSend.", __FILE__
,
3844 // Make sure that our process will get scheduled.
3845 ProcessPriorityManager::SetProcessPriority(this,
3846 PROCESS_PRIORITY_FOREGROUND
);
3847 // The normal shutdown sequence is to send a shutdown message
3848 // to the child and then just wait for ActorDestroy which will
3849 // cleanup everything and remove our blockers.
3850 if (!ShutDownProcess(SEND_SHUTDOWN_MESSAGE
)) {
3851 KillHard("Failed to send Shutdown message. Destroying the process...");
3854 } else if (IsLaunching()) {
3855 MaybeLogBlockShutdownDiagnostics(
3856 this, "BlockShutdown: !CanSend && IsLaunching.", __FILE__
, __LINE__
);
3858 // If we get here while we are launching, we must wait for the child to
3859 // be able to react on our commands. Mark this process as dead. This
3860 // will make bail out LaunchSubprocessResolve and kick off the normal
3861 // shutdown sequence.
3864 MOZ_ASSERT(IsDead());
3866 MaybeLogBlockShutdownDiagnostics(
3867 this, "BlockShutdown: !!! !CanSend && !IsLaunching && !IsDead !!!",
3868 __FILE__
, __LINE__
);
3870 MaybeLogBlockShutdownDiagnostics(
3871 this, "BlockShutdown: !CanSend && !IsLaunching && IsDead.", __FILE__
,
3874 // Nothing left we can do. We must assume that we race with an ongoing
3875 // process shutdown, such that we can expect our shutdown blockers to be
3876 // removed normally.
3883 ContentParent::GetName(nsAString
& aName
) {
3884 aName
.AssignLiteral("ContentParent:");
3885 aName
.AppendPrintf(" id=%p", this);
3890 ContentParent::GetState(nsIPropertyBag
** aResult
) {
3891 auto props
= MakeRefPtr
<nsHashPropertyBag
>();
3892 props
->SetPropertyAsACString(u
"remoteTypePrefix"_ns
,
3893 RemoteTypePrefix(mRemoteType
));
3894 *aResult
= props
.forget().downcast
<nsIWritablePropertyBag
>().take();
3898 static void InitShutdownClients() {
3899 if (!sXPCOMShutdownClient
) {
3901 nsCOMPtr
<nsIAsyncShutdownService
> svc
= services::GetAsyncShutdownService();
3906 nsCOMPtr
<nsIAsyncShutdownClient
> client
;
3907 // TODO: It seems as if getPhase from AsyncShutdown.sys.mjs does not check
3908 // if we are beyond our phase already. See bug 1762840.
3909 if (!AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMWillShutdown
)) {
3910 rv
= svc
->GetXpcomWillShutdown(getter_AddRefs(client
));
3911 if (NS_SUCCEEDED(rv
)) {
3912 sXPCOMShutdownClient
= client
.forget();
3913 ClearOnShutdown(&sXPCOMShutdownClient
);
3916 if (!AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdown
)) {
3917 rv
= svc
->GetProfileBeforeChange(getter_AddRefs(client
));
3918 if (NS_SUCCEEDED(rv
)) {
3919 sProfileBeforeChangeClient
= client
.forget();
3920 ClearOnShutdown(&sProfileBeforeChangeClient
);
3923 // TODO: ShutdownPhase::AppShutdownConfirmed is not mapping to
3924 // QuitApplicationGranted, see bug 1762840 comment 4.
3925 if (!AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed
)) {
3926 rv
= svc
->GetQuitApplicationGranted(getter_AddRefs(client
));
3927 if (NS_SUCCEEDED(rv
)) {
3928 sQuitApplicationGrantedClient
= client
.forget();
3929 ClearOnShutdown(&sQuitApplicationGrantedClient
);
3935 void ContentParent::AddShutdownBlockers() {
3936 InitShutdownClients();
3937 MOZ_ASSERT(sXPCOMShutdownClient
);
3938 MOZ_ASSERT(sProfileBeforeChangeClient
);
3940 if (sXPCOMShutdownClient
) {
3941 sXPCOMShutdownClient
->AddBlocker(
3942 this, NS_LITERAL_STRING_FROM_CSTRING(__FILE__
), __LINE__
, u
""_ns
);
3944 if (sProfileBeforeChangeClient
) {
3945 sProfileBeforeChangeClient
->AddBlocker(
3946 this, NS_LITERAL_STRING_FROM_CSTRING(__FILE__
), __LINE__
, u
""_ns
);
3948 if (sQuitApplicationGrantedClient
) {
3949 sQuitApplicationGrantedClient
->AddBlocker(
3950 this, NS_LITERAL_STRING_FROM_CSTRING(__FILE__
), __LINE__
, u
""_ns
);
3954 void ContentParent::RemoveShutdownBlockers() {
3955 MOZ_ASSERT(sXPCOMShutdownClient
);
3956 MOZ_ASSERT(sProfileBeforeChangeClient
);
3958 MaybeLogBlockShutdownDiagnostics(this, "RemoveShutdownBlockers", __FILE__
,
3960 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
3961 mBlockShutdownCalled
= false;
3964 if (sXPCOMShutdownClient
) {
3965 Unused
<< sXPCOMShutdownClient
->RemoveBlocker(this);
3967 if (sProfileBeforeChangeClient
) {
3968 Unused
<< sProfileBeforeChangeClient
->RemoveBlocker(this);
3970 if (sQuitApplicationGrantedClient
) {
3971 Unused
<< sQuitApplicationGrantedClient
->RemoveBlocker(this);
3976 ContentParent::Observe(nsISupports
* aSubject
, const char* aTopic
,
3977 const char16_t
* aData
) {
3978 if (IsDead() || !mSubprocess
) {
3982 if (!strcmp(aTopic
, "nsPref:changed")) {
3983 // We know prefs are ASCII here.
3984 NS_LossyConvertUTF16toASCII
strData(aData
);
3986 Pref
pref(strData
, /* isLocked */ false,
3987 /* isSanitized */ false, Nothing(), Nothing());
3989 Preferences::GetPreference(&pref
, GeckoProcessType_Content
,
3992 // This check is a bit of a hack. We want to avoid sending excessive
3993 // preference updates to subprocesses for performance reasons, but we
3994 // currently don't have a great mechanism for doing so. (See Bug 1819714)
3995 // We're going to hijack the sanitization mechanism to accomplish our goal
3996 // but it imposes the following complications:
3997 // 1) It doesn't avoid sending anything to other (non-web-content)
3998 // subprocesses so we're not getting any perf gains there
3999 // 2) It confuses the subprocesses w.r.t. sanitization. The point of
4000 // sending a preference update of a sanitized preference is so that
4001 // content process knows when it's asked to resolve a sanitized
4002 // preference, and it can send telemetry and/or crash. With this
4003 // change, a sanitized pref that is created during the browser session
4004 // will not be sent to the content process, and therefore the content
4005 // process won't know it should telemetry/crash on access - it'll just
4006 // silently fail to resolve it. After browser restart, the sanitized
4007 // pref will be populated into the content process via the shared pref
4008 // map and _then_ if it is accessed, the content process will crash.
4009 // We're seeing good telemetry/crash rates right now, so we're okay with
4011 if (pref
.isSanitized()) {
4015 if (IsInitialized()) {
4016 MOZ_ASSERT(mQueuedPrefs
.IsEmpty());
4017 if (!SendPreferenceUpdate(pref
)) {
4018 return NS_ERROR_NOT_AVAILABLE
;
4021 MOZ_ASSERT(!IsDead());
4022 mQueuedPrefs
.AppendElement(pref
);
4032 // listening for memory pressure event
4033 if (!strcmp(aTopic
, "memory-pressure")) {
4034 Unused
<< SendFlushMemory(nsDependentString(aData
));
4035 } else if (!strcmp(aTopic
, "application-background")) {
4036 Unused
<< SendApplicationBackground();
4037 } else if (!strcmp(aTopic
, "application-foreground")) {
4038 Unused
<< SendApplicationForeground();
4039 } else if (!strcmp(aTopic
, NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC
)) {
4040 NS_ConvertUTF16toUTF8
dataStr(aData
);
4041 const char* offline
= dataStr
.get();
4042 if (!SendSetOffline(!strcmp(offline
, "true"))) {
4043 return NS_ERROR_NOT_AVAILABLE
;
4045 } else if (!strcmp(aTopic
, NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC
)) {
4046 if (!SendSetConnectivity(u
"true"_ns
.Equals(aData
))) {
4047 return NS_ERROR_NOT_AVAILABLE
;
4049 } else if (!strcmp(aTopic
, NS_IPC_CAPTIVE_PORTAL_SET_STATE
)) {
4050 nsCOMPtr
<nsICaptivePortalService
> cps
= do_QueryInterface(aSubject
);
4051 MOZ_ASSERT(cps
, "Should QI to a captive portal service");
4053 return NS_ERROR_FAILURE
;
4056 cps
->GetState(&state
);
4057 if (!SendSetCaptivePortalState(state
)) {
4058 return NS_ERROR_NOT_AVAILABLE
;
4061 // listening for alert notifications
4062 else if (!strcmp(aTopic
, "alertfinished") ||
4063 !strcmp(aTopic
, "alertclickcallback") ||
4064 !strcmp(aTopic
, "alertshow") ||
4065 !strcmp(aTopic
, "alertdisablecallback") ||
4066 !strcmp(aTopic
, "alertsettingscallback")) {
4067 if (!SendNotifyAlertsObserver(nsDependentCString(aTopic
),
4068 nsDependentString(aData
)))
4069 return NS_ERROR_NOT_AVAILABLE
;
4070 } else if (!strcmp(aTopic
, "child-gc-request")) {
4071 Unused
<< SendGarbageCollect();
4072 } else if (!strcmp(aTopic
, "child-cc-request")) {
4073 Unused
<< SendCycleCollect();
4074 } else if (!strcmp(aTopic
, "child-mmu-request")) {
4075 Unused
<< SendMinimizeMemoryUsage();
4076 } else if (!strcmp(aTopic
, "child-ghost-request")) {
4077 Unused
<< SendUnlinkGhosts();
4078 } else if (!strcmp(aTopic
, "last-pb-context-exited")) {
4079 Unused
<< SendLastPrivateDocShellDestroyed();
4081 #ifdef ACCESSIBILITY
4082 else if (aData
&& !strcmp(aTopic
, "a11y-init-or-shutdown")) {
4083 if (*aData
== '1') {
4084 // Make sure accessibility is running in content process when
4085 // accessibility gets initiated in chrome process.
4086 Unused
<< SendActivateA11y();
4088 // If possible, shut down accessibility in content process when
4089 // accessibility gets shutdown in chrome process.
4090 Unused
<< SendShutdownA11y();
4094 else if (!strcmp(aTopic
, "cacheservice:empty-cache")) {
4095 Unused
<< SendNotifyEmptyHTTPCache();
4096 } else if (!strcmp(aTopic
, "intl:app-locales-changed")) {
4097 nsTArray
<nsCString
> appLocales
;
4098 LocaleService::GetInstance()->GetAppLocalesAsBCP47(appLocales
);
4099 Unused
<< SendUpdateAppLocales(appLocales
);
4100 } else if (!strcmp(aTopic
, "intl:requested-locales-changed")) {
4101 nsTArray
<nsCString
> requestedLocales
;
4102 LocaleService::GetInstance()->GetRequestedLocales(requestedLocales
);
4103 Unused
<< SendUpdateRequestedLocales(requestedLocales
);
4104 } else if (!strcmp(aTopic
, "cookie-changed") ||
4105 !strcmp(aTopic
, "private-cookie-changed")) {
4106 MOZ_ASSERT(aSubject
, "cookie changed notification must have subject.");
4107 nsCOMPtr
<nsICookieNotification
> notification
= do_QueryInterface(aSubject
);
4108 MOZ_ASSERT(notification
,
4109 "cookie changed notification must have nsICookieNotification.");
4110 nsICookieNotification::Action action
= notification
->GetAction();
4112 PNeckoParent
* neckoParent
= LoneManagedOrNullAsserts(ManagedPNeckoParent());
4116 PCookieServiceParent
* csParent
=
4117 LoneManagedOrNullAsserts(neckoParent
->ManagedPCookieServiceParent());
4121 auto* cs
= static_cast<CookieServiceParent
*>(csParent
);
4122 if (action
== nsICookieNotification::COOKIES_BATCH_DELETED
) {
4123 nsCOMPtr
<nsIArray
> cookieList
;
4124 DebugOnly
<nsresult
> rv
=
4125 notification
->GetBatchDeletedCookies(getter_AddRefs(cookieList
));
4126 NS_ASSERTION(NS_SUCCEEDED(rv
) && cookieList
, "couldn't get cookie list");
4127 cs
->RemoveBatchDeletedCookies(cookieList
);
4131 if (action
== nsICookieNotification::ALL_COOKIES_CLEARED
) {
4136 // Do not push these cookie updates to the same process they originated
4138 if (cs
->ProcessingCookie()) {
4142 nsCOMPtr
<nsICookie
> xpcCookie
;
4143 DebugOnly
<nsresult
> rv
= notification
->GetCookie(getter_AddRefs(xpcCookie
));
4144 NS_ASSERTION(NS_SUCCEEDED(rv
) && xpcCookie
, "couldn't get cookie");
4146 // only broadcast the cookie change to content processes that need it
4147 const Cookie
& cookie
= xpcCookie
->AsCookie();
4149 // do not send cookie if content process does not have similar cookie
4150 if (!cs
->ContentProcessHasCookie(cookie
)) {
4154 if (action
== nsICookieNotification::COOKIE_DELETED
) {
4155 cs
->RemoveCookie(cookie
);
4156 } else if (action
== nsICookieNotification::COOKIE_ADDED
||
4157 action
== nsICookieNotification::COOKIE_CHANGED
) {
4158 cs
->AddCookie(cookie
);
4160 } else if (!strcmp(aTopic
, NS_NETWORK_LINK_TYPE_TOPIC
)) {
4161 UpdateNetworkLinkType();
4162 } else if (!strcmp(aTopic
, "network:socket-process-crashed")) {
4163 Unused
<< SendSocketProcessCrashed();
4164 } else if (!strcmp(aTopic
, DEFAULT_TIMEZONE_CHANGED_OBSERVER_TOPIC
)) {
4165 Unused
<< SendSystemTimezoneChanged();
4166 } else if (!strcmp(aTopic
, NS_NETWORK_TRR_MODE_CHANGED_TOPIC
)) {
4167 nsCOMPtr
<nsIDNSService
> dns
= do_GetService(NS_DNSSERVICE_CONTRACTID
);
4168 nsIDNSService::ResolverMode mode
;
4169 dns
->GetCurrentTrrMode(&mode
);
4170 Unused
<< SendSetTRRMode(mode
, static_cast<nsIDNSService::ResolverMode
>(
4171 StaticPrefs::network_trr_mode()));
4177 void ContentParent::UpdateNetworkLinkType() {
4179 nsCOMPtr
<nsINetworkLinkService
> nls
=
4180 do_GetService(NS_NETWORK_LINK_SERVICE_CONTRACTID
, &rv
);
4181 if (NS_FAILED(rv
)) {
4185 uint32_t linkType
= nsINetworkLinkService::LINK_TYPE_UNKNOWN
;
4186 rv
= nls
->GetLinkType(&linkType
);
4187 if (NS_FAILED(rv
)) {
4191 Unused
<< SendNetworkLinkTypeChange(linkType
);
4195 ContentParent::GetInterface(const nsIID
& aIID
, void** aResult
) {
4196 NS_ENSURE_ARG_POINTER(aResult
);
4198 if (aIID
.Equals(NS_GET_IID(nsIMessageSender
))) {
4199 nsCOMPtr
<nsIMessageSender
> mm
= GetMessageManager();
4204 return NS_NOINTERFACE
;
4207 mozilla::ipc::IPCResult
ContentParent::RecvInitBackground(
4208 Endpoint
<PBackgroundStarterParent
>&& aEndpoint
) {
4209 if (!BackgroundParent::AllocStarter(this, std::move(aEndpoint
))) {
4210 NS_WARNING("BackgroundParent::Alloc failed");
4216 bool ContentParent::CanOpenBrowser(const IPCTabContext
& aContext
) {
4217 // (PopupIPCTabContext lets the child process prove that it has access to
4218 // the app it's trying to open.)
4219 // On e10s we also allow UnsafeTabContext to allow service workers to open
4220 // windows. This is enforced in MaybeInvalidTabContext.
4221 if (aContext
.type() != IPCTabContext::TPopupIPCTabContext
) {
4222 MOZ_CRASH_UNLESS_FUZZING(
4223 "Unexpected IPCTabContext type. Aborting AllocPBrowserParent.");
4227 if (aContext
.type() == IPCTabContext::TPopupIPCTabContext
) {
4228 const PopupIPCTabContext
& popupContext
= aContext
.get_PopupIPCTabContext();
4230 auto opener
= BrowserParent::GetFrom(popupContext
.opener().AsParent());
4232 MOZ_CRASH_UNLESS_FUZZING(
4233 "Got null opener from child; aborting AllocPBrowserParent.");
4238 MaybeInvalidTabContext
tc(aContext
);
4239 if (!tc
.IsValid()) {
4240 NS_ERROR(nsPrintfCString("Child passed us an invalid TabContext. (%s) "
4241 "Aborting AllocPBrowserParent.",
4242 tc
.GetInvalidReason())
4250 static bool CloneIsLegal(ContentParent
* aCp
, CanonicalBrowsingContext
& aSource
,
4251 CanonicalBrowsingContext
& aTarget
) {
4252 // Source and target must be in the same BCG
4253 if (NS_WARN_IF(aSource
.Group() != aTarget
.Group())) {
4256 // The source and target must be in different toplevel <browser>s
4257 if (NS_WARN_IF(aSource
.Top() == aTarget
.Top())) {
4261 // Neither source nor target must be toplevel.
4262 if (NS_WARN_IF(aSource
.IsTop()) || NS_WARN_IF(aTarget
.IsTop())) {
4266 // Both should be embedded by the same process.
4267 auto* sourceEmbedder
= aSource
.GetParentWindowContext();
4268 if (NS_WARN_IF(!sourceEmbedder
) ||
4269 NS_WARN_IF(sourceEmbedder
->GetContentParent() != aCp
)) {
4273 auto* targetEmbedder
= aTarget
.GetParentWindowContext();
4274 if (NS_WARN_IF(!targetEmbedder
) ||
4275 NS_WARN_IF(targetEmbedder
->GetContentParent() != aCp
)) {
4283 mozilla::ipc::IPCResult
ContentParent::RecvCloneDocumentTreeInto(
4284 const MaybeDiscarded
<BrowsingContext
>& aSource
,
4285 const MaybeDiscarded
<BrowsingContext
>& aTarget
, PrintData
&& aPrintData
) {
4286 if (aSource
.IsNullOrDiscarded() || aTarget
.IsNullOrDiscarded()) {
4290 if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed
)) {
4291 // All existing processes have potentially been slated for removal already,
4292 // such that any subsequent call to GetNewOrUsedLaunchingBrowserProcess
4293 // (normally supposed to find an existing process here) will try to create
4294 // a new process (but fail) that nobody would ever really use. Let's avoid
4295 // this together with the expensive CloneDocumentTreeInto operation.
4299 auto* source
= aSource
.get_canonical();
4300 auto* target
= aTarget
.get_canonical();
4302 if (!CloneIsLegal(this, *source
, *target
)) {
4303 return IPC_FAIL(this, "Illegal subframe clone");
4306 ContentParent
* cp
= source
->GetContentParent();
4307 if (NS_WARN_IF(!cp
)) {
4311 if (NS_WARN_IF(cp
->GetRemoteType() == GetRemoteType())) {
4312 // Wanted to switch to a target browsing context that's already local again.
4313 // See bug 1676996 for how this can happen.
4315 // Dropping the switch on the floor seems fine for this case, though we
4316 // could also try to clone the local document.
4318 // If the remote type matches & it's in the same group (which was confirmed
4319 // by CloneIsLegal), it must be the exact same process.
4320 MOZ_DIAGNOSTIC_ASSERT(cp
== this);
4324 target
->CloneDocumentTreeInto(source
, cp
->GetRemoteType(),
4325 std::move(aPrintData
));
4329 mozilla::ipc::IPCResult
ContentParent::RecvUpdateRemotePrintSettings(
4330 const MaybeDiscarded
<BrowsingContext
>& aTarget
, PrintData
&& aPrintData
) {
4331 if (aTarget
.IsNullOrDiscarded()) {
4335 auto* target
= aTarget
.get_canonical();
4336 auto* bp
= target
->GetBrowserParent();
4337 if (NS_WARN_IF(!bp
)) {
4341 Unused
<< bp
->SendUpdateRemotePrintSettings(std::move(aPrintData
));
4345 mozilla::ipc::IPCResult
ContentParent::RecvConstructPopupBrowser(
4346 ManagedEndpoint
<PBrowserParent
>&& aBrowserEp
,
4347 ManagedEndpoint
<PWindowGlobalParent
>&& aWindowEp
, const TabId
& aTabId
,
4348 const IPCTabContext
& aContext
, const WindowGlobalInit
& aInitialWindowInit
,
4349 const uint32_t& aChromeFlags
) {
4350 MOZ_ASSERT(XRE_IsParentProcess());
4352 if (!CanOpenBrowser(aContext
)) {
4353 return IPC_FAIL(this, "CanOpenBrowser Failed");
4356 RefPtr
<CanonicalBrowsingContext
> browsingContext
=
4357 CanonicalBrowsingContext::Get(
4358 aInitialWindowInit
.context().mBrowsingContextId
);
4359 if (!browsingContext
|| browsingContext
->IsDiscarded()) {
4360 return IPC_FAIL(this, "Null or discarded initial BrowsingContext");
4362 if (!aInitialWindowInit
.principal()) {
4363 return IPC_FAIL(this, "Cannot create without valid initial principal");
4366 if (!ValidatePrincipal(aInitialWindowInit
.principal())) {
4367 LogAndAssertFailedPrincipalValidationInfo(aInitialWindowInit
.principal(),
4371 if (browsingContext
->GetBrowserParent()) {
4372 return IPC_FAIL(this, "BrowsingContext already has a BrowserParent");
4375 uint32_t chromeFlags
= aChromeFlags
;
4376 TabId
openerTabId(0);
4377 ContentParentId
openerCpId(0);
4378 if (aContext
.type() == IPCTabContext::TPopupIPCTabContext
) {
4379 // CanOpenBrowser has ensured that the IPCTabContext is of
4380 // type PopupIPCTabContext, and that the opener BrowserParent is
4382 const PopupIPCTabContext
& popupContext
= aContext
.get_PopupIPCTabContext();
4383 auto opener
= BrowserParent::GetFrom(popupContext
.opener().AsParent());
4384 openerTabId
= opener
->GetTabId();
4385 openerCpId
= opener
->Manager()->ChildID();
4387 // We must ensure that the private browsing and remoteness flags
4388 // match those of the opener.
4389 nsCOMPtr
<nsILoadContext
> loadContext
= opener
->GetLoadContext();
4391 return IPC_FAIL(this, "Missing Opener LoadContext");
4393 if (loadContext
->UsePrivateBrowsing()) {
4394 chromeFlags
|= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW
;
4396 if (loadContext
->UseRemoteSubframes()) {
4397 chromeFlags
|= nsIWebBrowserChrome::CHROME_FISSION_WINDOW
;
4401 // And because we're allocating a remote browser, of course the
4402 // window is remote.
4403 chromeFlags
|= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW
;
4405 if (NS_WARN_IF(!browsingContext
->IsOwnedByProcess(ChildID()))) {
4406 return IPC_FAIL(this, "BrowsingContext Owned by Incorrect Process!");
4409 MaybeInvalidTabContext
tc(aContext
);
4410 MOZ_ASSERT(tc
.IsValid());
4412 RefPtr
<WindowGlobalParent
> initialWindow
=
4413 WindowGlobalParent::CreateDisconnected(aInitialWindowInit
);
4414 if (!initialWindow
) {
4415 return IPC_FAIL(this, "Failed to create WindowGlobalParent");
4418 auto parent
= MakeRefPtr
<BrowserParent
>(this, aTabId
, tc
.GetTabContext(),
4419 browsingContext
, chromeFlags
);
4421 // Bind the created BrowserParent to IPC to actually link the actor.
4422 if (NS_WARN_IF(!BindPBrowserEndpoint(std::move(aBrowserEp
), parent
))) {
4423 return IPC_FAIL(this, "BindPBrowserEndpoint failed");
4426 // XXX: Why are we checking these requirements? It seems we should register
4427 // the created frame unconditionally?
4428 if (openerTabId
> 0) {
4429 // The creation of PBrowser was triggered from content process through
4431 // We need to register remote frame with the child generated tab id.
4432 auto* cpm
= ContentProcessManager::GetSingleton();
4433 if (!cpm
|| !cpm
->RegisterRemoteFrame(parent
)) {
4434 return IPC_FAIL(this, "RegisterRemoteFrame Failed");
4438 if (NS_WARN_IF(!parent
->BindPWindowGlobalEndpoint(std::move(aWindowEp
),
4440 return IPC_FAIL(this, "BindPWindowGlobalEndpoint failed");
4443 browsingContext
->SetCurrentBrowserParent(parent
);
4445 initialWindow
->Init();
4447 // When enabling input event prioritization, input events may preempt other
4448 // normal priority IPC messages. To prevent the input events preempt
4449 // PBrowserConstructor, we use an IPC 'RemoteIsReadyToHandleInputEvents' to
4450 // notify parent that BrowserChild is created. In this case, PBrowser is
4451 // initiated from content so that we can set BrowserParent as ready to handle
4453 parent
->SetReadyToHandleInputEvents();
4457 mozilla::PRemoteSpellcheckEngineParent
*
4458 ContentParent::AllocPRemoteSpellcheckEngineParent() {
4459 mozilla::RemoteSpellcheckEngineParent
* parent
=
4460 new mozilla::RemoteSpellcheckEngineParent();
4464 bool ContentParent::DeallocPRemoteSpellcheckEngineParent(
4465 PRemoteSpellcheckEngineParent
* parent
) {
4471 void ContentParent::SendShutdownTimerCallback(nsITimer
* aTimer
,
4473 auto* self
= static_cast<ContentParent
*>(aClosure
);
4474 self
->AsyncSendShutDownMessage();
4478 void ContentParent::ForceKillTimerCallback(nsITimer
* aTimer
, void* aClosure
) {
4479 // We don't want to time out the content process during XPCShell tests. This
4480 // is the easiest way to ensure that.
4481 if (PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR")) {
4485 auto* self
= static_cast<ContentParent
*>(aClosure
);
4486 self
->KillHard("ShutDownKill");
4489 void ContentParent::GeneratePairedMinidump(const char* aReason
) {
4490 // We're about to kill the child process associated with this content.
4491 // Something has gone wrong to get us here, so we generate a minidump
4492 // of the parent and child for submission to the crash server unless we're
4493 // already shutting down.
4494 if (mCrashReporter
&&
4495 !AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed
) &&
4496 StaticPrefs::dom_ipc_tabs_createKillHardCrashReports_AtStartup()) {
4497 // GeneratePairedMinidump creates two minidumps for us - the main
4498 // one is for the content process we're about to kill, and the other
4499 // one is for the main browser process. That second one is the extra
4500 // minidump tagging along, so we have to tell the crash reporter that
4501 // it exists and is being appended.
4502 nsAutoCString
additionalDumps("browser");
4503 mCrashReporter
->AddAnnotationNSCString(
4504 CrashReporter::Annotation::additional_minidumps
, additionalDumps
);
4505 nsDependentCString
reason(aReason
);
4506 mCrashReporter
->AddAnnotationNSCString(
4507 CrashReporter::Annotation::ipc_channel_error
, reason
);
4509 // Generate the report and insert into the queue for submittal.
4510 if (mCrashReporter
->GenerateMinidumpAndPair(this, "browser"_ns
)) {
4511 mCrashReporter
->FinalizeCrashReport();
4512 mCreatedPairedMinidumps
= true;
4517 void ContentParent::HandleOrphanedMinidump(nsString
* aDumpId
) {
4518 if (CrashReporter::FinalizeOrphanedMinidump(
4519 OtherPid(), GeckoProcessType_Content
, aDumpId
)) {
4520 CrashReporterHost::RecordCrash(GeckoProcessType_Content
,
4521 nsICrashService::CRASH_TYPE_CRASH
, *aDumpId
);
4523 NS_WARNING(nsPrintfCString("content process pid = %" PRIPID
4524 " crashed without leaving a minidump behind",
4530 // WARNING: aReason appears in telemetry, so any new value passed in requires
4532 void ContentParent::KillHard(const char* aReason
) {
4533 AUTO_PROFILER_LABEL("ContentParent::KillHard", OTHER
);
4535 // On Windows, calling KillHard multiple times causes problems - the
4536 // process handle becomes invalid on the first call, causing a second call
4537 // to crash our process - more details in bug 890840.
4538 if (mCalledKillHard
) {
4541 mCalledKillHard
= true;
4542 if (mSendShutdownTimer
) {
4543 mSendShutdownTimer
->Cancel();
4544 mSendShutdownTimer
= nullptr;
4546 if (mForceKillTimer
) {
4547 mForceKillTimer
->Cancel();
4548 mForceKillTimer
= nullptr;
4551 RemoveShutdownBlockers();
4552 nsCString reason
= nsDependentCString(aReason
);
4554 // If we find mIsNotifiedShutdownSuccess there is no reason to blame this
4555 // content process, most probably our parent process is just slow in
4556 // processing its own main thread queue.
4557 if (!mIsNotifiedShutdownSuccess
) {
4558 GeneratePairedMinidump(aReason
);
4560 reason
= nsDependentCString("KillHard after IsNotifiedShutdownSuccess.");
4562 Telemetry::Accumulate(Telemetry::SUBPROCESS_KILL_HARD
, reason
, 1);
4564 ProcessHandle otherProcessHandle
;
4565 if (!base::OpenProcessHandle(OtherPid(), &otherProcessHandle
)) {
4566 NS_ERROR("Failed to open child process when attempting kill.");
4568 GetIPCChannel()->InduceConnectionError();
4573 if (!KillProcess(otherProcessHandle
, base::PROCESS_END_KILLED_BY_USER
)) {
4574 if (mCrashReporter
) {
4575 mCrashReporter
->DeleteCrashReport();
4577 NS_WARNING("failed to kill subprocess!");
4582 ContentParent::GetLog(), LogLevel::Verbose
,
4583 ("KillHard Subprocess(%s): ContentParent %p mSubprocess %p handle "
4585 aReason
, this, mSubprocess
,
4586 mSubprocess
? (uintptr_t)mSubprocess
->GetChildProcessHandle() : -1));
4587 mSubprocess
->SetAlreadyDead();
4590 // After we've killed the remote process, also ensure we induce a connection
4591 // error in the IPC channel to immediately stop all IPC communication on this
4594 GetIPCChannel()->InduceConnectionError();
4597 // EnsureProcessTerminated has responsibilty for closing otherProcessHandle.
4598 XRE_GetIOMessageLoop()->PostTask(
4599 NewRunnableFunction("EnsureProcessTerminatedRunnable",
4600 &ProcessWatcher::EnsureProcessTerminated
,
4601 otherProcessHandle
, /*force=*/true));
4604 void ContentParent::FriendlyName(nsAString
& aName
, bool aAnonymize
) {
4606 if (mIsForBrowser
) {
4607 aName
.AssignLiteral("Browser");
4608 } else if (aAnonymize
) {
4609 aName
.AssignLiteral("<anonymized-name>");
4611 aName
.AssignLiteral("???");
4615 mozilla::ipc::IPCResult
ContentParent::RecvInitCrashReporter(
4616 const NativeThreadId
& aThreadId
) {
4618 MakeUnique
<CrashReporterHost
>(GeckoProcessType_Content
, aThreadId
);
4623 hal_sandbox::PHalParent
* ContentParent::AllocPHalParent() {
4624 return hal_sandbox::CreateHalParent();
4627 bool ContentParent::DeallocPHalParent(hal_sandbox::PHalParent
* aHal
) {
4632 devtools::PHeapSnapshotTempFileHelperParent
*
4633 ContentParent::AllocPHeapSnapshotTempFileHelperParent() {
4634 return devtools::HeapSnapshotTempFileHelperParent::Create();
4637 bool ContentParent::DeallocPHeapSnapshotTempFileHelperParent(
4638 devtools::PHeapSnapshotTempFileHelperParent
* aHeapSnapshotHelper
) {
4639 delete aHeapSnapshotHelper
;
4643 bool ContentParent::SendRequestMemoryReport(
4644 const uint32_t& aGeneration
, const bool& aAnonymize
,
4645 const bool& aMinimizeMemoryUsage
, const Maybe
<FileDescriptor
>& aDMDFile
) {
4646 // This automatically cancels the previous request.
4647 mMemoryReportRequest
= MakeUnique
<MemoryReportRequestHost
>(aGeneration
);
4648 // If we run the callback in response to a reply, then by definition |this|
4649 // is still alive, so the ref pointer is redundant, but it seems easier
4650 // to hold a strong reference than to worry about that.
4651 RefPtr
<ContentParent
> self(this);
4652 PContentParent::SendRequestMemoryReport(
4653 aGeneration
, aAnonymize
, aMinimizeMemoryUsage
, aDMDFile
,
4654 [&, self
](const uint32_t& aGeneration2
) {
4655 if (self
->mMemoryReportRequest
) {
4656 self
->mMemoryReportRequest
->Finish(aGeneration2
);
4657 self
->mMemoryReportRequest
= nullptr;
4660 [&, self
](mozilla::ipc::ResponseRejectReason
) {
4661 self
->mMemoryReportRequest
= nullptr;
4666 mozilla::ipc::IPCResult
ContentParent::RecvAddMemoryReport(
4667 const MemoryReport
& aReport
) {
4668 if (mMemoryReportRequest
) {
4669 mMemoryReportRequest
->RecvReport(aReport
);
4674 PCycleCollectWithLogsParent
* ContentParent::AllocPCycleCollectWithLogsParent(
4675 const bool& aDumpAllTraces
, const FileDescriptor
& aGCLog
,
4676 const FileDescriptor
& aCCLog
) {
4677 MOZ_CRASH("Don't call this; use ContentParent::CycleCollectWithLogs");
4680 bool ContentParent::DeallocPCycleCollectWithLogsParent(
4681 PCycleCollectWithLogsParent
* aActor
) {
4686 bool ContentParent::CycleCollectWithLogs(
4687 bool aDumpAllTraces
, nsICycleCollectorLogSink
* aSink
,
4688 nsIDumpGCAndCCLogsCallback
* aCallback
) {
4689 return CycleCollectWithLogsParent::AllocAndSendConstructor(
4690 this, aDumpAllTraces
, aSink
, aCallback
);
4693 PScriptCacheParent
* ContentParent::AllocPScriptCacheParent(
4694 const FileDescOrError
& cacheFile
, const bool& wantCacheData
) {
4695 return new loader::ScriptCacheParent(wantCacheData
);
4698 bool ContentParent::DeallocPScriptCacheParent(PScriptCacheParent
* cache
) {
4699 delete static_cast<loader::ScriptCacheParent
*>(cache
);
4703 already_AddRefed
<PNeckoParent
> ContentParent::AllocPNeckoParent() {
4704 RefPtr
<NeckoParent
> actor
= new NeckoParent();
4705 return actor
.forget();
4708 mozilla::ipc::IPCResult
ContentParent::RecvInitStreamFilter(
4709 const uint64_t& aChannelId
, const nsAString
& aAddonId
,
4710 InitStreamFilterResolver
&& aResolver
) {
4711 extensions::StreamFilterParent::Create(this, aChannelId
, aAddonId
)
4713 GetCurrentSerialEventTarget(), __func__
,
4714 [aResolver
](mozilla::ipc::Endpoint
<PStreamFilterChild
>&& aEndpoint
) {
4715 aResolver(std::move(aEndpoint
));
4717 [aResolver
](bool aDummy
) {
4718 aResolver(mozilla::ipc::Endpoint
<PStreamFilterChild
>());
4724 mozilla::ipc::IPCResult
ContentParent::RecvAddSecurityState(
4725 const MaybeDiscarded
<WindowContext
>& aContext
, uint32_t aStateFlags
) {
4726 if (aContext
.IsNullOrDiscarded()) {
4730 aContext
.get()->AddSecurityState(aStateFlags
);
4734 already_AddRefed
<PExternalHelperAppParent
>
4735 ContentParent::AllocPExternalHelperAppParent(
4736 nsIURI
* uri
, const mozilla::net::LoadInfoArgs
& aLoadInfoArgs
,
4737 const nsACString
& aMimeContentType
, const nsACString
& aContentDisposition
,
4738 const uint32_t& aContentDispositionHint
,
4739 const nsAString
& aContentDispositionFilename
, const bool& aForceSave
,
4740 const int64_t& aContentLength
, const bool& aWasFileChannel
,
4741 nsIURI
* aReferrer
, const MaybeDiscarded
<BrowsingContext
>& aContext
,
4742 const bool& aShouldCloseWindow
) {
4743 RefPtr
<ExternalHelperAppParent
> parent
= new ExternalHelperAppParent(
4744 uri
, aContentLength
, aWasFileChannel
, aContentDisposition
,
4745 aContentDispositionHint
, aContentDispositionFilename
);
4746 return parent
.forget();
4749 mozilla::ipc::IPCResult
ContentParent::RecvPExternalHelperAppConstructor(
4750 PExternalHelperAppParent
* actor
, nsIURI
* uri
,
4751 const LoadInfoArgs
& loadInfoArgs
, const nsACString
& aMimeContentType
,
4752 const nsACString
& aContentDisposition
,
4753 const uint32_t& aContentDispositionHint
,
4754 const nsAString
& aContentDispositionFilename
, const bool& aForceSave
,
4755 const int64_t& aContentLength
, const bool& aWasFileChannel
,
4756 nsIURI
* aReferrer
, const MaybeDiscarded
<BrowsingContext
>& aContext
,
4757 const bool& aShouldCloseWindow
) {
4758 BrowsingContext
* context
= aContext
.IsDiscarded() ? nullptr : aContext
.get();
4759 if (!static_cast<ExternalHelperAppParent
*>(actor
)->Init(
4760 loadInfoArgs
, aMimeContentType
, aForceSave
, aReferrer
, context
,
4761 aShouldCloseWindow
)) {
4762 return IPC_FAIL(this, "Init failed.");
4767 already_AddRefed
<PHandlerServiceParent
>
4768 ContentParent::AllocPHandlerServiceParent() {
4769 RefPtr
<HandlerServiceParent
> actor
= new HandlerServiceParent();
4770 return actor
.forget();
4773 media::PMediaParent
* ContentParent::AllocPMediaParent() {
4774 return media::AllocPMediaParent();
4777 bool ContentParent::DeallocPMediaParent(media::PMediaParent
* aActor
) {
4778 return media::DeallocPMediaParent(aActor
);
4781 PBenchmarkStorageParent
* ContentParent::AllocPBenchmarkStorageParent() {
4782 return new BenchmarkStorageParent
;
4785 bool ContentParent::DeallocPBenchmarkStorageParent(
4786 PBenchmarkStorageParent
* aActor
) {
4791 #ifdef MOZ_WEBSPEECH
4792 already_AddRefed
<PSpeechSynthesisParent
>
4793 ContentParent::AllocPSpeechSynthesisParent() {
4794 if (!StaticPrefs::media_webspeech_synth_enabled()) {
4797 RefPtr
<SpeechSynthesisParent
> actor
= new SpeechSynthesisParent();
4798 return actor
.forget();
4801 mozilla::ipc::IPCResult
ContentParent::RecvPSpeechSynthesisConstructor(
4802 PSpeechSynthesisParent
* aActor
) {
4803 if (!static_cast<SpeechSynthesisParent
*>(aActor
)->SendInit()) {
4804 return IPC_FAIL(this, "SpeechSynthesisParent::SendInit failed.");
4810 mozilla::ipc::IPCResult
ContentParent::RecvStartVisitedQueries(
4811 const nsTArray
<RefPtr
<nsIURI
>>& aUris
) {
4812 nsCOMPtr
<IHistory
> history
= components::History::Service();
4816 for (const auto& uri
: aUris
) {
4817 if (NS_WARN_IF(!uri
)) {
4820 history
->ScheduleVisitedQuery(uri
, this);
4825 mozilla::ipc::IPCResult
ContentParent::RecvSetURITitle(nsIURI
* uri
,
4826 const nsAString
& title
) {
4828 return IPC_FAIL(this, "uri must not be null.");
4830 nsCOMPtr
<IHistory
> history
= components::History::Service();
4832 history
->SetURITitle(uri
, title
);
4837 mozilla::ipc::IPCResult
ContentParent::RecvIsSecureURI(
4838 nsIURI
* aURI
, const OriginAttributes
& aOriginAttributes
,
4839 bool* aIsSecureURI
) {
4840 nsCOMPtr
<nsISiteSecurityService
> sss(do_GetService(NS_SSSERVICE_CONTRACTID
));
4842 return IPC_FAIL(this, "Failed to get nsISiteSecurityService.");
4845 return IPC_FAIL(this, "aURI must not be null.");
4847 nsresult rv
= sss
->IsSecureURI(aURI
, aOriginAttributes
, aIsSecureURI
);
4848 if (NS_FAILED(rv
)) {
4849 return IPC_FAIL(this, "IsSecureURI failed.");
4854 mozilla::ipc::IPCResult
ContentParent::RecvAccumulateMixedContentHSTS(
4855 nsIURI
* aURI
, const bool& aActive
,
4856 const OriginAttributes
& aOriginAttributes
) {
4858 return IPC_FAIL(this, "aURI must not be null.");
4860 nsMixedContentBlocker::AccumulateMixedContentHSTS(aURI
, aActive
,
4865 mozilla::ipc::IPCResult
ContentParent::RecvLoadURIExternal(
4866 nsIURI
* uri
, nsIPrincipal
* aTriggeringPrincipal
,
4867 nsIPrincipal
* aRedirectPrincipal
,
4868 const MaybeDiscarded
<BrowsingContext
>& aContext
,
4869 bool aWasExternallyTriggered
, bool aHasValidUserGestureActivation
) {
4870 if (aContext
.IsDiscarded()) {
4874 nsCOMPtr
<nsIExternalProtocolService
> extProtService(
4875 do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID
));
4876 if (!extProtService
) {
4881 return IPC_FAIL(this, "uri must not be null.");
4884 BrowsingContext
* bc
= aContext
.get();
4885 extProtService
->LoadURI(uri
, aTriggeringPrincipal
, aRedirectPrincipal
, bc
,
4886 aWasExternallyTriggered
,
4887 aHasValidUserGestureActivation
);
4891 mozilla::ipc::IPCResult
ContentParent::RecvExtProtocolChannelConnectParent(
4892 const uint64_t& registrarId
) {
4895 // First get the real channel created before redirect on the parent.
4896 nsCOMPtr
<nsIChannel
> channel
;
4897 rv
= NS_LinkRedirectChannels(registrarId
, nullptr, getter_AddRefs(channel
));
4898 NS_ENSURE_SUCCESS(rv
, IPC_OK());
4900 nsCOMPtr
<nsIParentChannel
> parent
= do_QueryInterface(channel
, &rv
);
4901 NS_ENSURE_SUCCESS(rv
, IPC_OK());
4903 // The channel itself is its own (faked) parent, link it.
4904 rv
= NS_LinkRedirectChannels(registrarId
, parent
, getter_AddRefs(channel
));
4905 NS_ENSURE_SUCCESS(rv
, IPC_OK());
4907 // Signal the parent channel that it's a redirect-to parent. This will
4908 // make AsyncOpen on it do nothing (what we want).
4909 // Yes, this is a bit of a hack, but I don't think it's necessary to invent
4910 // a new interface just to set this flag on the channel.
4911 parent
->SetParentListener(nullptr);
4916 mozilla::ipc::IPCResult
ContentParent::RecvShowAlert(
4917 nsIAlertNotification
* aAlert
) {
4919 return IPC_FAIL(this, "aAlert must not be null.");
4921 nsCOMPtr
<nsIAlertsService
> sysAlerts(components::Alerts::Service());
4923 sysAlerts
->ShowAlert(aAlert
, this);
4928 mozilla::ipc::IPCResult
ContentParent::RecvCloseAlert(const nsAString
& aName
,
4929 bool aContextClosed
) {
4930 nsCOMPtr
<nsIAlertsService
> sysAlerts(components::Alerts::Service());
4932 sysAlerts
->CloseAlert(aName
, aContextClosed
);
4938 mozilla::ipc::IPCResult
ContentParent::RecvDisableNotifications(
4939 nsIPrincipal
* aPrincipal
) {
4941 return IPC_FAIL(this, "No principal");
4944 if (!ValidatePrincipal(aPrincipal
)) {
4945 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
4947 Unused
<< Notification::RemovePermission(aPrincipal
);
4951 mozilla::ipc::IPCResult
ContentParent::RecvOpenNotificationSettings(
4952 nsIPrincipal
* aPrincipal
) {
4954 return IPC_FAIL(this, "No principal");
4957 if (!ValidatePrincipal(aPrincipal
)) {
4958 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
4960 Unused
<< Notification::OpenSettings(aPrincipal
);
4964 mozilla::ipc::IPCResult
ContentParent::RecvNotificationEvent(
4965 const nsAString
& aType
, const NotificationEventData
& aData
) {
4966 nsCOMPtr
<nsIServiceWorkerManager
> swm
=
4967 mozilla::components::ServiceWorkerManager::Service();
4968 if (NS_WARN_IF(!swm
)) {
4969 // Probably shouldn't happen, but no need to crash the child process.
4973 if (aType
.EqualsLiteral("click")) {
4974 nsresult rv
= swm
->SendNotificationClickEvent(
4975 aData
.originSuffix(), aData
.scope(), aData
.ID(), aData
.title(),
4976 aData
.dir(), aData
.lang(), aData
.body(), aData
.tag(), aData
.icon(),
4977 aData
.data(), aData
.behavior());
4978 Unused
<< NS_WARN_IF(NS_FAILED(rv
));
4980 MOZ_ASSERT(aType
.EqualsLiteral("close"));
4981 nsresult rv
= swm
->SendNotificationCloseEvent(
4982 aData
.originSuffix(), aData
.scope(), aData
.ID(), aData
.title(),
4983 aData
.dir(), aData
.lang(), aData
.body(), aData
.tag(), aData
.icon(),
4984 aData
.data(), aData
.behavior());
4985 Unused
<< NS_WARN_IF(NS_FAILED(rv
));
4991 mozilla::ipc::IPCResult
ContentParent::RecvSyncMessage(
4992 const nsAString
& aMsg
, const ClonedMessageData
& aData
,
4993 nsTArray
<StructuredCloneData
>* aRetvals
) {
4994 AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("ContentParent::RecvSyncMessage",
4996 MMPrinter::Print("ContentParent::RecvSyncMessage", aMsg
, aData
);
4998 RefPtr
<nsFrameMessageManager
> ppm
= mMessageManager
;
5000 ipc::StructuredCloneData data
;
5001 ipc::UnpackClonedMessageData(aData
, data
);
5003 ppm
->ReceiveMessage(ppm
, nullptr, aMsg
, true, &data
, aRetvals
,
5009 mozilla::ipc::IPCResult
ContentParent::RecvAsyncMessage(
5010 const nsAString
& aMsg
, const ClonedMessageData
& aData
) {
5011 AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("ContentParent::RecvAsyncMessage",
5013 MMPrinter::Print("ContentParent::RecvAsyncMessage", aMsg
, aData
);
5015 RefPtr
<nsFrameMessageManager
> ppm
= mMessageManager
;
5017 ipc::StructuredCloneData data
;
5018 ipc::UnpackClonedMessageData(aData
, data
);
5020 ppm
->ReceiveMessage(ppm
, nullptr, aMsg
, false, &data
, nullptr,
5027 static int32_t AddGeolocationListener(
5028 nsIDOMGeoPositionCallback
* watcher
,
5029 nsIDOMGeoPositionErrorCallback
* errorCallBack
, bool highAccuracy
) {
5030 RefPtr
<Geolocation
> geo
= Geolocation::NonWindowSingleton();
5032 UniquePtr
<PositionOptions
> options
= MakeUnique
<PositionOptions
>();
5033 options
->mTimeout
= 0;
5034 options
->mMaximumAge
= 0;
5035 options
->mEnableHighAccuracy
= highAccuracy
;
5036 return geo
->WatchPosition(watcher
, errorCallBack
, std::move(options
));
5039 mozilla::ipc::IPCResult
ContentParent::RecvAddGeolocationListener(
5040 const bool& aHighAccuracy
) {
5041 // To ensure no geolocation updates are skipped, we always force the
5042 // creation of a new listener.
5043 RecvRemoveGeolocationListener();
5044 mGeolocationWatchID
= AddGeolocationListener(this, this, aHighAccuracy
);
5048 mozilla::ipc::IPCResult
ContentParent::RecvRemoveGeolocationListener() {
5049 if (mGeolocationWatchID
!= -1) {
5050 RefPtr
<Geolocation
> geo
= Geolocation::NonWindowSingleton();
5052 geo
->ClearWatch(mGeolocationWatchID
);
5054 mGeolocationWatchID
= -1;
5059 mozilla::ipc::IPCResult
ContentParent::RecvSetGeolocationHigherAccuracy(
5060 const bool& aEnable
) {
5061 // This should never be called without a listener already present,
5062 // so this check allows us to forgo securing privileges.
5063 if (mGeolocationWatchID
!= -1) {
5064 RecvRemoveGeolocationListener();
5065 mGeolocationWatchID
= AddGeolocationListener(this, this, aEnable
);
5071 ContentParent::HandleEvent(nsIDOMGeoPosition
* postion
) {
5072 Unused
<< SendGeolocationUpdate(postion
);
5077 ContentParent::HandleEvent(GeolocationPositionError
* positionError
) {
5078 Unused
<< SendGeolocationError(positionError
->Code());
5082 mozilla::ipc::IPCResult
ContentParent::RecvConsoleMessage(
5083 const nsAString
& aMessage
) {
5085 nsCOMPtr
<nsIConsoleService
> consoleService
=
5086 do_GetService(NS_CONSOLESERVICE_CONTRACTID
, &rv
);
5087 if (NS_SUCCEEDED(rv
)) {
5088 RefPtr
<nsConsoleMessage
> msg(new nsConsoleMessage(aMessage
));
5089 msg
->SetIsForwardedFromContentProcess(true);
5090 consoleService
->LogMessageWithMode(msg
, nsIConsoleService::SuppressLog
);
5095 mozilla::ipc::IPCResult
ContentParent::RecvReportFrameTimingData(
5096 const LoadInfoArgs
& loadInfoArgs
, const nsAString
& entryName
,
5097 const nsAString
& initiatorType
, UniquePtr
<PerformanceTimingData
>&& aData
) {
5099 return IPC_FAIL(this, "aData should not be null");
5102 RefPtr
<WindowGlobalParent
> parent
=
5103 WindowGlobalParent::GetByInnerWindowId(loadInfoArgs
.innerWindowID());
5104 if (!parent
|| !parent
->GetContentParent()) {
5108 MOZ_ASSERT(parent
->GetContentParent() != this,
5109 "No need to bounce around if in the same process");
5111 Unused
<< parent
->GetContentParent()->SendReportFrameTimingData(
5112 loadInfoArgs
, entryName
, initiatorType
, std::move(aData
));
5116 mozilla::ipc::IPCResult
ContentParent::RecvScriptError(
5117 const nsAString
& aMessage
, const nsAString
& aSourceName
,
5118 const nsAString
& aSourceLine
, const uint32_t& aLineNumber
,
5119 const uint32_t& aColNumber
, const uint32_t& aFlags
,
5120 const nsACString
& aCategory
, const bool& aFromPrivateWindow
,
5121 const uint64_t& aInnerWindowId
, const bool& aFromChromeContext
) {
5122 return RecvScriptErrorInternal(aMessage
, aSourceName
, aSourceLine
,
5123 aLineNumber
, aColNumber
, aFlags
, aCategory
,
5124 aFromPrivateWindow
, aFromChromeContext
);
5127 mozilla::ipc::IPCResult
ContentParent::RecvScriptErrorWithStack(
5128 const nsAString
& aMessage
, const nsAString
& aSourceName
,
5129 const nsAString
& aSourceLine
, const uint32_t& aLineNumber
,
5130 const uint32_t& aColNumber
, const uint32_t& aFlags
,
5131 const nsACString
& aCategory
, const bool& aFromPrivateWindow
,
5132 const bool& aFromChromeContext
, const ClonedMessageData
& aFrame
) {
5133 return RecvScriptErrorInternal(
5134 aMessage
, aSourceName
, aSourceLine
, aLineNumber
, aColNumber
, aFlags
,
5135 aCategory
, aFromPrivateWindow
, aFromChromeContext
, &aFrame
);
5138 mozilla::ipc::IPCResult
ContentParent::RecvScriptErrorInternal(
5139 const nsAString
& aMessage
, const nsAString
& aSourceName
,
5140 const nsAString
& aSourceLine
, const uint32_t& aLineNumber
,
5141 const uint32_t& aColNumber
, const uint32_t& aFlags
,
5142 const nsACString
& aCategory
, const bool& aFromPrivateWindow
,
5143 const bool& aFromChromeContext
, const ClonedMessageData
* aStack
) {
5145 nsCOMPtr
<nsIConsoleService
> consoleService
=
5146 do_GetService(NS_CONSOLESERVICE_CONTRACTID
, &rv
);
5147 if (NS_FAILED(rv
)) {
5151 nsCOMPtr
<nsIScriptError
> msg
;
5154 StructuredCloneData data
;
5155 UnpackClonedMessageData(*aStack
, data
);
5158 if (NS_WARN_IF(!jsapi
.Init(xpc::PrivilegedJunkScope()))) {
5161 JSContext
* cx
= jsapi
.cx();
5163 JS::Rooted
<JS::Value
> stack(cx
);
5165 data
.Read(cx
, &stack
, rv
);
5166 if (rv
.Failed() || !stack
.isObject()) {
5167 rv
.SuppressException();
5171 JS::Rooted
<JSObject
*> stackObj(cx
, &stack
.toObject());
5172 if (!JS::IsUnwrappedSavedFrame(stackObj
)) {
5173 return IPC_FAIL(this, "Unexpected object");
5176 JS::Rooted
<JSObject
*> stackGlobal(cx
, JS::GetNonCCWObjectGlobal(stackObj
));
5177 msg
= new nsScriptErrorWithStack(JS::NothingHandleValue
, stackObj
,
5180 msg
= new nsScriptError();
5183 rv
= msg
->Init(aMessage
, aSourceName
, aSourceLine
, aLineNumber
, aColNumber
,
5184 aFlags
, aCategory
, aFromPrivateWindow
, aFromChromeContext
);
5185 if (NS_FAILED(rv
)) return IPC_OK();
5187 msg
->SetIsForwardedFromContentProcess(true);
5189 consoleService
->LogMessageWithMode(msg
, nsIConsoleService::SuppressLog
);
5193 bool ContentParent::DoLoadMessageManagerScript(const nsAString
& aURL
,
5194 bool aRunInGlobalScope
) {
5195 MOZ_ASSERT(!aRunInGlobalScope
);
5196 return SendLoadProcessScript(aURL
);
5199 nsresult
ContentParent::DoSendAsyncMessage(const nsAString
& aMessage
,
5200 StructuredCloneData
& aHelper
) {
5201 ClonedMessageData data
;
5202 if (!BuildClonedMessageData(aHelper
, data
)) {
5203 return NS_ERROR_DOM_DATA_CLONE_ERR
;
5205 if (!SendAsyncMessage(aMessage
, data
)) {
5206 return NS_ERROR_UNEXPECTED
;
5211 mozilla::ipc::IPCResult
ContentParent::RecvCopyFavicon(
5212 nsIURI
* aOldURI
, nsIURI
* aNewURI
, const bool& aInPrivateBrowsing
) {
5214 return IPC_FAIL(this, "aOldURI should not be null");
5217 return IPC_FAIL(this, "aNewURI should not be null");
5220 nsDocShell::CopyFavicon(aOldURI
, aNewURI
, aInPrivateBrowsing
);
5224 mozilla::ipc::IPCResult
ContentParent::RecvFindImageText(
5225 IPCImage
&& aImage
, nsTArray
<nsCString
>&& aLanguages
,
5226 FindImageTextResolver
&& aResolver
) {
5227 if (!TextRecognition::IsSupported() ||
5228 !Preferences::GetBool("dom.text-recognition.enabled")) {
5229 return IPC_FAIL(this, "Text recognition not available.");
5232 RefPtr
<DataSourceSurface
> surf
=
5233 nsContentUtils::IPCImageToSurface(std::move(aImage
));
5235 aResolver(TextRecognitionResultOrError("Failed to read image"_ns
));
5238 TextRecognition::FindText(*surf
, aLanguages
)
5240 GetCurrentSerialEventTarget(), __func__
,
5241 [resolver
= std::move(aResolver
)](
5242 TextRecognition::NativePromise::ResolveOrRejectValue
&& aValue
) {
5243 if (aValue
.IsResolve()) {
5244 resolver(TextRecognitionResultOrError(aValue
.ResolveValue()));
5246 resolver(TextRecognitionResultOrError(aValue
.RejectValue()));
5252 bool ContentParent::ShouldContinueFromReplyTimeout() {
5253 RefPtr
<ProcessHangMonitor
> monitor
= ProcessHangMonitor::Get();
5254 return !monitor
|| !monitor
->ShouldTimeOutCPOWs();
5257 mozilla::ipc::IPCResult
ContentParent::RecvAddIdleObserver(
5258 const uint64_t& aObserver
, const uint32_t& aIdleTimeInS
) {
5260 nsCOMPtr
<nsIUserIdleService
> idleService
=
5261 do_GetService("@mozilla.org/widget/useridleservice;1", &rv
);
5262 NS_ENSURE_SUCCESS(rv
, IPC_FAIL(this, "Failed to get UserIdleService."));
5264 RefPtr
<ParentIdleListener
> listener
=
5265 new ParentIdleListener(this, aObserver
, aIdleTimeInS
);
5266 rv
= idleService
->AddIdleObserver(listener
, aIdleTimeInS
);
5267 NS_ENSURE_SUCCESS(rv
, IPC_FAIL(this, "AddIdleObserver failed."));
5268 mIdleListeners
.AppendElement(listener
);
5272 mozilla::ipc::IPCResult
ContentParent::RecvRemoveIdleObserver(
5273 const uint64_t& aObserver
, const uint32_t& aIdleTimeInS
) {
5274 RefPtr
<ParentIdleListener
> listener
;
5275 for (int32_t i
= mIdleListeners
.Length() - 1; i
>= 0; --i
) {
5276 listener
= static_cast<ParentIdleListener
*>(mIdleListeners
[i
].get());
5277 if (listener
->mObserver
== aObserver
&& listener
->mTime
== aIdleTimeInS
) {
5279 nsCOMPtr
<nsIUserIdleService
> idleService
=
5280 do_GetService("@mozilla.org/widget/useridleservice;1", &rv
);
5281 NS_ENSURE_SUCCESS(rv
, IPC_FAIL(this, "Failed to get UserIdleService."));
5282 idleService
->RemoveIdleObserver(listener
, aIdleTimeInS
);
5283 mIdleListeners
.RemoveElementAt(i
);
5290 mozilla::ipc::IPCResult
ContentParent::RecvBackUpXResources(
5291 const FileDescriptor
& aXSocketFd
) {
5293 MOZ_CRASH("This message only makes sense on X11 platforms");
5295 MOZ_ASSERT(!mChildXSocketFdDup
, "Already backed up X resources??");
5296 if (aXSocketFd
.IsValid()) {
5297 mChildXSocketFdDup
= aXSocketFd
.ClonePlatformHandle();
5303 class AnonymousTemporaryFileRequestor final
: public Runnable
{
5305 AnonymousTemporaryFileRequestor(ContentParent
* aCP
, const uint64_t& aID
)
5306 : Runnable("dom::AnonymousTemporaryFileRequestor"),
5312 NS_IMETHOD
Run() override
{
5313 if (NS_IsMainThread()) {
5314 FileDescOrError result
;
5315 if (NS_WARN_IF(NS_FAILED(mRv
))) {
5316 // Returning false will kill the child process; instead
5317 // propagate the error and let the child handle it.
5320 result
= FileDescriptor(FileDescriptor::PlatformHandleType(
5321 PR_FileDesc2NativeHandle(mPRFD
)));
5322 // The FileDescriptor object owns a duplicate of the file handle; we
5323 // must close the original (and clean up the NSPR descriptor).
5326 Unused
<< mCP
->SendProvideAnonymousTemporaryFile(mID
, result
);
5327 // It's important to release this reference while wr're on the main
5331 mRv
= NS_OpenAnonymousTemporaryFile(&mPRFD
);
5332 NS_DispatchToMainThread(this);
5338 RefPtr
<ContentParent
> mCP
;
5344 mozilla::ipc::IPCResult
ContentParent::RecvRequestAnonymousTemporaryFile(
5345 const uint64_t& aID
) {
5346 // Make sure to send a callback to the child if we bail out early.
5347 nsresult rv
= NS_OK
;
5348 RefPtr
<ContentParent
> self(this);
5349 auto autoNotifyChildOnError
= MakeScopeExit([&, self
]() {
5350 if (NS_FAILED(rv
)) {
5351 FileDescOrError
result(rv
);
5352 Unused
<< self
->SendProvideAnonymousTemporaryFile(aID
, result
);
5356 // We use a helper runnable to open the anonymous temporary file on the IO
5357 // thread. The same runnable will call us back on the main thread when the
5358 // file has been opened.
5359 nsCOMPtr
<nsIEventTarget
> target
=
5360 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID
, &rv
);
5365 rv
= target
->Dispatch(new AnonymousTemporaryFileRequestor(this, aID
),
5366 NS_DISPATCH_NORMAL
);
5367 if (NS_WARN_IF(NS_FAILED(rv
))) {
5375 mozilla::ipc::IPCResult
ContentParent::RecvCreateAudioIPCConnection(
5376 CreateAudioIPCConnectionResolver
&& aResolver
) {
5377 FileDescriptor fd
= CubebUtils::CreateAudioIPCConnection();
5378 FileDescOrError result
;
5382 result
= NS_ERROR_FAILURE
;
5384 aResolver(std::move(result
));
5388 already_AddRefed
<extensions::PExtensionsParent
>
5389 ContentParent::AllocPExtensionsParent() {
5390 return MakeAndAddRef
<extensions::ExtensionsParent
>();
5393 void ContentParent::NotifyUpdatedDictionaries() {
5394 RefPtr
<mozSpellChecker
> spellChecker(mozSpellChecker::Create());
5395 MOZ_ASSERT(spellChecker
, "No spell checker?");
5397 nsTArray
<nsCString
> dictionaries
;
5398 spellChecker
->GetDictionaryList(&dictionaries
);
5400 for (auto* cp
: AllProcesses(eLive
)) {
5401 Unused
<< cp
->SendUpdateDictionaryList(dictionaries
);
5405 void ContentParent::NotifyUpdatedFonts(bool aFullRebuild
) {
5406 if (gfxPlatformFontList::PlatformFontList()->SharedFontList()) {
5407 for (auto* cp
: AllProcesses(eLive
)) {
5408 Unused
<< cp
->SendRebuildFontList(aFullRebuild
);
5413 SystemFontList fontList
;
5414 gfxPlatform::GetPlatform()->ReadSystemFontList(&fontList
);
5416 for (auto* cp
: AllProcesses(eLive
)) {
5417 Unused
<< cp
->SendUpdateFontList(fontList
);
5422 PWebrtcGlobalParent
* ContentParent::AllocPWebrtcGlobalParent() {
5423 return WebrtcGlobalParent::Alloc();
5426 bool ContentParent::DeallocPWebrtcGlobalParent(PWebrtcGlobalParent
* aActor
) {
5427 WebrtcGlobalParent::Dealloc(static_cast<WebrtcGlobalParent
*>(aActor
));
5432 void ContentParent::GetIPCTransferableData(
5433 nsIDragSession
* aSession
, BrowserParent
* aParent
,
5434 nsTArray
<IPCTransferableData
>& aIPCTransferables
) {
5435 RefPtr
<DataTransfer
> transfer
= aSession
->GetDataTransfer();
5437 // Pass eDrop to get DataTransfer with external
5438 // drag formats cached.
5439 transfer
= new DataTransfer(nullptr, eDrop
, true, -1);
5440 aSession
->SetDataTransfer(transfer
);
5442 // Note, even though this fills the DataTransfer object with
5443 // external data, the data is usually transfered over IPC lazily when
5445 transfer
->FillAllExternalData();
5446 nsCOMPtr
<nsILoadContext
> lc
= aParent
? aParent
->GetLoadContext() : nullptr;
5447 nsCOMPtr
<nsIArray
> transferables
= transfer
->GetTransferables(lc
);
5448 nsContentUtils::TransferablesToIPCTransferableDatas(
5449 transferables
, aIPCTransferables
, false, this);
5452 void ContentParent::MaybeInvokeDragSession(BrowserParent
* aParent
,
5453 EventMessage aMessage
) {
5454 // dnd uses IPCBlob to transfer data to the content process and the IPC
5455 // message is sent as normal priority. When sending input events with input
5456 // priority, the message may be preempted by the later dnd events. To make
5457 // sure the input events and the blob message are processed in time order
5458 // on the content process, we temporarily send the input events with normal
5459 // priority when there is an active dnd session.
5460 SetInputPriorityEventEnabled(false);
5462 nsCOMPtr
<nsIDragService
> dragService
=
5463 do_GetService("@mozilla.org/widget/dragservice;1");
5468 if (dragService
->MaybeAddChildProcess(this)) {
5469 nsCOMPtr
<nsIDragSession
> session
;
5470 dragService
->GetCurrentSession(getter_AddRefs(session
));
5472 // We need to send transferable data to child process.
5473 nsTArray
<IPCTransferableData
> ipcTransferables
;
5474 GetIPCTransferableData(session
, aParent
, ipcTransferables
);
5476 session
->GetDragAction(&action
);
5478 RefPtr
<WindowContext
> sourceWC
;
5479 session
->GetSourceWindowContext(getter_AddRefs(sourceWC
));
5480 RefPtr
<WindowContext
> sourceTopWC
;
5481 session
->GetSourceTopWindowContext(getter_AddRefs(sourceTopWC
));
5482 mozilla::Unused
<< SendInvokeDragSession(
5483 sourceWC
, sourceTopWC
, std::move(ipcTransferables
), action
);
5488 if (dragService
->MustUpdateDataTransfer(aMessage
)) {
5489 nsCOMPtr
<nsIDragSession
> session
;
5490 dragService
->GetCurrentSession(getter_AddRefs(session
));
5492 // We need to send transferable data to child process.
5493 nsTArray
<IPCTransferableData
> ipcTransferables
;
5494 GetIPCTransferableData(session
, aParent
, ipcTransferables
);
5495 mozilla::Unused
<< SendUpdateDragSession(std::move(ipcTransferables
),
5501 mozilla::ipc::IPCResult
ContentParent::RecvUpdateDropEffect(
5502 const uint32_t& aDragAction
, const uint32_t& aDropEffect
) {
5503 nsCOMPtr
<nsIDragSession
> dragSession
= nsContentUtils::GetDragSession();
5505 dragSession
->SetDragAction(aDragAction
);
5506 RefPtr
<DataTransfer
> dt
= dragSession
->GetDataTransfer();
5508 dt
->SetDropEffectInt(aDropEffect
);
5510 dragSession
->UpdateDragEffect();
5515 PContentPermissionRequestParent
*
5516 ContentParent::AllocPContentPermissionRequestParent(
5517 const nsTArray
<PermissionRequest
>& aRequests
, nsIPrincipal
* aPrincipal
,
5518 nsIPrincipal
* aTopLevelPrincipal
, const bool& aIsHandlingUserInput
,
5519 const bool& aMaybeUnsafePermissionDelegate
, const TabId
& aTabId
) {
5520 RefPtr
<BrowserParent
> tp
;
5521 ContentProcessManager
* cpm
= ContentProcessManager::GetSingleton();
5524 cpm
->GetTopLevelBrowserParentByProcessAndTabId(this->ChildID(), aTabId
);
5530 nsIPrincipal
* topPrincipal
= aTopLevelPrincipal
;
5531 if (!topPrincipal
) {
5532 nsCOMPtr
<nsIPrincipal
> principal
= tp
->GetContentPrincipal();
5533 topPrincipal
= principal
;
5535 return nsContentPermissionUtils::CreateContentPermissionRequestParent(
5536 aRequests
, tp
->GetOwnerElement(), aPrincipal
, topPrincipal
,
5537 aIsHandlingUserInput
, aMaybeUnsafePermissionDelegate
, aTabId
);
5540 bool ContentParent::DeallocPContentPermissionRequestParent(
5541 PContentPermissionRequestParent
* actor
) {
5542 nsContentPermissionUtils::NotifyRemoveContentPermissionRequestParent(actor
);
5547 already_AddRefed
<PWebBrowserPersistDocumentParent
>
5548 ContentParent::AllocPWebBrowserPersistDocumentParent(
5549 PBrowserParent
* aBrowser
, const MaybeDiscarded
<BrowsingContext
>& aContext
) {
5550 return MakeAndAddRef
<WebBrowserPersistDocumentParent
>();
5553 mozilla::ipc::IPCResult
ContentParent::CommonCreateWindow(
5554 PBrowserParent
* aThisTab
, BrowsingContext
& aParent
, bool aSetOpener
,
5555 const uint32_t& aChromeFlags
, const bool& aCalledFromJS
,
5556 const bool& aForPrinting
, const bool& aForWindowDotPrint
,
5557 nsIURI
* aURIToLoad
, const nsACString
& aFeatures
,
5558 const UserActivation::Modifiers
& aModifiers
,
5559 BrowserParent
* aNextRemoteBrowser
, const nsAString
& aName
,
5560 nsresult
& aResult
, nsCOMPtr
<nsIRemoteTab
>& aNewRemoteTab
,
5561 bool* aWindowIsNew
, int32_t& aOpenLocation
,
5562 nsIPrincipal
* aTriggeringPrincipal
, nsIReferrerInfo
* aReferrerInfo
,
5563 bool aLoadURI
, nsIContentSecurityPolicy
* aCsp
,
5564 const OriginAttributes
& aOriginAttributes
) {
5565 // The content process should never be in charge of computing whether or
5566 // not a window should be private - the parent will do that.
5567 const uint32_t badFlags
= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW
|
5568 nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW
|
5569 nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME
;
5570 if (!!(aChromeFlags
& badFlags
)) {
5571 return IPC_FAIL(this, "Forbidden aChromeFlags passed");
5574 RefPtr
<nsOpenWindowInfo
> openInfo
= new nsOpenWindowInfo();
5575 openInfo
->mForceNoOpener
= !aSetOpener
;
5576 openInfo
->mParent
= &aParent
;
5577 openInfo
->mIsRemote
= true;
5578 openInfo
->mIsForPrinting
= aForPrinting
;
5579 openInfo
->mIsForWindowDotPrint
= aForWindowDotPrint
;
5580 openInfo
->mNextRemoteBrowser
= aNextRemoteBrowser
;
5581 openInfo
->mOriginAttributes
= aOriginAttributes
;
5583 MOZ_ASSERT_IF(aForWindowDotPrint
, aForPrinting
);
5585 RefPtr
<BrowserParent
> topParent
= BrowserParent::GetFrom(aThisTab
);
5586 while (topParent
&& topParent
->GetBrowserBridgeParent()) {
5587 topParent
= topParent
->GetBrowserBridgeParent()->Manager();
5589 RefPtr
<BrowserHost
> thisBrowserHost
=
5590 topParent
? topParent
->GetBrowserHost() : nullptr;
5591 MOZ_ASSERT_IF(topParent
, thisBrowserHost
);
5592 RefPtr
<BrowsingContext
> topBC
=
5593 topParent
? topParent
->GetBrowsingContext() : nullptr;
5594 MOZ_ASSERT_IF(topParent
, topBC
);
5596 // The content process should have set its remote and fission flags correctly.
5598 if ((!!(aChromeFlags
& nsIWebBrowserChrome::CHROME_REMOTE_WINDOW
) !=
5599 topBC
->UseRemoteTabs()) ||
5600 (!!(aChromeFlags
& nsIWebBrowserChrome::CHROME_FISSION_WINDOW
) !=
5601 topBC
->UseRemoteSubframes())) {
5602 return IPC_FAIL(this, "Unexpected aChromeFlags passed");
5605 if (!aOriginAttributes
.EqualsIgnoringFPD(topBC
->OriginAttributesRef())) {
5606 return IPC_FAIL(this, "Passed-in OriginAttributes does not match opener");
5610 nsCOMPtr
<nsIContent
> frame
;
5612 frame
= topParent
->GetOwnerElement();
5615 nsCOMPtr
<nsPIDOMWindowOuter
> outerWin
;
5617 outerWin
= frame
->OwnerDoc()->GetWindow();
5619 // If our chrome window is in the process of closing, don't try to open a
5621 if (outerWin
&& outerWin
->Closed()) {
5626 nsCOMPtr
<nsIBrowserDOMWindow
> browserDOMWin
;
5628 browserDOMWin
= topParent
->GetBrowserDOMWindow();
5631 // If we haven't found a chrome window to open in, just use the most recently
5634 outerWin
= nsContentUtils::GetMostRecentNonPBWindow();
5635 if (NS_WARN_IF(!outerWin
)) {
5636 aResult
= NS_ERROR_FAILURE
;
5640 if (nsGlobalWindowOuter::Cast(outerWin
)->IsChromeWindow()) {
5642 nsGlobalWindowOuter::Cast(outerWin
)->GetBrowserDOMWindow();
5646 aOpenLocation
= nsWindowWatcher::GetWindowOpenLocation(
5647 outerWin
, aChromeFlags
, aModifiers
, aCalledFromJS
, aForPrinting
);
5649 MOZ_ASSERT(aOpenLocation
== nsIBrowserDOMWindow::OPEN_NEWTAB
||
5650 aOpenLocation
== nsIBrowserDOMWindow::OPEN_NEWTAB_BACKGROUND
||
5651 aOpenLocation
== nsIBrowserDOMWindow::OPEN_NEWWINDOW
||
5652 aOpenLocation
== nsIBrowserDOMWindow::OPEN_PRINT_BROWSER
);
5654 if (NS_WARN_IF(!browserDOMWin
)) {
5655 // Opening in the same window or headless requires an nsIBrowserDOMWindow.
5656 aOpenLocation
= nsIBrowserDOMWindow::OPEN_NEWWINDOW
;
5659 if (aOpenLocation
== nsIBrowserDOMWindow::OPEN_NEWTAB
||
5660 aOpenLocation
== nsIBrowserDOMWindow::OPEN_NEWTAB_BACKGROUND
||
5661 aOpenLocation
== nsIBrowserDOMWindow::OPEN_PRINT_BROWSER
) {
5662 RefPtr
<Element
> openerElement
= do_QueryObject(frame
);
5664 nsCOMPtr
<nsIOpenURIInFrameParams
> params
=
5665 new nsOpenURIInFrameParams(openInfo
, openerElement
);
5666 params
->SetReferrerInfo(aReferrerInfo
);
5667 MOZ_ASSERT(aTriggeringPrincipal
, "need a valid triggeringPrincipal");
5668 params
->SetTriggeringPrincipal(aTriggeringPrincipal
);
5669 params
->SetCsp(aCsp
);
5674 aResult
= browserDOMWin
->OpenURIInFrame(aURIToLoad
, params
, aOpenLocation
,
5675 nsIBrowserDOMWindow::OPEN_NEW
,
5676 aName
, getter_AddRefs(el
));
5678 aResult
= browserDOMWin
->CreateContentWindowInFrame(
5679 aURIToLoad
, params
, aOpenLocation
, nsIBrowserDOMWindow::OPEN_NEW
,
5680 aName
, getter_AddRefs(el
));
5682 RefPtr
<nsFrameLoaderOwner
> frameLoaderOwner
= do_QueryObject(el
);
5683 if (NS_SUCCEEDED(aResult
) && frameLoaderOwner
) {
5684 RefPtr
<nsFrameLoader
> frameLoader
= frameLoaderOwner
->GetFrameLoader();
5686 aNewRemoteTab
= frameLoader
->GetRemoteTab();
5687 // At this point, it's possible the inserted frameloader hasn't gone
5688 // through layout yet. To ensure that the dimensions that we send down
5689 // when telling the frameloader to display will be correct (instead of
5690 // falling back to a 10x10 default), we force layout if necessary to get
5691 // the most up-to-date dimensions. See bug 1358712 for details.
5692 frameLoader
->ForceLayoutIfNecessary();
5694 } else if (NS_SUCCEEDED(aResult
) && !frameLoaderOwner
) {
5695 // Fall through to the normal window opening code path when there is no
5696 // window which we can open a new tab in.
5697 aOpenLocation
= nsIBrowserDOMWindow::OPEN_NEWWINDOW
;
5699 *aWindowIsNew
= false;
5702 // If we didn't retarget our window open into a new window, we should return
5704 if (aOpenLocation
!= nsIBrowserDOMWindow::OPEN_NEWWINDOW
) {
5709 nsCOMPtr
<nsPIWindowWatcher
> pwwatch
=
5710 do_GetService(NS_WINDOWWATCHER_CONTRACTID
, &aResult
);
5711 if (NS_WARN_IF(NS_FAILED(aResult
))) {
5715 WindowFeatures features
;
5716 features
.Tokenize(aFeatures
);
5718 aResult
= pwwatch
->OpenWindowWithRemoteTab(
5719 thisBrowserHost
, features
, aModifiers
, aCalledFromJS
, aParent
.FullZoom(),
5720 openInfo
, getter_AddRefs(aNewRemoteTab
));
5721 if (NS_WARN_IF(NS_FAILED(aResult
))) {
5725 MOZ_ASSERT(aNewRemoteTab
);
5726 RefPtr
<BrowserHost
> newBrowserHost
= BrowserHost::GetFrom(aNewRemoteTab
);
5727 RefPtr
<BrowserParent
> newBrowserParent
= newBrowserHost
->GetActor();
5729 // At this point, it's possible the inserted frameloader hasn't gone through
5730 // layout yet. To ensure that the dimensions that we send down when telling
5731 // the frameloader to display will be correct (instead of falling back to a
5732 // 10x10 default), we force layout if necessary to get the most up-to-date
5733 // dimensions. See bug 1358712 for details.
5734 nsCOMPtr
<Element
> frameElement
= newBrowserHost
->GetOwnerElement();
5735 MOZ_ASSERT(frameElement
);
5736 if (nsWindowWatcher::HaveSpecifiedSize(features
)) {
5737 // We want to flush the layout anyway because of the resize to the specified
5738 // size. (Bug 1793605).
5739 RefPtr
<Document
> chromeDoc
= frameElement
->OwnerDoc();
5740 MOZ_ASSERT(chromeDoc
);
5741 chromeDoc
->FlushPendingNotifications(FlushType::Layout
);
5743 RefPtr
<nsFrameLoaderOwner
> frameLoaderOwner
= do_QueryObject(frameElement
);
5744 MOZ_ASSERT(frameLoaderOwner
);
5745 RefPtr
<nsFrameLoader
> frameLoader
= frameLoaderOwner
->GetFrameLoader();
5746 MOZ_ASSERT(frameLoader
);
5747 frameLoader
->ForceLayoutIfNecessary();
5750 // If we were passed a name for the window which would override the default,
5751 // we should send it down to the new tab.
5752 if (nsContentUtils::IsOverridingWindowName(aName
)) {
5753 MOZ_ALWAYS_SUCCEEDS(newBrowserHost
->GetBrowsingContext()->SetName(aName
));
5756 MOZ_ASSERT(newBrowserHost
->GetBrowsingContext()->OriginAttributesRef() ==
5759 if (aURIToLoad
&& aLoadURI
) {
5760 nsCOMPtr
<mozIDOMWindowProxy
> openerWindow
;
5761 if (aSetOpener
&& topParent
) {
5762 openerWindow
= topParent
->GetParentWindowOuter();
5764 nsCOMPtr
<nsIBrowserDOMWindow
> newBrowserDOMWin
=
5765 newBrowserParent
->GetBrowserDOMWindow();
5766 if (NS_WARN_IF(!newBrowserDOMWin
)) {
5767 aResult
= NS_ERROR_ABORT
;
5770 RefPtr
<BrowsingContext
> bc
;
5771 aResult
= newBrowserDOMWin
->OpenURI(
5772 aURIToLoad
, openInfo
, nsIBrowserDOMWindow::OPEN_CURRENTWINDOW
,
5773 nsIBrowserDOMWindow::OPEN_NEW
, aTriggeringPrincipal
, aCsp
,
5774 getter_AddRefs(bc
));
5780 mozilla::ipc::IPCResult
ContentParent::RecvCreateWindow(
5781 PBrowserParent
* aThisTab
, const MaybeDiscarded
<BrowsingContext
>& aParent
,
5782 PBrowserParent
* aNewTab
, const uint32_t& aChromeFlags
,
5783 const bool& aCalledFromJS
, const bool& aForPrinting
,
5784 const bool& aForPrintPreview
, nsIURI
* aURIToLoad
,
5785 const nsACString
& aFeatures
, const UserActivation::Modifiers
& aModifiers
,
5786 nsIPrincipal
* aTriggeringPrincipal
, nsIContentSecurityPolicy
* aCsp
,
5787 nsIReferrerInfo
* aReferrerInfo
, const OriginAttributes
& aOriginAttributes
,
5788 CreateWindowResolver
&& aResolve
) {
5789 if (!aTriggeringPrincipal
) {
5790 return IPC_FAIL(this, "No principal");
5793 if (!ValidatePrincipal(aTriggeringPrincipal
)) {
5794 LogAndAssertFailedPrincipalValidationInfo(aTriggeringPrincipal
, __func__
);
5797 nsresult rv
= NS_OK
;
5798 CreatedWindowInfo cwi
;
5800 // We always expect to open a new window here. If we don't, it's an error.
5801 cwi
.windowOpened() = true;
5802 cwi
.maxTouchPoints() = 0;
5804 // Make sure to resolve the resolver when this function exits, even if we
5805 // failed to generate a valid response.
5806 auto resolveOnExit
= MakeScopeExit([&] {
5807 // Copy over the nsresult, and then resolve.
5812 RefPtr
<BrowserParent
> thisTab
= BrowserParent::GetFrom(aThisTab
);
5813 RefPtr
<BrowserParent
> newTab
= BrowserParent::GetFrom(aNewTab
);
5816 auto destroyNewTabOnError
= MakeScopeExit([&] {
5817 // We always expect to open a new window here. If we don't, it's an error.
5818 if (!cwi
.windowOpened() || NS_FAILED(rv
)) {
5825 // Don't continue to try to create a new window if we've been fully discarded.
5826 RefPtr
<BrowsingContext
> parent
= aParent
.GetMaybeDiscarded();
5827 if (NS_WARN_IF(!parent
)) {
5828 rv
= NS_ERROR_FAILURE
;
5832 // Validate that our new BrowsingContext looks as we would expect it.
5833 RefPtr
<BrowsingContext
> newBC
= newTab
->GetBrowsingContext();
5835 return IPC_FAIL(this, "Missing BrowsingContext for new tab");
5838 uint64_t newBCOpenerId
= newBC
->GetOpenerId();
5839 if (newBCOpenerId
!= 0 && parent
->Id() != newBCOpenerId
) {
5840 return IPC_FAIL(this, "Invalid opener BrowsingContext for new tab");
5842 if (newBC
->GetParent() != nullptr) {
5843 return IPC_FAIL(this,
5844 "Unexpected non-toplevel BrowsingContext for new tab");
5846 if (!!(aChromeFlags
& nsIWebBrowserChrome::CHROME_REMOTE_WINDOW
) !=
5847 newBC
->UseRemoteTabs() ||
5848 !!(aChromeFlags
& nsIWebBrowserChrome::CHROME_FISSION_WINDOW
) !=
5849 newBC
->UseRemoteSubframes()) {
5850 return IPC_FAIL(this, "Unexpected aChromeFlags passed");
5852 if (!aOriginAttributes
.EqualsIgnoringFPD(newBC
->OriginAttributesRef())) {
5853 return IPC_FAIL(this, "Opened tab has mismatched OriginAttributes");
5856 if (thisTab
&& BrowserParent::GetFrom(thisTab
)->GetBrowsingContext()) {
5857 BrowsingContext
* thisTabBC
= thisTab
->GetBrowsingContext();
5858 if (thisTabBC
->UseRemoteTabs() != newBC
->UseRemoteTabs() ||
5859 thisTabBC
->UseRemoteSubframes() != newBC
->UseRemoteSubframes() ||
5860 thisTabBC
->UsePrivateBrowsing() != newBC
->UsePrivateBrowsing()) {
5861 return IPC_FAIL(this, "New BrowsingContext has mismatched LoadContext");
5864 BrowserParent::AutoUseNewTab
aunt(newTab
);
5866 nsCOMPtr
<nsIRemoteTab
> newRemoteTab
;
5867 int32_t openLocation
= nsIBrowserDOMWindow::OPEN_NEWWINDOW
;
5868 mozilla::ipc::IPCResult ipcResult
= CommonCreateWindow(
5869 aThisTab
, *parent
, newBCOpenerId
!= 0, aChromeFlags
, aCalledFromJS
,
5870 aForPrinting
, aForPrintPreview
, aURIToLoad
, aFeatures
, aModifiers
, newTab
,
5871 VoidString(), rv
, newRemoteTab
, &cwi
.windowOpened(), openLocation
,
5872 aTriggeringPrincipal
, aReferrerInfo
, /* aLoadUri = */ false, aCsp
,
5878 if (NS_WARN_IF(NS_FAILED(rv
)) || !newRemoteTab
) {
5882 MOZ_ASSERT(BrowserHost::GetFrom(newRemoteTab
.get()) ==
5883 newTab
->GetBrowserHost());
5885 // This used to happen in the child - there may now be a better place to
5887 MOZ_ALWAYS_SUCCEEDS(newBC
->SetHasSiblings(
5888 openLocation
== nsIBrowserDOMWindow::OPEN_NEWTAB
||
5889 openLocation
== nsIBrowserDOMWindow::OPEN_NEWTAB_BACKGROUND
));
5891 newTab
->SwapFrameScriptsFrom(cwi
.frameScripts());
5892 newTab
->MaybeShowFrame();
5894 nsCOMPtr
<nsIWidget
> widget
= newTab
->GetWidget();
5896 cwi
.dimensions() = newTab
->GetDimensionInfo();
5899 cwi
.maxTouchPoints() = newTab
->GetMaxTouchPoints();
5904 mozilla::ipc::IPCResult
ContentParent::RecvCreateWindowInDifferentProcess(
5905 PBrowserParent
* aThisTab
, const MaybeDiscarded
<BrowsingContext
>& aParent
,
5906 const uint32_t& aChromeFlags
, const bool& aCalledFromJS
, nsIURI
* aURIToLoad
,
5907 const nsACString
& aFeatures
, const UserActivation::Modifiers
& aModifiers
,
5908 const nsAString
& aName
, nsIPrincipal
* aTriggeringPrincipal
,
5909 nsIContentSecurityPolicy
* aCsp
, nsIReferrerInfo
* aReferrerInfo
,
5910 const OriginAttributes
& aOriginAttributes
) {
5911 MOZ_DIAGNOSTIC_ASSERT(!nsContentUtils::IsSpecialName(aName
));
5913 // Don't continue to try to create a new window if we've been fully discarded.
5914 RefPtr
<BrowsingContext
> parent
= aParent
.GetMaybeDiscarded();
5915 if (NS_WARN_IF(!parent
)) {
5919 nsCOMPtr
<nsIRemoteTab
> newRemoteTab
;
5921 int32_t openLocation
= nsIBrowserDOMWindow::OPEN_NEWWINDOW
;
5923 // If we have enough data, check the schemes of the loader and loadee
5924 // to make sure they make sense.
5925 if (aURIToLoad
&& aURIToLoad
->SchemeIs("file") &&
5926 GetRemoteType() != FILE_REMOTE_TYPE
&&
5927 Preferences::GetBool("browser.tabs.remote.enforceRemoteTypeRestrictions",
5929 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
5931 nsAutoCString uriToLoadStr
;
5932 nsAutoCString triggeringUriStr
;
5933 aURIToLoad
->GetAsciiSpec(uriToLoadStr
);
5934 aTriggeringPrincipal
->GetAsciiSpec(triggeringUriStr
);
5936 NS_WARNING(nsPrintfCString(
5937 "RecvCreateWindowInDifferentProcess blocked loading file "
5938 "scheme from non-file remotetype: %s tried to load %s",
5939 triggeringUriStr
.get(), uriToLoadStr
.get())
5943 "RecvCreateWindowInDifferentProcess blocked loading improper scheme");
5949 mozilla::ipc::IPCResult ipcResult
= CommonCreateWindow(
5950 aThisTab
, *parent
, /* aSetOpener = */ false, aChromeFlags
, aCalledFromJS
,
5951 /* aForPrinting = */ false,
5952 /* aForPrintPreview = */ false, aURIToLoad
, aFeatures
, aModifiers
,
5953 /* aNextRemoteBrowser = */ nullptr, aName
, rv
, newRemoteTab
, &windowIsNew
,
5954 openLocation
, aTriggeringPrincipal
, aReferrerInfo
,
5955 /* aLoadUri = */ true, aCsp
, aOriginAttributes
);
5960 if (NS_FAILED(rv
)) {
5961 NS_WARNING("Call to CommonCreateWindow failed.");
5967 mozilla::ipc::IPCResult
ContentParent::RecvShutdownProfile(
5968 const nsACString
& aProfile
) {
5969 profiler_received_exit_profile(aProfile
);
5973 mozilla::ipc::IPCResult
ContentParent::RecvShutdownPerfStats(
5974 const nsACString
& aPerfStats
) {
5975 PerfStats::StorePerfStats(this, aPerfStats
);
5979 mozilla::ipc::IPCResult
ContentParent::RecvGetFontListShmBlock(
5980 const uint32_t& aGeneration
, const uint32_t& aIndex
,
5981 base::SharedMemoryHandle
* aOut
) {
5982 auto* fontList
= gfxPlatformFontList::PlatformFontList();
5983 MOZ_RELEASE_ASSERT(fontList
, "gfxPlatformFontList not initialized?");
5984 fontList
->ShareFontListShmBlockToProcess(aGeneration
, aIndex
, Pid(), aOut
);
5988 mozilla::ipc::IPCResult
ContentParent::RecvInitializeFamily(
5989 const uint32_t& aGeneration
, const uint32_t& aFamilyIndex
,
5990 const bool& aLoadCmaps
) {
5991 auto* fontList
= gfxPlatformFontList::PlatformFontList();
5992 MOZ_RELEASE_ASSERT(fontList
, "gfxPlatformFontList not initialized?");
5993 fontList
->InitializeFamily(aGeneration
, aFamilyIndex
, aLoadCmaps
);
5997 mozilla::ipc::IPCResult
ContentParent::RecvSetCharacterMap(
5998 const uint32_t& aGeneration
, const uint32_t& aFamilyIndex
,
5999 const bool& aAlias
, const uint32_t& aFaceIndex
,
6000 const gfxSparseBitSet
& aMap
) {
6001 auto* fontList
= gfxPlatformFontList::PlatformFontList();
6002 MOZ_RELEASE_ASSERT(fontList
, "gfxPlatformFontList not initialized?");
6003 fontList
->SetCharacterMap(aGeneration
, aFamilyIndex
, aAlias
, aFaceIndex
,
6008 mozilla::ipc::IPCResult
ContentParent::RecvInitOtherFamilyNames(
6009 const uint32_t& aGeneration
, const bool& aDefer
, bool* aLoaded
) {
6010 auto* fontList
= gfxPlatformFontList::PlatformFontList();
6011 MOZ_RELEASE_ASSERT(fontList
, "gfxPlatformFontList not initialized?");
6012 *aLoaded
= fontList
->InitOtherFamilyNames(aGeneration
, aDefer
);
6016 mozilla::ipc::IPCResult
ContentParent::RecvSetupFamilyCharMap(
6017 const uint32_t& aGeneration
, const uint32_t& aIndex
, const bool& aAlias
) {
6018 auto* fontList
= gfxPlatformFontList::PlatformFontList();
6019 MOZ_RELEASE_ASSERT(fontList
, "gfxPlatformFontList not initialized?");
6020 fontList
->SetupFamilyCharMap(aGeneration
, aIndex
, aAlias
);
6024 mozilla::ipc::IPCResult
ContentParent::RecvStartCmapLoading(
6025 const uint32_t& aGeneration
, const uint32_t& aStartIndex
) {
6026 auto* fontList
= gfxPlatformFontList::PlatformFontList();
6027 MOZ_RELEASE_ASSERT(fontList
, "gfxPlatformFontList not initialized?");
6028 fontList
->StartCmapLoading(aGeneration
, aStartIndex
);
6032 mozilla::ipc::IPCResult
ContentParent::RecvGetHyphDict(
6033 nsIURI
* aURI
, base::SharedMemoryHandle
* aOutHandle
, uint32_t* aOutSize
) {
6035 return IPC_FAIL(this, "aURI must not be null.");
6037 nsHyphenationManager::Instance()->ShareHyphDictToProcess(
6038 aURI
, Pid(), aOutHandle
, aOutSize
);
6042 mozilla::ipc::IPCResult
ContentParent::RecvGraphicsError(
6043 const nsACString
& aError
) {
6044 if (gfx::LogForwarder
* lf
= gfx::Factory::GetLogForwarder()) {
6045 std::stringstream message
;
6046 message
<< "CP+" << aError
;
6047 lf
->UpdateStringsVector(message
.str());
6052 mozilla::ipc::IPCResult
ContentParent::RecvBeginDriverCrashGuard(
6053 const uint32_t& aGuardType
, bool* aOutCrashed
) {
6054 // Only one driver crash guard should be active at a time, per-process.
6055 MOZ_ASSERT(!mDriverCrashGuard
);
6057 UniquePtr
<gfx::DriverCrashGuard
> guard
;
6058 switch (gfx::CrashGuardType(aGuardType
)) {
6059 case gfx::CrashGuardType::D3D11Layers
:
6060 guard
= MakeUnique
<gfx::D3D11LayersCrashGuard
>(this);
6062 case gfx::CrashGuardType::GLContext
:
6063 guard
= MakeUnique
<gfx::GLContextCrashGuard
>(this);
6065 case gfx::CrashGuardType::WMFVPXVideo
:
6066 guard
= MakeUnique
<gfx::WMFVPXVideoCrashGuard
>(this);
6069 return IPC_FAIL(this, "unknown crash guard type");
6072 if (guard
->Crashed()) {
6073 *aOutCrashed
= true;
6077 *aOutCrashed
= false;
6078 mDriverCrashGuard
= std::move(guard
);
6082 mozilla::ipc::IPCResult
ContentParent::RecvEndDriverCrashGuard(
6083 const uint32_t& aGuardType
) {
6084 mDriverCrashGuard
= nullptr;
6088 mozilla::ipc::IPCResult
ContentParent::RecvNotifyBenchmarkResult(
6089 const nsAString
& aCodecName
, const uint32_t& aDecodeFPS
)
6092 if (aCodecName
.EqualsLiteral("VP9")) {
6093 Preferences::SetUint(VP9Benchmark::sBenchmarkFpsPref
, aDecodeFPS
);
6094 Preferences::SetUint(VP9Benchmark::sBenchmarkFpsVersionCheck
,
6095 VP9Benchmark::sBenchmarkVersionID
);
6100 mozilla::ipc::IPCResult
ContentParent::RecvNotifyPushObservers(
6101 const nsACString
& aScope
, nsIPrincipal
* aPrincipal
,
6102 const nsAString
& aMessageId
) {
6104 return IPC_FAIL(this, "No principal");
6107 if (!ValidatePrincipal(aPrincipal
)) {
6108 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
6110 PushMessageDispatcher
dispatcher(aScope
, aPrincipal
, aMessageId
, Nothing());
6111 Unused
<< NS_WARN_IF(NS_FAILED(dispatcher
.NotifyObserversAndWorkers()));
6115 mozilla::ipc::IPCResult
ContentParent::RecvNotifyPushObserversWithData(
6116 const nsACString
& aScope
, nsIPrincipal
* aPrincipal
,
6117 const nsAString
& aMessageId
, nsTArray
<uint8_t>&& aData
) {
6119 return IPC_FAIL(this, "No principal");
6122 if (!ValidatePrincipal(aPrincipal
)) {
6123 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
6125 PushMessageDispatcher
dispatcher(aScope
, aPrincipal
, aMessageId
,
6126 Some(std::move(aData
)));
6127 Unused
<< NS_WARN_IF(NS_FAILED(dispatcher
.NotifyObserversAndWorkers()));
6131 mozilla::ipc::IPCResult
6132 ContentParent::RecvNotifyPushSubscriptionChangeObservers(
6133 const nsACString
& aScope
, nsIPrincipal
* aPrincipal
) {
6135 return IPC_FAIL(this, "No principal");
6138 if (!ValidatePrincipal(aPrincipal
)) {
6139 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
6141 PushSubscriptionChangeDispatcher
dispatcher(aScope
, aPrincipal
);
6142 Unused
<< NS_WARN_IF(NS_FAILED(dispatcher
.NotifyObserversAndWorkers()));
6146 mozilla::ipc::IPCResult
ContentParent::RecvPushError(const nsACString
& aScope
,
6147 nsIPrincipal
* aPrincipal
,
6148 const nsAString
& aMessage
,
6149 const uint32_t& aFlags
) {
6151 return IPC_FAIL(this, "No principal");
6154 if (!ValidatePrincipal(aPrincipal
)) {
6155 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
6157 PushErrorDispatcher
dispatcher(aScope
, aPrincipal
, aMessage
, aFlags
);
6158 Unused
<< NS_WARN_IF(NS_FAILED(dispatcher
.NotifyObserversAndWorkers()));
6162 mozilla::ipc::IPCResult
6163 ContentParent::RecvNotifyPushSubscriptionModifiedObservers(
6164 const nsACString
& aScope
, nsIPrincipal
* aPrincipal
) {
6166 return IPC_FAIL(this, "No principal");
6169 if (!ValidatePrincipal(aPrincipal
)) {
6170 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
6172 PushSubscriptionModifiedDispatcher
dispatcher(aScope
, aPrincipal
);
6173 Unused
<< NS_WARN_IF(NS_FAILED(dispatcher
.NotifyObservers()));
6178 void ContentParent::BroadcastBlobURLRegistration(const nsACString
& aURI
,
6179 BlobImpl
* aBlobImpl
,
6180 nsIPrincipal
* aPrincipal
,
6181 const nsCString
& aPartitionKey
,
6182 ContentParent
* aIgnoreThisCP
) {
6183 uint64_t originHash
= ComputeLoadedOriginHash(aPrincipal
);
6186 BlobURLProtocolHandler::IsBlobURLBroadcastPrincipal(aPrincipal
);
6188 nsCString
uri(aURI
);
6190 for (auto* cp
: AllProcesses(eLive
)) {
6191 if (cp
!= aIgnoreThisCP
) {
6192 if (!toBeSent
&& !cp
->mLoadedOriginHashes
.Contains(originHash
)) {
6196 nsresult rv
= cp
->TransmitPermissionsForPrincipal(aPrincipal
);
6197 if (NS_WARN_IF(NS_FAILED(rv
))) {
6202 rv
= IPCBlobUtils::Serialize(aBlobImpl
, ipcBlob
);
6203 if (NS_WARN_IF(NS_FAILED(rv
))) {
6207 Unused
<< cp
->SendBlobURLRegistration(uri
, ipcBlob
, aPrincipal
,
6214 void ContentParent::BroadcastBlobURLUnregistration(
6215 const nsACString
& aURI
, nsIPrincipal
* aPrincipal
,
6216 ContentParent
* aIgnoreThisCP
) {
6217 uint64_t originHash
= ComputeLoadedOriginHash(aPrincipal
);
6220 BlobURLProtocolHandler::IsBlobURLBroadcastPrincipal(aPrincipal
);
6222 nsCString
uri(aURI
);
6224 for (auto* cp
: AllProcesses(eLive
)) {
6225 if (cp
!= aIgnoreThisCP
&&
6226 (toBeSent
|| cp
->mLoadedOriginHashes
.Contains(originHash
))) {
6227 Unused
<< cp
->SendBlobURLUnregistration(uri
);
6232 mozilla::ipc::IPCResult
ContentParent::RecvStoreAndBroadcastBlobURLRegistration(
6233 const nsACString
& aURI
, const IPCBlob
& aBlob
, nsIPrincipal
* aPrincipal
,
6234 const nsCString
& aPartitionKey
) {
6236 return IPC_FAIL(this, "No principal");
6239 if (!ValidatePrincipal(aPrincipal
, {ValidatePrincipalOptions::AllowSystem
})) {
6240 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
6242 RefPtr
<BlobImpl
> blobImpl
= IPCBlobUtils::Deserialize(aBlob
);
6243 if (NS_WARN_IF(!blobImpl
)) {
6244 return IPC_FAIL(this, "Blob deserialization failed.");
6247 BlobURLProtocolHandler::AddDataEntry(aURI
, aPrincipal
, aPartitionKey
,
6249 BroadcastBlobURLRegistration(aURI
, blobImpl
, aPrincipal
, aPartitionKey
, this);
6251 // We want to store this blobURL, so we can unregister it if the child
6253 mBlobURLs
.AppendElement(aURI
);
6258 mozilla::ipc::IPCResult
6259 ContentParent::RecvUnstoreAndBroadcastBlobURLUnregistration(
6260 const nsACString
& aURI
, nsIPrincipal
* aPrincipal
) {
6262 return IPC_FAIL(this, "No principal");
6265 if (!ValidatePrincipal(aPrincipal
, {ValidatePrincipalOptions::AllowSystem
})) {
6266 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
6268 BlobURLProtocolHandler::RemoveDataEntry(aURI
, false /* Don't broadcast */);
6269 BroadcastBlobURLUnregistration(aURI
, aPrincipal
, this);
6270 mBlobURLs
.RemoveElement(aURI
);
6274 mozilla::ipc::IPCResult
ContentParent::RecvGetFilesRequest(
6275 const nsID
& aUUID
, const nsAString
& aDirectoryPath
,
6276 const bool& aRecursiveFlag
) {
6277 MOZ_ASSERT(!mGetFilesPendingRequests
.GetWeak(aUUID
));
6279 if (!mozilla::Preferences::GetBool("dom.filesystem.pathcheck.disabled",
6281 RefPtr
<FileSystemSecurity
> fss
= FileSystemSecurity::Get();
6283 return IPC_FAIL(this, "Failed to get FileSystemSecurity.");
6286 if (!fss
->ContentProcessHasAccessTo(ChildID(), aDirectoryPath
)) {
6287 return IPC_FAIL(this, "ContentProcessHasAccessTo failed.");
6292 RefPtr
<GetFilesHelper
> helper
= GetFilesHelperParent::Create(
6293 aUUID
, aDirectoryPath
, aRecursiveFlag
, this, rv
);
6295 if (NS_WARN_IF(rv
.Failed())) {
6296 if (!SendGetFilesResponse(aUUID
,
6297 GetFilesResponseFailure(rv
.StealNSResult()))) {
6298 return IPC_FAIL(this, "SendGetFilesResponse failed.");
6303 mGetFilesPendingRequests
.InsertOrUpdate(aUUID
, std::move(helper
));
6307 mozilla::ipc::IPCResult
ContentParent::RecvDeleteGetFilesRequest(
6308 const nsID
& aUUID
) {
6309 mGetFilesPendingRequests
.Remove(aUUID
);
6313 void ContentParent::SendGetFilesResponseAndForget(
6314 const nsID
& aUUID
, const GetFilesResponseResult
& aResult
) {
6315 if (mGetFilesPendingRequests
.Remove(aUUID
)) {
6316 Unused
<< SendGetFilesResponse(aUUID
, aResult
);
6320 void ContentParent::PaintTabWhileInterruptingJS(BrowserParent
* aBrowserParent
) {
6321 if (!mHangMonitorActor
) {
6324 ProcessHangMonitor::PaintWhileInterruptingJS(mHangMonitorActor
,
6328 void ContentParent::UnloadLayersWhileInterruptingJS(
6329 BrowserParent
* aBrowserParent
) {
6330 if (!mHangMonitorActor
) {
6333 ProcessHangMonitor::UnloadLayersWhileInterruptingJS(mHangMonitorActor
,
6337 void ContentParent::CancelContentJSExecutionIfRunning(
6338 BrowserParent
* aBrowserParent
, nsIRemoteTab::NavigationType aNavigationType
,
6339 const CancelContentJSOptions
& aCancelContentJSOptions
) {
6340 if (!mHangMonitorActor
) {
6344 ProcessHangMonitor::CancelContentJSExecutionIfRunning(
6345 mHangMonitorActor
, aBrowserParent
, aNavigationType
,
6346 aCancelContentJSOptions
);
6349 void ContentParent::SetMainThreadQoSPriority(
6350 nsIThread::QoSPriority aQoSPriority
) {
6351 if (!mHangMonitorActor
) {
6355 ProcessHangMonitor::SetMainThreadQoSPriority(mHangMonitorActor
, aQoSPriority
);
6358 void ContentParent::UpdateCookieStatus(nsIChannel
* aChannel
) {
6359 PNeckoParent
* neckoParent
= LoneManagedOrNullAsserts(ManagedPNeckoParent());
6360 PCookieServiceParent
* csParent
=
6361 LoneManagedOrNullAsserts(neckoParent
->ManagedPCookieServiceParent());
6363 auto* cs
= static_cast<CookieServiceParent
*>(csParent
);
6364 cs
->TrackCookieLoad(aChannel
);
6368 nsresult
ContentParent::AboutToLoadHttpDocumentForChild(
6369 nsIChannel
* aChannel
, bool* aShouldWaitForPermissionCookieUpdate
) {
6370 MOZ_ASSERT(aChannel
);
6372 if (aShouldWaitForPermissionCookieUpdate
) {
6373 *aShouldWaitForPermissionCookieUpdate
= false;
6377 bool isDocument
= aChannel
->IsDocument();
6379 // We may be looking at a nsIHttpChannel which has isMainDocumentChannel set
6380 // (e.g. the internal http channel for a view-source: load.).
6381 nsCOMPtr
<nsIHttpChannel
> httpChannel
= do_QueryInterface(aChannel
);
6383 rv
= httpChannel
->GetIsMainDocumentChannel(&isDocument
);
6384 NS_ENSURE_SUCCESS(rv
, rv
);
6391 // Get the principal for the channel result, so that we can get the permission
6392 // key for the document which will be created from this response.
6393 nsIScriptSecurityManager
* ssm
= nsContentUtils::GetSecurityManager();
6394 if (NS_WARN_IF(!ssm
)) {
6395 return NS_ERROR_FAILURE
;
6398 nsCOMPtr
<nsIPrincipal
> principal
;
6399 nsCOMPtr
<nsIPrincipal
> partitionedPrincipal
;
6400 rv
= ssm
->GetChannelResultPrincipals(aChannel
, getter_AddRefs(principal
),
6401 getter_AddRefs(partitionedPrincipal
));
6402 NS_ENSURE_SUCCESS(rv
, rv
);
6404 // Let the caller know we're going to send main thread IPC for updating
6405 // permisssions/cookies.
6406 if (aShouldWaitForPermissionCookieUpdate
) {
6407 *aShouldWaitForPermissionCookieUpdate
= true;
6410 TransmitBlobURLsForPrincipal(principal
);
6412 // Tranmit permissions for both regular and partitioned principal so that the
6413 // content process can get permissions for the partitioned principal. For
6414 // example, the desk-notification permission for a partitioned service worker.
6415 rv
= TransmitPermissionsForPrincipal(principal
);
6416 NS_ENSURE_SUCCESS(rv
, rv
);
6418 rv
= TransmitPermissionsForPrincipal(partitionedPrincipal
);
6419 NS_ENSURE_SUCCESS(rv
, rv
);
6421 nsLoadFlags newLoadFlags
;
6422 aChannel
->GetLoadFlags(&newLoadFlags
);
6423 if (newLoadFlags
& nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE
) {
6424 UpdateCookieStatus(aChannel
);
6427 RefPtr
<nsILoadInfo
> loadInfo
= aChannel
->LoadInfo();
6428 RefPtr
<BrowsingContext
> browsingContext
;
6429 rv
= loadInfo
->GetTargetBrowsingContext(getter_AddRefs(browsingContext
));
6430 NS_ENSURE_SUCCESS(rv
, rv
);
6432 if (!NextGenLocalStorageEnabled()) {
6436 if (principal
->GetIsContentPrincipal()) {
6437 nsCOMPtr
<nsILocalStorageManager
> lsm
=
6438 do_GetService("@mozilla.org/dom/localStorage-manager;1");
6439 if (NS_WARN_IF(!lsm
)) {
6440 return NS_ERROR_FAILURE
;
6443 nsCOMPtr
<nsIPrincipal
> storagePrincipal
;
6444 rv
= ssm
->GetChannelResultStoragePrincipal(
6445 aChannel
, getter_AddRefs(storagePrincipal
));
6446 NS_ENSURE_SUCCESS(rv
, rv
);
6448 RefPtr
<Promise
> dummy
;
6449 rv
= lsm
->Preload(storagePrincipal
, nullptr, getter_AddRefs(dummy
));
6450 if (NS_FAILED(rv
)) {
6451 NS_WARNING("Failed to preload local storage!");
6458 nsresult
ContentParent::TransmitPermissionsForPrincipal(
6459 nsIPrincipal
* aPrincipal
) {
6460 // Create the key, and send it down to the content process.
6461 nsTArray
<std::pair
<nsCString
, nsCString
>> pairs
=
6462 PermissionManager::GetAllKeysForPrincipal(aPrincipal
);
6463 MOZ_ASSERT(pairs
.Length() >= 1);
6464 for (auto& pair
: pairs
) {
6465 EnsurePermissionsByKey(pair
.first
, pair
.second
);
6468 // We need to add the Site to the secondary keys of interest here.
6469 // This allows site-scoped permission updates to propogate when the
6470 // port is non-standard.
6471 nsAutoCString siteKey
;
6473 PermissionManager::GetKeyForPrincipal(aPrincipal
, false, true, siteKey
);
6474 if (NS_SUCCEEDED(rv
) && !siteKey
.IsEmpty()) {
6475 mActiveSecondaryPermissionKeys
.EnsureInserted(siteKey
);
6481 void ContentParent::TransmitBlobURLsForPrincipal(nsIPrincipal
* aPrincipal
) {
6482 // If we're already broadcasting BlobURLs with this principal, we don't need
6483 // to send them here.
6484 if (BlobURLProtocolHandler::IsBlobURLBroadcastPrincipal(aPrincipal
)) {
6488 // We shouldn't have any Blob URLs with expanded principals, so transmit URLs
6489 // for each principal in the AllowList instead.
6490 if (nsCOMPtr
<nsIExpandedPrincipal
> ep
= do_QueryInterface(aPrincipal
)) {
6491 for (const auto& prin
: ep
->AllowList()) {
6492 TransmitBlobURLsForPrincipal(prin
);
6497 uint64_t originHash
= ComputeLoadedOriginHash(aPrincipal
);
6499 if (!mLoadedOriginHashes
.Contains(originHash
)) {
6500 mLoadedOriginHashes
.AppendElement(originHash
);
6502 nsTArray
<BlobURLRegistrationData
> registrations
;
6503 BlobURLProtocolHandler::ForEachBlobURL(
6504 [&](BlobImpl
* aBlobImpl
, nsIPrincipal
* aBlobPrincipal
,
6505 const nsCString
& aPartitionKey
, const nsACString
& aURI
,
6507 // This check uses `ComputeLoadedOriginHash` to compare, rather than
6508 // doing the more accurate `Equals` check, as it needs to match the
6509 // behaviour of the logic to broadcast new registrations.
6510 if (originHash
!= ComputeLoadedOriginHash(aBlobPrincipal
)) {
6515 nsresult rv
= IPCBlobUtils::Serialize(aBlobImpl
, ipcBlob
);
6516 if (NS_WARN_IF(NS_FAILED(rv
))) {
6520 registrations
.AppendElement(
6521 BlobURLRegistrationData(nsCString(aURI
), ipcBlob
, aPrincipal
,
6522 nsCString(aPartitionKey
), aRevoked
));
6524 rv
= TransmitPermissionsForPrincipal(aBlobPrincipal
);
6525 Unused
<< NS_WARN_IF(NS_FAILED(rv
));
6529 if (!registrations
.IsEmpty()) {
6530 Unused
<< SendInitBlobURLs(registrations
);
6535 void ContentParent::TransmitBlobDataIfBlobURL(nsIURI
* aURI
) {
6538 nsCOMPtr
<nsIPrincipal
> principal
;
6539 if (BlobURLProtocolHandler::GetBlobURLPrincipal(aURI
,
6540 getter_AddRefs(principal
))) {
6541 TransmitBlobURLsForPrincipal(principal
);
6545 void ContentParent::EnsurePermissionsByKey(const nsACString
& aKey
,
6546 const nsACString
& aOrigin
) {
6547 // NOTE: Make sure to initialize the permission manager before updating the
6548 // mActivePermissionKeys list. If the permission manager is being initialized
6549 // by this call to GetPermissionManager, and we've added the key to
6550 // mActivePermissionKeys, then the permission manager will send down a
6551 // SendAddPermission before receiving the SendSetPermissionsWithKey message.
6552 RefPtr
<PermissionManager
> permManager
= PermissionManager::GetInstance();
6557 if (!mActivePermissionKeys
.EnsureInserted(aKey
)) {
6561 nsTArray
<IPC::Permission
> perms
;
6562 if (permManager
->GetPermissionsFromOriginOrKey(aOrigin
, aKey
, perms
)) {
6563 Unused
<< SendSetPermissionsWithKey(aKey
, perms
);
6567 bool ContentParent::NeedsPermissionsUpdate(
6568 const nsACString
& aPermissionKey
) const {
6569 return mActivePermissionKeys
.Contains(aPermissionKey
);
6572 bool ContentParent::NeedsSecondaryKeyPermissionsUpdate(
6573 const nsACString
& aPermissionKey
) const {
6574 return mActiveSecondaryPermissionKeys
.Contains(aPermissionKey
);
6577 mozilla::ipc::IPCResult
ContentParent::RecvAccumulateChildHistograms(
6578 nsTArray
<HistogramAccumulation
>&& aAccumulations
) {
6579 TelemetryIPC::AccumulateChildHistograms(GetTelemetryProcessID(mRemoteType
),
6584 mozilla::ipc::IPCResult
ContentParent::RecvAccumulateChildKeyedHistograms(
6585 nsTArray
<KeyedHistogramAccumulation
>&& aAccumulations
) {
6586 TelemetryIPC::AccumulateChildKeyedHistograms(
6587 GetTelemetryProcessID(mRemoteType
), aAccumulations
);
6591 mozilla::ipc::IPCResult
ContentParent::RecvUpdateChildScalars(
6592 nsTArray
<ScalarAction
>&& aScalarActions
) {
6593 TelemetryIPC::UpdateChildScalars(GetTelemetryProcessID(mRemoteType
),
6598 mozilla::ipc::IPCResult
ContentParent::RecvUpdateChildKeyedScalars(
6599 nsTArray
<KeyedScalarAction
>&& aScalarActions
) {
6600 TelemetryIPC::UpdateChildKeyedScalars(GetTelemetryProcessID(mRemoteType
),
6605 mozilla::ipc::IPCResult
ContentParent::RecvRecordChildEvents(
6606 nsTArray
<mozilla::Telemetry::ChildEventData
>&& aEvents
) {
6607 TelemetryIPC::RecordChildEvents(GetTelemetryProcessID(mRemoteType
), aEvents
);
6611 mozilla::ipc::IPCResult
ContentParent::RecvRecordDiscardedData(
6612 const mozilla::Telemetry::DiscardedData
& aDiscardedData
) {
6613 TelemetryIPC::RecordDiscardedData(GetTelemetryProcessID(mRemoteType
),
6618 mozilla::ipc::IPCResult
ContentParent::RecvRecordPageLoadEvent(
6619 const mozilla::glean::perf::PageLoadExtra
& aPageLoadEventExtra
) {
6620 mozilla::glean::perf::page_load
.Record(mozilla::Some(aPageLoadEventExtra
));
6622 // Send the PageLoadPing after every 30 page loads, or on startup.
6623 if (++sPageLoadEventCounter
>= 30) {
6624 NS_SUCCEEDED(NS_DispatchToMainThreadQueue(
6625 NS_NewRunnableFunction(
6626 "PageLoadPingIdleTask",
6627 [] { mozilla::glean_pings::Pageload
.Submit("threshold"_ns
); }),
6628 EventQueuePriority::Idle
));
6629 sPageLoadEventCounter
= 0;
6635 //////////////////////////////////////////////////////////////////
6636 // PURLClassifierParent
6638 PURLClassifierParent
* ContentParent::AllocPURLClassifierParent(
6639 nsIPrincipal
* aPrincipal
, bool* aSuccess
) {
6640 MOZ_ASSERT(NS_IsMainThread());
6643 RefPtr
<URLClassifierParent
> actor
= new URLClassifierParent();
6644 return actor
.forget().take();
6647 mozilla::ipc::IPCResult
ContentParent::RecvPURLClassifierConstructor(
6648 PURLClassifierParent
* aActor
, nsIPrincipal
* aPrincipal
, bool* aSuccess
) {
6649 MOZ_ASSERT(NS_IsMainThread());
6653 auto* actor
= static_cast<URLClassifierParent
*>(aActor
);
6654 nsCOMPtr
<nsIPrincipal
> principal(aPrincipal
);
6656 actor
->ClassificationFailed();
6659 if (!ValidatePrincipal(aPrincipal
)) {
6660 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
6662 return actor
->StartClassify(principal
, aSuccess
);
6665 bool ContentParent::DeallocPURLClassifierParent(PURLClassifierParent
* aActor
) {
6666 MOZ_ASSERT(NS_IsMainThread());
6669 RefPtr
<URLClassifierParent
> actor
=
6670 dont_AddRef(static_cast<URLClassifierParent
*>(aActor
));
6674 //////////////////////////////////////////////////////////////////
6675 // PURLClassifierLocalParent
6677 PURLClassifierLocalParent
* ContentParent::AllocPURLClassifierLocalParent(
6678 nsIURI
* aURI
, const nsTArray
<IPCURLClassifierFeature
>& aFeatures
) {
6679 MOZ_ASSERT(NS_IsMainThread());
6681 RefPtr
<URLClassifierLocalParent
> actor
= new URLClassifierLocalParent();
6682 return actor
.forget().take();
6685 mozilla::ipc::IPCResult
ContentParent::RecvPURLClassifierLocalConstructor(
6686 PURLClassifierLocalParent
* aActor
, nsIURI
* aURI
,
6687 nsTArray
<IPCURLClassifierFeature
>&& aFeatures
) {
6688 MOZ_ASSERT(NS_IsMainThread());
6691 nsTArray
<IPCURLClassifierFeature
> features
= std::move(aFeatures
);
6694 return IPC_FAIL(this, "aURI should not be null");
6697 auto* actor
= static_cast<URLClassifierLocalParent
*>(aActor
);
6698 return actor
->StartClassify(aURI
, features
);
6701 bool ContentParent::DeallocPURLClassifierLocalParent(
6702 PURLClassifierLocalParent
* aActor
) {
6703 MOZ_ASSERT(NS_IsMainThread());
6706 RefPtr
<URLClassifierLocalParent
> actor
=
6707 dont_AddRef(static_cast<URLClassifierLocalParent
*>(aActor
));
6711 PSessionStorageObserverParent
*
6712 ContentParent::AllocPSessionStorageObserverParent() {
6713 MOZ_ASSERT(NS_IsMainThread());
6715 return mozilla::dom::AllocPSessionStorageObserverParent();
6718 mozilla::ipc::IPCResult
ContentParent::RecvPSessionStorageObserverConstructor(
6719 PSessionStorageObserverParent
* aActor
) {
6720 MOZ_ASSERT(NS_IsMainThread());
6723 if (!mozilla::dom::RecvPSessionStorageObserverConstructor(aActor
)) {
6724 return IPC_FAIL(this, "RecvPSessionStorageObserverConstructor failed.");
6729 bool ContentParent::DeallocPSessionStorageObserverParent(
6730 PSessionStorageObserverParent
* aActor
) {
6731 MOZ_ASSERT(NS_IsMainThread());
6734 return mozilla::dom::DeallocPSessionStorageObserverParent(aActor
);
6737 mozilla::ipc::IPCResult
ContentParent::RecvBHRThreadHang(
6738 const HangDetails
& aDetails
) {
6739 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
6741 // Copy the HangDetails recieved over the network into a nsIHangDetails, and
6742 // then fire our own observer notification.
6743 // XXX: We should be able to avoid this potentially expensive copy here by
6744 // moving our deserialized argument.
6745 nsCOMPtr
<nsIHangDetails
> hangDetails
=
6746 new nsHangDetails(HangDetails(aDetails
), PersistedToDisk::No
);
6747 obs
->NotifyObservers(hangDetails
, "bhr-thread-hang", nullptr);
6752 mozilla::ipc::IPCResult
ContentParent::RecvAddCertException(
6753 nsIX509Cert
* aCert
, const nsACString
& aHostName
, int32_t aPort
,
6754 const OriginAttributes
& aOriginAttributes
, bool aIsTemporary
,
6755 AddCertExceptionResolver
&& aResolver
) {
6756 nsCOMPtr
<nsICertOverrideService
> overrideService
=
6757 do_GetService(NS_CERTOVERRIDE_CONTRACTID
);
6758 if (!overrideService
) {
6759 aResolver(NS_ERROR_FAILURE
);
6762 nsresult rv
= overrideService
->RememberValidityOverride(
6763 aHostName
, aPort
, aOriginAttributes
, aCert
, aIsTemporary
);
6768 mozilla::ipc::IPCResult
6769 ContentParent::RecvAutomaticStorageAccessPermissionCanBeGranted(
6770 nsIPrincipal
* aPrincipal
,
6771 AutomaticStorageAccessPermissionCanBeGrantedResolver
&& aResolver
) {
6773 return IPC_FAIL(this, "No principal");
6776 if (!ValidatePrincipal(aPrincipal
)) {
6777 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
6779 aResolver(Document::AutomaticStorageAccessPermissionCanBeGranted(aPrincipal
));
6783 mozilla::ipc::IPCResult
6784 ContentParent::RecvStorageAccessPermissionGrantedForOrigin(
6785 uint64_t aTopLevelWindowId
,
6786 const MaybeDiscarded
<BrowsingContext
>& aParentContext
,
6787 nsIPrincipal
* aTrackingPrincipal
, const nsACString
& aTrackingOrigin
,
6788 const int& aAllowMode
,
6789 const Maybe
<ContentBlockingNotifier::StorageAccessPermissionGrantedReason
>&
6791 const bool& aFrameOnly
,
6792 StorageAccessPermissionGrantedForOriginResolver
&& aResolver
) {
6793 if (aParentContext
.IsNullOrDiscarded()) {
6797 if (!aTrackingPrincipal
) {
6798 return IPC_FAIL(this, "No principal");
6801 // We only report here if we cannot report the console directly in the content
6802 // process. In that case, the `aReason` would be given a value. Otherwise, it
6805 ContentBlockingNotifier::ReportUnblockingToConsole(
6806 aParentContext
.get_canonical(), NS_ConvertUTF8toUTF16(aTrackingOrigin
),
6810 StorageAccessAPIHelper::SaveAccessForOriginOnParentProcess(
6811 aTopLevelWindowId
, aParentContext
.get_canonical(), aTrackingPrincipal
,
6812 aAllowMode
, aFrameOnly
)
6813 ->Then(GetCurrentSerialEventTarget(), __func__
,
6814 [aResolver
= std::move(aResolver
)](
6815 StorageAccessAPIHelper::ParentAccessGrantPromise::
6816 ResolveOrRejectValue
&& aValue
) {
6818 aValue
.IsResolve() && NS_SUCCEEDED(aValue
.ResolveValue());
6824 mozilla::ipc::IPCResult
ContentParent::RecvCompleteAllowAccessFor(
6825 const MaybeDiscarded
<BrowsingContext
>& aParentContext
,
6826 uint64_t aTopLevelWindowId
, nsIPrincipal
* aTrackingPrincipal
,
6827 const nsACString
& aTrackingOrigin
, uint32_t aCookieBehavior
,
6828 const ContentBlockingNotifier::StorageAccessPermissionGrantedReason
&
6830 CompleteAllowAccessForResolver
&& aResolver
) {
6831 if (aParentContext
.IsNullOrDiscarded()) {
6835 StorageAccessAPIHelper::CompleteAllowAccessForOnParentProcess(
6836 aParentContext
.get_canonical(), aTopLevelWindowId
, aTrackingPrincipal
,
6837 aTrackingOrigin
, aCookieBehavior
, aReason
, nullptr)
6838 ->Then(GetCurrentSerialEventTarget(), __func__
,
6839 [aResolver
= std::move(aResolver
)](
6840 StorageAccessAPIHelper::StorageAccessPermissionGrantPromise::
6841 ResolveOrRejectValue
&& aValue
) {
6842 Maybe
<StorageAccessPromptChoices
> choice
;
6843 if (aValue
.IsResolve()) {
6844 choice
.emplace(static_cast<StorageAccessPromptChoices
>(
6845 aValue
.ResolveValue()));
6852 mozilla::ipc::IPCResult
ContentParent::RecvSetAllowStorageAccessRequestFlag(
6853 nsIPrincipal
* aEmbeddedPrincipal
, nsIURI
* aEmbeddingOrigin
,
6854 SetAllowStorageAccessRequestFlagResolver
&& aResolver
) {
6855 MOZ_ASSERT(aEmbeddedPrincipal
);
6856 MOZ_ASSERT(aEmbeddingOrigin
);
6858 if (!aEmbeddedPrincipal
|| !aEmbeddingOrigin
) {
6863 // Get the permission manager and build the key.
6864 RefPtr
<PermissionManager
> permManager
= PermissionManager::GetInstance();
6869 nsCOMPtr
<nsIURI
> embeddedURI
= aEmbeddedPrincipal
->GetURI();
6870 nsCString permissionKey
;
6871 bool success
= AntiTrackingUtils::CreateStorageRequestPermissionKey(
6872 embeddedURI
, permissionKey
);
6878 // Set the permission to ALLOW for a prefence specified amount of seconds.
6879 // Time units are inconsistent, be careful
6880 int64_t when
= (PR_Now() / PR_USEC_PER_MSEC
) +
6881 StaticPrefs::dom_storage_access_forward_declared_lifetime() *
6883 nsCOMPtr
<nsIPrincipal
> principal
= BasePrincipal::CreateContentPrincipal(
6884 aEmbeddingOrigin
, aEmbeddedPrincipal
->OriginAttributesRef());
6885 nsresult rv
= permManager
->AddFromPrincipal(
6886 principal
, permissionKey
, nsIPermissionManager::ALLOW_ACTION
,
6887 nsIPermissionManager::EXPIRE_TIME
, when
);
6888 if (NS_FAILED(rv
)) {
6893 // Resolve with success if we set the permission.
6898 mozilla::ipc::IPCResult
ContentParent::RecvTestAllowStorageAccessRequestFlag(
6899 nsIPrincipal
* aEmbeddingPrincipal
, nsIURI
* aEmbeddedOrigin
,
6900 TestAllowStorageAccessRequestFlagResolver
&& aResolver
) {
6901 MOZ_ASSERT(aEmbeddingPrincipal
);
6902 MOZ_ASSERT(aEmbeddedOrigin
);
6904 // Get the permission manager and build the key.
6905 RefPtr
<PermissionManager
> permManager
= PermissionManager::GetInstance();
6910 nsCString requestPermissionKey
;
6911 bool success
= AntiTrackingUtils::CreateStorageRequestPermissionKey(
6912 aEmbeddedOrigin
, requestPermissionKey
);
6918 // Get the permission and resolve false if it is not set to ALLOW.
6919 uint32_t access
= nsIPermissionManager::UNKNOWN_ACTION
;
6920 nsresult rv
= permManager
->TestPermissionFromPrincipal(
6921 aEmbeddingPrincipal
, requestPermissionKey
, &access
);
6922 if (NS_FAILED(rv
)) {
6926 if (access
!= nsIPermissionManager::ALLOW_ACTION
) {
6931 // Remove the permission, failing if the permission manager fails
6932 rv
= permManager
->RemoveFromPrincipal(aEmbeddingPrincipal
,
6933 requestPermissionKey
);
6934 if (NS_FAILED(rv
)) {
6939 // At this point, signal to our caller that the permission was set
6944 mozilla::ipc::IPCResult
ContentParent::RecvStoreUserInteractionAsPermission(
6945 nsIPrincipal
* aPrincipal
) {
6947 return IPC_FAIL(this, "No principal");
6950 if (!ValidatePrincipal(aPrincipal
)) {
6951 LogAndAssertFailedPrincipalValidationInfo(aPrincipal
, __func__
);
6953 ContentBlockingUserInteraction::Observe(aPrincipal
);
6957 mozilla::ipc::IPCResult
ContentParent::RecvTestCookiePermissionDecided(
6958 const MaybeDiscarded
<BrowsingContext
>& aContext
, nsIPrincipal
* aPrincipal
,
6959 const TestCookiePermissionDecidedResolver
&& aResolver
) {
6960 if (aContext
.IsNullOrDiscarded()) {
6965 return IPC_FAIL(this, "No principal");
6968 RefPtr
<WindowGlobalParent
> wgp
=
6969 aContext
.get_canonical()->GetCurrentWindowGlobal();
6970 nsCOMPtr
<nsICookieJarSettings
> cjs
= wgp
->CookieJarSettings();
6972 Maybe
<bool> result
=
6973 StorageAccessAPIHelper::CheckCookiesPermittedDecidesStorageAccessAPI(
6979 mozilla::ipc::IPCResult
ContentParent::RecvTestStorageAccessPermission(
6980 nsIPrincipal
* aEmbeddingPrincipal
, const nsCString
& aEmbeddedOrigin
,
6981 const TestStorageAccessPermissionResolver
&& aResolver
) {
6982 // Get the permission manager and build the key.
6983 RefPtr
<PermissionManager
> permManager
= PermissionManager::GetInstance();
6985 aResolver(Nothing());
6988 nsCString requestPermissionKey
;
6989 AntiTrackingUtils::CreateStoragePermissionKey(aEmbeddedOrigin
,
6990 requestPermissionKey
);
6992 // Test the permission
6993 uint32_t access
= nsIPermissionManager::UNKNOWN_ACTION
;
6994 nsresult rv
= permManager
->TestPermissionFromPrincipal(
6995 aEmbeddingPrincipal
, requestPermissionKey
, &access
);
6996 if (NS_FAILED(rv
)) {
6997 aResolver(Nothing());
7000 if (access
== nsIPermissionManager::ALLOW_ACTION
) {
7001 aResolver(Some(true));
7002 } else if (access
== nsIPermissionManager::DENY_ACTION
) {
7003 aResolver(Some(false));
7005 aResolver(Nothing());
7011 mozilla::ipc::IPCResult
ContentParent::RecvNotifyMediaPlaybackChanged(
7012 const MaybeDiscarded
<BrowsingContext
>& aContext
,
7013 MediaPlaybackState aState
) {
7014 if (aContext
.IsNullOrDiscarded()) {
7017 if (RefPtr
<IMediaInfoUpdater
> updater
=
7018 aContext
.get_canonical()->GetMediaController()) {
7019 updater
->NotifyMediaPlaybackChanged(aContext
.ContextId(), aState
);
7024 mozilla::ipc::IPCResult
ContentParent::RecvNotifyMediaAudibleChanged(
7025 const MaybeDiscarded
<BrowsingContext
>& aContext
, MediaAudibleState aState
) {
7026 if (aContext
.IsNullOrDiscarded()) {
7029 if (RefPtr
<IMediaInfoUpdater
> updater
=
7030 aContext
.get_canonical()->GetMediaController()) {
7031 updater
->NotifyMediaAudibleChanged(aContext
.ContextId(), aState
);
7036 mozilla::ipc::IPCResult
ContentParent::RecvNotifyPictureInPictureModeChanged(
7037 const MaybeDiscarded
<BrowsingContext
>& aContext
, bool aEnabled
) {
7038 if (aContext
.IsNullOrDiscarded()) {
7041 if (RefPtr
<MediaController
> controller
=
7042 aContext
.get_canonical()->GetMediaController()) {
7043 controller
->SetIsInPictureInPictureMode(aContext
.ContextId(), aEnabled
);
7048 mozilla::ipc::IPCResult
ContentParent::RecvAbortOtherOrientationPendingPromises(
7049 const MaybeDiscarded
<BrowsingContext
>& aContext
) {
7050 if (aContext
.IsNullOrDiscarded()) {
7054 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7056 context
->Group()->EachOtherParent(this, [&](ContentParent
* aParent
) {
7057 Unused
<< aParent
->SendAbortOrientationPendingPromises(context
);
7063 mozilla::ipc::IPCResult
ContentParent::RecvNotifyMediaSessionUpdated(
7064 const MaybeDiscarded
<BrowsingContext
>& aContext
, bool aIsCreated
) {
7065 if (aContext
.IsNullOrDiscarded()) {
7069 RefPtr
<IMediaInfoUpdater
> updater
=
7070 aContext
.get_canonical()->GetMediaController();
7075 updater
->NotifySessionCreated(aContext
->Id());
7077 updater
->NotifySessionDestroyed(aContext
->Id());
7082 mozilla::ipc::IPCResult
ContentParent::RecvNotifyUpdateMediaMetadata(
7083 const MaybeDiscarded
<BrowsingContext
>& aContext
,
7084 const Maybe
<MediaMetadataBase
>& aMetadata
) {
7085 if (aContext
.IsNullOrDiscarded()) {
7088 if (RefPtr
<IMediaInfoUpdater
> updater
=
7089 aContext
.get_canonical()->GetMediaController()) {
7090 updater
->UpdateMetadata(aContext
.ContextId(), aMetadata
);
7095 mozilla::ipc::IPCResult
7096 ContentParent::RecvNotifyMediaSessionPlaybackStateChanged(
7097 const MaybeDiscarded
<BrowsingContext
>& aContext
,
7098 MediaSessionPlaybackState aPlaybackState
) {
7099 if (aContext
.IsNullOrDiscarded()) {
7102 if (RefPtr
<IMediaInfoUpdater
> updater
=
7103 aContext
.get_canonical()->GetMediaController()) {
7104 updater
->SetDeclaredPlaybackState(aContext
.ContextId(), aPlaybackState
);
7109 mozilla::ipc::IPCResult
7110 ContentParent::RecvNotifyMediaSessionSupportedActionChanged(
7111 const MaybeDiscarded
<BrowsingContext
>& aContext
, MediaSessionAction aAction
,
7113 if (aContext
.IsNullOrDiscarded()) {
7116 RefPtr
<IMediaInfoUpdater
> updater
=
7117 aContext
.get_canonical()->GetMediaController();
7122 updater
->EnableAction(aContext
.ContextId(), aAction
);
7124 updater
->DisableAction(aContext
.ContextId(), aAction
);
7129 mozilla::ipc::IPCResult
ContentParent::RecvNotifyMediaFullScreenState(
7130 const MaybeDiscarded
<BrowsingContext
>& aContext
, bool aIsInFullScreen
) {
7131 if (aContext
.IsNullOrDiscarded()) {
7134 if (RefPtr
<IMediaInfoUpdater
> updater
=
7135 aContext
.get_canonical()->GetMediaController()) {
7136 updater
->NotifyMediaFullScreenState(aContext
.ContextId(), aIsInFullScreen
);
7141 mozilla::ipc::IPCResult
ContentParent::RecvNotifyPositionStateChanged(
7142 const MaybeDiscarded
<BrowsingContext
>& aContext
,
7143 const Maybe
<PositionState
>& aState
) {
7144 if (aContext
.IsNullOrDiscarded()) {
7147 if (RefPtr
<IMediaInfoUpdater
> updater
=
7148 aContext
.get_canonical()->GetMediaController()) {
7149 updater
->UpdatePositionState(aContext
.ContextId(), aState
);
7154 mozilla::ipc::IPCResult
ContentParent::RecvAddOrRemovePageAwakeRequest(
7155 const MaybeDiscarded
<BrowsingContext
>& aContext
,
7156 const bool& aShouldAddCount
) {
7157 if (aContext
.IsNullOrDiscarded()) {
7160 if (aShouldAddCount
) {
7161 aContext
.get_canonical()->AddPageAwakeRequest();
7163 aContext
.get_canonical()->RemovePageAwakeRequest();
7169 mozilla::ipc::IPCResult
ContentParent::RecvGetModulesTrust(
7170 ModulePaths
&& aModPaths
, bool aRunAtNormalPriority
,
7171 GetModulesTrustResolver
&& aResolver
) {
7172 RefPtr
<DllServices
> dllSvc(DllServices::Get());
7173 dllSvc
->GetModulesTrust(std::move(aModPaths
), aRunAtNormalPriority
)
7175 GetMainThreadSerialEventTarget(), __func__
,
7176 [aResolver
](ModulesMapResult
&& aResult
) {
7177 aResolver(Some(ModulesMapResult(std::move(aResult
))));
7179 [aResolver
](nsresult aRv
) { aResolver(Nothing()); });
7182 #endif // defined(XP_WIN)
7184 mozilla::ipc::IPCResult
ContentParent::RecvCreateBrowsingContext(
7185 uint64_t aGroupId
, BrowsingContext::IPCInitializer
&& aInit
) {
7186 RefPtr
<WindowGlobalParent
> parent
;
7187 if (aInit
.mParentId
!= 0) {
7188 parent
= WindowGlobalParent::GetByInnerWindowId(aInit
.mParentId
);
7190 return IPC_FAIL(this, "Parent doesn't exist in parent process");
7194 if (parent
&& parent
->GetContentParent() != this) {
7195 // We're trying attach a child BrowsingContext to a parent
7196 // WindowContext in another process. This is illegal since the
7197 // only thing that could create that child BrowsingContext is the parent
7198 // window's process.
7199 return IPC_FAIL(this,
7200 "Must create BrowsingContext from the parent's process");
7203 RefPtr
<BrowsingContext
> opener
;
7204 if (aInit
.GetOpenerId() != 0) {
7205 opener
= BrowsingContext::Get(aInit
.GetOpenerId());
7207 return IPC_FAIL(this, "Opener doesn't exist in parent process");
7211 RefPtr
<BrowsingContext
> child
= BrowsingContext::Get(aInit
.mId
);
7213 // This is highly suspicious. BrowsingContexts should only be created once,
7214 // so finding one indicates that someone is doing something they shouldn't.
7215 return IPC_FAIL(this, "A BrowsingContext with this ID already exists");
7218 // Ensure that the passed-in BrowsingContextGroup is valid.
7219 RefPtr
<BrowsingContextGroup
> group
=
7220 BrowsingContextGroup::GetOrCreate(aGroupId
);
7221 if (parent
&& parent
->Group() != group
) {
7222 if (parent
->Group()->Id() != aGroupId
) {
7223 return IPC_FAIL(this, "Parent has different group ID");
7225 return IPC_FAIL(this, "Parent has different group object");
7228 if (opener
&& opener
->Group() != group
) {
7229 if (opener
->Group()->Id() != aGroupId
) {
7230 return IPC_FAIL(this, "Opener has different group ID");
7232 return IPC_FAIL(this, "Opener has different group object");
7235 if (!parent
&& !opener
&& !group
->Toplevels().IsEmpty()) {
7236 return IPC_FAIL(this, "Unrelated context from child in stale group");
7239 return BrowsingContext::CreateFromIPC(std::move(aInit
), group
, this);
7242 bool ContentParent::CheckBrowsingContextEmbedder(CanonicalBrowsingContext
* aBC
,
7243 const char* aOperation
) const {
7244 if (!aBC
->IsEmbeddedInProcess(ChildID())) {
7245 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Warning
,
7246 ("ParentIPC: Trying to %s out of process context 0x%08" PRIx64
,
7247 aOperation
, aBC
->Id()));
7253 mozilla::ipc::IPCResult
ContentParent::RecvDiscardBrowsingContext(
7254 const MaybeDiscarded
<BrowsingContext
>& aContext
, bool aDoDiscard
,
7255 DiscardBrowsingContextResolver
&& aResolve
) {
7256 if (CanonicalBrowsingContext
* context
=
7257 CanonicalBrowsingContext::Cast(aContext
.GetMaybeDiscarded())) {
7258 if (aDoDiscard
&& !context
->IsDiscarded()) {
7259 if (!CheckBrowsingContextEmbedder(context
, "discard")) {
7260 return IPC_FAIL(this, "Illegal Discard attempt");
7263 context
->Detach(/* aFromIPC */ true);
7265 context
->AddFinalDiscardListener(aResolve
);
7269 // Resolve the promise, as we've received and handled the message. This will
7270 // allow the content process to fully-discard references to this BC.
7275 void ContentParent::UnregisterRemoveWorkerActor() {
7276 MOZ_ASSERT(NS_IsMainThread());
7279 RecursiveMutexAutoLock
lock(mThreadsafeHandle
->mMutex
);
7280 if (--mThreadsafeHandle
->mRemoteWorkerActorCount
) {
7285 MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose
,
7286 ("UnregisterRemoveWorkerActor %p", this));
7287 MaybeBeginShutDown();
7290 mozilla::ipc::IPCResult
ContentParent::RecvWindowClose(
7291 const MaybeDiscarded
<BrowsingContext
>& aContext
, bool aTrustedCaller
) {
7292 if (aContext
.IsNullOrDiscarded()) {
7294 BrowsingContext::GetLog(), LogLevel::Debug
,
7295 ("ParentIPC: Trying to send a message to dead or detached context"));
7298 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7300 // FIXME Need to check that the sending process has access to the unit of
7302 // browsing contexts of bc.
7304 if (ContentParent
* cp
= context
->GetContentParent()) {
7305 Unused
<< cp
->SendWindowClose(context
, aTrustedCaller
);
7310 mozilla::ipc::IPCResult
ContentParent::RecvWindowFocus(
7311 const MaybeDiscarded
<BrowsingContext
>& aContext
, CallerType aCallerType
,
7312 uint64_t aActionId
) {
7313 if (aContext
.IsNullOrDiscarded()) {
7315 BrowsingContext::GetLog(), LogLevel::Debug
,
7316 ("ParentIPC: Trying to send a message to dead or detached context"));
7319 LOGFOCUS(("ContentParent::RecvWindowFocus actionid: %" PRIu64
, aActionId
));
7320 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7322 if (ContentParent
* cp
= context
->GetContentParent()) {
7323 Unused
<< cp
->SendWindowFocus(context
, aCallerType
, aActionId
);
7328 mozilla::ipc::IPCResult
ContentParent::RecvWindowBlur(
7329 const MaybeDiscarded
<BrowsingContext
>& aContext
, CallerType aCallerType
) {
7330 if (aContext
.IsNullOrDiscarded()) {
7332 BrowsingContext::GetLog(), LogLevel::Debug
,
7333 ("ParentIPC: Trying to send a message to dead or detached context"));
7336 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7338 if (ContentParent
* cp
= context
->GetContentParent()) {
7339 Unused
<< cp
->SendWindowBlur(context
, aCallerType
);
7344 mozilla::ipc::IPCResult
ContentParent::RecvRaiseWindow(
7345 const MaybeDiscarded
<BrowsingContext
>& aContext
, CallerType aCallerType
,
7346 uint64_t aActionId
) {
7347 if (aContext
.IsNullOrDiscarded()) {
7349 BrowsingContext::GetLog(), LogLevel::Debug
,
7350 ("ParentIPC: Trying to send a message to dead or detached context"));
7353 LOGFOCUS(("ContentParent::RecvRaiseWindow actionid: %" PRIu64
, aActionId
));
7355 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7357 if (ContentParent
* cp
= context
->GetContentParent()) {
7358 Unused
<< cp
->SendRaiseWindow(context
, aCallerType
, aActionId
);
7363 mozilla::ipc::IPCResult
ContentParent::RecvAdjustWindowFocus(
7364 const MaybeDiscarded
<BrowsingContext
>& aContext
, bool aIsVisible
,
7365 uint64_t aActionId
, bool aShouldClearFocus
,
7366 const MaybeDiscarded
<BrowsingContext
>& aAncestorBrowsingContextToFocus
) {
7367 if (aContext
.IsNullOrDiscarded()) {
7369 BrowsingContext::GetLog(), LogLevel::Debug
,
7370 ("ParentIPC: Trying to send a message to dead or detached context"));
7374 ("ContentParent::RecvAdjustWindowFocus isVisible %d actionid: %" PRIu64
,
7375 aIsVisible
, aActionId
));
7377 nsTHashMap
<nsPtrHashKey
<ContentParent
>, bool> processes(2);
7378 processes
.InsertOrUpdate(this, true);
7380 ContentProcessManager
* cpm
= ContentProcessManager::GetSingleton();
7382 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7384 BrowsingContext
* parent
= context
->GetParent();
7389 CanonicalBrowsingContext
* canonicalParent
= parent
->Canonical();
7390 ContentParent
* cp
= cpm
->GetContentProcessById(
7391 ContentParentId(canonicalParent
->OwnerProcessId()));
7392 if (cp
&& !processes
.Get(cp
)) {
7393 Unused
<< cp
->SendAdjustWindowFocus(context
, aIsVisible
, aActionId
,
7395 aAncestorBrowsingContextToFocus
);
7396 processes
.InsertOrUpdate(cp
, true);
7398 context
= canonicalParent
;
7404 mozilla::ipc::IPCResult
ContentParent::RecvClearFocus(
7405 const MaybeDiscarded
<BrowsingContext
>& aContext
) {
7406 if (aContext
.IsNullOrDiscarded()) {
7408 BrowsingContext::GetLog(), LogLevel::Debug
,
7409 ("ParentIPC: Trying to send a message to dead or detached context"));
7412 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7414 if (ContentParent
* cp
= context
->GetContentParent()) {
7415 Unused
<< cp
->SendClearFocus(context
);
7420 mozilla::ipc::IPCResult
ContentParent::RecvSetFocusedBrowsingContext(
7421 const MaybeDiscarded
<BrowsingContext
>& aContext
, uint64_t aActionId
) {
7422 if (aContext
.IsNullOrDiscarded()) {
7424 BrowsingContext::GetLog(), LogLevel::Debug
,
7425 ("ParentIPC: Trying to send a message to dead or detached context"));
7428 LOGFOCUS(("ContentParent::RecvSetFocusedBrowsingContext actionid: %" PRIu64
,
7430 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7432 nsFocusManager
* fm
= nsFocusManager::GetFocusManager();
7437 if (!fm
->SetFocusedBrowsingContextInChrome(context
, aActionId
)) {
7439 "Ignoring out-of-sequence attempt [%p] to set focused browsing context "
7442 Unused
<< SendReviseFocusedBrowsingContext(
7443 aActionId
, fm
->GetFocusedBrowsingContextInChrome(),
7444 fm
->GetActionIdForFocusedBrowsingContextInChrome());
7448 BrowserParent::UpdateFocusFromBrowsingContext();
7450 context
->Group()->EachOtherParent(this, [&](ContentParent
* aParent
) {
7451 Unused
<< aParent
->SendSetFocusedBrowsingContext(context
, aActionId
);
7457 mozilla::ipc::IPCResult
ContentParent::RecvSetActiveBrowsingContext(
7458 const MaybeDiscarded
<BrowsingContext
>& aContext
, uint64_t aActionId
) {
7459 if (aContext
.IsNullOrDiscarded()) {
7461 BrowsingContext::GetLog(), LogLevel::Debug
,
7462 ("ParentIPC: Trying to send a message to dead or detached context"));
7465 LOGFOCUS(("ContentParent::RecvSetActiveBrowsingContext actionid: %" PRIu64
,
7467 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7469 nsFocusManager
* fm
= nsFocusManager::GetFocusManager();
7474 if (!fm
->SetActiveBrowsingContextInChrome(context
, aActionId
)) {
7476 ("Ignoring out-of-sequence attempt [%p] to set active browsing context "
7479 Unused
<< SendReviseActiveBrowsingContext(
7480 aActionId
, fm
->GetActiveBrowsingContextInChrome(),
7481 fm
->GetActionIdForActiveBrowsingContextInChrome());
7485 context
->Group()->EachOtherParent(this, [&](ContentParent
* aParent
) {
7486 Unused
<< aParent
->SendSetActiveBrowsingContext(context
, aActionId
);
7492 mozilla::ipc::IPCResult
ContentParent::RecvUnsetActiveBrowsingContext(
7493 const MaybeDiscarded
<BrowsingContext
>& aContext
, uint64_t aActionId
) {
7494 if (aContext
.IsNullOrDiscarded()) {
7496 BrowsingContext::GetLog(), LogLevel::Debug
,
7497 ("ParentIPC: Trying to send a message to dead or detached context"));
7500 LOGFOCUS(("ContentParent::RecvUnsetActiveBrowsingContext actionid: %" PRIu64
,
7502 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7504 nsFocusManager
* fm
= nsFocusManager::GetFocusManager();
7509 if (!fm
->SetActiveBrowsingContextInChrome(nullptr, aActionId
)) {
7511 ("Ignoring out-of-sequence attempt to unset active browsing context in "
7514 Unused
<< SendReviseActiveBrowsingContext(
7515 aActionId
, fm
->GetActiveBrowsingContextInChrome(),
7516 fm
->GetActionIdForActiveBrowsingContextInChrome());
7520 context
->Group()->EachOtherParent(this, [&](ContentParent
* aParent
) {
7521 Unused
<< aParent
->SendUnsetActiveBrowsingContext(context
, aActionId
);
7527 mozilla::ipc::IPCResult
ContentParent::RecvSetFocusedElement(
7528 const MaybeDiscarded
<BrowsingContext
>& aContext
, bool aNeedsFocus
) {
7529 if (aContext
.IsNullOrDiscarded()) {
7531 BrowsingContext::GetLog(), LogLevel::Debug
,
7532 ("ParentIPC: Trying to send a message to dead or detached context"));
7535 LOGFOCUS(("ContentParent::RecvSetFocusedElement"));
7536 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7538 if (ContentParent
* cp
= context
->GetContentParent()) {
7539 Unused
<< cp
->SendSetFocusedElement(context
, aNeedsFocus
);
7544 mozilla::ipc::IPCResult
ContentParent::RecvFinalizeFocusOuter(
7545 const MaybeDiscarded
<BrowsingContext
>& aContext
, bool aCanFocus
,
7546 CallerType aCallerType
) {
7547 if (aContext
.IsNullOrDiscarded()) {
7549 BrowsingContext::GetLog(), LogLevel::Debug
,
7550 ("ParentIPC: Trying to send a message to dead or detached context"));
7553 LOGFOCUS(("ContentParent::RecvFinalizeFocusOuter"));
7554 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7555 ContentProcessManager
* cpm
= ContentProcessManager::GetSingleton();
7557 ContentParent
* cp
= cpm
->GetContentProcessById(
7558 ContentParentId(context
->EmbedderProcessId()));
7560 Unused
<< cp
->SendFinalizeFocusOuter(context
, aCanFocus
, aCallerType
);
7566 mozilla::ipc::IPCResult
ContentParent::RecvInsertNewFocusActionId(
7567 uint64_t aActionId
) {
7568 LOGFOCUS(("ContentParent::RecvInsertNewFocusActionId actionid: %" PRIu64
,
7570 nsFocusManager
* fm
= nsFocusManager::GetFocusManager();
7572 fm
->InsertNewFocusActionId(aActionId
);
7577 mozilla::ipc::IPCResult
ContentParent::RecvBlurToParent(
7578 const MaybeDiscarded
<BrowsingContext
>& aFocusedBrowsingContext
,
7579 const MaybeDiscarded
<BrowsingContext
>& aBrowsingContextToClear
,
7580 const MaybeDiscarded
<BrowsingContext
>& aAncestorBrowsingContextToFocus
,
7581 bool aIsLeavingDocument
, bool aAdjustWidget
,
7582 bool aBrowsingContextToClearHandled
,
7583 bool aAncestorBrowsingContextToFocusHandled
, uint64_t aActionId
) {
7584 if (aFocusedBrowsingContext
.IsNullOrDiscarded()) {
7586 BrowsingContext::GetLog(), LogLevel::Debug
,
7587 ("ParentIPC: Trying to send a message to dead or detached context"));
7592 ("ContentParent::RecvBlurToParent isLeavingDocument %d adjustWidget %d "
7593 "browsingContextToClearHandled %d ancestorBrowsingContextToFocusHandled "
7594 "%d actionid: %" PRIu64
,
7595 aIsLeavingDocument
, aAdjustWidget
, aBrowsingContextToClearHandled
,
7596 aAncestorBrowsingContextToFocusHandled
, aActionId
));
7598 CanonicalBrowsingContext
* focusedBrowsingContext
=
7599 aFocusedBrowsingContext
.get_canonical();
7601 // If aBrowsingContextToClear and aAncestorBrowsingContextToFocusHandled
7602 // didn't get handled in the process that sent this IPC message and they
7603 // aren't in the same process as aFocusedBrowsingContext, we need to split
7604 // off their handling here and use SendSetFocusedElement to send them
7605 // elsewhere than the blurring itself.
7607 bool ancestorDifferent
=
7608 (!aAncestorBrowsingContextToFocusHandled
&&
7609 !aAncestorBrowsingContextToFocus
.IsNullOrDiscarded() &&
7610 (focusedBrowsingContext
->OwnerProcessId() !=
7611 aAncestorBrowsingContextToFocus
.get_canonical()->OwnerProcessId()));
7612 if (!aBrowsingContextToClearHandled
&&
7613 !aBrowsingContextToClear
.IsNullOrDiscarded() &&
7614 (focusedBrowsingContext
->OwnerProcessId() !=
7615 aBrowsingContextToClear
.get_canonical()->OwnerProcessId())) {
7616 MOZ_RELEASE_ASSERT(!ancestorDifferent
,
7617 "This combination is not supposed to happen.");
7618 if (ContentParent
* cp
=
7619 aBrowsingContextToClear
.get_canonical()->GetContentParent()) {
7620 Unused
<< cp
->SendSetFocusedElement(aBrowsingContextToClear
, false);
7622 } else if (ancestorDifferent
) {
7623 if (ContentParent
* cp
= aAncestorBrowsingContextToFocus
.get_canonical()
7624 ->GetContentParent()) {
7625 Unused
<< cp
->SendSetFocusedElement(aAncestorBrowsingContextToFocus
,
7630 if (ContentParent
* cp
= focusedBrowsingContext
->GetContentParent()) {
7631 Unused
<< cp
->SendBlurToChild(aFocusedBrowsingContext
,
7632 aBrowsingContextToClear
,
7633 aAncestorBrowsingContextToFocus
,
7634 aIsLeavingDocument
, aAdjustWidget
, aActionId
);
7640 mozilla::ipc::IPCResult
ContentParent::RecvMaybeExitFullscreen(
7641 const MaybeDiscarded
<BrowsingContext
>& aContext
) {
7642 if (aContext
.IsNullOrDiscarded()) {
7644 BrowsingContext::GetLog(), LogLevel::Debug
,
7645 ("ParentIPC: Trying to send a message to dead or detached context"));
7648 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7650 if (ContentParent
* cp
= context
->GetContentParent()) {
7651 Unused
<< cp
->SendMaybeExitFullscreen(context
);
7657 mozilla::ipc::IPCResult
ContentParent::RecvWindowPostMessage(
7658 const MaybeDiscarded
<BrowsingContext
>& aContext
,
7659 const ClonedOrErrorMessageData
& aMessage
, const PostMessageData
& aData
) {
7660 if (aContext
.IsNullOrDiscarded()) {
7662 BrowsingContext::GetLog(), LogLevel::Debug
,
7663 ("ParentIPC: Trying to send a message to dead or detached context"));
7666 CanonicalBrowsingContext
* context
= aContext
.get_canonical();
7668 if (aData
.source().IsDiscarded()) {
7670 BrowsingContext::GetLog(), LogLevel::Debug
,
7671 ("ParentIPC: Trying to send a message from dead or detached context"));
7675 RefPtr
<ContentParent
> cp
= context
->GetContentParent();
7677 MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug
,
7678 ("ParentIPC: Trying to send PostMessage to dead content process"));
7682 ClonedOrErrorMessageData message
;
7683 StructuredCloneData messageFromChild
;
7684 if (aMessage
.type() == ClonedOrErrorMessageData::TClonedMessageData
) {
7685 UnpackClonedMessageData(aMessage
, messageFromChild
);
7687 ClonedMessageData clonedMessageData
;
7688 if (BuildClonedMessageData(messageFromChild
, clonedMessageData
)) {
7689 message
= std::move(clonedMessageData
);
7692 message
= ErrorMessageData();
7695 MOZ_ASSERT(aMessage
.type() == ClonedOrErrorMessageData::TErrorMessageData
);
7696 message
= ErrorMessageData();
7699 Unused
<< cp
->SendWindowPostMessage(context
, message
, aData
);
7703 void ContentParent::AddBrowsingContextGroup(BrowsingContextGroup
* aGroup
) {
7704 MOZ_DIAGNOSTIC_ASSERT(aGroup
);
7705 // Ensure that the group has been inserted, and if we're not launching
7706 // anymore, also begin subscribing. Launching processes will be subscribed if
7707 // they finish launching in `LaunchSubprocessResolve`.
7708 if (mGroups
.EnsureInserted(aGroup
) && !IsLaunching()) {
7709 aGroup
->Subscribe(this);
7713 void ContentParent::RemoveBrowsingContextGroup(BrowsingContextGroup
* aGroup
) {
7714 MOZ_DIAGNOSTIC_ASSERT(aGroup
);
7715 // Remove the group from our list. This is called from the
7716 // BrowsingContextGroup when unsubscribing, so we don't need to do it here.
7717 if (mGroups
.EnsureRemoved(aGroup
) && CanSend()) {
7718 // If we're removing the entry for the first time, tell the content process
7719 // to clean up the group.
7720 Unused
<< SendDestroyBrowsingContextGroup(aGroup
->Id());
7724 mozilla::ipc::IPCResult
ContentParent::RecvCommitBrowsingContextTransaction(
7725 const MaybeDiscarded
<BrowsingContext
>& aContext
,
7726 BrowsingContext::BaseTransaction
&& aTransaction
, uint64_t aEpoch
) {
7727 // Record the new BrowsingContextFieldEpoch associated with this transaction.
7728 // This should be done unconditionally, so that we're always in-sync.
7730 // The order the parent process receives transactions is considered the
7731 // "canonical" ordering, so we don't need to worry about doing any
7732 // epoch-related validation.
7733 MOZ_ASSERT(aEpoch
== mBrowsingContextFieldEpoch
+ 1,
7734 "Child process skipped an epoch?");
7735 mBrowsingContextFieldEpoch
= aEpoch
;
7737 return aTransaction
.CommitFromIPC(aContext
, this);
7740 mozilla::ipc::IPCResult
ContentParent::RecvBlobURLDataRequest(
7741 const nsACString
& aBlobURL
, nsIPrincipal
* aTriggeringPrincipal
,
7742 nsIPrincipal
* aLoadingPrincipal
, const OriginAttributes
& aOriginAttributes
,
7743 uint64_t aInnerWindowId
, const nsCString
& aPartitionKey
,
7744 BlobURLDataRequestResolver
&& aResolver
) {
7745 RefPtr
<BlobImpl
> blobImpl
;
7747 // Since revoked blobs are also retrieved, it is possible that the blob no
7748 // longer exists (due to the 5 second timeout) when execution reaches here
7749 if (!BlobURLProtocolHandler::GetDataEntry(
7750 aBlobURL
, getter_AddRefs(blobImpl
), aLoadingPrincipal
,
7751 aTriggeringPrincipal
, aOriginAttributes
, aInnerWindowId
,
7752 aPartitionKey
, true /* AlsoIfRevoked */)) {
7753 aResolver(NS_ERROR_DOM_BAD_URI
);
7758 nsresult rv
= IPCBlobUtils::Serialize(blobImpl
, ipcBlob
);
7760 if (NS_WARN_IF(NS_FAILED(rv
))) {
7769 mozilla::ipc::IPCResult
ContentParent::RecvReportServiceWorkerShutdownProgress(
7770 uint32_t aShutdownStateId
, ServiceWorkerShutdownState::Progress aProgress
) {
7771 RefPtr
<ServiceWorkerManager
> swm
= ServiceWorkerManager::GetInstance();
7772 MOZ_RELEASE_ASSERT(swm
, "ServiceWorkers should shutdown before SWM.");
7774 swm
->ReportServiceWorkerShutdownProgress(aShutdownStateId
, aProgress
);
7779 mozilla::ipc::IPCResult
ContentParent::RecvNotifyOnHistoryReload(
7780 const MaybeDiscarded
<BrowsingContext
>& aContext
, const bool& aForceReload
,
7781 NotifyOnHistoryReloadResolver
&& aResolver
) {
7782 bool canReload
= false;
7783 Maybe
<NotNull
<RefPtr
<nsDocShellLoadState
>>> loadState
;
7784 Maybe
<bool> reloadActiveEntry
;
7785 if (!aContext
.IsNullOrDiscarded()) {
7786 aContext
.get_canonical()->NotifyOnHistoryReload(
7787 aForceReload
, canReload
, loadState
, reloadActiveEntry
);
7790 std::tuple
<const bool&,
7791 const Maybe
<NotNull
<RefPtr
<nsDocShellLoadState
>>>&,
7792 const Maybe
<bool>&>(canReload
, loadState
, reloadActiveEntry
));
7796 mozilla::ipc::IPCResult
ContentParent::RecvHistoryCommit(
7797 const MaybeDiscarded
<BrowsingContext
>& aContext
, const uint64_t& aLoadID
,
7798 const nsID
& aChangeID
, const uint32_t& aLoadType
, const bool& aPersist
,
7799 const bool& aCloneEntryChildren
, const bool& aChannelExpired
,
7800 const uint32_t& aCacheKey
) {
7801 if (!aContext
.IsDiscarded()) {
7802 CanonicalBrowsingContext
* canonical
= aContext
.get_canonical();
7805 this, "Could not get canonical. aContext.get_canonical() fails.");
7807 canonical
->SessionHistoryCommit(aLoadID
, aChangeID
, aLoadType
, aPersist
,
7808 aCloneEntryChildren
, aChannelExpired
,
7814 mozilla::ipc::IPCResult
ContentParent::RecvHistoryGo(
7815 const MaybeDiscarded
<BrowsingContext
>& aContext
, int32_t aOffset
,
7816 uint64_t aHistoryEpoch
, bool aRequireUserInteraction
, bool aUserActivation
,
7817 HistoryGoResolver
&& aResolveRequestedIndex
) {
7818 if (!aContext
.IsNullOrDiscarded()) {
7819 RefPtr
<CanonicalBrowsingContext
> canonical
= aContext
.get_canonical();
7820 aResolveRequestedIndex(
7821 canonical
->HistoryGo(aOffset
, aHistoryEpoch
, aRequireUserInteraction
,
7822 aUserActivation
, Some(ChildID())));
7827 mozilla::ipc::IPCResult
ContentParent::RecvSynchronizeLayoutHistoryState(
7828 const MaybeDiscarded
<BrowsingContext
>& aContext
,
7829 nsILayoutHistoryState
* aState
) {
7830 if (aContext
.IsNull()) {
7834 BrowsingContext
* bc
= aContext
.GetMaybeDiscarded();
7838 SessionHistoryEntry
* entry
= bc
->Canonical()->GetActiveSessionHistoryEntry();
7840 entry
->SetLayoutHistoryState(aState
);
7845 mozilla::ipc::IPCResult
ContentParent::RecvSessionHistoryEntryTitle(
7846 const MaybeDiscarded
<BrowsingContext
>& aContext
, const nsAString
& aTitle
) {
7847 if (aContext
.IsNullOrDiscarded()) {
7851 SessionHistoryEntry
* entry
=
7852 aContext
.get_canonical()->GetActiveSessionHistoryEntry();
7854 entry
->SetTitle(aTitle
);
7859 mozilla::ipc::IPCResult
7860 ContentParent::RecvSessionHistoryEntryScrollRestorationIsManual(
7861 const MaybeDiscarded
<BrowsingContext
>& aContext
, const bool& aIsManual
) {
7862 if (aContext
.IsNullOrDiscarded()) {
7866 SessionHistoryEntry
* entry
=
7867 aContext
.get_canonical()->GetActiveSessionHistoryEntry();
7869 entry
->SetScrollRestorationIsManual(aIsManual
);
7874 mozilla::ipc::IPCResult
ContentParent::RecvSessionHistoryEntryScrollPosition(
7875 const MaybeDiscarded
<BrowsingContext
>& aContext
, const int32_t& aX
,
7876 const int32_t& aY
) {
7877 if (aContext
.IsNullOrDiscarded()) {
7881 SessionHistoryEntry
* entry
=
7882 aContext
.get_canonical()->GetActiveSessionHistoryEntry();
7884 entry
->SetScrollPosition(aX
, aY
);
7889 mozilla::ipc::IPCResult
7890 ContentParent::RecvSessionHistoryEntryStoreWindowNameInContiguousEntries(
7891 const MaybeDiscarded
<BrowsingContext
>& aContext
, const nsAString
& aName
) {
7892 if (aContext
.IsNullOrDiscarded()) {
7896 // Per https://html.spec.whatwg.org/#history-traversal 4.2.1, we need to set
7897 // the name to all contiguous entries. This has to be called before
7898 // CanonicalBrowsingContext::SessionHistoryCommit(), so the active entry is
7899 // still the old entry that we want to set.
7901 SessionHistoryEntry
* entry
=
7902 aContext
.get_canonical()->GetActiveSessionHistoryEntry();
7905 nsSHistory::WalkContiguousEntries(
7906 entry
, [&](nsISHEntry
* aEntry
) { aEntry
->SetName(aName
); });
7912 mozilla::ipc::IPCResult
ContentParent::RecvSessionHistoryEntryCacheKey(
7913 const MaybeDiscarded
<BrowsingContext
>& aContext
,
7914 const uint32_t& aCacheKey
) {
7915 if (aContext
.IsNullOrDiscarded()) {
7919 SessionHistoryEntry
* entry
=
7920 aContext
.get_canonical()->GetActiveSessionHistoryEntry();
7922 entry
->SetCacheKey(aCacheKey
);
7927 mozilla::ipc::IPCResult
ContentParent::RecvSessionHistoryEntryWireframe(
7928 const MaybeDiscarded
<BrowsingContext
>& aContext
,
7929 const Wireframe
& aWireframe
) {
7930 if (aContext
.IsNull()) {
7934 BrowsingContext
* bc
= aContext
.GetMaybeDiscarded();
7939 SessionHistoryEntry
* entry
= bc
->Canonical()->GetActiveSessionHistoryEntry();
7941 entry
->SetWireframe(Some(aWireframe
));
7946 mozilla::ipc::IPCResult
7947 ContentParent::RecvGetLoadingSessionHistoryInfoFromParent(
7948 const MaybeDiscarded
<BrowsingContext
>& aContext
,
7949 GetLoadingSessionHistoryInfoFromParentResolver
&& aResolver
) {
7950 if (aContext
.IsNullOrDiscarded()) {
7954 Maybe
<LoadingSessionHistoryInfo
> info
;
7955 aContext
.get_canonical()->GetLoadingSessionHistoryInfoFromParent(info
);
7961 mozilla::ipc::IPCResult
ContentParent::RecvRemoveFromBFCache(
7962 const MaybeDiscarded
<BrowsingContext
>& aContext
) {
7963 if (aContext
.IsNullOrDiscarded()) {
7967 nsCOMPtr
<nsFrameLoaderOwner
> owner
=
7968 do_QueryInterface(aContext
.get_canonical()->GetEmbedderElement());
7973 RefPtr
<nsFrameLoader
> frameLoader
= owner
->GetFrameLoader();
7974 if (!frameLoader
|| !frameLoader
->GetMaybePendingBrowsingContext()) {
7978 nsCOMPtr
<nsISHistory
> shistory
= frameLoader
->GetMaybePendingBrowsingContext()
7980 ->GetSessionHistory();
7985 uint32_t count
= shistory
->GetCount();
7986 for (uint32_t i
= 0; i
< count
; ++i
) {
7987 nsCOMPtr
<nsISHEntry
> entry
;
7988 shistory
->GetEntryAtIndex(i
, getter_AddRefs(entry
));
7989 nsCOMPtr
<SessionHistoryEntry
> she
= do_QueryInterface(entry
);
7991 if (RefPtr
<nsFrameLoader
> frameLoader
= she
->GetFrameLoader()) {
7992 if (frameLoader
->GetMaybePendingBrowsingContext() == aContext
.get()) {
7993 she
->SetFrameLoader(nullptr);
7994 frameLoader
->Destroy();
8004 mozilla::ipc::IPCResult
ContentParent::RecvSetActiveSessionHistoryEntry(
8005 const MaybeDiscarded
<BrowsingContext
>& aContext
,
8006 const Maybe
<nsPoint
>& aPreviousScrollPos
, SessionHistoryInfo
&& aInfo
,
8007 uint32_t aLoadType
, uint32_t aUpdatedCacheKey
, const nsID
& aChangeID
) {
8008 if (!aContext
.IsNullOrDiscarded()) {
8009 aContext
.get_canonical()->SetActiveSessionHistoryEntry(
8010 aPreviousScrollPos
, &aInfo
, aLoadType
, aUpdatedCacheKey
, aChangeID
);
8015 mozilla::ipc::IPCResult
ContentParent::RecvReplaceActiveSessionHistoryEntry(
8016 const MaybeDiscarded
<BrowsingContext
>& aContext
,
8017 SessionHistoryInfo
&& aInfo
) {
8018 if (!aContext
.IsNullOrDiscarded()) {
8019 aContext
.get_canonical()->ReplaceActiveSessionHistoryEntry(&aInfo
);
8024 mozilla::ipc::IPCResult
8025 ContentParent::RecvRemoveDynEntriesFromActiveSessionHistoryEntry(
8026 const MaybeDiscarded
<BrowsingContext
>& aContext
) {
8027 if (!aContext
.IsNullOrDiscarded()) {
8028 aContext
.get_canonical()->RemoveDynEntriesFromActiveSessionHistoryEntry();
8033 mozilla::ipc::IPCResult
ContentParent::RecvRemoveFromSessionHistory(
8034 const MaybeDiscarded
<BrowsingContext
>& aContext
, const nsID
& aChangeID
) {
8035 if (!aContext
.IsNullOrDiscarded()) {
8036 aContext
.get_canonical()->RemoveFromSessionHistory(aChangeID
);
8041 mozilla::ipc::IPCResult
ContentParent::RecvHistoryReload(
8042 const MaybeDiscarded
<BrowsingContext
>& aContext
,
8043 const uint32_t aReloadFlags
) {
8044 if (!aContext
.IsNullOrDiscarded()) {
8045 nsCOMPtr
<nsISHistory
> shistory
=
8046 aContext
.get_canonical()->GetSessionHistory();
8048 shistory
->Reload(aReloadFlags
);
8054 mozilla::ipc::IPCResult
ContentParent::RecvCommitWindowContextTransaction(
8055 const MaybeDiscarded
<WindowContext
>& aContext
,
8056 WindowContext::BaseTransaction
&& aTransaction
, uint64_t aEpoch
) {
8057 // Record the new BrowsingContextFieldEpoch associated with this transaction.
8058 // This should be done unconditionally, so that we're always in-sync.
8060 // The order the parent process receives transactions is considered the
8061 // "canonical" ordering, so we don't need to worry about doing any
8062 // epoch-related validation.
8063 MOZ_ASSERT(aEpoch
== mBrowsingContextFieldEpoch
+ 1,
8064 "Child process skipped an epoch?");
8065 mBrowsingContextFieldEpoch
= aEpoch
;
8067 return aTransaction
.CommitFromIPC(aContext
, this);
8070 NS_IMETHODIMP
ContentParent::GetChildID(uint64_t* aOut
) {
8071 *aOut
= this->ChildID();
8075 NS_IMETHODIMP
ContentParent::GetOsPid(int32_t* aOut
) {
8080 NS_IMETHODIMP
ContentParent::GetRemoteType(nsACString
& aRemoteType
) {
8081 aRemoteType
= GetRemoteType();
8085 IPCResult
ContentParent::RecvRawMessage(
8086 const JSActorMessageMeta
& aMeta
, const Maybe
<ClonedMessageData
>& aData
,
8087 const Maybe
<ClonedMessageData
>& aStack
) {
8088 Maybe
<StructuredCloneData
> data
;
8091 data
->BorrowFromClonedMessageData(*aData
);
8093 Maybe
<StructuredCloneData
> stack
;
8096 stack
->BorrowFromClonedMessageData(*aStack
);
8098 MMPrinter::Print("ContentParent::RecvRawMessage", aMeta
.actorName(),
8099 aMeta
.messageName(), aData
);
8100 ReceiveRawMessage(aMeta
, std::move(data
), std::move(stack
));
8104 NS_IMETHODIMP
ContentParent::GetActor(const nsACString
& aName
, JSContext
* aCx
,
8105 JSProcessActorParent
** retval
) {
8107 RefPtr
<JSProcessActorParent
> actor
=
8108 JSActorManager::GetActor(aCx
, aName
, error
)
8109 .downcast
<JSProcessActorParent
>();
8110 if (error
.MaybeSetPendingException(aCx
)) {
8111 return NS_ERROR_FAILURE
;
8113 actor
.forget(retval
);
8117 NS_IMETHODIMP
ContentParent::GetExistingActor(const nsACString
& aName
,
8118 JSProcessActorParent
** retval
) {
8119 RefPtr
<JSProcessActorParent
> actor
=
8120 JSActorManager::GetExistingActor(aName
).downcast
<JSProcessActorParent
>();
8121 actor
.forget(retval
);
8125 already_AddRefed
<JSActor
> ContentParent::InitJSActor(
8126 JS::Handle
<JSObject
*> aMaybeActor
, const nsACString
& aName
,
8128 RefPtr
<JSProcessActorParent
> actor
;
8129 if (aMaybeActor
.get()) {
8130 aRv
= UNWRAP_OBJECT(JSProcessActorParent
, aMaybeActor
.get(), actor
);
8135 actor
= new JSProcessActorParent();
8138 MOZ_RELEASE_ASSERT(!actor
->Manager(),
8139 "mManager was already initialized once!");
8140 actor
->Init(aName
, this);
8141 return actor
.forget();
8144 IPCResult
ContentParent::RecvFOGData(ByteBuf
&& buf
) {
8145 glean::FOGData(std::move(buf
));
8149 mozilla::ipc::IPCResult
ContentParent::RecvSetContainerFeaturePolicy(
8150 const MaybeDiscardedBrowsingContext
& aContainerContext
,
8151 FeaturePolicy
* aContainerFeaturePolicy
) {
8152 if (aContainerContext
.IsNullOrDiscarded()) {
8156 auto* context
= aContainerContext
.get_canonical();
8157 context
->SetContainerFeaturePolicy(aContainerFeaturePolicy
);
8162 NS_IMETHODIMP
ContentParent::GetCanSend(bool* aCanSend
) {
8163 *aCanSend
= CanSend();
8167 ContentParent
* ContentParent::AsContentParent() { return this; }
8169 JSActorManager
* ContentParent::AsJSActorManager() { return this; }
8171 IPCResult
ContentParent::RecvGetSystemIcon(nsIURI
* aURI
,
8172 GetSystemIconResolver
&& aResolver
) {
8173 using ResolverArgs
= std::tuple
<const nsresult
&, mozilla::Maybe
<ByteBuf
>&&>;
8176 Maybe
<ByteBuf
> bytebuf
= Nothing();
8177 aResolver(ResolverArgs(NS_ERROR_NULL_POINTER
, std::move(bytebuf
)));
8181 #if defined(MOZ_WIDGET_GTK)
8182 Maybe
<ByteBuf
> bytebuf
= Some(ByteBuf
{});
8183 nsresult rv
= nsIconChannel::GetIcon(aURI
, bytebuf
.ptr());
8184 if (NS_WARN_IF(NS_FAILED(rv
))) {
8185 bytebuf
= Nothing();
8187 aResolver(ResolverArgs(rv
, std::move(bytebuf
)));
8189 #elif defined(XP_WIN)
8190 nsIconChannel::GetIconAsync(aURI
)->Then(
8191 GetCurrentSerialEventTarget(), __func__
,
8192 [aResolver
](ByteBuf
&& aByteBuf
) {
8193 Maybe
<ByteBuf
> bytebuf
= Some(std::move(aByteBuf
));
8194 aResolver(ResolverArgs(NS_OK
, std::move(bytebuf
)));
8196 [aResolver
](nsresult aErr
) {
8197 Maybe
<ByteBuf
> bytebuf
= Nothing();
8198 aResolver(ResolverArgs(aErr
, std::move(bytebuf
)));
8203 "This message is currently implemented only on GTK and Windows "
8208 #ifdef FUZZING_SNAPSHOT
8209 IPCResult
ContentParent::RecvSignalFuzzingReady() {
8210 // No action needed here, we already observe this message directly
8211 // on the channel and act accordingly.
8216 nsCString
ThreadsafeContentParentHandle::GetRemoteType() {
8217 RecursiveMutexAutoLock
lock(mMutex
);
8221 bool ThreadsafeContentParentHandle::MaybeRegisterRemoteWorkerActor(
8222 MoveOnlyFunction
<bool(uint32_t, bool)> aCallback
) {
8223 RecursiveMutexAutoLock
lock(mMutex
);
8224 if (aCallback(mRemoteWorkerActorCount
, mShutdownStarted
)) {
8225 // TODO: I'd wish we could assert here that our ContentParent is alive.
8226 ++mRemoteWorkerActorCount
;
8233 } // namespace mozilla
8235 NS_IMPL_ISUPPORTS(ParentIdleListener
, nsIObserver
)
8238 ParentIdleListener::Observe(nsISupports
*, const char* aTopic
,
8239 const char16_t
* aData
) {
8240 mozilla::Unused
<< mParent
->SendNotifyIdleObserver(
8241 mObserver
, nsDependentCString(aTopic
), nsDependentString(aData
));