Coverage Report

Created: 2018-09-25 14:53

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