Line data Source code
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 "TabParent.h"
14 :
15 : #if defined(ANDROID) || defined(LINUX)
16 : # include <sys/time.h>
17 : # include <sys/resource.h>
18 : #endif
19 :
20 : #include "chrome/common/process_watcher.h"
21 :
22 : #include "mozilla/a11y/PDocAccessible.h"
23 : #include "GeckoProfiler.h"
24 : #include "GMPServiceParent.h"
25 : #include "HandlerServiceParent.h"
26 : #include "IHistory.h"
27 : #include "imgIContainer.h"
28 : #if defined(XP_WIN) && defined(ACCESSIBILITY)
29 : #include "mozilla/a11y/AccessibleWrap.h"
30 : #include "mozilla/a11y/Compatibility.h"
31 : #endif
32 : #include "mozilla/BasePrincipal.h"
33 : #include "mozilla/ClearOnShutdown.h"
34 : #include "mozilla/StyleSheetInlines.h"
35 : #include "mozilla/DataStorage.h"
36 : #include "mozilla/devtools/HeapSnapshotTempFileHelperParent.h"
37 : #include "mozilla/docshell/OfflineCacheUpdateParent.h"
38 : #include "mozilla/dom/ClientManager.h"
39 : #include "mozilla/dom/ClientOpenWindowOpActors.h"
40 : #include "mozilla/dom/DataTransfer.h"
41 : #include "mozilla/dom/Element.h"
42 : #include "mozilla/dom/File.h"
43 : #include "mozilla/dom/FileCreatorHelper.h"
44 : #include "mozilla/dom/FileSystemSecurity.h"
45 : #include "mozilla/dom/IPCBlobUtils.h"
46 : #include "mozilla/dom/ExternalHelperAppParent.h"
47 : #include "mozilla/dom/GetFilesHelper.h"
48 : #include "mozilla/dom/GeolocationBinding.h"
49 : #include "mozilla/dom/MemoryReportRequest.h"
50 : #include "mozilla/dom/Notification.h"
51 : #include "mozilla/dom/PContentBridgeParent.h"
52 : #include "mozilla/dom/PContentPermissionRequestParent.h"
53 : #include "mozilla/dom/PCycleCollectWithLogsParent.h"
54 : #include "mozilla/dom/PositionError.h"
55 : #include "mozilla/dom/ServiceWorkerRegistrar.h"
56 : #include "mozilla/dom/power/PowerManagerService.h"
57 : #include "mozilla/dom/Permissions.h"
58 : #include "mozilla/dom/PresentationParent.h"
59 : #include "mozilla/dom/PPresentationParent.h"
60 : #include "mozilla/dom/PushNotifier.h"
61 : #include "mozilla/dom/quota/QuotaManagerService.h"
62 : #include "mozilla/dom/URLClassifierParent.h"
63 : #include "mozilla/embedding/printingui/PrintingParent.h"
64 : #include "mozilla/extensions/StreamFilterParent.h"
65 : #include "mozilla/gfx/gfxVars.h"
66 : #include "mozilla/gfx/GPUProcessManager.h"
67 : #include "mozilla/hal_sandbox/PHalParent.h"
68 : #include "mozilla/ipc/BackgroundChild.h"
69 : #include "mozilla/ipc/BackgroundParent.h"
70 : #include "mozilla/ipc/CrashReporterHost.h"
71 : #include "mozilla/ipc/FileDescriptorUtils.h"
72 : #include "mozilla/ipc/PChildToParentStreamParent.h"
73 : #include "mozilla/ipc/TestShellParent.h"
74 : #include "mozilla/ipc/IPCStreamUtils.h"
75 : #include "mozilla/intl/LocaleService.h"
76 : #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
77 : #include "mozilla/layers/PAPZParent.h"
78 : #include "mozilla/layers/CompositorThread.h"
79 : #include "mozilla/layers/ImageBridgeParent.h"
80 : #include "mozilla/layers/LayerTreeOwnerTracker.h"
81 : #include "mozilla/layout/RenderFrameParent.h"
82 : #include "mozilla/loader/ScriptCacheActors.h"
83 : #include "mozilla/LoginReputationIPC.h"
84 : #include "mozilla/LookAndFeel.h"
85 : #include "mozilla/media/MediaParent.h"
86 : #include "mozilla/Move.h"
87 : #include "mozilla/net/NeckoParent.h"
88 : #include "mozilla/net/CookieServiceParent.h"
89 : #include "mozilla/net/PCookieServiceParent.h"
90 : #include "mozilla/plugins/PluginBridge.h"
91 : #include "mozilla/Preferences.h"
92 : #include "mozilla/ProcessHangMonitor.h"
93 : #include "mozilla/ProcessHangMonitorIPC.h"
94 : #include "mozilla/Scheduler.h"
95 : #include "mozilla/ScopeExit.h"
96 : #include "mozilla/ScriptPreloader.h"
97 : #include "mozilla/Services.h"
98 : #include "mozilla/StaticPtr.h"
99 : #include "mozilla/Telemetry.h"
100 : #include "mozilla/TelemetryIPC.h"
101 : #include "mozilla/WebBrowserPersistDocumentParent.h"
102 : #include "mozilla/widget/ScreenManager.h"
103 : #include "mozilla/Unused.h"
104 : #include "mozilla/HangDetails.h"
105 : #include "nsAnonymousTemporaryFile.h"
106 : #include "nsAppRunner.h"
107 : #include "nsCDefaultURIFixup.h"
108 : #include "nsCExternalHandlerService.h"
109 : #include "nsCOMPtr.h"
110 : #include "nsChromeRegistryChrome.h"
111 : #include "nsConsoleMessage.h"
112 : #include "nsConsoleService.h"
113 : #include "nsContentUtils.h"
114 : #include "nsDebugImpl.h"
115 : #include "nsFrameLoader.h"
116 : #include "nsFrameMessageManager.h"
117 : #include "nsHashPropertyBag.h"
118 : #include "nsIAlertsService.h"
119 : #include "nsIClipboard.h"
120 : #include "nsICookie.h"
121 : #include "nsContentPermissionHelper.h"
122 : #include "nsIContentProcess.h"
123 : #include "nsICycleCollectorListener.h"
124 : #include "nsIDocShellTreeOwner.h"
125 : #include "nsIDocument.h"
126 : #include "nsGeolocation.h"
127 : #include "nsIDragService.h"
128 : #include "mozilla/dom/WakeLock.h"
129 : #include "nsIDOMWindow.h"
130 : #include "nsIExternalProtocolService.h"
131 : #include "nsIFormProcessor.h"
132 : #include "nsIGfxInfo.h"
133 : #include "nsIIdleService.h"
134 : #include "nsIInterfaceRequestorUtils.h"
135 : #include "nsIMemoryInfoDumper.h"
136 : #include "nsIMemoryReporter.h"
137 : #include "nsIMozBrowserFrame.h"
138 : #include "nsIMutable.h"
139 : #include "nsIObserverService.h"
140 : #include "nsIParentChannel.h"
141 : #include "nsIPresShell.h"
142 : #include "nsIRemoteWindowContext.h"
143 : #include "nsIScriptError.h"
144 : #include "nsIScriptSecurityManager.h"
145 : #include "nsISiteSecurityService.h"
146 : #include "nsISound.h"
147 : #include "nsISpellChecker.h"
148 : #include "nsISupportsPrimitives.h"
149 : #include "nsITimer.h"
150 : #include "nsIURIFixup.h"
151 : #include "nsIURL.h"
152 : #include "nsIDocShellTreeOwner.h"
153 : #include "nsIXULWindow.h"
154 : #include "nsIDOMChromeWindow.h"
155 : #include "nsIWindowWatcher.h"
156 : #include "nsPIWindowWatcher.h"
157 : #include "nsThread.h"
158 : #include "nsWindowWatcher.h"
159 : #include "nsIXULRuntime.h"
160 : #include "mozilla/dom/ParentProcessMessageManager.h"
161 : #include "mozilla/dom/ProcessMessageManager.h"
162 : #include "mozilla/dom/nsMixedContentBlocker.h"
163 : #include "nsMemoryInfoDumper.h"
164 : #include "nsMemoryReporterManager.h"
165 : #include "nsScriptError.h"
166 : #include "nsServiceManagerUtils.h"
167 : #include "nsStyleSheetService.h"
168 : #include "nsThreadUtils.h"
169 : #include "nsToolkitCompsCID.h"
170 : #include "nsWidgetsCID.h"
171 : #include "PreallocatedProcessManager.h"
172 : #include "ProcessPriorityManager.h"
173 : #include "SandboxHal.h"
174 : #include "SourceSurfaceRawData.h"
175 : #include "TabParent.h"
176 : #include "URIUtils.h"
177 : #include "nsIWebBrowserChrome.h"
178 : #include "nsIDocShell.h"
179 : #include "nsDocShell.h"
180 : #include "nsOpenURIInFrameParams.h"
181 : #include "mozilla/net/NeckoMessageUtils.h"
182 : #include "gfxPlatform.h"
183 : #include "gfxPrefs.h"
184 : #include "prio.h"
185 : #include "private/pprio.h"
186 : #include "ContentProcessManager.h"
187 : #include "mozilla/dom/BlobURLProtocolHandler.h"
188 : #include "mozilla/dom/ipc/StructuredCloneData.h"
189 : #include "mozilla/PerformanceUtils.h"
190 : #include "mozilla/psm/PSMContentListener.h"
191 : #include "nsPluginHost.h"
192 : #include "nsPluginTags.h"
193 : #include "nsIBlocklistService.h"
194 : #include "mozilla/StyleSheet.h"
195 : #include "mozilla/StyleSheetInlines.h"
196 : #include "nsICaptivePortalService.h"
197 : #include "nsIObjectLoadingContent.h"
198 : #include "nsIBidiKeyboard.h"
199 : #include "nsLayoutStylesheetCache.h"
200 :
201 : #include "mozilla/Sprintf.h"
202 :
203 : #ifdef MOZ_WEBRTC
204 : #include "signaling/src/peerconnection/WebrtcGlobalParent.h"
205 : #endif
206 :
207 : #if defined(ANDROID) || defined(LINUX)
208 : #include "nsSystemInfo.h"
209 : #endif
210 :
211 : #if defined(XP_LINUX)
212 : #include "mozilla/Hal.h"
213 : #endif
214 :
215 : #ifdef ANDROID
216 : # include "gfxAndroidPlatform.h"
217 : #endif
218 :
219 : # include "nsPermissionManager.h"
220 :
221 : #ifdef MOZ_WIDGET_ANDROID
222 : # include "AndroidBridge.h"
223 : #endif
224 :
225 : #ifdef MOZ_WIDGET_GTK
226 : #include <gdk/gdk.h>
227 : #endif
228 :
229 : #include "mozilla/RemoteSpellCheckEngineParent.h"
230 :
231 : #include "Crypto.h"
232 :
233 : #ifdef MOZ_WEBSPEECH
234 : #include "mozilla/dom/SpeechSynthesisParent.h"
235 : #endif
236 :
237 : #if defined(MOZ_CONTENT_SANDBOX)
238 : #include "mozilla/SandboxSettings.h"
239 : #if defined(XP_LINUX)
240 : #include "mozilla/SandboxInfo.h"
241 : #include "mozilla/SandboxBroker.h"
242 : #include "mozilla/SandboxBrokerPolicyFactory.h"
243 : #endif
244 : #endif
245 :
246 : #ifdef MOZ_TOOLKIT_SEARCH
247 : #include "nsIBrowserSearchService.h"
248 : #endif
249 :
250 : #ifdef XP_WIN
251 : #include "mozilla/audio/AudioNotificationSender.h"
252 : #include "mozilla/widget/AudioSession.h"
253 : #endif
254 :
255 : #ifdef ACCESSIBILITY
256 : #include "nsAccessibilityService.h"
257 : #endif
258 :
259 : #ifdef MOZ_GECKO_PROFILER
260 : #include "nsIProfiler.h"
261 : #include "ProfilerParent.h"
262 : #endif
263 :
264 : #ifdef MOZ_CODE_COVERAGE
265 : #include "mozilla/CodeCoverageHandler.h"
266 : #endif
267 :
268 : // For VP9Benchmark::sBenchmarkFpsPref
269 : #include "Benchmark.h"
270 :
271 : static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
272 :
273 : using base::KillProcess;
274 :
275 : using namespace CrashReporter;
276 : using namespace mozilla::dom::power;
277 : using namespace mozilla::media;
278 : using namespace mozilla::embedding;
279 : using namespace mozilla::gfx;
280 : using namespace mozilla::gmp;
281 : using namespace mozilla::hal;
282 : using namespace mozilla::ipc;
283 : using namespace mozilla::intl;
284 : using namespace mozilla::layers;
285 : using namespace mozilla::layout;
286 : using namespace mozilla::net;
287 : using namespace mozilla::jsipc;
288 : using namespace mozilla::psm;
289 : using namespace mozilla::widget;
290 : using mozilla::loader::PScriptCacheParent;
291 : using mozilla::Telemetry::ProcessID;
292 :
293 : // XXX Workaround for bug 986973 to maintain the existing broken semantics
294 : template<>
295 : struct nsIConsoleService::COMTypeInfo<nsConsoleService, void> {
296 : static const nsIID kIID;
297 : };
298 : const nsIID nsIConsoleService::COMTypeInfo<nsConsoleService, void>::kIID = NS_ICONSOLESERVICE_IID;
299 :
300 : namespace mozilla {
301 : namespace CubebUtils {
302 : extern FileDescriptor CreateAudioIPCConnection();
303 : }
304 :
305 : namespace dom {
306 :
307 : #define NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC "ipc:network:set-offline"
308 : #define NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC "ipc:network:set-connectivity"
309 :
310 : // IPC receiver for remote GC/CC logging.
311 : class CycleCollectWithLogsParent final : public PCycleCollectWithLogsParent
312 : {
313 : public:
314 0 : ~CycleCollectWithLogsParent()
315 0 : {
316 0 : MOZ_COUNT_DTOR(CycleCollectWithLogsParent);
317 0 : }
318 :
319 0 : static bool AllocAndSendConstructor(ContentParent* aManager,
320 : bool aDumpAllTraces,
321 : nsICycleCollectorLogSink* aSink,
322 : nsIDumpGCAndCCLogsCallback* aCallback)
323 : {
324 : CycleCollectWithLogsParent *actor;
325 : FILE* gcLog;
326 : FILE* ccLog;
327 : nsresult rv;
328 :
329 0 : actor = new CycleCollectWithLogsParent(aSink, aCallback);
330 0 : rv = actor->mSink->Open(&gcLog, &ccLog);
331 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
332 0 : delete actor;
333 : return false;
334 : }
335 :
336 : return aManager->
337 0 : SendPCycleCollectWithLogsConstructor(actor,
338 : aDumpAllTraces,
339 0 : FILEToFileDescriptor(gcLog),
340 0 : FILEToFileDescriptor(ccLog));
341 : }
342 :
343 : private:
344 0 : virtual mozilla::ipc::IPCResult RecvCloseGCLog() override
345 : {
346 0 : Unused << mSink->CloseGCLog();
347 0 : return IPC_OK();
348 : }
349 :
350 0 : virtual mozilla::ipc::IPCResult RecvCloseCCLog() override
351 : {
352 0 : Unused << mSink->CloseCCLog();
353 0 : return IPC_OK();
354 : }
355 :
356 0 : virtual mozilla::ipc::IPCResult Recv__delete__() override
357 : {
358 : // Report completion to mCallback only on successful
359 : // completion of the protocol.
360 0 : nsCOMPtr<nsIFile> gcLog, ccLog;
361 0 : mSink->GetGcLog(getter_AddRefs(gcLog));
362 0 : mSink->GetCcLog(getter_AddRefs(ccLog));
363 0 : Unused << mCallback->OnDump(gcLog, ccLog, /* parent = */ false);
364 0 : return IPC_OK();
365 : }
366 :
367 0 : virtual void ActorDestroy(ActorDestroyReason aReason) override
368 : {
369 : // If the actor is unexpectedly destroyed, we deliberately
370 : // don't call Close[GC]CLog on the sink, because the logs may
371 : // be incomplete. See also the nsCycleCollectorLogSinkToFile
372 : // implementaiton of those methods, and its destructor.
373 0 : }
374 :
375 0 : CycleCollectWithLogsParent(nsICycleCollectorLogSink *aSink,
376 : nsIDumpGCAndCCLogsCallback *aCallback)
377 0 : : mSink(aSink), mCallback(aCallback)
378 : {
379 0 : MOZ_COUNT_CTOR(CycleCollectWithLogsParent);
380 0 : }
381 :
382 : nsCOMPtr<nsICycleCollectorLogSink> mSink;
383 : nsCOMPtr<nsIDumpGCAndCCLogsCallback> mCallback;
384 : };
385 :
386 : // A memory reporter for ContentParent objects themselves.
387 0 : class ContentParentsMemoryReporter final : public nsIMemoryReporter
388 : {
389 0 : ~ContentParentsMemoryReporter() {}
390 : public:
391 : NS_DECL_ISUPPORTS
392 : NS_DECL_NSIMEMORYREPORTER
393 : };
394 :
395 0 : NS_IMPL_ISUPPORTS(ContentParentsMemoryReporter, nsIMemoryReporter)
396 :
397 : NS_IMETHODIMP
398 0 : ContentParentsMemoryReporter::CollectReports(
399 : nsIHandleReportCallback* aHandleReport,
400 : nsISupports* aData,
401 : bool aAnonymize)
402 : {
403 0 : AutoTArray<ContentParent*, 16> cps;
404 0 : ContentParent::GetAllEvenIfDead(cps);
405 :
406 0 : for (uint32_t i = 0; i < cps.Length(); i++) {
407 0 : ContentParent* cp = cps[i];
408 0 : MessageChannel* channel = cp->GetIPCChannel();
409 :
410 0 : nsString friendlyName;
411 0 : cp->FriendlyName(friendlyName, aAnonymize);
412 :
413 0 : cp->AddRef();
414 0 : nsrefcnt refcnt = cp->Release();
415 :
416 0 : const char* channelStr = "no channel";
417 0 : uint32_t numQueuedMessages = 0;
418 0 : if (channel) {
419 0 : if (channel->Unsound_IsClosed()) {
420 : channelStr = "closed channel";
421 : } else {
422 0 : channelStr = "open channel";
423 : }
424 0 : numQueuedMessages = channel->Unsound_NumQueuedMessages();
425 : }
426 :
427 : nsPrintfCString path("queued-ipc-messages/content-parent"
428 : "(%s, pid=%d, %s, 0x%p, refcnt=%" PRIuPTR ")",
429 0 : NS_ConvertUTF16toUTF8(friendlyName).get(),
430 : cp->Pid(), channelStr,
431 0 : static_cast<nsIContentParent*>(cp), refcnt);
432 :
433 0 : NS_NAMED_LITERAL_CSTRING(desc,
434 : "The number of unset IPC messages held in this ContentParent's "
435 : "channel. A large value here might indicate that we're leaking "
436 : "messages. Similarly, a ContentParent object for a process that's no "
437 : "longer running could indicate that we're leaking ContentParents.");
438 :
439 0 : aHandleReport->Callback(/* process */ EmptyCString(), path,
440 : KIND_OTHER, UNITS_COUNT,
441 0 : numQueuedMessages, desc, aData);
442 : }
443 :
444 0 : return NS_OK;
445 : }
446 :
447 : nsClassHashtable<nsStringHashKey, nsTArray<ContentParent*>>* ContentParent::sBrowserContentParents;
448 :
449 : namespace {
450 :
451 : class ScriptableCPInfo final : public nsIContentProcessInfo
452 : {
453 : public:
454 0 : explicit ScriptableCPInfo(ContentParent* aParent)
455 0 : : mContentParent(aParent)
456 : {
457 0 : MOZ_ASSERT(mContentParent);
458 0 : }
459 :
460 : NS_DECL_ISUPPORTS
461 : NS_DECL_NSICONTENTPROCESSINFO
462 :
463 : void ProcessDied()
464 : {
465 0 : mContentParent = nullptr;
466 : }
467 :
468 : private:
469 0 : ~ScriptableCPInfo()
470 0 : {
471 0 : MOZ_ASSERT(!mContentParent, "must call ProcessDied");
472 0 : }
473 :
474 : ContentParent* mContentParent;
475 : };
476 :
477 0 : NS_IMPL_ISUPPORTS(ScriptableCPInfo, nsIContentProcessInfo)
478 :
479 : NS_IMETHODIMP
480 0 : ScriptableCPInfo::GetIsAlive(bool* aIsAlive)
481 : {
482 0 : *aIsAlive = mContentParent != nullptr;
483 0 : return NS_OK;
484 : }
485 :
486 : NS_IMETHODIMP
487 0 : ScriptableCPInfo::GetProcessId(int32_t* aPID)
488 : {
489 0 : if (!mContentParent) {
490 0 : *aPID = -1;
491 0 : return NS_ERROR_NOT_INITIALIZED;
492 : }
493 :
494 0 : *aPID = mContentParent->Pid();
495 0 : if (*aPID == -1) {
496 : return NS_ERROR_FAILURE;
497 : }
498 :
499 0 : return NS_OK;
500 : }
501 :
502 : NS_IMETHODIMP
503 0 : ScriptableCPInfo::GetOpener(nsIContentProcessInfo** aInfo)
504 : {
505 0 : *aInfo = nullptr;
506 0 : if (!mContentParent) {
507 : return NS_ERROR_NOT_INITIALIZED;
508 : }
509 :
510 0 : if (ContentParent* opener = mContentParent->Opener()) {
511 0 : nsCOMPtr<nsIContentProcessInfo> info = opener->ScriptableHelper();
512 0 : info.forget(aInfo);
513 : }
514 : return NS_OK;
515 : }
516 :
517 : NS_IMETHODIMP
518 0 : ScriptableCPInfo::GetTabCount(int32_t* aTabCount)
519 : {
520 0 : if (!mContentParent) {
521 : return NS_ERROR_NOT_INITIALIZED;
522 : }
523 :
524 0 : ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
525 0 : *aTabCount = cpm->GetTabParentCountByProcessId(mContentParent->ChildID());
526 :
527 0 : return NS_OK;
528 : }
529 :
530 : NS_IMETHODIMP
531 0 : ScriptableCPInfo::GetMessageManager(nsISupports** aMessenger)
532 : {
533 0 : *aMessenger = nullptr;
534 0 : if (!mContentParent) {
535 : return NS_ERROR_NOT_INITIALIZED;
536 : }
537 :
538 0 : RefPtr<ProcessMessageManager> manager = mContentParent->GetMessageManager();
539 0 : manager.forget(aMessenger);
540 : return NS_OK;
541 : }
542 :
543 : ProcessID
544 0 : GetTelemetryProcessID(const nsAString& remoteType)
545 : {
546 : // OOP WebExtensions run in a content process.
547 : // For Telemetry though we want to break out collected data from the WebExtensions process into
548 : // a separate bucket, to make sure we can analyze it separately and avoid skewing normal content
549 : // process metrics.
550 0 : return remoteType.EqualsLiteral(EXTENSION_REMOTE_TYPE) ? ProcessID::Extension : ProcessID::Content;
551 : }
552 :
553 : } // anonymous namespace
554 :
555 : nsDataHashtable<nsUint32HashKey, ContentParent*>* ContentParent::sJSPluginContentParents;
556 : nsTArray<ContentParent*>* ContentParent::sPrivateContent;
557 0 : StaticAutoPtr<LinkedList<ContentParent> > ContentParent::sContentParents;
558 : #if defined(XP_LINUX) && defined(MOZ_CONTENT_SANDBOX)
559 : UniquePtr<SandboxBrokerPolicyFactory> ContentParent::sSandboxBrokerPolicyFactory;
560 : #endif
561 : uint64_t ContentParent::sNextTabParentId = 0;
562 0 : nsDataHashtable<nsUint64HashKey, TabParent*> ContentParent::sNextTabParents;
563 :
564 : // This is true when subprocess launching is enabled. This is the
565 : // case between StartUp() and ShutDown().
566 : static bool sCanLaunchSubprocesses;
567 :
568 : // Set to true if the DISABLE_UNSAFE_CPOW_WARNINGS environment variable is
569 : // set.
570 : static bool sDisableUnsafeCPOWWarnings = false;
571 :
572 : // The first content child has ID 1, so the chrome process can have ID 0.
573 : static uint64_t gContentChildID = 1;
574 :
575 : static const char* sObserverTopics[] = {
576 : "xpcom-shutdown",
577 : "profile-before-change",
578 : NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC,
579 : NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC,
580 : NS_IPC_CAPTIVE_PORTAL_SET_STATE,
581 : "memory-pressure",
582 : "child-gc-request",
583 : "child-cc-request",
584 : "child-mmu-request",
585 : "child-ghost-request",
586 : "last-pb-context-exited",
587 : "file-watcher-update",
588 : #ifdef ACCESSIBILITY
589 : "a11y-init-or-shutdown",
590 : #endif
591 : "cacheservice:empty-cache",
592 : "intl:app-locales-changed",
593 : "intl:requested-locales-changed",
594 : "cookie-changed",
595 : "private-cookie-changed",
596 : };
597 :
598 : // PreallocateProcess is called by the PreallocatedProcessManager.
599 : // ContentParent then takes this process back within GetNewOrUsedBrowserProcess.
600 : /*static*/ already_AddRefed<ContentParent>
601 0 : ContentParent::PreallocateProcess()
602 : {
603 : RefPtr<ContentParent> process =
604 : new ContentParent(/* aOpener = */ nullptr,
605 0 : NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE));
606 :
607 0 : PreallocatedProcessManager::AddBlocker(process);
608 :
609 0 : if (!process->LaunchSubprocess(PROCESS_PRIORITY_PREALLOC)) {
610 : return nullptr;
611 : }
612 :
613 : return process.forget();
614 : }
615 :
616 : /*static*/ void
617 0 : ContentParent::StartUp()
618 : {
619 : // We could launch sub processes from content process
620 : // FIXME Bug 1023701 - Stop using ContentParent static methods in
621 : // child process
622 0 : sCanLaunchSubprocesses = true;
623 :
624 0 : if (!XRE_IsParentProcess()) {
625 : return;
626 : }
627 :
628 : // Note: This reporter measures all ContentParents.
629 0 : RegisterStrongMemoryReporter(new ContentParentsMemoryReporter());
630 :
631 0 : BackgroundChild::Startup();
632 0 : ClientManager::Startup();
633 :
634 0 : sDisableUnsafeCPOWWarnings = PR_GetEnv("DISABLE_UNSAFE_CPOW_WARNINGS");
635 :
636 : #if defined(XP_LINUX) && defined(MOZ_CONTENT_SANDBOX)
637 : sSandboxBrokerPolicyFactory = MakeUnique<SandboxBrokerPolicyFactory>();
638 : #endif
639 : }
640 :
641 : /*static*/ void
642 0 : ContentParent::ShutDown()
643 : {
644 : // No-op for now. We rely on normal process shutdown and
645 : // ClearOnShutdown() to clean up our state.
646 0 : sCanLaunchSubprocesses = false;
647 :
648 : #if defined(XP_LINUX) && defined(MOZ_CONTENT_SANDBOX)
649 : sSandboxBrokerPolicyFactory = nullptr;
650 : #endif
651 0 : }
652 :
653 : /*static*/ uint32_t
654 0 : ContentParent::GetPoolSize(const nsAString& aContentProcessType)
655 : {
656 0 : if (!sBrowserContentParents) {
657 : return 0;
658 : }
659 :
660 : nsTArray<ContentParent*>* parents =
661 0 : sBrowserContentParents->Get(aContentProcessType);
662 :
663 0 : return parents ? parents->Length() : 0;
664 : }
665 :
666 :
667 : /*static*/ nsTArray<ContentParent*>&
668 0 : ContentParent::GetOrCreatePool(const nsAString& aContentProcessType)
669 : {
670 0 : if (!sBrowserContentParents) {
671 0 : sBrowserContentParents =
672 0 : new nsClassHashtable<nsStringHashKey, nsTArray<ContentParent*>>;
673 : }
674 :
675 0 : return *sBrowserContentParents->LookupOrAdd(aContentProcessType);
676 : }
677 :
678 : /*static*/ uint32_t
679 0 : ContentParent::GetMaxProcessCount(const nsAString& aContentProcessType)
680 : {
681 0 : if (aContentProcessType.EqualsLiteral("web")) {
682 0 : return GetMaxWebProcessCount();
683 : }
684 :
685 0 : nsAutoCString processCountPref("dom.ipc.processCount.");
686 0 : processCountPref.Append(NS_ConvertUTF16toUTF8(aContentProcessType));
687 :
688 : int32_t maxContentParents;
689 0 : if (NS_FAILED(Preferences::GetInt(processCountPref.get(), &maxContentParents))) {
690 0 : maxContentParents = Preferences::GetInt("dom.ipc.processCount", 1);
691 : }
692 :
693 0 : if (maxContentParents < 1) {
694 0 : maxContentParents = 1;
695 : }
696 :
697 0 : return static_cast<uint32_t>(maxContentParents);
698 : }
699 :
700 : /*static*/ bool
701 0 : ContentParent::IsMaxProcessCountReached(const nsAString& aContentProcessType)
702 : {
703 0 : return GetPoolSize(aContentProcessType) >= GetMaxProcessCount(aContentProcessType);
704 : }
705 :
706 : /*static*/ void
707 0 : ContentParent::ReleaseCachedProcesses()
708 : {
709 0 : if (!GetPoolSize(NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE))) {
710 0 : return;
711 : }
712 :
713 : // We might want to extend this for other process types as well in the future...
714 0 : nsTArray<ContentParent*>& contentParents = GetOrCreatePool(NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE));
715 0 : ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
716 0 : nsTArray<ContentParent*> toRelease;
717 :
718 : // Shuting down these processes will change the array so let's use another array for the removal.
719 0 : for (auto* cp : contentParents) {
720 0 : nsTArray<TabId> tabIds = cpm->GetTabParentsByProcessId(cp->mChildID);
721 0 : if (!tabIds.Length()) {
722 0 : toRelease.AppendElement(cp);
723 : }
724 : }
725 :
726 0 : for (auto* cp : toRelease) {
727 : // Start a soft shutdown.
728 0 : cp->ShutDownProcess(SEND_SHUTDOWN_MESSAGE);
729 : // Make sure we don't select this process for new tabs.
730 0 : cp->MarkAsDead();
731 : // Make sure that this process is no longer accessible from JS by its message manager.
732 0 : cp->ShutDownMessageManager();
733 : }
734 : }
735 :
736 : /*static*/ already_AddRefed<ContentParent>
737 0 : ContentParent::MinTabSelect(const nsTArray<ContentParent*>& aContentParents,
738 : ContentParent* aOpener, int32_t aMaxContentParents)
739 : {
740 0 : uint32_t maxSelectable = std::min(static_cast<uint32_t>(aContentParents.Length()),
741 0 : static_cast<uint32_t>(aMaxContentParents));
742 0 : uint32_t min = INT_MAX;
743 0 : RefPtr<ContentParent> candidate;
744 0 : ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
745 :
746 0 : for (uint32_t i = 0; i < maxSelectable; i++) {
747 0 : ContentParent* p = aContentParents[i];
748 0 : NS_ASSERTION(p->IsAlive(), "Non-alive contentparent in sBrowserContentParents?");
749 0 : if (p->mOpener == aOpener) {
750 0 : uint32_t tabCount = cpm->GetTabParentCountByProcessId(p->ChildID());
751 0 : if (tabCount < min) {
752 0 : candidate = p;
753 0 : min = tabCount;
754 : }
755 : }
756 : }
757 :
758 0 : return candidate.forget();
759 : }
760 :
761 : /*static*/ already_AddRefed<ContentParent>
762 0 : ContentParent::GetNewOrUsedBrowserProcess(const nsAString& aRemoteType,
763 : ProcessPriority aPriority,
764 : ContentParent* aOpener,
765 : bool aPreferUsed)
766 : {
767 0 : nsTArray<ContentParent*>& contentParents = GetOrCreatePool(aRemoteType);
768 0 : uint32_t maxContentParents = GetMaxProcessCount(aRemoteType);
769 0 : if (aRemoteType.EqualsLiteral(LARGE_ALLOCATION_REMOTE_TYPE)) {
770 : // We never want to re-use Large-Allocation processes.
771 0 : if (contentParents.Length() >= maxContentParents) {
772 0 : return GetNewOrUsedBrowserProcess(NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE),
773 : aPriority,
774 0 : aOpener);
775 : }
776 : } else {
777 0 : uint32_t numberOfParents = contentParents.Length();
778 0 : nsTArray<nsIContentProcessInfo*> infos(numberOfParents);
779 0 : for (auto* cp : contentParents) {
780 0 : infos.AppendElement(cp->mScriptableHelper);
781 : }
782 :
783 0 : if (aPreferUsed && numberOfParents) {
784 : // For the preloaded browser we don't want to create a new process but reuse an
785 : // existing one.
786 0 : maxContentParents = numberOfParents;
787 : }
788 :
789 : nsCOMPtr<nsIContentProcessProvider> cpp =
790 0 : do_GetService("@mozilla.org/ipc/processselector;1");
791 0 : nsIContentProcessInfo* openerInfo = aOpener ? aOpener->mScriptableHelper.get() : nullptr;
792 : int32_t index;
793 0 : if (cpp &&
794 0 : NS_SUCCEEDED(cpp->ProvideProcess(aRemoteType, openerInfo,
795 : infos.Elements(), infos.Length(),
796 : maxContentParents, &index))) {
797 : // If the provider returned an existing ContentParent, use that one.
798 0 : if (0 <= index && static_cast<uint32_t>(index) <= maxContentParents) {
799 0 : RefPtr<ContentParent> retval = contentParents[index];
800 0 : return retval.forget();
801 : }
802 : } else {
803 : // If there was a problem with the JS chooser, fall back to a random
804 : // selection.
805 0 : NS_WARNING("nsIContentProcessProvider failed to return a process");
806 0 : RefPtr<ContentParent> random;
807 0 : if (contentParents.Length() >= maxContentParents &&
808 0 : (random = MinTabSelect(contentParents, aOpener, maxContentParents))) {
809 0 : return random.forget();
810 : }
811 : }
812 :
813 : // Try to take the preallocated process only for the default process type.
814 : // The preallocated process manager might not had the chance yet to release the process
815 : // after a very recent ShutDownProcess, let's make sure we don't try to reuse a process
816 : // that is being shut down.
817 0 : RefPtr<ContentParent> p;
818 0 : if (aRemoteType.EqualsLiteral(DEFAULT_REMOTE_TYPE) &&
819 0 : (p = PreallocatedProcessManager::Take()) &&
820 0 : !p->mShutdownPending) {
821 : // For pre-allocated process we have not set the opener yet.
822 0 : p->mOpener = aOpener;
823 0 : contentParents.AppendElement(p);
824 0 : p->mActivateTS = TimeStamp::Now();
825 0 : return p.forget();
826 : }
827 : }
828 :
829 : // Create a new process from scratch.
830 0 : RefPtr<ContentParent> p = new ContentParent(aOpener, aRemoteType);
831 :
832 : // Until the new process is ready let's not allow to start up any preallocated processes.
833 0 : PreallocatedProcessManager::AddBlocker(p);
834 :
835 0 : if (!p->LaunchSubprocess(aPriority)) {
836 : return nullptr;
837 : }
838 :
839 0 : contentParents.AppendElement(p);
840 0 : p->mActivateTS = TimeStamp::Now();
841 : return p.forget();
842 : }
843 :
844 : /*static*/ already_AddRefed<ContentParent>
845 0 : ContentParent::GetNewOrUsedJSPluginProcess(uint32_t aPluginID,
846 : const hal::ProcessPriority& aPriority)
847 : {
848 0 : RefPtr<ContentParent> p;
849 0 : if (sJSPluginContentParents) {
850 0 : p = sJSPluginContentParents->Get(aPluginID);
851 : } else {
852 0 : sJSPluginContentParents =
853 0 : new nsDataHashtable<nsUint32HashKey, ContentParent*>();
854 : }
855 :
856 0 : if (p) {
857 : return p.forget();
858 : }
859 :
860 0 : p = new ContentParent(aPluginID);
861 :
862 0 : if (!p->LaunchSubprocess(aPriority)) {
863 : return nullptr;
864 : }
865 :
866 0 : sJSPluginContentParents->Put(aPluginID, p);
867 :
868 : return p.forget();
869 : }
870 :
871 : /*static*/ ProcessPriority
872 0 : ContentParent::GetInitialProcessPriority(Element* aFrameElement)
873 : {
874 : // Frames with mozapptype == critical which are expecting a system message
875 : // get FOREGROUND_HIGH priority.
876 :
877 0 : if (!aFrameElement) {
878 : return PROCESS_PRIORITY_FOREGROUND;
879 : }
880 :
881 0 : nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(aFrameElement);
882 0 : if (!browserFrame) {
883 : return PROCESS_PRIORITY_FOREGROUND;
884 : }
885 :
886 : return PROCESS_PRIORITY_FOREGROUND;
887 : }
888 :
889 : #if defined(XP_WIN)
890 : extern const wchar_t* kPluginWidgetContentParentProperty;
891 :
892 : /*static*/ void
893 : ContentParent::SendAsyncUpdate(nsIWidget* aWidget)
894 : {
895 : if (!aWidget || aWidget->Destroyed()) {
896 : return;
897 : }
898 : // Fire off an async request to the plugin to paint its window
899 : HWND hwnd = (HWND)aWidget->GetNativeData(NS_NATIVE_WINDOW);
900 : NS_ASSERTION(hwnd, "Expected valid hwnd value.");
901 : ContentParent* cp = reinterpret_cast<ContentParent*>(
902 : ::GetPropW(hwnd, kPluginWidgetContentParentProperty));
903 : if (cp && !cp->IsDestroyed()) {
904 : Unused << cp->SendUpdateWindow((uintptr_t)hwnd);
905 : }
906 : }
907 : #endif // defined(XP_WIN)
908 :
909 : mozilla::ipc::IPCResult
910 0 : ContentParent::RecvCreateChildProcess(const IPCTabContext& aContext,
911 : const hal::ProcessPriority& aPriority,
912 : const TabId& aOpenerTabId,
913 : const TabId& aTabId,
914 : ContentParentId* aCpId,
915 : bool* aIsForBrowser)
916 : {
917 : #if 0
918 : if (!CanOpenBrowser(aContext)) {
919 : return false;
920 : }
921 : #endif
922 0 : RefPtr<ContentParent> cp;
923 0 : MaybeInvalidTabContext tc(aContext);
924 0 : if (!tc.IsValid()) {
925 0 : NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
926 : "the child process. (%s)",
927 : tc.GetInvalidReason()).get());
928 0 : return IPC_FAIL_NO_REASON(this);
929 : }
930 :
931 0 : if (tc.GetTabContext().IsJSPlugin()) {
932 0 : cp = GetNewOrUsedJSPluginProcess(tc.GetTabContext().JSPluginId(),
933 0 : aPriority);
934 : }
935 : else {
936 0 : cp = GetNewOrUsedBrowserProcess(NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE),
937 0 : aPriority, this);
938 : }
939 :
940 0 : if (!cp) {
941 0 : *aCpId = 0;
942 0 : *aIsForBrowser = false;
943 : return IPC_OK();
944 : }
945 :
946 0 : *aCpId = cp->ChildID();
947 0 : *aIsForBrowser = cp->IsForBrowser();
948 :
949 0 : ContentProcessManager *cpm = ContentProcessManager::GetSingleton();
950 0 : if (cp->IsForJSPlugin()) {
951 : // We group all the iframes for a specific JS plugin into one process, regardless of
952 : // origin. As a consequence that process can't be a child of the content process that
953 : // contains the document with the element loading the plugin. All content processes
954 : // need to be able to communicate with the process for the JS plugin.
955 0 : cpm->RegisterRemoteFrame(aTabId, ChildID(), aOpenerTabId, aContext, cp->ChildID());
956 : return IPC_OK();
957 : }
958 :
959 : // cp was already added to the ContentProcessManager, this just sets the parent ID.
960 0 : cpm->AddContentProcess(cp, this->ChildID());
961 :
962 0 : if (cpm->AddGrandchildProcess(this->ChildID(), cp->ChildID()) &&
963 0 : cpm->RegisterRemoteFrame(aTabId, ChildID(), aOpenerTabId, aContext, cp->ChildID())) {
964 : return IPC_OK();
965 : }
966 :
967 0 : return IPC_FAIL_NO_REASON(this);
968 : }
969 :
970 : mozilla::ipc::IPCResult
971 0 : ContentParent::RecvBridgeToChildProcess(const ContentParentId& aCpId,
972 : Endpoint<PContentBridgeParent>* aEndpoint)
973 : {
974 0 : ContentProcessManager *cpm = ContentProcessManager::GetSingleton();
975 0 : ContentParent* cp = cpm->GetContentProcessById(aCpId);
976 :
977 0 : if (cp && cp->CanCommunicateWith(ChildID())) {
978 0 : Endpoint<PContentBridgeParent> parent;
979 0 : Endpoint<PContentBridgeChild> child;
980 :
981 0 : if (NS_FAILED(PContentBridge::CreateEndpoints(OtherPid(), cp->OtherPid(),
982 : &parent, &child))) {
983 0 : return IPC_FAIL(this, "CreateEndpoints failed");
984 : }
985 :
986 0 : *aEndpoint = std::move(parent);
987 :
988 0 : if (!cp->SendInitContentBridgeChild(std::move(child))) {
989 0 : return IPC_FAIL(this, "SendInitContentBridgeChild failed");
990 : }
991 :
992 : return IPC_OK();
993 : }
994 :
995 : // You can't bridge to a process you didn't open!
996 0 : KillHard("BridgeToChildProcess");
997 0 : return IPC_FAIL_NO_REASON(this);
998 : }
999 :
1000 0 : static nsIDocShell* GetOpenerDocShellHelper(Element* aFrameElement)
1001 : {
1002 : // Propagate the private-browsing status of the element's parent
1003 : // docshell to the remote docshell, via the chrome flags.
1004 0 : nsCOMPtr<Element> frameElement = do_QueryInterface(aFrameElement);
1005 0 : MOZ_ASSERT(frameElement);
1006 0 : nsPIDOMWindowOuter* win = frameElement->OwnerDoc()->GetWindow();
1007 0 : if (!win) {
1008 0 : NS_WARNING("Remote frame has no window");
1009 0 : return nullptr;
1010 : }
1011 0 : nsIDocShell* docShell = win->GetDocShell();
1012 0 : if (!docShell) {
1013 0 : NS_WARNING("Remote frame has no docshell");
1014 0 : return nullptr;
1015 : }
1016 :
1017 : return docShell;
1018 : }
1019 :
1020 : mozilla::ipc::IPCResult
1021 0 : ContentParent::RecvCreateGMPService()
1022 : {
1023 0 : Endpoint<PGMPServiceParent> parent;
1024 0 : Endpoint<PGMPServiceChild> child;
1025 :
1026 : nsresult rv;
1027 0 : rv = PGMPService::CreateEndpoints(base::GetCurrentProcId(),
1028 : OtherPid(),
1029 0 : &parent, &child);
1030 0 : if (NS_FAILED(rv)) {
1031 0 : MOZ_ASSERT(false, "CreateEndpoints failed");
1032 : return IPC_FAIL_NO_REASON(this);
1033 : }
1034 :
1035 0 : if (!GMPServiceParent::Create(std::move(parent))) {
1036 0 : MOZ_ASSERT(false, "GMPServiceParent::Create failed");
1037 : return IPC_FAIL_NO_REASON(this);
1038 : }
1039 :
1040 0 : if (!SendInitGMPService(std::move(child))) {
1041 0 : MOZ_ASSERT(false, "SendInitGMPService failed");
1042 : return IPC_FAIL_NO_REASON(this);
1043 : }
1044 :
1045 : return IPC_OK();
1046 : }
1047 :
1048 : mozilla::ipc::IPCResult
1049 0 : ContentParent::RecvLoadPlugin(const uint32_t& aPluginId,
1050 : nsresult* aRv,
1051 : uint32_t* aRunID,
1052 : Endpoint<PPluginModuleParent>* aEndpoint)
1053 : {
1054 0 : *aRv = NS_OK;
1055 0 : if (!mozilla::plugins::SetupBridge(aPluginId, this, aRv, aRunID, aEndpoint)) {
1056 0 : return IPC_FAIL_NO_REASON(this);
1057 : }
1058 : return IPC_OK();
1059 : }
1060 :
1061 : mozilla::ipc::IPCResult
1062 0 : ContentParent::RecvUngrabPointer(const uint32_t& aTime)
1063 : {
1064 : #if !defined(MOZ_WIDGET_GTK)
1065 : MOZ_CRASH("This message only makes sense on GTK platforms");
1066 : #else
1067 0 : gdk_pointer_ungrab(aTime);
1068 0 : return IPC_OK();
1069 : #endif
1070 : }
1071 :
1072 : mozilla::ipc::IPCResult
1073 0 : ContentParent::RecvRemovePermission(const IPC::Principal& aPrincipal,
1074 : const nsCString& aPermissionType,
1075 : nsresult* aRv) {
1076 0 : *aRv = Permissions::RemovePermission(aPrincipal, aPermissionType.get());
1077 0 : return IPC_OK();
1078 : }
1079 :
1080 : mozilla::ipc::IPCResult
1081 0 : ContentParent::RecvConnectPluginBridge(const uint32_t& aPluginId,
1082 : nsresult* aRv,
1083 : Endpoint<PPluginModuleParent>* aEndpoint)
1084 : {
1085 0 : *aRv = NS_OK;
1086 : // We don't need to get the run ID for the plugin, since we already got it
1087 : // in the first call to SetupBridge in RecvLoadPlugin, so we pass in a dummy
1088 : // pointer and just throw it away.
1089 0 : uint32_t dummy = 0;
1090 0 : if (!mozilla::plugins::SetupBridge(aPluginId, this, aRv, &dummy, aEndpoint)) {
1091 0 : return IPC_FAIL(this, "SetupBridge failed");
1092 : }
1093 : return IPC_OK();
1094 : }
1095 :
1096 : /*static*/ TabParent*
1097 0 : ContentParent::CreateBrowser(const TabContext& aContext,
1098 : Element* aFrameElement,
1099 : ContentParent* aOpenerContentParent,
1100 : TabParent* aSameTabGroupAs,
1101 : uint64_t aNextTabParentId)
1102 : {
1103 0 : AUTO_PROFILER_LABEL("ContentParent::CreateBrowser", OTHER);
1104 :
1105 0 : if (!sCanLaunchSubprocesses) {
1106 : return nullptr;
1107 : }
1108 :
1109 0 : nsAutoString remoteType;
1110 0 : if (!aFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::RemoteType,
1111 : remoteType)) {
1112 0 : remoteType.AssignLiteral(DEFAULT_REMOTE_TYPE);
1113 : }
1114 :
1115 0 : if (aNextTabParentId) {
1116 0 : if (TabParent* parent =
1117 0 : sNextTabParents.GetAndRemove(aNextTabParentId).valueOr(nullptr)) {
1118 0 : MOZ_ASSERT(!parent->GetOwnerElement(),
1119 : "Shouldn't have an owner elemnt before");
1120 0 : parent->SetOwnerElement(aFrameElement);
1121 0 : return parent;
1122 : }
1123 : }
1124 :
1125 0 : ProcessPriority initialPriority = GetInitialProcessPriority(aFrameElement);
1126 0 : bool isInContentProcess = !XRE_IsParentProcess();
1127 0 : TabId tabId(nsContentUtils::GenerateTabId());
1128 :
1129 0 : nsIDocShell* docShell = GetOpenerDocShellHelper(aFrameElement);
1130 0 : TabId openerTabId;
1131 0 : if (docShell) {
1132 0 : openerTabId = TabParent::GetTabIdFrom(docShell);
1133 : }
1134 :
1135 0 : bool isPreloadBrowser = false;
1136 0 : nsAutoString isPreloadBrowserStr;
1137 0 : if (aFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::preloadedState,
1138 : isPreloadBrowserStr)) {
1139 0 : isPreloadBrowser = isPreloadBrowserStr.EqualsLiteral("preloaded");
1140 : }
1141 :
1142 0 : RefPtr<nsIContentParent> constructorSender;
1143 0 : if (isInContentProcess) {
1144 0 : MOZ_ASSERT(aContext.IsMozBrowserElement() || aContext.IsJSPlugin());
1145 0 : constructorSender = CreateContentBridgeParent(aContext, initialPriority,
1146 0 : openerTabId, tabId);
1147 : } else {
1148 0 : if (aOpenerContentParent) {
1149 0 : constructorSender = aOpenerContentParent;
1150 : } else {
1151 0 : if (aContext.IsJSPlugin()) {
1152 : constructorSender =
1153 0 : GetNewOrUsedJSPluginProcess(aContext.JSPluginId(),
1154 0 : initialPriority);
1155 : } else {
1156 : constructorSender =
1157 0 : GetNewOrUsedBrowserProcess(remoteType, initialPriority,
1158 0 : nullptr, isPreloadBrowser);
1159 : }
1160 0 : if (!constructorSender) {
1161 : return nullptr;
1162 : }
1163 : }
1164 0 : ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
1165 : cpm->RegisterRemoteFrame(tabId,
1166 0 : ContentParentId(0),
1167 : openerTabId,
1168 0 : aContext.AsIPCTabContext(),
1169 0 : constructorSender->ChildID());
1170 : }
1171 0 : if (constructorSender) {
1172 0 : nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
1173 0 : docShell->GetTreeOwner(getter_AddRefs(treeOwner));
1174 0 : if (!treeOwner) {
1175 0 : return nullptr;
1176 : }
1177 :
1178 0 : nsCOMPtr<nsIWebBrowserChrome> wbc = do_GetInterface(treeOwner);
1179 0 : if (!wbc) {
1180 0 : return nullptr;
1181 : }
1182 0 : uint32_t chromeFlags = 0;
1183 0 : wbc->GetChromeFlags(&chromeFlags);
1184 :
1185 0 : nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
1186 0 : if (loadContext && loadContext->UsePrivateBrowsing()) {
1187 0 : chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
1188 : }
1189 0 : if (docShell->GetAffectPrivateSessionLifetime()) {
1190 0 : chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME;
1191 : }
1192 :
1193 0 : if (tabId == 0) {
1194 0 : return nullptr;
1195 : }
1196 : RefPtr<TabParent> tp(new TabParent(constructorSender, tabId,
1197 0 : aContext, chromeFlags));
1198 0 : tp->SetInitedByParent();
1199 :
1200 : PBrowserParent* browser =
1201 0 : constructorSender->SendPBrowserConstructor(
1202 : // DeallocPBrowserParent() releases this ref.
1203 0 : tp.forget().take(), tabId,
1204 0 : aSameTabGroupAs ? aSameTabGroupAs->GetTabId() : TabId(0),
1205 0 : aContext.AsIPCTabContext(),
1206 : chromeFlags,
1207 0 : constructorSender->ChildID(),
1208 0 : constructorSender->IsForBrowser());
1209 :
1210 0 : if (remoteType.EqualsLiteral(LARGE_ALLOCATION_REMOTE_TYPE)) {
1211 : // Tell the TabChild object that it was created due to a Large-Allocation
1212 : // request.
1213 0 : Unused << browser->SendAwaitLargeAlloc();
1214 : }
1215 :
1216 0 : if (browser) {
1217 0 : RefPtr<TabParent> constructedTabParent = TabParent::GetFrom(browser);
1218 0 : constructedTabParent->SetOwnerElement(aFrameElement);
1219 0 : return constructedTabParent;
1220 : }
1221 : }
1222 : return nullptr;
1223 : }
1224 :
1225 : /*static*/ ContentBridgeParent*
1226 0 : ContentParent::CreateContentBridgeParent(const TabContext& aContext,
1227 : const hal::ProcessPriority& aPriority,
1228 : const TabId& aOpenerTabId,
1229 : const TabId& aTabId)
1230 : {
1231 0 : MOZ_ASSERT(aTabId);
1232 :
1233 0 : ContentChild* child = ContentChild::GetSingleton();
1234 0 : ContentParentId cpId;
1235 : bool isForBrowser;
1236 0 : if (!child->SendCreateChildProcess(aContext.AsIPCTabContext(),
1237 : aPriority,
1238 : aOpenerTabId,
1239 : aTabId,
1240 : &cpId,
1241 : &isForBrowser)) {
1242 : return nullptr;
1243 : }
1244 0 : if (cpId == 0) {
1245 : return nullptr;
1246 : }
1247 0 : Endpoint<PContentBridgeParent> endpoint;
1248 0 : if (!child->SendBridgeToChildProcess(cpId, &endpoint)) {
1249 : return nullptr;
1250 : }
1251 0 : ContentBridgeParent* parent = ContentBridgeParent::Create(std::move(endpoint));
1252 0 : parent->SetChildID(cpId);
1253 0 : parent->SetIsForBrowser(isForBrowser);
1254 0 : parent->SetIsForJSPlugin(aContext.IsJSPlugin());
1255 0 : return parent;
1256 : }
1257 :
1258 : void
1259 0 : ContentParent::GetAll(nsTArray<ContentParent*>& aArray)
1260 : {
1261 0 : aArray.Clear();
1262 :
1263 0 : for (auto* cp : AllProcesses(eLive)) {
1264 0 : aArray.AppendElement(cp);
1265 : }
1266 0 : }
1267 :
1268 : void
1269 0 : ContentParent::GetAllEvenIfDead(nsTArray<ContentParent*>& aArray)
1270 : {
1271 0 : aArray.Clear();
1272 :
1273 0 : for (auto* cp : AllProcesses(eAll)) {
1274 0 : aArray.AppendElement(cp);
1275 : }
1276 0 : }
1277 :
1278 : const nsAString&
1279 0 : ContentParent::GetRemoteType() const
1280 : {
1281 0 : return mRemoteType;
1282 : }
1283 :
1284 : void
1285 0 : ContentParent::Init()
1286 : {
1287 0 : nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
1288 0 : if (obs) {
1289 : size_t length = ArrayLength(sObserverTopics);
1290 0 : for (size_t i = 0; i < length; ++i) {
1291 0 : obs->AddObserver(this, sObserverTopics[i], false);
1292 : }
1293 : }
1294 :
1295 : // Register ContentParent as an observer for changes to any pref whose prefix
1296 : // matches the empty string, i.e. all of them.
1297 0 : Preferences::AddStrongObserver(this, "");
1298 :
1299 0 : if (obs) {
1300 0 : nsAutoString cpId;
1301 0 : cpId.AppendInt(static_cast<uint64_t>(this->ChildID()));
1302 0 : obs->NotifyObservers(static_cast<nsIObserver*>(this), "ipc:content-created", cpId.get());
1303 : }
1304 :
1305 : #ifdef ACCESSIBILITY
1306 : // If accessibility is running in chrome process then start it in content
1307 : // process.
1308 0 : if (nsIPresShell::IsAccessibilityActive()) {
1309 : #if defined(XP_WIN)
1310 : // Don't init content a11y if we detect an incompat version of JAWS in use.
1311 : if (!mozilla::a11y::Compatibility::IsOldJAWS()) {
1312 : Unused << SendActivateA11y(::GetCurrentThreadId(),
1313 : a11y::AccessibleWrap::GetContentProcessIdFor(ChildID()));
1314 : }
1315 : #else
1316 0 : Unused << SendActivateA11y(0, 0);
1317 : #endif
1318 : }
1319 : #endif
1320 :
1321 : #ifdef MOZ_GECKO_PROFILER
1322 0 : Unused << SendInitProfiler(ProfilerParent::CreateForProcess(OtherPid()));
1323 : #endif
1324 :
1325 : // Ensure that the default set of permissions are avaliable in the content
1326 : // process before we try to load any URIs in it.
1327 0 : EnsurePermissionsByKey(EmptyCString());
1328 :
1329 0 : RefPtr<GeckoMediaPluginServiceParent> gmps(GeckoMediaPluginServiceParent::GetSingleton());
1330 0 : gmps->UpdateContentProcessGMPCapabilities();
1331 :
1332 0 : mScriptableHelper = new ScriptableCPInfo(this);
1333 0 : }
1334 :
1335 : namespace {
1336 :
1337 : class RemoteWindowContext final : public nsIRemoteWindowContext
1338 : , public nsIInterfaceRequestor
1339 : {
1340 : public:
1341 0 : explicit RemoteWindowContext(TabParent* aTabParent)
1342 0 : : mTabParent(aTabParent)
1343 : {
1344 0 : }
1345 :
1346 : NS_DECL_ISUPPORTS
1347 : NS_DECL_NSIINTERFACEREQUESTOR
1348 : NS_DECL_NSIREMOTEWINDOWCONTEXT
1349 :
1350 : private:
1351 : ~RemoteWindowContext();
1352 : RefPtr<TabParent> mTabParent;
1353 : };
1354 :
1355 0 : NS_IMPL_ISUPPORTS(RemoteWindowContext, nsIRemoteWindowContext, nsIInterfaceRequestor)
1356 :
1357 0 : RemoteWindowContext::~RemoteWindowContext()
1358 : {
1359 0 : }
1360 :
1361 : NS_IMETHODIMP
1362 0 : RemoteWindowContext::GetInterface(const nsIID& aIID, void** aSink)
1363 : {
1364 0 : return QueryInterface(aIID, aSink);
1365 : }
1366 :
1367 : NS_IMETHODIMP
1368 0 : RemoteWindowContext::OpenURI(nsIURI* aURI)
1369 : {
1370 0 : mTabParent->LoadURL(aURI);
1371 0 : return NS_OK;
1372 : }
1373 :
1374 : } // namespace
1375 :
1376 : void
1377 0 : ContentParent::ShutDownProcess(ShutDownMethod aMethod)
1378 : {
1379 0 : if (mScriptableHelper) {
1380 0 : static_cast<ScriptableCPInfo*>(mScriptableHelper.get())->ProcessDied();
1381 0 : mScriptableHelper = nullptr;
1382 : }
1383 :
1384 : // Shutting down by sending a shutdown message works differently than the
1385 : // other methods. We first call Shutdown() in the child. After the child is
1386 : // ready, it calls FinishShutdown() on us. Then we close the channel.
1387 0 : if (aMethod == SEND_SHUTDOWN_MESSAGE) {
1388 0 : if (mIPCOpen && !mShutdownPending) {
1389 : // Stop sending input events with input priority when shutting down.
1390 0 : SetInputPriorityEventEnabled(false);
1391 0 : if (SendShutdown()) {
1392 0 : mShutdownPending = true;
1393 : // Start the force-kill timer if we haven't already.
1394 0 : StartForceKillTimer();
1395 : }
1396 : }
1397 : // If call was not successful, the channel must have been broken
1398 : // somehow, and we will clean up the error in ActorDestroy.
1399 : return;
1400 : }
1401 :
1402 : using mozilla::dom::quota::QuotaManagerService;
1403 :
1404 0 : if (QuotaManagerService* quotaManagerService = QuotaManagerService::Get()) {
1405 0 : quotaManagerService->AbortOperationsForProcess(mChildID);
1406 : }
1407 :
1408 : // If Close() fails with an error, we'll end up back in this function, but
1409 : // with aMethod = CLOSE_CHANNEL_WITH_ERROR.
1410 :
1411 0 : if (aMethod == CLOSE_CHANNEL && !mCalledClose) {
1412 : // Close() can only be called once: It kicks off the destruction
1413 : // sequence.
1414 0 : mCalledClose = true;
1415 0 : Close();
1416 : }
1417 :
1418 : const ManagedContainer<POfflineCacheUpdateParent>& ocuParents =
1419 0 : ManagedPOfflineCacheUpdateParent();
1420 0 : for (auto iter = ocuParents.ConstIter(); !iter.Done(); iter.Next()) {
1421 : RefPtr<mozilla::docshell::OfflineCacheUpdateParent> ocuParent =
1422 0 : static_cast<mozilla::docshell::OfflineCacheUpdateParent*>(iter.Get()->GetKey());
1423 0 : ocuParent->StopSendingMessagesToChild();
1424 : }
1425 :
1426 : // NB: must MarkAsDead() here so that this isn't accidentally
1427 : // returned from Get*() while in the midst of shutdown.
1428 0 : MarkAsDead();
1429 :
1430 : // A ContentParent object might not get freed until after XPCOM shutdown has
1431 : // shut down the cycle collector. But by then it's too late to release any
1432 : // CC'ed objects, so we need to null them out here, while we still can. See
1433 : // bug 899761.
1434 0 : ShutDownMessageManager();
1435 : }
1436 :
1437 : mozilla::ipc::IPCResult
1438 0 : ContentParent::RecvFinishShutdown()
1439 : {
1440 : // At this point, we already called ShutDownProcess once with
1441 : // SEND_SHUTDOWN_MESSAGE. To actually close the channel, we call
1442 : // ShutDownProcess again with CLOSE_CHANNEL.
1443 0 : MOZ_ASSERT(mShutdownPending);
1444 0 : ShutDownProcess(CLOSE_CHANNEL);
1445 0 : return IPC_OK();
1446 : }
1447 :
1448 : void
1449 0 : ContentParent::ShutDownMessageManager()
1450 : {
1451 0 : if (!mMessageManager) {
1452 : return;
1453 : }
1454 :
1455 0 : mMessageManager->ReceiveMessage(mMessageManager, nullptr,
1456 0 : CHILD_PROCESS_SHUTDOWN_MESSAGE, false,
1457 0 : nullptr, nullptr, nullptr, nullptr, IgnoreErrors());
1458 :
1459 0 : mMessageManager->Disconnect();
1460 0 : mMessageManager = nullptr;
1461 : }
1462 :
1463 : void
1464 0 : ContentParent::RemoveFromList()
1465 : {
1466 0 : if (IsForJSPlugin()) {
1467 0 : if (sJSPluginContentParents) {
1468 0 : sJSPluginContentParents->Remove(mJSPluginID);
1469 0 : if (!sJSPluginContentParents->Count()) {
1470 0 : delete sJSPluginContentParents;
1471 0 : sJSPluginContentParents = nullptr;
1472 : }
1473 : }
1474 0 : } else if (sBrowserContentParents) {
1475 0 : if (auto entry = sBrowserContentParents->Lookup(mRemoteType)) {
1476 0 : nsTArray<ContentParent*>* contentParents = entry.Data();
1477 0 : contentParents->RemoveElement(this);
1478 0 : if (contentParents->IsEmpty()) {
1479 0 : entry.Remove();
1480 : }
1481 : }
1482 0 : if (sBrowserContentParents->IsEmpty()) {
1483 0 : delete sBrowserContentParents;
1484 0 : sBrowserContentParents = nullptr;
1485 : }
1486 : }
1487 :
1488 0 : if (sPrivateContent) {
1489 0 : sPrivateContent->RemoveElement(this);
1490 0 : if (!sPrivateContent->Length()) {
1491 0 : delete sPrivateContent;
1492 0 : sPrivateContent = nullptr;
1493 : }
1494 : }
1495 0 : }
1496 :
1497 : void
1498 0 : ContentParent::MarkAsTroubled()
1499 : {
1500 0 : RemoveFromList();
1501 0 : mIsAvailable = false;
1502 0 : }
1503 :
1504 : void
1505 0 : ContentParent::MarkAsDead()
1506 : {
1507 0 : MarkAsTroubled();
1508 0 : mIsAlive = false;
1509 0 : }
1510 :
1511 : void
1512 0 : ContentParent::OnChannelError()
1513 : {
1514 0 : RefPtr<ContentParent> content(this);
1515 0 : PContentParent::OnChannelError();
1516 0 : }
1517 :
1518 : void
1519 0 : ContentParent::OnChannelConnected(int32_t pid)
1520 : {
1521 0 : MOZ_ASSERT(NS_IsMainThread());
1522 :
1523 : #ifndef ASYNC_CONTENTPROC_LAUNCH
1524 : SetOtherProcessId(pid);
1525 : #endif
1526 :
1527 : #if defined(ANDROID) || defined(LINUX)
1528 : // Check nice preference
1529 0 : int32_t nice = Preferences::GetInt("dom.ipc.content.nice", 0);
1530 :
1531 : // Environment variable overrides preference
1532 0 : char* relativeNicenessStr = getenv("MOZ_CHILD_PROCESS_RELATIVE_NICENESS");
1533 0 : if (relativeNicenessStr) {
1534 0 : nice = atoi(relativeNicenessStr);
1535 : }
1536 :
1537 : /* make the GUI thread have higher priority on single-cpu devices */
1538 0 : nsCOMPtr<nsIPropertyBag2> infoService = do_GetService(NS_SYSTEMINFO_CONTRACTID);
1539 0 : if (infoService) {
1540 : int32_t cpus;
1541 0 : nsresult rv = infoService->GetPropertyAsInt32(NS_LITERAL_STRING("cpucount"), &cpus);
1542 0 : if (NS_FAILED(rv)) {
1543 0 : cpus = 1;
1544 : }
1545 0 : if (nice != 0 && cpus == 1) {
1546 0 : setpriority(PRIO_PROCESS, pid, getpriority(PRIO_PROCESS, pid) + nice);
1547 : }
1548 : }
1549 : #endif
1550 :
1551 : #if defined(MOZ_CODE_COVERAGE) && defined(ASYNC_CONTENTPROC_LAUNCH)
1552 0 : Unused << SendShareCodeCoverageMutex(
1553 0 : CodeCoverageHandler::Get()->GetMutexHandle(pid));
1554 : #endif
1555 0 : }
1556 :
1557 : void
1558 0 : ContentParent::ProcessingError(Result aCode, const char* aReason)
1559 : {
1560 0 : if (MsgDropped == aCode) {
1561 : return;
1562 : }
1563 : #ifndef FUZZING
1564 : // Other errors are big deals.
1565 0 : KillHard(aReason);
1566 : #endif
1567 : }
1568 :
1569 : /* static */
1570 : bool
1571 0 : ContentParent::AllocateLayerTreeId(TabParent* aTabParent, layers::LayersId* aId)
1572 : {
1573 0 : return AllocateLayerTreeId(aTabParent->Manager()->AsContentParent(),
1574 0 : aTabParent, aTabParent->GetTabId(), aId);
1575 : }
1576 :
1577 : /* static */
1578 : bool
1579 0 : ContentParent::AllocateLayerTreeId(ContentParent* aContent,
1580 : TabParent* aTopLevel, const TabId& aTabId,
1581 : layers::LayersId* aId)
1582 : {
1583 0 : GPUProcessManager* gpu = GPUProcessManager::Get();
1584 :
1585 0 : *aId = gpu->AllocateLayerTreeId();
1586 :
1587 0 : if (!aContent || !aTopLevel) {
1588 : return false;
1589 : }
1590 :
1591 0 : gpu->MapLayerTreeId(*aId, aContent->OtherPid());
1592 :
1593 0 : return true;
1594 : }
1595 :
1596 : mozilla::ipc::IPCResult
1597 0 : ContentParent::RecvAllocateLayerTreeId(const ContentParentId& aCpId,
1598 : const TabId& aTabId, layers::LayersId* aId)
1599 : {
1600 : // Protect against spoofing by a compromised child. aCpId must either
1601 : // correspond to the process that this ContentParent represents or be a
1602 : // child of it.
1603 0 : ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
1604 0 : RefPtr<ContentParent> contentParent = cpm->GetContentProcessById(aCpId);
1605 0 : if (!contentParent ||
1606 0 : (ChildID() != aCpId && !contentParent->CanCommunicateWith(ChildID()))) {
1607 0 : return IPC_FAIL_NO_REASON(this);
1608 : }
1609 :
1610 : // GetTopLevelTabParentByProcessAndTabId will make sure that aTabId
1611 : // lives in the process for aCpId.
1612 : RefPtr<TabParent> browserParent =
1613 0 : cpm->GetTopLevelTabParentByProcessAndTabId(aCpId, aTabId);
1614 0 : MOZ_ASSERT(contentParent && browserParent);
1615 :
1616 0 : if (!AllocateLayerTreeId(contentParent, browserParent, aTabId, aId)) {
1617 0 : return IPC_FAIL_NO_REASON(this);
1618 : }
1619 : return IPC_OK();
1620 : }
1621 :
1622 : mozilla::ipc::IPCResult
1623 0 : ContentParent::RecvDeallocateLayerTreeId(const ContentParentId& aCpId,
1624 : const layers::LayersId& aId)
1625 : {
1626 0 : GPUProcessManager* gpu = GPUProcessManager::Get();
1627 :
1628 0 : ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
1629 0 : RefPtr<ContentParent> contentParent = cpm->GetContentProcessById(aCpId);
1630 0 : if (!contentParent || !contentParent->CanCommunicateWith(ChildID())) {
1631 0 : return IPC_FAIL(this, "Spoofed DeallocateLayerTreeId call");
1632 : }
1633 :
1634 0 : if (!gpu->IsLayerTreeIdMapped(aId, contentParent->OtherPid())) {
1635 : // You can't deallocate layer tree ids that you didn't allocate
1636 0 : KillHard("DeallocateLayerTreeId");
1637 : }
1638 :
1639 0 : gpu->UnmapLayerTreeId(aId, contentParent->OtherPid());
1640 :
1641 : return IPC_OK();
1642 : }
1643 :
1644 : namespace {
1645 :
1646 : void
1647 0 : DelayedDeleteSubprocess(GeckoChildProcessHost* aSubprocess)
1648 : {
1649 0 : RefPtr<DeleteTask<GeckoChildProcessHost>> task = new DeleteTask<GeckoChildProcessHost>(aSubprocess);
1650 0 : XRE_GetIOMessageLoop()->PostTask(task.forget());
1651 0 : }
1652 :
1653 : // This runnable only exists to delegate ownership of the
1654 : // ContentParent to this runnable, until it's deleted by the event
1655 : // system.
1656 0 : struct DelayedDeleteContentParentTask : public Runnable
1657 : {
1658 0 : explicit DelayedDeleteContentParentTask(ContentParent* aObj)
1659 0 : : Runnable("dom::DelayedDeleteContentParentTask")
1660 0 : , mObj(aObj)
1661 : {
1662 0 : }
1663 :
1664 : // No-op
1665 0 : NS_IMETHOD Run() override { return NS_OK; }
1666 :
1667 : RefPtr<ContentParent> mObj;
1668 : };
1669 :
1670 : } // namespace
1671 :
1672 : void
1673 0 : ContentParent::ActorDestroy(ActorDestroyReason why)
1674 : {
1675 0 : if (mForceKillTimer) {
1676 0 : mForceKillTimer->Cancel();
1677 0 : mForceKillTimer = nullptr;
1678 : }
1679 :
1680 : // Signal shutdown completion regardless of error state, so we can
1681 : // finish waiting in the xpcom-shutdown/profile-before-change observer.
1682 0 : mIPCOpen = false;
1683 :
1684 0 : if (mHangMonitorActor) {
1685 0 : ProcessHangMonitor::RemoveProcess(mHangMonitorActor);
1686 0 : mHangMonitorActor = nullptr;
1687 : }
1688 :
1689 0 : RefPtr<FileSystemSecurity> fss = FileSystemSecurity::Get();
1690 0 : if (fss) {
1691 0 : fss->Forget(ChildID());
1692 : }
1693 :
1694 0 : if (why == NormalShutdown && !mCalledClose) {
1695 : // If we shut down normally but haven't called Close, assume somebody
1696 : // else called Close on us. In that case, we still need to call
1697 : // ShutDownProcess below to perform other necessary clean up.
1698 0 : mCalledClose = true;
1699 : }
1700 :
1701 : // Make sure we always clean up.
1702 0 : ShutDownProcess(why == NormalShutdown ? CLOSE_CHANNEL
1703 0 : : CLOSE_CHANNEL_WITH_ERROR);
1704 :
1705 0 : RefPtr<ContentParent> kungFuDeathGrip(this);
1706 0 : nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
1707 0 : if (obs) {
1708 : size_t length = ArrayLength(sObserverTopics);
1709 0 : for (size_t i = 0; i < length; ++i) {
1710 0 : obs->RemoveObserver(static_cast<nsIObserver*>(this),
1711 0 : sObserverTopics[i]);
1712 : }
1713 : }
1714 :
1715 : // remove the global remote preferences observers
1716 0 : Preferences::RemoveObserver(this, "");
1717 0 : gfxVars::RemoveReceiver(this);
1718 :
1719 0 : if (GPUProcessManager* gpu = GPUProcessManager::Get()) {
1720 : // Note: the manager could have shutdown already.
1721 0 : gpu->RemoveListener(this);
1722 : }
1723 :
1724 0 : RecvRemoveGeolocationListener();
1725 :
1726 0 : mConsoleService = nullptr;
1727 :
1728 0 : if (obs) {
1729 0 : RefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
1730 :
1731 0 : props->SetPropertyAsUint64(NS_LITERAL_STRING("childID"), mChildID);
1732 :
1733 0 : if (AbnormalShutdown == why) {
1734 : Telemetry::Accumulate(Telemetry::SUBPROCESS_ABNORMAL_ABORT,
1735 0 : NS_LITERAL_CSTRING("content"), 1);
1736 :
1737 0 : props->SetPropertyAsBool(NS_LITERAL_STRING("abnormal"), true);
1738 :
1739 : // There's a window in which child processes can crash
1740 : // after IPC is established, but before a crash reporter
1741 : // is created.
1742 0 : if (mCrashReporter) {
1743 : // if mCreatedPairedMinidumps is true, we've already generated
1744 : // parent/child dumps for desktop crashes.
1745 0 : if (!mCreatedPairedMinidumps) {
1746 0 : mCrashReporter->GenerateCrashReport(OtherPid());
1747 : }
1748 :
1749 0 : nsAutoString dumpID;
1750 0 : if (mCrashReporter->HasMinidump()) {
1751 0 : dumpID = mCrashReporter->MinidumpID();
1752 : }
1753 0 : props->SetPropertyAsAString(NS_LITERAL_STRING("dumpID"), dumpID);
1754 : }
1755 : }
1756 0 : nsAutoString cpId;
1757 0 : cpId.AppendInt(static_cast<uint64_t>(this->ChildID()));
1758 0 : obs->NotifyObservers((nsIPropertyBag2*) props, "ipc:content-shutdown", cpId.get());
1759 : }
1760 :
1761 : // Remove any and all idle listeners.
1762 : nsCOMPtr<nsIIdleService> idleService =
1763 0 : do_GetService("@mozilla.org/widget/idleservice;1");
1764 0 : MOZ_ASSERT(idleService);
1765 0 : RefPtr<ParentIdleListener> listener;
1766 0 : for (int32_t i = mIdleListeners.Length() - 1; i >= 0; --i) {
1767 0 : listener = static_cast<ParentIdleListener*>(mIdleListeners[i].get());
1768 0 : idleService->RemoveIdleObserver(listener, listener->mTime);
1769 : }
1770 0 : mIdleListeners.Clear();
1771 :
1772 : MessageLoop::current()->
1773 0 : PostTask(NewRunnableFunction("DelayedDeleteSubprocessRunnable",
1774 0 : DelayedDeleteSubprocess, mSubprocess));
1775 0 : mSubprocess = nullptr;
1776 :
1777 : // IPDL rules require actors to live on past ActorDestroy, but it
1778 : // may be that the kungFuDeathGrip above is the last reference to
1779 : // |this|. If so, when we go out of scope here, we're deleted and
1780 : // all hell breaks loose.
1781 : //
1782 : // This runnable ensures that a reference to |this| lives on at
1783 : // least until after the current task finishes running.
1784 0 : NS_DispatchToCurrentThread(new DelayedDeleteContentParentTask(this));
1785 :
1786 0 : ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
1787 : nsTArray<ContentParentId> childIDArray =
1788 0 : cpm->GetAllChildProcessById(this->ChildID());
1789 :
1790 : // Destroy any processes created by this ContentParent
1791 0 : for(uint32_t i = 0; i < childIDArray.Length(); i++) {
1792 0 : ContentParent* cp = cpm->GetContentProcessById(childIDArray[i]);
1793 0 : MessageLoop::current()->PostTask(
1794 0 : NewRunnableMethod<ShutDownMethod>("dom::ContentParent::ShutDownProcess",
1795 : cp,
1796 : &ContentParent::ShutDownProcess,
1797 0 : SEND_SHUTDOWN_MESSAGE));
1798 : }
1799 0 : cpm->RemoveContentProcess(this->ChildID());
1800 :
1801 0 : if (mDriverCrashGuard) {
1802 0 : mDriverCrashGuard->NotifyCrashed();
1803 : }
1804 :
1805 : // Unregister all the BlobURLs registered by the ContentChild.
1806 0 : for (uint32_t i = 0; i < mBlobURLs.Length(); ++i) {
1807 0 : BlobURLProtocolHandler::RemoveDataEntry(mBlobURLs[i]);
1808 : }
1809 :
1810 0 : mBlobURLs.Clear();
1811 :
1812 : #if defined(XP_WIN32) && defined(ACCESSIBILITY)
1813 : a11y::AccessibleWrap::ReleaseContentProcessIdFor(ChildID());
1814 : #endif
1815 0 : }
1816 :
1817 : bool
1818 0 : ContentParent::TryToRecycle()
1819 : {
1820 : // This life time check should be replaced by a memory health check (memory usage + fragmentation).
1821 0 : const double kMaxLifeSpan = 5;
1822 0 : if (mShutdownPending ||
1823 0 : mCalledKillHard ||
1824 0 : !IsAvailable() ||
1825 0 : !mRemoteType.EqualsLiteral(DEFAULT_REMOTE_TYPE) ||
1826 0 : (TimeStamp::Now() - mActivateTS).ToSeconds() > kMaxLifeSpan ||
1827 0 : !PreallocatedProcessManager::Provide(this)) {
1828 : return false;
1829 : }
1830 :
1831 : // The PreallocatedProcessManager took over the ownership let's not keep a reference to it,
1832 : // until we don't take it back.
1833 0 : RemoveFromList();
1834 0 : return true;
1835 : }
1836 :
1837 : bool
1838 0 : ContentParent::ShouldKeepProcessAlive() const
1839 : {
1840 0 : if (IsForJSPlugin()) {
1841 : return true;
1842 : }
1843 :
1844 0 : if (!sBrowserContentParents) {
1845 : return false;
1846 : }
1847 :
1848 : // If we have already been marked as troubled/dead, don't prevent shutdown.
1849 0 : if (!IsAvailable()) {
1850 : return false;
1851 : }
1852 :
1853 0 : auto contentParents = sBrowserContentParents->Get(mRemoteType);
1854 0 : if (!contentParents) {
1855 : return false;
1856 : }
1857 :
1858 : // We might want to keep alive some content processes alive during test runs,
1859 : // for performance reasons. This should never be used in production.
1860 : // We don't want to alter behavior if the pref is not set, so default to 0.
1861 0 : int32_t processesToKeepAlive = 0;
1862 :
1863 0 : nsAutoCString keepAlivePref("dom.ipc.keepProcessesAlive.");
1864 0 : keepAlivePref.Append(NS_ConvertUTF16toUTF8(mRemoteType));
1865 0 : if (NS_FAILED(Preferences::GetInt(keepAlivePref.get(), &processesToKeepAlive))) {
1866 : return false;
1867 : }
1868 :
1869 0 : int32_t numberOfAliveProcesses = contentParents->Length();
1870 :
1871 0 : return numberOfAliveProcesses <= processesToKeepAlive;
1872 : }
1873 :
1874 : void
1875 0 : ContentParent::NotifyTabDestroying(const TabId& aTabId,
1876 : const ContentParentId& aCpId)
1877 : {
1878 0 : if (XRE_IsParentProcess()) {
1879 : // There can be more than one PBrowser for a given app process
1880 : // because of popup windows. PBrowsers can also destroy
1881 : // concurrently. When all the PBrowsers are destroying, kick off
1882 : // another task to ensure the child process *really* shuts down,
1883 : // even if the PBrowsers themselves never finish destroying.
1884 0 : ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
1885 0 : ContentParent* cp = cpm->GetContentProcessById(aCpId);
1886 0 : if (!cp) {
1887 0 : return;
1888 : }
1889 0 : ++cp->mNumDestroyingTabs;
1890 0 : nsTArray<TabId> tabIds = cpm->GetTabParentsByProcessId(aCpId);
1891 0 : if (static_cast<size_t>(cp->mNumDestroyingTabs) != tabIds.Length()) {
1892 : return;
1893 : }
1894 :
1895 0 : if (cp->ShouldKeepProcessAlive()) {
1896 : return;
1897 : }
1898 :
1899 0 : if (cp->TryToRecycle()) {
1900 : return;
1901 : }
1902 :
1903 : // We're dying now, so prevent this content process from being
1904 : // recycled during its shutdown procedure.
1905 0 : cp->MarkAsDead();
1906 0 : cp->StartForceKillTimer();
1907 : } else {
1908 0 : ContentChild::GetSingleton()->SendNotifyTabDestroying(aTabId, aCpId);
1909 : }
1910 : }
1911 :
1912 : void
1913 0 : ContentParent::StartForceKillTimer()
1914 : {
1915 0 : if (mForceKillTimer || !mIPCOpen) {
1916 : return;
1917 : }
1918 :
1919 0 : int32_t timeoutSecs = Preferences::GetInt("dom.ipc.tabs.shutdownTimeoutSecs", 5);
1920 0 : if (timeoutSecs > 0) {
1921 0 : NS_NewTimerWithFuncCallback(getter_AddRefs(mForceKillTimer),
1922 : ContentParent::ForceKillTimerCallback,
1923 : this,
1924 0 : timeoutSecs * 1000,
1925 : nsITimer::TYPE_ONE_SHOT,
1926 0 : "dom::ContentParent::StartForceKillTimer");
1927 0 : MOZ_ASSERT(mForceKillTimer);
1928 : }
1929 : }
1930 :
1931 : void
1932 0 : ContentParent::NotifyTabDestroyed(const TabId& aTabId,
1933 : bool aNotifiedDestroying)
1934 : {
1935 0 : if (aNotifiedDestroying) {
1936 0 : --mNumDestroyingTabs;
1937 : }
1938 :
1939 : nsTArray<PContentPermissionRequestParent*> parentArray =
1940 0 : nsContentPermissionUtils::GetContentPermissionRequestParentById(aTabId);
1941 :
1942 : // Need to close undeleted ContentPermissionRequestParents before tab is closed.
1943 0 : for (auto& permissionRequestParent : parentArray) {
1944 0 : Unused << PContentPermissionRequestParent::Send__delete__(permissionRequestParent);
1945 : }
1946 :
1947 : // There can be more than one PBrowser for a given app process
1948 : // because of popup windows. When the last one closes, shut
1949 : // us down.
1950 0 : ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
1951 0 : nsTArray<TabId> tabIds = cpm->GetTabParentsByProcessId(this->ChildID());
1952 :
1953 0 : if (tabIds.Length() == 1 && !ShouldKeepProcessAlive() && !TryToRecycle()) {
1954 : // In the case of normal shutdown, send a shutdown message to child to
1955 : // allow it to perform shutdown tasks.
1956 0 : MessageLoop::current()->PostTask(
1957 0 : NewRunnableMethod<ShutDownMethod>("dom::ContentParent::ShutDownProcess",
1958 : this,
1959 : &ContentParent::ShutDownProcess,
1960 0 : SEND_SHUTDOWN_MESSAGE));
1961 : }
1962 0 : }
1963 :
1964 : jsipc::CPOWManager*
1965 0 : ContentParent::GetCPOWManager()
1966 : {
1967 14 : if (PJavaScriptParent* p = LoneManagedOrNullAsserts(ManagedPJavaScriptParent())) {
1968 14 : return CPOWManagerFor(p);
1969 : }
1970 : return nullptr;
1971 : }
1972 :
1973 : TestShellParent*
1974 0 : ContentParent::CreateTestShell()
1975 : {
1976 0 : return static_cast<TestShellParent*>(SendPTestShellConstructor());
1977 : }
1978 :
1979 : bool
1980 0 : ContentParent::DestroyTestShell(TestShellParent* aTestShell)
1981 : {
1982 0 : return PTestShellParent::Send__delete__(aTestShell);
1983 : }
1984 :
1985 : TestShellParent*
1986 0 : ContentParent::GetTestShellSingleton()
1987 : {
1988 0 : PTestShellParent* p = LoneManagedOrNullAsserts(ManagedPTestShellParent());
1989 0 : return static_cast<TestShellParent*>(p);
1990 : }
1991 :
1992 : bool
1993 0 : ContentParent::LaunchSubprocess(ProcessPriority aInitialPriority /* = PROCESS_PRIORITY_FOREGROUND */)
1994 : {
1995 0 : AUTO_PROFILER_LABEL("ContentParent::LaunchSubprocess", OTHER);
1996 :
1997 2 : if (!ContentProcessManager::GetSingleton()) {
1998 : // Shutdown has begun, we shouldn't spawn any more child processes.
1999 : return false;
2000 : }
2001 :
2002 3 : std::vector<std::string> extraArgs;
2003 0 : extraArgs.push_back("-childID");
2004 : char idStr[21];
2005 0 : SprintfLiteral(idStr, "%" PRId64, static_cast<uint64_t>(mChildID));
2006 8 : extraArgs.push_back(idStr);
2007 10 : extraArgs.push_back(IsForBrowser() ? "-isForBrowser" : "-notForBrowser");
2008 :
2009 : // Prefs information is passed via anonymous shared memory to avoid bloating
2010 : // the command line.
2011 :
2012 : // Serialize the early prefs.
2013 3 : nsAutoCStringN<1024> prefs;
2014 2 : Preferences::SerializePreferences(prefs);
2015 :
2016 : // Set up the shared memory.
2017 1 : base::SharedMemory shm;
2018 1 : if (!shm.Create(prefs.Length())) {
2019 0 : NS_ERROR("failed to create shared memory in the parent");
2020 0 : MarkAsDead();
2021 0 : return false;
2022 : }
2023 1 : if (!shm.Map(prefs.Length())) {
2024 0 : NS_ERROR("failed to map shared memory in the parent");
2025 0 : MarkAsDead();
2026 0 : return false;
2027 : }
2028 :
2029 : // Copy the serialized prefs into the shared memory.
2030 4 : memcpy(static_cast<char*>(shm.memory()), prefs.get(), prefs.Length());
2031 :
2032 : #if defined(XP_WIN)
2033 : // Record the handle as to-be-shared, and pass it via a command flag. This
2034 : // works because Windows handles are system-wide.
2035 : HANDLE prefsHandle = shm.handle();
2036 : mSubprocess->AddHandleToShare(prefsHandle);
2037 : extraArgs.push_back("-prefsHandle");
2038 : extraArgs.push_back(
2039 : nsPrintfCString("%zu", reinterpret_cast<uintptr_t>(prefsHandle)).get());
2040 : #else
2041 : // In contrast, Unix fds are per-process. So remap the fd to a fixed one that
2042 : // will be used in the child.
2043 : // XXX: bug 1440207 is about improving how fixed fds are used.
2044 : //
2045 : // Note: on Android, AddFdToRemap() sets up the fd to be passed via a Parcel,
2046 : // and the fixed fd isn't used. However, we still need to mark it for
2047 : // remapping so it doesn't get closed in the child.
2048 2 : mSubprocess->AddFdToRemap(shm.handle().fd, kPrefsFileDescriptor);
2049 : #endif
2050 :
2051 : // Pass the length via a command flag.
2052 8 : extraArgs.push_back("-prefsLen");
2053 10 : extraArgs.push_back(nsPrintfCString("%zu", uintptr_t(prefs.Length())).get());
2054 :
2055 : // Scheduler prefs need to be handled differently because the scheduler needs
2056 : // to start up in the content process before the normal preferences service.
2057 0 : nsCString schedulerPrefs = Scheduler::GetPrefs();
2058 8 : extraArgs.push_back("-schedulerPrefs");
2059 0 : extraArgs.push_back(schedulerPrefs.get());
2060 :
2061 2 : if (gSafeMode) {
2062 0 : extraArgs.push_back("-safeMode");
2063 : }
2064 :
2065 0 : nsCString parentBuildID(mozilla::PlatformBuildID());
2066 8 : extraArgs.push_back("-parentBuildID");
2067 0 : extraArgs.push_back(parentBuildID.get());
2068 :
2069 0 : SetOtherProcessId(kInvalidProcessId, ProcessIdState::ePending);
2070 : #ifdef ASYNC_CONTENTPROC_LAUNCH
2071 2 : if (!mSubprocess->Launch(extraArgs)) {
2072 : #else
2073 : if (!mSubprocess->LaunchAndWaitForProcessHandle(extraArgs)) {
2074 : #endif
2075 0 : NS_ERROR("failed to launch child in the parent");
2076 0 : MarkAsDead();
2077 0 : return false;
2078 : }
2079 :
2080 : #ifdef ASYNC_CONTENTPROC_LAUNCH
2081 4 : OpenWithAsyncPid(mSubprocess->GetChannel());
2082 : #else
2083 : base::ProcessId procId =
2084 : base::GetProcId(mSubprocess->GetChildProcessHandle());
2085 : Open(mSubprocess->GetChannel(), procId);
2086 : #ifdef MOZ_CODE_COVERAGE
2087 : Unused << SendShareCodeCoverageMutex(
2088 : CodeCoverageHandler::Get()->GetMutexHandle(procId));
2089 : #endif
2090 : #endif // ASYNC_CONTENTPROC_LAUNCH
2091 :
2092 0 : InitInternal(aInitialPriority);
2093 :
2094 0 : ContentProcessManager::GetSingleton()->AddContentProcess(this);
2095 :
2096 1 : mHangMonitorActor = ProcessHangMonitor::AddProcess(this);
2097 :
2098 : // Set a reply timeout for CPOWs.
2099 1 : SetReplyTimeoutMs(Preferences::GetInt("dom.ipc.cpow.timeout", 0));
2100 :
2101 : // TODO: In ASYNC_CONTENTPROC_LAUNCH, if OtherPid() is not called between
2102 : // mSubprocess->Launch() and this, then we're not really measuring how long it
2103 : // took to spawn the process.
2104 0 : Telemetry::Accumulate(Telemetry::CONTENT_PROCESS_LAUNCH_TIME_MS,
2105 2 : static_cast<uint32_t>((TimeStamp::Now() - mLaunchTS)
2106 0 : .ToMilliseconds()));
2107 :
2108 0 : nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
2109 0 : if (obs) {
2110 0 : nsAutoString cpId;
2111 1 : cpId.AppendInt(static_cast<uint64_t>(this->ChildID()));
2112 1 : obs->NotifyObservers(static_cast<nsIObserver*>(this), "ipc:content-initializing", cpId.get());
2113 : }
2114 :
2115 1 : Init();
2116 :
2117 : return true;
2118 : }
2119 :
2120 0 : ContentParent::ContentParent(ContentParent* aOpener,
2121 : const nsAString& aRemoteType,
2122 2 : int32_t aJSPluginID)
2123 : : nsIContentParent()
2124 : , mSubprocess(nullptr)
2125 : , mLaunchTS(TimeStamp::Now())
2126 : , mActivateTS(TimeStamp::Now())
2127 : , mOpener(aOpener)
2128 : , mRemoteType(aRemoteType)
2129 : , mChildID(gContentChildID++)
2130 : , mGeolocationWatchID(-1)
2131 : , mJSPluginID(aJSPluginID)
2132 : , mNumDestroyingTabs(0)
2133 : , mIsAvailable(true)
2134 : , mIsAlive(true)
2135 2 : , mIsForBrowser(!mRemoteType.IsEmpty())
2136 : , mCalledClose(false)
2137 : , mCalledKillHard(false)
2138 : , mCreatedPairedMinidumps(false)
2139 : , mShutdownPending(false)
2140 : , mIPCOpen(true)
2141 : , mIsRemoteInputEventQueueEnabled(false)
2142 : , mIsInputPriorityEventEnabled(false)
2143 42 : , mHangMonitorActor(nullptr)
2144 : {
2145 : // Insert ourselves into the global linked list of ContentParent objects.
2146 2 : if (!sContentParents) {
2147 0 : sContentParents = new LinkedList<ContentParent>();
2148 : }
2149 4 : sContentParents->insertBack(this);
2150 :
2151 : // From this point on, NS_WARNING, NS_ASSERTION, etc. should print out the
2152 : // PID along with the warning.
2153 2 : nsDebugImpl::SetMultiprocessMode("Parent");
2154 :
2155 : #if defined(XP_WIN)
2156 : if (XRE_IsParentProcess()) {
2157 : audio::AudioNotificationSender::Init();
2158 : }
2159 : // Request Windows message deferral behavior on our side of the PContent
2160 : // channel. Generally only applies to the situation where we get caught in
2161 : // a deadlock with the plugin process when sending CPOWs.
2162 : GetIPCChannel()->SetChannelFlags(MessageChannel::REQUIRE_DEFERRED_MESSAGE_PROTECTION);
2163 : #endif
2164 :
2165 0 : NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
2166 0 : bool isFile = mRemoteType.EqualsLiteral(FILE_REMOTE_TYPE);
2167 2 : mSubprocess = new ContentProcessHost(this, isFile);
2168 0 : }
2169 :
2170 0 : ContentParent::~ContentParent()
2171 : {
2172 0 : if (mForceKillTimer) {
2173 0 : mForceKillTimer->Cancel();
2174 : }
2175 :
2176 0 : NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
2177 :
2178 : // We should be removed from all these lists in ActorDestroy.
2179 0 : MOZ_ASSERT(!sPrivateContent || !sPrivateContent->Contains(this));
2180 0 : if (IsForJSPlugin()) {
2181 0 : MOZ_ASSERT(!sJSPluginContentParents ||
2182 : !sJSPluginContentParents->Get(mJSPluginID));
2183 : } else {
2184 0 : MOZ_ASSERT(!sBrowserContentParents ||
2185 : !sBrowserContentParents->Contains(mRemoteType) ||
2186 : !sBrowserContentParents->Get(mRemoteType)->Contains(this));
2187 : }
2188 0 : }
2189 :
2190 : void
2191 0 : ContentParent::InitInternal(ProcessPriority aInitialPriority)
2192 : {
2193 0 : Telemetry::Accumulate(Telemetry::CONTENT_PROCESS_LAUNCH_TIME_MS,
2194 2 : static_cast<uint32_t>((TimeStamp::Now() - mLaunchTS)
2195 0 : .ToMilliseconds()));
2196 :
2197 0 : XPCOMInitData xpcomInit;
2198 :
2199 0 : nsCOMPtr<nsIIOService> io(do_GetIOService());
2200 0 : MOZ_ASSERT(io, "No IO service?");
2201 3 : DebugOnly<nsresult> rv = io->GetOffline(&xpcomInit.isOffline());
2202 0 : MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed getting offline?");
2203 :
2204 2 : rv = io->GetConnectivity(&xpcomInit.isConnected());
2205 0 : MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed getting connectivity?");
2206 :
2207 0 : xpcomInit.captivePortalState() = nsICaptivePortalService::UNKNOWN;
2208 0 : nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CONTRACTID);
2209 1 : if (cps) {
2210 1 : cps->GetState(&xpcomInit.captivePortalState());
2211 : }
2212 :
2213 0 : nsIBidiKeyboard* bidi = nsContentUtils::GetBidiKeyboard();
2214 :
2215 0 : xpcomInit.isLangRTL() = false;
2216 0 : xpcomInit.haveBidiKeyboards() = false;
2217 0 : if (bidi) {
2218 1 : bidi->IsLangRTL(&xpcomInit.isLangRTL());
2219 1 : bidi->GetHaveBidiKeyboards(&xpcomInit.haveBidiKeyboards());
2220 : }
2221 :
2222 2 : nsCOMPtr<nsISpellChecker> spellChecker(do_GetService(NS_SPELLCHECKER_CONTRACTID));
2223 0 : MOZ_ASSERT(spellChecker, "No spell checker?");
2224 :
2225 0 : spellChecker->GetDictionaryList(&xpcomInit.dictionaries());
2226 :
2227 1 : LocaleService::GetInstance()->GetAppLocalesAsLangTags(xpcomInit.appLocales());
2228 0 : LocaleService::GetInstance()->GetRequestedLocales(xpcomInit.requestedLocales());
2229 :
2230 2 : nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1"));
2231 0 : MOZ_ASSERT(clipboard, "No clipboard?");
2232 :
2233 2 : rv = clipboard->SupportsSelectionClipboard(&xpcomInit.clipboardCaps().supportsSelectionClipboard());
2234 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
2235 :
2236 2 : rv = clipboard->SupportsFindClipboard(&xpcomInit.clipboardCaps().supportsFindClipboard());
2237 1 : MOZ_ASSERT(NS_SUCCEEDED(rv));
2238 :
2239 : // Let's copy the domain policy from the parent to the child (if it's active).
2240 0 : StructuredCloneData initialData;
2241 0 : nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
2242 1 : if (ssm) {
2243 0 : ssm->CloneDomainPolicy(&xpcomInit.domainPolicy());
2244 :
2245 0 : if (ParentProcessMessageManager* mm = nsFrameMessageManager::sParentProcessManager) {
2246 1 : AutoJSAPI jsapi;
2247 1 : if (NS_WARN_IF(!jsapi.Init(xpc::PrivilegedJunkScope()))) {
2248 0 : MOZ_CRASH();
2249 : }
2250 2 : JS::RootedValue init(jsapi.cx());
2251 : // We'll crash on failure, so use a IgnoredErrorResult (which also auto-suppresses
2252 : // exceptions).
2253 0 : IgnoredErrorResult rv;
2254 1 : mm->GetInitialProcessData(jsapi.cx(), &init, rv);
2255 2 : if (NS_WARN_IF(rv.Failed())) {
2256 0 : MOZ_CRASH();
2257 : }
2258 :
2259 1 : initialData.Write(jsapi.cx(), init, rv);
2260 2 : if (NS_WARN_IF(rv.Failed())) {
2261 0 : MOZ_CRASH();
2262 : }
2263 : }
2264 : }
2265 : // This is only implemented (returns a non-empty list) by MacOSX and Linux
2266 : // at present.
2267 0 : nsTArray<SystemFontListEntry> fontList;
2268 1 : gfxPlatform::GetPlatform()->ReadSystemFontList(&fontList);
2269 2 : nsTArray<LookAndFeelInt> lnfCache = LookAndFeel::GetIntCache();
2270 :
2271 : // Content processes have no permission to access profile directory, so we
2272 : // send the file URL instead.
2273 0 : StyleSheet* ucs = nsLayoutStylesheetCache::Singleton()->UserContentSheet();
2274 1 : if (ucs) {
2275 0 : SerializeURI(ucs->GetSheetURI(), xpcomInit.userContentSheetURL());
2276 : } else {
2277 1 : SerializeURI(nullptr, xpcomInit.userContentSheetURL());
2278 : }
2279 :
2280 : // 1. Build ContentDeviceData first, as it may affect some gfxVars.
2281 0 : gfxPlatform::GetPlatform()->BuildContentDeviceData(&xpcomInit.contentDeviceData());
2282 : // 2. Gather non-default gfxVars.
2283 0 : xpcomInit.gfxNonDefaultVarUpdates() = gfxVars::FetchNonDefaultVars();
2284 : // 3. Start listening for gfxVars updates, to notify content process later on.
2285 0 : gfxVars::AddReceiver(this);
2286 :
2287 0 : nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
2288 0 : if (gfxInfo) {
2289 0 : for (int32_t i = 1; i <= nsIGfxInfo::FEATURE_MAX_VALUE; ++i) {
2290 0 : int32_t status = 0;
2291 0 : nsAutoCString failureId;
2292 0 : gfxInfo->GetFeatureStatus(i, failureId, &status);
2293 0 : dom::GfxInfoFeatureStatus gfxFeatureStatus;
2294 0 : gfxFeatureStatus.feature() = i;
2295 0 : gfxFeatureStatus.status() = status;
2296 50 : gfxFeatureStatus.failureId() = failureId;
2297 25 : xpcomInit.gfxFeatureStatus().AppendElement(gfxFeatureStatus);
2298 : }
2299 : }
2300 :
2301 1 : DataStorage::GetAllChildProcessData(xpcomInit.dataStorage());
2302 :
2303 : // Send the dynamic scalar definitions to the new process.
2304 1 : TelemetryIPC::GetDynamicScalarDefinitions(xpcomInit.dynamicScalarDefs());
2305 :
2306 : // Must send screen info before send initialData
2307 1 : ScreenManager& screenManager = ScreenManager::GetSingleton();
2308 0 : screenManager.CopyScreensToRemote(this);
2309 :
2310 1 : Unused << SendSetXPCOMProcessAttributes(xpcomInit, initialData, lnfCache,
2311 : fontList);
2312 :
2313 0 : nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
2314 : nsChromeRegistryChrome* chromeRegistry =
2315 1 : static_cast<nsChromeRegistryChrome*>(registrySvc.get());
2316 0 : chromeRegistry->SendRegisteredChrome(this);
2317 :
2318 0 : if (gAppData) {
2319 0 : nsCString version(gAppData->version);
2320 0 : nsCString buildID(gAppData->buildID);
2321 0 : nsCString name(gAppData->name);
2322 0 : nsCString UAName(gAppData->UAName);
2323 0 : nsCString ID(gAppData->ID);
2324 3 : nsCString vendor(gAppData->vendor);
2325 3 : nsCString sourceURL(gAppData->sourceURL);
2326 :
2327 : // Sending all information to content process.
2328 1 : Unused << SendAppInfo(version, buildID, name, UAName, ID, vendor, sourceURL);
2329 : }
2330 :
2331 : // Send the child its remote type. On Mac, this needs to be sent prior
2332 : // to the message we send to enable the Sandbox (SendStartProcessSandbox)
2333 : // because different remote types require different sandbox privileges.
2334 0 : Unused << SendRemoteType(mRemoteType);
2335 :
2336 1 : ScriptPreloader::InitContentChild(*this);
2337 :
2338 : // Initialize the message manager (and load delayed scripts) now that we
2339 : // have established communications with the child.
2340 1 : mMessageManager->InitWithCallback(this);
2341 :
2342 : // Set the subprocess's priority. We do this early on because we're likely
2343 : // /lowering/ the process's CPU and memory priority, which it has inherited
2344 : // from this process.
2345 : //
2346 : // This call can cause us to send IPC messages to the child process, so it
2347 : // must come after the Open() call above.
2348 1 : ProcessPriorityManager::SetProcessPriority(this, aInitialPriority);
2349 :
2350 : // NB: internally, this will send an IPC message to the child
2351 : // process to get it to create the CompositorBridgeChild. This
2352 : // message goes through the regular IPC queue for this
2353 : // channel, so delivery will happen-before any other messages
2354 : // we send. The CompositorBridgeChild must be created before any
2355 : // PBrowsers are created, because they rely on the Compositor
2356 : // already being around. (Creation is async, so can't happen
2357 : // on demand.)
2358 0 : GPUProcessManager* gpm = GPUProcessManager::Get();
2359 :
2360 0 : Endpoint<PCompositorManagerChild> compositor;
2361 0 : Endpoint<PImageBridgeChild> imageBridge;
2362 0 : Endpoint<PVRManagerChild> vrBridge;
2363 2 : Endpoint<PVideoDecoderManagerChild> videoManager;
2364 0 : AutoTArray<uint32_t, 3> namespaces;
2365 :
2366 2 : DebugOnly<bool> opened = gpm->CreateContentBridges(OtherPid(),
2367 : &compositor,
2368 : &imageBridge,
2369 : &vrBridge,
2370 : &videoManager,
2371 2 : &namespaces);
2372 0 : MOZ_ASSERT(opened);
2373 :
2374 0 : Unused << SendInitRendering(std::move(compositor),
2375 0 : std::move(imageBridge),
2376 1 : std::move(vrBridge),
2377 1 : std::move(videoManager),
2378 : namespaces);
2379 :
2380 0 : gpm->AddListener(this);
2381 :
2382 1 : nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
2383 1 : if (sheetService) {
2384 : // This looks like a lot of work, but in a normal browser session we just
2385 : // send two loads.
2386 : //
2387 : // The URIs of the Gecko and Servo sheets should be the same, so it
2388 : // shouldn't matter which we look at.
2389 :
2390 0 : for (StyleSheet* sheet : *sheetService->AgentStyleSheets()) {
2391 0 : URIParams uri;
2392 1 : SerializeURI(sheet->GetSheetURI(), uri);
2393 1 : Unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::AGENT_SHEET);
2394 : }
2395 :
2396 1 : for (StyleSheet* sheet : *sheetService->UserStyleSheets()) {
2397 0 : URIParams uri;
2398 0 : SerializeURI(sheet->GetSheetURI(), uri);
2399 0 : Unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::USER_SHEET);
2400 : }
2401 :
2402 1 : for (StyleSheet* sheet : *sheetService->AuthorStyleSheets()) {
2403 0 : URIParams uri;
2404 0 : SerializeURI(sheet->GetSheetURI(), uri);
2405 0 : Unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::AUTHOR_SHEET);
2406 : }
2407 : }
2408 :
2409 : #if defined(XP_WIN)
2410 : // Send the info needed to join the browser process's audio session.
2411 : nsID id;
2412 : nsString sessionName;
2413 : nsString iconPath;
2414 : if (NS_SUCCEEDED(mozilla::widget::GetAudioSessionData(id, sessionName,
2415 : iconPath))) {
2416 : Unused << SendSetAudioSessionData(id, sessionName, iconPath);
2417 : }
2418 : #endif
2419 :
2420 : #ifdef MOZ_CONTENT_SANDBOX
2421 : bool shouldSandbox = true;
2422 : MaybeFileDesc brokerFd = void_t();
2423 : // XXX: Checking the pref here makes it possible to enable/disable sandboxing
2424 : // during an active session. Currently the pref is only used for testing
2425 : // purpose. If the decision is made to permanently rely on the pref, this
2426 : // should be changed so that it is required to restart firefox for the change
2427 : // of value to take effect.
2428 : shouldSandbox = IsContentSandboxEnabled();
2429 :
2430 : #ifdef XP_LINUX
2431 : if (shouldSandbox) {
2432 : MOZ_ASSERT(!mSandboxBroker);
2433 : bool isFileProcess = mRemoteType.EqualsLiteral(FILE_REMOTE_TYPE);
2434 : UniquePtr<SandboxBroker::Policy> policy =
2435 : sSandboxBrokerPolicyFactory->GetContentPolicy(Pid(), isFileProcess);
2436 : if (policy) {
2437 : brokerFd = FileDescriptor();
2438 : mSandboxBroker = SandboxBroker::Create(std::move(policy), Pid(), brokerFd);
2439 : if (!mSandboxBroker) {
2440 : KillHard("SandboxBroker::Create failed");
2441 : return;
2442 : }
2443 : MOZ_ASSERT(static_cast<const FileDescriptor&>(brokerFd).IsValid());
2444 : }
2445 : }
2446 : #endif
2447 : if (shouldSandbox && !SendSetProcessSandbox(brokerFd)) {
2448 : KillHard("SandboxInitFailed");
2449 : }
2450 : #endif
2451 :
2452 : {
2453 3 : RefPtr<ServiceWorkerRegistrar> swr = ServiceWorkerRegistrar::Get();
2454 0 : MOZ_ASSERT(swr);
2455 :
2456 2 : nsTArray<ServiceWorkerRegistrationData> registrations;
2457 1 : swr->GetRegistrations(registrations);
2458 :
2459 : // Send down to the content process the permissions for each of the
2460 : // registered service worker scopes.
2461 0 : for (auto& registration : registrations) {
2462 0 : nsCOMPtr<nsIPrincipal> principal = PrincipalInfoToPrincipal(registration.principal());
2463 0 : if (principal) {
2464 0 : TransmitPermissionsForPrincipal(principal);
2465 : }
2466 : }
2467 :
2468 2 : Unused << SendInitServiceWorkers(ServiceWorkerConfiguration(registrations));
2469 : }
2470 :
2471 : {
2472 0 : nsTArray<BlobURLRegistrationData> registrations;
2473 0 : if (BlobURLProtocolHandler::GetAllBlobURLEntries(registrations, this)) {
2474 0 : for (const BlobURLRegistrationData& registration : registrations) {
2475 0 : nsresult rv = TransmitPermissionsForPrincipal(registration.principal());
2476 0 : Unused << NS_WARN_IF(NS_FAILED(rv));
2477 : }
2478 :
2479 1 : Unused << SendInitBlobURLs(registrations);
2480 : }
2481 : }
2482 :
2483 : // Start up nsPluginHost and run FindPlugins to cache the plugin list.
2484 : // If this isn't our first content process, just send over cached list.
2485 0 : RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
2486 0 : pluginHost->SendPluginsToContent();
2487 1 : MaybeEnableRemoteInputEventQueue();
2488 1 : }
2489 :
2490 : bool
2491 0 : ContentParent::IsAlive() const
2492 : {
2493 0 : return mIsAlive;
2494 : }
2495 :
2496 : int32_t
2497 0 : ContentParent::Pid() const
2498 : {
2499 0 : if (!mSubprocess || !mSubprocess->GetChildProcessHandle()) {
2500 : return -1;
2501 : }
2502 0 : return base::GetProcId(mSubprocess->GetChildProcessHandle());
2503 : }
2504 :
2505 : mozilla::ipc::IPCResult
2506 0 : ContentParent::RecvGetGfxVars(InfallibleTArray<GfxVarUpdate>* aVars)
2507 : {
2508 : // Ensure gfxVars is initialized (for xpcshell tests).
2509 0 : gfxVars::Initialize();
2510 :
2511 0 : *aVars = gfxVars::FetchNonDefaultVars();
2512 :
2513 : // Now that content has initialized gfxVars, we can start listening for
2514 : // updates.
2515 0 : gfxVars::AddReceiver(this);
2516 0 : return IPC_OK();
2517 : }
2518 :
2519 : void
2520 0 : ContentParent::OnCompositorUnexpectedShutdown()
2521 : {
2522 0 : GPUProcessManager* gpm = GPUProcessManager::Get();
2523 :
2524 0 : Endpoint<PCompositorManagerChild> compositor;
2525 0 : Endpoint<PImageBridgeChild> imageBridge;
2526 0 : Endpoint<PVRManagerChild> vrBridge;
2527 0 : Endpoint<PVideoDecoderManagerChild> videoManager;
2528 0 : AutoTArray<uint32_t, 3> namespaces;
2529 :
2530 0 : DebugOnly<bool> opened = gpm->CreateContentBridges(
2531 : OtherPid(),
2532 : &compositor,
2533 : &imageBridge,
2534 : &vrBridge,
2535 : &videoManager,
2536 0 : &namespaces);
2537 0 : MOZ_ASSERT(opened);
2538 :
2539 0 : Unused << SendReinitRendering(
2540 0 : std::move(compositor),
2541 0 : std::move(imageBridge),
2542 0 : std::move(vrBridge),
2543 0 : std::move(videoManager),
2544 : namespaces);
2545 0 : }
2546 :
2547 : void
2548 0 : ContentParent::OnCompositorDeviceReset()
2549 : {
2550 0 : Unused << SendReinitRenderingForDeviceReset();
2551 0 : }
2552 :
2553 : PClientOpenWindowOpParent*
2554 0 : ContentParent::AllocPClientOpenWindowOpParent(const ClientOpenWindowArgs& aArgs)
2555 : {
2556 0 : return AllocClientOpenWindowOpParent(aArgs);
2557 : }
2558 :
2559 : bool
2560 0 : ContentParent::DeallocPClientOpenWindowOpParent(PClientOpenWindowOpParent* aActor)
2561 : {
2562 0 : return DeallocClientOpenWindowOpParent(aActor);
2563 : }
2564 :
2565 : void
2566 0 : ContentParent::MaybeEnableRemoteInputEventQueue()
2567 : {
2568 1 : MOZ_ASSERT(!mIsRemoteInputEventQueueEnabled);
2569 1 : if (!IsInputEventQueueSupported()) {
2570 : return;
2571 : }
2572 0 : mIsRemoteInputEventQueueEnabled = true;
2573 1 : Unused << SendSetInputEventQueueEnabled();
2574 1 : SetInputPriorityEventEnabled(true);
2575 : }
2576 :
2577 : void
2578 0 : ContentParent::SetInputPriorityEventEnabled(bool aEnabled)
2579 : {
2580 0 : if (!IsInputEventQueueSupported() ||
2581 2 : !mIsRemoteInputEventQueueEnabled ||
2582 1 : mIsInputPriorityEventEnabled == aEnabled) {
2583 : return;
2584 : }
2585 1 : mIsInputPriorityEventEnabled = aEnabled;
2586 : // Send IPC messages to flush the pending events in the input event queue and
2587 : // the normal event queue. See PContent.ipdl for more details.
2588 0 : Unused << SendSuspendInputEventQueue();
2589 1 : Unused << SendFlushInputEventQueue();
2590 1 : Unused << SendResumeInputEventQueue();
2591 : }
2592 :
2593 : /*static*/ bool
2594 3 : ContentParent::IsInputEventQueueSupported()
2595 : {
2596 : static bool sSupported = false;
2597 : static bool sInitialized = false;
2598 0 : if (!sInitialized) {
2599 0 : MOZ_ASSERT(Preferences::IsServiceAvailable());
2600 1 : sSupported = Preferences::GetBool("input_event_queue.supported", false);
2601 0 : sInitialized = true;
2602 : }
2603 3 : return sSupported;
2604 : }
2605 :
2606 : void
2607 0 : ContentParent::OnVarChanged(const GfxVarUpdate& aVar)
2608 : {
2609 0 : if (!mIPCOpen) {
2610 : return;
2611 : }
2612 0 : Unused << SendVarUpdate(aVar);
2613 : }
2614 :
2615 : mozilla::ipc::IPCResult
2616 0 : ContentParent::RecvReadFontList(InfallibleTArray<FontListEntry>* retValue)
2617 : {
2618 : #ifdef ANDROID
2619 : gfxAndroidPlatform::GetPlatform()->GetSystemFontList(retValue);
2620 : #endif
2621 0 : return IPC_OK();
2622 : }
2623 :
2624 : mozilla::ipc::IPCResult
2625 0 : ContentParent::RecvSetClipboard(const IPCDataTransfer& aDataTransfer,
2626 : const bool& aIsPrivateData,
2627 : const IPC::Principal& aRequestingPrincipal,
2628 : const uint32_t& aContentPolicyType,
2629 : const int32_t& aWhichClipboard)
2630 : {
2631 : nsresult rv;
2632 0 : nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
2633 0 : NS_ENSURE_SUCCESS(rv, IPC_OK());
2634 :
2635 : nsCOMPtr<nsITransferable> trans =
2636 0 : do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
2637 0 : NS_ENSURE_SUCCESS(rv, IPC_OK());
2638 0 : trans->Init(nullptr);
2639 :
2640 0 : rv = nsContentUtils::IPCTransferableToTransferable(aDataTransfer,
2641 : aIsPrivateData,
2642 : aRequestingPrincipal,
2643 : aContentPolicyType,
2644 : trans, this, nullptr);
2645 0 : NS_ENSURE_SUCCESS(rv, IPC_OK());
2646 :
2647 0 : clipboard->SetData(trans, nullptr, aWhichClipboard);
2648 : return IPC_OK();
2649 : }
2650 :
2651 : mozilla::ipc::IPCResult
2652 0 : ContentParent::RecvGetClipboard(nsTArray<nsCString>&& aTypes,
2653 : const int32_t& aWhichClipboard,
2654 : IPCDataTransfer* aDataTransfer)
2655 : {
2656 : nsresult rv;
2657 0 : nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
2658 0 : NS_ENSURE_SUCCESS(rv, IPC_OK());
2659 :
2660 0 : nsCOMPtr<nsITransferable> trans = do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
2661 0 : NS_ENSURE_SUCCESS(rv, IPC_OK());
2662 0 : trans->Init(nullptr);
2663 :
2664 0 : for (uint32_t t = 0; t < aTypes.Length(); t++) {
2665 0 : trans->AddDataFlavor(aTypes[t].get());
2666 : }
2667 :
2668 0 : clipboard->GetData(trans, aWhichClipboard);
2669 0 : nsContentUtils::TransferableToIPCTransferable(trans, aDataTransfer,
2670 0 : true, nullptr, this);
2671 : return IPC_OK();
2672 : }
2673 :
2674 : mozilla::ipc::IPCResult
2675 0 : ContentParent::RecvEmptyClipboard(const int32_t& aWhichClipboard)
2676 : {
2677 : nsresult rv;
2678 0 : nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
2679 0 : NS_ENSURE_SUCCESS(rv, IPC_OK());
2680 :
2681 0 : clipboard->EmptyClipboard(aWhichClipboard);
2682 :
2683 : return IPC_OK();
2684 : }
2685 :
2686 : mozilla::ipc::IPCResult
2687 0 : ContentParent::RecvClipboardHasType(nsTArray<nsCString>&& aTypes,
2688 : const int32_t& aWhichClipboard,
2689 : bool* aHasType)
2690 : {
2691 : nsresult rv;
2692 0 : nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
2693 0 : NS_ENSURE_SUCCESS(rv, IPC_OK());
2694 :
2695 0 : const char** typesChrs = new const char *[aTypes.Length()];
2696 0 : for (uint32_t t = 0; t < aTypes.Length(); t++) {
2697 0 : typesChrs[t] = aTypes[t].get();
2698 : }
2699 :
2700 0 : clipboard->HasDataMatchingFlavors(typesChrs, aTypes.Length(),
2701 0 : aWhichClipboard, aHasType);
2702 :
2703 0 : delete [] typesChrs;
2704 : return IPC_OK();
2705 : }
2706 :
2707 : mozilla::ipc::IPCResult
2708 0 : ContentParent::RecvPlaySound(const URIParams& aURI)
2709 : {
2710 0 : nsCOMPtr<nsIURI> soundURI = DeserializeURI(aURI);
2711 0 : bool isChrome = false;
2712 : // If the check here fails, it can only mean that this message was spoofed.
2713 0 : if (!soundURI || NS_FAILED(soundURI->SchemeIs("chrome", &isChrome)) || !isChrome) {
2714 : // PlaySound only accepts a valid chrome URI.
2715 0 : return IPC_FAIL_NO_REASON(this);
2716 : }
2717 0 : nsCOMPtr<nsIURL> soundURL(do_QueryInterface(soundURI));
2718 0 : if (!soundURL) {
2719 : return IPC_OK();
2720 : }
2721 :
2722 : nsresult rv;
2723 0 : nsCOMPtr<nsISound> sound(do_GetService(NS_SOUND_CID, &rv));
2724 0 : NS_ENSURE_SUCCESS(rv, IPC_OK());
2725 :
2726 0 : sound->Play(soundURL);
2727 :
2728 : return IPC_OK();
2729 : }
2730 :
2731 : mozilla::ipc::IPCResult
2732 0 : ContentParent::RecvBeep()
2733 : {
2734 : nsresult rv;
2735 0 : nsCOMPtr<nsISound> sound(do_GetService(NS_SOUND_CID, &rv));
2736 0 : NS_ENSURE_SUCCESS(rv, IPC_OK());
2737 :
2738 0 : sound->Beep();
2739 :
2740 : return IPC_OK();
2741 : }
2742 :
2743 : mozilla::ipc::IPCResult
2744 0 : ContentParent::RecvPlayEventSound(const uint32_t& aEventId)
2745 : {
2746 : nsresult rv;
2747 0 : nsCOMPtr<nsISound> sound(do_GetService(NS_SOUND_CID, &rv));
2748 0 : NS_ENSURE_SUCCESS(rv, IPC_OK());
2749 :
2750 0 : sound->PlayEventSound(aEventId);
2751 :
2752 : return IPC_OK();
2753 : }
2754 :
2755 : mozilla::ipc::IPCResult
2756 0 : ContentParent::RecvGetSystemColors(const uint32_t& colorsCount,
2757 : InfallibleTArray<uint32_t>* colors)
2758 : {
2759 : #ifdef MOZ_WIDGET_ANDROID
2760 : NS_ASSERTION(AndroidBridge::Bridge() != nullptr, "AndroidBridge is not available");
2761 : if (AndroidBridge::Bridge() == nullptr) {
2762 : // Do not fail - the colors won't be right, but it's not critical
2763 : return IPC_OK();
2764 : }
2765 :
2766 : colors->AppendElements(colorsCount);
2767 :
2768 : // The array elements correspond to the members of AndroidSystemColors structure,
2769 : // so just pass the pointer to the elements buffer
2770 : AndroidBridge::Bridge()->GetSystemColors((AndroidSystemColors*)colors->Elements());
2771 : #endif
2772 0 : return IPC_OK();
2773 : }
2774 :
2775 : mozilla::ipc::IPCResult
2776 0 : ContentParent::RecvGetIconForExtension(const nsCString& aFileExt,
2777 : const uint32_t& aIconSize,
2778 : InfallibleTArray<uint8_t>* bits)
2779 : {
2780 : #ifdef MOZ_WIDGET_ANDROID
2781 : NS_ASSERTION(AndroidBridge::Bridge() != nullptr, "AndroidBridge is not available");
2782 : if (AndroidBridge::Bridge() == nullptr) {
2783 : // Do not fail - just no icon will be shown
2784 : return IPC_OK();
2785 : }
2786 :
2787 : bits->AppendElements(aIconSize * aIconSize * 4);
2788 :
2789 : AndroidBridge::Bridge()->GetIconForExtension(aFileExt, aIconSize, bits->Elements());
2790 : #endif
2791 0 : return IPC_OK();
2792 : }
2793 :
2794 : mozilla::ipc::IPCResult
2795 0 : ContentParent::RecvGetShowPasswordSetting(bool* showPassword)
2796 : {
2797 : // default behavior is to show the last password character
2798 0 : *showPassword = true;
2799 : #ifdef MOZ_WIDGET_ANDROID
2800 : NS_ASSERTION(AndroidBridge::Bridge() != nullptr, "AndroidBridge is not available");
2801 :
2802 : *showPassword = java::GeckoAppShell::GetShowPasswordSetting();
2803 : #endif
2804 0 : return IPC_OK();
2805 : }
2806 :
2807 : mozilla::ipc::IPCResult
2808 1 : ContentParent::RecvFirstIdle()
2809 : {
2810 : // When the ContentChild goes idle, it sends us a FirstIdle message
2811 : // which we use as a good time to signal the PreallocatedProcessManager
2812 : // that it can start allocating processes from now on.
2813 1 : PreallocatedProcessManager::RemoveBlocker(this);
2814 1 : return IPC_OK();
2815 : }
2816 :
2817 : // We want ContentParent to show up in CC logs for debugging purposes, but we
2818 : // don't actually cycle collect it.
2819 0 : NS_IMPL_CYCLE_COLLECTION_0(ContentParent)
2820 :
2821 636 : NS_IMPL_CYCLE_COLLECTING_ADDREF(ContentParent)
2822 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(ContentParent)
2823 :
2824 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ContentParent)
2825 0 : NS_INTERFACE_MAP_ENTRY(nsIContentParent)
2826 0 : NS_INTERFACE_MAP_ENTRY(nsIObserver)
2827 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionCallback)
2828 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionErrorCallback)
2829 0 : NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
2830 14 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
2831 80 : NS_INTERFACE_MAP_END
2832 :
2833 : NS_IMETHODIMP
2834 63 : ContentParent::Observe(nsISupports* aSubject,
2835 : const char* aTopic,
2836 : const char16_t* aData)
2837 : {
2838 126 : if (mSubprocess && (!strcmp(aTopic, "profile-before-change") ||
2839 63 : !strcmp(aTopic, "xpcom-shutdown"))) {
2840 : // Make sure that our process will get scheduled.
2841 : ProcessPriorityManager::SetProcessPriority(this,
2842 0 : PROCESS_PRIORITY_FOREGROUND);
2843 :
2844 : // Okay to call ShutDownProcess multiple times.
2845 0 : ShutDownProcess(SEND_SHUTDOWN_MESSAGE);
2846 :
2847 : // Wait for shutdown to complete, so that we receive any shutdown
2848 : // data (e.g. telemetry) from the child before we quit.
2849 : // This loop terminate prematurely based on mForceKillTimer.
2850 0 : SpinEventLoopUntil([&]() { return !mIPCOpen || mCalledKillHard; });
2851 0 : NS_ASSERTION(!mSubprocess, "Close should have nulled mSubprocess");
2852 : }
2853 :
2854 63 : if (!mIsAlive || !mSubprocess)
2855 : return NS_OK;
2856 :
2857 : // listening for memory pressure event
2858 63 : if (!strcmp(aTopic, "memory-pressure")) {
2859 0 : Unused << SendFlushMemory(nsDependentString(aData));
2860 : }
2861 63 : else if (!strcmp(aTopic, "nsPref:changed")) {
2862 : // A pref changed. If it's not on the blacklist, inform child processes.
2863 : #define BLACKLIST_ENTRY(s) { s, (sizeof(s)/sizeof(char16_t)) - 1 }
2864 : struct BlacklistEntry {
2865 : const char16_t* mPrefBranch;
2866 : size_t mLen;
2867 : };
2868 : // These prefs are not useful in child processes.
2869 : static const BlacklistEntry sContentPrefBranchBlacklist[] = {
2870 : BLACKLIST_ENTRY(u"app.update.lastUpdateTime."),
2871 : BLACKLIST_ENTRY(u"datareporting.policy."),
2872 : BLACKLIST_ENTRY(u"browser.safebrowsing.provider."),
2873 : BLACKLIST_ENTRY(u"extensions.getAddons.cache."),
2874 : BLACKLIST_ENTRY(u"media.gmp-manager."),
2875 : BLACKLIST_ENTRY(u"media.gmp-gmpopenh264."),
2876 : };
2877 : #undef BLACKLIST_ENTRY
2878 :
2879 0 : for (const auto& entry : sContentPrefBranchBlacklist) {
2880 373 : if (NS_strncmp(entry.mPrefBranch, aData, entry.mLen) == 0) {
2881 1 : return NS_OK;
2882 : }
2883 : }
2884 :
2885 : // We know prefs are ASCII here.
2886 0 : NS_LossyConvertUTF16toASCII strData(aData);
2887 :
2888 0 : Pref pref(strData, /* isLocked */ false, null_t(), null_t());
2889 0 : Preferences::GetPreference(&pref);
2890 62 : if (!SendPreferenceUpdate(pref)) {
2891 0 : return NS_ERROR_NOT_AVAILABLE;
2892 : }
2893 : }
2894 0 : else if (!strcmp(aTopic, NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC)) {
2895 0 : NS_ConvertUTF16toUTF8 dataStr(aData);
2896 0 : const char *offline = dataStr.get();
2897 0 : if (!SendSetOffline(!strcmp(offline, "true") ? true : false)) {
2898 0 : return NS_ERROR_NOT_AVAILABLE;
2899 : }
2900 : }
2901 0 : else if (!strcmp(aTopic, NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC)) {
2902 0 : if (!SendSetConnectivity(NS_LITERAL_STRING("true").Equals(aData))) {
2903 : return NS_ERROR_NOT_AVAILABLE;
2904 : }
2905 0 : } else if (!strcmp(aTopic, NS_IPC_CAPTIVE_PORTAL_SET_STATE)) {
2906 0 : nsCOMPtr<nsICaptivePortalService> cps = do_QueryInterface(aSubject);
2907 0 : MOZ_ASSERT(cps, "Should QI to a captive portal service");
2908 0 : if (!cps) {
2909 0 : return NS_ERROR_FAILURE;
2910 : }
2911 : int32_t state;
2912 0 : cps->GetState(&state);
2913 0 : if (!SendSetCaptivePortalState(state)) {
2914 : return NS_ERROR_NOT_AVAILABLE;
2915 : }
2916 : }
2917 : // listening for alert notifications
2918 0 : else if (!strcmp(aTopic, "alertfinished") ||
2919 0 : !strcmp(aTopic, "alertclickcallback") ||
2920 0 : !strcmp(aTopic, "alertshow") ||
2921 0 : !strcmp(aTopic, "alertdisablecallback") ||
2922 0 : !strcmp(aTopic, "alertsettingscallback")) {
2923 0 : if (!SendNotifyAlertsObserver(nsDependentCString(aTopic),
2924 0 : nsDependentString(aData)))
2925 : return NS_ERROR_NOT_AVAILABLE;
2926 : }
2927 0 : else if (!strcmp(aTopic, "child-gc-request")){
2928 0 : Unused << SendGarbageCollect();
2929 : }
2930 0 : else if (!strcmp(aTopic, "child-cc-request")){
2931 0 : Unused << SendCycleCollect();
2932 : }
2933 0 : else if (!strcmp(aTopic, "child-mmu-request")){
2934 0 : Unused << SendMinimizeMemoryUsage();
2935 : }
2936 0 : else if (!strcmp(aTopic, "child-ghost-request")){
2937 0 : Unused << SendUnlinkGhosts();
2938 : }
2939 0 : else if (!strcmp(aTopic, "last-pb-context-exited")) {
2940 0 : Unused << SendLastPrivateDocShellDestroyed();
2941 : }
2942 : #ifdef ACCESSIBILITY
2943 0 : else if (aData && !strcmp(aTopic, "a11y-init-or-shutdown")) {
2944 0 : if (*aData == '1') {
2945 : // Make sure accessibility is running in content process when
2946 : // accessibility gets initiated in chrome process.
2947 : #if defined(XP_WIN)
2948 : // Don't init content a11y if we detect an incompat version of JAWS in use.
2949 : if (!mozilla::a11y::Compatibility::IsOldJAWS()) {
2950 : Unused << SendActivateA11y(::GetCurrentThreadId(),
2951 : a11y::AccessibleWrap::GetContentProcessIdFor(ChildID()));
2952 : }
2953 : #else
2954 0 : Unused << SendActivateA11y(0, 0);
2955 : #endif
2956 : } else {
2957 : // If possible, shut down accessibility in content process when
2958 : // accessibility gets shutdown in chrome process.
2959 0 : Unused << SendShutdownA11y();
2960 : }
2961 : }
2962 : #endif
2963 0 : else if (!strcmp(aTopic, "cacheservice:empty-cache")) {
2964 0 : Unused << SendNotifyEmptyHTTPCache();
2965 : }
2966 0 : else if (!strcmp(aTopic, "intl:app-locales-changed")) {
2967 0 : nsTArray<nsCString> appLocales;
2968 0 : LocaleService::GetInstance()->GetAppLocalesAsLangTags(appLocales);
2969 0 : Unused << SendUpdateAppLocales(appLocales);
2970 : }
2971 0 : else if (!strcmp(aTopic, "intl:requested-locales-changed")) {
2972 0 : nsTArray<nsCString> requestedLocales;
2973 0 : LocaleService::GetInstance()->GetRequestedLocales(requestedLocales);
2974 0 : Unused << SendUpdateRequestedLocales(requestedLocales);
2975 : }
2976 0 : else if (!strcmp(aTopic, "cookie-changed") ||
2977 0 : !strcmp(aTopic, "private-cookie-changed")) {
2978 0 : if (!aData) {
2979 0 : return NS_ERROR_UNEXPECTED;
2980 : }
2981 0 : PNeckoParent *neckoParent = LoneManagedOrNullAsserts(ManagedPNeckoParent());
2982 0 : if (!neckoParent) {
2983 : return NS_OK;
2984 : }
2985 0 : PCookieServiceParent *csParent = LoneManagedOrNullAsserts(neckoParent->ManagedPCookieServiceParent());
2986 0 : if (!csParent) {
2987 : return NS_OK;
2988 : }
2989 0 : auto *cs = static_cast<CookieServiceParent*>(csParent);
2990 : // Do not push these cookie updates to the same process they originated from.
2991 0 : if (cs->ProcessingCookie()) {
2992 : return NS_OK;
2993 : }
2994 0 : if (!nsCRT::strcmp(aData, u"batch-deleted")) {
2995 0 : nsCOMPtr<nsIArray> cookieList = do_QueryInterface(aSubject);
2996 0 : NS_ASSERTION(cookieList, "couldn't get cookie list");
2997 0 : cs->RemoveBatchDeletedCookies(cookieList);
2998 : return NS_OK;
2999 : }
3000 :
3001 0 : if (!nsCRT::strcmp(aData, u"cleared")) {
3002 0 : cs->RemoveAll();
3003 0 : return NS_OK;
3004 : }
3005 :
3006 0 : nsCOMPtr<nsICookie> xpcCookie = do_QueryInterface(aSubject);
3007 0 : NS_ASSERTION(xpcCookie, "couldn't get cookie");
3008 0 : if (!nsCRT::strcmp(aData, u"deleted")) {
3009 0 : cs->RemoveCookie(xpcCookie);
3010 0 : } else if ((!nsCRT::strcmp(aData, u"added")) ||
3011 0 : (!nsCRT::strcmp(aData, u"changed"))) {
3012 0 : cs->AddCookie(xpcCookie);
3013 : }
3014 : }
3015 : return NS_OK;
3016 : }
3017 :
3018 : NS_IMETHODIMP
3019 0 : ContentParent::GetInterface(const nsIID& aIID, void** aResult)
3020 : {
3021 0 : NS_ENSURE_ARG_POINTER(aResult);
3022 :
3023 0 : if (aIID.Equals(NS_GET_IID(nsIMessageSender))) {
3024 3 : nsCOMPtr<nsIMessageSender> mm = GetMessageManager();
3025 1 : mm.forget(aResult);
3026 : return NS_OK;
3027 : }
3028 :
3029 : return NS_NOINTERFACE;
3030 : }
3031 :
3032 : mozilla::ipc::IPCResult
3033 0 : ContentParent::RecvInitBackground(Endpoint<PBackgroundParent>&& aEndpoint)
3034 : {
3035 1 : if (!BackgroundParent::Alloc(this, std::move(aEndpoint))) {
3036 0 : return IPC_FAIL(this, "BackgroundParent::Alloc failed");
3037 : }
3038 :
3039 : return IPC_OK();
3040 : }
3041 :
3042 : mozilla::jsipc::PJavaScriptParent *
3043 0 : ContentParent::AllocPJavaScriptParent()
3044 : {
3045 2 : MOZ_ASSERT(ManagedPJavaScriptParent().IsEmpty());
3046 1 : return nsIContentParent::AllocPJavaScriptParent();
3047 : }
3048 :
3049 : bool
3050 0 : ContentParent::DeallocPJavaScriptParent(PJavaScriptParent *parent)
3051 : {
3052 0 : return nsIContentParent::DeallocPJavaScriptParent(parent);
3053 : }
3054 :
3055 : PBrowserParent*
3056 0 : ContentParent::AllocPBrowserParent(const TabId& aTabId,
3057 : const TabId& aSameTabGroupAs,
3058 : const IPCTabContext& aContext,
3059 : const uint32_t& aChromeFlags,
3060 : const ContentParentId& aCpId,
3061 : const bool& aIsForBrowser)
3062 : {
3063 0 : return nsIContentParent::AllocPBrowserParent(aTabId,
3064 : aSameTabGroupAs,
3065 : aContext,
3066 : aChromeFlags,
3067 : aCpId,
3068 0 : aIsForBrowser);
3069 : }
3070 :
3071 : bool
3072 0 : ContentParent::DeallocPBrowserParent(PBrowserParent* frame)
3073 : {
3074 0 : return nsIContentParent::DeallocPBrowserParent(frame);
3075 : }
3076 :
3077 : mozilla::ipc::IPCResult
3078 0 : ContentParent::RecvPBrowserConstructor(PBrowserParent* actor,
3079 : const TabId& tabId,
3080 : const TabId& sameTabGroupAs,
3081 : const IPCTabContext& context,
3082 : const uint32_t& chromeFlags,
3083 : const ContentParentId& cpId,
3084 : const bool& isForBrowser)
3085 : {
3086 : return nsIContentParent::RecvPBrowserConstructor(actor,
3087 : tabId,
3088 : sameTabGroupAs,
3089 : context,
3090 : chromeFlags,
3091 : cpId,
3092 0 : isForBrowser);
3093 : }
3094 :
3095 : PIPCBlobInputStreamParent*
3096 0 : ContentParent::AllocPIPCBlobInputStreamParent(const nsID& aID,
3097 : const uint64_t& aSize)
3098 : {
3099 0 : return nsIContentParent::AllocPIPCBlobInputStreamParent(aID, aSize);
3100 : }
3101 :
3102 : bool
3103 0 : ContentParent::DeallocPIPCBlobInputStreamParent(PIPCBlobInputStreamParent* aActor)
3104 : {
3105 0 : return nsIContentParent::DeallocPIPCBlobInputStreamParent(aActor);
3106 : }
3107 :
3108 : mozilla::PRemoteSpellcheckEngineParent *
3109 0 : ContentParent::AllocPRemoteSpellcheckEngineParent()
3110 : {
3111 0 : mozilla::RemoteSpellcheckEngineParent *parent = new mozilla::RemoteSpellcheckEngineParent();
3112 0 : return parent;
3113 : }
3114 :
3115 : bool
3116 0 : ContentParent::DeallocPRemoteSpellcheckEngineParent(PRemoteSpellcheckEngineParent *parent)
3117 : {
3118 0 : delete parent;
3119 0 : return true;
3120 : }
3121 :
3122 : /* static */ void
3123 0 : ContentParent::ForceKillTimerCallback(nsITimer* aTimer, void* aClosure)
3124 : {
3125 : // We don't want to time out the content process during XPCShell tests. This
3126 : // is the easiest way to ensure that.
3127 0 : if (PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR")) {
3128 : return;
3129 : }
3130 :
3131 0 : auto self = static_cast<ContentParent*>(aClosure);
3132 0 : self->KillHard("ShutDownKill");
3133 : }
3134 :
3135 : // WARNING: aReason appears in telemetry, so any new value passed in requires
3136 : // data review.
3137 : void
3138 0 : ContentParent::KillHard(const char* aReason)
3139 : {
3140 0 : AUTO_PROFILER_LABEL("ContentParent::KillHard", OTHER);
3141 :
3142 : // On Windows, calling KillHard multiple times causes problems - the
3143 : // process handle becomes invalid on the first call, causing a second call
3144 : // to crash our process - more details in bug 890840.
3145 0 : if (mCalledKillHard) {
3146 0 : return;
3147 : }
3148 0 : mCalledKillHard = true;
3149 0 : mForceKillTimer = nullptr;
3150 :
3151 0 : MessageChannel* channel = GetIPCChannel();
3152 0 : if (channel) {
3153 0 : channel->SetInKillHardShutdown();
3154 : }
3155 :
3156 : // We're about to kill the child process associated with this content.
3157 : // Something has gone wrong to get us here, so we generate a minidump
3158 : // of the parent and child for submission to the crash server.
3159 0 : if (mCrashReporter) {
3160 : // GeneratePairedMinidump creates two minidumps for us - the main
3161 : // one is for the content process we're about to kill, and the other
3162 : // one is for the main browser process. That second one is the extra
3163 : // minidump tagging along, so we have to tell the crash reporter that
3164 : // it exists and is being appended.
3165 0 : nsAutoCString additionalDumps("browser");
3166 0 : mCrashReporter->AddNote(
3167 0 : NS_LITERAL_CSTRING("additional_minidumps"),
3168 0 : additionalDumps);
3169 0 : nsDependentCString reason(aReason);
3170 0 : mCrashReporter->AddNote(
3171 0 : NS_LITERAL_CSTRING("ipc_channel_error"),
3172 0 : reason);
3173 :
3174 0 : Telemetry::Accumulate(Telemetry::SUBPROCESS_KILL_HARD, reason, 1);
3175 :
3176 0 : RefPtr<ContentParent> self = this;
3177 0 : std::function<void(bool)> callback = [self](bool aResult) {
3178 0 : self->OnGenerateMinidumpComplete(aResult);
3179 0 : };
3180 : // Generate the report and insert into the queue for submittal.
3181 0 : mCrashReporter->GenerateMinidumpAndPair(Process(),
3182 : nullptr,
3183 0 : NS_LITERAL_CSTRING("browser"),
3184 0 : std::move(callback),
3185 0 : true);
3186 : return;
3187 : }
3188 :
3189 0 : OnGenerateMinidumpComplete(false);
3190 : }
3191 :
3192 : void
3193 0 : ContentParent::OnGenerateMinidumpComplete(bool aDumpResult)
3194 : {
3195 0 : if (mCrashReporter && aDumpResult) {
3196 : // CrashReporterHost::GenerateMinidumpAndPair() is successful.
3197 0 : mCreatedPairedMinidumps = mCrashReporter->FinalizeCrashReport();
3198 : }
3199 :
3200 : Unused << aDumpResult; // Don't care about result if no minidump was requested.
3201 :
3202 : ProcessHandle otherProcessHandle;
3203 0 : if (!base::OpenProcessHandle(OtherPid(), &otherProcessHandle)) {
3204 0 : NS_ERROR("Failed to open child process when attempting kill.");
3205 0 : return;
3206 : }
3207 :
3208 0 : if (!KillProcess(otherProcessHandle, base::PROCESS_END_KILLED_BY_USER,
3209 : false)) {
3210 0 : NS_WARNING("failed to kill subprocess!");
3211 : }
3212 :
3213 0 : if (mSubprocess) {
3214 0 : mSubprocess->SetAlreadyDead();
3215 : }
3216 :
3217 : // EnsureProcessTerminated has responsibilty for closing otherProcessHandle.
3218 0 : XRE_GetIOMessageLoop()->PostTask(
3219 0 : NewRunnableFunction("EnsureProcessTerminatedRunnable",
3220 : &ProcessWatcher::EnsureProcessTerminated,
3221 0 : otherProcessHandle, /*force=*/true));
3222 : }
3223 :
3224 : void
3225 0 : ContentParent::FriendlyName(nsAString& aName, bool aAnonymize)
3226 : {
3227 0 : aName.Truncate();
3228 0 : if (mIsForBrowser) {
3229 0 : aName.AssignLiteral("Browser");
3230 0 : } else if (aAnonymize) {
3231 0 : aName.AssignLiteral("<anonymized-name>");
3232 : } else {
3233 0 : aName.AssignLiteral("???");
3234 : }
3235 0 : }
3236 :
3237 : mozilla::ipc::IPCResult
3238 0 : ContentParent::RecvInitCrashReporter(Shmem&& aShmem, const NativeThreadId& aThreadId)
3239 : {
3240 2 : mCrashReporter = MakeUnique<CrashReporterHost>(
3241 : GeckoProcessType_Content,
3242 : aShmem,
3243 0 : aThreadId);
3244 :
3245 1 : return IPC_OK();
3246 : }
3247 :
3248 : hal_sandbox::PHalParent*
3249 0 : ContentParent::AllocPHalParent()
3250 : {
3251 1 : return hal_sandbox::CreateHalParent();
3252 : }
3253 :
3254 : bool
3255 0 : ContentParent::DeallocPHalParent(hal_sandbox::PHalParent* aHal)
3256 : {
3257 0 : delete aHal;
3258 0 : return true;
3259 : }
3260 :
3261 : devtools::PHeapSnapshotTempFileHelperParent*
3262 0 : ContentParent::AllocPHeapSnapshotTempFileHelperParent()
3263 : {
3264 0 : return devtools::HeapSnapshotTempFileHelperParent::Create();
3265 : }
3266 :
3267 : bool
3268 0 : ContentParent::DeallocPHeapSnapshotTempFileHelperParent(
3269 : devtools::PHeapSnapshotTempFileHelperParent* aHeapSnapshotHelper)
3270 : {
3271 0 : delete aHeapSnapshotHelper;
3272 0 : return true;
3273 : }
3274 :
3275 : bool
3276 0 : ContentParent::SendRequestMemoryReport(const uint32_t& aGeneration,
3277 : const bool& aAnonymize,
3278 : const bool& aMinimizeMemoryUsage,
3279 : const MaybeFileDesc& aDMDFile)
3280 : {
3281 : // This automatically cancels the previous request.
3282 0 : mMemoryReportRequest = MakeUnique<MemoryReportRequestHost>(aGeneration);
3283 0 : Unused << PContentParent::SendRequestMemoryReport(
3284 : aGeneration,
3285 : aAnonymize,
3286 : aMinimizeMemoryUsage,
3287 : aDMDFile);
3288 0 : return IPC_OK();
3289 : }
3290 :
3291 : mozilla::ipc::IPCResult
3292 0 : ContentParent::RecvAddMemoryReport(const MemoryReport& aReport)
3293 : {
3294 0 : if (mMemoryReportRequest) {
3295 0 : mMemoryReportRequest->RecvReport(aReport);
3296 : }
3297 0 : return IPC_OK();
3298 : }
3299 :
3300 : mozilla::ipc::IPCResult
3301 0 : ContentParent::RecvFinishMemoryReport(const uint32_t& aGeneration)
3302 : {
3303 0 : if (mMemoryReportRequest) {
3304 0 : mMemoryReportRequest->Finish(aGeneration);
3305 0 : mMemoryReportRequest = nullptr;
3306 : }
3307 0 : return IPC_OK();
3308 : }
3309 :
3310 : mozilla::ipc::IPCResult
3311 0 : ContentParent::RecvAddPerformanceMetrics(nsTArray<PerformanceInfo>&& aMetrics)
3312 : {
3313 0 : if (!mozilla::dom::DOMPrefs::SchedulerLoggingEnabled()) {
3314 : // The pref is off, we should not get a performance metrics from the content
3315 : // child
3316 : return IPC_OK();
3317 : }
3318 0 : Unused << NS_WARN_IF(NS_FAILED(mozilla::NotifyPerformanceInfo(aMetrics)));
3319 : return IPC_OK();
3320 : }
3321 :
3322 : PCycleCollectWithLogsParent*
3323 0 : ContentParent::AllocPCycleCollectWithLogsParent(const bool& aDumpAllTraces,
3324 : const FileDescriptor& aGCLog,
3325 : const FileDescriptor& aCCLog)
3326 : {
3327 0 : MOZ_CRASH("Don't call this; use ContentParent::CycleCollectWithLogs");
3328 : }
3329 :
3330 : bool
3331 0 : ContentParent::DeallocPCycleCollectWithLogsParent(PCycleCollectWithLogsParent* aActor)
3332 : {
3333 0 : delete aActor;
3334 0 : return true;
3335 : }
3336 :
3337 : bool
3338 0 : ContentParent::CycleCollectWithLogs(bool aDumpAllTraces,
3339 : nsICycleCollectorLogSink* aSink,
3340 : nsIDumpGCAndCCLogsCallback* aCallback)
3341 : {
3342 0 : return CycleCollectWithLogsParent::AllocAndSendConstructor(this,
3343 : aDumpAllTraces,
3344 : aSink,
3345 0 : aCallback);
3346 : }
3347 :
3348 : PTestShellParent*
3349 0 : ContentParent::AllocPTestShellParent()
3350 : {
3351 0 : return new TestShellParent();
3352 : }
3353 :
3354 : bool
3355 0 : ContentParent::DeallocPTestShellParent(PTestShellParent* shell)
3356 : {
3357 0 : delete shell;
3358 0 : return true;
3359 : }
3360 :
3361 : PScriptCacheParent*
3362 0 : ContentParent::AllocPScriptCacheParent(const FileDescOrError& cacheFile, const bool& wantCacheData)
3363 : {
3364 2 : return new loader::ScriptCacheParent(wantCacheData);
3365 : }
3366 :
3367 : bool
3368 0 : ContentParent::DeallocPScriptCacheParent(PScriptCacheParent* cache)
3369 : {
3370 1 : delete static_cast<loader::ScriptCacheParent*>(cache);
3371 1 : return true;
3372 : }
3373 :
3374 : PNeckoParent*
3375 0 : ContentParent::AllocPNeckoParent()
3376 : {
3377 1 : return new NeckoParent();
3378 : }
3379 :
3380 : bool
3381 0 : ContentParent::DeallocPNeckoParent(PNeckoParent* necko)
3382 : {
3383 0 : delete necko;
3384 0 : return true;
3385 : }
3386 :
3387 : PPrintingParent*
3388 1 : ContentParent::AllocPPrintingParent()
3389 : {
3390 : #ifdef NS_PRINTING
3391 2 : if (mPrintingParent) {
3392 : // Only one PrintingParent should be created per process.
3393 : return nullptr;
3394 : }
3395 :
3396 : // Create the printing singleton for this process.
3397 2 : mPrintingParent = new PrintingParent();
3398 :
3399 : // Take another reference for IPDL code.
3400 0 : mPrintingParent.get()->AddRef();
3401 :
3402 2 : return mPrintingParent.get();
3403 : #else
3404 : MOZ_ASSERT_UNREACHABLE("Should never be created if no printing.");
3405 : return nullptr;
3406 : #endif
3407 : }
3408 :
3409 : bool
3410 0 : ContentParent::DeallocPPrintingParent(PPrintingParent* printing)
3411 : {
3412 : #ifdef NS_PRINTING
3413 0 : MOZ_RELEASE_ASSERT(mPrintingParent == printing,
3414 : "Only one PrintingParent should have been created per process.");
3415 :
3416 : // Release reference taken for IPDL code.
3417 0 : static_cast<PrintingParent*>(printing)->Release();
3418 :
3419 0 : mPrintingParent = nullptr;
3420 : #else
3421 : MOZ_ASSERT_UNREACHABLE("Should never have been created if no printing.");
3422 : #endif
3423 0 : return true;
3424 : }
3425 :
3426 : #ifdef NS_PRINTING
3427 : already_AddRefed<embedding::PrintingParent>
3428 0 : ContentParent::GetPrintingParent()
3429 : {
3430 0 : MOZ_ASSERT(mPrintingParent);
3431 :
3432 0 : RefPtr<embedding::PrintingParent> printingParent = mPrintingParent;
3433 0 : return printingParent.forget();
3434 : }
3435 : #endif
3436 :
3437 : mozilla::ipc::IPCResult
3438 0 : ContentParent::RecvInitStreamFilter(const uint64_t& aChannelId,
3439 : const nsString& aAddonId,
3440 : InitStreamFilterResolver&& aResolver)
3441 : {
3442 0 : Endpoint<PStreamFilterChild> endpoint;
3443 0 : Unused << extensions::StreamFilterParent::Create(this, aChannelId, aAddonId, &endpoint);
3444 :
3445 0 : aResolver(std::move(endpoint));
3446 :
3447 0 : return IPC_OK();
3448 : }
3449 :
3450 : PChildToParentStreamParent*
3451 0 : ContentParent::AllocPChildToParentStreamParent()
3452 : {
3453 0 : return nsIContentParent::AllocPChildToParentStreamParent();
3454 : }
3455 :
3456 : bool
3457 0 : ContentParent::DeallocPChildToParentStreamParent(PChildToParentStreamParent* aActor)
3458 : {
3459 0 : return nsIContentParent::DeallocPChildToParentStreamParent(aActor);
3460 : }
3461 :
3462 : PParentToChildStreamParent*
3463 0 : ContentParent::SendPParentToChildStreamConstructor(PParentToChildStreamParent* aActor)
3464 : {
3465 0 : return PContentParent::SendPParentToChildStreamConstructor(aActor);
3466 : }
3467 :
3468 : PParentToChildStreamParent*
3469 0 : ContentParent::AllocPParentToChildStreamParent()
3470 : {
3471 0 : return nsIContentParent::AllocPParentToChildStreamParent();
3472 : }
3473 :
3474 : bool
3475 0 : ContentParent::DeallocPParentToChildStreamParent(PParentToChildStreamParent* aActor)
3476 : {
3477 0 : return nsIContentParent::DeallocPParentToChildStreamParent(aActor);
3478 : }
3479 :
3480 : PPSMContentDownloaderParent*
3481 0 : ContentParent::AllocPPSMContentDownloaderParent(const uint32_t& aCertType)
3482 : {
3483 : RefPtr<PSMContentDownloaderParent> downloader =
3484 0 : new PSMContentDownloaderParent(aCertType);
3485 0 : return downloader.forget().take();
3486 : }
3487 :
3488 : bool
3489 0 : ContentParent::DeallocPPSMContentDownloaderParent(PPSMContentDownloaderParent* aListener)
3490 : {
3491 0 : auto* listener = static_cast<PSMContentDownloaderParent*>(aListener);
3492 0 : RefPtr<PSMContentDownloaderParent> downloader = dont_AddRef(listener);
3493 0 : return true;
3494 : }
3495 :
3496 : PExternalHelperAppParent*
3497 0 : ContentParent::AllocPExternalHelperAppParent(const OptionalURIParams& uri,
3498 : const nsCString& aMimeContentType,
3499 : const nsCString& aContentDisposition,
3500 : const uint32_t& aContentDispositionHint,
3501 : const nsString& aContentDispositionFilename,
3502 : const bool& aForceSave,
3503 : const int64_t& aContentLength,
3504 : const bool& aWasFileChannel,
3505 : const OptionalURIParams& aReferrer,
3506 : PBrowserParent* aBrowser)
3507 : {
3508 : ExternalHelperAppParent* parent =
3509 0 : new ExternalHelperAppParent(uri,
3510 0 : aContentLength,
3511 : aWasFileChannel,
3512 : aContentDisposition,
3513 : aContentDispositionHint,
3514 : aContentDispositionFilename);
3515 : parent->AddRef();
3516 : parent->Init(this,
3517 : aMimeContentType,
3518 0 : aForceSave,
3519 0 : aReferrer,
3520 : aBrowser);
3521 : return parent;
3522 : }
3523 0 :
3524 : bool
3525 0 : ContentParent::DeallocPExternalHelperAppParent(PExternalHelperAppParent* aService)
3526 0 : {
3527 0 : ExternalHelperAppParent *parent = static_cast<ExternalHelperAppParent *>(aService);
3528 : parent->Release();
3529 : return true;
3530 : }
3531 0 :
3532 : PHandlerServiceParent*
3533 0 : ContentParent::AllocPHandlerServiceParent()
3534 0 : {
3535 0 : HandlerServiceParent* actor = new HandlerServiceParent();
3536 : actor->AddRef();
3537 : return actor;
3538 : }
3539 0 :
3540 : bool
3541 0 : ContentParent::DeallocPHandlerServiceParent(PHandlerServiceParent* aHandlerServiceParent)
3542 0 : {
3543 : static_cast<HandlerServiceParent*>(aHandlerServiceParent)->Release();
3544 : return true;
3545 : }
3546 0 :
3547 : media::PMediaParent*
3548 0 : ContentParent::AllocPMediaParent()
3549 : {
3550 : return media::AllocPMediaParent();
3551 : }
3552 0 :
3553 : bool
3554 0 : ContentParent::DeallocPMediaParent(media::PMediaParent *aActor)
3555 : {
3556 : return media::DeallocPMediaParent(aActor);
3557 : }
3558 0 :
3559 : PPresentationParent*
3560 0 : ContentParent::AllocPPresentationParent()
3561 0 : {
3562 : RefPtr<PresentationParent> actor = new PresentationParent();
3563 : return actor.forget().take();
3564 : }
3565 0 :
3566 : bool
3567 : ContentParent::DeallocPPresentationParent(PPresentationParent* aActor)
3568 0 : {
3569 0 : RefPtr<PresentationParent> actor =
3570 : dont_AddRef(static_cast<PresentationParent*>(aActor));
3571 : return true;
3572 : }
3573 0 :
3574 : mozilla::ipc::IPCResult
3575 0 : ContentParent::RecvPPresentationConstructor(PPresentationParent* aActor)
3576 0 : {
3577 : if (!static_cast<PresentationParent*>(aActor)->Init(mChildID)) {
3578 : return IPC_FAIL_NO_REASON(this);
3579 : }
3580 : return IPC_OK();
3581 : }
3582 0 :
3583 : PSpeechSynthesisParent*
3584 : ContentParent::AllocPSpeechSynthesisParent()
3585 0 : {
3586 : #ifdef MOZ_WEBSPEECH
3587 : return new mozilla::dom::SpeechSynthesisParent();
3588 : #else
3589 : return nullptr;
3590 : #endif
3591 : }
3592 0 :
3593 : bool
3594 : ContentParent::DeallocPSpeechSynthesisParent(PSpeechSynthesisParent* aActor)
3595 0 : {
3596 0 : #ifdef MOZ_WEBSPEECH
3597 : delete aActor;
3598 : return true;
3599 : #else
3600 : return false;
3601 : #endif
3602 : }
3603 0 :
3604 : mozilla::ipc::IPCResult
3605 : ContentParent::RecvPSpeechSynthesisConstructor(PSpeechSynthesisParent* aActor)
3606 0 : {
3607 0 : #ifdef MOZ_WEBSPEECH
3608 : if (!static_cast<SpeechSynthesisParent*>(aActor)->SendInit()) {
3609 : return IPC_FAIL_NO_REASON(this);
3610 : }
3611 : return IPC_OK();
3612 : #else
3613 : return IPC_FAIL_NO_REASON(this);
3614 : #endif
3615 : }
3616 0 :
3617 : mozilla::ipc::IPCResult
3618 0 : ContentParent::RecvStartVisitedQuery(const URIParams& aURI)
3619 0 : {
3620 0 : nsCOMPtr<nsIURI> newURI = DeserializeURI(aURI);
3621 : if (!newURI) {
3622 0 : return IPC_FAIL_NO_REASON(this);
3623 0 : }
3624 0 : nsCOMPtr<IHistory> history = services::GetHistoryService();
3625 : if (history) {
3626 : history->RegisterVisitedCallback(newURI, nullptr);
3627 : }
3628 : return IPC_OK();
3629 : }
3630 :
3631 1 :
3632 : mozilla::ipc::IPCResult
3633 : ContentParent::RecvVisitURI(const URIParams& uri,
3634 : const OptionalURIParams& referrer,
3635 1 : const uint32_t& flags)
3636 1 : {
3637 0 : nsCOMPtr<nsIURI> ourURI = DeserializeURI(uri);
3638 : if (!ourURI) {
3639 0 : return IPC_FAIL_NO_REASON(this);
3640 0 : }
3641 1 : nsCOMPtr<nsIURI> ourReferrer = DeserializeURI(referrer);
3642 3 : nsCOMPtr<IHistory> history = services::GetHistoryService();
3643 : if (history) {
3644 : history->VisitURI(ourURI, ourReferrer, flags);
3645 : }
3646 : return IPC_OK();
3647 : }
3648 :
3649 1 :
3650 : mozilla::ipc::IPCResult
3651 : ContentParent::RecvSetURITitle(const URIParams& uri,
3652 1 : const nsString& title)
3653 1 : {
3654 0 : nsCOMPtr<nsIURI> ourURI = DeserializeURI(uri);
3655 : if (!ourURI) {
3656 0 : return IPC_FAIL_NO_REASON(this);
3657 1 : }
3658 2 : nsCOMPtr<IHistory> history = services::GetHistoryService();
3659 : if (history) {
3660 : history->SetURITitle(ourURI, title);
3661 : }
3662 : return IPC_OK();
3663 : }
3664 0 :
3665 : mozilla::ipc::IPCResult
3666 : ContentParent::RecvIsSecureURI(const uint32_t& aType,
3667 : const URIParams& aURI,
3668 : const uint32_t& aFlags,
3669 : const OriginAttributes& aOriginAttributes,
3670 0 : bool* aIsSecureURI)
3671 0 : {
3672 0 : nsCOMPtr<nsISiteSecurityService> sss(do_GetService(NS_SSSERVICE_CONTRACTID));
3673 : if (!sss) {
3674 0 : return IPC_FAIL_NO_REASON(this);
3675 0 : }
3676 0 : nsCOMPtr<nsIURI> ourURI = DeserializeURI(aURI);
3677 : if (!ourURI) {
3678 0 : return IPC_FAIL_NO_REASON(this);
3679 0 : }
3680 0 : nsresult rv = sss->IsSecureURI(aType, ourURI, aFlags, aOriginAttributes, nullptr,
3681 0 : nullptr, aIsSecureURI);
3682 : if (NS_FAILED(rv)) {
3683 : return IPC_FAIL_NO_REASON(this);
3684 : }
3685 : return IPC_OK();
3686 : }
3687 0 :
3688 : mozilla::ipc::IPCResult
3689 : ContentParent::RecvAccumulateMixedContentHSTS(const URIParams& aURI, const bool& aActive,
3690 0 : const OriginAttributes& aOriginAttributes)
3691 0 : {
3692 0 : nsCOMPtr<nsIURI> ourURI = DeserializeURI(aURI);
3693 : if (!ourURI) {
3694 0 : return IPC_FAIL_NO_REASON(this);
3695 : }
3696 : nsMixedContentBlocker::AccumulateMixedContentHSTS(ourURI, aActive, aOriginAttributes);
3697 : return IPC_OK();
3698 : }
3699 0 :
3700 : mozilla::ipc::IPCResult
3701 : ContentParent::RecvLoadURIExternal(const URIParams& uri,
3702 0 : PBrowserParent* windowContext)
3703 0 : {
3704 : nsCOMPtr<nsIExternalProtocolService> extProtService(do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
3705 : if (!extProtService) {
3706 0 : return IPC_OK();
3707 0 : }
3708 0 : nsCOMPtr<nsIURI> ourURI = DeserializeURI(uri);
3709 : if (!ourURI) {
3710 : return IPC_FAIL_NO_REASON(this);
3711 : }
3712 0 :
3713 0 : RefPtr<RemoteWindowContext> context =
3714 : new RemoteWindowContext(static_cast<TabParent*>(windowContext));
3715 : extProtService->LoadURI(ourURI, context);
3716 : return IPC_OK();
3717 : }
3718 0 :
3719 : mozilla::ipc::IPCResult
3720 : ContentParent::RecvExtProtocolChannelConnectParent(const uint32_t& registrarId)
3721 : {
3722 : nsresult rv;
3723 0 :
3724 0 : // First get the real channel created before redirect on the parent.
3725 0 : nsCOMPtr<nsIChannel> channel;
3726 : rv = NS_LinkRedirectChannels(registrarId, nullptr, getter_AddRefs(channel));
3727 0 : NS_ENSURE_SUCCESS(rv, IPC_OK());
3728 0 :
3729 : nsCOMPtr<nsIParentChannel> parent = do_QueryInterface(channel, &rv);
3730 : NS_ENSURE_SUCCESS(rv, IPC_OK());
3731 0 :
3732 0 : // The channel itself is its own (faked) parent, link it.
3733 : rv = NS_LinkRedirectChannels(registrarId, parent, getter_AddRefs(channel));
3734 : NS_ENSURE_SUCCESS(rv, IPC_OK());
3735 :
3736 : // Signal the parent channel that it's a redirect-to parent. This will
3737 : // make AsyncOpen on it do nothing (what we want).
3738 0 : // Yes, this is a bit of a hack, but I don't think it's necessary to invent
3739 : // a new interface just to set this flag on the channel.
3740 : parent->SetParentListener(nullptr);
3741 :
3742 : return IPC_OK();
3743 : }
3744 0 :
3745 : bool
3746 0 : ContentParent::HasNotificationPermission(const IPC::Principal& aPrincipal)
3747 : {
3748 : return true;
3749 : }
3750 0 :
3751 : mozilla::ipc::IPCResult
3752 0 : ContentParent::RecvShowAlert(nsIAlertNotification* aAlert)
3753 0 : {
3754 : if (!aAlert) {
3755 0 : return IPC_FAIL_NO_REASON(this);
3756 0 : }
3757 0 : nsCOMPtr<nsIPrincipal> principal;
3758 0 : nsresult rv = aAlert->GetPrincipal(getter_AddRefs(principal));
3759 : if (NS_WARN_IF(NS_FAILED(rv)) ||
3760 : !HasNotificationPermission(IPC::Principal(principal))) {
3761 :
3762 : return IPC_OK();
3763 0 : }
3764 0 :
3765 0 : nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_ALERTSERVICE_CONTRACTID));
3766 : if (sysAlerts) {
3767 : sysAlerts->ShowAlert(aAlert, this);
3768 : }
3769 : return IPC_OK();
3770 : }
3771 0 :
3772 : mozilla::ipc::IPCResult
3773 : ContentParent::RecvCloseAlert(const nsString& aName,
3774 0 : const IPC::Principal& aPrincipal)
3775 : {
3776 : if (!HasNotificationPermission(aPrincipal)) {
3777 : return IPC_OK();
3778 0 : }
3779 0 :
3780 0 : nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_ALERTSERVICE_CONTRACTID));
3781 : if (sysAlerts) {
3782 : sysAlerts->CloseAlert(aName, aPrincipal);
3783 : }
3784 :
3785 : return IPC_OK();
3786 : }
3787 0 :
3788 : mozilla::ipc::IPCResult
3789 0 : ContentParent::RecvDisableNotifications(const IPC::Principal& aPrincipal)
3790 0 : {
3791 : if (HasNotificationPermission(aPrincipal)) {
3792 0 : Unused << Notification::RemovePermission(aPrincipal);
3793 : }
3794 : return IPC_OK();
3795 : }
3796 0 :
3797 : mozilla::ipc::IPCResult
3798 0 : ContentParent::RecvOpenNotificationSettings(const IPC::Principal& aPrincipal)
3799 0 : {
3800 : if (HasNotificationPermission(aPrincipal)) {
3801 0 : Unused << Notification::OpenSettings(aPrincipal);
3802 : }
3803 : return IPC_OK();
3804 : }
3805 0 :
3806 : mozilla::ipc::IPCResult
3807 : ContentParent::RecvSyncMessage(const nsString& aMsg,
3808 : const ClonedMessageData& aData,
3809 : InfallibleTArray<CpowEntry>&& aCpows,
3810 : const IPC::Principal& aPrincipal,
3811 0 : nsTArray<StructuredCloneData>* aRetvals)
3812 0 : {
3813 : return nsIContentParent::RecvSyncMessage(aMsg, aData, std::move(aCpows),
3814 : aPrincipal, aRetvals);
3815 : }
3816 0 :
3817 : mozilla::ipc::IPCResult
3818 : ContentParent::RecvRpcMessage(const nsString& aMsg,
3819 : const ClonedMessageData& aData,
3820 : InfallibleTArray<CpowEntry>&& aCpows,
3821 : const IPC::Principal& aPrincipal,
3822 0 : nsTArray<StructuredCloneData>* aRetvals)
3823 0 : {
3824 : return nsIContentParent::RecvRpcMessage(aMsg, aData, std::move(aCpows), aPrincipal,
3825 : aRetvals);
3826 : }
3827 3 :
3828 : mozilla::ipc::IPCResult
3829 : ContentParent::RecvAsyncMessage(const nsString& aMsg,
3830 : InfallibleTArray<CpowEntry>&& aCpows,
3831 : const IPC::Principal& aPrincipal,
3832 3 : const ClonedMessageData& aData)
3833 3 : {
3834 : return nsIContentParent::RecvAsyncMessage(aMsg, std::move(aCpows), aPrincipal,
3835 : aData);
3836 : }
3837 0 :
3838 : static int32_t
3839 : AddGeolocationListener(nsIDOMGeoPositionCallback* watcher,
3840 : nsIDOMGeoPositionErrorCallback* errorCallBack,
3841 0 : bool highAccuracy)
3842 : {
3843 0 : RefPtr<Geolocation> geo = Geolocation::NonWindowSingleton();
3844 0 :
3845 0 : UniquePtr<PositionOptions> options = MakeUnique<PositionOptions>();
3846 0 : options->mTimeout = 0;
3847 0 : options->mMaximumAge = 0;
3848 : options->mEnableHighAccuracy = highAccuracy;
3849 : return geo->WatchPosition(watcher, errorCallBack, std::move(options));
3850 : }
3851 0 :
3852 : mozilla::ipc::IPCResult
3853 : ContentParent::RecvAddGeolocationListener(const IPC::Principal& aPrincipal,
3854 : const bool& aHighAccuracy)
3855 : {
3856 0 : // To ensure no geolocation updates are skipped, we always force the
3857 0 : // creation of a new listener.
3858 0 : RecvRemoveGeolocationListener();
3859 : mGeolocationWatchID = AddGeolocationListener(this, this, aHighAccuracy);
3860 : return IPC_OK();
3861 : }
3862 0 :
3863 : mozilla::ipc::IPCResult
3864 0 : ContentParent::RecvRemoveGeolocationListener()
3865 0 : {
3866 0 : if (mGeolocationWatchID != -1) {
3867 0 : RefPtr<Geolocation> geo = Geolocation::NonWindowSingleton();
3868 : geo->ClearWatch(mGeolocationWatchID);
3869 0 : mGeolocationWatchID = -1;
3870 : }
3871 : return IPC_OK();
3872 : }
3873 0 :
3874 : mozilla::ipc::IPCResult
3875 : ContentParent::RecvSetGeolocationHigherAccuracy(const bool& aEnable)
3876 : {
3877 0 : // This should never be called without a listener already present,
3878 0 : // so this check allows us to forgo securing privileges.
3879 0 : if (mGeolocationWatchID != -1) {
3880 : RecvRemoveGeolocationListener();
3881 0 : mGeolocationWatchID = AddGeolocationListener(this, this, aEnable);
3882 : }
3883 : return IPC_OK();
3884 : }
3885 0 :
3886 : NS_IMETHODIMP
3887 0 : ContentParent::HandleEvent(nsIDOMGeoPosition* postion)
3888 0 : {
3889 : Unused << SendGeolocationUpdate(postion);
3890 : return NS_OK;
3891 : }
3892 0 :
3893 : NS_IMETHODIMP
3894 0 : ContentParent::HandleEvent(PositionError* positionError)
3895 0 : {
3896 : Unused << SendGeolocationError(positionError->Code());
3897 : return NS_OK;
3898 : }
3899 0 :
3900 : nsConsoleService *
3901 0 : ContentParent::GetConsoleService()
3902 : {
3903 : if (mConsoleService) {
3904 : return mConsoleService.get();
3905 : }
3906 :
3907 : // XXXkhuey everything about this is terrible.
3908 : // Get the ConsoleService by CID rather than ContractID, so that we
3909 : // can cast the returned pointer to an nsConsoleService (rather than
3910 0 : // just an nsIConsoleService). This allows us to call the non-idl function
3911 0 : // nsConsoleService::LogMessageWithMode.
3912 0 : NS_DEFINE_CID(consoleServiceCID, NS_CONSOLESERVICE_CID);
3913 0 : nsCOMPtr<nsIConsoleService> consoleService(do_GetService(consoleServiceCID));
3914 : mConsoleService = static_cast<nsConsoleService*>(consoleService.get());
3915 : return mConsoleService.get();
3916 : }
3917 0 :
3918 : mozilla::ipc::IPCResult
3919 0 : ContentParent::RecvConsoleMessage(const nsString& aMessage)
3920 0 : {
3921 : RefPtr<nsConsoleService> consoleService = GetConsoleService();
3922 : if (!consoleService) {
3923 : return IPC_OK();
3924 0 : }
3925 0 :
3926 : RefPtr<nsConsoleMessage> msg(new nsConsoleMessage(aMessage.get()));
3927 : consoleService->LogMessageWithMode(msg, nsConsoleService::SuppressLog);
3928 : return IPC_OK();
3929 : }
3930 0 :
3931 : mozilla::ipc::IPCResult
3932 : ContentParent::RecvScriptError(const nsString& aMessage,
3933 : const nsString& aSourceName,
3934 : const nsString& aSourceLine,
3935 : const uint32_t& aLineNumber,
3936 : const uint32_t& aColNumber,
3937 : const uint32_t& aFlags,
3938 : const nsCString& aCategory,
3939 : const bool& aFromPrivateWindow)
3940 : {
3941 0 : return RecvScriptErrorInternal(aMessage, aSourceName, aSourceLine,
3942 : aLineNumber, aColNumber, aFlags,
3943 : aCategory, aFromPrivateWindow);
3944 : }
3945 0 :
3946 : mozilla::ipc::IPCResult
3947 : ContentParent::RecvScriptErrorWithStack(const nsString& aMessage,
3948 : const nsString& aSourceName,
3949 : const nsString& aSourceLine,
3950 : const uint32_t& aLineNumber,
3951 : const uint32_t& aColNumber,
3952 : const uint32_t& aFlags,
3953 : const nsCString& aCategory,
3954 : const bool& aFromPrivateWindow,
3955 : const ClonedMessageData& aFrame)
3956 : {
3957 0 : return RecvScriptErrorInternal(aMessage, aSourceName, aSourceLine,
3958 : aLineNumber, aColNumber, aFlags,
3959 : aCategory, aFromPrivateWindow, &aFrame);
3960 : }
3961 0 :
3962 : mozilla::ipc::IPCResult
3963 : ContentParent::RecvScriptErrorInternal(const nsString& aMessage,
3964 : const nsString& aSourceName,
3965 : const nsString& aSourceLine,
3966 : const uint32_t& aLineNumber,
3967 : const uint32_t& aColNumber,
3968 : const uint32_t& aFlags,
3969 : const nsCString& aCategory,
3970 : const bool& aFromPrivateWindow,
3971 0 : const ClonedMessageData* aStack)
3972 0 : {
3973 : RefPtr<nsConsoleService> consoleService = GetConsoleService();
3974 : if (!consoleService) {
3975 : return IPC_OK();
3976 0 : }
3977 :
3978 0 : nsCOMPtr<nsIScriptError> msg;
3979 0 :
3980 0 : if (aStack) {
3981 : StructuredCloneData data;
3982 0 : UnpackClonedMessageDataForParent(*aStack, data);
3983 0 :
3984 0 : AutoJSAPI jsapi;
3985 : if (NS_WARN_IF(!jsapi.Init(xpc::PrivilegedJunkScope()))) {
3986 0 : MOZ_CRASH();
3987 : }
3988 0 : JSContext* cx = jsapi.cx();
3989 0 :
3990 0 : JS::RootedValue stack(cx);
3991 0 : ErrorResult rv;
3992 0 : data.Read(cx, &stack, rv);
3993 0 : if (rv.Failed() || !stack.isObject()) {
3994 : rv.SuppressException();
3995 : return IPC_OK();
3996 0 : }
3997 0 :
3998 : JS::RootedObject stackObj(cx, &stack.toObject());
3999 0 : msg = new nsScriptErrorWithStack(stackObj);
4000 : } else {
4001 : msg = new nsScriptError();
4002 0 : }
4003 :
4004 0 : nsresult rv = msg->Init(aMessage, aSourceName, aSourceLine,
4005 0 : aLineNumber, aColNumber, aFlags,
4006 : aCategory.get(), aFromPrivateWindow);
4007 : if (NS_FAILED(rv))
4008 0 : return IPC_OK();
4009 :
4010 : consoleService->LogMessageWithMode(msg, nsConsoleService::SuppressLog);
4011 : return IPC_OK();
4012 : }
4013 0 :
4014 : mozilla::ipc::IPCResult
4015 0 : ContentParent::RecvPrivateDocShellsExist(const bool& aExist)
4016 0 : {
4017 0 : if (!sPrivateContent)
4018 0 : sPrivateContent = new nsTArray<ContentParent*>();
4019 : if (aExist) {
4020 0 : sPrivateContent->AppendElement(this);
4021 : } else {
4022 : sPrivateContent->RemoveElement(this);
4023 :
4024 : // Only fire the notification if we have private and non-private
4025 0 : // windows: if privatebrowsing.autostart is true, all windows are
4026 0 : // private.
4027 0 : if (!sPrivateContent->Length() &&
4028 0 : !Preferences::GetBool("browser.privatebrowsing.autostart")) {
4029 0 : nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
4030 0 : obs->NotifyObservers(nullptr, "last-pb-context-exited", nullptr);
4031 : delete sPrivateContent;
4032 : sPrivateContent = nullptr;
4033 0 : }
4034 : }
4035 : return IPC_OK();
4036 : }
4037 9 :
4038 : bool
4039 : ContentParent::DoLoadMessageManagerScript(const nsAString& aURL,
4040 9 : bool aRunInGlobalScope)
4041 18 : {
4042 : MOZ_ASSERT(!aRunInGlobalScope);
4043 : return SendLoadProcessScript(nsString(aURL));
4044 : }
4045 7 :
4046 : nsresult
4047 : ContentParent::DoSendAsyncMessage(JSContext* aCx,
4048 : const nsAString& aMessage,
4049 : StructuredCloneData& aHelper,
4050 : JS::Handle<JSObject *> aCpows,
4051 0 : nsIPrincipal* aPrincipal)
4052 7 : {
4053 : ClonedMessageData data;
4054 : if (!BuildClonedMessageDataForParent(this, aHelper, data)) {
4055 7 : return NS_ERROR_DOM_DATA_CLONE_ERR;
4056 7 : }
4057 0 : InfallibleTArray<CpowEntry> cpows;
4058 : jsipc::CPOWManager* mgr = GetCPOWManager();
4059 : if (aCpows && (!mgr || !mgr->Wrap(aCx, aCpows, &cpows))) {
4060 21 : return NS_ERROR_UNEXPECTED;
4061 : }
4062 : if (!SendAsyncMessage(nsString(aMessage), cpows, Principal(aPrincipal), data)) {
4063 0 : return NS_ERROR_UNEXPECTED;
4064 : }
4065 : return NS_OK;
4066 : }
4067 0 :
4068 : PIPCBlobInputStreamParent*
4069 : ContentParent::SendPIPCBlobInputStreamConstructor(PIPCBlobInputStreamParent* aActor,
4070 : const nsID& aID,
4071 0 : const uint64_t& aSize)
4072 : {
4073 : return PContentParent::SendPIPCBlobInputStreamConstructor(aActor, aID, aSize);
4074 : }
4075 1 :
4076 : PBrowserParent*
4077 : ContentParent::SendPBrowserConstructor(PBrowserParent* aActor,
4078 : const TabId& aTabId,
4079 : const TabId& aSameTabGroupAs,
4080 : const IPCTabContext& aContext,
4081 : const uint32_t& aChromeFlags,
4082 : const ContentParentId& aCpId,
4083 1 : const bool& aIsForBrowser)
4084 : {
4085 : return PContentParent::SendPBrowserConstructor(aActor,
4086 : aTabId,
4087 : aSameTabGroupAs,
4088 : aContext,
4089 0 : aChromeFlags,
4090 : aCpId,
4091 : aIsForBrowser);
4092 : }
4093 0 :
4094 : mozilla::ipc::IPCResult
4095 : ContentParent::RecvKeywordToURI(const nsCString& aKeyword,
4096 : nsString* aProviderName,
4097 : RefPtr<nsIInputStream>* aPostData,
4098 0 : OptionalURIParams* aURI)
4099 0 : {
4100 : *aPostData = nullptr;
4101 0 : *aURI = void_t();
4102 0 :
4103 : nsCOMPtr<nsIURIFixup> fixup = do_GetService(NS_URIFIXUP_CONTRACTID);
4104 : if (!fixup) {
4105 : return IPC_OK();
4106 0 : }
4107 :
4108 0 : nsCOMPtr<nsIURIFixupInfo> info;
4109 :
4110 : if (NS_FAILED(fixup->KeywordToURI(aKeyword, getter_AddRefs(*aPostData),
4111 : getter_AddRefs(info)))) {
4112 0 : return IPC_OK();
4113 : }
4114 0 : info->GetKeywordProviderName(*aProviderName);
4115 0 :
4116 0 : nsCOMPtr<nsIURI> uri;
4117 : info->GetPreferredURI(getter_AddRefs(uri));
4118 : SerializeURI(uri, *aURI);
4119 : return IPC_OK();
4120 : }
4121 0 :
4122 : mozilla::ipc::IPCResult
4123 : ContentParent::RecvNotifyKeywordSearchLoading(const nsString &aProvider,
4124 : const nsString &aKeyword)
4125 0 : {
4126 0 : #ifdef MOZ_TOOLKIT_SEARCH
4127 0 : nsCOMPtr<nsIBrowserSearchService> searchSvc = do_GetService("@mozilla.org/browser/search-service;1");
4128 0 : if (searchSvc) {
4129 0 : nsCOMPtr<nsISearchEngine> searchEngine;
4130 0 : searchSvc->GetEngineByName(aProvider, getter_AddRefs(searchEngine));
4131 0 : if (searchEngine) {
4132 : nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
4133 : if (obsSvc) {
4134 0 : // Note that "keyword-search" refers to a search via the url
4135 : // bar, not a bookmarks keyword search.
4136 : obsSvc->NotifyObservers(searchEngine, "keyword-search", aKeyword.get());
4137 : }
4138 : }
4139 0 : }
4140 : #endif
4141 : return IPC_OK();
4142 : }
4143 0 :
4144 : mozilla::ipc::IPCResult
4145 : ContentParent::RecvCopyFavicon(const URIParams& aOldURI,
4146 : const URIParams& aNewURI,
4147 : const IPC::Principal& aLoadingPrincipal,
4148 0 : const bool& aInPrivateBrowsing)
4149 0 : {
4150 : nsCOMPtr<nsIURI> oldURI = DeserializeURI(aOldURI);
4151 : if (!oldURI) {
4152 0 : return IPC_OK();
4153 0 : }
4154 : nsCOMPtr<nsIURI> newURI = DeserializeURI(aNewURI);
4155 : if (!newURI) {
4156 : return IPC_OK();
4157 0 : }
4158 :
4159 : nsDocShell::CopyFavicon(oldURI, newURI, aLoadingPrincipal, aInPrivateBrowsing);
4160 : return IPC_OK();
4161 : }
4162 0 :
4163 : bool
4164 0 : ContentParent::ShouldContinueFromReplyTimeout()
4165 0 : {
4166 : RefPtr<ProcessHangMonitor> monitor = ProcessHangMonitor::Get();
4167 : return !monitor || !monitor->ShouldTimeOutCPOWs();
4168 : }
4169 0 :
4170 : mozilla::ipc::IPCResult
4171 : ContentParent::RecvRecordingDeviceEvents(const nsString& aRecordingStatus,
4172 : const nsString& aPageURL,
4173 : const bool& aIsAudio,
4174 0 : const bool& aIsVideo)
4175 0 : {
4176 : nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
4177 0 : if (obs) {
4178 0 : // recording-device-ipc-events needs to gather more information from content process
4179 0 : RefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
4180 0 : props->SetPropertyAsUint64(NS_LITERAL_STRING("childID"), ChildID());
4181 0 : props->SetPropertyAsBool(NS_LITERAL_STRING("isAudio"), aIsAudio);
4182 : props->SetPropertyAsBool(NS_LITERAL_STRING("isVideo"), aIsVideo);
4183 0 : props->SetPropertyAsAString(NS_LITERAL_STRING("requestURL"), aPageURL);
4184 :
4185 0 : obs->NotifyObservers((nsIPropertyBag2*) props,
4186 : "recording-device-ipc-events",
4187 0 : aRecordingStatus.get());
4188 : } else {
4189 0 : NS_WARNING("Could not get the Observer service for ContentParent::RecvRecordingDeviceEvents.");
4190 : }
4191 : return IPC_OK();
4192 : }
4193 0 :
4194 : mozilla::ipc::IPCResult
4195 : ContentParent::RecvAddIdleObserver(const uint64_t& aObserver,
4196 : const uint32_t& aIdleTimeInS)
4197 : {
4198 0 : nsresult rv;
4199 0 : nsCOMPtr<nsIIdleService> idleService =
4200 : do_GetService("@mozilla.org/widget/idleservice;1", &rv);
4201 : NS_ENSURE_SUCCESS(rv, IPC_FAIL_NO_REASON(this));
4202 0 :
4203 0 : RefPtr<ParentIdleListener> listener =
4204 0 : new ParentIdleListener(this, aObserver, aIdleTimeInS);
4205 0 : rv = idleService->AddIdleObserver(listener, aIdleTimeInS);
4206 : NS_ENSURE_SUCCESS(rv, IPC_FAIL_NO_REASON(this));
4207 : mIdleListeners.AppendElement(listener);
4208 : return IPC_OK();
4209 : }
4210 0 :
4211 : mozilla::ipc::IPCResult
4212 : ContentParent::RecvRemoveIdleObserver(const uint64_t& aObserver,
4213 0 : const uint32_t& aIdleTimeInS)
4214 0 : {
4215 0 : RefPtr<ParentIdleListener> listener;
4216 0 : for (int32_t i = mIdleListeners.Length() - 1; i >= 0; --i) {
4217 0 : listener = static_cast<ParentIdleListener*>(mIdleListeners[i].get());
4218 : if (listener->mObserver == aObserver &&
4219 : listener->mTime == aIdleTimeInS) {
4220 0 : nsresult rv;
4221 0 : nsCOMPtr<nsIIdleService> idleService =
4222 0 : do_GetService("@mozilla.org/widget/idleservice;1", &rv);
4223 0 : NS_ENSURE_SUCCESS(rv, IPC_FAIL_NO_REASON(this));
4224 0 : idleService->RemoveIdleObserver(listener, aIdleTimeInS);
4225 : mIdleListeners.RemoveElementAt(i);
4226 : break;
4227 : }
4228 : }
4229 : return IPC_OK();
4230 : }
4231 0 :
4232 : mozilla::ipc::IPCResult
4233 : ContentParent::RecvBackUpXResources(const FileDescriptor& aXSocketFd)
4234 : {
4235 : #ifndef MOZ_X11
4236 0 : MOZ_CRASH("This message only makes sense on X11 platforms");
4237 : #else
4238 0 : MOZ_ASSERT(0 > mChildXSocketFdDup.get(),
4239 0 : "Already backed up X resources??");
4240 0 : if (aXSocketFd.IsValid()) {
4241 : auto rawFD = aXSocketFd.ClonePlatformHandle();
4242 : mChildXSocketFdDup.reset(rawFD.release());
4243 0 : }
4244 : #endif
4245 : return IPC_OK();
4246 0 : }
4247 :
4248 : class AnonymousTemporaryFileRequestor final : public Runnable
4249 0 : {
4250 0 : public:
4251 : AnonymousTemporaryFileRequestor(ContentParent* aCP, const uint64_t& aID)
4252 0 : : Runnable("dom::AnonymousTemporaryFileRequestor")
4253 : , mCP(aCP)
4254 0 : , mID(aID)
4255 : , mRv(NS_OK)
4256 0 : , mPRFD(nullptr)
4257 : {
4258 0 : }
4259 :
4260 0 : NS_IMETHOD Run() override
4261 0 : {
4262 0 : if (NS_IsMainThread()) {
4263 : FileDescOrError result;
4264 : if (NS_WARN_IF(NS_FAILED(mRv))) {
4265 0 : // Returning false will kill the child process; instead
4266 : // propagate the error and let the child handle it.
4267 0 : result = mRv;
4268 : } else {
4269 : result = FileDescriptor(FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(mPRFD)));
4270 0 : // The FileDescriptor object owns a duplicate of the file handle; we
4271 : // must close the original (and clean up the NSPR descriptor).
4272 0 : PR_Close(mPRFD);
4273 : }
4274 0 : Unused << mCP->SendProvideAnonymousTemporaryFile(mID, result);
4275 : // It's important to release this reference while wr're on the main thread!
4276 0 : mCP = nullptr;
4277 0 : } else {
4278 : mRv = NS_OpenAnonymousTemporaryFile(&mPRFD);
4279 0 : NS_DispatchToMainThread(this);
4280 : }
4281 : return NS_OK;
4282 : }
4283 :
4284 : private:
4285 : RefPtr<ContentParent> mCP;
4286 : uint64_t mID;
4287 : nsresult mRv;
4288 : PRFileDesc* mPRFD;
4289 : };
4290 0 :
4291 : mozilla::ipc::IPCResult
4292 : ContentParent::RecvRequestAnonymousTemporaryFile(const uint64_t& aID)
4293 0 : {
4294 0 : // Make sure to send a callback to the child if we bail out early.
4295 0 : nsresult rv = NS_OK;
4296 0 : RefPtr<ContentParent> self(this);
4297 0 : auto autoNotifyChildOnError = MakeScopeExit([&, self]() {
4298 0 : if (NS_FAILED(rv)) {
4299 : FileDescOrError result(rv);
4300 0 : Unused << self->SendProvideAnonymousTemporaryFile(aID, result);
4301 : }
4302 : });
4303 :
4304 : // We use a helper runnable to open the anonymous temporary file on the IO
4305 : // thread. The same runnable will call us back on the main thread when the
4306 0 : // file has been opened.
4307 0 : nsCOMPtr<nsIEventTarget> target
4308 : = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
4309 : if (!target) {
4310 : return IPC_OK();
4311 0 : }
4312 :
4313 0 : rv = target->Dispatch(new AnonymousTemporaryFileRequestor(this, aID),
4314 : NS_DISPATCH_NORMAL);
4315 : if (NS_WARN_IF(NS_FAILED(rv))) {
4316 : return IPC_OK();
4317 0 : }
4318 :
4319 : rv = NS_OK;
4320 : return IPC_OK();
4321 : }
4322 1 :
4323 : mozilla::ipc::IPCResult
4324 2 : ContentParent::RecvCreateAudioIPCConnection(CreateAudioIPCConnectionResolver&& aResolver)
4325 1 : {
4326 0 : FileDescriptor fd = CubebUtils::CreateAudioIPCConnection();
4327 : if (!fd.IsValid()) {
4328 0 : return IPC_FAIL(this, "CubebUtils::CreateAudioIPCConnection failed");
4329 : }
4330 : aResolver(std::move(fd));
4331 : return IPC_OK();
4332 : }
4333 :
4334 : static NS_DEFINE_CID(kFormProcessorCID, NS_FORMPROCESSOR_CID);
4335 0 :
4336 : mozilla::ipc::IPCResult
4337 : ContentParent::RecvKeygenProcessValue(const nsString& oldValue,
4338 : const nsString& challenge,
4339 : const nsString& keytype,
4340 : const nsString& keyparams,
4341 : nsString* newValue)
4342 0 : {
4343 0 : nsCOMPtr<nsIFormProcessor> formProcessor =
4344 0 : do_GetService(kFormProcessorCID);
4345 : if (!formProcessor) {
4346 : newValue->Truncate();
4347 : return IPC_OK();
4348 0 : }
4349 0 :
4350 : formProcessor->ProcessValueIPC(oldValue, challenge, keytype, keyparams,
4351 : *newValue);
4352 : return IPC_OK();
4353 : }
4354 0 :
4355 : mozilla::ipc::IPCResult
4356 : ContentParent::RecvKeygenProvideContent(nsString* aAttribute,
4357 : nsTArray<nsString>* aContent)
4358 0 : {
4359 0 : nsCOMPtr<nsIFormProcessor> formProcessor =
4360 : do_GetService(kFormProcessorCID);
4361 : if (!formProcessor) {
4362 : return IPC_OK();
4363 0 : }
4364 0 :
4365 : formProcessor->ProvideContent(NS_LITERAL_STRING("SELECT"), *aContent,
4366 : *aAttribute);
4367 : return IPC_OK();
4368 : }
4369 0 :
4370 : PFileDescriptorSetParent*
4371 0 : ContentParent::SendPFileDescriptorSetConstructor(const FileDescriptor& aFD)
4372 : {
4373 : return PContentParent::SendPFileDescriptorSetConstructor(aFD);
4374 : }
4375 0 :
4376 : PFileDescriptorSetParent*
4377 0 : ContentParent::AllocPFileDescriptorSetParent(const FileDescriptor& aFD)
4378 : {
4379 : return nsIContentParent::AllocPFileDescriptorSetParent(aFD);
4380 : }
4381 0 :
4382 : bool
4383 0 : ContentParent::DeallocPFileDescriptorSetParent(PFileDescriptorSetParent* aActor)
4384 : {
4385 : return nsIContentParent::DeallocPFileDescriptorSetParent(aActor);
4386 : }
4387 0 :
4388 : bool
4389 : ContentParent::IgnoreIPCPrincipal()
4390 : {
4391 0 : static bool sDidAddVarCache = false;
4392 0 : static bool sIgnoreIPCPrincipal = false;
4393 : if (!sDidAddVarCache) {
4394 0 : sDidAddVarCache = true;
4395 : Preferences::AddBoolVarCache(&sIgnoreIPCPrincipal,
4396 0 : "dom.testing.ignore_ipc_principal", false);
4397 : }
4398 : return sIgnoreIPCPrincipal;
4399 : }
4400 1 :
4401 : void
4402 1 : ContentParent::NotifyUpdatedDictionaries()
4403 1 : {
4404 : nsCOMPtr<nsISpellChecker> spellChecker(do_GetService(NS_SPELLCHECKER_CONTRACTID));
4405 2 : MOZ_ASSERT(spellChecker, "No spell checker?");
4406 0 :
4407 : InfallibleTArray<nsString> dictionaries;
4408 0 : spellChecker->GetDictionaryList(&dictionaries);
4409 0 :
4410 : for (auto* cp : AllProcesses(eLive)) {
4411 0 : Unused << cp->SendUpdateDictionaryList(dictionaries);
4412 : }
4413 : }
4414 0 :
4415 : void
4416 0 : ContentParent::NotifyUpdatedFonts()
4417 0 : {
4418 : InfallibleTArray<SystemFontListEntry> fontList;
4419 0 : gfxPlatform::GetPlatform()->ReadSystemFontList(&fontList);
4420 0 :
4421 : for (auto* cp : AllProcesses(eLive)) {
4422 0 : Unused << cp->SendUpdateFontList(fontList);
4423 : }
4424 : }
4425 0 :
4426 : /*static*/ void
4427 : ContentParent::UnregisterRemoteFrame(const TabId& aTabId,
4428 : const ContentParentId& aCpId,
4429 0 : bool aMarkedDestroying)
4430 0 : {
4431 0 : if (XRE_IsParentProcess()) {
4432 : ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
4433 0 : ContentParent* cp = cpm->GetContentProcessById(aCpId);
4434 :
4435 : if (!cp) {
4436 : return;
4437 0 : }
4438 :
4439 0 : cp->NotifyTabDestroyed(aTabId, aMarkedDestroying);
4440 :
4441 0 : ContentProcessManager::GetSingleton()->UnregisterRemoteFrame(aCpId, aTabId);
4442 0 : } else {
4443 : ContentChild::GetSingleton()->SendUnregisterRemoteFrame(aTabId, aCpId,
4444 : aMarkedDestroying);
4445 : }
4446 : }
4447 0 :
4448 : mozilla::ipc::IPCResult
4449 : ContentParent::RecvUnregisterRemoteFrame(const TabId& aTabId,
4450 : const ContentParentId& aCpId,
4451 0 : const bool& aMarkedDestroying)
4452 0 : {
4453 : UnregisterRemoteFrame(aTabId, aCpId, aMarkedDestroying);
4454 : return IPC_OK();
4455 : }
4456 0 :
4457 : mozilla::ipc::IPCResult
4458 : ContentParent::RecvNotifyTabDestroying(const TabId& aTabId,
4459 0 : const ContentParentId& aCpId)
4460 0 : {
4461 : NotifyTabDestroying(aTabId, aCpId);
4462 : return IPC_OK();
4463 : }
4464 0 :
4465 : nsTArray<TabContext>
4466 : ContentParent::GetManagedTabContext()
4467 0 : {
4468 : return ContentProcessManager::GetSingleton()->
4469 : GetTabContextByContentProcess(this->ChildID());
4470 : }
4471 0 :
4472 : mozilla::docshell::POfflineCacheUpdateParent*
4473 : ContentParent::AllocPOfflineCacheUpdateParent(const URIParams& aManifestURI,
4474 : const URIParams& aDocumentURI,
4475 : const PrincipalInfo& aLoadingPrincipalInfo,
4476 : const bool& aStickDocument)
4477 0 : {
4478 : RefPtr<mozilla::docshell::OfflineCacheUpdateParent> update =
4479 0 : new mozilla::docshell::OfflineCacheUpdateParent();
4480 : // Use this reference as the IPDL reference.
4481 : return update.forget().take();
4482 : }
4483 0 :
4484 : mozilla::ipc::IPCResult
4485 : ContentParent::RecvPOfflineCacheUpdateConstructor(POfflineCacheUpdateParent* aActor,
4486 : const URIParams& aManifestURI,
4487 : const URIParams& aDocumentURI,
4488 : const PrincipalInfo& aLoadingPrincipal,
4489 0 : const bool& aStickDocument)
4490 : {
4491 : MOZ_ASSERT(aActor);
4492 0 :
4493 : RefPtr<mozilla::docshell::OfflineCacheUpdateParent> update =
4494 0 : static_cast<mozilla::docshell::OfflineCacheUpdateParent*>(aActor);
4495 0 :
4496 : nsresult rv = update->Schedule(aManifestURI, aDocumentURI, aLoadingPrincipal, aStickDocument);
4497 0 : if (NS_FAILED(rv) && IsAlive()) {
4498 : // Inform the child of failure.
4499 : Unused << update->SendFinish(false, false);
4500 0 : }
4501 :
4502 : return IPC_OK();
4503 : }
4504 0 :
4505 : bool
4506 : ContentParent::DeallocPOfflineCacheUpdateParent(POfflineCacheUpdateParent* aActor)
4507 : {
4508 0 : // Reclaim the IPDL reference.
4509 0 : RefPtr<mozilla::docshell::OfflineCacheUpdateParent> update =
4510 : dont_AddRef(static_cast<mozilla::docshell::OfflineCacheUpdateParent*>(aActor));
4511 : return true;
4512 : }
4513 0 :
4514 : PWebrtcGlobalParent *
4515 : ContentParent::AllocPWebrtcGlobalParent()
4516 0 : {
4517 : #ifdef MOZ_WEBRTC
4518 : return WebrtcGlobalParent::Alloc();
4519 : #else
4520 : return nullptr;
4521 : #endif
4522 : }
4523 0 :
4524 : bool
4525 : ContentParent::DeallocPWebrtcGlobalParent(PWebrtcGlobalParent *aActor)
4526 0 : {
4527 0 : #ifdef MOZ_WEBRTC
4528 : WebrtcGlobalParent::Dealloc(static_cast<WebrtcGlobalParent*>(aActor));
4529 : return true;
4530 : #else
4531 : return false;
4532 : #endif
4533 : }
4534 0 :
4535 : mozilla::ipc::IPCResult
4536 0 : ContentParent::RecvSetOfflinePermission(const Principal& aPrincipal)
4537 0 : {
4538 0 : nsIPrincipal* principal = aPrincipal;
4539 : nsContentUtils::MaybeAllowOfflineAppByDefault(principal);
4540 : return IPC_OK();
4541 : }
4542 0 :
4543 : void
4544 : ContentParent::MaybeInvokeDragSession(TabParent* aParent)
4545 : {
4546 : // dnd uses IPCBlob to transfer data to the content process and the IPC
4547 : // message is sent as normal priority. When sending input events with input
4548 : // priority, the message may be preempted by the later dnd events. To make
4549 : // sure the input events and the blob message are processed in time order
4550 0 : // on the content process, we temporarily send the input events with normal
4551 : // priority when there is an active dnd session.
4552 : SetInputPriorityEventEnabled(false);
4553 0 :
4554 0 : nsCOMPtr<nsIDragService> dragService =
4555 : do_GetService("@mozilla.org/widget/dragservice;1");
4556 0 : if (dragService && dragService->MaybeAddChildProcess(this)) {
4557 0 : // We need to send transferable data to child process.
4558 0 : nsCOMPtr<nsIDragSession> session;
4559 0 : dragService->GetCurrentSession(getter_AddRefs(session));
4560 0 : if (session) {
4561 0 : nsTArray<IPCDataTransfer> dataTransfers;
4562 : RefPtr<DataTransfer> transfer = session->GetDataTransfer();
4563 : if (!transfer) {
4564 0 : // Pass eDrop to get DataTransfer with external
4565 0 : // drag formats cached.
4566 : transfer = new DataTransfer(nullptr, eDrop, true, -1);
4567 : session->SetDataTransfer(transfer);
4568 : }
4569 : // Note, even though this fills the DataTransfer object with
4570 0 : // external data, the data is usually transfered over IPC lazily when
4571 0 : // needed.
4572 0 : transfer->FillAllExternalData();
4573 : nsCOMPtr<nsILoadContext> lc = aParent ?
4574 0 : aParent->GetLoadContext() : nullptr;
4575 0 : nsCOMPtr<nsIArray> transferables =
4576 : transfer->GetTransferables(lc);
4577 : nsContentUtils::TransferablesToIPCTransferables(transferables,
4578 : dataTransfers,
4579 0 : false,
4580 : nullptr,
4581 0 : this);
4582 0 : uint32_t action;
4583 : session->GetDragAction(&action);
4584 : mozilla::Unused << SendInvokeDragSession(dataTransfers, action);
4585 0 : }
4586 : }
4587 : }
4588 0 :
4589 : mozilla::ipc::IPCResult
4590 : ContentParent::RecvUpdateDropEffect(const uint32_t& aDragAction,
4591 0 : const uint32_t& aDropEffect)
4592 0 : {
4593 0 : nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
4594 0 : if (dragSession) {
4595 0 : dragSession->SetDragAction(aDragAction);
4596 0 : RefPtr<DataTransfer> dt = dragSession->GetDataTransfer();
4597 : if (dt) {
4598 0 : dt->SetDropEffectInt(aDropEffect);
4599 : }
4600 0 : dragSession->UpdateDragEffect();
4601 : }
4602 : return IPC_OK();
4603 : }
4604 0 :
4605 : PContentPermissionRequestParent*
4606 : ContentParent::AllocPContentPermissionRequestParent(const InfallibleTArray<PermissionRequest>& aRequests,
4607 : const IPC::Principal& aPrincipal,
4608 : const bool& aIsHandlingUserInput,
4609 0 : const TabId& aTabId)
4610 : {
4611 0 : ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
4612 0 : RefPtr<TabParent> tp =
4613 : cpm->GetTopLevelTabParentByProcessAndTabId(this->ChildID(), aTabId);
4614 : if (!tp) {
4615 : return nullptr;
4616 0 : }
4617 :
4618 : return nsContentPermissionUtils::CreateContentPermissionRequestParent(aRequests,
4619 0 : tp->GetOwnerElement(),
4620 0 : aPrincipal,
4621 : aIsHandlingUserInput,
4622 : aTabId);
4623 : }
4624 0 :
4625 : bool
4626 0 : ContentParent::DeallocPContentPermissionRequestParent(PContentPermissionRequestParent* actor)
4627 0 : {
4628 0 : nsContentPermissionUtils::NotifyRemoveContentPermissionRequestParent(actor);
4629 : delete actor;
4630 : return true;
4631 : }
4632 0 :
4633 : PWebBrowserPersistDocumentParent*
4634 : ContentParent::AllocPWebBrowserPersistDocumentParent(PBrowserParent* aBrowser,
4635 0 : const uint64_t& aOuterWindowID)
4636 : {
4637 : return new WebBrowserPersistDocumentParent();
4638 : }
4639 0 :
4640 : bool
4641 0 : ContentParent::DeallocPWebBrowserPersistDocumentParent(PWebBrowserPersistDocumentParent* aActor)
4642 0 : {
4643 : delete aActor;
4644 : return true;
4645 : }
4646 0 :
4647 : mozilla::ipc::IPCResult
4648 : ContentParent::CommonCreateWindow(PBrowserParent* aThisTab,
4649 : bool aSetOpener,
4650 : const uint32_t& aChromeFlags,
4651 : const bool& aCalledFromJS,
4652 : const bool& aPositionSpecified,
4653 : const bool& aSizeSpecified,
4654 : nsIURI* aURIToLoad,
4655 : const nsCString& aFeatures,
4656 : const nsCString& aBaseURI,
4657 : const float& aFullZoom,
4658 : uint64_t aNextTabParentId,
4659 : const nsString& aName,
4660 : nsresult& aResult,
4661 : nsCOMPtr<nsITabParent>& aNewTabParent,
4662 : bool* aWindowIsNew,
4663 : nsIPrincipal* aTriggeringPrincipal,
4664 : uint32_t aReferrerPolicy,
4665 : bool aLoadURI)
4666 :
4667 : {
4668 : // The content process should never be in charge of computing whether or
4669 : // not a window should be private or remote - the parent will do that.
4670 : const uint32_t badFlags = nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW |
4671 0 : nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW |
4672 0 : nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME |
4673 0 : nsIWebBrowserChrome::CHROME_REMOTE_WINDOW;
4674 : if (!!(aChromeFlags & badFlags)) {
4675 : return IPC_FAIL(this, "Forbidden aChromeFlags passed");
4676 0 : }
4677 0 :
4678 0 : TabParent* thisTabParent = TabParent::GetFrom(aThisTab);
4679 0 : nsCOMPtr<nsIContent> frame;
4680 : if (thisTabParent) {
4681 0 : frame = do_QueryInterface(thisTabParent->GetOwnerElement());
4682 0 :
4683 : if (NS_WARN_IF(thisTabParent->IsMozBrowser())) {
4684 : return IPC_FAIL(this, "aThisTab is not a MozBrowser");
4685 : }
4686 0 : }
4687 0 :
4688 0 : nsCOMPtr<nsPIDOMWindowOuter> outerWin;
4689 : if (frame) {
4690 : outerWin = frame->OwnerDoc()->GetWindow();
4691 :
4692 0 : // If our chrome window is in the process of closing, don't try to open a
4693 0 : // new tab in it.
4694 : if (outerWin && outerWin->Closed()) {
4695 : outerWin = nullptr;
4696 : }
4697 0 : }
4698 0 :
4699 0 : nsCOMPtr<nsIBrowserDOMWindow> browserDOMWin;
4700 : if (thisTabParent) {
4701 : browserDOMWin = thisTabParent->GetBrowserDOMWindow();
4702 : }
4703 :
4704 0 : // If we haven't found a chrome window to open in, just use the most recently
4705 0 : // opened one.
4706 0 : if (!outerWin) {
4707 0 : outerWin = nsContentUtils::GetMostRecentNonPBWindow();
4708 0 : if (NS_WARN_IF(!outerWin)) {
4709 : aResult = NS_ERROR_FAILURE;
4710 : return IPC_OK();
4711 0 : }
4712 0 :
4713 0 : nsCOMPtr<nsIDOMChromeWindow> rootChromeWin = do_QueryInterface(outerWin);
4714 : if (rootChromeWin) {
4715 : rootChromeWin->GetBrowserDOMWindow(getter_AddRefs(browserDOMWin));
4716 : }
4717 0 : }
4718 0 :
4719 : int32_t openLocation = nsWindowWatcher::GetWindowOpenLocation(
4720 0 : outerWin, aChromeFlags, aCalledFromJS, aPositionSpecified, aSizeSpecified);
4721 :
4722 : MOZ_ASSERT(openLocation == nsIBrowserDOMWindow::OPEN_NEWTAB ||
4723 : openLocation == nsIBrowserDOMWindow::OPEN_NEWWINDOW);
4724 0 :
4725 0 : // Read the origin attributes for the tab from the opener tabParent.
4726 0 : OriginAttributes openerOriginAttributes;
4727 0 : if (thisTabParent) {
4728 0 : nsCOMPtr<nsILoadContext> loadContext = thisTabParent->GetLoadContext();
4729 0 : loadContext->GetOriginAttributes(openerOriginAttributes);
4730 : } else if (Preferences::GetBool("browser.privatebrowsing.autostart")) {
4731 : openerOriginAttributes.mPrivateBrowsingId = 1;
4732 0 : }
4733 0 :
4734 0 : if (openLocation == nsIBrowserDOMWindow::OPEN_NEWTAB) {
4735 0 : if (NS_WARN_IF(!browserDOMWin)) {
4736 : aResult = NS_ERROR_ABORT;
4737 : return IPC_OK();
4738 0 : }
4739 :
4740 : nsCOMPtr<nsIFrameLoaderOwner> opener = do_QueryInterface(frame);
4741 0 :
4742 0 : nsCOMPtr<nsIOpenURIInFrameParams> params =
4743 0 : new nsOpenURIInFrameParams(openerOriginAttributes, opener);
4744 0 : params->SetReferrer(NS_ConvertUTF8toUTF16(aBaseURI));
4745 0 : MOZ_ASSERT(aTriggeringPrincipal, "need a valid triggeringPrincipal");
4746 : params->SetTriggeringPrincipal(aTriggeringPrincipal);
4747 0 : params->SetReferrerPolicy(aReferrerPolicy);
4748 0 :
4749 0 : nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner;
4750 : if (aLoadURI) {
4751 : aResult = browserDOMWin->OpenURIInFrame(aURIToLoad,
4752 : params, openLocation,
4753 0 : nsIBrowserDOMWindow::OPEN_NEW,
4754 : aNextTabParentId, aName,
4755 0 : getter_AddRefs(frameLoaderOwner));
4756 : } else {
4757 : aResult = browserDOMWin->CreateContentWindowInFrame(aURIToLoad,
4758 : params, openLocation,
4759 0 : nsIBrowserDOMWindow::OPEN_NEW,
4760 : aNextTabParentId, aName,
4761 0 : getter_AddRefs(frameLoaderOwner));
4762 0 : }
4763 0 : if (NS_SUCCEEDED(aResult) && frameLoaderOwner) {
4764 0 : RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
4765 : if (frameLoader) {
4766 : aNewTabParent = frameLoader->GetTabParent();
4767 : // At this point, it's possible the inserted frameloader hasn't gone through
4768 : // layout yet. To ensure that the dimensions that we send down when telling the
4769 : // frameloader to display will be correct (instead of falling back to a 10x10
4770 0 : // default), we force layout if necessary to get the most up-to-date dimensions.
4771 : // See bug 1358712 for details.
4772 0 : frameLoader->ForceLayoutIfNecessary();
4773 : }
4774 : } else if (NS_SUCCEEDED(aResult) && !frameLoaderOwner) {
4775 : // Fall through to the normal window opening code path when there is no
4776 : // window which we can open a new tab in.
4777 0 : openLocation = nsIBrowserDOMWindow::OPEN_NEWWINDOW;
4778 : } else {
4779 : *aWindowIsNew = false;
4780 : }
4781 0 :
4782 0 : // If we didn't retarget our window open into a new window, we should return now.
4783 : if (openLocation != nsIBrowserDOMWindow::OPEN_NEWWINDOW) {
4784 : return IPC_OK();
4785 : }
4786 : }
4787 0 :
4788 0 : nsCOMPtr<nsPIWindowWatcher> pwwatch =
4789 : do_GetService(NS_WINDOWWATCHER_CONTRACTID, &aResult);
4790 : if (NS_WARN_IF(NS_FAILED(aResult))) {
4791 : return IPC_OK();
4792 0 : }
4793 0 :
4794 : aResult = pwwatch->OpenWindowWithTabParent(thisTabParent,
4795 0 : aFeatures, aCalledFromJS, aFullZoom,
4796 0 : aNextTabParentId,
4797 0 : !aSetOpener,
4798 : getter_AddRefs(aNewTabParent));
4799 : if (NS_WARN_IF(NS_FAILED(aResult))) {
4800 : return IPC_OK();
4801 0 : }
4802 :
4803 : MOZ_ASSERT(aNewTabParent);
4804 :
4805 : // At this point, it's possible the inserted frameloader hasn't gone through
4806 : // layout yet. To ensure that the dimensions that we send down when telling the
4807 : // frameloader to display will be correct (instead of falling back to a 10x10
4808 : // default), we force layout if necessary to get the most up-to-date dimensions.
4809 : // See bug 1358712 for details.
4810 : //
4811 : // This involves doing a bit of gymnastics in order to get at the FrameLoader,
4812 : // so we scope this to avoid polluting the main function scope.
4813 0 : {
4814 0 : nsCOMPtr<Element> frameElement =
4815 0 : TabParent::GetFrom(aNewTabParent)->GetOwnerElement();
4816 0 : MOZ_ASSERT(frameElement);
4817 0 : nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner = do_QueryInterface(frameElement);
4818 0 : MOZ_ASSERT(frameLoaderOwner);
4819 0 : RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
4820 : MOZ_ASSERT(frameLoader);
4821 : frameLoader->ForceLayoutIfNecessary();
4822 : }
4823 :
4824 0 : // If we were passed a name for the window which would override the default,
4825 0 : // we should send it down to the new tab.
4826 : if (nsContentUtils::IsOverridingWindowName(aName)) {
4827 : Unused << TabParent::GetFrom(aNewTabParent)->SendSetWindowName(aName);
4828 : }
4829 :
4830 : // Don't send down the OriginAttributes if the content process is handling
4831 : // setting up the window for us. We only want to send them in the async case.
4832 : //
4833 0 : // If we send it down in the non-async case, then we might set the
4834 0 : // OriginAttributes after the document has already navigated.
4835 0 : if (!aSetOpener) {
4836 : Unused << TabParent::GetFrom(aNewTabParent)
4837 : ->SendSetOriginAttributes(openerOriginAttributes);
4838 0 : }
4839 0 :
4840 0 : if (aURIToLoad && aLoadURI) {
4841 0 : nsCOMPtr<mozIDOMWindowProxy> openerWindow;
4842 : if (aSetOpener && thisTabParent) {
4843 : openerWindow = thisTabParent->GetParentWindowOuter();
4844 0 : }
4845 0 : nsCOMPtr<nsIBrowserDOMWindow> newBrowserDOMWin =
4846 0 : TabParent::GetFrom(aNewTabParent)->GetBrowserDOMWindow();
4847 0 : if (NS_WARN_IF(!newBrowserDOMWin)) {
4848 : aResult = NS_ERROR_ABORT;
4849 0 : return IPC_OK();
4850 0 : }
4851 : nsCOMPtr<mozIDOMWindowProxy> win;
4852 : aResult = newBrowserDOMWin->OpenURI(aURIToLoad, openerWindow,
4853 : nsIBrowserDOMWindow::OPEN_CURRENTWINDOW,
4854 0 : nsIBrowserDOMWindow::OPEN_NEW,
4855 : aTriggeringPrincipal,
4856 : getter_AddRefs(win));
4857 : }
4858 :
4859 : return IPC_OK();
4860 : }
4861 0 :
4862 : mozilla::ipc::IPCResult
4863 : ContentParent::RecvCreateWindow(PBrowserParent* aThisTab,
4864 : PBrowserParent* aNewTab,
4865 : PRenderFrameParent* aRenderFrame,
4866 : const uint32_t& aChromeFlags,
4867 : const bool& aCalledFromJS,
4868 : const bool& aPositionSpecified,
4869 : const bool& aSizeSpecified,
4870 : const OptionalURIParams& aURIToLoad,
4871 : const nsCString& aFeatures,
4872 : const nsCString& aBaseURI,
4873 : const float& aFullZoom,
4874 : const IPC::Principal& aTriggeringPrincipal,
4875 : const uint32_t& aReferrerPolicy,
4876 0 : CreateWindowResolver&& aResolve)
4877 0 : {
4878 : nsresult rv = NS_OK;
4879 : CreatedWindowInfo cwi;
4880 0 :
4881 0 : // We always expect to open a new window here. If we don't, it's an error.
4882 0 : cwi.windowOpened() = true;
4883 : cwi.layersId() = LayersId{0};
4884 : cwi.maxTouchPoints() = 0;
4885 :
4886 0 : // Make sure to resolve the resolver when this function exits, even if we
4887 : // failed to generate a valid response.
4888 0 : auto resolveOnExit = MakeScopeExit([&] {
4889 0 : // Copy over the nsresult, and then resolve.
4890 0 : cwi.rv() = rv;
4891 : aResolve(cwi);
4892 0 : });
4893 0 :
4894 : TabParent* newTab = TabParent::GetFrom(aNewTab);
4895 0 : MOZ_ASSERT(newTab);
4896 :
4897 0 : auto destroyNewTabOnError = MakeScopeExit([&] {
4898 0 : // We always expect to open a new window here. If we don't, it's an error.
4899 0 : if (!cwi.windowOpened() || NS_FAILED(rv)) {
4900 : if (newTab) {
4901 : newTab->Destroy();
4902 0 : }
4903 : }
4904 : });
4905 :
4906 0 : // Content has requested that we open this new content window, so
4907 : // we must have an opener.
4908 0 : newTab->SetHasContentOpener(true);
4909 0 :
4910 0 : TabParent::AutoUseNewTab aunt(newTab, &cwi.urlToLoad());
4911 : const uint64_t nextTabParentId = ++sNextTabParentId;
4912 0 : sNextTabParents.Put(nextTabParentId, newTab);
4913 :
4914 0 : const nsCOMPtr<nsIURI> uriToLoad = DeserializeURI(aURIToLoad);
4915 :
4916 : nsCOMPtr<nsITabParent> newRemoteTab;
4917 : mozilla::ipc::IPCResult ipcResult =
4918 : CommonCreateWindow(aThisTab, /* aSetOpener = */ true, aChromeFlags,
4919 0 : aCalledFromJS, aPositionSpecified, aSizeSpecified,
4920 0 : uriToLoad, aFeatures, aBaseURI, aFullZoom,
4921 : nextTabParentId, VoidString(), rv,
4922 0 : newRemoteTab, &cwi.windowOpened(),
4923 0 : aTriggeringPrincipal, aReferrerPolicy,
4924 0 : /* aLoadUri = */ false);
4925 : if (!ipcResult) {
4926 : return ipcResult;
4927 0 : }
4928 :
4929 : if (NS_WARN_IF(NS_FAILED(rv)) || !newRemoteTab) {
4930 : return IPC_OK();
4931 0 : }
4932 0 :
4933 : if (sNextTabParents.GetAndRemove(nextTabParentId).valueOr(nullptr)) {
4934 0 : cwi.windowOpened() = false;
4935 : }
4936 0 : MOZ_ASSERT(TabParent::GetFrom(newRemoteTab) == newTab);
4937 :
4938 0 : newTab->SwapFrameScriptsFrom(cwi.frameScripts());
4939 0 :
4940 0 : RenderFrameParent* rfp = static_cast<RenderFrameParent*>(aRenderFrame);
4941 0 : if (!newTab->SetRenderFrame(rfp) ||
4942 : !newTab->GetRenderFrameInfo(&cwi.textureFactoryIdentifier(), &cwi.layersId())) {
4943 0 : rv = NS_ERROR_FAILURE;
4944 : }
4945 0 : cwi.compositorOptions() = rfp->GetCompositorOptions();
4946 0 :
4947 0 : nsCOMPtr<nsIWidget> widget = newTab->GetWidget();
4948 0 : if (widget) {
4949 : cwi.maxTouchPoints() = widget->GetMaxTouchPoints();
4950 : cwi.dimensions() = newTab->GetDimensionInfo();
4951 : }
4952 :
4953 : return IPC_OK();
4954 : }
4955 0 :
4956 : mozilla::ipc::IPCResult
4957 : ContentParent::RecvCreateWindowInDifferentProcess(
4958 : PBrowserParent* aThisTab,
4959 : const uint32_t& aChromeFlags,
4960 : const bool& aCalledFromJS,
4961 : const bool& aPositionSpecified,
4962 : const bool& aSizeSpecified,
4963 : const OptionalURIParams& aURIToLoad,
4964 : const nsCString& aFeatures,
4965 : const nsCString& aBaseURI,
4966 : const float& aFullZoom,
4967 : const nsString& aName,
4968 : const IPC::Principal& aTriggeringPrincipal,
4969 0 : const uint32_t& aReferrerPolicy)
4970 : {
4971 0 : nsCOMPtr<nsITabParent> newRemoteTab;
4972 : bool windowIsNew;
4973 : nsCOMPtr<nsIURI> uriToLoad = DeserializeURI(aURIToLoad);
4974 : nsresult rv;
4975 : mozilla::ipc::IPCResult ipcResult =
4976 : CommonCreateWindow(aThisTab, /* aSetOpener = */ false, aChromeFlags,
4977 : aCalledFromJS, aPositionSpecified, aSizeSpecified,
4978 : uriToLoad, aFeatures, aBaseURI, aFullZoom,
4979 0 : /* aNextTabParentId = */ 0, aName, rv,
4980 0 : newRemoteTab, &windowIsNew, aTriggeringPrincipal,
4981 0 : aReferrerPolicy, /* aLoadUri = */ true);
4982 : if (!ipcResult) {
4983 : return ipcResult;
4984 0 : }
4985 0 :
4986 : if (NS_FAILED(rv)) {
4987 : NS_WARNING("Call to CommonCreateWindow failed.");
4988 : }
4989 :
4990 : return IPC_OK();
4991 : }
4992 0 :
4993 : mozilla::ipc::IPCResult
4994 : ContentParent::RecvShutdownProfile(const nsCString& aProfile)
4995 0 : {
4996 0 : #ifdef MOZ_GECKO_PROFILER
4997 : nsCOMPtr<nsIProfiler> profiler(do_GetService("@mozilla.org/tools/profiler;1"));
4998 0 : profiler->ReceiveShutdownProfile(aProfile);
4999 : #endif
5000 : return IPC_OK();
5001 : }
5002 0 :
5003 : mozilla::ipc::IPCResult
5004 0 : ContentParent::RecvGetGraphicsDeviceInitData(ContentDeviceData* aOut)
5005 0 : {
5006 : gfxPlatform::GetPlatform()->BuildContentDeviceData(aOut);
5007 : return IPC_OK();
5008 : }
5009 0 :
5010 : mozilla::ipc::IPCResult
5011 0 : ContentParent::RecvGraphicsError(const nsCString& aError)
5012 0 : {
5013 0 : gfx::LogForwarder* lf = gfx::Factory::GetLogForwarder();
5014 0 : if (lf) {
5015 0 : std::stringstream message;
5016 : message << "CP+" << aError.get();
5017 0 : lf->UpdateStringsVector(message.str());
5018 : }
5019 : return IPC_OK();
5020 : }
5021 0 :
5022 : mozilla::ipc::IPCResult
5023 : ContentParent::RecvBeginDriverCrashGuard(const uint32_t& aGuardType, bool* aOutCrashed)
5024 0 : {
5025 : // Only one driver crash guard should be active at a time, per-process.
5026 0 : MOZ_ASSERT(!mDriverCrashGuard);
5027 0 :
5028 : UniquePtr<gfx::DriverCrashGuard> guard;
5029 0 : switch (gfx::CrashGuardType(aGuardType)) {
5030 0 : case gfx::CrashGuardType::D3D11Layers:
5031 : guard = MakeUnique<gfx::D3D11LayersCrashGuard>(this);
5032 0 : break;
5033 0 : case gfx::CrashGuardType::D3D9Video:
5034 : guard = MakeUnique<gfx::D3D9VideoCrashGuard>(this);
5035 0 : break;
5036 0 : case gfx::CrashGuardType::GLContext:
5037 : guard = MakeUnique<gfx::GLContextCrashGuard>(this);
5038 0 : break;
5039 0 : case gfx::CrashGuardType::D3D11Video:
5040 : guard = MakeUnique<gfx::D3D11VideoCrashGuard>(this);
5041 0 : break;
5042 : default:
5043 : MOZ_ASSERT_UNREACHABLE("unknown crash guard type");
5044 : return IPC_FAIL_NO_REASON(this);
5045 0 : }
5046 0 :
5047 : if (guard->Crashed()) {
5048 : *aOutCrashed = true;
5049 : return IPC_OK();
5050 0 : }
5051 0 :
5052 : *aOutCrashed = false;
5053 : mDriverCrashGuard = std::move(guard);
5054 : return IPC_OK();
5055 : }
5056 0 :
5057 : mozilla::ipc::IPCResult
5058 0 : ContentParent::RecvEndDriverCrashGuard(const uint32_t& aGuardType)
5059 0 : {
5060 : mDriverCrashGuard = nullptr;
5061 : return IPC_OK();
5062 : }
5063 0 :
5064 : mozilla::ipc::IPCResult
5065 : ContentParent::RecvGetAndroidSystemInfo(AndroidSystemInfo* aInfo)
5066 : {
5067 : #ifdef MOZ_WIDGET_ANDROID
5068 : nsSystemInfo::GetAndroidSystemInfo(aInfo);
5069 0 : return IPC_OK();
5070 : #else
5071 : MOZ_CRASH("wrong platform!");
5072 : return IPC_FAIL_NO_REASON(this);
5073 : #endif
5074 : }
5075 0 :
5076 : mozilla::ipc::IPCResult
5077 : ContentParent::RecvNotifyBenchmarkResult(const nsString& aCodecName,
5078 : const uint32_t& aDecodeFPS)
5079 0 :
5080 0 : {
5081 0 : if (aCodecName.EqualsLiteral("VP9")) {
5082 0 : Preferences::SetUint(VP9Benchmark::sBenchmarkFpsPref, aDecodeFPS);
5083 : Preferences::SetUint(VP9Benchmark::sBenchmarkFpsVersionCheck,
5084 0 : VP9Benchmark::sBenchmarkVersionID);
5085 : }
5086 : return IPC_OK();
5087 : }
5088 0 :
5089 : mozilla::ipc::IPCResult
5090 : ContentParent::RecvNotifyPushObservers(const nsCString& aScope,
5091 : const IPC::Principal& aPrincipal,
5092 0 : const nsString& aMessageId)
5093 0 : {
5094 0 : PushMessageDispatcher dispatcher(aScope, aPrincipal, aMessageId, Nothing());
5095 : Unused << NS_WARN_IF(NS_FAILED(dispatcher.NotifyObservers()));
5096 : return IPC_OK();
5097 : }
5098 0 :
5099 : mozilla::ipc::IPCResult
5100 : ContentParent::RecvNotifyPushObserversWithData(const nsCString& aScope,
5101 : const IPC::Principal& aPrincipal,
5102 : const nsString& aMessageId,
5103 0 : InfallibleTArray<uint8_t>&& aData)
5104 0 : {
5105 0 : PushMessageDispatcher dispatcher(aScope, aPrincipal, aMessageId, Some(aData));
5106 : Unused << NS_WARN_IF(NS_FAILED(dispatcher.NotifyObservers()));
5107 : return IPC_OK();
5108 : }
5109 0 :
5110 : mozilla::ipc::IPCResult
5111 : ContentParent::RecvNotifyPushSubscriptionChangeObservers(const nsCString& aScope,
5112 0 : const IPC::Principal& aPrincipal)
5113 0 : {
5114 0 : PushSubscriptionChangeDispatcher dispatcher(aScope, aPrincipal);
5115 : Unused << NS_WARN_IF(NS_FAILED(dispatcher.NotifyObservers()));
5116 : return IPC_OK();
5117 : }
5118 0 :
5119 : mozilla::ipc::IPCResult
5120 : ContentParent::RecvNotifyPushSubscriptionModifiedObservers(const nsCString& aScope,
5121 0 : const IPC::Principal& aPrincipal)
5122 0 : {
5123 0 : PushSubscriptionModifiedDispatcher dispatcher(aScope, aPrincipal);
5124 : Unused << NS_WARN_IF(NS_FAILED(dispatcher.NotifyObservers()));
5125 : return IPC_OK();
5126 : }
5127 0 :
5128 : mozilla::ipc::IPCResult
5129 0 : ContentParent::RecvNotifyLowMemory()
5130 : {
5131 0 : MarkAsTroubled();
5132 :
5133 0 : Telemetry::ScalarAdd(Telemetry::ScalarID::DOM_CONTENTPROCESS_TROUBLED_DUE_TO_MEMORY, 1);
5134 :
5135 0 : nsThread::SaveMemoryReportNearOOM(nsThread::ShouldSaveMemoryReport::kForceReport);
5136 :
5137 : return IPC_OK();
5138 : }
5139 0 :
5140 : /* static */ void
5141 : ContentParent::BroadcastBlobURLRegistration(const nsACString& aURI,
5142 : BlobImpl* aBlobImpl,
5143 : nsIPrincipal* aPrincipal,
5144 0 : ContentParent* aIgnoreThisCP)
5145 0 : {
5146 : nsCString uri(aURI);
5147 0 : IPC::Principal principal(aPrincipal);
5148 0 :
5149 0 : for (auto* cp : AllProcesses(eLive)) {
5150 0 : if (cp != aIgnoreThisCP) {
5151 : nsresult rv = cp->TransmitPermissionsForPrincipal(principal);
5152 : if (NS_WARN_IF(NS_FAILED(rv))) {
5153 : break;
5154 0 : }
5155 0 :
5156 0 : IPCBlob ipcBlob;
5157 : rv = IPCBlobUtils::Serialize(aBlobImpl, cp, ipcBlob);
5158 : if (NS_WARN_IF(NS_FAILED(rv))) {
5159 : break;
5160 0 : }
5161 :
5162 : Unused << cp->SendBlobURLRegistration(uri, ipcBlob, principal);
5163 0 : }
5164 : }
5165 : }
5166 0 :
5167 : /* static */ void
5168 : ContentParent::BroadcastBlobURLUnregistration(const nsACString& aURI,
5169 0 : ContentParent* aIgnoreThisCP)
5170 : {
5171 0 : nsCString uri(aURI);
5172 0 :
5173 0 : for (auto* cp : AllProcesses(eLive)) {
5174 : if (cp != aIgnoreThisCP) {
5175 : Unused << cp->SendBlobURLUnregistration(uri);
5176 0 : }
5177 : }
5178 : }
5179 0 :
5180 : mozilla::ipc::IPCResult
5181 : ContentParent::RecvStoreAndBroadcastBlobURLRegistration(const nsCString& aURI,
5182 : const IPCBlob& aBlob,
5183 0 : const Principal& aPrincipal)
5184 0 : {
5185 0 : RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(aBlob);
5186 : if (NS_WARN_IF(!blobImpl)) {
5187 : return IPC_FAIL_NO_REASON(this);
5188 0 : }
5189 :
5190 0 : if (NS_SUCCEEDED(BlobURLProtocolHandler::AddDataEntry(aURI, aPrincipal,
5191 : blobImpl))) {
5192 : BroadcastBlobURLRegistration(aURI, blobImpl, aPrincipal, this);
5193 :
5194 0 : // We want to store this blobURL, so we can unregister it if the child
5195 : // crashes.
5196 : mBlobURLs.AppendElement(aURI);
5197 0 : }
5198 :
5199 : BroadcastBlobURLRegistration(aURI, blobImpl, aPrincipal, this);
5200 : return IPC_OK();
5201 : }
5202 0 :
5203 : mozilla::ipc::IPCResult
5204 0 : ContentParent::RecvUnstoreAndBroadcastBlobURLUnregistration(const nsCString& aURI)
5205 0 : {
5206 0 : BlobURLProtocolHandler::RemoveDataEntry(aURI, false /* Don't broadcast */);
5207 : BroadcastBlobURLUnregistration(aURI, this);
5208 0 : mBlobURLs.RemoveElement(aURI);
5209 :
5210 : return IPC_OK();
5211 : }
5212 0 :
5213 : mozilla::ipc::IPCResult
5214 : ContentParent::RecvGetA11yContentId(uint32_t* aContentId)
5215 : {
5216 : #if defined(XP_WIN32) && defined(ACCESSIBILITY)
5217 : *aContentId = a11y::AccessibleWrap::GetContentProcessIdFor(ChildID());
5218 : MOZ_ASSERT(*aContentId);
5219 0 : return IPC_OK();
5220 : #else
5221 : return IPC_FAIL_NO_REASON(this);
5222 : #endif
5223 : }
5224 0 :
5225 : mozilla::ipc::IPCResult
5226 : ContentParent::RecvA11yHandlerControl(const uint32_t& aPid,
5227 : const IHandlerControlHolder& aHandlerControl)
5228 : {
5229 : #if defined(XP_WIN32) && defined(ACCESSIBILITY)
5230 : MOZ_ASSERT(!aHandlerControl.IsNull());
5231 : RefPtr<IHandlerControl> proxy(aHandlerControl.Get());
5232 : a11y::AccessibleWrap::SetHandlerControl(aPid, std::move(proxy));
5233 0 : return IPC_OK();
5234 : #else
5235 : return IPC_FAIL_NO_REASON(this);
5236 : #endif
5237 : }
5238 :
5239 : } // namespace dom
5240 0 : } // namespace mozilla
5241 :
5242 : NS_IMPL_ISUPPORTS(ParentIdleListener, nsIObserver)
5243 0 :
5244 : NS_IMETHODIMP
5245 0 : ParentIdleListener::Observe(nsISupports*, const char* aTopic, const char16_t* aData)
5246 0 : {
5247 0 : mozilla::Unused << mParent->SendNotifyIdleObserver(mObserver,
5248 0 : nsDependentCString(aTopic),
5249 : nsDependentString(aData));
5250 : return NS_OK;
5251 : }
5252 0 :
5253 : bool
5254 0 : ContentParent::HandleWindowsMessages(const Message& aMsg) const
5255 : {
5256 : MOZ_ASSERT(aMsg.is_sync());
5257 :
5258 : // a11y messages can be triggered by windows messages, which means if we
5259 0 : // allow handling windows messages while we wait for the response to a sync
5260 0 : // a11y message we can reenter the ipc message sending code.
5261 : if (a11y::PDocAccessible::PDocAccessibleStart < aMsg.type() &&
5262 : a11y::PDocAccessible::PDocAccessibleEnd > aMsg.type()) {
5263 : return false;
5264 0 : }
5265 :
5266 : return true;
5267 : }
5268 0 :
5269 : mozilla::ipc::IPCResult
5270 : ContentParent::RecvGetFilesRequest(const nsID& aUUID,
5271 : const nsString& aDirectoryPath,
5272 0 : const bool& aRecursiveFlag)
5273 : {
5274 0 : MOZ_ASSERT(!mGetFilesPendingRequests.GetWeak(aUUID));
5275 0 :
5276 0 : if (!mozilla::Preferences::GetBool("dom.filesystem.pathcheck.disabled", false)) {
5277 : RefPtr<FileSystemSecurity> fss = FileSystemSecurity::Get();
5278 0 : if (NS_WARN_IF(!fss ||
5279 : !fss->ContentProcessHasAccessTo(ChildID(), aDirectoryPath))) {
5280 : return IPC_FAIL_NO_REASON(this);
5281 : }
5282 0 : }
5283 :
5284 0 : ErrorResult rv;
5285 0 : RefPtr<GetFilesHelper> helper =
5286 : GetFilesHelperParent::Create(aUUID, aDirectoryPath, aRecursiveFlag, this,
5287 0 : rv);
5288 0 :
5289 0 : if (NS_WARN_IF(rv.Failed())) {
5290 0 : if (!SendGetFilesResponse(aUUID,
5291 : GetFilesResponseFailure(rv.StealNSResult()))) {
5292 : return IPC_FAIL_NO_REASON(this);
5293 : }
5294 : return IPC_OK();
5295 0 : }
5296 :
5297 : mGetFilesPendingRequests.Put(aUUID, helper);
5298 : return IPC_OK();
5299 : }
5300 0 :
5301 : mozilla::ipc::IPCResult
5302 0 : ContentParent::RecvDeleteGetFilesRequest(const nsID& aUUID)
5303 0 : {
5304 : mGetFilesPendingRequests.Remove(aUUID);
5305 : return IPC_OK();
5306 : }
5307 0 :
5308 : void
5309 : ContentParent::SendGetFilesResponseAndForget(const nsID& aUUID,
5310 0 : const GetFilesResponseResult& aResult)
5311 0 : {
5312 : if (mGetFilesPendingRequests.Remove(aUUID)) {
5313 0 : Unused << SendGetFilesResponse(aUUID, aResult);
5314 : }
5315 : }
5316 0 :
5317 : void
5318 : ContentParent::PaintTabWhileInterruptingJS(TabParent* aTabParent,
5319 : bool aForceRepaint,
5320 0 : uint64_t aLayerObserverEpoch)
5321 : {
5322 : if (!mHangMonitorActor) {
5323 0 : return;
5324 : }
5325 : ProcessHangMonitor::PaintWhileInterruptingJS(mHangMonitorActor,
5326 0 : aTabParent,
5327 : aForceRepaint,
5328 : aLayerObserverEpoch);
5329 : }
5330 0 :
5331 : void
5332 0 : ContentParent::UpdateCookieStatus(nsIChannel *aChannel)
5333 0 : {
5334 0 : PNeckoParent *neckoParent = LoneManagedOrNullAsserts(ManagedPNeckoParent());
5335 0 : PCookieServiceParent *csParent = LoneManagedOrNullAsserts(neckoParent->ManagedPCookieServiceParent());
5336 0 : if (csParent) {
5337 : auto *cs = static_cast<CookieServiceParent*>(csParent);
5338 0 : cs->TrackCookieLoad(aChannel);
5339 : }
5340 : }
5341 0 :
5342 : nsresult
5343 0 : ContentParent::AboutToLoadHttpFtpWyciwygDocumentForChild(nsIChannel* aChannel)
5344 : {
5345 : MOZ_ASSERT(aChannel);
5346 0 :
5347 0 : nsresult rv;
5348 : bool isDocument = aChannel->IsDocument();
5349 : if (!isDocument) {
5350 0 : // We may be looking at a nsIHttpChannel which has isMainDocumentChannel set
5351 0 : // (e.g. the internal http channel for a view-source: load.).
5352 0 : nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
5353 0 : if (httpChannel) {
5354 : rv = httpChannel->GetIsMainDocumentChannel(&isDocument);
5355 : NS_ENSURE_SUCCESS(rv, rv);
5356 0 : }
5357 : }
5358 : if (!isDocument) {
5359 : return NS_OK;
5360 : }
5361 :
5362 0 : // Get the principal for the channel result, so that we can get the permission
5363 0 : // key for the document which will be created from this response.
5364 : nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
5365 : if (NS_WARN_IF(!ssm)) {
5366 : return NS_ERROR_FAILURE;
5367 0 : }
5368 0 :
5369 0 : nsCOMPtr<nsIPrincipal> principal;
5370 : rv = ssm->GetChannelResultPrincipal(aChannel, getter_AddRefs(principal));
5371 0 : NS_ENSURE_SUCCESS(rv, rv);
5372 0 :
5373 : rv = TransmitPermissionsForPrincipal(principal);
5374 : NS_ENSURE_SUCCESS(rv, rv);
5375 0 :
5376 0 : nsLoadFlags newLoadFlags;
5377 0 : aChannel->GetLoadFlags(&newLoadFlags);
5378 : if (newLoadFlags & nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE) {
5379 : UpdateCookieStatus(aChannel);
5380 : }
5381 :
5382 : return NS_OK;
5383 : }
5384 0 :
5385 : nsresult
5386 : ContentParent::TransmitPermissionsForPrincipal(nsIPrincipal* aPrincipal)
5387 : {
5388 0 : // Create the key, and send it down to the content process.
5389 0 : nsTArray<nsCString> keys =
5390 0 : nsPermissionManager::GetAllKeysForPrincipal(aPrincipal);
5391 0 : MOZ_ASSERT(keys.Length() >= 1);
5392 : for (auto& key : keys) {
5393 : EnsurePermissionsByKey(key);
5394 0 : }
5395 :
5396 : return NS_OK;
5397 : }
5398 1 :
5399 : void
5400 : ContentParent::EnsurePermissionsByKey(const nsCString& aKey)
5401 : {
5402 : // NOTE: Make sure to initialize the permission manager before updating the
5403 : // mActivePermissionKeys list. If the permission manager is being initialized
5404 : // by this call to GetPermissionManager, and we've added the key to
5405 : // mActivePermissionKeys, then the permission manager will send down a
5406 2 : // SendAddPermission before receiving the SendSetPermissionsWithKey message.
5407 : nsCOMPtr<nsIPermissionManager> permManager =
5408 1 : services::GetPermissionManager();
5409 0 :
5410 : if (mActivePermissionKeys.Contains(aKey)) {
5411 1 : return;
5412 : }
5413 2 : mActivePermissionKeys.PutEntry(aKey);
5414 0 :
5415 0 : nsTArray<IPC::Permission> perms;
5416 : nsresult rv = permManager->GetPermissionsWithKey(aKey, perms);
5417 : if (NS_WARN_IF(NS_FAILED(rv))) {
5418 : return;
5419 0 : }
5420 :
5421 : Unused << SendSetPermissionsWithKey(aKey, perms);
5422 : }
5423 3 :
5424 : bool
5425 0 : ContentParent::NeedsPermissionsUpdate(const nsACString& aPermissionKey) const
5426 : {
5427 : return mActivePermissionKeys.Contains(aPermissionKey);
5428 : }
5429 0 :
5430 : mozilla::ipc::IPCResult
5431 : ContentParent::RecvAccumulateChildHistograms(
5432 2 : InfallibleTArray<HistogramAccumulation>&& aAccumulations)
5433 2 : {
5434 : TelemetryIPC::AccumulateChildHistograms(GetTelemetryProcessID(mRemoteType), aAccumulations);
5435 : return IPC_OK();
5436 : }
5437 2 :
5438 : mozilla::ipc::IPCResult
5439 : ContentParent::RecvAccumulateChildKeyedHistograms(
5440 2 : InfallibleTArray<KeyedHistogramAccumulation>&& aAccumulations)
5441 2 : {
5442 : TelemetryIPC::AccumulateChildKeyedHistograms(GetTelemetryProcessID(mRemoteType), aAccumulations);
5443 : return IPC_OK();
5444 : }
5445 0 :
5446 : mozilla::ipc::IPCResult
5447 : ContentParent::RecvUpdateChildScalars(
5448 0 : InfallibleTArray<ScalarAction>&& aScalarActions)
5449 0 : {
5450 : TelemetryIPC::UpdateChildScalars(GetTelemetryProcessID(mRemoteType), aScalarActions);
5451 : return IPC_OK();
5452 : }
5453 0 :
5454 : mozilla::ipc::IPCResult
5455 : ContentParent::RecvUpdateChildKeyedScalars(
5456 0 : InfallibleTArray<KeyedScalarAction>&& aScalarActions)
5457 0 : {
5458 : TelemetryIPC::UpdateChildKeyedScalars(GetTelemetryProcessID(mRemoteType), aScalarActions);
5459 : return IPC_OK();
5460 : }
5461 0 :
5462 : mozilla::ipc::IPCResult
5463 0 : ContentParent::RecvRecordChildEvents(nsTArray<mozilla::Telemetry::ChildEventData>&& aEvents)
5464 0 : {
5465 : TelemetryIPC::RecordChildEvents(GetTelemetryProcessID(mRemoteType), aEvents);
5466 : return IPC_OK();
5467 : }
5468 2 :
5469 : mozilla::ipc::IPCResult
5470 : ContentParent::RecvRecordDiscardedData(
5471 2 : const mozilla::Telemetry::DiscardedData& aDiscardedData)
5472 2 : {
5473 2 : TelemetryIPC::RecordDiscardedData(GetTelemetryProcessID(mRemoteType),
5474 : aDiscardedData);
5475 : return IPC_OK();
5476 : }
5477 :
5478 : //////////////////////////////////////////////////////////////////
5479 : // PURLClassifierParent
5480 0 :
5481 : PURLClassifierParent*
5482 : ContentParent::AllocPURLClassifierParent(const Principal& aPrincipal,
5483 : const bool& aUseTrackingProtection,
5484 0 : bool* aSuccess)
5485 : {
5486 0 : MOZ_ASSERT(NS_IsMainThread());
5487 0 :
5488 0 : *aSuccess = true;
5489 : RefPtr<URLClassifierParent> actor = new URLClassifierParent();
5490 : return actor.forget().take();
5491 : }
5492 0 :
5493 : mozilla::ipc::IPCResult
5494 : ContentParent::RecvPURLClassifierConstructor(PURLClassifierParent* aActor,
5495 : const Principal& aPrincipal,
5496 : const bool& aUseTrackingProtection,
5497 0 : bool* aSuccess)
5498 0 : {
5499 0 : MOZ_ASSERT(NS_IsMainThread());
5500 : MOZ_ASSERT(aActor);
5501 0 : *aSuccess = false;
5502 0 :
5503 0 : auto* actor = static_cast<URLClassifierParent*>(aActor);
5504 0 : nsCOMPtr<nsIPrincipal> principal(aPrincipal);
5505 : if (!principal) {
5506 : actor->ClassificationFailed();
5507 0 : return IPC_OK();
5508 : }
5509 : return actor->StartClassify(principal, aUseTrackingProtection, aSuccess);
5510 : }
5511 0 :
5512 : bool
5513 0 : ContentParent::DeallocPURLClassifierParent(PURLClassifierParent* aActor)
5514 0 : {
5515 : MOZ_ASSERT(NS_IsMainThread());
5516 : MOZ_ASSERT(aActor);
5517 0 :
5518 0 : RefPtr<URLClassifierParent> actor =
5519 : dont_AddRef(static_cast<URLClassifierParent*>(aActor));
5520 : return true;
5521 : }
5522 :
5523 : //////////////////////////////////////////////////////////////////
5524 : // PURLClassifierLocalParent
5525 0 :
5526 : PURLClassifierLocalParent*
5527 : ContentParent::AllocPURLClassifierLocalParent(const URIParams& aURI,
5528 0 : const nsCString& aTables)
5529 : {
5530 0 : MOZ_ASSERT(NS_IsMainThread());
5531 0 :
5532 : RefPtr<URLClassifierLocalParent> actor = new URLClassifierLocalParent();
5533 : return actor.forget().take();
5534 : }
5535 0 :
5536 : mozilla::ipc::IPCResult
5537 : ContentParent::RecvPURLClassifierLocalConstructor(PURLClassifierLocalParent* aActor,
5538 : const URIParams& aURI,
5539 0 : const nsCString& aTables)
5540 0 : {
5541 : MOZ_ASSERT(NS_IsMainThread());
5542 0 : MOZ_ASSERT(aActor);
5543 0 :
5544 0 : nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
5545 0 : if (!uri) {
5546 : NS_WARNING("Failed to DeserializeURI");
5547 : return IPC_FAIL_NO_REASON(this);
5548 0 : }
5549 0 :
5550 : auto* actor = static_cast<URLClassifierLocalParent*>(aActor);
5551 : return actor->StartClassify(uri, aTables);
5552 : }
5553 0 :
5554 : bool
5555 0 : ContentParent::DeallocPURLClassifierLocalParent(PURLClassifierLocalParent* aActor)
5556 0 : {
5557 : MOZ_ASSERT(NS_IsMainThread());
5558 : MOZ_ASSERT(aActor);
5559 0 :
5560 0 : RefPtr<URLClassifierLocalParent> actor =
5561 : dont_AddRef(static_cast<URLClassifierLocalParent*>(aActor));
5562 : return true;
5563 : }
5564 0 :
5565 : PLoginReputationParent*
5566 0 : ContentParent::AllocPLoginReputationParent(const URIParams& aURI)
5567 : {
5568 0 : MOZ_ASSERT(NS_IsMainThread());
5569 0 :
5570 : RefPtr<LoginReputationParent> actor = new LoginReputationParent();
5571 : return actor.forget().take();
5572 : }
5573 0 :
5574 : mozilla::ipc::IPCResult
5575 : ContentParent::RecvPLoginReputationConstructor(PLoginReputationParent* aActor,
5576 0 : const URIParams& aURI)
5577 0 : {
5578 : MOZ_ASSERT(NS_IsMainThread());
5579 0 : MOZ_ASSERT(aActor);
5580 0 :
5581 0 : nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
5582 : if (!uri) {
5583 : return IPC_FAIL_NO_REASON(this);
5584 0 : }
5585 0 :
5586 : auto* actor = static_cast<LoginReputationParent*>(aActor);
5587 : return actor->QueryReputation(uri);
5588 : }
5589 0 :
5590 : bool
5591 0 : ContentParent::DeallocPLoginReputationParent(PLoginReputationParent* aActor)
5592 0 : {
5593 : MOZ_ASSERT(NS_IsMainThread());
5594 : MOZ_ASSERT(aActor);
5595 0 :
5596 0 : RefPtr<LoginReputationParent> actor =
5597 : dont_AddRef(static_cast<LoginReputationParent*>(aActor));
5598 : return true;
5599 : }
5600 0 :
5601 : mozilla::ipc::IPCResult
5602 : ContentParent::RecvClassifyLocal(const URIParams& aURI, const nsCString& aTables,
5603 0 : nsresult *aRv, nsTArray<nsCString>* aResults)
5604 0 : {
5605 0 : MOZ_ASSERT(aResults);
5606 0 : nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
5607 : if (!uri) {
5608 : return IPC_FAIL_NO_REASON(this);
5609 0 : }
5610 0 : nsCOMPtr<nsIURIClassifier> uriClassifier =
5611 0 : do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID);
5612 : if (!uriClassifier) {
5613 0 : return IPC_FAIL_NO_REASON(this);
5614 : }
5615 : *aRv = uriClassifier->ClassifyLocalWithTables(uri, aTables, *aResults);
5616 : return IPC_OK();
5617 : }
5618 0 :
5619 : mozilla::ipc::IPCResult
5620 : ContentParent::RecvFileCreationRequest(const nsID& aID,
5621 : const nsString& aFullPath,
5622 : const nsString& aType,
5623 : const nsString& aName,
5624 : const bool& aLastModifiedPassed,
5625 : const int64_t& aLastModified,
5626 : const bool& aExistenceCheck,
5627 : const bool& aIsFromNsIFile)
5628 : {
5629 0 : // We allow the creation of File via this IPC call only for the 'file' process
5630 0 : // or for testing.
5631 0 : if (!mRemoteType.EqualsLiteral(FILE_REMOTE_TYPE) &&
5632 : !Preferences::GetBool("dom.file.createInChild", false)) {
5633 : return IPC_FAIL_NO_REASON(this);
5634 0 : }
5635 :
5636 0 : RefPtr<BlobImpl> blobImpl;
5637 0 : nsresult rv =
5638 0 : FileCreatorHelper::CreateBlobImplForIPC(aFullPath, aType, aName,
5639 0 : aLastModifiedPassed,
5640 0 : aLastModified, aExistenceCheck,
5641 0 : aIsFromNsIFile,
5642 0 : getter_AddRefs(blobImpl));
5643 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
5644 : if (!SendFileCreationResponse(aID, FileCreationErrorResult(rv))) {
5645 : return IPC_FAIL_NO_REASON(this);
5646 : }
5647 :
5648 : return IPC_OK();
5649 0 : }
5650 :
5651 0 : MOZ_ASSERT(blobImpl);
5652 0 :
5653 0 : IPCBlob ipcBlob;
5654 0 : rv = IPCBlobUtils::Serialize(blobImpl, this, ipcBlob);
5655 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
5656 : if (!SendFileCreationResponse(aID, FileCreationErrorResult(rv))) {
5657 : return IPC_FAIL_NO_REASON(this);
5658 : }
5659 :
5660 : return IPC_OK();
5661 0 : }
5662 0 :
5663 : if (!SendFileCreationResponse(aID, FileCreationSuccessResult(ipcBlob))) {
5664 : return IPC_FAIL_NO_REASON(this);
5665 : }
5666 :
5667 : return IPC_OK();
5668 : }
5669 0 :
5670 : bool
5671 : ContentParent::CanCommunicateWith(ContentParentId aOtherProcess)
5672 : {
5673 0 : // Normally a process can only communicate with its parent, but a JS plugin process can
5674 0 : // communicate with any process.
5675 0 : ContentProcessManager *cpm = ContentProcessManager::GetSingleton();
5676 : ContentParentId parentId;
5677 : if (!cpm->GetParentProcessId(ChildID(), &parentId)) {
5678 0 : return false;
5679 0 : }
5680 : if (IsForJSPlugin()) {
5681 0 : return parentId == ContentParentId(0);
5682 : }
5683 : return parentId == aOtherProcess;
5684 : }
5685 0 :
5686 : mozilla::ipc::IPCResult
5687 0 : ContentParent::RecvMaybeReloadPlugins()
5688 0 : {
5689 0 : RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
5690 : pluginHost->ReloadPlugins();
5691 : return IPC_OK();
5692 : }
5693 0 :
5694 : mozilla::ipc::IPCResult
5695 0 : ContentParent::RecvDeviceReset()
5696 0 : {
5697 0 : GPUProcessManager* pm = GPUProcessManager::Get();
5698 : if (pm) {
5699 : pm->SimulateDeviceReset();
5700 0 : }
5701 :
5702 : return IPC_OK();
5703 : }
5704 0 :
5705 : mozilla::ipc::IPCResult
5706 0 : ContentParent::RecvBHRThreadHang(const HangDetails& aDetails)
5707 0 : {
5708 : nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
5709 : if (obs) {
5710 : // Copy the HangDetails recieved over the network into a nsIHangDetails, and
5711 : // then fire our own observer notification.
5712 : // XXX: We should be able to avoid this potentially expensive copy here by
5713 0 : // moving our deserialized argument.
5714 0 : nsCOMPtr<nsIHangDetails> hangDetails =
5715 : new nsHangDetails(HangDetails(aDetails));
5716 0 : obs->NotifyObservers(hangDetails, "bhr-thread-hang", nullptr);
5717 : }
5718 : return IPC_OK();
5719 : }
|