Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
* License, v. 2.0. If a copy of the MPL was not distributed with this
5
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "mozilla/DebugOnly.h"
8
9
#include "base/basictypes.h"
10
#include "base/shared_memory.h"
11
12
#include "ContentParent.h"
13
#include "ProcessUtils.h"
14
#include "BrowserParent.h"
15
16
#include "chrome/common/process_watcher.h"
17
18
#ifdef ACCESSIBILITY
19
# include "mozilla/a11y/PDocAccessible.h"
20
#endif
21
#include "GeckoProfiler.h"
22
#include "GMPServiceParent.h"
23
#include "HandlerServiceParent.h"
24
#include "IHistory.h"
25
#if defined(XP_WIN) && defined(ACCESSIBILITY)
26
# include "mozilla/a11y/AccessibleWrap.h"
27
# include "mozilla/a11y/Compatibility.h"
28
#endif
29
#include <utility>
30
31
#include "BrowserParent.h"
32
#include "ContentProcessManager.h"
33
#include "Geolocation.h"
34
#include "GfxInfoBase.h"
35
#include "MMPrinter.h"
36
#include "PreallocatedProcessManager.h"
37
#include "ProcessPriorityManager.h"
38
#include "SandboxHal.h"
39
#include "SourceSurfaceRawData.h"
40
#include "URIUtils.h"
41
#include "gfxPlatform.h"
42
#include "gfxPlatformFontList.h"
43
#include "mozilla/AntiTrackingCommon.h"
44
#include "mozilla/BasePrincipal.h"
45
#include "mozilla/BenchmarkStorageParent.h"
46
#include "mozilla/ClearOnShutdown.h"
47
#include "mozilla/Components.h"
48
#include "mozilla/DataStorage.h"
49
#include "mozilla/GlobalStyleSheetCache.h"
50
#include "mozilla/HangDetails.h"
51
#include "mozilla/LoginReputationIPC.h"
52
#include "mozilla/LookAndFeel.h"
53
#include "mozilla/PerformanceMetricsCollector.h"
54
#include "mozilla/Preferences.h"
55
#include "mozilla/PresShell.h"
56
#include "mozilla/ProcessHangMonitor.h"
57
#include "mozilla/ProcessHangMonitorIPC.h"
58
#include "mozilla/RDDProcessManager.h"
59
#include "mozilla/ScopeExit.h"
60
#include "mozilla/ScriptPreloader.h"
61
#include "mozilla/Services.h"
62
#include "mozilla/Sprintf.h"
63
#include "mozilla/StaticPrefs_dom.h"
64
#include "mozilla/StaticPrefs_media.h"
65
#include "mozilla/StaticPtr.h"
66
#include "mozilla/StyleSheet.h"
67
#include "mozilla/StyleSheetInlines.h"
68
#include "mozilla/Telemetry.h"
69
#include "mozilla/TelemetryIPC.h"
70
#include "mozilla/Unused.h"
71
#include "mozilla/WebBrowserPersistDocumentParent.h"
72
#include "mozilla/devtools/HeapSnapshotTempFileHelperParent.h"
73
#include "mozilla/docshell/OfflineCacheUpdateParent.h"
74
#include "mozilla/dom/BlobURLProtocolHandler.h"
75
#include "mozilla/dom/BrowserHost.h"
76
#include "mozilla/dom/BrowsingContext.h"
77
#include "mozilla/dom/BrowsingContextGroup.h"
78
#include "mozilla/dom/CancelContentJSOptionsBinding.h"
79
#include "mozilla/dom/CanonicalBrowsingContext.h"
80
#include "mozilla/dom/ClientManager.h"
81
#include "mozilla/dom/ClientOpenWindowOpActors.h"
82
#include "mozilla/dom/ContentChild.h"
83
#include "mozilla/dom/ContentMediaController.h"
84
#include "mozilla/dom/DataTransfer.h"
85
#include "mozilla/dom/Document.h"
86
#include "mozilla/dom/Element.h"
87
#include "mozilla/dom/ExternalHelperAppParent.h"
88
#include "mozilla/dom/File.h"
89
#include "mozilla/dom/FileSystemSecurity.h"
90
#include "mozilla/dom/GeolocationBinding.h"
91
#include "mozilla/dom/GeolocationPositionError.h"
92
#include "mozilla/dom/GetFilesHelper.h"
93
#include "mozilla/dom/IPCBlobInputStreamParent.h"
94
#include "mozilla/dom/IPCBlobUtils.h"
95
#include "mozilla/dom/JSWindowActorService.h"
96
#include "mozilla/dom/LocalStorageCommon.h"
97
#include "mozilla/dom/MediaController.h"
98
#include "mozilla/dom/MemoryReportRequest.h"
99
#include "mozilla/dom/Notification.h"
100
#include "mozilla/dom/PContentPermissionRequestParent.h"
101
#include "mozilla/dom/PCycleCollectWithLogsParent.h"
102
#include "mozilla/dom/PPresentationParent.h"
103
#include "mozilla/dom/ParentProcessMessageManager.h"
104
#include "mozilla/dom/Permissions.h"
105
#include "mozilla/dom/PresentationParent.h"
106
#include "mozilla/dom/ProcessMessageManager.h"
107
#include "mozilla/dom/PushNotifier.h"
108
#include "mozilla/dom/SHEntryParent.h"
109
#include "mozilla/dom/SHistoryParent.h"
110
#include "mozilla/dom/ServiceWorkerRegistrar.h"
111
#include "mozilla/dom/ServiceWorkerUtils.h"
112
#include "mozilla/dom/StorageIPC.h"
113
#include "mozilla/dom/URLClassifierParent.h"
114
#include "mozilla/dom/WakeLock.h"
115
#include "mozilla/dom/WindowGlobalParent.h"
116
#include "mozilla/dom/ipc/SharedMap.h"
117
#include "mozilla/dom/ipc/StructuredCloneData.h"
118
#include "mozilla/dom/nsMixedContentBlocker.h"
119
#include "mozilla/dom/power/PowerManagerService.h"
120
#include "mozilla/dom/quota/QuotaManagerService.h"
121
#include "mozilla/embedding/printingui/PrintingParent.h"
122
#include "mozilla/extensions/StreamFilterParent.h"
123
#include "mozilla/gfx/GPUProcessManager.h"
124
#include "mozilla/gfx/gfxVars.h"
125
#include "mozilla/hal_sandbox/PHalParent.h"
126
#include "mozilla/intl/LocaleService.h"
127
#include "mozilla/ipc/BackgroundChild.h"
128
#include "mozilla/ipc/BackgroundParent.h"
129
#include "mozilla/ipc/CrashReporterHost.h"
130
#include "mozilla/ipc/FileDescriptorSetParent.h"
131
#include "mozilla/ipc/FileDescriptorUtils.h"
132
#include "mozilla/ipc/IPCStreamAlloc.h"
133
#include "mozilla/ipc/IPCStreamDestination.h"
134
#include "mozilla/ipc/IPCStreamSource.h"
135
#include "mozilla/ipc/IPCStreamUtils.h"
136
#include "mozilla/ipc/PChildToParentStreamParent.h"
137
#include "mozilla/ipc/TestShellParent.h"
138
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
139
#include "mozilla/layers/CompositorThread.h"
140
#include "mozilla/layers/ImageBridgeParent.h"
141
#include "mozilla/layers/LayerTreeOwnerTracker.h"
142
#include "mozilla/layers/PAPZParent.h"
143
#include "mozilla/loader/ScriptCacheActors.h"
144
#include "mozilla/media/MediaParent.h"
145
#include "mozilla/mozSpellChecker.h"
146
#include "mozilla/net/CookieServiceParent.h"
147
#include "mozilla/net/NeckoMessageUtils.h"
148
#include "mozilla/net/NeckoParent.h"
149
#include "mozilla/net/PCookieServiceParent.h"
150
#include "mozilla/plugins/PluginBridge.h"
151
#include "mozilla/psm/PSMContentListener.h"
152
#include "mozilla/recordreplay/ParentIPC.h"
153
#include "mozilla/widget/ScreenManager.h"
154
#include "nsAnonymousTemporaryFile.h"
155
#include "nsAppRunner.h"
156
#include "nsCExternalHandlerService.h"
157
#include "nsCOMPtr.h"
158
#include "nsChromeRegistryChrome.h"
159
#include "nsConsoleMessage.h"
160
#include "nsConsoleService.h"
161
#include "nsContentPermissionHelper.h"
162
#include "nsContentUtils.h"
163
#include "nsDebugImpl.h"
164
#include "nsDirectoryServiceDefs.h"
165
#include "nsDocShell.h"
166
#include "nsEmbedCID.h"
167
#include "nsFrameLoader.h"
168
#include "nsFrameMessageManager.h"
169
#include "nsHashPropertyBag.h"
170
#include "nsHyphenationManager.h"
171
#include "nsIAlertsService.h"
172
#include "nsIAppStartup.h"
173
#include "nsIAppWindow.h"
174
#include "nsIAsyncInputStream.h"
175
#include "nsIBidiKeyboard.h"
176
#include "nsICaptivePortalService.h"
177
#include "nsICertOverrideService.h"
178
#include "nsIClipboard.h"
179
#include "nsIContentProcess.h"
180
#include "nsIContentSecurityPolicy.h"
181
#include "nsICookie.h"
182
#include "nsICrashService.h"
183
#include "nsICycleCollectorListener.h"
184
#include "nsIDOMChromeWindow.h"
185
#include "nsIDocShell.h"
186
#include "nsIDocShellTreeOwner.h"
187
#include "nsIDragService.h"
188
#include "nsIExternalProtocolService.h"
189
#include "nsIGfxInfo.h"
190
#include "nsIIdleService.h"
191
#include "nsIInterfaceRequestorUtils.h"
192
#include "nsILocalStorageManager.h"
193
#include "nsIMemoryInfoDumper.h"
194
#include "nsIMemoryReporter.h"
195
#include "nsIMozBrowserFrame.h"
196
#include "nsINetworkLinkService.h"
197
#include "nsIObserverService.h"
198
#include "nsIParentChannel.h"
199
#include "nsIScriptError.h"
200
#include "nsIScriptSecurityManager.h"
201
#include "nsISearchService.h"
202
#include "nsIServiceWorkerManager.h"
203
#include "nsISiteSecurityService.h"
204
#include "nsISound.h"
205
#include "nsIStringBundle.h"
206
#include "nsITimer.h"
207
#include "nsIURIFixup.h"
208
#include "nsIURL.h"
209
#include "nsIWebBrowserChrome.h"
210
#include "nsIX509Cert.h"
211
#include "nsIXULRuntime.h"
212
#include "nsMemoryInfoDumper.h"
213
#include "nsMemoryReporterManager.h"
214
#include "nsOpenURIInFrameParams.h"
215
#include "nsPIWindowWatcher.h"
216
#include "nsPluginHost.h"
217
#include "nsPluginTags.h"
218
#include "nsQueryObject.h"
219
#include "nsReadableUtils.h"
220
#include "nsScriptError.h"
221
#include "nsSerializationHelper.h"
222
#include "nsServiceManagerUtils.h"
223
#include "nsStreamUtils.h"
224
#include "nsStyleSheetService.h"
225
#include "nsThread.h"
226
#include "nsThreadUtils.h"
227
#include "nsWidgetsCID.h"
228
#include "nsWindowWatcher.h"
229
#include "prio.h"
230
#include "private/pprio.h"
231
#include "xpcpublic.h"
232
233
#ifdef MOZ_WEBRTC
234
# include "signaling/src/peerconnection/WebrtcGlobalParent.h"
235
#endif
236
237
#if defined(XP_MACOSX)
238
# include "nsMacUtilsImpl.h"
239
#endif
240
241
#if defined(ANDROID) || defined(LINUX)
242
# include "nsSystemInfo.h"
243
#endif
244
245
#if defined(XP_LINUX)
246
# include "mozilla/Hal.h"
247
#endif
248
249
#ifdef ANDROID
250
# include "gfxAndroidPlatform.h"
251
#endif
252
253
#include "nsPermissionManager.h"
254
255
#ifdef MOZ_WIDGET_ANDROID
256
# include "AndroidBridge.h"
257
#endif
258
259
#ifdef MOZ_WIDGET_GTK
260
# include <gdk/gdk.h>
261
#endif
262
263
#include "mozilla/RemoteSpellCheckEngineParent.h"
264
265
#include "Crypto.h"
266
267
#ifdef MOZ_WEBSPEECH
268
# include "mozilla/dom/SpeechSynthesisParent.h"
269
#endif
270
271
#if defined(MOZ_SANDBOX)
272
# include "mozilla/SandboxSettings.h"
273
# if defined(XP_LINUX)
274
# include "mozilla/SandboxInfo.h"
275
# include "mozilla/SandboxBroker.h"
276
# include "mozilla/SandboxBrokerPolicyFactory.h"
277
# endif
278
# if defined(XP_MACOSX)
279
# include "mozilla/Sandbox.h"
280
# endif
281
#endif
282
283
#ifdef XP_WIN
284
# include "mozilla/audio/AudioNotificationSender.h"
285
# include "mozilla/widget/AudioSession.h"
286
# include "mozilla/WinDllServices.h"
287
#endif
288
289
#ifdef ACCESSIBILITY
290
# include "nsAccessibilityService.h"
291
#endif
292
293
#ifdef MOZ_GECKO_PROFILER
294
# include "nsIProfiler.h"
295
# include "ProfilerParent.h"
296
#endif
297
298
#ifdef MOZ_CODE_COVERAGE
299
# include "mozilla/CodeCoverageHandler.h"
300
#endif
301
302
// For VP9Benchmark::sBenchmarkFpsPref
303
#include "Benchmark.h"
304
305
// XXX need another bug to move this to a common header.
306
#ifdef DISABLE_ASSERTS_FOR_FUZZING
307
# define ASSERT_UNLESS_FUZZING(...) \
308
do { \
309
} while (0)
310
#else
311
# define ASSERT_UNLESS_FUZZING(...) MOZ_ASSERT(false, __VA_ARGS__)
312
#endif
313
314
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
315
316
using base::KillProcess;
317
318
using namespace CrashReporter;
319
using namespace mozilla::dom::power;
320
using namespace mozilla::media;
321
using namespace mozilla::embedding;
322
using namespace mozilla::gfx;
323
using namespace mozilla::gmp;
324
using namespace mozilla::hal;
325
using namespace mozilla::ipc;
326
using namespace mozilla::intl;
327
using namespace mozilla::layers;
328
using namespace mozilla::layout;
329
using namespace mozilla::net;
330
using namespace mozilla::jsipc;
331
using namespace mozilla::psm;
332
using namespace mozilla::widget;
333
using mozilla::loader::PScriptCacheParent;
334
using mozilla::Telemetry::ProcessID;
335
336
// XXX Workaround for bug 986973 to maintain the existing broken semantics
337
template <>
338
struct nsIConsoleService::COMTypeInfo<nsConsoleService, void> {
339
static const nsIID kIID;
340
};
341
const nsIID nsIConsoleService::COMTypeInfo<nsConsoleService, void>::kIID =
342
NS_ICONSOLESERVICE_IID;
343
344
namespace mozilla {
345
namespace CubebUtils {
346
extern FileDescriptor CreateAudioIPCConnection();
347
}
348
349
namespace dom {
350
351
#define NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC "ipc:network:set-offline"
352
#define NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC "ipc:network:set-connectivity"
353
354
// IPC receiver for remote GC/CC logging.
355
class CycleCollectWithLogsParent final : public PCycleCollectWithLogsParent {
356
public:
357
~CycleCollectWithLogsParent() { MOZ_COUNT_DTOR(CycleCollectWithLogsParent); }
358
359
static bool AllocAndSendConstructor(ContentParent* aManager,
360
bool aDumpAllTraces,
361
nsICycleCollectorLogSink* aSink,
362
nsIDumpGCAndCCLogsCallback* aCallback) {
363
CycleCollectWithLogsParent* actor;
364
FILE* gcLog;
365
FILE* ccLog;
366
nsresult rv;
367
368
actor = new CycleCollectWithLogsParent(aSink, aCallback);
369
rv = actor->mSink->Open(&gcLog, &ccLog);
370
if (NS_WARN_IF(NS_FAILED(rv))) {
371
delete actor;
372
return false;
373
}
374
375
return aManager->SendPCycleCollectWithLogsConstructor(
376
actor, aDumpAllTraces, FILEToFileDescriptor(gcLog),
377
FILEToFileDescriptor(ccLog));
378
}
379
380
private:
381
virtual mozilla::ipc::IPCResult RecvCloseGCLog() override {
382
Unused << mSink->CloseGCLog();
383
return IPC_OK();
384
}
385
386
virtual mozilla::ipc::IPCResult RecvCloseCCLog() override {
387
Unused << mSink->CloseCCLog();
388
return IPC_OK();
389
}
390
391
virtual mozilla::ipc::IPCResult Recv__delete__() override {
392
// Report completion to mCallback only on successful
393
// completion of the protocol.
394
nsCOMPtr<nsIFile> gcLog, ccLog;
395
mSink->GetGcLog(getter_AddRefs(gcLog));
396
mSink->GetCcLog(getter_AddRefs(ccLog));
397
Unused << mCallback->OnDump(gcLog, ccLog, /* parent = */ false);
398
return IPC_OK();
399
}
400
401
virtual void ActorDestroy(ActorDestroyReason aReason) override {
402
// If the actor is unexpectedly destroyed, we deliberately
403
// don't call Close[GC]CLog on the sink, because the logs may
404
// be incomplete. See also the nsCycleCollectorLogSinkToFile
405
// implementaiton of those methods, and its destructor.
406
}
407
408
CycleCollectWithLogsParent(nsICycleCollectorLogSink* aSink,
409
nsIDumpGCAndCCLogsCallback* aCallback)
410
: mSink(aSink), mCallback(aCallback) {
411
MOZ_COUNT_CTOR(CycleCollectWithLogsParent);
412
}
413
414
nsCOMPtr<nsICycleCollectorLogSink> mSink;
415
nsCOMPtr<nsIDumpGCAndCCLogsCallback> mCallback;
416
};
417
418
// A memory reporter for ContentParent objects themselves.
419
class ContentParentsMemoryReporter final : public nsIMemoryReporter {
420
~ContentParentsMemoryReporter() {}
421
422
public:
423
NS_DECL_ISUPPORTS
424
NS_DECL_NSIMEMORYREPORTER
425
};
426
427
NS_IMPL_ISUPPORTS(ContentParentsMemoryReporter, nsIMemoryReporter)
428
429
NS_IMETHODIMP
430
ContentParentsMemoryReporter::CollectReports(
431
nsIHandleReportCallback* aHandleReport, nsISupports* aData,
432
bool aAnonymize) {
433
AutoTArray<ContentParent*, 16> cps;
434
ContentParent::GetAllEvenIfDead(cps);
435
436
for (uint32_t i = 0; i < cps.Length(); i++) {
437
ContentParent* cp = cps[i];
438
MessageChannel* channel = cp->GetIPCChannel();
439
440
nsString friendlyName;
441
cp->FriendlyName(friendlyName, aAnonymize);
442
443
cp->AddRef();
444
nsrefcnt refcnt = cp->Release();
445
446
const char* channelStr = "no channel";
447
uint32_t numQueuedMessages = 0;
448
if (channel) {
449
if (channel->Unsound_IsClosed()) {
450
channelStr = "closed channel";
451
} else {
452
channelStr = "open channel";
453
}
454
numQueuedMessages = channel->Unsound_NumQueuedMessages();
455
}
456
457
nsPrintfCString path(
458
"queued-ipc-messages/content-parent"
459
"(%s, pid=%d, %s, 0x%p, refcnt=%" PRIuPTR ")",
460
NS_ConvertUTF16toUTF8(friendlyName).get(), cp->Pid(), channelStr,
461
static_cast<nsIObserver*>(cp), refcnt);
462
463
NS_NAMED_LITERAL_CSTRING(
464
desc,
465
"The number of unset IPC messages held in this ContentParent's "
466
"channel. A large value here might indicate that we're leaking "
467
"messages. Similarly, a ContentParent object for a process that's no "
468
"longer running could indicate that we're leaking ContentParents.");
469
470
aHandleReport->Callback(/* process */ EmptyCString(), path, KIND_OTHER,
471
UNITS_COUNT, numQueuedMessages, desc, aData);
472
}
473
474
return NS_OK;
475
}
476
477
nsClassHashtable<nsStringHashKey, nsTArray<ContentParent*>>*
478
ContentParent::sBrowserContentParents;
479
480
namespace {
481
482
uint64_t ComputeLoadedOriginHash(nsIPrincipal* aPrincipal) {
483
uint32_t originNoSuffix =
484
BasePrincipal::Cast(aPrincipal)->GetOriginNoSuffixHash();
485
uint32_t originSuffix =
486
BasePrincipal::Cast(aPrincipal)->GetOriginSuffixHash();
487
488
return ((uint64_t)originNoSuffix) << 32 | originSuffix;
489
}
490
491
class ScriptableCPInfo final : public nsIContentProcessInfo {
492
public:
493
explicit ScriptableCPInfo(ContentParent* aParent) : mContentParent(aParent) {
494
MOZ_ASSERT(mContentParent);
495
}
496
497
NS_DECL_ISUPPORTS
498
NS_DECL_NSICONTENTPROCESSINFO
499
500
void ProcessDied() { mContentParent = nullptr; }
501
502
private:
503
~ScriptableCPInfo() { MOZ_ASSERT(!mContentParent, "must call ProcessDied"); }
504
505
ContentParent* mContentParent;
506
};
507
508
NS_IMPL_ISUPPORTS(ScriptableCPInfo, nsIContentProcessInfo)
509
510
NS_IMETHODIMP
511
ScriptableCPInfo::GetIsAlive(bool* aIsAlive) {
512
*aIsAlive = mContentParent != nullptr;
513
return NS_OK;
514
}
515
516
NS_IMETHODIMP
517
ScriptableCPInfo::GetProcessId(int32_t* aPID) {
518
if (!mContentParent) {
519
*aPID = -1;
520
return NS_ERROR_NOT_INITIALIZED;
521
}
522
523
*aPID = mContentParent->Pid();
524
if (*aPID == -1) {
525
return NS_ERROR_FAILURE;
526
}
527
528
return NS_OK;
529
}
530
531
NS_IMETHODIMP
532
ScriptableCPInfo::GetOpener(nsIContentProcessInfo** aInfo) {
533
*aInfo = nullptr;
534
if (!mContentParent) {
535
return NS_ERROR_NOT_INITIALIZED;
536
}
537
538
if (ContentParent* opener = mContentParent->Opener()) {
539
nsCOMPtr<nsIContentProcessInfo> info = opener->ScriptableHelper();
540
info.forget(aInfo);
541
}
542
return NS_OK;
543
}
544
545
NS_IMETHODIMP
546
ScriptableCPInfo::GetTabCount(int32_t* aTabCount) {
547
if (!mContentParent) {
548
return NS_ERROR_NOT_INITIALIZED;
549
}
550
551
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
552
*aTabCount = cpm->GetBrowserParentCountByProcessId(mContentParent->ChildID());
553
554
return NS_OK;
555
}
556
557
NS_IMETHODIMP
558
ScriptableCPInfo::GetMessageManager(nsISupports** aMessenger) {
559
*aMessenger = nullptr;
560
if (!mContentParent) {
561
return NS_ERROR_NOT_INITIALIZED;
562
}
563
564
RefPtr<ProcessMessageManager> manager = mContentParent->GetMessageManager();
565
manager.forget(aMessenger);
566
return NS_OK;
567
}
568
569
ProcessID GetTelemetryProcessID(const nsAString& remoteType) {
570
// OOP WebExtensions run in a content process.
571
// For Telemetry though we want to break out collected data from the
572
// WebExtensions process into a separate bucket, to make sure we can analyze
573
// it separately and avoid skewing normal content process metrics.
574
return remoteType.EqualsLiteral(EXTENSION_REMOTE_TYPE) ? ProcessID::Extension
575
: ProcessID::Content;
576
}
577
578
} // anonymous namespace
579
580
nsDataHashtable<nsUint32HashKey, ContentParent*>*
581
ContentParent::sJSPluginContentParents;
582
nsTArray<ContentParent*>* ContentParent::sPrivateContent;
583
StaticAutoPtr<LinkedList<ContentParent>> ContentParent::sContentParents;
584
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
585
UniquePtr<SandboxBrokerPolicyFactory>
586
ContentParent::sSandboxBrokerPolicyFactory;
587
#endif
588
uint64_t ContentParent::sNextRemoteTabId = 0;
589
nsDataHashtable<nsUint64HashKey, BrowserParent*>
590
ContentParent::sNextBrowserParents;
591
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
592
StaticAutoPtr<std::vector<std::string>> ContentParent::sMacSandboxParams;
593
#endif
594
595
// Whether a private docshell has been seen before.
596
static bool sHasSeenPrivateDocShell = false;
597
598
// This is true when subprocess launching is enabled. This is the
599
// case between StartUp() and ShutDown().
600
static bool sCanLaunchSubprocesses;
601
602
// Set to true if the DISABLE_UNSAFE_CPOW_WARNINGS environment variable is
603
// set.
604
static bool sDisableUnsafeCPOWWarnings = false;
605
606
// Set to true when the first content process gets created.
607
static bool sCreatedFirstContentProcess = false;
608
609
// The first content child has ID 1, so the chrome process can have ID 0.
610
static uint64_t gContentChildID = 1;
611
612
static const char* sObserverTopics[] = {
613
"xpcom-shutdown",
614
"profile-before-change",
615
NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC,
616
NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC,
617
NS_IPC_CAPTIVE_PORTAL_SET_STATE,
618
"memory-pressure",
619
"child-gc-request",
620
"child-cc-request",
621
"child-mmu-request",
622
"child-ghost-request",
623
"last-pb-context-exited",
624
"file-watcher-update",
625
#ifdef ACCESSIBILITY
626
"a11y-init-or-shutdown",
627
#endif
628
"cacheservice:empty-cache",
629
"intl:app-locales-changed",
630
"intl:requested-locales-changed",
631
"cookie-changed",
632
"private-cookie-changed",
633
NS_NETWORK_LINK_TYPE_TOPIC,
634
};
635
636
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
637
bool ContentParent::sEarlySandboxInit = false;
638
#endif
639
640
// PreallocateProcess is called by the PreallocatedProcessManager.
641
// ContentParent then takes this process back within GetNewOrUsedBrowserProcess.
642
/*static*/ RefPtr<ContentParent::LaunchPromise>
643
ContentParent::PreallocateProcess() {
644
RefPtr<ContentParent> process = new ContentParent(
645
/* aOpener = */ nullptr, NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE),
646
eNotRecordingOrReplaying,
647
/* aRecordingFile = */ EmptyString());
648
649
return process->LaunchSubprocessAsync(PROCESS_PRIORITY_PREALLOC);
650
}
651
652
/*static*/
653
void ContentParent::StartUp() {
654
// We could launch sub processes from content process
655
// FIXME Bug 1023701 - Stop using ContentParent static methods in
656
// child process
657
sCanLaunchSubprocesses = true;
658
659
if (!XRE_IsParentProcess()) {
660
return;
661
}
662
663
// Note: This reporter measures all ContentParents.
664
RegisterStrongMemoryReporter(new ContentParentsMemoryReporter());
665
666
BackgroundChild::Startup();
667
ClientManager::Startup();
668
669
sDisableUnsafeCPOWWarnings = PR_GetEnv("DISABLE_UNSAFE_CPOW_WARNINGS");
670
671
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
672
sSandboxBrokerPolicyFactory = MakeUnique<SandboxBrokerPolicyFactory>();
673
#endif
674
675
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
676
sMacSandboxParams = new std::vector<std::string>;
677
#endif
678
}
679
680
/*static*/
681
void ContentParent::ShutDown() {
682
// No-op for now. We rely on normal process shutdown and
683
// ClearOnShutdown() to clean up our state.
684
sCanLaunchSubprocesses = false;
685
686
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
687
sSandboxBrokerPolicyFactory = nullptr;
688
#endif
689
690
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
691
sMacSandboxParams = nullptr;
692
#endif
693
}
694
695
/*static*/
696
uint32_t ContentParent::GetPoolSize(const nsAString& aContentProcessType) {
697
if (!sBrowserContentParents) {
698
return 0;
699
}
700
701
nsTArray<ContentParent*>* parents =
702
sBrowserContentParents->Get(aContentProcessType);
703
704
return parents ? parents->Length() : 0;
705
}
706
707
/*static*/ nsTArray<ContentParent*>& ContentParent::GetOrCreatePool(
708
const nsAString& aContentProcessType) {
709
if (!sBrowserContentParents) {
710
sBrowserContentParents =
711
new nsClassHashtable<nsStringHashKey, nsTArray<ContentParent*>>;
712
}
713
714
return *sBrowserContentParents->LookupOrAdd(aContentProcessType);
715
}
716
717
const nsDependentSubstring RemoteTypePrefix(
718
const nsAString& aContentProcessType) {
719
// The suffix after a `=` in a remoteType is dynamic, and used to control the
720
// process pool to use.
721
int32_t equalIdx = aContentProcessType.FindChar(L'=');
722
if (equalIdx == kNotFound) {
723
equalIdx = aContentProcessType.Length();
724
}
725
return StringHead(aContentProcessType, equalIdx);
726
}
727
728
bool IsWebRemoteType(const nsAString& aContentProcessType) {
729
return StringBeginsWith(aContentProcessType,
730
NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE));
731
}
732
733
bool IsWebCoopCoepRemoteType(const nsAString& aContentProcessType) {
734
return StringBeginsWith(aContentProcessType,
735
NS_LITERAL_STRING(WITH_COOP_COEP_REMOTE_TYPE_PREFIX));
736
}
737
738
/*static*/
739
uint32_t ContentParent::GetMaxProcessCount(
740
const nsAString& aContentProcessType) {
741
// Max process count is based only on the prefix.
742
const nsDependentSubstring processTypePrefix =
743
RemoteTypePrefix(aContentProcessType);
744
745
// Check for the default remote type of "web", as it uses different prefs.
746
if (processTypePrefix.EqualsLiteral("web")) {
747
return GetMaxWebProcessCount();
748
}
749
750
// Read the pref controling this remote type. `dom.ipc.processCount` is not
751
// used as a fallback, as it is intended to control the number of "web"
752
// content processes, checked in `mozilla::GetMaxWebProcessCount()`.
753
nsAutoCString processCountPref("dom.ipc.processCount.");
754
AppendUTF16toUTF8(processTypePrefix, processCountPref);
755
756
int32_t maxContentParents = Preferences::GetInt(processCountPref.get(), 1);
757
if (maxContentParents < 1) {
758
maxContentParents = 1;
759
}
760
761
return static_cast<uint32_t>(maxContentParents);
762
}
763
764
/*static*/
765
bool ContentParent::IsMaxProcessCountReached(
766
const nsAString& aContentProcessType) {
767
return GetPoolSize(aContentProcessType) >=
768
GetMaxProcessCount(aContentProcessType);
769
}
770
771
/*static*/
772
void ContentParent::ReleaseCachedProcesses() {
773
if (!GetPoolSize(NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE))) {
774
return;
775
}
776
777
// We might want to extend this for other process types as well in the
778
// future...
779
nsTArray<ContentParent*>& contentParents =
780
GetOrCreatePool(NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE));
781
nsTArray<ContentParent*> toRelease;
782
783
// Shuting down these processes will change the array so let's use another
784
// array for the removal.
785
for (auto* cp : contentParents) {
786
if (cp->ManagedPBrowserParent().Count() == 0) {
787
toRelease.AppendElement(cp);
788
}
789
}
790
791
for (auto* cp : toRelease) {
792
// Start a soft shutdown.
793
cp->ShutDownProcess(SEND_SHUTDOWN_MESSAGE);
794
// Make sure we don't select this process for new tabs.
795
cp->MarkAsDead();
796
// Make sure that this process is no longer accessible from JS by its
797
// message manager.
798
cp->ShutDownMessageManager();
799
}
800
}
801
802
/*static*/
803
already_AddRefed<ContentParent> ContentParent::MinTabSelect(
804
const nsTArray<ContentParent*>& aContentParents, ContentParent* aOpener,
805
int32_t aMaxContentParents) {
806
uint32_t maxSelectable =
807
std::min(static_cast<uint32_t>(aContentParents.Length()),
808
static_cast<uint32_t>(aMaxContentParents));
809
uint32_t min = INT_MAX;
810
RefPtr<ContentParent> candidate;
811
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
812
813
for (uint32_t i = 0; i < maxSelectable; i++) {
814
ContentParent* p = aContentParents[i];
815
NS_ASSERTION(p->IsAlive(),
816
"Non-alive contentparent in sBrowserContentParents?");
817
if (!p->mShutdownPending && p->mOpener == aOpener) {
818
uint32_t tabCount = cpm->GetBrowserParentCountByProcessId(p->ChildID());
819
if (tabCount < min) {
820
candidate = p;
821
min = tabCount;
822
}
823
}
824
}
825
826
return candidate.forget();
827
}
828
829
static bool CreateTemporaryRecordingFile(nsAString& aResult) {
830
static int sNumTemporaryRecordings;
831
nsCOMPtr<nsIFile> file;
832
return !NS_FAILED(
833
NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(file))) &&
834
!NS_FAILED(file->AppendNative(
835
nsPrintfCString("TempRecording.%d.%d", base::GetCurrentProcId(),
836
++sNumTemporaryRecordings))) &&
837
!NS_FAILED(file->GetPath(aResult));
838
}
839
840
/*static*/
841
Maybe<ContentParent::RecordReplayState> ContentParent::GetRecordReplayState(
842
Element* aFrameElement, nsAString& aRecordingFile) {
843
if (!aFrameElement) {
844
return Some(eNotRecordingOrReplaying);
845
}
846
aFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::ReplayExecution,
847
aRecordingFile);
848
if (!aRecordingFile.IsEmpty()) {
849
return Some(eReplaying);
850
}
851
aFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::RecordExecution,
852
aRecordingFile);
853
if (aRecordingFile.IsEmpty() &&
854
recordreplay::parent::SaveAllRecordingsDirectory()) {
855
aRecordingFile.AssignLiteral("*");
856
}
857
if (!aRecordingFile.IsEmpty()) {
858
if (aRecordingFile.EqualsLiteral("*") &&
859
!CreateTemporaryRecordingFile(aRecordingFile)) {
860
return Nothing();
861
}
862
return Some(eRecording);
863
}
864
return Some(eNotRecordingOrReplaying);
865
}
866
867
/*static*/
868
already_AddRefed<ContentParent> ContentParent::GetUsedBrowserProcess(
869
ContentParent* aOpener, const nsAString& aRemoteType,
870
nsTArray<ContentParent*>& aContentParents, uint32_t aMaxContentParents,
871
bool aPreferUsed) {
872
uint32_t numberOfParents = aContentParents.Length();
873
nsTArray<RefPtr<nsIContentProcessInfo>> infos(numberOfParents);
874
for (auto* cp : aContentParents) {
875
infos.AppendElement(cp->mScriptableHelper);
876
}
877
878
if (aPreferUsed && numberOfParents) {
879
// For the preloaded browser we don't want to create a new process but
880
// reuse an existing one.
881
aMaxContentParents = numberOfParents;
882
}
883
884
nsCOMPtr<nsIContentProcessProvider> cpp =
885
do_GetService("@mozilla.org/ipc/processselector;1");
886
nsIContentProcessInfo* openerInfo =
887
aOpener ? aOpener->mScriptableHelper.get() : nullptr;
888
int32_t index;
889
if (cpp && NS_SUCCEEDED(cpp->ProvideProcess(aRemoteType, openerInfo, infos,
890
aMaxContentParents, &index))) {
891
// If the provider returned an existing ContentParent, use that one.
892
if (0 <= index && static_cast<uint32_t>(index) <= aMaxContentParents) {
893
RefPtr<ContentParent> retval = aContentParents[index];
894
return retval.forget();
895
}
896
} else {
897
// If there was a problem with the JS chooser, fall back to a random
898
// selection.
899
NS_WARNING("nsIContentProcessProvider failed to return a process");
900
RefPtr<ContentParent> random;
901
if (aContentParents.Length() >= aMaxContentParents &&
902
(random = MinTabSelect(aContentParents, aOpener, aMaxContentParents))) {
903
return random.forget();
904
}
905
}
906
907
// Try to take the preallocated process only for the default process type.
908
// The preallocated process manager might not had the chance yet to release
909
// the process after a very recent ShutDownProcess, let's make sure we don't
910
// try to reuse a process that is being shut down.
911
RefPtr<ContentParent> p;
912
if (aRemoteType.EqualsLiteral(DEFAULT_REMOTE_TYPE) &&
913
(p = PreallocatedProcessManager::Take()) && !p->mShutdownPending) {
914
// For pre-allocated process we have not set the opener yet.
915
p->mOpener = aOpener;
916
aContentParents.AppendElement(p);
917
p->mActivateTS = TimeStamp::Now();
918
return p.forget();
919
}
920
921
return nullptr;
922
}
923
924
/*static*/
925
RefPtr<ContentParent::LaunchPromise>
926
ContentParent::GetNewOrUsedBrowserProcessAsync(Element* aFrameElement,
927
const nsAString& aRemoteType,
928
ProcessPriority aPriority,
929
ContentParent* aOpener,
930
bool aPreferUsed) {
931
// Figure out if this process will be recording or replaying, and which file
932
// to use for the recording.
933
nsAutoString recordingFile;
934
Maybe<RecordReplayState> maybeRecordReplayState =
935
GetRecordReplayState(aFrameElement, recordingFile);
936
if (maybeRecordReplayState.isNothing()) {
937
// Error, cannot fulfill this record/replay request.
938
return nullptr;
939
}
940
RecordReplayState recordReplayState = maybeRecordReplayState.value();
941
942
nsTArray<ContentParent*>& contentParents = GetOrCreatePool(aRemoteType);
943
uint32_t maxContentParents = GetMaxProcessCount(aRemoteType);
944
if (recordReplayState ==
945
eNotRecordingOrReplaying // Fall through and always create a new
946
// process when recording or replaying.
947
&& aRemoteType.EqualsLiteral(
948
LARGE_ALLOCATION_REMOTE_TYPE) // We never want to re-use
949
// Large-Allocation processes.
950
&& contentParents.Length() >= maxContentParents) {
951
return GetNewOrUsedBrowserProcessAsync(
952
aFrameElement, NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE), aPriority,
953
aOpener);
954
}
955
{
956
RefPtr<ContentParent> existing = GetUsedBrowserProcess(
957
aOpener, aRemoteType, contentParents, maxContentParents, aPreferUsed);
958
if (existing != nullptr) {
959
return LaunchPromise::CreateAndResolve(existing, __func__);
960
}
961
}
962
963
// Create a new process from scratch.
964
RefPtr<ContentParent> p =
965
new ContentParent(aOpener, aRemoteType, recordReplayState, recordingFile);
966
967
RefPtr<LaunchPromise> launchPromise = p->LaunchSubprocessAsync(aPriority);
968
MOZ_ASSERT(launchPromise);
969
970
// Until the new process is ready let's not allow to start up any
971
// preallocated processes. In case of success, the blocker is removed
972
// when we receive the first `idle` message. In case of failure, we
973
// cleanup manually in the `OnReject`.
974
PreallocatedProcessManager::AddBlocker(p);
975
976
return launchPromise->Then(
977
GetCurrentThreadSerialEventTarget(), __func__,
978
// on resolve
979
[p, recordReplayState,
980
launchPromise](const RefPtr<ContentParent>& subProcess) {
981
if (recordReplayState == eNotRecordingOrReplaying) {
982
// We cannot reuse `contentParents` as it may have been
983
// overwritten or otherwise altered by another process launch.
984
nsTArray<ContentParent*>& contentParents =
985
GetOrCreatePool(p->GetRemoteType());
986
contentParents.AppendElement(p);
987
}
988
989
p->mActivateTS = TimeStamp::Now();
990
return launchPromise;
991
},
992
[p, launchPromise]() {
993
PreallocatedProcessManager::RemoveBlocker(p);
994
return launchPromise;
995
});
996
}
997
998
/*static*/
999
already_AddRefed<ContentParent> ContentParent::GetNewOrUsedBrowserProcess(
1000
Element* aFrameElement, const nsAString& aRemoteType,
1001
ProcessPriority aPriority, ContentParent* aOpener, bool aPreferUsed) {
1002
// Figure out if this process will be recording or replaying, and which file
1003
// to use for the recording.
1004
nsAutoString recordingFile;
1005
Maybe<RecordReplayState> maybeRecordReplayState =
1006
GetRecordReplayState(aFrameElement, recordingFile);
1007
if (maybeRecordReplayState.isNothing()) {
1008
// Error, cannot fulfill this record/replay request.
1009
return nullptr;
1010
}
1011
RecordReplayState recordReplayState = maybeRecordReplayState.value();
1012
1013
nsTArray<ContentParent*>& contentParents = GetOrCreatePool(aRemoteType);
1014
uint32_t maxContentParents = GetMaxProcessCount(aRemoteType);
1015
if (recordReplayState ==
1016
eNotRecordingOrReplaying // Fall through and always create a new
1017
// process when recording or replaying.
1018
&& aRemoteType.EqualsLiteral(
1019
LARGE_ALLOCATION_REMOTE_TYPE) // We never want to re-use
1020
// Large-Allocation processes.
1021
&& contentParents.Length() >= maxContentParents) {
1022
return GetNewOrUsedBrowserProcess(aFrameElement,
1023
NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE),
1024
aPriority, aOpener);
1025
}
1026
1027
if (recordReplayState == eNotRecordingOrReplaying) {
1028
RefPtr<ContentParent> existing = GetUsedBrowserProcess(
1029
aOpener, aRemoteType, contentParents, maxContentParents, aPreferUsed);
1030
if (existing != nullptr) {
1031
return existing.forget();
1032
}
1033
}
1034
1035
// Create a new process from scratch.
1036
RefPtr<ContentParent> p =
1037
new ContentParent(aOpener, aRemoteType, recordReplayState, recordingFile);
1038
1039
if (!p->LaunchSubprocessSync(aPriority)) {
1040
return nullptr;
1041
}
1042
1043
// Until the new process is ready let's not allow to start up any preallocated
1044
// processes.
1045
PreallocatedProcessManager::AddBlocker(p);
1046
1047
if (recordReplayState == eNotRecordingOrReplaying) {
1048
contentParents.AppendElement(p);
1049
}
1050
1051
p->mActivateTS = TimeStamp::Now();
1052
return p.forget();
1053
}
1054
1055
/*static*/
1056
already_AddRefed<ContentParent> ContentParent::GetNewOrUsedJSPluginProcess(
1057
uint32_t aPluginID, const hal::ProcessPriority& aPriority) {
1058
RefPtr<ContentParent> p;
1059
if (sJSPluginContentParents) {
1060
p = sJSPluginContentParents->Get(aPluginID);
1061
} else {
1062
sJSPluginContentParents =
1063
new nsDataHashtable<nsUint32HashKey, ContentParent*>();
1064
}
1065
1066
if (p) {
1067
return p.forget();
1068
}
1069
1070
p = new ContentParent(aPluginID);
1071
1072
if (!p->LaunchSubprocessSync(aPriority)) {
1073
return nullptr;
1074
}
1075
1076
sJSPluginContentParents->Put(aPluginID, p);
1077
1078
return p.forget();
1079
}
1080
1081
/*static*/
1082
ProcessPriority ContentParent::GetInitialProcessPriority(
1083
Element* aFrameElement) {
1084
// Frames with mozapptype == critical which are expecting a system message
1085
// get FOREGROUND_HIGH priority.
1086
1087
if (!aFrameElement) {
1088
return PROCESS_PRIORITY_FOREGROUND;
1089
}
1090
1091
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(aFrameElement);
1092
if (!browserFrame) {
1093
return PROCESS_PRIORITY_FOREGROUND;
1094
}
1095
1096
return PROCESS_PRIORITY_FOREGROUND;
1097
}
1098
1099
#if defined(XP_WIN)
1100
extern const wchar_t* kPluginWidgetContentParentProperty;
1101
1102
/*static*/
1103
void ContentParent::SendAsyncUpdate(nsIWidget* aWidget) {
1104
if (!aWidget || aWidget->Destroyed()) {
1105
return;
1106
}
1107
// Fire off an async request to the plugin to paint its window
1108
HWND hwnd = (HWND)aWidget->GetNativeData(NS_NATIVE_WINDOW);
1109
NS_ASSERTION(hwnd, "Expected valid hwnd value.");
1110
ContentParent* cp = reinterpret_cast<ContentParent*>(
1111
::GetPropW(hwnd, kPluginWidgetContentParentProperty));
1112
if (cp && !cp->IsDestroyed()) {
1113
Unused << cp->SendUpdateWindow((uintptr_t)hwnd);
1114
}
1115
}
1116
#endif // defined(XP_WIN)
1117
1118
static nsIDocShell* GetOpenerDocShellHelper(Element* aFrameElement) {
1119
// Propagate the private-browsing status of the element's parent
1120
// docshell to the remote docshell, via the chrome flags.
1121
MOZ_ASSERT(aFrameElement);
1122
nsPIDOMWindowOuter* win = aFrameElement->OwnerDoc()->GetWindow();
1123
if (!win) {
1124
NS_WARNING("Remote frame has no window");
1125
return nullptr;
1126
}
1127
nsIDocShell* docShell = win->GetDocShell();
1128
if (!docShell) {
1129
NS_WARNING("Remote frame has no docshell");
1130
return nullptr;
1131
}
1132
1133
return docShell;
1134
}
1135
1136
mozilla::ipc::IPCResult ContentParent::RecvCreateGMPService() {
1137
Endpoint<PGMPServiceParent> parent;
1138
Endpoint<PGMPServiceChild> child;
1139
1140
nsresult rv;
1141
rv = PGMPService::CreateEndpoints(base::GetCurrentProcId(), OtherPid(),
1142
&parent, &child);
1143
if (NS_FAILED(rv)) {
1144
MOZ_ASSERT(false, "CreateEndpoints failed");
1145
return IPC_FAIL_NO_REASON(this);
1146
}
1147
1148
if (!GMPServiceParent::Create(std::move(parent))) {
1149
MOZ_ASSERT(false, "GMPServiceParent::Create failed");
1150
return IPC_FAIL_NO_REASON(this);
1151
}
1152
1153
if (!SendInitGMPService(std::move(child))) {
1154
MOZ_ASSERT(false, "SendInitGMPService failed");
1155
return IPC_FAIL_NO_REASON(this);
1156
}
1157
1158
return IPC_OK();
1159
}
1160
1161
mozilla::ipc::IPCResult ContentParent::RecvLoadPlugin(
1162
const uint32_t& aPluginId, nsresult* aRv, uint32_t* aRunID,
1163
Endpoint<PPluginModuleParent>* aEndpoint) {
1164
*aRv = NS_OK;
1165
if (!mozilla::plugins::SetupBridge(aPluginId, this, aRv, aRunID, aEndpoint)) {
1166
return IPC_FAIL_NO_REASON(this);
1167
}
1168
return IPC_OK();
1169
}
1170
1171
mozilla::ipc::IPCResult ContentParent::RecvUngrabPointer(
1172
const uint32_t& aTime) {
1173
#if !defined(MOZ_WIDGET_GTK)
1174
MOZ_CRASH("This message only makes sense on GTK platforms");
1175
#else
1176
gdk_pointer_ungrab(aTime);
1177
return IPC_OK();
1178
#endif
1179
}
1180
1181
mozilla::ipc::IPCResult ContentParent::RecvRemovePermission(
1182
const IPC::Principal& aPrincipal, const nsCString& aPermissionType,
1183
nsresult* aRv) {
1184
*aRv = Permissions::RemovePermission(aPrincipal, aPermissionType);
1185
return IPC_OK();
1186
}
1187
1188
mozilla::ipc::IPCResult ContentParent::RecvConnectPluginBridge(
1189
const uint32_t& aPluginId, nsresult* aRv,
1190
Endpoint<PPluginModuleParent>* aEndpoint) {
1191
*aRv = NS_OK;
1192
// We don't need to get the run ID for the plugin, since we already got it
1193
// in the first call to SetupBridge in RecvLoadPlugin, so we pass in a dummy
1194
// pointer and just throw it away.
1195
uint32_t dummy = 0;
1196
if (!mozilla::plugins::SetupBridge(aPluginId, this, aRv, &dummy, aEndpoint)) {
1197
return IPC_FAIL(this, "SetupBridge failed");
1198
}
1199
return IPC_OK();
1200
}
1201
1202
mozilla::ipc::IPCResult ContentParent::RecvLaunchRDDProcess(
1203
nsresult* aRv, Endpoint<PRemoteDecoderManagerChild>* aEndpoint) {
1204
*aRv = NS_OK;
1205
1206
if (XRE_IsParentProcess() &&
1207
BrowserTabsRemoteAutostart() && // only do rdd process if e10s on
1208
Preferences::GetBool("media.rdd-process.enabled", false)) {
1209
RDDProcessManager* rdd = RDDProcessManager::Get();
1210
if (rdd) {
1211
bool rddOpened = rdd->LaunchRDDProcess();
1212
if (rddOpened) {
1213
rddOpened = rdd->CreateContentBridge(OtherPid(), aEndpoint);
1214
}
1215
1216
if (NS_WARN_IF(!rddOpened)) {
1217
*aRv = NS_ERROR_NOT_AVAILABLE;
1218
}
1219
} else {
1220
*aRv = NS_ERROR_NOT_AVAILABLE;
1221
}
1222
}
1223
1224
return IPC_OK();
1225
}
1226
1227
/*static*/
1228
already_AddRefed<RemoteBrowser> ContentParent::CreateBrowser(
1229
const TabContext& aContext, Element* aFrameElement,
1230
const nsAString& aRemoteType, BrowsingContext* aBrowsingContext,
1231
ContentParent* aOpenerContentParent, BrowserParent* aSameTabGroupAs,
1232
uint64_t aNextRemoteTabId) {
1233
AUTO_PROFILER_LABEL("ContentParent::CreateBrowser", OTHER);
1234
1235
if (!sCanLaunchSubprocesses) {
1236
return nullptr;
1237
}
1238
1239
nsAutoString remoteType(aRemoteType);
1240
if (remoteType.IsEmpty()) {
1241
remoteType.AssignLiteral(DEFAULT_REMOTE_TYPE);
1242
}
1243
1244
if (aNextRemoteTabId) {
1245
if (BrowserParent* parent =
1246
sNextBrowserParents.GetAndRemove(aNextRemoteTabId)
1247
.valueOr(nullptr)) {
1248
RefPtr<BrowserHost> browserHost = new BrowserHost(parent);
1249
MOZ_ASSERT(!parent->GetOwnerElement(),
1250
"Shouldn't have an owner elemnt before");
1251
parent->SetOwnerElement(aFrameElement);
1252
return browserHost.forget();
1253
}
1254
}
1255
1256
ProcessPriority initialPriority = GetInitialProcessPriority(aFrameElement);
1257
TabId tabId(nsContentUtils::GenerateTabId());
1258
1259
nsIDocShell* docShell = GetOpenerDocShellHelper(aFrameElement);
1260
TabId openerTabId;
1261
if (docShell) {
1262
openerTabId = BrowserParent::GetTabIdFrom(docShell);
1263
}
1264
1265
bool isPreloadBrowser = false;
1266
nsAutoString isPreloadBrowserStr;
1267
if (aFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::preloadedState,
1268
isPreloadBrowserStr)) {
1269
isPreloadBrowser = isPreloadBrowserStr.EqualsLiteral("preloaded");
1270
}
1271
1272
RefPtr<ContentParent> constructorSender;
1273
MOZ_RELEASE_ASSERT(XRE_IsParentProcess(),
1274
"Cannot allocate BrowserParent in content process");
1275
if (aOpenerContentParent) {
1276
constructorSender = aOpenerContentParent;
1277
} else {
1278
if (aContext.IsJSPlugin()) {
1279
constructorSender =
1280
GetNewOrUsedJSPluginProcess(aContext.JSPluginId(), initialPriority);
1281
} else {
1282
constructorSender =
1283
GetNewOrUsedBrowserProcess(aFrameElement, remoteType, initialPriority,
1284
nullptr, isPreloadBrowser);
1285
}
1286
if (!constructorSender) {
1287
return nullptr;
1288
}
1289
}
1290
1291
aBrowsingContext->SetEmbedderElement(aFrameElement);
1292
1293
// Ensure that our content process is subscribed to our newly created
1294
// BrowsingContextGroup.
1295
aBrowsingContext->Group()->EnsureSubscribed(constructorSender);
1296
1297
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
1298
docShell->GetTreeOwner(getter_AddRefs(treeOwner));
1299
if (!treeOwner) {
1300
return nullptr;
1301
}
1302
1303
nsCOMPtr<nsIWebBrowserChrome> wbc = do_GetInterface(treeOwner);
1304
if (!wbc) {
1305
return nullptr;
1306
}
1307
uint32_t chromeFlags = 0;
1308
wbc->GetChromeFlags(&chromeFlags);
1309
1310
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
1311
if (loadContext && loadContext->UsePrivateBrowsing()) {
1312
chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
1313
}
1314
if (loadContext && loadContext->UseRemoteTabs()) {
1315
chromeFlags |= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW;
1316
}
1317
if (loadContext && loadContext->UseRemoteSubframes()) {
1318
chromeFlags |= nsIWebBrowserChrome::CHROME_FISSION_WINDOW;
1319
}
1320
if (docShell->GetAffectPrivateSessionLifetime()) {
1321
chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME;
1322
}
1323
1324
if (tabId == 0) {
1325
return nullptr;
1326
}
1327
1328
aBrowsingContext->Canonical()->SetOwnerProcessId(
1329
constructorSender->ChildID());
1330
1331
RefPtr<BrowserParent> browserParent =
1332
new BrowserParent(constructorSender, tabId, aContext,
1333
aBrowsingContext->Canonical(), chromeFlags);
1334
1335
// Open a remote endpoint for our PBrowser actor.
1336
ManagedEndpoint<PBrowserChild> childEp =
1337
constructorSender->OpenPBrowserEndpoint(browserParent);
1338
if (NS_WARN_IF(!childEp.IsValid())) {
1339
return nullptr;
1340
}
1341
1342
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
1343
cpm->RegisterRemoteFrame(browserParent);
1344
1345
nsCOMPtr<nsIPrincipal> initialPrincipal =
1346
NullPrincipal::Create(aContext.OriginAttributesRef());
1347
WindowGlobalInit windowInit = WindowGlobalActor::AboutBlankInitializer(
1348
aBrowsingContext, initialPrincipal);
1349
1350
auto windowParent =
1351
MakeRefPtr<WindowGlobalParent>(windowInit, /* inprocess */ false);
1352
1353
// Open a remote endpoint for the initial PWindowGlobal actor.
1354
ManagedEndpoint<PWindowGlobalChild> windowEp =
1355
browserParent->OpenPWindowGlobalEndpoint(windowParent);
1356
if (NS_WARN_IF(!windowEp.IsValid())) {
1357
return nullptr;
1358
}
1359
1360
// Tell the content process to set up its PBrowserChild.
1361
bool ok = constructorSender->SendConstructBrowser(
1362
std::move(childEp), std::move(windowEp), tabId,
1363
aSameTabGroupAs ? aSameTabGroupAs->GetTabId() : TabId(0),
1364
aContext.AsIPCTabContext(), windowInit, chromeFlags,
1365
constructorSender->ChildID(), constructorSender->IsForBrowser(),
1366
/* aIsTopLevel */ true);
1367
if (NS_WARN_IF(!ok)) {
1368
return nullptr;
1369
}
1370
1371
windowParent->Init(windowInit);
1372
1373
if (remoteType.EqualsLiteral(LARGE_ALLOCATION_REMOTE_TYPE)) {
1374
// Tell the BrowserChild object that it was created due to a
1375
// Large-Allocation request.
1376
Unused << browserParent->SendAwaitLargeAlloc();
1377
}
1378
1379
RefPtr<BrowserHost> browserHost = new BrowserHost(browserParent);
1380
browserParent->SetOwnerElement(aFrameElement);
1381
return browserHost.forget();
1382
}
1383
1384
void ContentParent::GetAll(nsTArray<ContentParent*>& aArray) {
1385
aArray.Clear();
1386
1387
for (auto* cp : AllProcesses(eLive)) {
1388
aArray.AppendElement(cp);
1389
}
1390
}
1391
1392
void ContentParent::GetAllEvenIfDead(nsTArray<ContentParent*>& aArray) {
1393
aArray.Clear();
1394
1395
for (auto* cp : AllProcesses(eAll)) {
1396
aArray.AppendElement(cp);
1397
}
1398
}
1399
1400
void ContentParent::BroadcastStringBundle(
1401
const StringBundleDescriptor& aBundle) {
1402
AutoTArray<StringBundleDescriptor, 1> array;
1403
array.AppendElement(aBundle);
1404
1405
for (auto* cp : AllProcesses(eLive)) {
1406
Unused << cp->SendRegisterStringBundles(array);
1407
}
1408
}
1409
1410
void ContentParent::BroadcastFontListChanged() {
1411
for (auto* cp : AllProcesses(eLive)) {
1412
Unused << cp->SendFontListChanged();
1413
}
1414
}
1415
1416
const nsAString& ContentParent::GetRemoteType() const { return mRemoteType; }
1417
1418
void ContentParent::Init() {
1419
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
1420
if (obs) {
1421
size_t length = ArrayLength(sObserverTopics);
1422
for (size_t i = 0; i < length; ++i) {
1423
obs->AddObserver(this, sObserverTopics[i], false);
1424
}
1425
}
1426
1427
// Flush any pref updates that happened during launch and weren't
1428
// included in the blobs set up in LaunchSubprocessInternal.
1429
for (const Pref& pref : mQueuedPrefs) {
1430
Unused << NS_WARN_IF(!SendPreferenceUpdate(pref));
1431
}
1432
mQueuedPrefs.Clear();
1433
1434
if (obs) {
1435
nsAutoString cpId;
1436
cpId.AppendInt(static_cast<uint64_t>(this->ChildID()));
1437
obs->NotifyObservers(static_cast<nsIObserver*>(this), "ipc:content-created",
1438
cpId.get());
1439
}
1440
1441
#ifdef ACCESSIBILITY
1442
// If accessibility is running in chrome process then start it in content
1443
// process.
1444
if (PresShell::IsAccessibilityActive()) {
1445
# if defined(XP_WIN)
1446
// Don't init content a11y if we detect an incompat version of JAWS in use.
1447
if (!mozilla::a11y::Compatibility::IsOldJAWS()) {
1448
Unused << SendActivateA11y(
1449
::GetCurrentThreadId(),
1450
a11y::AccessibleWrap::GetContentProcessIdFor(ChildID()));
1451
}
1452
# else
1453
Unused << SendActivateA11y(0, 0);
1454
# endif
1455
}
1456
#endif // #ifdef ACCESSIBILITY
1457
1458
#ifdef MOZ_GECKO_PROFILER
1459
Unused << SendInitProfiler(ProfilerParent::CreateForProcess(OtherPid()));
1460
#endif
1461
1462
// Ensure that the default set of permissions are avaliable in the content
1463
// process before we try to load any URIs in it.
1464
EnsurePermissionsByKey(EmptyCString());
1465
1466
RefPtr<GeckoMediaPluginServiceParent> gmps(
1467
GeckoMediaPluginServiceParent::GetSingleton());
1468
gmps->UpdateContentProcessGMPCapabilities();
1469
1470
mScriptableHelper = new ScriptableCPInfo(this);
1471
}
1472
1473
NS_IMPL_ISUPPORTS(RemoteWindowContext, nsIRemoteWindowContext,
1474
nsIInterfaceRequestor)
1475
1476
RemoteWindowContext::RemoteWindowContext(BrowserParent* aBrowserParent)
1477
: mBrowserParent(aBrowserParent) {}
1478
1479
NS_IMETHODIMP
1480
RemoteWindowContext::GetInterface(const nsIID& aIID, void** aSink) {
1481
return QueryInterface(aIID, aSink);
1482
}
1483
1484
NS_IMETHODIMP
1485
RemoteWindowContext::OpenURI(nsIURI* aURI) {
1486
mBrowserParent->LoadURL(aURI);
1487
return NS_OK;
1488
}
1489
1490
NS_IMETHODIMP
1491
RemoteWindowContext::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) {
1492
nsCOMPtr<nsILoadContext> loadContext = mBrowserParent->GetLoadContext();
1493
*aUsePrivateBrowsing = loadContext && loadContext->UsePrivateBrowsing();
1494
return NS_OK;
1495
}
1496
1497
void ContentParent::MaybeAsyncSendShutDownMessage() {
1498
MOZ_ASSERT(NS_IsMainThread());
1499
MOZ_ASSERT(!TryToRecycle());
1500
1501
#ifdef DEBUG
1502
// Calling this below while the lock is acquired will deadlock.
1503
bool shouldKeepProcessAlive = ShouldKeepProcessAlive();
1504
#endif
1505
1506
auto lock = mRemoteWorkerActorData.Lock();
1507
MOZ_ASSERT_IF(!lock->mCount, !shouldKeepProcessAlive);
1508
1509
if (lock->mCount) {
1510
return;
1511
}
1512
1513
MOZ_ASSERT(!lock->mShutdownStarted);
1514
lock->mShutdownStarted = true;
1515
1516
// In the case of normal shutdown, send a shutdown message to child to
1517
// allow it to perform shutdown tasks.
1518
MessageLoop::current()->PostTask(NewRunnableMethod<ShutDownMethod>(
1519
"dom::ContentParent::ShutDownProcess", this,
1520
&ContentParent::ShutDownProcess, SEND_SHUTDOWN_MESSAGE));
1521
}
1522
1523
void ContentParent::ShutDownProcess(ShutDownMethod aMethod) {
1524
if (mScriptableHelper) {
1525
static_cast<ScriptableCPInfo*>(mScriptableHelper.get())->ProcessDied();
1526
mScriptableHelper = nullptr;
1527
}
1528
1529
// Shutting down by sending a shutdown message works differently than the
1530
// other methods. We first call Shutdown() in the child. After the child is
1531
// ready, it calls FinishShutdown() on us. Then we close the channel.
1532
if (aMethod == SEND_SHUTDOWN_MESSAGE) {
1533
if (const char* directory =
1534
recordreplay::parent::SaveAllRecordingsDirectory()) {
1535
// Save a recording for the child process before it shuts down.
1536
static int sNumSavedRecordings;
1537
nsCOMPtr<nsIFile> file;
1538
if (!NS_FAILED(NS_NewNativeLocalFile(nsDependentCString(directory), false,
1539
getter_AddRefs(file))) &&
1540
!NS_FAILED(file->AppendNative(
1541
nsPrintfCString("Recording.%d.%d", base::GetCurrentProcId(),
1542
++sNumSavedRecordings)))) {
1543
bool unused;
1544
SaveRecording(file, &unused);
1545
}
1546
}
1547
1548
if (mIPCOpen && !mShutdownPending) {
1549
// Stop sending input events with input priority when shutting down.
1550
SetInputPriorityEventEnabled(false);
1551
if (SendShutdown()) {
1552
mShutdownPending = true;
1553
// Start the force-kill timer if we haven't already.
1554
StartForceKillTimer();
1555
}
1556
}
1557
// If call was not successful, the channel must have been broken
1558
// somehow, and we will clean up the error in ActorDestroy.
1559
return;
1560
}
1561
1562
using mozilla::dom::quota::QuotaManagerService;
1563
1564
if (QuotaManagerService* qms = QuotaManagerService::GetOrCreate()) {
1565
qms->AbortOperationsForProcess(mChildID);
1566
}
1567
1568
// If Close() fails with an error, we'll end up back in this function, but
1569
// with aMethod = CLOSE_CHANNEL_WITH_ERROR.
1570
1571
if (aMethod == CLOSE_CHANNEL && !mCalledClose) {
1572
// Close() can only be called once: It kicks off the destruction
1573
// sequence.
1574
mCalledClose = true;
1575
Close();
1576
}
1577
1578
const ManagedContainer<POfflineCacheUpdateParent>& ocuParents =
1579
ManagedPOfflineCacheUpdateParent();
1580
for (auto iter = ocuParents.ConstIter(); !iter.Done(); iter.Next()) {
1581
RefPtr<mozilla::docshell::OfflineCacheUpdateParent> ocuParent =
1582
static_cast<mozilla::docshell::OfflineCacheUpdateParent*>(
1583
iter.Get()->GetKey());
1584
ocuParent->StopSendingMessagesToChild();
1585
}
1586
1587
// NB: must MarkAsDead() here so that this isn't accidentally
1588
// returned from Get*() while in the midst of shutdown.
1589
MarkAsDead();
1590
1591
// A ContentParent object might not get freed until after XPCOM shutdown has
1592
// shut down the cycle collector. But by then it's too late to release any
1593
// CC'ed objects, so we need to null them out here, while we still can. See
1594
// bug 899761.
1595
ShutDownMessageManager();
1596
}
1597
1598
mozilla::ipc::IPCResult ContentParent::RecvFinishShutdown() {
1599
// At this point, we already called ShutDownProcess once with
1600
// SEND_SHUTDOWN_MESSAGE. To actually close the channel, we call
1601
// ShutDownProcess again with CLOSE_CHANNEL.
1602
MOZ_ASSERT(mShutdownPending);
1603
ShutDownProcess(CLOSE_CHANNEL);
1604
return IPC_OK();
1605
}
1606
1607
void ContentParent::ShutDownMessageManager() {
1608
if (!mMessageManager) {
1609
return;
1610
}
1611
1612
mMessageManager->ReceiveMessage(
1613
mMessageManager, nullptr, CHILD_PROCESS_SHUTDOWN_MESSAGE, false, nullptr,
1614
nullptr, nullptr, nullptr, IgnoreErrors());
1615
1616
mMessageManager->SetOsPid(-1);
1617
mMessageManager->Disconnect();
1618
mMessageManager = nullptr;
1619
}
1620
1621
void ContentParent::RemoveFromList() {
1622
if (IsForJSPlugin()) {
1623
if (sJSPluginContentParents) {
1624
sJSPluginContentParents->Remove(mJSPluginID);
1625
if (!sJSPluginContentParents->Count()) {
1626
delete sJSPluginContentParents;
1627
sJSPluginContentParents = nullptr;
1628
}
1629
}
1630
} else if (sBrowserContentParents) {
1631
if (auto entry = sBrowserContentParents->Lookup(mRemoteType)) {
1632
const auto& contentParents = entry.Data();
1633
contentParents->RemoveElement(this);
1634
if (contentParents->IsEmpty()) {
1635
entry.Remove();
1636
}
1637
}
1638
if (sBrowserContentParents->IsEmpty()) {
1639
delete sBrowserContentParents;
1640
sBrowserContentParents = nullptr;
1641
}
1642
}
1643
1644
if (sPrivateContent) {
1645
sPrivateContent->RemoveElement(this);
1646
if (!sPrivateContent->Length()) {
1647
delete sPrivateContent;
1648
sPrivateContent = nullptr;
1649
}
1650
}
1651
}
1652
1653
void ContentParent::MarkAsDead() {
1654
RemoveFromList();
1655
mLifecycleState = LifecycleState::DEAD;
1656
#ifdef MOZ_WIDGET_ANDROID
1657
nsCOMPtr<nsIEventTarget> launcherThread(GetIPCLauncher());
1658
MOZ_ASSERT(launcherThread);
1659
1660
auto procType = java::GeckoProcessType::CONTENT();
1661
auto selector =
1662
java::GeckoProcessManager::Selector::New(procType, OtherPid());
1663
1664
launcherThread->Dispatch(NS_NewRunnableFunction(
1665
"ContentParent::MarkAsDead",
1666
[selector = java::GeckoProcessManager::Selector::GlobalRef(selector)]() {
1667
java::GeckoProcessManager::MarkAsDead(selector);
1668
}));
1669
#endif
1670
}
1671
1672
void ContentParent::OnChannelError() {
1673
RefPtr<ContentParent> kungFuDeathGrip(this);
1674
PContentParent::OnChannelError();
1675
}
1676
1677
void ContentParent::OnChannelConnected(int32_t pid) {
1678
MOZ_ASSERT(NS_IsMainThread());
1679
1680
SetOtherProcessId(pid);
1681
}
1682
1683
void ContentParent::ProcessingError(Result aCode, const char* aReason) {
1684
if (MsgDropped == aCode) {
1685
return;
1686
}
1687
#ifndef FUZZING
1688
// Other errors are big deals.
1689
KillHard(aReason);
1690
#endif
1691
}
1692
1693
void ContentParent::ActorDestroy(ActorDestroyReason why) {
1694
MOZ_RELEASE_ASSERT(mSelfRef);
1695
1696
if (mForceKillTimer) {
1697
mForceKillTimer->Cancel();
1698
mForceKillTimer = nullptr;
1699
}
1700
1701
// Signal shutdown completion regardless of error state, so we can
1702
// finish waiting in the xpcom-shutdown/profile-before-change observer.
1703
mIPCOpen = false;
1704
1705
if (mHangMonitorActor) {
1706
ProcessHangMonitor::RemoveProcess(mHangMonitorActor);
1707
mHangMonitorActor = nullptr;
1708
}
1709
1710
RefPtr<FileSystemSecurity> fss = FileSystemSecurity::Get();
1711
if (fss) {
1712
fss->Forget(ChildID());
1713
}
1714
1715
if (why == NormalShutdown && !mCalledClose) {
1716
// If we shut down normally but haven't called Close, assume somebody
1717
// else called Close on us. In that case, we still need to call
1718
// ShutDownProcess below to perform other necessary clean up.
1719
mCalledClose = true;
1720
}
1721
1722
// Make sure we always clean up.
1723
ShutDownProcess(why == NormalShutdown ? CLOSE_CHANNEL
1724
: CLOSE_CHANNEL_WITH_ERROR);
1725
1726
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
1727
if (obs) {
1728
size_t length = ArrayLength(sObserverTopics);
1729
for (size_t i = 0; i < length; ++i) {
1730
obs->RemoveObserver(static_cast<nsIObserver*>(this), sObserverTopics[i]);
1731
}
1732
}
1733
1734
// remove the global remote preferences observers
1735
Preferences::RemoveObserver(this, "");
1736
gfxVars::RemoveReceiver(this);
1737
1738
if (GPUProcessManager* gpu = GPUProcessManager::Get()) {
1739
// Note: the manager could have shutdown already.
1740
gpu->RemoveListener(this);
1741
}
1742
1743
RecvRemoveGeolocationListener();
1744
1745
mConsoleService = nullptr;
1746
1747
if (obs) {
1748
RefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
1749
1750
props->SetPropertyAsUint64(NS_LITERAL_STRING("childID"), mChildID);
1751
1752
if (AbnormalShutdown == why) {
1753
Telemetry::Accumulate(Telemetry::SUBPROCESS_ABNORMAL_ABORT,
1754
NS_LITERAL_CSTRING("content"), 1);
1755
1756
props->SetPropertyAsBool(NS_LITERAL_STRING("abnormal"), true);
1757
1758
nsAutoString dumpID;
1759
// There's a window in which child processes can crash
1760
// after IPC is established, but before a crash reporter
1761
// is created.
1762
if (mCrashReporter) {
1763
// if mCreatedPairedMinidumps is true, we've already generated
1764
// parent/child dumps for desktop crashes.
1765
if (!mCreatedPairedMinidumps) {
1766
mCrashReporter->GenerateCrashReport(OtherPid());
1767
}
1768
1769
if (mCrashReporter->HasMinidump()) {
1770
dumpID = mCrashReporter->MinidumpID();
1771
}
1772
} else {
1773
HandleOrphanedMinidump(&dumpID);
1774
}
1775
1776
if (!dumpID.IsEmpty()) {
1777
props->SetPropertyAsAString(NS_LITERAL_STRING("dumpID"), dumpID);
1778
}
1779
}
1780
nsAutoString cpId;
1781
cpId.AppendInt(static_cast<uint64_t>(this->ChildID()));
1782
obs->NotifyObservers((nsIPropertyBag2*)props, "ipc:content-shutdown",
1783
cpId.get());
1784
}
1785
1786
// Remove any and all idle listeners.
1787
nsCOMPtr<nsIIdleService> idleService =
1788
do_GetService("@mozilla.org/widget/idleservice;1");
1789
MOZ_ASSERT(idleService);
1790
RefPtr<ParentIdleListener> listener;
1791
for (int32_t i = mIdleListeners.Length() - 1; i >= 0; --i) {
1792
listener = static_cast<ParentIdleListener*>(mIdleListeners[i].get());
1793
idleService->RemoveIdleObserver(listener, listener->mTime);
1794
}
1795
mIdleListeners.Clear();
1796
1797
// FIXME (bug 1520997): does this really need an additional dispatch?
1798
MessageLoop::current()->PostTask(NS_NewRunnableFunction(
1799
"DelayedDeleteSubprocessRunnable",
1800
[subprocess = mSubprocess] { subprocess->Destroy(); }));
1801
mSubprocess = nullptr;
1802
1803
// Delete any remaining replaying children.
1804
for (auto& replayingProcess : mReplayingChildren) {
1805
if (replayingProcess) {
1806
replayingProcess->Destroy();
1807
replayingProcess = nullptr;
1808
}
1809
}
1810
1811
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
1812
cpm->RemoveContentProcess(this->ChildID());
1813
1814
if (mDriverCrashGuard) {
1815
mDriverCrashGuard->NotifyCrashed();
1816
}
1817
1818
// Unregister all the BlobURLs registered by the ContentChild.
1819
for (uint32_t i = 0; i < mBlobURLs.Length(); ++i) {
1820
BlobURLProtocolHandler::RemoveDataEntry(mBlobURLs[i]);
1821
}
1822
1823
mBlobURLs.Clear();
1824
1825
#if defined(XP_WIN) && defined(ACCESSIBILITY)
1826
a11y::AccessibleWrap::ReleaseContentProcessIdFor(ChildID());
1827
#endif
1828
1829
nsTHashtable<nsRefPtrHashKey<BrowsingContextGroup>> groups;
1830
mGroups.SwapElements(groups);
1831
1832
for (auto iter = groups.Iter(); !iter.Done(); iter.Next()) {
1833
iter.Get()->GetKey()->Unsubscribe(this);
1834
}
1835
1836
MOZ_DIAGNOSTIC_ASSERT(mGroups.IsEmpty());
1837
}
1838
1839
void ContentParent::ActorDealloc() { mSelfRef = nullptr; }
1840
1841
bool ContentParent::TryToRecycle() {
1842
// This life time check should be replaced by a memory health check (memory
1843
// usage + fragmentation).
1844
const double kMaxLifeSpan = 5;
1845
if (mShutdownPending || mCalledKillHard || !IsAlive() ||
1846
!mRemoteType.EqualsLiteral(DEFAULT_REMOTE_TYPE) ||
1847
(TimeStamp::Now() - mActivateTS).ToSeconds() > kMaxLifeSpan ||
1848
!PreallocatedProcessManager::Provide(this)) {
1849
return false;
1850
}
1851
1852
// The PreallocatedProcessManager took over the ownership let's not keep a
1853
// reference to it, until we don't take it back.
1854
RemoveFromList();
1855
return true;
1856
}
1857
1858
bool ContentParent::ShouldKeepProcessAlive() {
1859
if (IsForJSPlugin()) {
1860
return true;
1861
}
1862
1863
// If we have active workers, we need to stay alive.
1864
{
1865
const auto lock = mRemoteWorkerActorData.Lock();
1866
if (lock->mCount) {
1867
return true;
1868
}
1869
}
1870
1871
if (!sBrowserContentParents) {
1872
return false;
1873
}
1874
1875
// If we have already been marked as dead, don't prevent shutdown.
1876
if (!IsAlive()) {
1877
return false;
1878
}
1879
1880
// Recording/replaying content parents cannot be reused and should not be
1881
// kept alive.
1882
if (this->IsRecordingOrReplaying()) {
1883
return false;
1884
}
1885
1886
auto contentParents = sBrowserContentParents->Get(mRemoteType);
1887
if (!contentParents) {
1888
return false;
1889
}
1890
1891
// We might want to keep some content processes alive for performance reasons.
1892
// e.g. test runs and privileged content process for some about: pages.
1893
// We don't want to alter behavior if the pref is not set, so default to 0.
1894
int32_t processesToKeepAlive = 0;
1895
1896
nsAutoCString keepAlivePref("dom.ipc.keepProcessesAlive.");
1897
1898
if (StringBeginsWith(mRemoteType,
1899
NS_LITERAL_STRING(FISSION_WEB_REMOTE_TYPE)) &&
1900
xpc::IsInAutomation()) {
1901
keepAlivePref.Append(FISSION_WEB_REMOTE_TYPE);
1902
keepAlivePref.AppendLiteral(".perOrigin");
1903
} else {
1904
keepAlivePref.Append(NS_ConvertUTF16toUTF8(mRemoteType));
1905
}
1906
if (NS_FAILED(
1907
Preferences::GetInt(keepAlivePref.get(), &processesToKeepAlive))) {
1908
return false;
1909
}
1910