Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/ipc/ContentChild.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
#ifdef MOZ_WIDGET_GTK
8
#include <gtk/gtk.h>
9
#endif
10
11
#include "ContentChild.h"
12
13
#include "GeckoProfiler.h"
14
#include "TabChild.h"
15
#include "HandlerServiceChild.h"
16
17
#include "mozilla/Attributes.h"
18
#include "mozilla/BackgroundHangMonitor.h"
19
#include "mozilla/LookAndFeel.h"
20
#include "mozilla/NullPrincipal.h"
21
#include "mozilla/Preferences.h"
22
#include "mozilla/ProcessHangMonitorIPC.h"
23
#include "mozilla/Unused.h"
24
#include "mozilla/StaticPrefs.h"
25
#include "mozilla/TelemetryIPC.h"
26
#include "mozilla/devtools/HeapSnapshotTempFileHelperChild.h"
27
#include "mozilla/docshell/OfflineCacheUpdateChild.h"
28
#include "mozilla/dom/ClientManager.h"
29
#include "mozilla/dom/ClientOpenWindowOpActors.h"
30
#include "mozilla/dom/ChildProcessMessageManager.h"
31
#include "mozilla/dom/ContentBridgeChild.h"
32
#include "mozilla/dom/ContentBridgeParent.h"
33
#include "mozilla/dom/ContentProcessMessageManager.h"
34
#include "mozilla/dom/DOMPrefs.h"
35
#include "mozilla/dom/VideoDecoderManagerChild.h"
36
#include "mozilla/dom/ContentParent.h"
37
#include "mozilla/dom/DataTransfer.h"
38
#include "mozilla/dom/DocGroup.h"
39
#include "mozilla/dom/ExternalHelperAppChild.h"
40
#include "mozilla/dom/FileCreatorHelper.h"
41
#include "mozilla/dom/GetFilesHelper.h"
42
#include "mozilla/dom/IPCBlobUtils.h"
43
#include "mozilla/dom/MemoryReportRequest.h"
44
#include "mozilla/dom/PLoginReputationChild.h"
45
#include "mozilla/dom/PushNotifier.h"
46
#include "mozilla/dom/ServiceWorkerManager.h"
47
#include "mozilla/dom/TabGroup.h"
48
#include "mozilla/dom/nsIContentChild.h"
49
#include "mozilla/dom/URLClassifierChild.h"
50
#include "mozilla/dom/WorkerDebugger.h"
51
#include "mozilla/dom/WorkerDebuggerManager.h"
52
#include "mozilla/dom/ipc/SharedMap.h"
53
#include "mozilla/gfx/gfxVars.h"
54
#include "mozilla/gfx/Logging.h"
55
#include "mozilla/psm/PSMContentListener.h"
56
#include "mozilla/hal_sandbox/PHalChild.h"
57
#include "mozilla/ipc/BackgroundChild.h"
58
#include "mozilla/ipc/FileDescriptorSetChild.h"
59
#include "mozilla/ipc/FileDescriptorUtils.h"
60
#include "mozilla/ipc/GeckoChildProcessHost.h"
61
#include "mozilla/ipc/ProcessChild.h"
62
#include "mozilla/ipc/PChildToParentStreamChild.h"
63
#include "mozilla/intl/LocaleService.h"
64
#include "mozilla/ipc/TestShellChild.h"
65
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
66
#include "mozilla/jsipc/PJavaScript.h"
67
#include "mozilla/layers/APZChild.h"
68
#include "mozilla/layers/CompositorManagerChild.h"
69
#include "mozilla/layers/ContentProcessController.h"
70
#include "mozilla/layers/ImageBridgeChild.h"
71
#include "mozilla/layout/RenderFrameChild.h"
72
#include "mozilla/loader/ScriptCacheActors.h"
73
#include "mozilla/net/NeckoChild.h"
74
#include "mozilla/net/CookieServiceChild.h"
75
#include "mozilla/net/CaptivePortalService.h"
76
#include "mozilla/PerformanceMetricsCollector.h"
77
#include "mozilla/PerformanceUtils.h"
78
#include "mozilla/plugins/PluginInstanceParent.h"
79
#include "mozilla/plugins/PluginModuleParent.h"
80
#include "mozilla/recordreplay/ParentIPC.h"
81
#include "mozilla/widget/ScreenManager.h"
82
#include "mozilla/widget/WidgetMessageUtils.h"
83
#include "nsBaseDragService.h"
84
#include "mozilla/media/MediaChild.h"
85
#include "mozilla/BasePrincipal.h"
86
#include "mozilla/WebBrowserPersistDocumentChild.h"
87
#include "mozilla/HangDetails.h"
88
#include "imgLoader.h"
89
#include "GMPServiceChild.h"
90
#include "nsISimpleEnumerator.h"
91
#include "nsIStringBundle.h"
92
#include "nsIWorkerDebuggerManager.h"
93
#include "nsGeolocation.h"
94
95
#if !defined(XP_WIN)
96
#include "mozilla/Omnijar.h"
97
#endif
98
99
#ifdef MOZ_GECKO_PROFILER
100
#include "ChildProfilerController.h"
101
#endif
102
103
#if defined(MOZ_CONTENT_SANDBOX)
104
#include "mozilla/SandboxSettings.h"
105
#if defined(XP_WIN)
106
#include "mozilla/sandboxTarget.h"
107
#elif defined(XP_LINUX)
108
#include "mozilla/Sandbox.h"
109
#include "mozilla/SandboxInfo.h"
110
#include "CubebUtils.h"
111
#elif defined(XP_MACOSX)
112
#include "mozilla/Sandbox.h"
113
#elif defined(__OpenBSD__)
114
#include <unistd.h>
115
#endif
116
#endif
117
118
#include "mozilla/Unused.h"
119
120
#include "mozInlineSpellChecker.h"
121
#include "nsDocShell.h"
122
#include "nsDocShellLoadInfo.h"
123
#include "nsIConsoleListener.h"
124
#include "nsIContentViewer.h"
125
#include "nsICycleCollectorListener.h"
126
#include "nsIIdlePeriod.h"
127
#include "nsIDragService.h"
128
#include "nsIInterfaceRequestorUtils.h"
129
#include "nsIMemoryReporter.h"
130
#include "nsIMemoryInfoDumper.h"
131
#include "nsIMutable.h"
132
#include "nsIObserverService.h"
133
#include "nsIScriptSecurityManager.h"
134
#include "nsMemoryInfoDumper.h"
135
#include "nsServiceManagerUtils.h"
136
#include "nsStyleSheetService.h"
137
#include "nsVariant.h"
138
#include "nsXULAppAPI.h"
139
#include "nsIScriptError.h"
140
#include "nsIConsoleService.h"
141
#include "nsJSEnvironment.h"
142
#include "SandboxHal.h"
143
#include "nsDebugImpl.h"
144
#include "nsHashPropertyBag.h"
145
#include "nsLayoutStylesheetCache.h"
146
#include "nsThreadManager.h"
147
#include "nsAnonymousTemporaryFile.h"
148
#include "nsISpellChecker.h"
149
#include "nsClipboardProxy.h"
150
#include "nsDirectoryService.h"
151
#include "nsDirectoryServiceUtils.h"
152
#include "nsDirectoryServiceDefs.h"
153
#include "nsContentPermissionHelper.h"
154
#include "nsPluginHost.h"
155
#ifdef NS_PRINTING
156
#include "nsPrintingProxy.h"
157
#endif
158
#include "nsWindowMemoryReporter.h"
159
160
#include "IHistory.h"
161
#include "nsNetUtil.h"
162
163
#include "base/message_loop.h"
164
#include "base/process_util.h"
165
#include "base/task.h"
166
167
#include "nsChromeRegistryContent.h"
168
#include "nsFrameMessageManager.h"
169
170
#include "nsIGeolocationProvider.h"
171
#include "mozilla/dom/PCycleCollectWithLogsChild.h"
172
173
#include "nsIScriptSecurityManager.h"
174
#include "mozilla/dom/BlobURLProtocolHandler.h"
175
176
#ifdef MOZ_WEBRTC
177
#include "signaling/src/peerconnection/WebrtcGlobalChild.h"
178
#endif
179
180
#include "nsPermission.h"
181
#include "nsPermissionManager.h"
182
183
#include "PermissionMessageUtils.h"
184
185
#if defined(MOZ_WIDGET_ANDROID)
186
#include "APKOpen.h"
187
#endif
188
189
#ifdef XP_WIN
190
#include <process.h>
191
#define getpid _getpid
192
#include "mozilla/widget/AudioSession.h"
193
#include "mozilla/audio/AudioNotificationReceiver.h"
194
#endif
195
196
#if defined(XP_MACOSX)
197
#include <CoreServices/CoreServices.h>
198
// Info.plist key associated with the developer repo path
199
#define MAC_DEV_REPO_KEY "MozillaDeveloperRepoPath"
200
// Info.plist key associated with the developer repo object directory
201
#define MAC_DEV_OBJ_KEY "MozillaDeveloperObjPath"
202
#endif /* XP_MACOSX */
203
204
#ifdef MOZ_X11
205
#include "mozilla/X11Util.h"
206
#endif
207
208
#ifdef ACCESSIBILITY
209
#include "nsAccessibilityService.h"
210
#ifdef XP_WIN
211
#include "mozilla/a11y/AccessibleWrap.h"
212
#endif
213
#endif
214
215
#include "mozilla/dom/File.h"
216
#include "mozilla/dom/PPresentationChild.h"
217
#include "mozilla/dom/PresentationIPCService.h"
218
#include "mozilla/ipc/InputStreamUtils.h"
219
220
#ifdef MOZ_WEBSPEECH
221
#include "mozilla/dom/PSpeechSynthesisChild.h"
222
#endif
223
224
#include "ClearOnShutdown.h"
225
#include "ProcessUtils.h"
226
#include "URIUtils.h"
227
#include "nsContentUtils.h"
228
#include "nsIPrincipal.h"
229
#include "DomainPolicy.h"
230
#include "mozilla/dom/ipc/StructuredCloneData.h"
231
#include "mozilla/ipc/CrashReporterClient.h"
232
#include "mozilla/net/NeckoMessageUtils.h"
233
#include "mozilla/widget/PuppetBidiKeyboard.h"
234
#include "mozilla/RemoteSpellCheckEngineChild.h"
235
#include "GMPServiceChild.h"
236
#include "GfxInfoBase.h"
237
#include "gfxPlatform.h"
238
#include "nscore.h" // for NS_FREE_PERMANENT_DATA
239
#include "VRManagerChild.h"
240
#include "private/pprio.h"
241
#include "nsString.h"
242
243
#ifdef MOZ_WIDGET_GTK
244
#include "nsAppRunner.h"
245
#endif
246
247
#ifdef MOZ_CODE_COVERAGE
248
#include "mozilla/CodeCoverageHandler.h"
249
#endif
250
251
using namespace mozilla;
252
using namespace mozilla::docshell;
253
using namespace mozilla::dom::ipc;
254
using namespace mozilla::media;
255
using namespace mozilla::embedding;
256
using namespace mozilla::gmp;
257
using namespace mozilla::hal_sandbox;
258
using namespace mozilla::ipc;
259
using namespace mozilla::intl;
260
using namespace mozilla::layers;
261
using namespace mozilla::layout;
262
using namespace mozilla::net;
263
using namespace mozilla::jsipc;
264
using namespace mozilla::psm;
265
using namespace mozilla::widget;
266
using mozilla::loader::PScriptCacheChild;
267
268
namespace mozilla {
269
270
namespace dom {
271
272
// IPC sender for remote GC/CC logging.
273
class CycleCollectWithLogsChild final
274
  : public PCycleCollectWithLogsChild
275
  , public nsICycleCollectorLogSink
276
{
277
public:
278
  NS_DECL_ISUPPORTS
279
280
  CycleCollectWithLogsChild(const FileDescriptor& aGCLog,
281
                            const FileDescriptor& aCCLog)
282
0
  {
283
0
    mGCLog = FileDescriptorToFILE(aGCLog, "w");
284
0
    mCCLog = FileDescriptorToFILE(aCCLog, "w");
285
0
  }
286
287
  NS_IMETHOD Open(FILE** aGCLog, FILE** aCCLog) override
288
0
  {
289
0
    if (NS_WARN_IF(!mGCLog) || NS_WARN_IF(!mCCLog)) {
290
0
      return NS_ERROR_FAILURE;
291
0
    }
292
0
    *aGCLog = mGCLog;
293
0
    *aCCLog = mCCLog;
294
0
    return NS_OK;
295
0
  }
296
297
  NS_IMETHOD CloseGCLog() override
298
0
  {
299
0
    MOZ_ASSERT(mGCLog);
300
0
    fclose(mGCLog);
301
0
    mGCLog = nullptr;
302
0
    SendCloseGCLog();
303
0
    return NS_OK;
304
0
  }
305
306
  NS_IMETHOD CloseCCLog() override
307
0
  {
308
0
    MOZ_ASSERT(mCCLog);
309
0
    fclose(mCCLog);
310
0
    mCCLog = nullptr;
311
0
    SendCloseCCLog();
312
0
    return NS_OK;
313
0
  }
314
315
  NS_IMETHOD GetFilenameIdentifier(nsAString& aIdentifier) override
316
0
  {
317
0
    return UnimplementedProperty();
318
0
  }
319
320
  NS_IMETHOD SetFilenameIdentifier(const nsAString& aIdentifier) override
321
0
  {
322
0
    return UnimplementedProperty();
323
0
  }
324
325
  NS_IMETHOD GetProcessIdentifier(int32_t *aIdentifier) override
326
0
  {
327
0
    return UnimplementedProperty();
328
0
  }
329
330
  NS_IMETHOD SetProcessIdentifier(int32_t aIdentifier) override
331
0
  {
332
0
    return UnimplementedProperty();
333
0
  }
334
335
  NS_IMETHOD GetGcLog(nsIFile** aPath) override
336
0
  {
337
0
    return UnimplementedProperty();
338
0
  }
339
340
  NS_IMETHOD GetCcLog(nsIFile** aPath) override
341
0
  {
342
0
    return UnimplementedProperty();
343
0
  }
344
345
private:
346
  ~CycleCollectWithLogsChild() override
347
0
  {
348
0
    if (mGCLog) {
349
0
      fclose(mGCLog);
350
0
      mGCLog = nullptr;
351
0
    }
352
0
    if (mCCLog) {
353
0
      fclose(mCCLog);
354
0
      mCCLog = nullptr;
355
0
    }
356
0
    // The XPCOM refcount drives the IPC lifecycle; see also
357
0
    // DeallocPCycleCollectWithLogsChild.
358
0
    Unused << Send__delete__(this);
359
0
  }
360
361
  nsresult UnimplementedProperty()
362
0
  {
363
0
    MOZ_ASSERT(false, "This object is a remote GC/CC logger;"
364
0
                      " this property isn't meaningful.");
365
0
    return NS_ERROR_UNEXPECTED;
366
0
  }
367
368
  FILE* mGCLog;
369
  FILE* mCCLog;
370
};
371
372
NS_IMPL_ISUPPORTS(CycleCollectWithLogsChild, nsICycleCollectorLogSink);
373
374
class AlertObserver
375
{
376
public:
377
378
  AlertObserver(nsIObserver *aObserver, const nsString& aData)
379
    : mObserver(aObserver)
380
    , mData(aData)
381
0
  {
382
0
  }
383
384
0
  ~AlertObserver() = default;
385
386
  bool ShouldRemoveFrom(nsIObserver* aObserver,
387
                        const nsString& aData) const
388
0
  {
389
0
    return (mObserver == aObserver && mData == aData);
390
0
  }
391
392
  bool Observes(const nsString& aData) const
393
0
  {
394
0
    return mData.Equals(aData);
395
0
  }
396
397
  bool Notify(const nsCString& aType) const
398
0
  {
399
0
    mObserver->Observe(nullptr, aType.get(), mData.get());
400
0
    return true;
401
0
  }
402
403
private:
404
  nsCOMPtr<nsIObserver> mObserver;
405
  nsString mData;
406
};
407
408
class ConsoleListener final : public nsIConsoleListener
409
{
410
public:
411
  explicit ConsoleListener(ContentChild* aChild)
412
0
  : mChild(aChild) {}
413
414
  NS_DECL_ISUPPORTS
415
  NS_DECL_NSICONSOLELISTENER
416
417
private:
418
  ~ConsoleListener() = default;
419
420
  ContentChild* mChild;
421
  friend class ContentChild;
422
};
423
424
NS_IMPL_ISUPPORTS(ConsoleListener, nsIConsoleListener)
425
426
// Before we send the error to the parent process (which
427
// involves copying the memory), truncate any long lines.  CSS
428
// errors in particular share the memory for long lines with
429
// repeated errors, but the IPC communication we're about to do
430
// will break that sharing, so we better truncate now.
431
static void
432
TruncateString(nsAString& aString)
433
0
{
434
0
  if (aString.Length() > 1000) {
435
0
    aString.Truncate(1000);
436
0
  }
437
0
}
438
439
NS_IMETHODIMP
440
ConsoleListener::Observe(nsIConsoleMessage* aMessage)
441
0
{
442
0
  if (!mChild) {
443
0
    return NS_OK;
444
0
  }
445
0
446
0
  nsCOMPtr<nsIScriptError> scriptError = do_QueryInterface(aMessage);
447
0
  if (scriptError) {
448
0
    nsAutoString msg, sourceName, sourceLine;
449
0
    nsCString category;
450
0
    uint32_t lineNum, colNum, flags;
451
0
    bool fromPrivateWindow;
452
0
453
0
    nsresult rv = scriptError->GetErrorMessage(msg);
454
0
    NS_ENSURE_SUCCESS(rv, rv);
455
0
    TruncateString(msg);
456
0
    rv = scriptError->GetSourceName(sourceName);
457
0
    NS_ENSURE_SUCCESS(rv, rv);
458
0
    TruncateString(sourceName);
459
0
    rv = scriptError->GetSourceLine(sourceLine);
460
0
    NS_ENSURE_SUCCESS(rv, rv);
461
0
    TruncateString(sourceLine);
462
0
463
0
    rv = scriptError->GetCategory(getter_Copies(category));
464
0
    NS_ENSURE_SUCCESS(rv, rv);
465
0
    rv = scriptError->GetLineNumber(&lineNum);
466
0
    NS_ENSURE_SUCCESS(rv, rv);
467
0
    rv = scriptError->GetColumnNumber(&colNum);
468
0
    NS_ENSURE_SUCCESS(rv, rv);
469
0
    rv = scriptError->GetFlags(&flags);
470
0
    NS_ENSURE_SUCCESS(rv, rv);
471
0
    rv = scriptError->GetIsFromPrivateWindow(&fromPrivateWindow);
472
0
    NS_ENSURE_SUCCESS(rv, rv);
473
0
474
0
    {
475
0
      AutoJSAPI jsapi;
476
0
      jsapi.Init();
477
0
      JSContext* cx = jsapi.cx();
478
0
479
0
      JS::RootedValue stack(cx);
480
0
      rv = scriptError->GetStack(&stack);
481
0
      NS_ENSURE_SUCCESS(rv, rv);
482
0
483
0
      if (stack.isObject()) {
484
0
        // Because |stack| might be a cross-compartment wrapper, we can't use it
485
0
        // with JSAutoRealm. Use the stackGlobal for that.
486
0
        JS::RootedValue stackGlobal(cx);
487
0
        rv = scriptError->GetStackGlobal(&stackGlobal);
488
0
        NS_ENSURE_SUCCESS(rv, rv);
489
0
490
0
        JSAutoRealm ar(cx, &stackGlobal.toObject());
491
0
492
0
        StructuredCloneData data;
493
0
        ErrorResult err;
494
0
        data.Write(cx, stack, err);
495
0
        if (err.Failed()) {
496
0
          return err.StealNSResult();
497
0
        }
498
0
499
0
        ClonedMessageData cloned;
500
0
        if (!data.BuildClonedMessageDataForChild(mChild, cloned)) {
501
0
          return NS_ERROR_FAILURE;
502
0
        }
503
0
504
0
        mChild->SendScriptErrorWithStack(msg, sourceName, sourceLine,
505
0
                                         lineNum, colNum, flags, category,
506
0
                                         fromPrivateWindow, cloned);
507
0
        return NS_OK;
508
0
      }
509
0
    }
510
0
511
0
512
0
    mChild->SendScriptError(msg, sourceName, sourceLine,
513
0
                            lineNum, colNum, flags, category,
514
0
                            fromPrivateWindow);
515
0
    return NS_OK;
516
0
  }
517
0
518
0
  nsString msg;
519
0
  nsresult rv = aMessage->GetMessageMoz(msg);
520
0
  NS_ENSURE_SUCCESS(rv, rv);
521
0
  mChild->SendConsoleMessage(msg);
522
0
  return NS_OK;
523
0
}
524
525
#ifdef NIGHTLY_BUILD
526
/**
527
 * The singleton of this class is registered with the BackgroundHangMonitor as an
528
 * annotator, so that the hang monitor can record whether or not there were
529
 * pending input events when the thread hung.
530
 */
531
class PendingInputEventHangAnnotator final
532
  : public BackgroundHangAnnotator
533
{
534
public:
535
  virtual void AnnotateHang(BackgroundHangAnnotations& aAnnotations) override
536
0
  {
537
0
    int32_t pending = ContentChild::GetSingleton()->GetPendingInputEvents();
538
0
    if (pending > 0) {
539
0
      aAnnotations.AddAnnotation(NS_LITERAL_STRING("PendingInput"), pending);
540
0
    }
541
0
  }
542
543
  static PendingInputEventHangAnnotator sSingleton;
544
};
545
PendingInputEventHangAnnotator PendingInputEventHangAnnotator::sSingleton;
546
#endif
547
548
class ContentChild::ShutdownCanary final
549
{ };
550
551
ContentChild* ContentChild::sSingleton;
552
StaticAutoPtr<ContentChild::ShutdownCanary> ContentChild::sShutdownCanary;
553
554
ContentChild::ContentChild()
555
 : mID(uint64_t(-1))
556
#if defined(XP_WIN) && defined(ACCESSIBILITY)
557
 , mMainChromeTid(0)
558
 , mMsaaID(0)
559
#endif
560
 , mIsForBrowser(false)
561
 , mIsAlive(true)
562
 , mShuttingDown(false)
563
0
{
564
0
  // This process is a content process, so it's clearly running in
565
0
  // multiprocess mode!
566
0
  nsDebugImpl::SetMultiprocessMode("Child");
567
0
568
0
  // When ContentChild is created, the observer service does not even exist.
569
0
  // When ContentChild::RecvSetXPCOMProcessAttributes is called (the first
570
0
  // IPDL call made on this object), shutdown may have already happened. Thus
571
0
  // we create a canary here that relies upon getting cleared if shutdown
572
0
  // happens without requiring the observer service at this time.
573
0
  if (!sShutdownCanary) {
574
0
    sShutdownCanary = new ShutdownCanary();
575
0
    ClearOnShutdown(&sShutdownCanary, ShutdownPhase::Shutdown);
576
0
  }
577
0
}
578
579
#ifdef _MSC_VER
580
#pragma warning(push)
581
#pragma warning(disable:4722) /* Silence "destructor never returns" warning */
582
#endif
583
584
ContentChild::~ContentChild()
585
0
{
586
0
#ifndef NS_FREE_PERMANENT_DATA
587
0
  MOZ_CRASH("Content Child shouldn't be destroyed.");
588
0
#endif
589
0
}
590
591
#ifdef _MSC_VER
592
#pragma warning(pop)
593
#endif
594
595
0
NS_INTERFACE_MAP_BEGIN(ContentChild)
596
0
  NS_INTERFACE_MAP_ENTRY(nsIContentChild)
597
0
  NS_INTERFACE_MAP_ENTRY(nsIWindowProvider)
598
0
  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentChild)
599
0
NS_INTERFACE_MAP_END
600
601
602
mozilla::ipc::IPCResult
603
ContentChild::RecvSetXPCOMProcessAttributes(const XPCOMInitData& aXPCOMInit,
604
                                            const StructuredCloneData& aInitialData,
605
                                            nsTArray<LookAndFeelInt>&& aLookAndFeelIntCache,
606
                                            nsTArray<SystemFontListEntry>&& aFontList)
607
0
{
608
0
  if (!sShutdownCanary) {
609
0
    return IPC_OK();
610
0
  }
611
0
612
0
  mLookAndFeelCache = std::move(aLookAndFeelIntCache);
613
0
  mFontList = std::move(aFontList);
614
0
  gfx::gfxVars::SetValuesForInitialize(aXPCOMInit.gfxNonDefaultVarUpdates());
615
0
  InitXPCOM(aXPCOMInit, aInitialData);
616
0
  InitGraphicsDeviceData(aXPCOMInit.contentDeviceData());
617
0
618
0
  return IPC_OK();
619
0
}
620
621
bool
622
ContentChild::Init(MessageLoop* aIOLoop,
623
                   base::ProcessId aParentPid,
624
                   const char* aParentBuildID,
625
                   IPC::Channel* aChannel,
626
                   uint64_t aChildID,
627
                   bool aIsForBrowser)
628
0
{
629
0
#ifdef MOZ_WIDGET_GTK
630
0
  // When running X11 only build we need to pass a display down
631
0
  // to gtk_init because it's not going to use the one from the environment
632
0
  // on its own when deciding which backend to use, and when starting under
633
0
  // XWayland, it may choose to start with the wayland backend
634
0
  // instead of the x11 backend.
635
0
  // The DISPLAY environment variable is normally set by the parent process.
636
0
  // The MOZ_GDK_DISPLAY environment variable is set from nsAppRunner.cpp
637
0
  // when --display is set by the command line.
638
0
  if (!gfxPlatform::IsHeadless()) {
639
0
    const char* display_name = PR_GetEnv("MOZ_GDK_DISPLAY");
640
0
#ifndef MOZ_WAYLAND
641
0
    if (!display_name) {
642
0
      display_name = PR_GetEnv("DISPLAY");
643
0
    }
644
0
#endif
645
0
    if (display_name) {
646
0
      int argc = 3;
647
0
      char option_name[] = "--display";
648
0
      char* argv[] = {
649
0
        // argv0 is unused because g_set_prgname() was called in
650
0
        // XRE_InitChildProcess().
651
0
        nullptr,
652
0
        option_name,
653
0
        const_cast<char*>(display_name),
654
0
        nullptr
655
0
      };
656
0
      char** argvp = argv;
657
0
      gtk_init(&argc, &argvp);
658
0
    } else {
659
0
      gtk_init(nullptr, nullptr);
660
0
    }
661
0
  }
662
0
#endif
663
0
664
0
#ifdef MOZ_X11
665
0
  if (!gfxPlatform::IsHeadless()) {
666
0
    // Do this after initializing GDK, or GDK will install its own handler.
667
0
    XRE_InstallX11ErrorHandler();
668
0
  }
669
0
#endif
670
0
671
0
  NS_ASSERTION(!sSingleton, "only one ContentChild per child");
672
0
673
0
  // Once we start sending IPC messages, we need the thread manager to be
674
0
  // initialized so we can deal with the responses. Do that here before we
675
0
  // try to construct the crash reporter.
676
0
  nsresult rv = nsThreadManager::get().Init();
677
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
678
0
    return false;
679
0
  }
680
0
681
0
  // Middleman processes use a special channel for forwarding messages to
682
0
  // their own children.
683
0
  if (recordreplay::IsMiddleman()) {
684
0
    SetMiddlemanIPCChannel(recordreplay::parent::ChannelToUIProcess());
685
0
  }
686
0
687
0
  if (!Open(aChannel, aParentPid, aIOLoop)) {
688
0
    return false;
689
0
  }
690
0
  sSingleton = this;
691
0
692
0
  // If communications with the parent have broken down, take the process
693
0
  // down so it's not hanging around.
694
0
  GetIPCChannel()->SetAbortOnError(true);
695
#if defined(XP_WIN) && defined(ACCESSIBILITY)
696
  GetIPCChannel()->SetChannelFlags(MessageChannel::REQUIRE_A11Y_REENTRY);
697
#endif
698
699
0
  // This must be checked before any IPDL message, which may hit sentinel
700
0
  // errors due to parent and content processes having different
701
0
  // versions.
702
0
  MessageChannel* channel = GetIPCChannel();
703
0
  if (channel && !channel->SendBuildIDsMatchMessage(aParentBuildID)) {
704
0
    // We need to quit this process if the buildID doesn't match the parent's.
705
0
    // This can occur when an update occurred in the background.
706
0
    ProcessChild::QuickExit();
707
0
  }
708
0
709
0
#ifdef MOZ_X11
710
0
  if (!gfxPlatform::IsHeadless()) {
711
0
    // Send the parent our X socket to act as a proxy reference for our X
712
0
    // resources.
713
0
    int xSocketFd = ConnectionNumber(DefaultXDisplay());
714
0
    SendBackUpXResources(FileDescriptor(xSocketFd));
715
0
  }
716
0
#endif
717
0
718
0
  CrashReporterClient::InitSingleton(this);
719
0
720
0
  mID = aChildID;
721
0
  mIsForBrowser = aIsForBrowser;
722
0
723
0
#ifdef NS_PRINTING
724
0
  // Force the creation of the nsPrintingProxy so that it's IPC counterpart,
725
0
  // PrintingParent, is always available for printing initiated from the parent.
726
0
  RefPtr<nsPrintingProxy> printingProxy = nsPrintingProxy::GetInstance();
727
0
#endif
728
0
729
0
  SetProcessName(NS_LITERAL_STRING("Web Content"));
730
0
731
0
#ifdef NIGHTLY_BUILD
732
0
  // NOTE: We have to register the annotator on the main thread, as annotators
733
0
  // only affect a single thread.
734
0
  SystemGroup::Dispatch(TaskCategory::Other,
735
0
                        NS_NewRunnableFunction("RegisterPendingInputEventHangAnnotator", [] {
736
0
                          BackgroundHangMonitor::RegisterAnnotator(
737
0
                            PendingInputEventHangAnnotator::sSingleton);
738
0
                        }));
739
0
#endif
740
0
741
0
  return true;
742
0
}
743
744
void
745
ContentChild::SetProcessName(const nsAString& aName)
746
0
{
747
0
  char* name;
748
0
  if ((name = PR_GetEnv("MOZ_DEBUG_APP_PROCESS")) &&
749
0
    aName.EqualsASCII(name)) {
750
0
#ifdef OS_POSIX
751
0
    printf_stderr("\n\nCHILDCHILDCHILDCHILD\n  [%s] debug me @%d\n\n", name,
752
0
                  getpid());
753
0
    sleep(30);
754
#elif defined(OS_WIN)
755
    // Windows has a decent JIT debugging story, so NS_DebugBreak does the
756
    // right thing.
757
    NS_DebugBreak(NS_DEBUG_BREAK,
758
                 "Invoking NS_DebugBreak() to debug child process",
759
                 nullptr, __FILE__, __LINE__);
760
#endif
761
  }
762
0
763
0
  mProcessName = aName;
764
0
  mozilla::ipc::SetThisProcessName(NS_LossyConvertUTF16toASCII(aName).get());
765
0
}
766
767
NS_IMETHODIMP
768
ContentChild::ProvideWindow(mozIDOMWindowProxy* aParent,
769
                            uint32_t aChromeFlags,
770
                            bool aCalledFromJS,
771
                            bool aPositionSpecified,
772
                            bool aSizeSpecified,
773
                            nsIURI* aURI,
774
                            const nsAString& aName,
775
                            const nsACString& aFeatures,
776
                            bool aForceNoOpener,
777
                            nsDocShellLoadInfo* aLoadInfo,
778
                            bool* aWindowIsNew,
779
                            mozIDOMWindowProxy** aReturn)
780
0
{
781
0
  return ProvideWindowCommon(nullptr, aParent, false, aChromeFlags,
782
0
                             aCalledFromJS, aPositionSpecified,
783
0
                             aSizeSpecified, aURI, aName, aFeatures,
784
0
                             aForceNoOpener, aLoadInfo, aWindowIsNew, aReturn);
785
0
}
786
787
static nsresult
788
GetCreateWindowParams(mozIDOMWindowProxy* aParent,
789
                      nsDocShellLoadInfo* aLoadInfo,
790
                      nsACString& aBaseURIString, float* aFullZoom,
791
                      uint32_t* aReferrerPolicy,
792
                      nsIPrincipal** aTriggeringPrincipal)
793
0
{
794
0
  *aFullZoom = 1.0f;
795
0
  if (!aTriggeringPrincipal) {
796
0
    NS_ERROR("aTriggeringPrincipal is null");
797
0
    return NS_ERROR_FAILURE;
798
0
  }
799
0
  auto* opener = nsPIDOMWindowOuter::From(aParent);
800
0
  if (!opener) {
801
0
    nsCOMPtr<nsIPrincipal> nullPrincipal =
802
0
      NullPrincipal::CreateWithoutOriginAttributes();
803
0
    NS_ADDREF(*aTriggeringPrincipal = nullPrincipal);
804
0
    return NS_OK;
805
0
  }
806
0
807
0
  nsCOMPtr<nsIDocument> doc = opener->GetDoc();
808
0
  NS_ADDREF(*aTriggeringPrincipal = doc->NodePrincipal());
809
0
  nsCOMPtr<nsIURI> baseURI = doc->GetDocBaseURI();
810
0
  if (!baseURI) {
811
0
    NS_ERROR("nsIDocument didn't return a base URI");
812
0
    return NS_ERROR_FAILURE;
813
0
  }
814
0
815
0
  baseURI->GetSpec(aBaseURIString);
816
0
817
0
  if (aLoadInfo) {
818
0
    if (!aLoadInfo->SendReferrer()) {
819
0
      *aReferrerPolicy = mozilla::net::RP_No_Referrer;
820
0
    } else {
821
0
      *aReferrerPolicy = aLoadInfo->ReferrerPolicy();
822
0
    }
823
0
  }
824
0
825
0
  RefPtr<nsDocShell> openerDocShell =
826
0
    static_cast<nsDocShell*>(opener->GetDocShell());
827
0
  if (!openerDocShell) {
828
0
    return NS_OK;
829
0
  }
830
0
831
0
  nsCOMPtr<nsIContentViewer> cv;
832
0
  nsresult rv = openerDocShell->GetContentViewer(getter_AddRefs(cv));
833
0
  if (NS_SUCCEEDED(rv) && cv) {
834
0
    cv->GetFullZoom(aFullZoom);
835
0
  }
836
0
837
0
  return NS_OK;
838
0
}
839
840
nsresult
841
ContentChild::ProvideWindowCommon(TabChild* aTabOpener,
842
                                  mozIDOMWindowProxy* aParent,
843
                                  bool aIframeMoz,
844
                                  uint32_t aChromeFlags,
845
                                  bool aCalledFromJS,
846
                                  bool aPositionSpecified,
847
                                  bool aSizeSpecified,
848
                                  nsIURI* aURI,
849
                                  const nsAString& aName,
850
                                  const nsACString& aFeatures,
851
                                  bool aForceNoOpener,
852
                                  nsDocShellLoadInfo* aLoadInfo,
853
                                  bool* aWindowIsNew,
854
                                  mozIDOMWindowProxy** aReturn)
855
0
{
856
0
  *aReturn = nullptr;
857
0
858
0
  nsAutoPtr<IPCTabContext> ipcContext;
859
0
  TabId openerTabId = TabId(0);
860
0
  nsAutoCString features(aFeatures);
861
0
  nsAutoString name(aName);
862
0
863
0
  nsresult rv;
864
0
865
0
  MOZ_ASSERT(!aParent || aTabOpener,
866
0
             "If aParent is non-null, we should have an aTabOpener");
867
0
868
0
  // Cache the boolean preference for allowing noopener windows to open in a
869
0
  // separate process.
870
0
  static bool sNoopenerNewProcess = false;
871
0
  static bool sNoopenerNewProcessInited = false;
872
0
  if (!sNoopenerNewProcessInited) {
873
0
    Preferences::AddBoolVarCache(&sNoopenerNewProcess,
874
0
                                 "dom.noopener.newprocess.enabled");
875
0
    sNoopenerNewProcessInited = true;
876
0
  }
877
0
878
0
  // Check if we should load in a different process. We always want to load in a
879
0
  // different process if we have noopener set, but we also might if we can't
880
0
  // load in the current process.
881
0
  bool loadInDifferentProcess = aForceNoOpener && sNoopenerNewProcess;
882
0
  if (aTabOpener && !loadInDifferentProcess && aURI) {
883
0
    nsCOMPtr<nsIWebBrowserChrome3> browserChrome3;
884
0
    rv = aTabOpener->GetWebBrowserChrome(getter_AddRefs(browserChrome3));
885
0
    if (NS_SUCCEEDED(rv) && browserChrome3) {
886
0
      bool shouldLoad;
887
0
      rv = browserChrome3->ShouldLoadURIInThisProcess(aURI, &shouldLoad);
888
0
      loadInDifferentProcess = NS_SUCCEEDED(rv) && !shouldLoad;
889
0
    }
890
0
  }
891
0
892
0
  // If we're in a content process and we have noopener set, there's no reason
893
0
  // to load in our process, so let's load it elsewhere!
894
0
  if (loadInDifferentProcess) {
895
0
    nsAutoCString baseURIString;
896
0
    float fullZoom;
897
0
    nsCOMPtr<nsIPrincipal> triggeringPrincipal;
898
0
    uint32_t referrerPolicy = mozilla::net::RP_Unset;
899
0
    rv = GetCreateWindowParams(aParent, aLoadInfo, baseURIString, &fullZoom,
900
0
                               &referrerPolicy,
901
0
                               getter_AddRefs(triggeringPrincipal));
902
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
903
0
      return rv;
904
0
    }
905
0
906
0
    OptionalURIParams uriToLoad;
907
0
    SerializeURI(aURI, uriToLoad);
908
0
    Unused << SendCreateWindowInDifferentProcess(aTabOpener,
909
0
                                                 aChromeFlags,
910
0
                                                 aCalledFromJS,
911
0
                                                 aPositionSpecified,
912
0
                                                 aSizeSpecified,
913
0
                                                 uriToLoad,
914
0
                                                 features,
915
0
                                                 baseURIString,
916
0
                                                 fullZoom,
917
0
                                                 name,
918
0
                                                 Principal(triggeringPrincipal),
919
0
                                                 referrerPolicy);
920
0
921
0
    // We return NS_ERROR_ABORT, so that the caller knows that we've abandoned
922
0
    // the window open as far as it is concerned.
923
0
    return NS_ERROR_ABORT;
924
0
  }
925
0
926
0
  if (aTabOpener) {
927
0
    PopupIPCTabContext context;
928
0
    openerTabId = aTabOpener->GetTabId();
929
0
    context.opener() = openerTabId;
930
0
    context.isMozBrowserElement() = aTabOpener->IsMozBrowserElement();
931
0
    ipcContext = new IPCTabContext(context);
932
0
  } else {
933
0
    // It's possible to not have a TabChild opener in the case
934
0
    // of ServiceWorker::OpenWindow.
935
0
    UnsafeIPCTabContext unsafeTabContext;
936
0
    ipcContext = new IPCTabContext(unsafeTabContext);
937
0
  }
938
0
939
0
  MOZ_ASSERT(ipcContext);
940
0
  TabId tabId(nsContentUtils::GenerateTabId());
941
0
942
0
  // We need to assign a TabGroup to the PBrowser actor before we send it to the
943
0
  // parent. Otherwise, the parent could send messages to us before we have a
944
0
  // proper TabGroup for that actor.
945
0
  RefPtr<TabGroup> tabGroup;
946
0
  if (aTabOpener && !aForceNoOpener) {
947
0
    // The new actor will use the same tab group as the opener.
948
0
    tabGroup = aTabOpener->TabGroup();
949
0
  } else {
950
0
    tabGroup = new TabGroup();
951
0
  }
952
0
953
0
  TabContext newTabContext = aTabOpener ? *aTabOpener : TabContext();
954
0
  RefPtr<TabChild> newChild = new TabChild(this, tabId, tabGroup,
955
0
                                           newTabContext, aChromeFlags);
956
0
  if (NS_FAILED(newChild->Init())) {
957
0
    return NS_ERROR_ABORT;
958
0
  }
959
0
960
0
  if (aTabOpener) {
961
0
    MOZ_ASSERT(ipcContext->type() == IPCTabContext::TPopupIPCTabContext);
962
0
    ipcContext->get_PopupIPCTabContext().opener() = aTabOpener;
963
0
  }
964
0
965
0
  nsCOMPtr<nsIEventTarget> target = tabGroup->EventTargetFor(TaskCategory::Other);
966
0
  SetEventTargetForActor(newChild, target);
967
0
968
0
  Unused << SendPBrowserConstructor(
969
0
    // We release this ref in DeallocPBrowserChild
970
0
    RefPtr<TabChild>(newChild).forget().take(),
971
0
    tabId, TabId(0), *ipcContext, aChromeFlags,
972
0
    GetID(), IsForBrowser());
973
0
974
0
975
0
  PRenderFrameChild* renderFrame = newChild->SendPRenderFrameConstructor();
976
0
977
0
  nsCOMPtr<nsPIDOMWindowInner> parentTopInnerWindow;
978
0
  if (aParent) {
979
0
    nsCOMPtr<nsPIDOMWindowOuter> parentTopWindow =
980
0
      nsPIDOMWindowOuter::From(aParent)->GetTop();
981
0
    if (parentTopWindow) {
982
0
      parentTopInnerWindow = parentTopWindow->GetCurrentInnerWindow();
983
0
    }
984
0
  }
985
0
986
0
  // Set to true when we're ready to return from this function.
987
0
  bool ready = false;
988
0
989
0
  // NOTE: Capturing by reference here is safe, as this function won't return
990
0
  // until one of these callbacks is called.
991
0
  auto resolve = [&] (const CreatedWindowInfo& info) {
992
0
    MOZ_RELEASE_ASSERT(NS_IsMainThread());
993
0
    rv = info.rv();
994
0
    *aWindowIsNew = info.windowOpened();
995
0
    nsTArray<FrameScriptInfo> frameScripts(info.frameScripts());
996
0
    nsCString urlToLoad = info.urlToLoad();
997
0
    TextureFactoryIdentifier textureFactoryIdentifier = info.textureFactoryIdentifier();
998
0
    layers::LayersId layersId = info.layersId();
999
0
    CompositorOptions compositorOptions = info.compositorOptions();
1000
0
    uint32_t maxTouchPoints = info.maxTouchPoints();
1001
0
    DimensionInfo dimensionInfo = info.dimensions();
1002
0
    bool hasSiblings = info.hasSiblings();
1003
0
1004
0
    // Once this function exits, we should try to exit the nested event loop.
1005
0
    ready = true;
1006
0
1007
0
    // NOTE: We have to handle this immediately in the resolve callback in order
1008
0
    // to make sure that we don't process any more IPC messages before returning
1009
0
    // from ProvideWindowCommon.
1010
0
1011
0
    // Handle the error which we got back from the parent process, if we got
1012
0
    // one.
1013
0
    if (NS_FAILED(rv)) {
1014
0
      return;
1015
0
    }
1016
0
1017
0
    if (!*aWindowIsNew) {
1018
0
      rv = NS_ERROR_ABORT;
1019
0
      return;
1020
0
    }
1021
0
1022
0
    // If the TabChild has been torn down, we don't need to do this anymore.
1023
0
    if (NS_WARN_IF(!newChild->IPCOpen() || newChild->IsDestroyed())) {
1024
0
      rv = NS_ERROR_ABORT;
1025
0
      return;
1026
0
    }
1027
0
1028
0
    if (!layersId.IsValid()) { // if renderFrame is invalid.
1029
0
      renderFrame = nullptr;
1030
0
    }
1031
0
1032
0
    ShowInfo showInfo(EmptyString(), false, false, true, false, 0, 0, 0);
1033
0
    auto* opener = nsPIDOMWindowOuter::From(aParent);
1034
0
    nsIDocShell* openerShell;
1035
0
    if (opener && (openerShell = opener->GetDocShell())) {
1036
0
      nsCOMPtr<nsILoadContext> context = do_QueryInterface(openerShell);
1037
0
      showInfo = ShowInfo(EmptyString(), false,
1038
0
                          context->UsePrivateBrowsing(), true, false,
1039
0
                          aTabOpener->WebWidget()->GetDPI(),
1040
0
                          aTabOpener->WebWidget()->RoundsWidgetCoordinatesTo(),
1041
0
                          aTabOpener->WebWidget()->GetDefaultScale().scale);
1042
0
    }
1043
0
1044
0
    newChild->SetMaxTouchPoints(maxTouchPoints);
1045
0
    newChild->SetHasSiblings(hasSiblings);
1046
0
1047
0
    // Set the opener window for this window before we start loading the document
1048
0
    // inside of it. We have to do this before loading the remote scripts, because
1049
0
    // they can poke at the document and cause the nsDocument to be created before
1050
0
    // the openerwindow
1051
0
    nsCOMPtr<mozIDOMWindowProxy> windowProxy = do_GetInterface(newChild->WebNavigation());
1052
0
    if (!aForceNoOpener && windowProxy && aParent) {
1053
0
      nsPIDOMWindowOuter* outer = nsPIDOMWindowOuter::From(windowProxy);
1054
0
      nsPIDOMWindowOuter* parent = nsPIDOMWindowOuter::From(aParent);
1055
0
      outer->SetOpenerWindow(parent, *aWindowIsNew);
1056
0
    }
1057
0
1058
0
    // Unfortunately we don't get a window unless we've shown the frame.  That's
1059
0
    // pretty bogus; see bug 763602.
1060
0
    newChild->DoFakeShow(textureFactoryIdentifier, layersId, compositorOptions,
1061
0
                        renderFrame, showInfo);
1062
0
1063
0
    newChild->RecvUpdateDimensions(dimensionInfo);
1064
0
1065
0
    for (size_t i = 0; i < frameScripts.Length(); i++) {
1066
0
      FrameScriptInfo& info = frameScripts[i];
1067
0
      if (!newChild->RecvLoadRemoteScript(info.url(), info.runInGlobalScope())) {
1068
0
        MOZ_CRASH();
1069
0
      }
1070
0
    }
1071
0
1072
0
    if (!urlToLoad.IsEmpty()) {
1073
0
      newChild->RecvLoadURL(urlToLoad, showInfo);
1074
0
    }
1075
0
1076
0
    nsCOMPtr<mozIDOMWindowProxy> win = do_GetInterface(newChild->WebNavigation());
1077
0
    win.forget(aReturn);
1078
0
  };
1079
0
1080
0
  // NOTE: Capturing by reference here is safe, as this function won't return
1081
0
  // until one of these callbacks is called.
1082
0
  auto reject = [&] (ResponseRejectReason) {
1083
0
    MOZ_RELEASE_ASSERT(NS_IsMainThread());
1084
0
    NS_WARNING("windowCreated promise rejected");
1085
0
    rv = NS_ERROR_NOT_AVAILABLE;
1086
0
    ready = true;
1087
0
  };
1088
0
1089
0
  // Send down the request to open the window.
1090
0
  if (aIframeMoz) {
1091
0
    MOZ_ASSERT(aTabOpener);
1092
0
    nsAutoCString url;
1093
0
    if (aURI) {
1094
0
      aURI->GetSpec(url);
1095
0
    } else {
1096
0
      // We can't actually send a nullptr up as the URI, since IPDL doesn't let us
1097
0
      // send nullptr's for primitives. We indicate that the nsString for the URI
1098
0
      // should be converted to a nullptr by voiding the string.
1099
0
      url.SetIsVoid(true);
1100
0
    }
1101
0
1102
0
    // NOTE: BrowserFrameOpenWindowPromise is the same type as
1103
0
    // CreateWindowPromise, and this code depends on that fact.
1104
0
    newChild->SendBrowserFrameOpenWindow(aTabOpener, renderFrame,
1105
0
                                         NS_ConvertUTF8toUTF16(url),
1106
0
                                         name, NS_ConvertUTF8toUTF16(features),
1107
0
                                         std::move(resolve), std::move(reject));
1108
0
  } else {
1109
0
    nsAutoCString baseURIString;
1110
0
    float fullZoom;
1111
0
    nsCOMPtr<nsIPrincipal> triggeringPrincipal;
1112
0
    uint32_t referrerPolicy = mozilla::net::RP_Unset;
1113
0
    rv = GetCreateWindowParams(aParent, aLoadInfo, baseURIString, &fullZoom,
1114
0
                               &referrerPolicy,
1115
0
                               getter_AddRefs(triggeringPrincipal));
1116
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
1117
0
      return rv;
1118
0
    }
1119
0
1120
0
    OptionalURIParams uriToLoad;
1121
0
    if (aURI) {
1122
0
      SerializeURI(aURI, uriToLoad);
1123
0
    } else {
1124
0
      uriToLoad = mozilla::void_t();
1125
0
    }
1126
0
1127
0
    SendCreateWindow(aTabOpener, newChild, renderFrame,
1128
0
                     aChromeFlags, aCalledFromJS, aPositionSpecified,
1129
0
                     aSizeSpecified, uriToLoad, features, baseURIString,
1130
0
                     fullZoom, Principal(triggeringPrincipal), referrerPolicy,
1131
0
                     std::move(resolve), std::move(reject));
1132
0
  }
1133
0
1134
0
  // =======================
1135
0
  // Begin Nested Event Loop
1136
0
  // =======================
1137
0
1138
0
  // We have to wait for a response from either SendCreateWindow or
1139
0
  // SendBrowserFrameOpenWindow with information we're going to need to return
1140
0
  // from this function, So we spin a nested event loop until they get back to
1141
0
  // us.
1142
0
1143
0
  // Prevent the docshell from becoming active while the nested event loop is
1144
0
  // spinning.
1145
0
  newChild->AddPendingDocShellBlocker();
1146
0
  auto removePendingDocShellBlocker = MakeScopeExit([&] {
1147
0
    if (newChild) {
1148
0
      newChild->RemovePendingDocShellBlocker();
1149
0
    }
1150
0
  });
1151
0
1152
0
  // Suspend our window if we have one to make sure we don't re-enter it.
1153
0
  if (parentTopInnerWindow) {
1154
0
    parentTopInnerWindow->Suspend();
1155
0
  }
1156
0
1157
0
  {
1158
0
    AutoNoJSAPI nojsapi;
1159
0
1160
0
    // Spin the event loop until we get a response. Callers of this function
1161
0
    // already have to guard against an inner event loop spinning in the
1162
0
    // non-e10s case because of the need to spin one to create a new chrome
1163
0
    // window.
1164
0
    SpinEventLoopUntil([&] () { return ready; });
1165
0
    MOZ_RELEASE_ASSERT(ready,
1166
0
                       "We are on the main thread, so we should not exit this "
1167
0
                       "loop without ready being true.");
1168
0
  }
1169
0
1170
0
  if (parentTopInnerWindow) {
1171
0
    parentTopInnerWindow->Resume();
1172
0
  }
1173
0
1174
0
  // =====================
1175
0
  // End Nested Event Loop
1176
0
  // =====================
1177
0
1178
0
  // We should have the results already set by the callbacks.
1179
0
  MOZ_ASSERT_IF(NS_SUCCEEDED(rv), *aReturn);
1180
0
  return rv;
1181
0
}
1182
1183
void
1184
ContentChild::GetProcessName(nsAString& aName) const
1185
0
{
1186
0
  aName.Assign(mProcessName);
1187
0
}
1188
1189
bool
1190
ContentChild::IsAlive() const
1191
0
{
1192
0
  return mIsAlive;
1193
0
}
1194
1195
bool
1196
ContentChild::IsShuttingDown() const
1197
0
{
1198
0
  return mShuttingDown;
1199
0
}
1200
1201
void
1202
ContentChild::GetProcessName(nsACString& aName) const
1203
0
{
1204
0
  aName.Assign(NS_ConvertUTF16toUTF8(mProcessName));
1205
0
}
1206
1207
/* static */ void
1208
ContentChild::AppendProcessId(nsACString& aName)
1209
0
{
1210
0
  if (!aName.IsEmpty()) {
1211
0
    aName.Append(' ');
1212
0
  }
1213
0
  unsigned pid = getpid();
1214
0
  aName.Append(nsPrintfCString("(pid %u)", pid));
1215
0
}
1216
1217
void
1218
ContentChild::InitGraphicsDeviceData(const ContentDeviceData& aData)
1219
0
{
1220
0
  gfxPlatform::InitChild(aData);
1221
0
}
1222
1223
void
1224
ContentChild::InitXPCOM(const XPCOMInitData& aXPCOMInit,
1225
                        const mozilla::dom::ipc::StructuredCloneData& aInitialData)
1226
0
{
1227
0
  // Do this as early as possible to get the parent process to initialize the
1228
0
  // background thread since we'll likely need database information very soon.
1229
0
  BackgroundChild::Startup();
1230
0
1231
0
  PBackgroundChild* actorChild = BackgroundChild::GetOrCreateForCurrentThread();
1232
0
  if (NS_WARN_IF(!actorChild)) {
1233
0
    MOZ_ASSERT_UNREACHABLE("PBackground init can't fail at this point");
1234
0
    return;
1235
0
  }
1236
0
1237
0
  ClientManager::Startup();
1238
0
1239
0
  nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
1240
0
  if (!svc) {
1241
0
    NS_WARNING("Couldn't acquire console service");
1242
0
    return;
1243
0
  }
1244
0
1245
0
  mConsoleListener = new ConsoleListener(this);
1246
0
  if (NS_FAILED(svc->RegisterListener(mConsoleListener)))
1247
0
    NS_WARNING("Couldn't register console listener for child process");
1248
0
1249
0
  mAvailableDictionaries = aXPCOMInit.dictionaries();
1250
0
1251
0
  RecvSetOffline(aXPCOMInit.isOffline());
1252
0
  RecvSetConnectivity(aXPCOMInit.isConnected());
1253
0
  LocaleService::GetInstance()->AssignAppLocales(aXPCOMInit.appLocales());
1254
0
  LocaleService::GetInstance()->AssignRequestedLocales(aXPCOMInit.requestedLocales());
1255
0
1256
0
  RecvSetCaptivePortalState(aXPCOMInit.captivePortalState());
1257
0
  RecvBidiKeyboardNotify(aXPCOMInit.isLangRTL(), aXPCOMInit.haveBidiKeyboards());
1258
0
1259
0
  // Create the CPOW manager as soon as possible. Middleman processes don't use
1260
0
  // CPOWs, because their recording child will also have a CPOW manager that
1261
0
  // communicates with the UI process.
1262
0
  if (!recordreplay::IsMiddleman()) {
1263
0
    SendPJavaScriptConstructor();
1264
0
  }
1265
0
1266
0
  if (aXPCOMInit.domainPolicy().active()) {
1267
0
    nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
1268
0
    MOZ_ASSERT(ssm);
1269
0
    ssm->ActivateDomainPolicyInternal(getter_AddRefs(mPolicy));
1270
0
    if (!mPolicy) {
1271
0
      MOZ_CRASH("Failed to activate domain policy.");
1272
0
    }
1273
0
    mPolicy->ApplyClone(&aXPCOMInit.domainPolicy());
1274
0
  }
1275
0
1276
0
  nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1"));
1277
0
  if (nsCOMPtr<nsIClipboardProxy> clipboardProxy = do_QueryInterface(clipboard)) {
1278
0
    clipboardProxy->SetCapabilities(aXPCOMInit.clipboardCaps());
1279
0
  }
1280
0
1281
0
  {
1282
0
    AutoJSAPI jsapi;
1283
0
    if (NS_WARN_IF(!jsapi.Init(xpc::PrivilegedJunkScope()))) {
1284
0
      MOZ_CRASH();
1285
0
    }
1286
0
    ErrorResult rv;
1287
0
    JS::RootedValue data(jsapi.cx());
1288
0
    mozilla::dom::ipc::StructuredCloneData id;
1289
0
    id.Copy(aInitialData);
1290
0
    id.Read(jsapi.cx(), &data, rv);
1291
0
    if (NS_WARN_IF(rv.Failed())) {
1292
0
      MOZ_CRASH();
1293
0
    }
1294
0
    auto* global = ContentProcessMessageManager::Get();
1295
0
    global->SetInitialProcessData(data);
1296
0
  }
1297
0
1298
0
  // The stylesheet cache is not ready yet. Store this URL for future use.
1299
0
  nsCOMPtr<nsIURI> ucsURL = DeserializeURI(aXPCOMInit.userContentSheetURL());
1300
0
  nsLayoutStylesheetCache::SetUserContentCSSURL(ucsURL);
1301
0
1302
0
  GfxInfoBase::SetFeatureStatus(aXPCOMInit.gfxFeatureStatus());
1303
0
1304
0
  DataStorage::SetCachedStorageEntries(aXPCOMInit.dataStorage());
1305
0
1306
0
  // Set the dynamic scalar definitions for this process.
1307
0
  TelemetryIPC::AddDynamicScalarDefinitions(aXPCOMInit.dynamicScalarDefs());
1308
0
1309
0
  DOMPrefs::Initialize();
1310
0
}
1311
1312
mozilla::ipc::IPCResult
1313
ContentChild::RecvRequestMemoryReport(const uint32_t& aGeneration,
1314
                                      const bool& aAnonymize,
1315
                                      const bool& aMinimizeMemoryUsage,
1316
                                      const MaybeFileDesc& aDMDFile)
1317
0
{
1318
0
  nsCString process;
1319
0
  GetProcessName(process);
1320
0
  AppendProcessId(process);
1321
0
1322
0
  MemoryReportRequestClient::Start(
1323
0
    aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, process);
1324
0
  return IPC_OK();
1325
0
}
1326
1327
PCycleCollectWithLogsChild*
1328
ContentChild::AllocPCycleCollectWithLogsChild(const bool& aDumpAllTraces,
1329
                                              const FileDescriptor& aGCLog,
1330
                                              const FileDescriptor& aCCLog)
1331
0
{
1332
0
  auto* actor = new CycleCollectWithLogsChild(aGCLog, aCCLog);
1333
0
  // Return actor with refcount 0, which is safe because it has a non-XPCOM type.
1334
0
  return actor;
1335
0
}
1336
1337
mozilla::ipc::IPCResult
1338
ContentChild::RecvPCycleCollectWithLogsConstructor(PCycleCollectWithLogsChild* aActor,
1339
                                                   const bool& aDumpAllTraces,
1340
                                                   const FileDescriptor& aGCLog,
1341
                                                   const FileDescriptor& aCCLog)
1342
0
{
1343
0
  // Take a reference here, where the XPCOM type is regained.
1344
0
  RefPtr<CycleCollectWithLogsChild> sink = static_cast<CycleCollectWithLogsChild*>(aActor);
1345
0
  nsCOMPtr<nsIMemoryInfoDumper> dumper = do_GetService("@mozilla.org/memory-info-dumper;1");
1346
0
1347
0
  dumper->DumpGCAndCCLogsToSink(aDumpAllTraces, sink);
1348
0
1349
0
  // The actor's destructor is called when the last reference goes away...
1350
0
  return IPC_OK();
1351
0
}
1352
1353
bool
1354
ContentChild::DeallocPCycleCollectWithLogsChild(PCycleCollectWithLogsChild* /* aActor */)
1355
0
{
1356
0
  // ...so when we get here, there's nothing for us to do.
1357
0
  //
1358
0
  // Also, we're already in ~CycleCollectWithLogsChild (q.v.) at
1359
0
  // this point, so we shouldn't touch the actor in any case.
1360
0
  return true;
1361
0
}
1362
1363
mozilla::ipc::IPCResult
1364
ContentChild::RecvInitContentBridgeChild(Endpoint<PContentBridgeChild>&& aEndpoint)
1365
0
{
1366
0
  ContentBridgeChild::Create(std::move(aEndpoint));
1367
0
  return IPC_OK();
1368
0
}
1369
1370
mozilla::ipc::IPCResult
1371
ContentChild::RecvInitGMPService(Endpoint<PGMPServiceChild>&& aGMPService)
1372
0
{
1373
0
  if (!GMPServiceChild::Create(std::move(aGMPService))) {
1374
0
    return IPC_FAIL_NO_REASON(this);
1375
0
  }
1376
0
  return IPC_OK();
1377
0
}
1378
1379
mozilla::ipc::IPCResult
1380
ContentChild::RecvInitProfiler(Endpoint<PProfilerChild>&& aEndpoint)
1381
0
{
1382
0
#ifdef MOZ_GECKO_PROFILER
1383
0
  mProfilerController = ChildProfilerController::Create(std::move(aEndpoint));
1384
0
#endif
1385
0
  return IPC_OK();
1386
0
}
1387
1388
mozilla::ipc::IPCResult
1389
ContentChild::RecvGMPsChanged(nsTArray<GMPCapabilityData>&& capabilities)
1390
0
{
1391
0
  GeckoMediaPluginServiceChild::UpdateGMPCapabilities(std::move(capabilities));
1392
0
  return IPC_OK();
1393
0
}
1394
1395
mozilla::ipc::IPCResult
1396
ContentChild::RecvInitProcessHangMonitor(Endpoint<PProcessHangMonitorChild>&& aHangMonitor)
1397
0
{
1398
0
  CreateHangMonitorChild(std::move(aHangMonitor));
1399
0
  return IPC_OK();
1400
0
}
1401
1402
mozilla::ipc::IPCResult
1403
ContentChild::GetResultForRenderingInitFailure(base::ProcessId aOtherPid)
1404
0
{
1405
0
  if (aOtherPid == base::GetCurrentProcId() || aOtherPid == OtherPid()) {
1406
0
    // If we are talking to ourselves, or the UI process, then that is a fatal
1407
0
    // protocol error.
1408
0
    return IPC_FAIL_NO_REASON(this);
1409
0
  }
1410
0
1411
0
  // If we are talking to the GPU process, then we should recover from this on
1412
0
  // the next ContentChild::RecvReinitRendering call.
1413
0
  gfxCriticalNote << "Could not initialize rendering with GPU process";
1414
0
  return IPC_OK();
1415
0
}
1416
1417
mozilla::ipc::IPCResult
1418
ContentChild::RecvRequestPerformanceMetrics(const nsID& aID)
1419
0
{
1420
0
  MOZ_ASSERT(mozilla::StaticPrefs::dom_performance_enable_scheduler_timing());
1421
0
  nsTArray<PerformanceInfo> info;
1422
0
  CollectPerformanceInfo(info);
1423
0
  SendAddPerformanceMetrics(aID, info);
1424
0
  return IPC_OK();
1425
0
}
1426
1427
mozilla::ipc::IPCResult
1428
ContentChild::RecvInitRendering(Endpoint<PCompositorManagerChild>&& aCompositor,
1429
                                Endpoint<PImageBridgeChild>&& aImageBridge,
1430
                                Endpoint<PVRManagerChild>&& aVRBridge,
1431
                                Endpoint<PVideoDecoderManagerChild>&& aVideoManager,
1432
                                nsTArray<uint32_t>&& namespaces)
1433
0
{
1434
0
  MOZ_ASSERT(namespaces.Length() == 3);
1435
0
1436
0
  // Note that for all of the methods below, if it can fail, it should only
1437
0
  // return false if the failure is an IPDL error. In such situations,
1438
0
  // ContentChild can reason about whether or not to wait for
1439
0
  // RecvReinitRendering (because we surmised the GPU process crashed), or if it
1440
0
  // should crash itself (because we are actually talking to the UI process). If
1441
0
  // there are localized failures (e.g. failed to spawn a thread), then it
1442
0
  // should MOZ_RELEASE_ASSERT or MOZ_CRASH as necessary instead.
1443
0
  if (!CompositorManagerChild::Init(std::move(aCompositor), namespaces[0])) {
1444
0
    return GetResultForRenderingInitFailure(aCompositor.OtherPid());
1445
0
  }
1446
0
  if (!CompositorManagerChild::CreateContentCompositorBridge(namespaces[1])) {
1447
0
    return GetResultForRenderingInitFailure(aCompositor.OtherPid());
1448
0
  }
1449
0
  if (!ImageBridgeChild::InitForContent(std::move(aImageBridge), namespaces[2])) {
1450
0
    return GetResultForRenderingInitFailure(aImageBridge.OtherPid());
1451
0
  }
1452
0
  if (!gfx::VRManagerChild::InitForContent(std::move(aVRBridge))) {
1453
0
    return GetResultForRenderingInitFailure(aVRBridge.OtherPid());
1454
0
  }
1455
0
  VideoDecoderManagerChild::InitForContent(std::move(aVideoManager));
1456
0
  return IPC_OK();
1457
0
}
1458
1459
mozilla::ipc::IPCResult
1460
ContentChild::RecvReinitRendering(Endpoint<PCompositorManagerChild>&& aCompositor,
1461
                                  Endpoint<PImageBridgeChild>&& aImageBridge,
1462
                                  Endpoint<PVRManagerChild>&& aVRBridge,
1463
                                  Endpoint<PVideoDecoderManagerChild>&& aVideoManager,
1464
                                  nsTArray<uint32_t>&& namespaces)
1465
0
{
1466
0
  MOZ_ASSERT(namespaces.Length() == 3);
1467
0
  nsTArray<RefPtr<TabChild>> tabs = TabChild::GetAll();
1468
0
1469
0
  // Zap all the old layer managers we have lying around.
1470
0
  for (const auto& tabChild : tabs) {
1471
0
    if (tabChild->GetLayersId().IsValid()) {
1472
0
      tabChild->InvalidateLayers();
1473
0
    }
1474
0
  }
1475
0
1476
0
  // Re-establish singleton bridges to the compositor.
1477
0
  if (!CompositorManagerChild::Init(std::move(aCompositor), namespaces[0])) {
1478
0
    return GetResultForRenderingInitFailure(aCompositor.OtherPid());
1479
0
  }
1480
0
  if (!CompositorManagerChild::CreateContentCompositorBridge(namespaces[1])) {
1481
0
    return GetResultForRenderingInitFailure(aCompositor.OtherPid());
1482
0
  }
1483
0
  if (!ImageBridgeChild::ReinitForContent(std::move(aImageBridge), namespaces[2])) {
1484
0
    return GetResultForRenderingInitFailure(aImageBridge.OtherPid());
1485
0
  }
1486
0
  if (!gfx::VRManagerChild::ReinitForContent(std::move(aVRBridge))) {
1487
0
    return GetResultForRenderingInitFailure(aVRBridge.OtherPid());
1488
0
  }
1489
0
  gfxPlatform::GetPlatform()->CompositorUpdated();
1490
0
1491
0
  // Establish new PLayerTransactions.
1492
0
  for (const auto& tabChild : tabs) {
1493
0
    if (tabChild->GetLayersId().IsValid()) {
1494
0
      tabChild->ReinitRendering();
1495
0
    }
1496
0
  }
1497
0
1498
0
  VideoDecoderManagerChild::InitForContent(std::move(aVideoManager));
1499
0
  return IPC_OK();
1500
0
}
1501
1502
mozilla::ipc::IPCResult
1503
ContentChild::RecvAudioDefaultDeviceChange()
1504
0
{
1505
#ifdef XP_WIN
1506
  audio::AudioNotificationReceiver::NotifyDefaultDeviceChanged();
1507
#endif
1508
0
  return IPC_OK();
1509
0
}
1510
1511
mozilla::ipc::IPCResult
1512
ContentChild::RecvReinitRenderingForDeviceReset()
1513
0
{
1514
0
  gfxPlatform::GetPlatform()->CompositorUpdated();
1515
0
1516
0
  nsTArray<RefPtr<TabChild>> tabs = TabChild::GetAll();
1517
0
  for (const auto& tabChild : tabs) {
1518
0
    if (tabChild->GetLayersId().IsValid()) {
1519
0
      tabChild->ReinitRenderingForDeviceReset();
1520
0
    }
1521
0
  }
1522
0
  return IPC_OK();
1523
0
}
1524
1525
#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
1526
1527
#include <stdlib.h>
1528
1529
static bool
1530
GetAppPaths(nsCString &aAppPath, nsCString &aAppBinaryPath, nsCString &aAppDir)
1531
{
1532
  nsAutoCString appPath;
1533
  nsAutoCString appBinaryPath(
1534
    (CommandLine::ForCurrentProcess()->argv()[0]).c_str());
1535
1536
  nsAutoCString::const_iterator start, end;
1537
  appBinaryPath.BeginReading(start);
1538
  appBinaryPath.EndReading(end);
1539
  if (RFindInReadable(NS_LITERAL_CSTRING(".app/Contents/MacOS/"), start, end)) {
1540
    end = start;
1541
    ++end; ++end; ++end; ++end;
1542
    appBinaryPath.BeginReading(start);
1543
    appPath.Assign(Substring(start, end));
1544
  } else {
1545
    return false;
1546
  }
1547
1548
  nsCOMPtr<nsIFile> app, appBinary;
1549
  nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(appPath),
1550
                                true, getter_AddRefs(app));
1551
  if (NS_FAILED(rv)) {
1552
    return false;
1553
  }
1554
  rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(appBinaryPath),
1555
                       true, getter_AddRefs(appBinary));
1556
  if (NS_FAILED(rv)) {
1557
    return false;
1558
  }
1559
1560
  nsCOMPtr<nsIFile> appDir;
1561
  nsCOMPtr<nsIProperties> dirSvc =
1562
    do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
1563
  if (!dirSvc) {
1564
    return false;
1565
  }
1566
  rv = dirSvc->Get(NS_GRE_DIR,
1567
                   NS_GET_IID(nsIFile), getter_AddRefs(appDir));
1568
  if (NS_FAILED(rv)) {
1569
    return false;
1570
  }
1571
  bool exists;
1572
  rv = appDir->Exists(&exists);
1573
  if (NS_FAILED(rv) || !exists) {
1574
    return false;
1575
  }
1576
1577
  // appDir points to .app/Contents/Resources, for our purposes we want
1578
  // .app/Contents.
1579
  nsCOMPtr<nsIFile> appDirParent;
1580
  rv = appDir->GetParent(getter_AddRefs(appDirParent));
1581
  if (NS_FAILED(rv)) {
1582
    return false;
1583
  }
1584
1585
  rv = app->Normalize();
1586
  if (NS_FAILED(rv)) {
1587
    return false;
1588
  }
1589
  app->GetNativePath(aAppPath);
1590
1591
  rv = appBinary->Normalize();
1592
  if (NS_FAILED(rv)) {
1593
    return false;
1594
  }
1595
  appBinary->GetNativePath(aAppBinaryPath);
1596
1597
  rv = appDirParent->Normalize();
1598
  if (NS_FAILED(rv)) {
1599
    return false;
1600
  }
1601
  appDirParent->GetNativePath(aAppDir);
1602
1603
  return true;
1604
}
1605
1606
// This function is only used in an |#ifdef DEBUG| path.
1607
#ifdef DEBUG
1608
// Given a path to a file, return the directory which contains it.
1609
static nsAutoCString
1610
GetDirectoryPath(const char *aPath) {
1611
  nsCOMPtr<nsIFile> file = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
1612
  if (!file ||
1613
      NS_FAILED(file->InitWithNativePath(nsDependentCString(aPath)))) {
1614
    MOZ_CRASH("Failed to create or init an nsIFile");
1615
  }
1616
  nsCOMPtr<nsIFile> directoryFile;
1617
  if (NS_FAILED(file->GetParent(getter_AddRefs(directoryFile))) ||
1618
      !directoryFile) {
1619
    MOZ_CRASH("Failed to get parent for an nsIFile");
1620
  }
1621
  directoryFile->Normalize();
1622
  nsAutoCString directoryPath;
1623
  if (NS_FAILED(directoryFile->GetNativePath(directoryPath))) {
1624
    MOZ_CRASH("Failed to get path for an nsIFile");
1625
  }
1626
  return directoryPath;
1627
}
1628
#endif // DEBUG
1629
1630
extern "C" {
1631
CGError
1632
CGSSetDenyWindowServerConnections(bool);
1633
void CGSShutdownServerConnections();
1634
};
1635
1636
static bool
1637
StartMacOSContentSandbox()
1638
{
1639
  int sandboxLevel = GetEffectiveContentSandboxLevel();
1640
  if (sandboxLevel < 1) {
1641
    return false;
1642
  }
1643
1644
  // Close all current connections to the WindowServer. This ensures that the
1645
  // Activity Monitor will not label the content process as "Not responding"
1646
  // because it's not running a native event loop. See bug 1384336.
1647
  CGSShutdownServerConnections();
1648
1649
  // Actual security benefits are only acheived when we additionally deny
1650
  // future connections, however this currently breaks WebGL so it's not done
1651
  // by default.
1652
  if (Preferences::GetBool(
1653
        "security.sandbox.content.mac.disconnect-windowserver")) {
1654
    CGError result = CGSSetDenyWindowServerConnections(true);
1655
    MOZ_DIAGNOSTIC_ASSERT(result == kCGErrorSuccess);
1656
#if !MOZ_DIAGNOSTIC_ASSERT_ENABLED
1657
    Unused << result;
1658
#endif
1659
  }
1660
1661
  nsAutoCString appPath, appBinaryPath, appDir;
1662
  if (!GetAppPaths(appPath, appBinaryPath, appDir)) {
1663
    MOZ_CRASH("Error resolving child process path");
1664
  }
1665
1666
  ContentChild* cc = ContentChild::GetSingleton();
1667
1668
  nsresult rv;
1669
  nsCOMPtr<nsIFile> profileDir;
1670
  cc->GetProfileDir(getter_AddRefs(profileDir));
1671
  nsCString profileDirPath;
1672
  if (profileDir) {
1673
    profileDir->Normalize();
1674
    rv = profileDir->GetNativePath(profileDirPath);
1675
    if (NS_FAILED(rv) || profileDirPath.IsEmpty()) {
1676
      MOZ_CRASH("Failed to get profile path");
1677
    }
1678
  }
1679
1680
  bool isFileProcess = cc->GetRemoteType().EqualsLiteral(FILE_REMOTE_TYPE);
1681
1682
  MacSandboxInfo info;
1683
  info.type = MacSandboxType_Content;
1684
  info.level = sandboxLevel;
1685
  info.hasFilePrivileges = isFileProcess;
1686
  info.shouldLog = Preferences::GetBool("security.sandbox.logging.enabled") ||
1687
                   PR_GetEnv("MOZ_SANDBOX_LOGGING");
1688
  info.appPath.assign(appPath.get());
1689
  info.appBinaryPath.assign(appBinaryPath.get());
1690
  info.appDir.assign(appDir.get());
1691
  info.hasAudio = !Preferences::GetBool("media.cubeb.sandbox");
1692
1693
  // These paths are used to whitelist certain directories used by the testing
1694
  // system. They should not be considered a public API, and are only intended
1695
  // for use in automation.
1696
  nsAutoCString testingReadPath1;
1697
  Preferences::GetCString("security.sandbox.content.mac.testing_read_path1",
1698
                          testingReadPath1);
1699
  if (!testingReadPath1.IsEmpty()) {
1700
    info.testingReadPath1.assign(testingReadPath1.get());
1701
  }
1702
  nsAutoCString testingReadPath2;
1703
  Preferences::GetCString("security.sandbox.content.mac.testing_read_path2",
1704
                          testingReadPath2);
1705
  if (!testingReadPath2.IsEmpty()) {
1706
    info.testingReadPath2.assign(testingReadPath2.get());
1707
  }
1708
1709
  if (mozilla::IsDevelopmentBuild()) {
1710
    nsCOMPtr<nsIFile> repoDir;
1711
    rv = mozilla::GetRepoDir(getter_AddRefs(repoDir));
1712
    if (NS_FAILED(rv)) {
1713
      MOZ_CRASH("Failed to get path to repo dir");
1714
    }
1715
    nsCString repoDirPath;
1716
    Unused << repoDir->GetNativePath(repoDirPath);
1717
    info.testingReadPath3.assign(repoDirPath.get());
1718
1719
    nsCOMPtr<nsIFile> objDir;
1720
    rv = mozilla::GetObjDir(getter_AddRefs(objDir));
1721
    if (NS_FAILED(rv)) {
1722
      MOZ_CRASH("Failed to get path to build object dir");
1723
    }
1724
1725
    nsCString objDirPath;
1726
    Unused << objDir->GetNativePath(objDirPath);
1727
    info.testingReadPath4.assign(objDirPath.get());
1728
  }
1729
1730
  if (profileDir) {
1731
    info.hasSandboxedProfile = true;
1732
    info.profileDir.assign(profileDirPath.get());
1733
  } else {
1734
    info.hasSandboxedProfile = false;
1735
  }
1736
1737
#ifdef DEBUG
1738
  // When a content process dies intentionally (|NoteIntentionalCrash|), for
1739
  // tests it wants to log that it did this. Allow writing to this location
1740
  // that the testrunner wants.
1741
  char *bloatLog = PR_GetEnv("XPCOM_MEM_BLOAT_LOG");
1742
  if (bloatLog != nullptr) {
1743
    // |bloatLog| points to a specific file, but we actually write to a sibling
1744
    // of that path.
1745
    nsAutoCString bloatDirectoryPath = GetDirectoryPath(bloatLog);
1746
    info.debugWriteDir.assign(bloatDirectoryPath.get());
1747
  }
1748
#endif // DEBUG
1749
1750
  std::string err;
1751
  if (!mozilla::StartMacSandbox(info, err)) {
1752
    NS_WARNING(err.c_str());
1753
    MOZ_CRASH("sandbox_init() failed");
1754
  }
1755
1756
  return true;
1757
}
1758
#endif
1759
1760
mozilla::ipc::IPCResult
1761
ContentChild::RecvSetProcessSandbox(const MaybeFileDesc& aBroker)
1762
0
{
1763
0
  // We may want to move the sandbox initialization somewhere else
1764
0
  // at some point; see bug 880808.
1765
0
#if defined(MOZ_CONTENT_SANDBOX)
1766
0
  bool sandboxEnabled = true;
1767
0
#if defined(XP_LINUX)
1768
0
  // On Linux, we have to support systems that can't use any sandboxing.
1769
0
  if (!SandboxInfo::Get().CanSandboxContent()) {
1770
0
    sandboxEnabled = false;
1771
0
  } else {
1772
0
    // Pre-start audio before sandboxing; see bug 1443612.
1773
0
    if (!Preferences::GetBool("media.cubeb.sandbox")) {
1774
0
      Unused << CubebUtils::GetCubebContext();
1775
0
    }
1776
0
  }
1777
0
1778
0
  if (sandboxEnabled) {
1779
0
    sandboxEnabled =
1780
0
      SetContentProcessSandbox(ContentProcessSandboxParams::ForThisProcess(aBroker));
1781
0
  }
1782
#elif defined(XP_WIN)
1783
  mozilla::SandboxTarget::Instance()->StartSandbox();
1784
#elif defined(XP_MACOSX)
1785
  sandboxEnabled = StartMacOSContentSandbox();
1786
#elif defined(__OpenBSD__)
1787
  sandboxEnabled = StartOpenBSDSandbox(GeckoProcessType_Content);
1788
  /* dont overwrite an existing session dbus address, but ensure it is set */
1789
  if (!PR_GetEnv("DBUS_SESSION_BUS_ADDRESS")) {
1790
      static LazyLogModule sPledgeLog("SandboxPledge");
1791
      MOZ_LOG(sPledgeLog, LogLevel::Debug, ("no session dbus found, faking one\n"));
1792
      PR_SetEnv("DBUS_SESSION_BUS_ADDRESS=");
1793
  }
1794
#endif
1795
1796
0
  CrashReporter::AnnotateCrashReport(
1797
0
    CrashReporter::Annotation::ContentSandboxEnabled, sandboxEnabled);
1798
0
#if defined(XP_LINUX) && !defined(OS_ANDROID)
1799
0
  CrashReporter::AnnotateCrashReport(
1800
0
    CrashReporter::Annotation::ContentSandboxCapabilities,
1801
0
    static_cast<int>(SandboxInfo::Get().AsInteger()));
1802
0
#endif /* XP_LINUX && !OS_ANDROID */
1803
0
  CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::RemoteType,
1804
0
                                     NS_ConvertUTF16toUTF8(GetRemoteType()));
1805
0
#endif /* MOZ_CONTENT_SANDBOX */
1806
0
1807
0
  return IPC_OK();
1808
0
}
1809
1810
mozilla::ipc::IPCResult
1811
ContentChild::RecvBidiKeyboardNotify(const bool& aIsLangRTL,
1812
                                     const bool& aHaveBidiKeyboards)
1813
0
{
1814
0
  // bidi is always of type PuppetBidiKeyboard* (because in the child, the only
1815
0
  // possible implementation of nsIBidiKeyboard is PuppetBidiKeyboard).
1816
0
  PuppetBidiKeyboard* bidi = static_cast<PuppetBidiKeyboard*>(nsContentUtils::GetBidiKeyboard());
1817
0
  if (bidi) {
1818
0
    bidi->SetBidiKeyboardInfo(aIsLangRTL, aHaveBidiKeyboards);
1819
0
  }
1820
0
  return IPC_OK();
1821
0
}
1822
1823
static StaticRefPtr<CancelableRunnable> gFirstIdleTask;
1824
1825
static void
1826
FirstIdle(void)
1827
0
{
1828
0
  MOZ_ASSERT(gFirstIdleTask);
1829
0
  gFirstIdleTask = nullptr;
1830
0
1831
0
  // When recording or replaying, the middleman process will send this message instead.
1832
0
  if (!recordreplay::IsRecordingOrReplaying()) {
1833
0
    ContentChild::GetSingleton()->SendFirstIdle();
1834
0
  }
1835
0
}
1836
1837
mozilla::jsipc::PJavaScriptChild *
1838
ContentChild::AllocPJavaScriptChild()
1839
0
{
1840
0
  MOZ_ASSERT(ManagedPJavaScriptChild().IsEmpty());
1841
0
1842
0
  return nsIContentChild::AllocPJavaScriptChild();
1843
0
}
1844
1845
bool
1846
ContentChild::DeallocPJavaScriptChild(PJavaScriptChild *aChild)
1847
0
{
1848
0
  return nsIContentChild::DeallocPJavaScriptChild(aChild);
1849
0
}
1850
1851
PBrowserChild*
1852
ContentChild::AllocPBrowserChild(const TabId& aTabId,
1853
                                 const TabId& aSameTabGroupAs,
1854
                                 const IPCTabContext& aContext,
1855
                                 const uint32_t& aChromeFlags,
1856
                                 const ContentParentId& aCpID,
1857
                                 const bool& aIsForBrowser)
1858
0
{
1859
0
  return nsIContentChild::AllocPBrowserChild(aTabId,
1860
0
                                             aSameTabGroupAs,
1861
0
                                             aContext,
1862
0
                                             aChromeFlags,
1863
0
                                             aCpID,
1864
0
                                             aIsForBrowser);
1865
0
}
1866
1867
bool
1868
ContentChild::SendPBrowserConstructor(PBrowserChild* aActor,
1869
                                      const TabId& aTabId,
1870
                                      const TabId& aSameTabGroupAs,
1871
                                      const IPCTabContext& aContext,
1872
                                      const uint32_t& aChromeFlags,
1873
                                      const ContentParentId& aCpID,
1874
                                      const bool& aIsForBrowser)
1875
0
{
1876
0
  if (IsShuttingDown()) {
1877
0
    return false;
1878
0
  }
1879
0
1880
0
  return PContentChild::SendPBrowserConstructor(aActor,
1881
0
                                                aTabId,
1882
0
                                                aSameTabGroupAs,
1883
0
                                                aContext,
1884
0
                                                aChromeFlags,
1885
0
                                                aCpID,
1886
0
                                                aIsForBrowser);
1887
0
}
1888
1889
mozilla::ipc::IPCResult
1890
ContentChild::RecvPBrowserConstructor(PBrowserChild* aActor,
1891
                                      const TabId& aTabId,
1892
                                      const TabId& aSameTabGroupAs,
1893
                                      const IPCTabContext& aContext,
1894
                                      const uint32_t& aChromeFlags,
1895
                                      const ContentParentId& aCpID,
1896
                                      const bool& aIsForBrowser)
1897
0
{
1898
0
  MOZ_ASSERT(!IsShuttingDown());
1899
0
1900
0
  static bool hasRunOnce = false;
1901
0
  if (!hasRunOnce) {
1902
0
    hasRunOnce = true;
1903
0
    MOZ_ASSERT(!gFirstIdleTask);
1904
0
    RefPtr<CancelableRunnable> firstIdleTask = NewCancelableRunnableFunction("FirstIdleRunnable",
1905
0
                                                                             FirstIdle);
1906
0
    gFirstIdleTask = firstIdleTask;
1907
0
    if (NS_FAILED(NS_IdleDispatchToCurrentThread(firstIdleTask.forget()))) {
1908
0
      gFirstIdleTask = nullptr;
1909
0
      hasRunOnce = false;
1910
0
    }
1911
0
  }
1912
0
1913
0
  return nsIContentChild::RecvPBrowserConstructor(aActor,
1914
0
                                                  aTabId,
1915
0
                                                  aSameTabGroupAs,
1916
0
                                                  aContext,
1917
0
                                                  aChromeFlags,
1918
0
                                                  aCpID,
1919
0
                                                  aIsForBrowser);
1920
0
}
1921
1922
void
1923
ContentChild::GetAvailableDictionaries(InfallibleTArray<nsString>& aDictionaries)
1924
0
{
1925
0
  aDictionaries = mAvailableDictionaries;
1926
0
}
1927
1928
PFileDescriptorSetChild*
1929
ContentChild::SendPFileDescriptorSetConstructor(const FileDescriptor& aFD)
1930
0
{
1931
0
  if (IsShuttingDown()) {
1932
0
    return nullptr;
1933
0
  }
1934
0
1935
0
  return PContentChild::SendPFileDescriptorSetConstructor(aFD);
1936
0
}
1937
1938
PFileDescriptorSetChild*
1939
ContentChild::AllocPFileDescriptorSetChild(const FileDescriptor& aFD)
1940
0
{
1941
0
  return nsIContentChild::AllocPFileDescriptorSetChild(aFD);
1942
0
}
1943
1944
bool
1945
ContentChild::DeallocPFileDescriptorSetChild(PFileDescriptorSetChild* aActor)
1946
0
{
1947
0
  return nsIContentChild::DeallocPFileDescriptorSetChild(aActor);
1948
0
}
1949
1950
bool
1951
ContentChild::DeallocPBrowserChild(PBrowserChild* aIframe)
1952
0
{
1953
0
  return nsIContentChild::DeallocPBrowserChild(aIframe);
1954
0
}
1955
1956
PIPCBlobInputStreamChild*
1957
ContentChild::AllocPIPCBlobInputStreamChild(const nsID& aID,
1958
                                            const uint64_t& aSize)
1959
0
{
1960
0
  return nsIContentChild::AllocPIPCBlobInputStreamChild(aID, aSize);
1961
0
}
1962
1963
bool
1964
ContentChild::DeallocPIPCBlobInputStreamChild(PIPCBlobInputStreamChild* aActor)
1965
0
{
1966
0
  return nsIContentChild::DeallocPIPCBlobInputStreamChild(aActor);
1967
0
}
1968
1969
mozilla::PRemoteSpellcheckEngineChild *
1970
ContentChild::AllocPRemoteSpellcheckEngineChild()
1971
0
{
1972
0
  MOZ_CRASH("Default Constructor for PRemoteSpellcheckEngineChild should never be called");
1973
0
  return nullptr;
1974
0
}
1975
1976
bool
1977
ContentChild::DeallocPRemoteSpellcheckEngineChild(PRemoteSpellcheckEngineChild *child)
1978
0
{
1979
0
  delete child;
1980
0
  return true;
1981
0
}
1982
1983
PPresentationChild*
1984
ContentChild::AllocPPresentationChild()
1985
0
{
1986
0
  MOZ_CRASH("We should never be manually allocating PPresentationChild actors");
1987
0
  return nullptr;
1988
0
}
1989
1990
bool
1991
ContentChild::DeallocPPresentationChild(PPresentationChild* aActor)
1992
0
{
1993
0
  delete aActor;
1994
0
  return true;
1995
0
}
1996
1997
mozilla::ipc::IPCResult
1998
ContentChild::RecvNotifyPresentationReceiverLaunched(PBrowserChild* aIframe,
1999
                                                     const nsString& aSessionId)
2000
0
{
2001
0
  nsCOMPtr<nsIDocShell> docShell =
2002
0
    do_GetInterface(static_cast<TabChild*>(aIframe)->WebNavigation());
2003
0
  NS_WARNING_ASSERTION(docShell, "WebNavigation failed");
2004
0
2005
0
  nsCOMPtr<nsIPresentationService> service =
2006
0
    do_GetService(PRESENTATION_SERVICE_CONTRACTID);
2007
0
  NS_WARNING_ASSERTION(service, "presentation service is missing");
2008
0
2009
0
  Unused << NS_WARN_IF(NS_FAILED(static_cast<PresentationIPCService*>(service.get())->MonitorResponderLoading(aSessionId, docShell)));
2010
0
2011
0
  return IPC_OK();
2012
0
}
2013
2014
mozilla::ipc::IPCResult
2015
ContentChild::RecvNotifyPresentationReceiverCleanUp(const nsString& aSessionId)
2016
0
{
2017
0
  nsCOMPtr<nsIPresentationService> service =
2018
0
    do_GetService(PRESENTATION_SERVICE_CONTRACTID);
2019
0
  NS_WARNING_ASSERTION(service, "presentation service is missing");
2020
0
2021
0
  Unused << NS_WARN_IF(NS_FAILED(service->UntrackSessionInfo(aSessionId, nsIPresentationService::ROLE_RECEIVER)));
2022
0
2023
0
  return IPC_OK();
2024
0
}
2025
2026
mozilla::ipc::IPCResult
2027
ContentChild::RecvNotifyEmptyHTTPCache()
2028
0
{
2029
0
  MOZ_ASSERT(NS_IsMainThread());
2030
0
  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
2031
0
  obs->NotifyObservers(nullptr, "cacheservice:empty-cache", nullptr);
2032
0
  return IPC_OK();
2033
0
}
2034
2035
PHalChild*
2036
ContentChild::AllocPHalChild()
2037
0
{
2038
0
  return CreateHalChild();
2039
0
}
2040
2041
bool
2042
ContentChild::DeallocPHalChild(PHalChild* aHal)
2043
0
{
2044
0
  delete aHal;
2045
0
  return true;
2046
0
}
2047
2048
devtools::PHeapSnapshotTempFileHelperChild*
2049
ContentChild::AllocPHeapSnapshotTempFileHelperChild()
2050
0
{
2051
0
  return devtools::HeapSnapshotTempFileHelperChild::Create();
2052
0
}
2053
2054
bool
2055
ContentChild::DeallocPHeapSnapshotTempFileHelperChild(
2056
  devtools::PHeapSnapshotTempFileHelperChild* aHeapSnapshotHelper)
2057
0
{
2058
0
  delete aHeapSnapshotHelper;
2059
0
  return true;
2060
0
}
2061
2062
PTestShellChild*
2063
ContentChild::AllocPTestShellChild()
2064
0
{
2065
0
  return new TestShellChild();
2066
0
}
2067
2068
bool
2069
ContentChild::DeallocPTestShellChild(PTestShellChild* shell)
2070
0
{
2071
0
  delete shell;
2072
0
  return true;
2073
0
}
2074
2075
jsipc::CPOWManager*
2076
ContentChild::GetCPOWManager()
2077
0
{
2078
0
  if (PJavaScriptChild* c = LoneManagedOrNullAsserts(ManagedPJavaScriptChild())) {
2079
0
    return CPOWManagerFor(c);
2080
0
  }
2081
0
  if (recordreplay::IsMiddleman()) {
2082
0
    return nullptr;
2083
0
  }
2084
0
  return CPOWManagerFor(SendPJavaScriptConstructor());
2085
0
}
2086
2087
mozilla::ipc::IPCResult
2088
ContentChild::RecvPTestShellConstructor(PTestShellChild* actor)
2089
0
{
2090
0
  return IPC_OK();
2091
0
}
2092
2093
void
2094
ContentChild::UpdateCookieStatus(nsIChannel   *aChannel)
2095
0
{
2096
0
  RefPtr<CookieServiceChild> csChild =
2097
0
    CookieServiceChild::GetSingleton();
2098
0
  NS_ASSERTION(csChild, "Couldn't get CookieServiceChild");
2099
0
2100
0
  csChild->TrackCookieLoad(aChannel);
2101
0
}
2102
2103
PScriptCacheChild*
2104
ContentChild::AllocPScriptCacheChild(const FileDescOrError& cacheFile, const bool& wantCacheData)
2105
0
{
2106
0
  return new loader::ScriptCacheChild();
2107
0
}
2108
2109
bool
2110
ContentChild::DeallocPScriptCacheChild(PScriptCacheChild* cache)
2111
0
{
2112
0
  delete static_cast<loader::ScriptCacheChild*>(cache);
2113
0
  return true;
2114
0
}
2115
2116
mozilla::ipc::IPCResult
2117
ContentChild::RecvPScriptCacheConstructor(PScriptCacheChild* actor, const FileDescOrError& cacheFile, const bool& wantCacheData)
2118
0
{
2119
0
  Maybe<FileDescriptor> fd;
2120
0
  if (cacheFile.type() == cacheFile.TFileDescriptor) {
2121
0
    fd.emplace(cacheFile.get_FileDescriptor());
2122
0
  }
2123
0
2124
0
  static_cast<loader::ScriptCacheChild*>(actor)->Init(fd, wantCacheData);
2125
0
  return IPC_OK();
2126
0
}
2127
2128
PNeckoChild*
2129
ContentChild::AllocPNeckoChild()
2130
0
{
2131
0
  return new NeckoChild();
2132
0
}
2133
2134
bool
2135
ContentChild::DeallocPNeckoChild(PNeckoChild* necko)
2136
0
{
2137
0
  delete necko;
2138
0
  return true;
2139
0
}
2140
2141
PPrintingChild*
2142
ContentChild::AllocPPrintingChild()
2143
0
{
2144
0
  // The ContentParent should never attempt to allocate the nsPrintingProxy,
2145
0
  // which implements PPrintingChild. Instead, the nsPrintingProxy service is
2146
0
  // requested and instantiated via XPCOM, and the constructor of
2147
0
  // nsPrintingProxy sets up the IPC connection.
2148
0
  MOZ_CRASH("Should never get here!");
2149
0
  return nullptr;
2150
0
}
2151
2152
bool
2153
ContentChild::DeallocPPrintingChild(PPrintingChild* printing)
2154
0
{
2155
0
  return true;
2156
0
}
2157
2158
PChildToParentStreamChild*
2159
ContentChild::SendPChildToParentStreamConstructor(PChildToParentStreamChild* aActor)
2160
0
{
2161
0
  if (IsShuttingDown()) {
2162
0
    return nullptr;
2163
0
  }
2164
0
2165
0
  return PContentChild::SendPChildToParentStreamConstructor(aActor);
2166
0
}
2167
2168
PChildToParentStreamChild*
2169
ContentChild::AllocPChildToParentStreamChild()
2170
0
{
2171
0
  return nsIContentChild::AllocPChildToParentStreamChild();
2172
0
}
2173
2174
bool
2175
ContentChild::DeallocPChildToParentStreamChild(PChildToParentStreamChild* aActor)
2176
0
{
2177
0
  return nsIContentChild::DeallocPChildToParentStreamChild(aActor);
2178
0
}
2179
2180
PParentToChildStreamChild*
2181
ContentChild::AllocPParentToChildStreamChild()
2182
0
{
2183
0
  return nsIContentChild::AllocPParentToChildStreamChild();
2184
0
}
2185
2186
bool
2187
ContentChild::DeallocPParentToChildStreamChild(PParentToChildStreamChild* aActor)
2188
0
{
2189
0
  return nsIContentChild::DeallocPParentToChildStreamChild(aActor);
2190
0
}
2191
2192
PPSMContentDownloaderChild*
2193
ContentChild::AllocPPSMContentDownloaderChild(const uint32_t& aCertType)
2194
0
{
2195
0
  // NB: We don't need aCertType in the child actor.
2196
0
  RefPtr<PSMContentDownloaderChild> child = new PSMContentDownloaderChild();
2197
0
  return child.forget().take();
2198
0
}
2199
2200
bool
2201
ContentChild::DeallocPPSMContentDownloaderChild(PPSMContentDownloaderChild* aListener)
2202
0
{
2203
0
  auto* listener = static_cast<PSMContentDownloaderChild*>(aListener);
2204
0
  RefPtr<PSMContentDownloaderChild> child = dont_AddRef(listener);
2205
0
  return true;
2206
0
}
2207
2208
PExternalHelperAppChild*
2209
ContentChild::AllocPExternalHelperAppChild(const OptionalURIParams& uri,
2210
                                           const nsCString& aMimeContentType,
2211
                                           const nsCString& aContentDisposition,
2212
                                           const uint32_t& aContentDispositionHint,
2213
                                           const nsString& aContentDispositionFilename,
2214
                                           const bool& aForceSave,
2215
                                           const int64_t& aContentLength,
2216
                                           const bool& aWasFileChannel,
2217
                                           const OptionalURIParams& aReferrer,
2218
                                           PBrowserChild* aBrowser)
2219
0
{
2220
0
  auto *child = new ExternalHelperAppChild();
2221
0
  child->AddRef();
2222
0
  return child;
2223
0
}
2224
2225
bool
2226
ContentChild::DeallocPExternalHelperAppChild(PExternalHelperAppChild* aService)
2227
0
{
2228
0
  ExternalHelperAppChild *child = static_cast<ExternalHelperAppChild*>(aService);
2229
0
  child->Release();
2230
0
  return true;
2231
0
}
2232
2233
PHandlerServiceChild*
2234
ContentChild::AllocPHandlerServiceChild()
2235
0
{
2236
0
  auto* actor = new HandlerServiceChild();
2237
0
  actor->AddRef();
2238
0
  return actor;
2239
0
}
2240
2241
bool ContentChild::DeallocPHandlerServiceChild(PHandlerServiceChild* aHandlerServiceChild)
2242
0
{
2243
0
  static_cast<HandlerServiceChild*>(aHandlerServiceChild)->Release();
2244
0
  return true;
2245
0
}
2246
2247
media::PMediaChild*
2248
ContentChild::AllocPMediaChild()
2249
0
{
2250
0
  return media::AllocPMediaChild();
2251
0
}
2252
2253
bool
2254
ContentChild::DeallocPMediaChild(media::PMediaChild *aActor)
2255
0
{
2256
0
  return media::DeallocPMediaChild(aActor);
2257
0
}
2258
2259
PSpeechSynthesisChild*
2260
ContentChild::AllocPSpeechSynthesisChild()
2261
0
{
2262
0
#ifdef MOZ_WEBSPEECH
2263
0
  MOZ_CRASH("No one should be allocating PSpeechSynthesisChild actors");
2264
#else
2265
  return nullptr;
2266
#endif
2267
}
2268
2269
bool
2270
ContentChild::DeallocPSpeechSynthesisChild(PSpeechSynthesisChild* aActor)
2271
0
{
2272
0
#ifdef MOZ_WEBSPEECH
2273
0
  delete aActor;
2274
0
  return true;
2275
#else
2276
  return false;
2277
#endif
2278
}
2279
2280
PWebrtcGlobalChild *
2281
ContentChild::AllocPWebrtcGlobalChild()
2282
0
{
2283
0
#ifdef MOZ_WEBRTC
2284
0
  auto *child = new WebrtcGlobalChild();
2285
0
  return child;
2286
#else
2287
  return nullptr;
2288
#endif
2289
}
2290
2291
bool
2292
ContentChild::DeallocPWebrtcGlobalChild(PWebrtcGlobalChild *aActor)
2293
0
{
2294
0
#ifdef MOZ_WEBRTC
2295
0
  delete static_cast<WebrtcGlobalChild*>(aActor);
2296
0
  return true;
2297
#else
2298
  return false;
2299
#endif
2300
}
2301
2302
2303
mozilla::ipc::IPCResult
2304
ContentChild::RecvRegisterChrome(InfallibleTArray<ChromePackage>&& packages,
2305
                                 InfallibleTArray<SubstitutionMapping>&& resources,
2306
                                 InfallibleTArray<OverrideMapping>&& overrides,
2307
                                 const nsCString& locale,
2308
                                 const bool& reset)
2309
0
{
2310
0
  nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
2311
0
  nsChromeRegistryContent* chromeRegistry =
2312
0
    static_cast<nsChromeRegistryContent*>(registrySvc.get());
2313
0
  if (!chromeRegistry) {
2314
0
    return IPC_FAIL(this, "ChromeRegistryContent is null!");
2315
0
  }
2316
0
  chromeRegistry->RegisterRemoteChrome(packages, resources, overrides,
2317
0
                                       locale, reset);
2318
0
  return IPC_OK();
2319
0
}
2320
2321
mozilla::ipc::IPCResult
2322
ContentChild::RecvRegisterChromeItem(const ChromeRegistryItem& item)
2323
0
{
2324
0
  nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
2325
0
  nsChromeRegistryContent* chromeRegistry =
2326
0
    static_cast<nsChromeRegistryContent*>(registrySvc.get());
2327
0
  if (!chromeRegistry) {
2328
0
    return IPC_FAIL(this, "ChromeRegistryContent is null!");
2329
0
  }
2330
0
  switch (item.type()) {
2331
0
    case ChromeRegistryItem::TChromePackage:
2332
0
      chromeRegistry->RegisterPackage(item.get_ChromePackage());
2333
0
      break;
2334
0
2335
0
    case ChromeRegistryItem::TOverrideMapping:
2336
0
      chromeRegistry->RegisterOverride(item.get_OverrideMapping());
2337
0
      break;
2338
0
2339
0
    case ChromeRegistryItem::TSubstitutionMapping:
2340
0
      chromeRegistry->RegisterSubstitution(item.get_SubstitutionMapping());
2341
0
      break;
2342
0
2343
0
    default:
2344
0
      MOZ_ASSERT(false, "bad chrome item");
2345
0
      return IPC_FAIL_NO_REASON(this);
2346
0
  }
2347
0
2348
0
  return IPC_OK();
2349
0
}
2350
2351
mozilla::ipc::IPCResult
2352
ContentChild::RecvClearImageCache(const bool& privateLoader, const bool& chrome)
2353
0
{
2354
0
  imgLoader* loader = privateLoader ? imgLoader::PrivateBrowsingLoader() :
2355
0
                                      imgLoader::NormalLoader();
2356
0
2357
0
  loader->ClearCache(chrome);
2358
0
  return IPC_OK();
2359
0
}
2360
2361
mozilla::ipc::IPCResult
2362
ContentChild::RecvSetOffline(const bool& offline)
2363
0
{
2364
0
  nsCOMPtr<nsIIOService> io (do_GetIOService());
2365
0
  NS_ASSERTION(io, "IO Service can not be null");
2366
0
2367
0
  io->SetOffline(offline);
2368
0
2369
0
  return IPC_OK();
2370
0
}
2371
2372
mozilla::ipc::IPCResult
2373
ContentChild::RecvSetConnectivity(const bool& connectivity)
2374
0
{
2375
0
  nsCOMPtr<nsIIOService> io(do_GetIOService());
2376
0
  nsCOMPtr<nsIIOServiceInternal> ioInternal(do_QueryInterface(io));
2377
0
  NS_ASSERTION(ioInternal, "IO Service can not be null");
2378
0
2379
0
  ioInternal->SetConnectivity(connectivity);
2380
0
2381
0
  return IPC_OK();
2382
0
}
2383
2384
mozilla::ipc::IPCResult
2385
ContentChild::RecvSetCaptivePortalState(const int32_t& aState)
2386
0
{
2387
0
  nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID);
2388
0
  if (!cps) {
2389
0
    return IPC_OK();
2390
0
  }
2391
0
2392
0
  mozilla::net::CaptivePortalService *portal =
2393
0
    static_cast<mozilla::net::CaptivePortalService*>(cps.get());
2394
0
  portal->SetStateInChild(aState);
2395
0
2396
0
  return IPC_OK();
2397
0
}
2398
2399
void
2400
ContentChild::ActorDestroy(ActorDestroyReason why)
2401
0
{
2402
0
  if (mForceKillTimer) {
2403
0
    mForceKillTimer->Cancel();
2404
0
    mForceKillTimer = nullptr;
2405
0
  }
2406
0
2407
0
  if (AbnormalShutdown == why) {
2408
0
    NS_WARNING("shutting down early because of crash!");
2409
0
    ProcessChild::QuickExit();
2410
0
  }
2411
0
2412
0
#ifndef NS_FREE_PERMANENT_DATA
2413
0
  // In release builds, there's no point in the content process
2414
0
  // going through the full XPCOM shutdown path, because it doesn't
2415
0
  // keep persistent state.
2416
0
  ProcessChild::QuickExit();
2417
#else
2418
  if (gFirstIdleTask) {
2419
    gFirstIdleTask->Cancel();
2420
    gFirstIdleTask = nullptr;
2421
  }
2422
2423
  BlobURLProtocolHandler::RemoveDataEntries();
2424
2425
  mSharedData = nullptr;
2426
2427
  mAlertObservers.Clear();
2428
2429
  mIdleObservers.Clear();
2430
2431
  nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
2432
  if (svc) {
2433
    svc->UnregisterListener(mConsoleListener);
2434
    mConsoleListener->mChild = nullptr;
2435
  }
2436
  mIsAlive = false;
2437
2438
  CrashReporterClient::DestroySingleton();
2439
2440
  XRE_ShutdownChildProcess();
2441
#endif // NS_FREE_PERMANENT_DATA
2442
}
2443
2444
void
2445
ContentChild::ProcessingError(Result aCode, const char* aReason)
2446
0
{
2447
0
  switch (aCode) {
2448
0
    case MsgDropped:
2449
0
      NS_WARNING("MsgDropped in ContentChild");
2450
0
      return;
2451
0
2452
0
    case MsgNotKnown:
2453
0
    case MsgNotAllowed:
2454
0
    case MsgPayloadError:
2455
0
    case MsgProcessingError:
2456
0
    case MsgRouteError:
2457
0
    case MsgValueError:
2458
0
      break;
2459
0
2460
0
    default:
2461
0
      MOZ_CRASH("not reached");
2462
0
  }
2463
0
2464
0
  nsDependentCString reason(aReason);
2465
0
  CrashReporter::AnnotateCrashReport(
2466
0
    CrashReporter::Annotation::ipc_channel_error, reason);
2467
0
2468
0
  MOZ_CRASH("Content child abort due to IPC error");
2469
0
}
2470
2471
nsresult
2472
ContentChild::AddRemoteAlertObserver(const nsString& aData,
2473
                                     nsIObserver* aObserver)
2474
0
{
2475
0
  NS_ASSERTION(aObserver, "Adding a null observer?");
2476
0
  mAlertObservers.AppendElement(new AlertObserver(aObserver, aData));
2477
0
  return NS_OK;
2478
0
}
2479
2480
mozilla::ipc::IPCResult
2481
ContentChild::RecvPreferenceUpdate(const Pref& aPref)
2482
0
{
2483
0
  Preferences::SetPreference(aPref);
2484
0
  return IPC_OK();
2485
0
}
2486
2487
mozilla::ipc::IPCResult
2488
ContentChild::RecvVarUpdate(const GfxVarUpdate& aVar)
2489
0
{
2490
0
  gfx::gfxVars::ApplyUpdate(aVar);
2491
0
  return IPC_OK();
2492
0
}
2493
2494
mozilla::ipc::IPCResult
2495
ContentChild::RecvDataStoragePut(const nsString& aFilename,
2496
                                 const DataStorageItem& aItem)
2497
0
{
2498
0
  RefPtr<DataStorage> storage = DataStorage::GetFromRawFileName(aFilename);
2499
0
  if (storage) {
2500
0
    storage->Put(aItem.key(), aItem.value(), aItem.type());
2501
0
  }
2502
0
  return IPC_OK();
2503
0
}
2504
2505
mozilla::ipc::IPCResult
2506
ContentChild::RecvDataStorageRemove(const nsString& aFilename,
2507
                                    const nsCString& aKey,
2508
                                    const DataStorageType& aType)
2509
0
{
2510
0
  RefPtr<DataStorage> storage = DataStorage::GetFromRawFileName(aFilename);
2511
0
  if (storage) {
2512
0
    storage->Remove(aKey, aType);
2513
0
  }
2514
0
  return IPC_OK();
2515
0
}
2516
2517
mozilla::ipc::IPCResult
2518
ContentChild::RecvDataStorageClear(const nsString& aFilename)
2519
0
{
2520
0
  RefPtr<DataStorage> storage = DataStorage::GetFromRawFileName(aFilename);
2521
0
  if (storage) {
2522
0
    storage->Clear();
2523
0
  }
2524
0
  return IPC_OK();
2525
0
}
2526
2527
mozilla::ipc::IPCResult
2528
ContentChild::RecvNotifyAlertsObserver(const nsCString& aType, const nsString& aData)
2529
0
{
2530
0
  for (uint32_t i = 0; i < mAlertObservers.Length();
2531
0
     /*we mutate the array during the loop; ++i iff no mutation*/) {
2532
0
    AlertObserver* observer = mAlertObservers[i];
2533
0
    if (observer->Observes(aData) && observer->Notify(aType)) {
2534
0
      // if aType == alertfinished, this alert is done.  we can
2535
0
      // remove the observer.
2536
0
      if (aType.Equals(nsDependentCString("alertfinished"))) {
2537
0
        mAlertObservers.RemoveElementAt(i);
2538
0
        continue;
2539
0
      }
2540
0
    }
2541
0
    ++i;
2542
0
  }
2543
0
  return IPC_OK();
2544
0
}
2545
2546
// NOTE: This method is being run in the SystemGroup, and thus cannot directly
2547
// touch pages. See GetSpecificMessageEventTarget.
2548
mozilla::ipc::IPCResult
2549
ContentChild::RecvNotifyVisited(nsTArray<URIParams>&& aURIs)
2550
0
{
2551
0
  for (const URIParams& uri : aURIs) {
2552
0
    nsCOMPtr<nsIURI> newURI = DeserializeURI(uri);
2553
0
    if (!newURI) {
2554
0
      return IPC_FAIL_NO_REASON(this);
2555
0
    }
2556
0
    nsCOMPtr<IHistory> history = services::GetHistoryService();
2557
0
    if (history) {
2558
0
      history->NotifyVisited(newURI);
2559
0
    }
2560
0
  }
2561
0
  return IPC_OK();
2562
0
}
2563
2564
mozilla::ipc::IPCResult
2565
ContentChild::RecvLoadProcessScript(const nsString& aURL)
2566
0
{
2567
0
  auto* global = ContentProcessMessageManager::Get();
2568
0
  global->LoadScript(aURL);
2569
0
  return IPC_OK();
2570
0
}
2571
2572
mozilla::ipc::IPCResult
2573
ContentChild::RecvAsyncMessage(const nsString& aMsg,
2574
                               InfallibleTArray<CpowEntry>&& aCpows,
2575
                               const IPC::Principal& aPrincipal,
2576
                               const ClonedMessageData& aData)
2577
0
{
2578
0
  AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING(
2579
0
    "ContentChild::RecvAsyncMessage", OTHER, aMsg);
2580
0
2581
0
  CrossProcessCpowHolder cpows(this, aCpows);
2582
0
  RefPtr<nsFrameMessageManager> cpm =
2583
0
    nsFrameMessageManager::GetChildProcessManager();
2584
0
  if (cpm) {
2585
0
    StructuredCloneData data;
2586
0
    ipc::UnpackClonedMessageDataForChild(aData, data);
2587
0
    cpm->ReceiveMessage(cpm, nullptr, aMsg, false, &data, &cpows, aPrincipal, nullptr,
2588
0
                        IgnoreErrors());
2589
0
  }
2590
0
  return IPC_OK();
2591
0
}
2592
2593
mozilla::ipc::IPCResult
2594
ContentChild::RecvRegisterStringBundles(nsTArray<mozilla::dom::StringBundleDescriptor>&& aDescriptors)
2595
0
{
2596
0
  nsCOMPtr<nsIStringBundleService> stringBundleService =
2597
0
    services::GetStringBundleService();
2598
0
2599
0
  for (auto& descriptor : aDescriptors) {
2600
0
    stringBundleService->RegisterContentBundle(descriptor.bundleURL(), descriptor.mapFile(),
2601
0
                                               descriptor.mapSize());
2602
0
  }
2603
0
2604
0
  return IPC_OK();
2605
0
}
2606
2607
mozilla::ipc::IPCResult
2608
ContentChild::RecvUpdateSharedData(const FileDescriptor& aMapFile,
2609
                                   const uint32_t& aMapSize,
2610
                                   nsTArray<IPCBlob>&& aBlobs,
2611
                                   nsTArray<nsCString>&& aChangedKeys)
2612
0
{
2613
0
  nsTArray<RefPtr<BlobImpl>> blobImpls(aBlobs.Length());
2614
0
  for (auto& ipcBlob : aBlobs) {
2615
0
    blobImpls.AppendElement(IPCBlobUtils::Deserialize(ipcBlob));
2616
0
  }
2617
0
2618
0
  if (mSharedData) {
2619
0
    mSharedData->Update(aMapFile, aMapSize,
2620
0
                        std::move(blobImpls),
2621
0
                        std::move(aChangedKeys));
2622
0
  } else {
2623
0
    mSharedData = new SharedMap(ContentProcessMessageManager::Get()->GetParentObject(),
2624
0
                                aMapFile, aMapSize, std::move(blobImpls));
2625
0
  }
2626
0
2627
0
  return IPC_OK();
2628
0
}
2629
2630
mozilla::ipc::IPCResult
2631
ContentChild::RecvGeolocationUpdate(nsIDOMGeoPosition* aPosition)
2632
0
{
2633
0
  RefPtr<nsGeolocationService> gs =
2634
0
    nsGeolocationService::GetGeolocationService();
2635
0
  if (!gs) {
2636
0
    return IPC_OK();
2637
0
  }
2638
0
  gs->Update(aPosition);
2639
0
  return IPC_OK();
2640
0
}
2641
2642
mozilla::ipc::IPCResult
2643
ContentChild::RecvGeolocationError(const uint16_t& errorCode)
2644
0
{
2645
0
  RefPtr<nsGeolocationService> gs =
2646
0
    nsGeolocationService::GetGeolocationService();
2647
0
  if (!gs) {
2648
0
    return IPC_OK();
2649
0
  }
2650
0
  gs->NotifyError(errorCode);
2651
0
  return IPC_OK();
2652
0
}
2653
2654
mozilla::ipc::IPCResult
2655
ContentChild::RecvUpdateDictionaryList(InfallibleTArray<nsString>&& aDictionaries)
2656
0
{
2657
0
  mAvailableDictionaries = aDictionaries;
2658
0
  mozInlineSpellChecker::UpdateCanEnableInlineSpellChecking();
2659
0
  return IPC_OK();
2660
0
}
2661
2662
mozilla::ipc::IPCResult
2663
ContentChild::RecvUpdateFontList(InfallibleTArray<SystemFontListEntry>&& aFontList)
2664
0
{
2665
0
  mFontList = std::move(aFontList);
2666
0
  gfxPlatform::GetPlatform()->UpdateFontList();
2667
0
  return IPC_OK();
2668
0
}
2669
2670
mozilla::ipc::IPCResult
2671
ContentChild::RecvUpdateAppLocales(nsTArray<nsCString>&& aAppLocales)
2672
0
{
2673
0
  LocaleService::GetInstance()->AssignAppLocales(aAppLocales);
2674
0
  return IPC_OK();
2675
0
}
2676
2677
mozilla::ipc::IPCResult
2678
ContentChild::RecvUpdateRequestedLocales(nsTArray<nsCString>&& aRequestedLocales)
2679
0
{
2680
0
  LocaleService::GetInstance()->AssignRequestedLocales(aRequestedLocales);
2681
0
  return IPC_OK();
2682
0
}
2683
2684
mozilla::ipc::IPCResult
2685
ContentChild::RecvClearSiteDataReloadNeeded(const nsString& aOrigin)
2686
0
{
2687
0
  // Rebroadcast "clear-site-data-reload-needed".
2688
0
  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
2689
0
  if (obs) {
2690
0
    obs->NotifyObservers(nullptr, "clear-site-data-reload-needed",
2691
0
                         aOrigin.get());
2692
0
  }
2693
0
  return IPC_OK();
2694
0
}
2695
2696
mozilla::ipc::IPCResult
2697
ContentChild::RecvAddPermission(const IPC::Permission& permission)
2698
0
{
2699
0
  nsCOMPtr<nsIPermissionManager> permissionManagerIface =
2700
0
    services::GetPermissionManager();
2701
0
  nsPermissionManager* permissionManager =
2702
0
    static_cast<nsPermissionManager*>(permissionManagerIface.get());
2703
0
  MOZ_ASSERT(permissionManager,
2704
0
         "We have no permissionManager in the Content process !");
2705
0
2706
0
  // note we do not need to force mUserContextId to the default here because
2707
0
  // the permission manager does that internally.
2708
0
  nsAutoCString originNoSuffix;
2709
0
  OriginAttributes attrs;
2710
0
  bool success = attrs.PopulateFromOrigin(permission.origin, originNoSuffix);
2711
0
  NS_ENSURE_TRUE(success, IPC_FAIL_NO_REASON(this));
2712
0
2713
0
  nsCOMPtr<nsIURI> uri;
2714
0
  nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
2715
0
  NS_ENSURE_SUCCESS(rv, IPC_OK());
2716
0
2717
0
  nsCOMPtr<nsIPrincipal> principal = mozilla::BasePrincipal::CreateCodebasePrincipal(uri, attrs);
2718
0
2719
0
  // child processes don't care about modification time.
2720
0
  int64_t modificationTime = 0;
2721
0
2722
0
  permissionManager->AddInternal(principal,
2723
0
                                 nsCString(permission.type),
2724
0
                                 permission.capability,
2725
0
                                 0,
2726
0
                                 permission.expireType,
2727
0
                                 permission.expireTime,
2728
0
                                 modificationTime,
2729
0
                                 nsPermissionManager::eNotify,
2730
0
                                 nsPermissionManager::eNoDBOperation);
2731
0
2732
0
  return IPC_OK();
2733
0
}
2734
2735
mozilla::ipc::IPCResult
2736
ContentChild::RecvRemoveAllPermissions()
2737
0
{
2738
0
  nsCOMPtr<nsIPermissionManager> permissionManagerIface =
2739
0
    services::GetPermissionManager();
2740
0
  nsPermissionManager* permissionManager =
2741
0
    static_cast<nsPermissionManager*>(permissionManagerIface.get());
2742
0
  MOZ_ASSERT(permissionManager,
2743
0
         "We have no permissionManager in the Content process !");
2744
0
2745
0
  permissionManager->RemoveAllFromIPC();
2746
0
  return IPC_OK();
2747
0
}
2748
2749
mozilla::ipc::IPCResult
2750
ContentChild::RecvFlushMemory(const nsString& reason)
2751
0
{
2752
0
  nsCOMPtr<nsIObserverService> os =
2753
0
    mozilla::services::GetObserverService();
2754
0
  if (os) {
2755
0
    os->NotifyObservers(nullptr, "memory-pressure", reason.get());
2756
0
  }
2757
0
  return IPC_OK();
2758
0
}
2759
2760
mozilla::ipc::IPCResult
2761
ContentChild::RecvActivateA11y(const uint32_t& aMainChromeTid,
2762
                               const uint32_t& aMsaaID)
2763
0
{
2764
0
#ifdef ACCESSIBILITY
2765
#ifdef XP_WIN
2766
  MOZ_ASSERT(aMainChromeTid != 0);
2767
  mMainChromeTid = aMainChromeTid;
2768
2769
  MOZ_ASSERT(aMsaaID != 0);
2770
  mMsaaID = aMsaaID;
2771
#endif // XP_WIN
2772
2773
0
  // Start accessibility in content process if it's running in chrome
2774
0
  // process.
2775
0
  GetOrCreateAccService(nsAccessibilityService::eMainProcess);
2776
0
#endif // ACCESSIBILITY
2777
0
  return IPC_OK();
2778
0
}
2779
2780
mozilla::ipc::IPCResult
2781
ContentChild::RecvShutdownA11y()
2782
0
{
2783
0
#ifdef ACCESSIBILITY
2784
0
  // Try to shutdown accessibility in content process if it's shutting down in
2785
0
  // chrome process.
2786
0
  MaybeShutdownAccService(nsAccessibilityService::eMainProcess);
2787
0
#endif
2788
0
  return IPC_OK();
2789
0
}
2790
2791
mozilla::ipc::IPCResult
2792
ContentChild::RecvGarbageCollect()
2793
0
{
2794
0
  // Rebroadcast the "child-gc-request" so that workers will GC.
2795
0
  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
2796
0
  if (obs) {
2797
0
    obs->NotifyObservers(nullptr, "child-gc-request", nullptr);
2798
0
  }
2799
0
  nsJSContext::GarbageCollectNow(JS::gcreason::DOM_IPC);
2800
0
  return IPC_OK();
2801
0
}
2802
2803
mozilla::ipc::IPCResult
2804
ContentChild::RecvCycleCollect()
2805
0
{
2806
0
  // Rebroadcast the "child-cc-request" so that workers will CC.
2807
0
  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
2808
0
  if (obs) {
2809
0
    obs->NotifyObservers(nullptr, "child-cc-request", nullptr);
2810
0
  }
2811
0
  nsJSContext::CycleCollectNow();
2812
0
  return IPC_OK();
2813
0
}
2814
2815
mozilla::ipc::IPCResult
2816
ContentChild::RecvUnlinkGhosts()
2817
0
{
2818
#ifdef DEBUG
2819
  nsWindowMemoryReporter::UnlinkGhostWindows();
2820
#endif
2821
0
  return IPC_OK();
2822
0
}
2823
2824
mozilla::ipc::IPCResult
2825
ContentChild::RecvAppInfo(const nsCString& version, const nsCString& buildID,
2826
                          const nsCString& name, const nsCString& UAName,
2827
                          const nsCString& ID, const nsCString& vendor,
2828
                          const nsCString& sourceURL)
2829
0
{
2830
0
  mAppInfo.version.Assign(version);
2831
0
  mAppInfo.buildID.Assign(buildID);
2832
0
  mAppInfo.name.Assign(name);
2833
0
  mAppInfo.UAName.Assign(UAName);
2834
0
  mAppInfo.ID.Assign(ID);
2835
0
  mAppInfo.vendor.Assign(vendor);
2836
0
  mAppInfo.sourceURL.Assign(sourceURL);
2837
0
2838
0
  return IPC_OK();
2839
0
}
2840
2841
mozilla::ipc::IPCResult
2842
ContentChild::RecvRemoteType(const nsString& aRemoteType)
2843
0
{
2844
0
  MOZ_ASSERT(DOMStringIsNull(mRemoteType));
2845
0
2846
0
  mRemoteType.Assign(aRemoteType);
2847
0
2848
0
  // For non-default ("web") types, update the process name so about:memory's
2849
0
  // process names are more obvious.
2850
0
  if (aRemoteType.EqualsLiteral(FILE_REMOTE_TYPE)) {
2851
0
    SetProcessName(NS_LITERAL_STRING("file:// Content"));
2852
0
  } else if (aRemoteType.EqualsLiteral(EXTENSION_REMOTE_TYPE)) {
2853
0
    SetProcessName(NS_LITERAL_STRING("WebExtensions"));
2854
0
  } else if (aRemoteType.EqualsLiteral(PRIVILEGED_REMOTE_TYPE)) {
2855
0
    SetProcessName(NS_LITERAL_STRING("Privileged Content"));
2856
0
  } else if (aRemoteType.EqualsLiteral(LARGE_ALLOCATION_REMOTE_TYPE)) {
2857
0
    SetProcessName(NS_LITERAL_STRING("Large Allocation Web Content"));
2858
0
  }
2859
0
2860
0
  return IPC_OK();
2861
0
}
2862
2863
const nsAString&
2864
ContentChild::GetRemoteType() const
2865
0
{
2866
0
  return mRemoteType;
2867
0
}
2868
2869
mozilla::ipc::IPCResult
2870
ContentChild::RecvInitServiceWorkers(const ServiceWorkerConfiguration& aConfig)
2871
0
{
2872
0
  RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
2873
0
  if (!swm) {
2874
0
    // browser shutdown began
2875
0
    return IPC_OK();
2876
0
  }
2877
0
  swm->LoadRegistrations(aConfig.serviceWorkerRegistrations());
2878
0
  return IPC_OK();
2879
0
}
2880
2881
mozilla::ipc::IPCResult
2882
ContentChild::RecvInitBlobURLs(nsTArray<BlobURLRegistrationData>&& aRegistrations)
2883
0
{
2884
0
  for (uint32_t i = 0; i < aRegistrations.Length(); ++i) {
2885
0
    BlobURLRegistrationData& registration = aRegistrations[i];
2886
0
    RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(registration.blob());
2887
0
    MOZ_ASSERT(blobImpl);
2888
0
2889
0
    BlobURLProtocolHandler::AddDataEntry(registration.url(),
2890
0
                                         registration.principal(),
2891
0
                                         blobImpl);
2892
0
    // If we have received an already-revoked blobURL, we have to keep it alive
2893
0
    // for a while (see BlobURLProtocolHandler) in order to support pending
2894
0
    // operations such as navigation, download and so on.
2895
0
    if (registration.revoked()) {
2896
0
      BlobURLProtocolHandler::RemoveDataEntry(registration.url(), false);
2897
0
    }
2898
0
  }
2899
0
2900
0
  return IPC_OK();
2901
0
}
2902
2903
mozilla::ipc::IPCResult
2904
ContentChild::RecvLastPrivateDocShellDestroyed()
2905
0
{
2906
0
  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
2907
0
  obs->NotifyObservers(nullptr, "last-pb-context-exited", nullptr);
2908
0
  return IPC_OK();
2909
0
}
2910
2911
mozilla::ipc::IPCResult
2912
ContentChild::RecvNotifyProcessPriorityChanged(
2913
  const hal::ProcessPriority& aPriority)
2914
0
{
2915
0
  nsCOMPtr<nsIObserverService> os = services::GetObserverService();
2916
0
  NS_ENSURE_TRUE(os, IPC_OK());
2917
0
2918
0
  RefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
2919
0
  props->SetPropertyAsInt32(NS_LITERAL_STRING("priority"),
2920
0
                            static_cast<int32_t>(aPriority));
2921
0
2922
0
  os->NotifyObservers(static_cast<nsIPropertyBag2*>(props),
2923
0
                      "ipc:process-priority-changed",  nullptr);
2924
0
  return IPC_OK();
2925
0
}
2926
2927
mozilla::ipc::IPCResult
2928
ContentChild::RecvMinimizeMemoryUsage()
2929
0
{
2930
0
  nsCOMPtr<nsIMemoryReporterManager> mgr =
2931
0
    do_GetService("@mozilla.org/memory-reporter-manager;1");
2932
0
  NS_ENSURE_TRUE(mgr, IPC_OK());
2933
0
2934
0
  Unused << mgr->MinimizeMemoryUsage(/* callback = */ nullptr);
2935
0
  return IPC_OK();
2936
0
}
2937
2938
void
2939
ContentChild::AddIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS)
2940
0
{
2941
0
  MOZ_ASSERT(aObserver, "null idle observer");
2942
0
  // Make sure aObserver isn't released while we wait for the parent
2943
0
  aObserver->AddRef();
2944
0
  SendAddIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS);
2945
0
  mIdleObservers.PutEntry(aObserver);
2946
0
}
2947
2948
void
2949
ContentChild::RemoveIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS)
2950
0
{
2951
0
  MOZ_ASSERT(aObserver, "null idle observer");
2952
0
  SendRemoveIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS);
2953
0
  aObserver->Release();
2954
0
  mIdleObservers.RemoveEntry(aObserver);
2955
0
}
2956
2957
mozilla::ipc::IPCResult
2958
ContentChild::RecvNotifyIdleObserver(const uint64_t& aObserver,
2959
                                     const nsCString& aTopic,
2960
                                     const nsString& aTimeStr)
2961
0
{
2962
0
  nsIObserver* observer = reinterpret_cast<nsIObserver*>(aObserver);
2963
0
  if (mIdleObservers.Contains(observer)) {
2964
0
    observer->Observe(nullptr, aTopic.get(), aTimeStr.get());
2965
0
  } else {
2966
0
    NS_WARNING("Received notification for an idle observer that was removed.");
2967
0
  }
2968
0
  return IPC_OK();
2969
0
}
2970
2971
mozilla::ipc::IPCResult
2972
ContentChild::RecvLoadAndRegisterSheet(const URIParams& aURI, const uint32_t& aType)
2973
0
{
2974
0
  nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
2975
0
  if (!uri) {
2976
0
    return IPC_OK();
2977
0
  }
2978
0
2979
0
  nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
2980
0
  if (sheetService) {
2981
0
    sheetService->LoadAndRegisterSheet(uri, aType);
2982
0
  }
2983
0
2984
0
  return IPC_OK();
2985
0
}
2986
2987
mozilla::ipc::IPCResult
2988
ContentChild::RecvUnregisterSheet(const URIParams& aURI, const uint32_t& aType)
2989
0
{
2990
0
  nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
2991
0
  if (!uri) {
2992
0
    return IPC_OK();
2993
0
  }
2994
0
2995
0
  nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
2996
0
  if (sheetService) {
2997
0
    sheetService->UnregisterSheet(uri, aType);
2998
0
  }
2999
0
3000
0
  return IPC_OK();
3001
0
}
3002
3003
POfflineCacheUpdateChild*
3004
ContentChild::AllocPOfflineCacheUpdateChild(const URIParams& manifestURI,
3005
                                            const URIParams& documentURI,
3006
                                            const PrincipalInfo& aLoadingPrincipalInfo,
3007
                                            const bool& stickDocument)
3008
0
{
3009
0
  MOZ_CRASH("unused");
3010
0
  return nullptr;
3011
0
}
3012
3013
bool
3014
ContentChild::DeallocPOfflineCacheUpdateChild(POfflineCacheUpdateChild* actor)
3015
0
{
3016
0
  OfflineCacheUpdateChild* offlineCacheUpdate =
3017
0
    static_cast<OfflineCacheUpdateChild*>(actor);
3018
0
  NS_RELEASE(offlineCacheUpdate);
3019
0
  return true;
3020
0
}
3021
3022
mozilla::ipc::IPCResult
3023
ContentChild::RecvDomainSetChanged(const uint32_t& aSetType,
3024
                                   const uint32_t& aChangeType,
3025
                                   const OptionalURIParams& aDomain)
3026
0
{
3027
0
  if (aChangeType == ACTIVATE_POLICY) {
3028
0
    if (mPolicy) {
3029
0
      return IPC_OK();
3030
0
    }
3031
0
    nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
3032
0
    MOZ_ASSERT(ssm);
3033
0
    ssm->ActivateDomainPolicyInternal(getter_AddRefs(mPolicy));
3034
0
    if (!mPolicy) {
3035
0
      return IPC_FAIL_NO_REASON(this);
3036
0
    }
3037
0
    return IPC_OK();
3038
0
  }
3039
0
  if (!mPolicy) {
3040
0
    MOZ_ASSERT_UNREACHABLE("If the domain policy is not active yet,"
3041
0
                           " the first message should be ACTIVATE_POLICY");
3042
0
    return IPC_FAIL_NO_REASON(this);
3043
0
  }
3044
0
3045
0
  NS_ENSURE_TRUE(mPolicy, IPC_FAIL_NO_REASON(this));
3046
0
3047
0
  if (aChangeType == DEACTIVATE_POLICY) {
3048
0
    mPolicy->Deactivate();
3049
0
    mPolicy = nullptr;
3050
0
    return IPC_OK();
3051
0
  }
3052
0
3053
0
  nsCOMPtr<nsIDomainSet> set;
3054
0
  switch(aSetType) {
3055
0
    case BLACKLIST:
3056
0
      mPolicy->GetBlacklist(getter_AddRefs(set));
3057
0
      break;
3058
0
    case SUPER_BLACKLIST:
3059
0
      mPolicy->GetSuperBlacklist(getter_AddRefs(set));
3060
0
      break;
3061
0
    case WHITELIST:
3062
0
      mPolicy->GetWhitelist(getter_AddRefs(set));
3063
0
      break;
3064
0
    case SUPER_WHITELIST:
3065
0
      mPolicy->GetSuperWhitelist(getter_AddRefs(set));
3066
0
      break;
3067
0
    default:
3068
0
      MOZ_ASSERT_UNREACHABLE("Unexpected setType");
3069
0
      return IPC_FAIL_NO_REASON(this);
3070
0
  }
3071
0
3072
0
  MOZ_ASSERT(set);
3073
0
3074
0
  nsCOMPtr<nsIURI> uri = DeserializeURI(aDomain);
3075
0
3076
0
  switch(aChangeType) {
3077
0
    case ADD_DOMAIN:
3078
0
      NS_ENSURE_TRUE(uri, IPC_FAIL_NO_REASON(this));
3079
0
      set->Add(uri);
3080
0
      break;
3081
0
    case REMOVE_DOMAIN:
3082
0
      NS_ENSURE_TRUE(uri, IPC_FAIL_NO_REASON(this));
3083
0
      set->Remove(uri);
3084
0
      break;
3085
0
    case CLEAR_DOMAINS:
3086
0
      set->Clear();
3087
0
      break;
3088
0
    default:
3089
0
      MOZ_ASSERT_UNREACHABLE("Unexpected changeType");
3090
0
      return IPC_FAIL_NO_REASON(this);
3091
0
  }
3092
0
3093
0
  return IPC_OK();
3094
0
}
3095
3096
void
3097
ContentChild::StartForceKillTimer()
3098
0
{
3099
0
  if (mForceKillTimer) {
3100
0
    return;
3101
0
  }
3102
0
3103
0
  int32_t timeoutSecs = Preferences::GetInt("dom.ipc.tabs.shutdownTimeoutSecs", 5);
3104
0
  if (timeoutSecs > 0) {
3105
0
    NS_NewTimerWithFuncCallback(getter_AddRefs(mForceKillTimer),
3106
0
                                ContentChild::ForceKillTimerCallback,
3107
0
                                this,
3108
0
                                timeoutSecs * 1000,
3109
0
                                nsITimer::TYPE_ONE_SHOT,
3110
0
                                "dom::ContentChild::StartForceKillTimer");
3111
0
    MOZ_ASSERT(mForceKillTimer);
3112
0
  }
3113
0
}
3114
3115
/* static */ void
3116
ContentChild::ForceKillTimerCallback(nsITimer* aTimer, void* aClosure)
3117
0
{
3118
0
  ProcessChild::QuickExit();
3119
0
}
3120
3121
mozilla::ipc::IPCResult
3122
ContentChild::RecvShutdown()
3123
0
{
3124
0
  nsCOMPtr<nsIObserverService> os = services::GetObserverService();
3125
0
  if (os) {
3126
0
    os->NotifyObservers(static_cast<nsIContentChild*>(this),
3127
0
                          "content-child-will-shutdown", nullptr);
3128
0
  }
3129
0
3130
0
  ShutdownInternal();
3131
0
  return IPC_OK();
3132
0
}
3133
3134
void
3135
ContentChild::ShutdownInternal()
3136
0
{
3137
0
  // If we receive the shutdown message from within a nested event loop, we want
3138
0
  // to wait for that event loop to finish. Otherwise we could prematurely
3139
0
  // terminate an "unload" or "pagehide" event handler (which might be doing a
3140
0
  // sync XHR, for example).
3141
0
  CrashReporter::AnnotateCrashReport(
3142
0
    CrashReporter::Annotation::IPCShutdownState,
3143
0
    NS_LITERAL_CSTRING("RecvShutdown"));
3144
0
3145
0
  MOZ_ASSERT(NS_IsMainThread());
3146
0
  RefPtr<nsThread> mainThread = nsThreadManager::get().GetCurrentThread();
3147
0
  // Note that we only have to check the recursion count for the current
3148
0
  // cooperative thread. Since the Shutdown message is not labeled with a
3149
0
  // SchedulerGroup, there can be no other cooperative threads doing work while
3150
0
  // we're running.
3151
0
  if (mainThread && mainThread->RecursionDepth() > 1) {
3152
0
    // We're in a nested event loop. Let's delay for an arbitrary period of
3153
0
    // time (100ms) in the hopes that the event loop will have finished by
3154
0
    // then.
3155
0
    MessageLoop::current()->PostDelayedTask(
3156
0
      NewRunnableMethod(
3157
0
        "dom::ContentChild::RecvShutdown", this,
3158
0
        &ContentChild::ShutdownInternal),
3159
0
      100);
3160
0
    return;
3161
0
  }
3162
0
3163
0
  mShuttingDown = true;
3164
0
3165
0
#ifdef NIGHTLY_BUILD
3166
0
  BackgroundHangMonitor::UnregisterAnnotator(PendingInputEventHangAnnotator::sSingleton);
3167
0
#endif
3168
0
3169
0
  if (mPolicy) {
3170
0
    mPolicy->Deactivate();
3171
0
    mPolicy = nullptr;
3172
0
  }
3173
0
3174
0
  nsCOMPtr<nsIObserverService> os = services::GetObserverService();
3175
0
  if (os) {
3176
0
    os->NotifyObservers(static_cast<nsIContentChild*>(this),
3177
0
                          "content-child-shutdown", nullptr);
3178
0
  }
3179
0
3180
#if defined(XP_WIN)
3181
    mozilla::widget::StopAudioSession();
3182
#endif
3183
3184
0
  GetIPCChannel()->SetAbortOnError(false);
3185
0
3186
0
#ifdef MOZ_GECKO_PROFILER
3187
0
  if (mProfilerController) {
3188
0
    nsCString shutdownProfile = mProfilerController->GrabShutdownProfileAndShutdown();
3189
0
    mProfilerController = nullptr;
3190
0
    // Send the shutdown profile to the parent process through our own
3191
0
    // message channel, which we know will survive for long enough.
3192
0
    Unused << SendShutdownProfile(shutdownProfile);
3193
0
  }
3194
0
#endif
3195
0
3196
0
  // Start a timer that will insure we quickly exit after a reasonable
3197
0
  // period of time. Prevents shutdown hangs after our connection to the
3198
0
  // parent closes.
3199
0
  StartForceKillTimer();
3200
0
3201
0
  CrashReporter::AnnotateCrashReport(
3202
0
    CrashReporter::Annotation::IPCShutdownState,
3203
0
    NS_LITERAL_CSTRING("SendFinishShutdown (sending)"));
3204
0
  bool sent = SendFinishShutdown();
3205
0
  CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::IPCShutdownState,
3206
0
                                     sent ? NS_LITERAL_CSTRING("SendFinishShutdown (sent)")
3207
0
                                          : NS_LITERAL_CSTRING("SendFinishShutdown (failed)"));
3208
0
}
3209
3210
PBrowserOrId
3211
ContentChild::GetBrowserOrId(TabChild* aTabChild)
3212
0
{
3213
0
  if (!aTabChild ||
3214
0
    this == aTabChild->Manager()) {
3215
0
    return PBrowserOrId(aTabChild);
3216
0
  }
3217
0
  return PBrowserOrId(aTabChild->GetTabId());
3218
0
}
3219
3220
mozilla::ipc::IPCResult
3221
ContentChild::RecvUpdateWindow(const uintptr_t& aChildId)
3222
0
{
3223
#if defined(XP_WIN)
3224
  NS_ASSERTION(aChildId, "Expected child hwnd value for remote plugin instance.");
3225
  mozilla::plugins::PluginInstanceParent* parentInstance =
3226
  mozilla::plugins::PluginInstanceParent::LookupPluginInstanceByID(aChildId);
3227
  if (parentInstance) {
3228
    // sync! update call to the plugin instance that forces the
3229
    // plugin to paint its child window.
3230
    if(!parentInstance->CallUpdateWindow()) {
3231
      return IPC_FAIL_NO_REASON(this);
3232
    }
3233
  }
3234
  return IPC_OK();
3235
#else
3236
0
  MOZ_ASSERT(false, "ContentChild::RecvUpdateWindow calls unexpected on this platform.");
3237
0
  return IPC_FAIL_NO_REASON(this);
3238
0
#endif
3239
0
}
3240
3241
PContentPermissionRequestChild*
3242
ContentChild::AllocPContentPermissionRequestChild(const InfallibleTArray<PermissionRequest>& aRequests,
3243
                                                  const IPC::Principal& aPrincipal,
3244
                                                  const bool& aIsHandlingUserInput,
3245
                                                  const TabId& aTabId)
3246
0
{
3247
0
  MOZ_CRASH("unused");
3248
0
  return nullptr;
3249
0
}
3250
3251
bool
3252
ContentChild::DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor)
3253
0
{
3254
0
  nsContentPermissionUtils::NotifyRemoveContentPermissionRequestChild(actor);
3255
0
  auto child = static_cast<RemotePermissionRequest*>(actor);
3256
0
  child->IPDLRelease();
3257
0
  return true;
3258
0
}
3259
3260
PWebBrowserPersistDocumentChild*
3261
ContentChild::AllocPWebBrowserPersistDocumentChild(PBrowserChild* aBrowser,
3262
                                                   const uint64_t& aOuterWindowID)
3263
0
{
3264
0
  return new WebBrowserPersistDocumentChild();
3265
0
}
3266
3267
mozilla::ipc::IPCResult
3268
ContentChild::RecvPWebBrowserPersistDocumentConstructor(PWebBrowserPersistDocumentChild *aActor,
3269
                                                        PBrowserChild* aBrowser,
3270
                                                        const uint64_t& aOuterWindowID)
3271
0
{
3272
0
  if (NS_WARN_IF(!aBrowser)) {
3273
0
    return IPC_FAIL_NO_REASON(this);
3274
0
  }
3275
0
  nsCOMPtr<nsIDocument> rootDoc =
3276
0
    static_cast<TabChild*>(aBrowser)->GetDocument();
3277
0
  nsCOMPtr<nsIDocument> foundDoc;
3278
0
  if (aOuterWindowID) {
3279
0
    foundDoc = nsContentUtils::GetSubdocumentWithOuterWindowId(rootDoc, aOuterWindowID);
3280
0
  } else {
3281
0
    foundDoc = rootDoc;
3282
0
  }
3283
0
3284
0
  if (!foundDoc) {
3285
0
    aActor->SendInitFailure(NS_ERROR_NO_CONTENT);
3286
0
  } else {
3287
0
    static_cast<WebBrowserPersistDocumentChild*>(aActor)->Start(foundDoc);
3288
0
  }
3289
0
  return IPC_OK();
3290
0
}
3291
3292
bool
3293
ContentChild::DeallocPWebBrowserPersistDocumentChild(PWebBrowserPersistDocumentChild* aActor)
3294
0
{
3295
0
  delete aActor;
3296
0
  return true;
3297
0
}
3298
3299
mozilla::ipc::IPCResult
3300
ContentChild::RecvSetAudioSessionData(const nsID& aId,
3301
                                      const nsString& aDisplayName,
3302
                                      const nsString& aIconPath)
3303
0
{
3304
#if defined(XP_WIN)
3305
    if (NS_FAILED(mozilla::widget::RecvAudioSessionData(aId, aDisplayName,
3306
                                                        aIconPath))) {
3307
      return IPC_OK();
3308
    }
3309
3310
    // Ignore failures here; we can't really do anything about them
3311
    mozilla::widget::StartAudioSession();
3312
    return IPC_OK();
3313
#else
3314
0
    MOZ_CRASH("Not Reached!");
3315
0
#endif
3316
0
}
3317
3318
// This code goes here rather than nsGlobalWindow.cpp because nsGlobalWindow.cpp
3319
// can't include ContentChild.h since it includes windows.h.
3320
3321
static uint64_t gNextWindowID = 0;
3322
3323
// We use only 53 bits for the window ID so that it can be converted to and from
3324
// a JS value without loss of precision. The upper bits of the window ID hold the
3325
// process ID. The lower bits identify the window.
3326
static const uint64_t kWindowIDTotalBits = 53;
3327
static const uint64_t kWindowIDProcessBits = 22;
3328
static const uint64_t kWindowIDWindowBits = kWindowIDTotalBits - kWindowIDProcessBits;
3329
3330
// Try to return a window ID that is unique across processes and that will never
3331
// be recycled.
3332
uint64_t
3333
NextWindowID()
3334
0
{
3335
0
  uint64_t processID = 0;
3336
0
  if (XRE_IsContentProcess()) {
3337
0
    ContentChild* cc = ContentChild::GetSingleton();
3338
0
    processID = cc->GetID();
3339
0
  }
3340
0
3341
0
  MOZ_RELEASE_ASSERT(processID < (uint64_t(1) << kWindowIDProcessBits));
3342
0
  uint64_t processBits = processID & ((uint64_t(1) << kWindowIDProcessBits) - 1);
3343
0
3344
0
  // Make sure no actual window ends up with mWindowID == 0.
3345
0
  uint64_t windowID = ++gNextWindowID;
3346
0
3347
0
  MOZ_RELEASE_ASSERT(windowID < (uint64_t(1) << kWindowIDWindowBits));
3348
0
  uint64_t windowBits = windowID & ((uint64_t(1) << kWindowIDWindowBits) - 1);
3349
0
3350
0
  return (processBits << kWindowIDWindowBits) | windowBits;
3351
0
}
3352
3353
mozilla::ipc::IPCResult
3354
ContentChild::RecvInvokeDragSession(nsTArray<IPCDataTransfer>&& aTransfers,
3355
                                    const uint32_t& aAction)
3356
0
{
3357
0
  nsCOMPtr<nsIDragService> dragService =
3358
0
    do_GetService("@mozilla.org/widget/dragservice;1");
3359
0
  if (dragService) {
3360
0
    dragService->StartDragSession();
3361
0
    nsCOMPtr<nsIDragSession> session;
3362
0
    dragService->GetCurrentSession(getter_AddRefs(session));
3363
0
    if (session) {
3364
0
      session->SetDragAction(aAction);
3365
0
      // Check if we are receiving any file objects. If we are we will want
3366
0
      // to hide any of the other objects coming in from content.
3367
0
      bool hasFiles = false;
3368
0
      for (uint32_t i = 0; i < aTransfers.Length() && !hasFiles; ++i) {
3369
0
        auto& items = aTransfers[i].items();
3370
0
        for (uint32_t j = 0; j < items.Length() && !hasFiles; ++j) {
3371
0
          if (items[j].data().type() == IPCDataTransferData::TIPCBlob) {
3372
0
            hasFiles = true;
3373
0
          }
3374
0
        }
3375
0
      }
3376
0
3377
0
      // Add the entries from the IPC to the new DataTransfer
3378
0
      nsCOMPtr<DataTransfer> dataTransfer =
3379
0
        new DataTransfer(nullptr, eDragStart, false, -1);
3380
0
      for (uint32_t i = 0; i < aTransfers.Length(); ++i) {
3381
0
        auto& items = aTransfers[i].items();
3382
0
        for (uint32_t j = 0; j < items.Length(); ++j) {
3383
0
          const IPCDataTransferItem& item = items[j];
3384
0
          RefPtr<nsVariantCC> variant = new nsVariantCC();
3385
0
          if (item.data().type() == IPCDataTransferData::TnsString) {
3386
0
            const nsString& data = item.data().get_nsString();
3387
0
            variant->SetAsAString(data);
3388
0
          } else if (item.data().type() == IPCDataTransferData::TShmem) {
3389
0
            Shmem data = item.data().get_Shmem();
3390
0
            variant->SetAsACString(nsDependentCSubstring(data.get<char>(), data.Size<char>()));
3391
0
            Unused << DeallocShmem(data);
3392
0
          } else if (item.data().type() == IPCDataTransferData::TIPCBlob) {
3393
0
            RefPtr<BlobImpl> blobImpl =
3394
0
              IPCBlobUtils::Deserialize(item.data().get_IPCBlob());
3395
0
            variant->SetAsISupports(blobImpl);
3396
0
          } else {
3397
0
            continue;
3398
0
          }
3399
0
          // We should hide this data from content if we have a file, and we aren't a file.
3400
0
          bool hidden = hasFiles && item.data().type() != IPCDataTransferData::TIPCBlob;
3401
0
          dataTransfer->SetDataWithPrincipalFromOtherProcess(
3402
0
            NS_ConvertUTF8toUTF16(item.flavor()), variant, i,
3403
0
            nsContentUtils::GetSystemPrincipal(), hidden);
3404
0
        }
3405
0
      }
3406
0
      session->SetDataTransfer(dataTransfer);
3407
0
    }
3408
0
  }
3409
0
  return IPC_OK();
3410
0
}
3411
3412
mozilla::ipc::IPCResult
3413
ContentChild::RecvEndDragSession(const bool& aDoneDrag,
3414
                                 const bool& aUserCancelled,
3415
                                 const LayoutDeviceIntPoint& aDragEndPoint,
3416
                                 const uint32_t& aKeyModifiers)
3417
0
{
3418
0
  nsCOMPtr<nsIDragService> dragService =
3419
0
    do_GetService("@mozilla.org/widget/dragservice;1");
3420
0
  if (dragService) {
3421
0
    if (aUserCancelled) {
3422
0
      nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
3423
0
      if (dragSession) {
3424
0
        dragSession->UserCancelled();
3425
0
      }
3426
0
    }
3427
0
    static_cast<nsBaseDragService*>(dragService.get())->SetDragEndPoint(aDragEndPoint);
3428
0
    dragService->EndDragSession(aDoneDrag, aKeyModifiers);
3429
0
  }
3430
0
  return IPC_OK();
3431
0
}
3432
3433
mozilla::ipc::IPCResult
3434
ContentChild::RecvPush(const nsCString& aScope,
3435
                       const IPC::Principal& aPrincipal,
3436
                       const nsString& aMessageId)
3437
0
{
3438
0
  PushMessageDispatcher dispatcher(aScope, aPrincipal, aMessageId, Nothing());
3439
0
  Unused << NS_WARN_IF(NS_FAILED(dispatcher.NotifyObserversAndWorkers()));
3440
0
  return IPC_OK();
3441
0
}
3442
3443
mozilla::ipc::IPCResult
3444
ContentChild::RecvPushWithData(const nsCString& aScope,
3445
                               const IPC::Principal& aPrincipal,
3446
                               const nsString& aMessageId,
3447
                               InfallibleTArray<uint8_t>&& aData)
3448
0
{
3449
0
  PushMessageDispatcher dispatcher(aScope, aPrincipal, aMessageId, Some(aData));
3450
0
  Unused << NS_WARN_IF(NS_FAILED(dispatcher.NotifyObserversAndWorkers()));
3451
0
  return IPC_OK();
3452
0
}
3453
3454
mozilla::ipc::IPCResult
3455
ContentChild::RecvPushSubscriptionChange(const nsCString& aScope,
3456
                                         const IPC::Principal& aPrincipal)
3457
0
{
3458
0
  PushSubscriptionChangeDispatcher dispatcher(aScope, aPrincipal);
3459
0
  Unused << NS_WARN_IF(NS_FAILED(dispatcher.NotifyObserversAndWorkers()));
3460
0
  return IPC_OK();
3461
0
}
3462
3463
mozilla::ipc::IPCResult
3464
ContentChild::RecvPushError(const nsCString& aScope, const IPC::Principal& aPrincipal,
3465
                            const nsString& aMessage, const uint32_t& aFlags)
3466
0
{
3467
0
  PushErrorDispatcher dispatcher(aScope, aPrincipal, aMessage, aFlags);
3468
0
  Unused << NS_WARN_IF(NS_FAILED(dispatcher.NotifyObserversAndWorkers()));
3469
0
  return IPC_OK();
3470
0
}
3471
3472
mozilla::ipc::IPCResult
3473
ContentChild::RecvNotifyPushSubscriptionModifiedObservers(const nsCString& aScope,
3474
                                                          const IPC::Principal& aPrincipal)
3475
0
{
3476
0
  PushSubscriptionModifiedDispatcher dispatcher(aScope, aPrincipal);
3477
0
  Unused << NS_WARN_IF(NS_FAILED(dispatcher.NotifyObservers()));
3478
0
  return IPC_OK();
3479
0
}
3480
3481
mozilla::ipc::IPCResult
3482
ContentChild::RecvBlobURLRegistration(const nsCString& aURI,
3483
                                      const IPCBlob& aBlob,
3484
                                      const IPC::Principal& aPrincipal)
3485
0
{
3486
0
  RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(aBlob);
3487
0
  MOZ_ASSERT(blobImpl);
3488
0
3489
0
  BlobURLProtocolHandler::AddDataEntry(aURI, aPrincipal, blobImpl);
3490
0
  return IPC_OK();
3491
0
}
3492
3493
mozilla::ipc::IPCResult
3494
ContentChild::RecvBlobURLUnregistration(const nsCString& aURI)
3495
0
{
3496
0
  BlobURLProtocolHandler::RemoveDataEntry(aURI,
3497
0
                                          /* aBroadcastToOtherProcesses = */ false);
3498
0
  return IPC_OK();
3499
0
}
3500
3501
#if defined(XP_WIN) && defined(ACCESSIBILITY)
3502
bool
3503
ContentChild::SendGetA11yContentId()
3504
{
3505
  return PContentChild::SendGetA11yContentId(&mMsaaID);
3506
}
3507
#endif // defined(XP_WIN) && defined(ACCESSIBILITY)
3508
3509
void
3510
ContentChild::CreateGetFilesRequest(const nsAString& aDirectoryPath,
3511
                                    bool aRecursiveFlag,
3512
                                    nsID& aUUID,
3513
                                    GetFilesHelperChild* aChild)
3514
0
{
3515
0
  MOZ_ASSERT(aChild);
3516
0
  MOZ_ASSERT(!mGetFilesPendingRequests.GetWeak(aUUID));
3517
0
3518
0
  Unused << SendGetFilesRequest(aUUID, nsString(aDirectoryPath),
3519
0
                                aRecursiveFlag);
3520
0
  mGetFilesPendingRequests.Put(aUUID, aChild);
3521
0
}
3522
3523
void
3524
ContentChild::DeleteGetFilesRequest(nsID& aUUID, GetFilesHelperChild* aChild)
3525
0
{
3526
0
  MOZ_ASSERT(aChild);
3527
0
  MOZ_ASSERT(mGetFilesPendingRequests.GetWeak(aUUID));
3528
0
3529
0
  Unused << SendDeleteGetFilesRequest(aUUID);
3530
0
  mGetFilesPendingRequests.Remove(aUUID);
3531
0
}
3532
3533
mozilla::ipc::IPCResult
3534
ContentChild::RecvGetFilesResponse(const nsID& aUUID,
3535
                                   const GetFilesResponseResult& aResult)
3536
0
{
3537
0
  GetFilesHelperChild* child = mGetFilesPendingRequests.GetWeak(aUUID);
3538
0
  // This object can already been deleted in case DeleteGetFilesRequest has
3539
0
  // been called when the response was sending by the parent.
3540
0
  if (!child) {
3541
0
    return IPC_OK();
3542
0
  }
3543
0
3544
0
  if (aResult.type() == GetFilesResponseResult::TGetFilesResponseFailure) {
3545
0
    child->Finished(aResult.get_GetFilesResponseFailure().errorCode());
3546
0
  } else {
3547
0
    MOZ_ASSERT(aResult.type() == GetFilesResponseResult::TGetFilesResponseSuccess);
3548
0
3549
0
    const nsTArray<IPCBlob>& ipcBlobs =
3550
0
      aResult.get_GetFilesResponseSuccess().blobs();
3551
0
3552
0
    bool succeeded = true;
3553
0
    for (uint32_t i = 0; succeeded && i < ipcBlobs.Length(); ++i) {
3554
0
      RefPtr<BlobImpl> impl = IPCBlobUtils::Deserialize(ipcBlobs[i]);
3555
0
      succeeded = child->AppendBlobImpl(impl);
3556
0
    }
3557
0
3558
0
    child->Finished(succeeded ? NS_OK : NS_ERROR_OUT_OF_MEMORY);
3559
0
  }
3560
0
3561
0
  mGetFilesPendingRequests.Remove(aUUID);
3562
0
  return IPC_OK();
3563
0
}
3564
3565
/* static */ void
3566
ContentChild::FatalErrorIfNotUsingGPUProcess(const char* const aErrorMsg,
3567
                                             base::ProcessId aOtherPid)
3568
0
{
3569
0
  // If we're communicating with the same process or the UI process then we
3570
0
  // want to crash normally. Otherwise we want to just warn as the other end
3571
0
  // must be the GPU process and it crashing shouldn't be fatal for us.
3572
0
  if (aOtherPid == base::GetCurrentProcId() ||
3573
0
      (GetSingleton() && GetSingleton()->OtherPid() == aOtherPid)) {
3574
0
    mozilla::ipc::FatalError(aErrorMsg, false);
3575
0
  } else {
3576
0
    nsAutoCString formattedMessage("IPDL error: \"");
3577
0
    formattedMessage.AppendASCII(aErrorMsg);
3578
0
    formattedMessage.AppendLiteral(R"(".)");
3579
0
    NS_WARNING(formattedMessage.get());
3580
0
  }
3581
0
}
3582
3583
PURLClassifierChild*
3584
ContentChild::AllocPURLClassifierChild(const Principal& aPrincipal,
3585
                                       const bool& aUseTrackingProtection,
3586
                                       bool* aSuccess)
3587
0
{
3588
0
  *aSuccess = true;
3589
0
  return new URLClassifierChild();
3590
0
}
3591
3592
bool
3593
ContentChild::DeallocPURLClassifierChild(PURLClassifierChild* aActor)
3594
0
{
3595
0
  MOZ_ASSERT(aActor);
3596
0
  delete aActor;
3597
0
  return true;
3598
0
}
3599
3600
PURLClassifierLocalChild*
3601
ContentChild::AllocPURLClassifierLocalChild(const URIParams& aUri,
3602
                                            const nsCString& aTables)
3603
0
{
3604
0
  return new URLClassifierLocalChild();
3605
0
}
3606
3607
bool
3608
ContentChild::DeallocPURLClassifierLocalChild(PURLClassifierLocalChild* aActor)
3609
0
{
3610
0
  MOZ_ASSERT(aActor);
3611
0
  delete aActor;
3612
0
  return true;
3613
0
}
3614
3615
PLoginReputationChild*
3616
ContentChild::AllocPLoginReputationChild(const URIParams& aUri)
3617
0
{
3618
0
  return new PLoginReputationChild();
3619
0
}
3620
3621
bool
3622
ContentChild::DeallocPLoginReputationChild(PLoginReputationChild* aActor)
3623
0
{
3624
0
  MOZ_ASSERT(aActor);
3625
0
  delete aActor;
3626
0
  return true;
3627
0
}
3628
3629
// The IPC code will call this method asking us to assign an event target to new
3630
// actors created by the ContentParent.
3631
already_AddRefed<nsIEventTarget>
3632
ContentChild::GetConstructedEventTarget(const Message& aMsg)
3633
0
{
3634
0
  // Currently we only set targets for PBrowser.
3635
0
  if (aMsg.type() != PContent::Msg_PBrowserConstructor__ID) {
3636
0
    return nullptr;
3637
0
  }
3638
0
3639
0
  return nsIContentChild::GetConstructedEventTarget(aMsg);
3640
0
}
3641
3642
void
3643
ContentChild::FileCreationRequest(nsID& aUUID, FileCreatorHelper* aHelper,
3644
                                  const nsAString& aFullPath,
3645
                                  const nsAString& aType,
3646
                                  const nsAString& aName,
3647
                                  const Optional<int64_t>& aLastModified,
3648
                                  bool aExistenceCheck,
3649
                                  bool aIsFromNsIFile)
3650
0
{
3651
0
  MOZ_ASSERT(aHelper);
3652
0
3653
0
  bool lastModifiedPassed = false;
3654
0
  int64_t lastModified = 0;
3655
0
  if (aLastModified.WasPassed()) {
3656
0
    lastModifiedPassed = true;
3657
0
    lastModified = aLastModified.Value();
3658
0
  }
3659
0
3660
0
  Unused << SendFileCreationRequest(aUUID, nsString(aFullPath), nsString(aType),
3661
0
                                    nsString(aName), lastModifiedPassed,
3662
0
                                    lastModified, aExistenceCheck,
3663
0
                                    aIsFromNsIFile);
3664
0
  mFileCreationPending.Put(aUUID, aHelper);
3665
0
}
3666
3667
mozilla::ipc::IPCResult
3668
ContentChild::RecvFileCreationResponse(const nsID& aUUID,
3669
                                       const FileCreationResult& aResult)
3670
0
{
3671
0
  FileCreatorHelper* helper = mFileCreationPending.GetWeak(aUUID);
3672
0
  if (!helper) {
3673
0
    return IPC_FAIL_NO_REASON(this);
3674
0
  }
3675
0
3676
0
  if (aResult.type() == FileCreationResult::TFileCreationErrorResult) {
3677
0
    helper->ResponseReceived(nullptr,
3678
0
                             aResult.get_FileCreationErrorResult().errorCode());
3679
0
  } else {
3680
0
    MOZ_ASSERT(aResult.type() == FileCreationResult::TFileCreationSuccessResult);
3681
0
3682
0
    RefPtr<BlobImpl> impl =
3683
0
      IPCBlobUtils::Deserialize(aResult.get_FileCreationSuccessResult().blob());
3684
0
    helper->ResponseReceived(impl, NS_OK);
3685
0
  }
3686
0
3687
0
  mFileCreationPending.Remove(aUUID);
3688
0
  return IPC_OK();
3689
0
}
3690
3691
mozilla::ipc::IPCResult
3692
ContentChild::RecvActivate(PBrowserChild* aTab)
3693
0
{
3694
0
  TabChild* tab = static_cast<TabChild*>(aTab);
3695
0
  return tab->RecvActivate();
3696
0
}
3697
3698
mozilla::ipc::IPCResult
3699
ContentChild::RecvDeactivate(PBrowserChild* aTab)
3700
0
{
3701
0
  TabChild* tab = static_cast<TabChild*>(aTab);
3702
0
  return tab->RecvDeactivate();
3703
0
}
3704
3705
mozilla::ipc::IPCResult
3706
ContentChild::RecvProvideAnonymousTemporaryFile(const uint64_t& aID,
3707
                                                const FileDescOrError& aFDOrError)
3708
0
{
3709
0
  nsAutoPtr<AnonymousTemporaryFileCallback> callback;
3710
0
  mPendingAnonymousTemporaryFiles.Remove(aID, &callback);
3711
0
  MOZ_ASSERT(callback);
3712
0
3713
0
  PRFileDesc* prfile = nullptr;
3714
0
  if (aFDOrError.type() == FileDescOrError::Tnsresult) {
3715
0
    DebugOnly<nsresult> rv = aFDOrError.get_nsresult();
3716
0
    MOZ_ASSERT(NS_FAILED(rv));
3717
0
  } else {
3718
0
    auto rawFD = aFDOrError.get_FileDescriptor().ClonePlatformHandle();
3719
0
    prfile = PR_ImportFile(PROsfd(rawFD.release()));
3720
0
  }
3721
0
  (*callback)(prfile);
3722
0
  return IPC_OK();
3723
0
}
3724
3725
nsresult
3726
ContentChild::AsyncOpenAnonymousTemporaryFile(const AnonymousTemporaryFileCallback& aCallback)
3727
0
{
3728
0
  MOZ_ASSERT(NS_IsMainThread());
3729
0
3730
0
  static uint64_t id = 0;
3731
0
  auto newID = id++;
3732
0
  if (!SendRequestAnonymousTemporaryFile(newID)) {
3733
0
    return NS_ERROR_FAILURE;
3734
0
  }
3735
0
3736
0
  // Remember the association with the callback.
3737
0
  MOZ_ASSERT(!mPendingAnonymousTemporaryFiles.Get(newID));
3738
0
  mPendingAnonymousTemporaryFiles.LookupOrAdd(newID, aCallback);
3739
0
  return NS_OK;
3740
0
}
3741
3742
mozilla::ipc::IPCResult
3743
ContentChild::RecvSetPermissionsWithKey(const nsCString& aPermissionKey,
3744
                                        nsTArray<IPC::Permission>&& aPerms)
3745
0
{
3746
0
  nsCOMPtr<nsIPermissionManager> permissionManager =
3747
0
    services::GetPermissionManager();
3748
0
  permissionManager->SetPermissionsWithKey(aPermissionKey, aPerms);
3749
0
  return IPC_OK();
3750
0
}
3751
3752
mozilla::ipc::IPCResult
3753
ContentChild::RecvRefreshScreens(nsTArray<ScreenDetails>&& aScreens)
3754
0
{
3755
0
  ScreenManager& screenManager = ScreenManager::GetSingleton();
3756
0
  screenManager.Refresh(std::move(aScreens));
3757
0
  return IPC_OK();
3758
0
}
3759
3760
already_AddRefed<nsIEventTarget>
3761
ContentChild::GetEventTargetFor(TabChild* aTabChild)
3762
0
{
3763
0
  return IToplevelProtocol::GetActorEventTarget(aTabChild);
3764
0
}
3765
3766
mozilla::ipc::IPCResult
3767
ContentChild::RecvSetPluginList(const uint32_t& aPluginEpoch,
3768
                                nsTArray<plugins::PluginTag>&& aPluginTags,
3769
                                nsTArray<plugins::FakePluginTag>&& aFakePluginTags)
3770
0
{
3771
0
  RefPtr<nsPluginHost> host = nsPluginHost::GetInst();
3772
0
  host->SetPluginsInContent(aPluginEpoch, aPluginTags, aFakePluginTags);
3773
0
  return IPC_OK();
3774
0
}
3775
3776
PClientOpenWindowOpChild*
3777
ContentChild::AllocPClientOpenWindowOpChild(const ClientOpenWindowArgs& aArgs)
3778
0
{
3779
0
  return AllocClientOpenWindowOpChild();
3780
0
}
3781
3782
IPCResult
3783
ContentChild::RecvPClientOpenWindowOpConstructor(PClientOpenWindowOpChild* aActor,
3784
                                                 const ClientOpenWindowArgs& aArgs)
3785
0
{
3786
0
  InitClientOpenWindowOpChild(aActor, aArgs);
3787
0
  return IPC_OK();
3788
0
}
3789
3790
bool
3791
ContentChild::DeallocPClientOpenWindowOpChild(PClientOpenWindowOpChild* aActor)
3792
0
{
3793
0
  return DeallocClientOpenWindowOpChild(aActor);
3794
0
}
3795
3796
mozilla::ipc::IPCResult
3797
ContentChild::RecvShareCodeCoverageMutex(const CrossProcessMutexHandle& aHandle)
3798
0
{
3799
#ifdef MOZ_CODE_COVERAGE
3800
  CodeCoverageHandler::Init(aHandle);
3801
  return IPC_OK();
3802
#else
3803
0
  MOZ_CRASH("Shouldn't receive this message in non-code coverage builds!");
3804
0
#endif
3805
0
}
3806
3807
mozilla::ipc::IPCResult
3808
ContentChild::RecvDumpCodeCoverageCounters(DumpCodeCoverageCountersResolver&& aResolver)
3809
0
{
3810
#ifdef MOZ_CODE_COVERAGE
3811
  CodeCoverageHandler::DumpCounters();
3812
  aResolver(/* unused */ true);
3813
  return IPC_OK();
3814
#else
3815
0
  MOZ_CRASH("Shouldn't receive this message in non-code coverage builds!");
3816
0
#endif
3817
0
}
3818
3819
mozilla::ipc::IPCResult
3820
ContentChild::RecvResetCodeCoverageCounters(ResetCodeCoverageCountersResolver&& aResolver)
3821
0
{
3822
#ifdef MOZ_CODE_COVERAGE
3823
  CodeCoverageHandler::ResetCounters();
3824
  aResolver(/* unused */ true);
3825
  return IPC_OK();
3826
#else
3827
0
  MOZ_CRASH("Shouldn't receive this message in non-code coverage builds!");
3828
0
#endif
3829
0
}
3830
3831
mozilla::ipc::IPCResult
3832
ContentChild::RecvSetInputEventQueueEnabled()
3833
0
{
3834
0
  nsThreadManager::get().EnableMainThreadEventPrioritization();
3835
0
  return IPC_OK();
3836
0
}
3837
3838
mozilla::ipc::IPCResult
3839
ContentChild::RecvFlushInputEventQueue()
3840
0
{
3841
0
  nsThreadManager::get().FlushInputEventPrioritization();
3842
0
  return IPC_OK();
3843
0
}
3844
3845
mozilla::ipc::IPCResult
3846
ContentChild::RecvSuspendInputEventQueue()
3847
0
{
3848
0
  nsThreadManager::get().SuspendInputEventPrioritization();
3849
0
  return IPC_OK();
3850
0
}
3851
3852
mozilla::ipc::IPCResult
3853
ContentChild::RecvResumeInputEventQueue()
3854
0
{
3855
0
  nsThreadManager::get().ResumeInputEventPrioritization();
3856
0
  return IPC_OK();
3857
0
}
3858
3859
mozilla::ipc::IPCResult
3860
ContentChild::RecvAddDynamicScalars(nsTArray<DynamicScalarDefinition>&& aDefs)
3861
0
{
3862
0
  TelemetryIPC::AddDynamicScalarDefinitions(aDefs);
3863
0
  return IPC_OK();
3864
0
}
3865
3866
mozilla::ipc::IPCResult
3867
ContentChild::RecvSaveRecording(const FileDescriptor& aFile)
3868
0
{
3869
0
  recordreplay::parent::SaveRecording(aFile);
3870
0
  return IPC_OK();
3871
0
}
3872
3873
already_AddRefed<nsIEventTarget>
3874
ContentChild::GetSpecificMessageEventTarget(const Message& aMsg)
3875
{
3876
  switch(aMsg.type()) {
3877
    // Javascript
3878
    case PJavaScript::Msg_DropTemporaryStrongReferences__ID:
3879
    case PJavaScript::Msg_DropObject__ID:
3880
3881
    // Navigation
3882
    case PContent::Msg_NotifyVisited__ID:
3883
3884
    // Storage API
3885
    case PContent::Msg_DataStoragePut__ID:
3886
    case PContent::Msg_DataStorageRemove__ID:
3887
    case PContent::Msg_DataStorageClear__ID:
3888
3889
    // Blob and BlobURL
3890
    case PContent::Msg_BlobURLRegistration__ID:
3891
    case PContent::Msg_BlobURLUnregistration__ID:
3892
    case PContent::Msg_InitBlobURLs__ID:
3893
    case PContent::Msg_PIPCBlobInputStreamConstructor__ID:
3894
    case PContent::Msg_StoreAndBroadcastBlobURLRegistration__ID:
3895
3896
      return do_AddRef(SystemGroup::EventTargetFor(TaskCategory::Other));
3897
3898
    default:
3899
      return nullptr;
3900
  }
3901
}
3902
3903
#ifdef NIGHTLY_BUILD
3904
void
3905
ContentChild::OnChannelReceivedMessage(const Message& aMsg)
3906
0
{
3907
0
  if (nsContentUtils::IsMessageInputEvent(aMsg)) {
3908
0
    mPendingInputEvents++;
3909
0
  }
3910
0
}
3911
3912
PContentChild::Result
3913
ContentChild::OnMessageReceived(const Message& aMsg)
3914
0
{
3915
0
  if (nsContentUtils::IsMessageInputEvent(aMsg)) {
3916
0
    DebugOnly<uint32_t> prevEvts = mPendingInputEvents--;
3917
0
    MOZ_ASSERT(prevEvts > 0);
3918
0
  }
3919
0
3920
0
  return PContentChild::OnMessageReceived(aMsg);
3921
0
}
3922
3923
PContentChild::Result
3924
ContentChild::OnMessageReceived(const Message& aMsg, Message*& aReply)
3925
0
{
3926
0
  return PContentChild::OnMessageReceived(aMsg, aReply);
3927
0
}
3928
#endif
3929
3930
} // namespace dom
3931
3932
#if defined(__OpenBSD__) && defined(MOZ_CONTENT_SANDBOX)
3933
#include <unistd.h>
3934
3935
static LazyLogModule sPledgeLog("SandboxPledge");
3936
3937
bool
3938
StartOpenBSDSandbox(GeckoProcessType type)
3939
{
3940
  nsAutoCString promisesString;
3941
  nsAutoCString processTypeString;
3942
3943
  switch (type) {
3944
    case GeckoProcessType_Default:
3945
      processTypeString = "main";
3946
      Preferences::GetCString("security.sandbox.pledge.main",
3947
                              promisesString);
3948
      break;
3949
3950
    case GeckoProcessType_Content:
3951
      processTypeString = "content";
3952
      Preferences::GetCString("security.sandbox.pledge.content",
3953
                              promisesString);
3954
      break;
3955
3956
    default:
3957
      MOZ_ASSERT(false, "unknown process type");
3958
      return false;
3959
  };
3960
3961
  if (pledge(promisesString.get(), NULL) == -1) {
3962
    if (errno == EINVAL) {
3963
        MOZ_LOG(sPledgeLog, LogLevel::Error,
3964
               ("pledge promises for %s process is a malformed string: '%s'\n",
3965
                processTypeString.get(), promisesString.get()));
3966
    } else if (errno == EPERM) {
3967
        MOZ_LOG(sPledgeLog, LogLevel::Error,
3968
               ("pledge promises for %s process can't elevate privileges: '%s'\n",
3969
                processTypeString.get(), promisesString.get()));
3970
    }
3971
    return false;
3972
  } else {
3973
      MOZ_LOG(sPledgeLog, LogLevel::Debug,
3974
             ("pledged %s process with promises: '%s'\n",
3975
              processTypeString.get(), promisesString.get()));
3976
  }
3977
  return true;
3978
}
3979
#endif
3980
3981
#if !defined(XP_WIN)
3982
bool IsDevelopmentBuild()
3983
3
{
3984
3
  nsCOMPtr<nsIFile> path = mozilla::Omnijar::GetPath(mozilla::Omnijar::GRE);
3985
3
  // If the path doesn't exist, we're a dev build.
3986
3
  return path == nullptr;
3987
3
}
3988
#endif /* !XP_WIN */
3989
3990
#if defined(XP_MACOSX)
3991
/*
3992
 * Helper function to read a string value for a given key from the .app's
3993
 * Info.plist.
3994
 */
3995
static nsresult
3996
GetStringValueFromBundlePlist(const nsAString& aKey, nsAutoCString& aValue)
3997
{
3998
  CFBundleRef mainBundle = CFBundleGetMainBundle();
3999
  if (mainBundle == nullptr) {
4000
    return NS_ERROR_FAILURE;
4001
  }
4002
4003
  // Read this app's bundle Info.plist as a dictionary
4004
  CFDictionaryRef bundleInfoDict = CFBundleGetInfoDictionary(mainBundle);
4005
  if (bundleInfoDict == nullptr) {
4006
    return NS_ERROR_FAILURE;
4007
  }
4008
4009
  nsAutoCString keyAutoCString = NS_ConvertUTF16toUTF8(aKey);
4010
  CFStringRef key = CFStringCreateWithCString(kCFAllocatorDefault,
4011
                                              keyAutoCString.get(),
4012
                                              kCFStringEncodingUTF8);
4013
  if (key == nullptr) {
4014
    return NS_ERROR_FAILURE;
4015
  }
4016
4017
  CFStringRef value = (CFStringRef)CFDictionaryGetValue(bundleInfoDict, key);
4018
  CFRelease(key);
4019
  if (value == nullptr) {
4020
    return NS_ERROR_FAILURE;
4021
  }
4022
4023
  CFIndex valueLength = CFStringGetLength(value);
4024
  if (valueLength == 0) {
4025
    return NS_ERROR_FAILURE;
4026
  }
4027
4028
  const char* valueCString = CFStringGetCStringPtr(value,
4029
                                                   kCFStringEncodingUTF8);
4030
  if (valueCString) {
4031
    aValue.Assign(valueCString);
4032
    return NS_OK;
4033
  }
4034
4035
  CFIndex maxLength =
4036
    CFStringGetMaximumSizeForEncoding(valueLength, kCFStringEncodingUTF8) + 1;
4037
  char* valueBuffer = static_cast<char*>(moz_xmalloc(maxLength));
4038
4039
  if (!CFStringGetCString(value, valueBuffer, maxLength,
4040
                          kCFStringEncodingUTF8)) {
4041
    free(valueBuffer);
4042
    return NS_ERROR_FAILURE;
4043
  }
4044
4045
  aValue.Assign(valueBuffer);
4046
  free(valueBuffer);
4047
  return NS_OK;
4048
}
4049
4050
/*
4051
 * Helper function for reading a path string from the .app's Info.plist
4052
 * and returning a directory object for that path with symlinks resolved.
4053
 */
4054
static nsresult
4055
GetDirFromBundlePlist(const nsAString& aKey, nsIFile **aDir)
4056
{
4057
  nsresult rv;
4058
4059
  nsAutoCString dirPath;
4060
  rv = GetStringValueFromBundlePlist(aKey, dirPath);
4061
  NS_ENSURE_SUCCESS(rv, rv);
4062
4063
  nsCOMPtr<nsIFile> dir;
4064
  rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(dirPath),
4065
                       false,
4066
                       getter_AddRefs(dir));
4067
  NS_ENSURE_SUCCESS(rv, rv);
4068
4069
  rv = dir->Normalize();
4070
  NS_ENSURE_SUCCESS(rv, rv);
4071
4072
  bool isDirectory = false;
4073
  rv = dir->IsDirectory(&isDirectory);
4074
  NS_ENSURE_SUCCESS(rv, rv);
4075
  if (!isDirectory) {
4076
    return NS_ERROR_FILE_NOT_DIRECTORY;
4077
  }
4078
4079
  dir.swap(*aDir);
4080
  return NS_OK;
4081
}
4082
4083
nsresult
4084
GetRepoDir(nsIFile **aRepoDir)
4085
{
4086
  MOZ_ASSERT(IsDevelopmentBuild());
4087
  return GetDirFromBundlePlist(NS_LITERAL_STRING(MAC_DEV_REPO_KEY), aRepoDir);
4088
}
4089
4090
nsresult
4091
GetObjDir(nsIFile **aObjDir)
4092
{
4093
  MOZ_ASSERT(IsDevelopmentBuild());
4094
  return GetDirFromBundlePlist(NS_LITERAL_STRING(MAC_DEV_OBJ_KEY), aObjDir);
4095
}
4096
#endif /* XP_MACOSX */
4097
4098
} // namespace mozilla