tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ContentChild.cpp (178777B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifdef MOZ_WIDGET_ANDROID
      8 #  include "AndroidDecoderModule.h"
      9 #endif
     10 
     11 #include "BrowserChild.h"
     12 #include "ContentChild.h"
     13 #include "GMPServiceChild.h"
     14 #include "GeckoProfiler.h"
     15 #include "Geolocation.h"
     16 #include "HandlerServiceChild.h"
     17 #include "ScrollingMetrics.h"
     18 #include "gfxUtils.h"
     19 #include "imgLoader.h"
     20 #include "mozilla/AppShutdown.h"
     21 #include "mozilla/Attributes.h"
     22 #include "mozilla/BackgroundHangMonitor.h"
     23 #include "mozilla/BasePrincipal.h"
     24 #include "mozilla/ClipboardContentAnalysisChild.h"
     25 #include "mozilla/ClipboardReadRequestChild.h"
     26 #include "mozilla/Components.h"
     27 #include "mozilla/FOGIPC.h"
     28 #include "mozilla/HangDetails.h"
     29 #include "mozilla/LoadInfo.h"
     30 #include "mozilla/Logging.h"
     31 #include "mozilla/LookAndFeel.h"
     32 #include "mozilla/MemoryTelemetry.h"
     33 #include "mozilla/NullPrincipal.h"
     34 #include "mozilla/PerfStats.h"
     35 #include "mozilla/Preferences.h"
     36 #include "mozilla/ProcessHangMonitorIPC.h"
     37 #include "mozilla/RemoteLazyInputStreamChild.h"
     38 #include "mozilla/RemoteMediaManagerChild.h"
     39 #include "mozilla/SchedulerGroup.h"
     40 #include "mozilla/ScopeExit.h"
     41 #include "mozilla/SharedStyleSheetCache.h"
     42 #include "mozilla/SimpleEnumerator.h"
     43 #include "mozilla/SpinEventLoopUntil.h"
     44 #include "mozilla/StaticPrefs_browser.h"
     45 #include "mozilla/StaticPrefs_dom.h"
     46 #include "mozilla/StaticPrefs_fission.h"
     47 #include "mozilla/StaticPrefs_javascript.h"
     48 #include "mozilla/StaticPrefs_media.h"
     49 #include "mozilla/StaticPrefs_threads.h"
     50 #include "mozilla/StorageAccessAPIHelper.h"
     51 #include "mozilla/TelemetryIPC.h"
     52 #include "mozilla/WebBrowserPersistDocumentChild.h"
     53 #include "mozilla/devtools/HeapSnapshotTempFileHelperChild.h"
     54 #include "mozilla/dom/AutoSuppressEventHandlingAndSuspend.h"
     55 #include "mozilla/dom/BlobImpl.h"
     56 #include "mozilla/dom/BrowserBridgeHost.h"
     57 #include "mozilla/dom/BrowsingContext.h"
     58 #include "mozilla/dom/BrowsingContextGroup.h"
     59 #include "mozilla/dom/ChildProcessChannelListener.h"
     60 #include "mozilla/dom/ChildProcessMessageManager.h"
     61 #include "mozilla/dom/ClientManager.h"
     62 #include "mozilla/dom/ContentParent.h"
     63 #include "mozilla/dom/ContentPlaybackController.h"
     64 #include "mozilla/dom/ContentProcessManager.h"
     65 #include "mozilla/dom/ContentProcessMessageManager.h"
     66 #include "mozilla/dom/DataTransfer.h"
     67 #include "mozilla/dom/DocGroup.h"
     68 #include "mozilla/dom/ExternalHelperAppChild.h"
     69 #include "mozilla/dom/GetFilesHelper.h"
     70 #include "mozilla/dom/IPCBlobUtils.h"
     71 #include "mozilla/dom/InProcessChild.h"
     72 #include "mozilla/dom/JSActorService.h"
     73 #include "mozilla/dom/JSProcessActorBinding.h"
     74 #include "mozilla/dom/JSProcessActorChild.h"
     75 #include "mozilla/dom/LSObject.h"
     76 #include "mozilla/dom/MemoryReportRequest.h"
     77 #include "mozilla/dom/Navigation.h"
     78 #include "mozilla/dom/PSessionStorageObserverChild.h"
     79 #include "mozilla/dom/PolicyContainer.h"
     80 #include "mozilla/dom/PostMessageEvent.h"
     81 #include "mozilla/dom/PushNotifier.h"
     82 #include "mozilla/dom/RemoteWorkerDebuggerManagerChild.h"
     83 #include "mozilla/dom/RemoteWorkerService.h"
     84 #include "mozilla/dom/ScreenOrientation.h"
     85 #include "mozilla/dom/ServiceWorkerManager.h"
     86 #include "mozilla/dom/SessionStorageManager.h"
     87 #include "mozilla/dom/SharedScriptCache.h"
     88 #include "mozilla/dom/URLClassifierChild.h"
     89 #include "mozilla/dom/UserActivation.h"
     90 #include "mozilla/dom/WindowGlobalChild.h"
     91 #include "mozilla/dom/WorkerDebugger.h"
     92 #include "mozilla/dom/WorkerDebuggerManager.h"
     93 #include "mozilla/dom/ipc/SharedMap.h"
     94 #include "mozilla/extensions/ExtensionsChild.h"
     95 #include "mozilla/extensions/StreamFilterParent.h"
     96 #include "mozilla/gfx/2D.h"
     97 #include "mozilla/gfx/Logging.h"
     98 #include "mozilla/gfx/gfxVars.h"
     99 #include "mozilla/hal_sandbox/PHalChild.h"
    100 #include "mozilla/image/FetchDecodedImage.h"
    101 #include "mozilla/intl/L10nRegistry.h"
    102 #include "mozilla/intl/LocaleService.h"
    103 #include "mozilla/intl/OSPreferences.h"
    104 #include "mozilla/ipc/BackgroundChild.h"
    105 #include "mozilla/ipc/Endpoint.h"
    106 #include "mozilla/ipc/FileDescriptorUtils.h"
    107 #include "mozilla/ipc/GeckoChildProcessHost.h"
    108 #include "mozilla/ipc/ProcessChild.h"
    109 #include "mozilla/ipc/TestShellChild.h"
    110 #include "mozilla/layers/APZChild.h"
    111 #include "mozilla/layers/CompositorManagerChild.h"
    112 #include "mozilla/layers/ContentProcessController.h"
    113 #include "mozilla/layers/ImageBridgeChild.h"
    114 #include "nsNSSComponent.h"
    115 #include "nsXPLookAndFeel.h"
    116 #ifdef NS_PRINTING
    117 #  include "mozilla/layout/RemotePrintJobChild.h"
    118 #endif
    119 #include "ChildProfilerController.h"
    120 #include "mozilla/loader/ScriptCacheActors.h"
    121 #include "mozilla/media/MediaChild.h"
    122 #include "mozilla/net/CaptivePortalService.h"
    123 #include "mozilla/net/ChildDNSService.h"
    124 #include "mozilla/net/CookieServiceChild.h"
    125 #include "mozilla/net/DocumentChannelChild.h"
    126 #include "mozilla/net/HttpChannelChild.h"
    127 #include "mozilla/widget/RemoteLookAndFeel.h"
    128 #include "mozilla/widget/ScreenManager.h"
    129 #include "mozilla/widget/WidgetMessageUtils.h"
    130 #include "mozmemory.h"
    131 #include "nsBaseDragService.h"
    132 #include "nsDocShellLoadTypes.h"
    133 #include "nsFocusManager.h"
    134 #include "nsHttpHandler.h"
    135 #include "nsIConsoleService.h"
    136 #include "nsIInputStreamChannel.h"
    137 #include "nsILayoutHistoryState.h"
    138 #include "nsILoadGroup.h"
    139 #include "nsIOpenWindowInfo.h"
    140 #include "nsISimpleEnumerator.h"
    141 #include "nsIStringBundle.h"
    142 #include "nsIURIMutator.h"
    143 #include "nsOpenWindowInfo.h"
    144 #include "nsQueryObject.h"
    145 #include "nsRefreshDriver.h"
    146 #include "nsSandboxFlags.h"
    147 
    148 #if defined(MOZ_SANDBOX)
    149 #  include "mozilla/SandboxSettings.h"
    150 #  if defined(XP_WIN)
    151 #    include "mozilla/ProcInfo.h"
    152 #    include "mozilla/sandboxTarget.h"
    153 #  elif defined(XP_LINUX)
    154 #    include "CubebUtils.h"
    155 #    include "mozilla/Sandbox.h"
    156 #    include "mozilla/SandboxInfo.h"
    157 #    include "mozilla/SandboxProfilerObserver.h"
    158 #  elif defined(XP_MACOSX)
    159 #    include <CoreGraphics/CGError.h>
    160 
    161 #    include "mozilla/Sandbox.h"
    162 #  elif defined(__OpenBSD__)
    163 #    include <err.h>
    164 #    include <sys/stat.h>
    165 #    include <unistd.h>
    166 
    167 #    include <fstream>
    168 
    169 #    include "BinaryPath.h"
    170 #    include "SpecialSystemDirectory.h"
    171 #    include "mozilla/ipc/UtilityProcessSandboxing.h"
    172 #    include "nsILineInputStream.h"
    173 #  endif
    174 #  if defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
    175 #    include "mozilla/SandboxTestingChild.h"
    176 #  endif
    177 #endif
    178 
    179 #include "IHistory.h"
    180 #include "ReferrerInfo.h"
    181 #include "SandboxHal.h"
    182 #include "base/message_loop.h"
    183 #include "base/process_util.h"
    184 #include "base/task.h"
    185 #include "mozInlineSpellChecker.h"
    186 #include "mozilla/GlobalStyleSheetCache.h"
    187 #include "mozilla/dom/BlobURLProtocolHandler.h"
    188 #include "mozilla/dom/PCycleCollectWithLogsChild.h"
    189 #include "mozilla/dom/PerformanceStorage.h"
    190 #include "nsAnonymousTemporaryFile.h"
    191 #include "nsCategoryManagerUtils.h"
    192 #include "nsChromeRegistryContent.h"
    193 #include "nsClipboardProxy.h"
    194 #include "nsContentPermissionHelper.h"
    195 #include "nsDebugImpl.h"
    196 #include "nsDirectoryService.h"
    197 #include "nsDirectoryServiceDefs.h"
    198 #include "nsDirectoryServiceUtils.h"
    199 #include "nsDocShell.h"
    200 #include "nsDocShellLoadState.h"
    201 #include "nsFrameMessageManager.h"
    202 #include "nsHashPropertyBag.h"
    203 #include "nsIConsoleListener.h"
    204 #include "nsICycleCollectorListener.h"
    205 #include "nsIDocShellTreeOwner.h"
    206 #include "nsIDocumentViewer.h"
    207 #include "nsIDragService.h"
    208 #include "nsIInterfaceRequestorUtils.h"
    209 #include "nsIMemoryInfoDumper.h"
    210 #include "nsIMemoryReporter.h"
    211 #include "nsIOService.h"
    212 #include "nsIObserverService.h"
    213 #include "nsIScriptError.h"
    214 #include "nsIScriptSecurityManager.h"
    215 #include "nsJSEnvironment.h"
    216 #include "nsJSUtils.h"
    217 #include "nsMemoryInfoDumper.h"
    218 #include "nsNetUtil.h"
    219 #include "nsServiceManagerUtils.h"
    220 #include "nsStyleSheetService.h"
    221 #include "nsThreadManager.h"
    222 #include "nsWindowMemoryReporter.h"
    223 #include "nsXULAppAPI.h"
    224 
    225 #ifdef MOZ_WEBRTC
    226 #  include "jsapi/WebrtcGlobalChild.h"
    227 #endif
    228 
    229 #include "PermissionMessageUtils.h"
    230 #include "mozilla/Permission.h"
    231 #include "mozilla/PermissionManager.h"
    232 
    233 #if defined(MOZ_WIDGET_ANDROID)
    234 #  include <sched.h>
    235 
    236 #  include "APKOpen.h"
    237 #endif
    238 
    239 #ifdef XP_WIN
    240 #  include <process.h>
    241 #  define getpid _getpid
    242 #  include "mozilla/WinDllServices.h"
    243 #endif
    244 
    245 #if defined(XP_MACOSX)
    246 #  include <sys/qos.h>
    247 
    248 #  include "nsMacUtilsImpl.h"
    249 #endif /* XP_MACOSX */
    250 
    251 #ifdef MOZ_X11
    252 #  include "mozilla/X11Util.h"
    253 #endif
    254 
    255 #ifdef ACCESSIBILITY
    256 #  include "nsAccessibilityService.h"
    257 #  ifdef XP_WIN
    258 #    include "mozilla/a11y/AccessibleWrap.h"
    259 #  endif
    260 #  include "mozilla/a11y/DocAccessible.h"
    261 #  include "mozilla/a11y/DocManager.h"
    262 #  include "mozilla/a11y/OuterDocAccessible.h"
    263 #endif
    264 
    265 #include "mozilla/dom/File.h"
    266 #include "mozilla/dom/MediaControllerBinding.h"
    267 
    268 #ifdef MOZ_WEBSPEECH
    269 #  include "mozilla/dom/PSpeechSynthesisChild.h"
    270 #endif
    271 
    272 #include "ClearOnShutdown.h"
    273 #include "DomainPolicy.h"
    274 #include "GfxInfoBase.h"
    275 #include "MMPrinter.h"
    276 #include "VRManagerChild.h"
    277 #include "gfxPlatform.h"
    278 #include "gfxPlatformFontList.h"
    279 #include "mozilla/RemoteSpellCheckEngineChild.h"
    280 #include "mozilla/dom/TabContext.h"
    281 #include "mozilla/dom/ipc/StructuredCloneData.h"
    282 #include "mozilla/ipc/CrashReporterClient.h"
    283 #include "mozilla/ipc/ProcessUtils.h"
    284 #include "mozilla/ipc/URIUtils.h"
    285 #include "mozilla/net/NeckoMessageUtils.h"
    286 #include "mozilla/widget/PuppetBidiKeyboard.h"
    287 #include "nsContentUtils.h"
    288 #include "nsIPrincipal.h"
    289 #include "nsString.h"
    290 #include "nscore.h"  // for NS_FREE_PERMANENT_DATA
    291 #include "private/pprio.h"
    292 
    293 #ifdef MOZ_WIDGET_GTK
    294 #  include <gtk/gtk.h>
    295 
    296 #  include "mozilla/WidgetUtilsGtk.h"
    297 #  include "nsAppRunner.h"
    298 #endif
    299 
    300 #ifdef MOZ_CODE_COVERAGE
    301 #  include "mozilla/CodeCoverageHandler.h"
    302 #endif
    303 
    304 #ifdef MOZ_WMF_CDM
    305 #  include "mozilla/dom/MediaKeySystemAccess.h"
    306 #endif
    307 
    308 extern mozilla::LazyLogModule gSHIPBFCacheLog;
    309 
    310 using namespace mozilla;
    311 using namespace mozilla::dom::ipc;
    312 using namespace mozilla::media;
    313 using namespace mozilla::embedding;
    314 using namespace mozilla::gmp;
    315 using namespace mozilla::hal_sandbox;
    316 using namespace mozilla::ipc;
    317 using namespace mozilla::intl;
    318 using namespace mozilla::layers;
    319 using namespace mozilla::layout;
    320 using namespace mozilla::net;
    321 using namespace mozilla::widget;
    322 using mozilla::loader::PScriptCacheChild;
    323 
    324 namespace geckoprofiler::markers {
    325 struct ProcessPriorityChange {
    326  static constexpr Span<const char> MarkerTypeName() {
    327    return MakeStringSpan("ProcessPriorityChange");
    328  }
    329  static void StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter& aWriter,
    330                                   const ProfilerString8View& aPreviousPriority,
    331                                   const ProfilerString8View& aNewPriority) {
    332    aWriter.StringProperty("Before", aPreviousPriority);
    333    aWriter.StringProperty("After", aNewPriority);
    334  }
    335  static MarkerSchema MarkerTypeDisplay() {
    336    using MS = MarkerSchema;
    337    MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable};
    338    schema.AddKeyFormat("Before", MS::Format::String);
    339    schema.AddKeyFormat("After", MS::Format::String);
    340    schema.AddStaticLabelValue("Note",
    341                               "This is a notification of the priority change "
    342                               "that was done by the parent process");
    343    schema.SetAllLabels(
    344        "priority: {marker.data.Before} -> {marker.data.After}");
    345    return schema;
    346  }
    347 };
    348 
    349 struct ProcessPriority {
    350  static constexpr Span<const char> MarkerTypeName() {
    351    return MakeStringSpan("ProcessPriority");
    352  }
    353  static void StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter& aWriter,
    354                                   const ProfilerString8View& aPriority,
    355                                   const ProfilingState& aProfilingState) {
    356    aWriter.StringProperty("Priority", aPriority);
    357    aWriter.StringProperty("Marker cause",
    358                           ProfilerString8View::WrapNullTerminatedString(
    359                               ProfilingStateToString(aProfilingState)));
    360  }
    361  static MarkerSchema MarkerTypeDisplay() {
    362    using MS = MarkerSchema;
    363    MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable};
    364    schema.AddKeyFormat("Priority", MS::Format::String);
    365    schema.AddKeyFormat("Marker cause", MS::Format::String);
    366    schema.SetAllLabels("priority: {marker.data.Priority}");
    367    return schema;
    368  }
    369 };
    370 }  // namespace geckoprofiler::markers
    371 
    372 namespace mozilla {
    373 namespace dom {
    374 
    375 // IPC sender for remote GC/CC logging.
    376 class CycleCollectWithLogsChild final : public PCycleCollectWithLogsChild {
    377 public:
    378  NS_INLINE_DECL_REFCOUNTING(CycleCollectWithLogsChild)
    379 
    380  class Sink final : public nsICycleCollectorLogSink {
    381    NS_DECL_ISUPPORTS
    382 
    383    Sink(CycleCollectWithLogsChild* aActor, const FileDescriptor& aGCLog,
    384         const FileDescriptor& aCCLog) {
    385      mActor = aActor;
    386      mGCLog = FileDescriptorToFILE(aGCLog, "w");
    387      mCCLog = FileDescriptorToFILE(aCCLog, "w");
    388    }
    389 
    390    NS_IMETHOD Open(FILE** aGCLog, FILE** aCCLog) override {
    391      if (NS_WARN_IF(!mGCLog) || NS_WARN_IF(!mCCLog)) {
    392        return NS_ERROR_FAILURE;
    393      }
    394      *aGCLog = mGCLog;
    395      *aCCLog = mCCLog;
    396      return NS_OK;
    397    }
    398 
    399    NS_IMETHOD CloseGCLog() override {
    400      MOZ_ASSERT(mGCLog);
    401      fclose(mGCLog);
    402      mGCLog = nullptr;
    403      mActor->SendCloseGCLog();
    404      return NS_OK;
    405    }
    406 
    407    NS_IMETHOD CloseCCLog() override {
    408      MOZ_ASSERT(mCCLog);
    409      fclose(mCCLog);
    410      mCCLog = nullptr;
    411      mActor->SendCloseCCLog();
    412      return NS_OK;
    413    }
    414 
    415    NS_IMETHOD GetFilenameIdentifier(nsAString& aIdentifier) override {
    416      return UnimplementedProperty();
    417    }
    418 
    419    NS_IMETHOD SetFilenameIdentifier(const nsAString& aIdentifier) override {
    420      return UnimplementedProperty();
    421    }
    422 
    423    NS_IMETHOD GetProcessIdentifier(int32_t* aIdentifier) override {
    424      return UnimplementedProperty();
    425    }
    426 
    427    NS_IMETHOD SetProcessIdentifier(int32_t aIdentifier) override {
    428      return UnimplementedProperty();
    429    }
    430 
    431    NS_IMETHOD GetGcLog(nsIFile** aPath) override {
    432      return UnimplementedProperty();
    433    }
    434 
    435    NS_IMETHOD GetCcLog(nsIFile** aPath) override {
    436      return UnimplementedProperty();
    437    }
    438 
    439   private:
    440    ~Sink() {
    441      if (mGCLog) {
    442        fclose(mGCLog);
    443        mGCLog = nullptr;
    444      }
    445      if (mCCLog) {
    446        fclose(mCCLog);
    447        mCCLog = nullptr;
    448      }
    449      // The XPCOM refcount drives the IPC lifecycle;
    450      (void)mActor->Send__delete__(mActor);
    451    }
    452 
    453    nsresult UnimplementedProperty() {
    454      MOZ_ASSERT(false,
    455                 "This object is a remote GC/CC logger;"
    456                 " this property isn't meaningful.");
    457      return NS_ERROR_UNEXPECTED;
    458    }
    459 
    460    RefPtr<CycleCollectWithLogsChild> mActor;
    461    FILE* mGCLog;
    462    FILE* mCCLog;
    463  };
    464 
    465 private:
    466  ~CycleCollectWithLogsChild() = default;
    467 };
    468 
    469 NS_IMPL_ISUPPORTS(CycleCollectWithLogsChild::Sink, nsICycleCollectorLogSink);
    470 
    471 class ConsoleListener final : public nsIConsoleListener {
    472 public:
    473  explicit ConsoleListener(ContentChild* aChild) : mChild(aChild) {}
    474 
    475  NS_DECL_ISUPPORTS
    476  NS_DECL_NSICONSOLELISTENER
    477 
    478 private:
    479  ~ConsoleListener() = default;
    480 
    481  ContentChild* mChild;
    482  friend class ContentChild;
    483 };
    484 
    485 NS_IMPL_ISUPPORTS(ConsoleListener, nsIConsoleListener)
    486 
    487 // Before we send the error to the parent process (which
    488 // involves copying the memory), truncate any long lines.  CSS
    489 // errors in particular share the memory for long lines with
    490 // repeated errors, but the IPC communication we're about to do
    491 // will break that sharing, so we better truncate now.
    492 template <typename CharT>
    493 static void TruncateString(nsTSubstring<CharT>& aString) {
    494  if (aString.Length() > 1000) {
    495    aString.Truncate(1000);
    496  }
    497 }
    498 
    499 NS_IMETHODIMP
    500 ConsoleListener::Observe(nsIConsoleMessage* aMessage) {
    501  if (!mChild) {
    502    return NS_OK;
    503  }
    504 
    505  nsCOMPtr<nsIScriptError> scriptError = do_QueryInterface(aMessage);
    506  if (scriptError) {
    507    nsAutoString msg;
    508    nsAutoCString sourceName;
    509    nsCString category;
    510    uint32_t lineNum, colNum, flags;
    511    bool fromPrivateWindow, fromChromeContext;
    512 
    513    nsresult rv = scriptError->GetErrorMessage(msg);
    514    NS_ENSURE_SUCCESS(rv, rv);
    515    TruncateString(msg);
    516    rv = scriptError->GetSourceName(sourceName);
    517    NS_ENSURE_SUCCESS(rv, rv);
    518    TruncateString(sourceName);
    519 
    520    rv = scriptError->GetCategory(getter_Copies(category));
    521    NS_ENSURE_SUCCESS(rv, rv);
    522    rv = scriptError->GetLineNumber(&lineNum);
    523    NS_ENSURE_SUCCESS(rv, rv);
    524    rv = scriptError->GetColumnNumber(&colNum);
    525    NS_ENSURE_SUCCESS(rv, rv);
    526    rv = scriptError->GetFlags(&flags);
    527    NS_ENSURE_SUCCESS(rv, rv);
    528    rv = scriptError->GetIsFromPrivateWindow(&fromPrivateWindow);
    529    NS_ENSURE_SUCCESS(rv, rv);
    530    rv = scriptError->GetIsFromChromeContext(&fromChromeContext);
    531    NS_ENSURE_SUCCESS(rv, rv);
    532 
    533    {
    534      AutoJSAPI jsapi;
    535      jsapi.Init();
    536      JSContext* cx = jsapi.cx();
    537 
    538      JS::Rooted<JS::Value> stack(cx);
    539      rv = scriptError->GetStack(&stack);
    540      NS_ENSURE_SUCCESS(rv, rv);
    541 
    542      if (stack.isObject()) {
    543        // Because |stack| might be a cross-compartment wrapper, we can't use it
    544        // with JSAutoRealm. Use the stackGlobal for that.
    545        JS::Rooted<JS::Value> stackGlobal(cx);
    546        rv = scriptError->GetStackGlobal(&stackGlobal);
    547        NS_ENSURE_SUCCESS(rv, rv);
    548 
    549        JSAutoRealm ar(cx, &stackGlobal.toObject());
    550 
    551        StructuredCloneData data;
    552        ErrorResult err;
    553        data.Write(cx, stack, err);
    554        if (err.Failed()) {
    555          return err.StealNSResult();
    556        }
    557 
    558        ClonedMessageData cloned;
    559        if (!data.BuildClonedMessageData(cloned)) {
    560          return NS_ERROR_FAILURE;
    561        }
    562 
    563        mChild->SendScriptErrorWithStack(msg, sourceName, lineNum, colNum,
    564                                         flags, category, fromPrivateWindow,
    565                                         fromChromeContext, cloned);
    566        return NS_OK;
    567      }
    568    }
    569 
    570    mChild->SendScriptError(msg, sourceName, lineNum, colNum, flags, category,
    571                            fromPrivateWindow, 0, fromChromeContext);
    572    return NS_OK;
    573  }
    574 
    575  nsString msg;
    576  nsresult rv = aMessage->GetMessageMoz(msg);
    577  NS_ENSURE_SUCCESS(rv, rv);
    578  mChild->SendConsoleMessage(msg);
    579  return NS_OK;
    580 }
    581 
    582 #ifdef NIGHTLY_BUILD
    583 /**
    584 * The singleton of this class is registered with the BackgroundHangMonitor as
    585 * an annotator, so that the hang monitor can record whether or not there were
    586 * pending input events when the thread hung.
    587 */
    588 class PendingInputEventHangAnnotator final : public BackgroundHangAnnotator {
    589 public:
    590  virtual void AnnotateHang(BackgroundHangAnnotations& aAnnotations) override {
    591    int32_t pending = ContentChild::GetSingleton()->GetPendingInputEvents();
    592    if (pending > 0) {
    593      aAnnotations.AddAnnotation(u"PendingInput"_ns, pending);
    594    }
    595  }
    596 
    597  static PendingInputEventHangAnnotator sSingleton;
    598 };
    599 PendingInputEventHangAnnotator PendingInputEventHangAnnotator::sSingleton;
    600 #endif
    601 
    602 class ContentChild::ShutdownCanary final {};
    603 
    604 ContentChild* ContentChild::sSingleton;
    605 StaticAutoPtr<ContentChild::ShutdownCanary> ContentChild::sShutdownCanary;
    606 
    607 ContentChild::ContentChild()
    608    : mIsForBrowser(false), mIsAlive(true), mShuttingDown(false) {
    609  // This process is a content process, so it's clearly running in
    610  // multiprocess mode!
    611  nsDebugImpl::SetMultiprocessMode("Child");
    612 
    613  // Our static analysis doesn't allow capturing ref-counted pointers in
    614  // lambdas, so we need to hide it in a uintptr_t. This is safe because this
    615  // lambda will be destroyed in ~ContentChild().
    616  uintptr_t self = reinterpret_cast<uintptr_t>(this);
    617  profiler_add_state_change_callback(
    618      AllProfilingStates(),
    619      [self](ProfilingState aProfilingState) {
    620        const ContentChild* selfPtr =
    621            reinterpret_cast<const ContentChild*>(self);
    622        PROFILER_MARKER("Process Priority", OTHER,
    623                        mozilla::MarkerThreadId::MainThread(), ProcessPriority,
    624                        ProfilerString8View::WrapNullTerminatedString(
    625                            ProcessPriorityToString(selfPtr->mProcessPriority)),
    626                        aProfilingState);
    627      },
    628      self);
    629 
    630  // When ContentChild is created, the observer service does not even exist.
    631  // When ContentChild::RecvSetXPCOMProcessAttributes is called (the first
    632  // IPDL call made on this object), shutdown may have already happened. Thus
    633  // we create a canary here that relies upon getting cleared if shutdown
    634  // happens without requiring the observer service at this time.
    635  if (!sShutdownCanary) {
    636    sShutdownCanary = new ShutdownCanary();
    637    ClearOnShutdown(&sShutdownCanary, ShutdownPhase::XPCOMShutdown);
    638  }
    639 }
    640 
    641 #ifdef _MSC_VER
    642 #  pragma warning(push)
    643 #  pragma warning(                                                  \
    644      disable : 4722) /* Silence "destructor never returns" warning \
    645                       */
    646 #endif
    647 
    648 ContentChild::~ContentChild() {
    649  profiler_remove_state_change_callback(reinterpret_cast<uintptr_t>(this));
    650 
    651 #ifndef NS_FREE_PERMANENT_DATA
    652  MOZ_CRASH("Content Child shouldn't be destroyed.");
    653 #endif
    654 }
    655 
    656 #ifdef _MSC_VER
    657 #  pragma warning(pop)
    658 #endif
    659 
    660 NS_INTERFACE_MAP_BEGIN(ContentChild)
    661  NS_INTERFACE_MAP_ENTRY(nsIDOMProcessChild)
    662  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMProcessChild)
    663 NS_INTERFACE_MAP_END
    664 
    665 mozilla::ipc::IPCResult ContentChild::RecvSetXPCOMProcessAttributes(
    666    XPCOMInitData&& aXPCOMInit,
    667    const UniquePtr<StructuredCloneData>& aInitialData,
    668    FullLookAndFeel&& aLookAndFeelData, dom::SystemFontList&& aFontList,
    669    Maybe<mozilla::ipc::ReadOnlySharedMemoryHandle>&& aSharedUASheetHandle,
    670    const uintptr_t& aSharedUASheetAddress,
    671    nsTArray<mozilla::ipc::ReadOnlySharedMemoryHandle>&& aSharedFontListBlocks,
    672    const bool& aIsReadyForBackgroundProcessing) {
    673  if (!sShutdownCanary) {
    674    return IPC_OK();
    675  }
    676 
    677  mLookAndFeelData = std::move(aLookAndFeelData);
    678  mFontList = std::move(aFontList);
    679  mSharedFontListBlocks = std::move(aSharedFontListBlocks);
    680 
    681  gfx::gfxVars::SetValuesForInitialize(aXPCOMInit.gfxNonDefaultVarUpdates());
    682  PerfStats::SetCollectionMask(aXPCOMInit.perfStatsMask());
    683  LookAndFeel::EnsureInit();
    684  InitSharedUASheets(std::move(aSharedUASheetHandle), aSharedUASheetAddress);
    685  InitXPCOM(std::move(aXPCOMInit), *aInitialData,
    686            aIsReadyForBackgroundProcessing);
    687  InitGraphicsDeviceData(aXPCOMInit.contentDeviceData());
    688  RefPtr<net::ChildDNSService> dnsServiceChild =
    689      dont_AddRef(net::ChildDNSService::GetSingleton());
    690  if (dnsServiceChild) {
    691    dnsServiceChild->SetTRRDomain(aXPCOMInit.trrDomain());
    692    dnsServiceChild->SetTRRModeInChild(aXPCOMInit.trrMode(),
    693                                       aXPCOMInit.trrModeFromPref());
    694  }
    695  return IPC_OK();
    696 }
    697 
    698 void ContentChild::Init(mozilla::ipc::UntypedEndpoint&& aEndpoint,
    699                        const char* aParentBuildID, bool aIsForBrowser) {
    700 #ifdef MOZ_WIDGET_GTK
    701  // When running X11 only build we need to pass a display down
    702  // to gtk_init because it's not going to use the one from the environment
    703  // on its own when deciding which backend to use, and when starting under
    704  // XWayland, it may choose to start with the wayland backend
    705  // instead of the x11 backend.
    706  // The DISPLAY environment variable is normally set by the parent process.
    707  // The MOZ_GDK_DISPLAY environment variable is set from nsAppRunner.cpp
    708  // when --display is set by the command line.
    709  if (!gfxPlatform::IsHeadless()) {
    710    const char* display_name = PR_GetEnv("MOZ_GDK_DISPLAY");
    711    if (!display_name) {
    712      bool waylandEnabled = false;
    713 #  ifdef MOZ_WAYLAND
    714      waylandEnabled = IsWaylandEnabled();
    715 #  endif
    716      if (!waylandEnabled) {
    717        display_name = PR_GetEnv("DISPLAY");
    718      }
    719    }
    720    if (display_name) {
    721      int argc = 3;
    722      char option_name[] = "--display";
    723      char* argv[] = {
    724          // argv0 is unused because g_set_prgname() was called in
    725          // XRE_InitChildProcess().
    726          nullptr, option_name, const_cast<char*>(display_name), nullptr};
    727      char** argvp = argv;
    728      gtk_init(&argc, &argvp);
    729    } else {
    730      gtk_init(nullptr, nullptr);
    731    }
    732  }
    733 #endif
    734 
    735 #ifdef MOZ_X11
    736  if (!gfxPlatform::IsHeadless()) {
    737    // Do this after initializing GDK, or GDK will install its own handler.
    738    XRE_InstallX11ErrorHandler();
    739  }
    740 #endif
    741 
    742  MOZ_ASSERT(!sSingleton, "only one ContentChild per child");
    743 
    744  // Once we start sending IPC messages, we need the thread manager to be
    745  // initialized so we can deal with the responses. Do that here before we
    746  // try to construct the crash reporter.
    747  nsresult rv = nsThreadManager::get().Init();
    748  if (NS_WARN_IF(NS_FAILED(rv))) {
    749    MOZ_CRASH("Failed to initialize the thread manager in ContentChild::Init");
    750  }
    751 
    752  if (!aEndpoint.Bind(this)) {
    753    MOZ_CRASH("Bind failed in ContentChild::Init");
    754  }
    755  sSingleton = this;
    756 
    757  // If communications with the parent have broken down, take the process
    758  // down so it's not hanging around.
    759  GetIPCChannel()->SetAbortOnError(true);
    760 
    761  // This must be checked before any IPDL message, which may hit sentinel
    762  // errors due to parent and content processes having different
    763  // versions.
    764  MessageChannel* channel = GetIPCChannel();
    765  if (channel && !channel->SendBuildIDsMatchMessage(aParentBuildID)) {
    766    // We need to quit this process if the buildID doesn't match the parent's.
    767    // This can occur when an update occurred in the background.
    768    ProcessChild::QuickExit();
    769  }
    770 
    771 #if defined(__OpenBSD__) && defined(MOZ_SANDBOX)
    772  StartOpenBSDSandbox(GeckoProcessType_Content);
    773 #endif
    774 
    775 #ifdef MOZ_X11
    776 #  ifdef MOZ_WIDGET_GTK
    777  if (GdkIsX11Display() && !gfxPlatform::IsHeadless()) {
    778    // Send the parent our X socket to act as a proxy reference for our X
    779    // resources.
    780    int xSocketFd = ConnectionNumber(DefaultXDisplay());
    781    SendBackUpXResources(FileDescriptor(xSocketFd));
    782  }
    783 #  endif
    784 #endif
    785 
    786  CrashReporterClient::InitSingleton(this);
    787 
    788  mIsForBrowser = aIsForBrowser;
    789 
    790  SetProcessName("Web Content"_ns);
    791 
    792 #ifdef NIGHTLY_BUILD
    793  // NOTE: We have to register the annotator on the main thread, as annotators
    794  // only affect a single thread.
    795  SchedulerGroup::Dispatch(
    796      NS_NewRunnableFunction("RegisterPendingInputEventHangAnnotator", [] {
    797        BackgroundHangMonitor::RegisterAnnotator(
    798            PendingInputEventHangAnnotator::sSingleton);
    799      }));
    800 #endif
    801 
    802 #if defined(MOZ_MEMORY) && defined(DEBUG) && !defined(MOZ_UBSAN)
    803  jemalloc_stats_t stats;
    804  jemalloc_stats(&stats);
    805  MOZ_ASSERT(!stats.opt_randomize_small,
    806             "Content process should not randomize small allocations");
    807 #endif
    808 }
    809 
    810 void ContentChild::AddProfileToProcessName(const nsACString& aProfile) {
    811  nsCOMPtr<nsIPrincipal> isolationPrincipal =
    812      ContentParent::CreateRemoteTypeIsolationPrincipal(mRemoteType);
    813  if (isolationPrincipal) {
    814    if (isolationPrincipal->OriginAttributesRef().IsPrivateBrowsing()) {
    815      return;
    816    }
    817  }
    818 
    819  mProcessName = aProfile + ":"_ns + mProcessName;  //<profile_name>:example.com
    820 }
    821 
    822 void ContentChild::SetProcessName(const nsACString& aName,
    823                                  const nsACString* aSite,
    824                                  const nsACString* aCurrentProfile) {
    825  char* name;
    826  if ((name = PR_GetEnv("MOZ_DEBUG_APP_PROCESS")) && aName.EqualsASCII(name)) {
    827 #ifdef XP_UNIX
    828    printf_stderr("\n\nCHILDCHILDCHILDCHILD\n  [%s] debug me @%d\n\n", name,
    829                  getpid());
    830    sleep(30);
    831 #elif defined(XP_WIN)
    832    // Windows has a decent JIT debugging story, so NS_DebugBreak does the
    833    // right thing.
    834    NS_DebugBreak(NS_DEBUG_BREAK,
    835                  "Invoking NS_DebugBreak() to debug child process", nullptr,
    836                  __FILE__, __LINE__);
    837 #endif
    838  }
    839 
    840  if (aSite) {
    841    profiler_set_process_name(aName, aSite);
    842  } else {
    843    profiler_set_process_name(aName);
    844  }
    845 
    846  mProcessName = aName;
    847 
    848  // Requires pref flip
    849  if (aSite && StaticPrefs::fission_processSiteNames()) {
    850    nsCOMPtr<nsIPrincipal> isolationPrincipal =
    851        ContentParent::CreateRemoteTypeIsolationPrincipal(mRemoteType);
    852    if (isolationPrincipal) {
    853      // DEFAULT_PRIVATE_BROWSING_ID is the value when it's not private
    854      MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
    855              ("private = %d, pref = %d",
    856               isolationPrincipal->OriginAttributesRef().IsPrivateBrowsing(),
    857               StaticPrefs::fission_processPrivateWindowSiteNames()));
    858      if (!isolationPrincipal->OriginAttributesRef().IsPrivateBrowsing()
    859 #ifdef NIGHTLY_BUILD
    860          // Nightly can show site names for private windows, with a second pref
    861          || StaticPrefs::fission_processPrivateWindowSiteNames()
    862 #endif
    863      ) {
    864 #if !defined(XP_MACOSX)
    865        // Mac doesn't have the 15-character limit Linux does
    866        // Sets profiler process name
    867        if (isolationPrincipal->SchemeIs("https")) {
    868          nsAutoCString schemeless;
    869          isolationPrincipal->GetHostPort(schemeless);
    870          nsAutoCString originSuffix;
    871          isolationPrincipal->GetOriginSuffix(originSuffix);
    872          schemeless.Append(originSuffix);
    873          mProcessName = schemeless;
    874        } else
    875 #endif
    876        {
    877          mProcessName = *aSite;
    878        }
    879      }
    880    }
    881  }
    882 
    883  if (StaticPrefs::fission_processProfileName() && aCurrentProfile &&
    884      !aCurrentProfile->IsEmpty()) {
    885    AddProfileToProcessName(*aCurrentProfile);
    886  }
    887 
    888  // else private window, don't change process name, or the pref isn't set
    889  // mProcessName is always flat (mProcessName == aName)
    890 
    891  mozilla::ipc::SetThisProcessName(mProcessName.get());
    892 
    893  MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
    894          ("Changed name of process %d to %s", getpid(),
    895           PromiseFlatCString(mProcessName).get()));
    896 }
    897 
    898 static nsresult GetCreateWindowParams(nsIOpenWindowInfo* aOpenWindowInfo,
    899                                      nsDocShellLoadState* aLoadState,
    900                                      bool aForceNoReferrer,
    901                                      nsIReferrerInfo** aReferrerInfo,
    902                                      nsIPrincipal** aTriggeringPrincipal,
    903                                      nsIPolicyContainer** aPolicyContainer) {
    904  if (!aTriggeringPrincipal || !aPolicyContainer) {
    905    NS_ERROR("aTriggeringPrincipal || aPolicyContainer is null");
    906    return NS_ERROR_FAILURE;
    907  }
    908 
    909  if (!aReferrerInfo) {
    910    NS_ERROR("aReferrerInfo is null");
    911    return NS_ERROR_FAILURE;
    912  }
    913 
    914  nsCOMPtr<nsIReferrerInfo> referrerInfo;
    915  if (aForceNoReferrer) {
    916    referrerInfo = new ReferrerInfo(nullptr, ReferrerPolicy::_empty, false);
    917  }
    918  if (aLoadState && !referrerInfo) {
    919    referrerInfo = aLoadState->GetReferrerInfo();
    920  }
    921 
    922  RefPtr<BrowsingContext> parent = aOpenWindowInfo->GetParent();
    923  nsCOMPtr<nsPIDOMWindowOuter> opener =
    924      parent ? parent->GetDOMWindow() : nullptr;
    925  if (!opener) {
    926    nsCOMPtr<nsIPrincipal> nullPrincipal =
    927        NullPrincipal::Create(aOpenWindowInfo->GetOriginAttributes());
    928    if (!referrerInfo) {
    929      referrerInfo = new ReferrerInfo(nullptr, ReferrerPolicy::_empty);
    930    }
    931 
    932    referrerInfo.swap(*aReferrerInfo);
    933    NS_ADDREF(*aTriggeringPrincipal = nullPrincipal);
    934    return NS_OK;
    935  }
    936 
    937  nsCOMPtr<Document> doc = opener->GetDoc();
    938  NS_ADDREF(*aTriggeringPrincipal = doc->NodePrincipal());
    939 
    940  nsCOMPtr<nsIPolicyContainer> policyContainer = doc->GetPolicyContainer();
    941  if (policyContainer) {
    942    policyContainer.forget(aPolicyContainer);
    943  }
    944 
    945  nsCOMPtr<nsIURI> baseURI = doc->GetDocBaseURI();
    946  if (!baseURI) {
    947    NS_ERROR("Document didn't return a base URI");
    948    return NS_ERROR_FAILURE;
    949  }
    950 
    951  if (!referrerInfo) {
    952    referrerInfo = new ReferrerInfo(*doc);
    953  }
    954 
    955  referrerInfo.swap(*aReferrerInfo);
    956  return NS_OK;
    957 }
    958 
    959 nsresult ContentChild::ProvideWindowCommon(
    960    NotNull<BrowserChild*> aTabOpener, nsIOpenWindowInfo* aOpenWindowInfo,
    961    uint32_t aChromeFlags, bool aCalledFromJS, nsIURI* aURI,
    962    const nsAString& aName, const nsACString& aFeatures,
    963    const UserActivation::Modifiers& aModifiers, bool aForceNoOpener,
    964    bool aForceNoReferrer, bool aIsPopupRequested,
    965    nsDocShellLoadState* aLoadState, bool* aWindowIsNew,
    966    BrowsingContext** aReturn) {
    967  MOZ_ASSERT(aOpenWindowInfo, "Must have openwindowinfo");
    968 
    969  *aReturn = nullptr;
    970 
    971  nsAutoCString features(aFeatures);
    972  nsAutoString name(aName);
    973 
    974  nsresult rv;
    975 
    976  RefPtr<BrowsingContext> parent = aOpenWindowInfo->GetParent();
    977  MOZ_DIAGNOSTIC_ASSERT(parent, "We must have a parent BC");
    978 
    979  // Block the attempt to open a new window if the opening BrowsingContext is
    980  // not marked to use remote tabs. This ensures that the newly opened window is
    981  // correctly remote.
    982  if (NS_WARN_IF(!parent->UseRemoteTabs())) {
    983    return NS_ERROR_ABORT;
    984  }
    985 
    986  bool useRemoteSubframes =
    987      aChromeFlags & nsIWebBrowserChrome::CHROME_FISSION_WINDOW;
    988 
    989  uint32_t parentSandboxFlags = parent->SandboxFlags();
    990  Document* doc = parent->GetDocument();
    991  if (doc) {
    992    parentSandboxFlags = doc->GetSandboxFlags();
    993  }
    994 
    995  const bool isForPrinting = aOpenWindowInfo->GetIsForPrinting();
    996  // Certain conditions complicate the process of creating the new
    997  // BrowsingContext, and prevent us from using the
    998  // "CreateWindowInDifferentProcess" codepath.
    999  //  * With Fission enabled, process selection will happen during the load, so
   1000  //    switching processes eagerly will not provide a benefit.
   1001  //  * Windows created for printing must be created within the current process
   1002  //    so that a static clone of the source document can be created.
   1003  //  * Sandboxed popups require the full window creation codepath.
   1004  //  * Loads with form or POST data require the full window creation codepath.
   1005  const bool cannotLoadInDifferentProcess =
   1006      useRemoteSubframes || isForPrinting ||
   1007      (parentSandboxFlags &
   1008       SANDBOX_PROPAGATES_TO_AUXILIARY_BROWSING_CONTEXTS) ||
   1009      (aLoadState &&
   1010       (aLoadState->IsFormSubmission() || aLoadState->PostDataStream()));
   1011  if (!cannotLoadInDifferentProcess) {
   1012    // If we're in a content process and we have noopener set, there's no reason
   1013    // to load in our process, so let's load it elsewhere!
   1014    bool loadInDifferentProcess =
   1015        aForceNoOpener && StaticPrefs::dom_noopener_newprocess_enabled();
   1016    if (loadInDifferentProcess) {
   1017      nsCOMPtr<nsIPrincipal> triggeringPrincipal;
   1018      nsCOMPtr<nsIPolicyContainer> policyContainer;
   1019      nsCOMPtr<nsIReferrerInfo> referrerInfo;
   1020      rv = GetCreateWindowParams(aOpenWindowInfo, aLoadState, aForceNoReferrer,
   1021                                 getter_AddRefs(referrerInfo),
   1022                                 getter_AddRefs(triggeringPrincipal),
   1023                                 getter_AddRefs(policyContainer));
   1024      if (NS_WARN_IF(NS_FAILED(rv))) {
   1025        return rv;
   1026      }
   1027 
   1028      if (name.LowerCaseEqualsLiteral("_blank")) {
   1029        name.Truncate();
   1030      }
   1031 
   1032      MOZ_DIAGNOSTIC_ASSERT(!nsContentUtils::IsSpecialName(name));
   1033 
   1034      const bool hasValidUserGestureActivation = [aLoadState, doc] {
   1035        if (aLoadState) {
   1036          return aLoadState->HasValidUserGestureActivation();
   1037        }
   1038        if (doc) {
   1039          return doc->HasValidTransientUserGestureActivation();
   1040        }
   1041        return false;
   1042      }();
   1043 
   1044      const bool textDirectiveUserActivation = [aLoadState, doc] {
   1045        if (doc && doc->ConsumeTextDirectiveUserActivation()) {
   1046          return true;
   1047        }
   1048        if (aLoadState) {
   1049          return aLoadState->GetTextDirectiveUserActivation();
   1050        }
   1051        return false;
   1052      }() || hasValidUserGestureActivation;
   1053 
   1054      (void)SendCreateWindowInDifferentProcess(
   1055          aTabOpener, parent, aChromeFlags, aCalledFromJS,
   1056          aOpenWindowInfo->GetIsTopLevelCreatedByWebContent(), aURI, features,
   1057          aModifiers, name, triggeringPrincipal, policyContainer, referrerInfo,
   1058          aOpenWindowInfo->GetOriginAttributes(), hasValidUserGestureActivation,
   1059          textDirectiveUserActivation);
   1060 
   1061      // We return NS_ERROR_ABORT, so that the caller knows that we've abandoned
   1062      // the window open as far as it is concerned.
   1063      return NS_ERROR_ABORT;
   1064    }
   1065  }
   1066 
   1067  TabId tabId(nsContentUtils::GenerateTabId());
   1068 
   1069  // We need to assign a TabGroup to the PBrowser actor before we send it to the
   1070  // parent. Otherwise, the parent could send messages to us before we have a
   1071  // proper TabGroup for that actor.
   1072  RefPtr<BrowsingContext> openerBC;
   1073  if (!aForceNoOpener) {
   1074    openerBC = parent;
   1075  }
   1076 
   1077  RefPtr<BrowsingContext> browsingContext = BrowsingContext::CreateDetached(
   1078      nullptr, openerBC, nullptr, aName, BrowsingContext::Type::Content,
   1079      BrowsingContext::CreateDetachedOptions{
   1080          .isPopupRequested = aIsPopupRequested,
   1081          .topLevelCreatedByWebContent = true,
   1082          .isForPrinting = isForPrinting,
   1083      });
   1084  MOZ_ALWAYS_SUCCEEDS(browsingContext->SetRemoteTabs(true));
   1085  MOZ_ALWAYS_SUCCEEDS(browsingContext->SetRemoteSubframes(useRemoteSubframes));
   1086  MOZ_ALWAYS_SUCCEEDS(browsingContext->SetOriginAttributes(
   1087      aOpenWindowInfo->GetOriginAttributes()));
   1088 
   1089  browsingContext->InitPendingInitialization(true);
   1090  auto unsetPending = MakeScopeExit([browsingContext]() {
   1091    (void)browsingContext->SetPendingInitialization(false);
   1092  });
   1093 
   1094  browsingContext->EnsureAttached();
   1095 
   1096  // Since bug 543435, aOpenWindowInfo has the right principal to load for the
   1097  // initial document. But creating windows is complicated and our code expects
   1098  // to setup the initial window global and browser pairs before the document.
   1099  // But without a document and window, we cannot use the
   1100  // WindowGlobalActor::WindowInitializer to correctly initialize a window
   1101  // global. So we must use the AboutBlankInitializer to create a dummy window
   1102  // global with corresponding document and window. Then we immediately set the
   1103  // correct principal which causes the creation of a new document, window and
   1104  // window global. These use the dummy window to correctly initialize the
   1105  // window global via a WindowInitializer.
   1106  nsCOMPtr<nsIPrincipal> initialPrincipal =
   1107      NullPrincipal::Create(browsingContext->OriginAttributesRef());
   1108  WindowGlobalInit windowInit = WindowGlobalActor::AboutBlankInitializer(
   1109      browsingContext, initialPrincipal);
   1110  nsCOMPtr<nsIOpenWindowInfo> openWindowInfoInitialPrincipal;
   1111  // Init code expects window global and open window info to have matching
   1112  // principals.
   1113  aOpenWindowInfo->CloneWithPrincipals(
   1114      initialPrincipal, initialPrincipal,
   1115      getter_AddRefs(openWindowInfoInitialPrincipal));
   1116 
   1117  RefPtr<WindowGlobalChild> windowChild =
   1118      WindowGlobalChild::CreateDisconnected(windowInit);
   1119  if (NS_WARN_IF(!windowChild)) {
   1120    return NS_ERROR_ABORT;
   1121  }
   1122 
   1123  auto newChild = MakeNotNull<RefPtr<BrowserChild>>(
   1124      this, tabId, *aTabOpener, browsingContext, aChromeFlags,
   1125      /* aIsTopLevel */ true);
   1126 
   1127  if (IsShuttingDown()) {
   1128    return NS_ERROR_ABORT;
   1129  }
   1130 
   1131  // Open a remote endpoint for our PBrowser actor.
   1132  ManagedEndpoint<PBrowserParent> parentEp = OpenPBrowserEndpoint(newChild);
   1133  if (NS_WARN_IF(!parentEp.IsValid())) {
   1134    return NS_ERROR_ABORT;
   1135  }
   1136 
   1137  // Open a remote endpoint for our PWindowGlobal actor.
   1138  ManagedEndpoint<PWindowGlobalParent> windowParentEp =
   1139      newChild->OpenPWindowGlobalEndpoint(windowChild);
   1140  if (NS_WARN_IF(!windowParentEp.IsValid())) {
   1141    return NS_ERROR_ABORT;
   1142  }
   1143 
   1144  // Tell the parent process to set up its PBrowserParent.
   1145  PopupIPCTabContext ipcContext(aTabOpener, 0);
   1146  if (NS_WARN_IF(!SendConstructPopupBrowser(
   1147          std::move(parentEp), std::move(windowParentEp), tabId, ipcContext,
   1148          windowInit, aChromeFlags))) {
   1149    return NS_ERROR_ABORT;
   1150  }
   1151 
   1152  windowChild->Init();
   1153  auto guardNullWindowGlobal = MakeScopeExit([&] {
   1154    if (!windowChild->GetWindowGlobal()) {
   1155      windowChild->Destroy();
   1156    }
   1157  });
   1158 
   1159  // Now that |newChild| has had its IPC link established, call |Init| to set it
   1160  // up.
   1161  // XXX: This MOZ_KnownLive is only necessary because the static analysis can't
   1162  // tell that NotNull<RefPtr<BrowserChild>> is a strong pointer.
   1163  RefPtr<nsPIDOMWindowOuter> parentWindow =
   1164      parent ? parent->GetDOMWindow() : nullptr;
   1165  if (NS_FAILED(MOZ_KnownLive(newChild)->Init(
   1166          parentWindow, windowChild, openWindowInfoInitialPrincipal))) {
   1167    return NS_ERROR_ABORT;
   1168  }
   1169 
   1170  // Now change the principal to what it should be according to aOpenWindowInfo.
   1171  // This creates a new document and the timing is quite fragile.
   1172  NS_ENSURE_TRUE(browsingContext->GetDOMWindow(), NS_ERROR_ABORT);
   1173  NS_ENSURE_TRUE(browsingContext->GetDOMWindow()->GetExtantDoc(),
   1174                 NS_ERROR_ABORT);
   1175  browsingContext->GetDOMWindow()->SetInitialPrincipal(
   1176      aOpenWindowInfo->PrincipalToInheritForAboutBlank());
   1177 
   1178  // Set to true when we're ready to return from this function.
   1179  bool ready = false;
   1180 
   1181  // NOTE: Capturing by reference here is safe, as this function won't return
   1182  // until one of these callbacks is called.
   1183  auto resolve = [&](CreatedWindowInfo&& info) {
   1184    MOZ_RELEASE_ASSERT(NS_IsMainThread());
   1185    rv = info.rv();
   1186    *aWindowIsNew = info.windowOpened();
   1187    nsTArray<FrameScriptInfo> frameScripts(std::move(info.frameScripts()));
   1188    uint32_t maxTouchPoints = info.maxTouchPoints();
   1189    DimensionInfo dimensionInfo = std::move(info.dimensions());
   1190 
   1191    // Once this function exits, we should try to exit the nested event loop.
   1192    ready = true;
   1193 
   1194    // NOTE: We have to handle this immediately in the resolve callback in order
   1195    // to make sure that we don't process any more IPC messages before returning
   1196    // from ProvideWindowCommon.
   1197 
   1198    // Handle the error which we got back from the parent process, if we got
   1199    // one.
   1200    if (NS_FAILED(rv)) {
   1201      return;
   1202    }
   1203 
   1204    if (!*aWindowIsNew) {
   1205      rv = NS_ERROR_ABORT;
   1206      return;
   1207    }
   1208 
   1209    // If the BrowserChild has been torn down, we don't need to do this anymore.
   1210    if (NS_WARN_IF(!newChild->IPCOpen() || newChild->IsDestroyed())) {
   1211      rv = NS_ERROR_ABORT;
   1212      return;
   1213    }
   1214 
   1215    ParentShowInfo showInfo(u""_ns, /* fakeShowInfo = */ true,
   1216                            /* isTransparent = */ false,
   1217                            newChild->WebWidget()->GetDPI(),
   1218                            newChild->WebWidget()->RoundsWidgetCoordinatesTo(),
   1219                            newChild->WebWidget()->GetDefaultScale().scale);
   1220 
   1221    newChild->SetMaxTouchPoints(maxTouchPoints);
   1222 
   1223    if (aForceNoOpener || !parent) {
   1224      MOZ_DIAGNOSTIC_ASSERT(!browsingContext->HadOriginalOpener());
   1225      MOZ_DIAGNOSTIC_ASSERT(browsingContext->GetTopLevelCreatedByWebContent());
   1226      MOZ_DIAGNOSTIC_ASSERT(browsingContext->GetOpenerId() == 0);
   1227    } else {
   1228      MOZ_DIAGNOSTIC_ASSERT(browsingContext->HadOriginalOpener());
   1229      MOZ_DIAGNOSTIC_ASSERT(browsingContext->GetTopLevelCreatedByWebContent());
   1230      MOZ_DIAGNOSTIC_ASSERT(browsingContext->GetOpenerId() == parent->Id());
   1231    }
   1232 
   1233    // Unfortunately we don't get a window unless we've shown the frame.  That's
   1234    // pretty bogus; see bug 763602.
   1235    newChild->DoFakeShow(showInfo);
   1236 
   1237    newChild->RecvUpdateDimensions(dimensionInfo);
   1238 
   1239    for (size_t i = 0; i < frameScripts.Length(); i++) {
   1240      FrameScriptInfo& info = frameScripts[i];
   1241      if (!newChild->RecvLoadRemoteScript(info.url(),
   1242                                          info.runInGlobalScope())) {
   1243        MOZ_CRASH();
   1244      }
   1245    }
   1246 
   1247    if (xpc::IsInAutomation()) {
   1248      if (nsCOMPtr<nsPIDOMWindowOuter> outer =
   1249              do_GetInterface(newChild->WebNavigation())) {
   1250        nsCOMPtr<nsIObserverService> obs(services::GetObserverService());
   1251        obs->NotifyObservers(
   1252            outer, "dangerous:test-only:new-browser-child-ready", nullptr);
   1253      }
   1254    }
   1255 
   1256    browsingContext.forget(aReturn);
   1257  };
   1258 
   1259  // NOTE: Capturing by reference here is safe, as this function won't return
   1260  // until one of these callbacks is called.
   1261  auto reject = [&](ResponseRejectReason) {
   1262    MOZ_RELEASE_ASSERT(NS_IsMainThread());
   1263    NS_WARNING("windowCreated promise rejected");
   1264    rv = NS_ERROR_NOT_AVAILABLE;
   1265    ready = true;
   1266  };
   1267 
   1268  // Send down the request to open the window.
   1269  nsCOMPtr<nsIPrincipal> triggeringPrincipal;
   1270  nsCOMPtr<nsIPolicyContainer> policyContainer;
   1271  nsCOMPtr<nsIReferrerInfo> referrerInfo;
   1272  rv = GetCreateWindowParams(aOpenWindowInfo, aLoadState, aForceNoReferrer,
   1273                             getter_AddRefs(referrerInfo),
   1274                             getter_AddRefs(triggeringPrincipal),
   1275                             getter_AddRefs(policyContainer));
   1276  if (NS_WARN_IF(NS_FAILED(rv))) {
   1277    return rv;
   1278  }
   1279 
   1280  SendCreateWindow(
   1281      aTabOpener, parent, newChild, aChromeFlags, aCalledFromJS,
   1282      aOpenWindowInfo->GetIsForPrinting(),
   1283      aOpenWindowInfo->GetIsForWindowDotPrint(),
   1284      aOpenWindowInfo->GetIsTopLevelCreatedByWebContent(), aURI, features,
   1285      aModifiers, triggeringPrincipal, policyContainer, referrerInfo,
   1286      aOpenWindowInfo->GetOriginAttributes(),
   1287      aLoadState ? aLoadState->HasValidUserGestureActivation() : false,
   1288      aLoadState ? aLoadState->GetTextDirectiveUserActivation() : false,
   1289      std::move(resolve), std::move(reject));
   1290 
   1291  // =======================
   1292  // Begin Nested Event Loop
   1293  // =======================
   1294 
   1295  // We have to wait for a response from SendCreateWindow or with information
   1296  // we're going to need to return from this function, So we spin a nested event
   1297  // loop until they get back to us.
   1298 
   1299  {
   1300    // Suppress event handling for all contexts in our BrowsingContextGroup so
   1301    // that event handlers cannot target our new window while it's still being
   1302    // opened. Note that pending events that were suppressed while our blocker
   1303    // was active will be dispatched asynchronously from a runnable dispatched
   1304    // to the main event loop after this function returns, not immediately when
   1305    // we leave this scope.
   1306    AutoSuppressEventHandlingAndSuspend seh(browsingContext->Group());
   1307 
   1308    AutoNoJSAPI nojsapi;
   1309 
   1310    // Spin the event loop until we get a response. Callers of this function
   1311    // already have to guard against an inner event loop spinning in the
   1312    // non-e10s case because of the need to spin one to create a new chrome
   1313    // window.
   1314    SpinEventLoopUntil("ContentChild::ProvideWindowCommon"_ns,
   1315                       [&]() { return ready; });
   1316    MOZ_RELEASE_ASSERT(ready,
   1317                       "We are on the main thread, so we should not exit this "
   1318                       "loop without ready being true.");
   1319  }
   1320 
   1321  // =====================
   1322  // End Nested Event Loop
   1323  // =====================
   1324 
   1325  // It's possible for our new BrowsingContext to become discarded during the
   1326  // nested event loop, in which case we shouldn't return it, since our callers
   1327  // will generally not be prepared to deal with that.
   1328  if (*aReturn && (*aReturn)->IsDiscarded()) {
   1329    NS_RELEASE(*aReturn);
   1330    return NS_ERROR_ABORT;
   1331  }
   1332 
   1333  // We should have the results already set by the callbacks.
   1334  MOZ_ASSERT_IF(NS_SUCCEEDED(rv), *aReturn);
   1335  return rv;
   1336 }
   1337 
   1338 bool ContentChild::IsAlive() const { return mIsAlive; }
   1339 
   1340 bool ContentChild::IsShuttingDown() const { return mShuttingDown; }
   1341 
   1342 void ContentChild::GetProcessName(nsACString& aName) const {
   1343  aName = mProcessName;
   1344 }
   1345 
   1346 /* static */
   1347 void ContentChild::AppendProcessId(nsACString& aName) {
   1348  if (!aName.IsEmpty()) {
   1349    aName.Append(' ');
   1350  }
   1351  unsigned pid = getpid();
   1352  aName.Append(nsPrintfCString("(pid %u)", pid));
   1353 }
   1354 
   1355 void ContentChild::InitGraphicsDeviceData(const ContentDeviceData& aData) {
   1356  gfxPlatform::InitChild(aData);
   1357 }
   1358 
   1359 void ContentChild::InitSharedUASheets(
   1360    Maybe<mozilla::ipc::ReadOnlySharedMemoryHandle>&& aHandle,
   1361    uintptr_t aAddress) {
   1362  MOZ_ASSERT_IF(!aHandle, !aAddress);
   1363 
   1364  if (!aAddress) {
   1365    return;
   1366  }
   1367 
   1368  // Map the shared memory storing the user agent style sheets.  Do this as
   1369  // early as possible to maximize the chance of being able to map at the
   1370  // address we want.
   1371  GlobalStyleSheetCache::SetSharedMemory(std::move(*aHandle), aAddress);
   1372 }
   1373 
   1374 void ContentChild::InitXPCOM(
   1375    XPCOMInitData&& aXPCOMInit,
   1376    const mozilla::dom::ipc::StructuredCloneData& aInitialData,
   1377    bool aIsReadyForBackgroundProcessing) {
   1378 #if defined(XP_WIN)
   1379  // DLL services untrusted modules processing depends on
   1380  // BackgroundChild::Startup having been called
   1381  RefPtr<DllServices> dllSvc(DllServices::Get());
   1382  dllSvc->StartUntrustedModulesProcessor(aIsReadyForBackgroundProcessing);
   1383 #endif  // defined(XP_WIN)
   1384 
   1385  PBackgroundChild* actorChild = BackgroundChild::GetOrCreateForCurrentThread();
   1386  if (NS_WARN_IF(!actorChild)) {
   1387    MOZ_ASSERT_UNREACHABLE("PBackground init can't fail at this point");
   1388    return;
   1389  }
   1390 
   1391  ClientManager::Startup();
   1392 
   1393  // RemoteWorkerService will be initialized in RecvRemoteType, to avoid to
   1394  // register it to the RemoteWorkerManager while it is still a prealloc
   1395  // remoteType and defer it to the point the child process is assigned a.
   1396  // actual remoteType.
   1397 
   1398  nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
   1399  if (!svc) {
   1400    NS_WARNING("Couldn't acquire console service");
   1401    return;
   1402  }
   1403 
   1404  mConsoleListener = new ConsoleListener(this);
   1405  if (NS_FAILED(svc->RegisterListener(mConsoleListener)))
   1406    NS_WARNING("Couldn't register console listener for child process");
   1407 
   1408  mAvailableDictionaries = std::move(aXPCOMInit.dictionaries());
   1409 
   1410  RecvSetOffline(aXPCOMInit.isOffline());
   1411  RecvSetConnectivity(aXPCOMInit.isConnected());
   1412 
   1413  OSPreferences::GetInstance()->AssignSysLocales(aXPCOMInit.sysLocales());
   1414 
   1415  LocaleService::GetInstance()->AssignAppLocales(aXPCOMInit.appLocales());
   1416  LocaleService::GetInstance()->AssignRequestedLocales(
   1417      aXPCOMInit.requestedLocales());
   1418 
   1419  L10nRegistry::RegisterFileSourcesFromParentProcess(
   1420      aXPCOMInit.l10nFileSources());
   1421 
   1422  RecvSetCaptivePortalState(aXPCOMInit.captivePortalState());
   1423  RecvBidiKeyboardNotify(aXPCOMInit.isLangRTL(),
   1424                         aXPCOMInit.haveBidiKeyboards());
   1425 
   1426  if (aXPCOMInit.domainPolicy().active()) {
   1427    nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
   1428    MOZ_ASSERT(ssm);
   1429    ssm->ActivateDomainPolicyInternal(getter_AddRefs(mPolicy));
   1430    if (!mPolicy) {
   1431      MOZ_CRASH("Failed to activate domain policy.");
   1432    }
   1433    mPolicy->ApplyClone(&aXPCOMInit.domainPolicy());
   1434  }
   1435 
   1436  nsCOMPtr<nsIClipboard> clipboard(
   1437      do_GetService("@mozilla.org/widget/clipboard;1"));
   1438  if (nsCOMPtr<nsIClipboardProxy> clipboardProxy =
   1439          do_QueryInterface(clipboard)) {
   1440    clipboardProxy->SetCapabilities(aXPCOMInit.clipboardCaps());
   1441  }
   1442 
   1443  {
   1444    AutoJSAPI jsapi;
   1445    if (NS_WARN_IF(!jsapi.Init(xpc::PrivilegedJunkScope()))) {
   1446      MOZ_CRASH();
   1447    }
   1448    ErrorResult rv;
   1449    JS::Rooted<JS::Value> data(jsapi.cx());
   1450    mozilla::dom::ipc::StructuredCloneData id;
   1451    id.Copy(aInitialData);
   1452    id.Read(jsapi.cx(), &data, rv);
   1453    if (NS_WARN_IF(rv.Failed())) {
   1454      MOZ_CRASH();
   1455    }
   1456    auto* global = ContentProcessMessageManager::Get();
   1457    global->SetInitialProcessData(data);
   1458  }
   1459 
   1460  // The stylesheet cache is not ready yet. Store this URL for future use.
   1461  nsCOMPtr<nsIURI> ucsURL = std::move(aXPCOMInit.userContentSheetURL());
   1462  GlobalStyleSheetCache::SetUserContentCSSURL(ucsURL);
   1463 
   1464  GfxInfoBase::SetFeatureStatus(std::move(aXPCOMInit.gfxFeatureStatus()));
   1465 
   1466  // Initialize the RemoteMediaManager thread and its associated PBackground
   1467  // channel.
   1468  RemoteMediaManagerChild::Init();
   1469 
   1470  Preferences::RegisterCallbackAndCall(&OnFissionBlocklistPrefChange,
   1471                                       kFissionEnforceBlockList);
   1472  Preferences::RegisterCallbackAndCall(&OnFissionBlocklistPrefChange,
   1473                                       kFissionOmitBlockListValues);
   1474 
   1475  // Set the dynamic scalar definitions for this process.
   1476  TelemetryIPC::AddDynamicScalarDefinitions(aXPCOMInit.dynamicScalarDefs());
   1477 }
   1478 
   1479 mozilla::ipc::IPCResult ContentChild::RecvRequestMemoryReport(
   1480    const uint32_t& aGeneration, const bool& aAnonymize,
   1481    const bool& aMinimizeMemoryUsage,
   1482    const Maybe<mozilla::ipc::FileDescriptor>& aDMDFile,
   1483    const RequestMemoryReportResolver& aResolver) {
   1484  nsCString process;
   1485  if (aAnonymize || mRemoteType.IsEmpty()) {
   1486    GetProcessName(process);
   1487  } else {
   1488    process = mRemoteType;
   1489  }
   1490  AppendProcessId(process);
   1491  MOZ_ASSERT(!process.IsEmpty());
   1492 
   1493  MemoryReportRequestClient::Start(
   1494      aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, process,
   1495      [&](const MemoryReport& aReport) {
   1496        (void)GetSingleton()->SendAddMemoryReport(aReport);
   1497      },
   1498      aResolver);
   1499  return IPC_OK();
   1500 }
   1501 
   1502 mozilla::ipc::IPCResult ContentChild::RecvDecodeImage(
   1503    NotNull<nsIURI*> aURI, const ImageIntSize& aSize,
   1504    DecodeImageResolver&& aResolver) {
   1505  auto size = aSize.ToUnknownSize();
   1506  // TODO(Bug 1999930): Investigate using  a content-principal for
   1507  // moz-remote-image: requests
   1508  image::FetchDecodedImage(aURI, size, nsContentUtils::GetSystemPrincipal())
   1509      ->Then(
   1510          GetCurrentSerialEventTarget(), __func__,
   1511          [size, aResolver](already_AddRefed<imgIContainer> aImage) {
   1512            using Result = std::tuple<nsresult, mozilla::Maybe<IPCImage>>;
   1513 
   1514            nsCOMPtr<imgIContainer> image(std::move(aImage));
   1515 
   1516            const int32_t flags = imgIContainer::FLAG_SYNC_DECODE |
   1517                                  imgIContainer::FLAG_ASYNC_NOTIFY;
   1518            RefPtr<gfx::SourceSurface> surface;
   1519            if (size.Width() && size.Height()) {
   1520              surface = image->GetFrameAtSize(size, imgIContainer::FRAME_FIRST,
   1521                                              flags);
   1522              if (surface && surface->GetSize() != size) {
   1523                surface = gfxUtils::ScaleSourceSurface(*surface, size);
   1524              }
   1525            } else {
   1526              surface = image->GetFrame(imgIContainer::FRAME_FIRST, flags);
   1527            }
   1528 
   1529            if (!surface) {
   1530              aResolver(Result(NS_ERROR_FAILURE, Nothing()));
   1531              return;
   1532            }
   1533 
   1534            if (RefPtr<gfx::DataSourceSurface> dataSurface =
   1535                    surface->GetDataSurface()) {
   1536              if (Maybe<IPCImage> image =
   1537                      nsContentUtils::SurfaceToIPCImage(*dataSurface)) {
   1538                aResolver(Result(NS_OK, std::move(image)));
   1539                return;
   1540              }
   1541            }
   1542 
   1543            aResolver(Result(NS_ERROR_FAILURE, Nothing()));
   1544            return;
   1545          },
   1546          [aResolver](nsresult aStatus) {
   1547            aResolver(std::tuple<nsresult, mozilla::Maybe<IPCImage>>(
   1548                aStatus, Nothing()));
   1549          });
   1550 
   1551  return IPC_OK();
   1552 }
   1553 
   1554 #if defined(XP_WIN)
   1555 mozilla::ipc::IPCResult ContentChild::RecvGetUntrustedModulesData(
   1556    GetUntrustedModulesDataResolver&& aResolver) {
   1557  RefPtr<DllServices> dllSvc(DllServices::Get());
   1558  dllSvc->GetUntrustedModulesData()->Then(
   1559      GetMainThreadSerialEventTarget(), __func__,
   1560      [aResolver](Maybe<UntrustedModulesData>&& aData) {
   1561        aResolver(std::move(aData));
   1562      },
   1563      [aResolver](nsresult aReason) { aResolver(Nothing()); });
   1564  return IPC_OK();
   1565 }
   1566 
   1567 mozilla::ipc::IPCResult ContentChild::RecvUnblockUntrustedModulesThread() {
   1568  if (nsCOMPtr<nsIObserverService> obs =
   1569          mozilla::services::GetObserverService()) {
   1570    obs->NotifyObservers(nullptr, "unblock-untrusted-modules-thread", nullptr);
   1571  }
   1572  return IPC_OK();
   1573 }
   1574 #endif  // defined(XP_WIN)
   1575 
   1576 PCycleCollectWithLogsChild* ContentChild::AllocPCycleCollectWithLogsChild(
   1577    const bool& aDumpAllTraces, const FileDescriptor& aGCLog,
   1578    const FileDescriptor& aCCLog) {
   1579  return do_AddRef(new CycleCollectWithLogsChild()).take();
   1580 }
   1581 
   1582 mozilla::ipc::IPCResult ContentChild::RecvPCycleCollectWithLogsConstructor(
   1583    PCycleCollectWithLogsChild* aActor, const bool& aDumpAllTraces,
   1584    const FileDescriptor& aGCLog, const FileDescriptor& aCCLog) {
   1585  // The sink's destructor is called when the last reference goes away, which
   1586  // will cause the actor to be closed down.
   1587  auto* actor = static_cast<CycleCollectWithLogsChild*>(aActor);
   1588  RefPtr<CycleCollectWithLogsChild::Sink> sink =
   1589      new CycleCollectWithLogsChild::Sink(actor, aGCLog, aCCLog);
   1590 
   1591  // Invoke the dumper, which will take a reference to the sink.
   1592  nsCOMPtr<nsIMemoryInfoDumper> dumper =
   1593      do_GetService("@mozilla.org/memory-info-dumper;1");
   1594  dumper->DumpGCAndCCLogsToSink(aDumpAllTraces, sink);
   1595  return IPC_OK();
   1596 }
   1597 
   1598 bool ContentChild::DeallocPCycleCollectWithLogsChild(
   1599    PCycleCollectWithLogsChild* aActor) {
   1600  RefPtr<CycleCollectWithLogsChild> actor =
   1601      dont_AddRef(static_cast<CycleCollectWithLogsChild*>(aActor));
   1602  return true;
   1603 }
   1604 
   1605 mozilla::ipc::IPCResult ContentChild::RecvInitGMPService(
   1606    Endpoint<PGMPServiceChild>&& aGMPService) {
   1607  if (!GMPServiceChild::Create(std::move(aGMPService))) {
   1608    return IPC_FAIL_NO_REASON(this);
   1609  }
   1610  return IPC_OK();
   1611 }
   1612 
   1613 mozilla::ipc::IPCResult ContentChild::RecvInitProfiler(
   1614    Endpoint<PProfilerChild>&& aEndpoint) {
   1615  mProfilerController = ChildProfilerController::Create(std::move(aEndpoint));
   1616  return IPC_OK();
   1617 }
   1618 
   1619 mozilla::ipc::IPCResult ContentChild::RecvGMPsChanged(
   1620    nsTArray<GMPCapabilityData>&& capabilities) {
   1621  GeckoMediaPluginServiceChild::UpdateGMPCapabilities(std::move(capabilities));
   1622  return IPC_OK();
   1623 }
   1624 
   1625 mozilla::ipc::IPCResult ContentChild::RecvInitProcessHangMonitor(
   1626    Endpoint<PProcessHangMonitorChild>&& aHangMonitor) {
   1627  CreateHangMonitorChild(std::move(aHangMonitor));
   1628  return IPC_OK();
   1629 }
   1630 
   1631 mozilla::ipc::IPCResult ContentChild::GetResultForRenderingInitFailure(
   1632    GeckoChildID aOtherChildID) {
   1633  if (aOtherChildID == XRE_GetChildID() || aOtherChildID == OtherChildID()) {
   1634    // If we are talking to ourselves, or the UI process, then that is a fatal
   1635    // protocol error.
   1636    return IPC_FAIL_NO_REASON(this);
   1637  }
   1638 
   1639  // If we are talking to the GPU process, then we should recover from this on
   1640  // the next ContentChild::RecvReinitRendering call.
   1641  gfxCriticalNote << "Could not initialize rendering with GPU process";
   1642  return IPC_OK();
   1643 }
   1644 
   1645 #if defined(XP_MACOSX)
   1646 extern "C" {
   1647 void CGSShutdownServerConnections();
   1648 };
   1649 #endif
   1650 
   1651 mozilla::ipc::IPCResult ContentChild::RecvInitRendering(
   1652    Endpoint<PCompositorManagerChild>&& aCompositor,
   1653    Endpoint<PImageBridgeChild>&& aImageBridge,
   1654    Endpoint<PVRManagerChild>&& aVRBridge,
   1655    Endpoint<PRemoteMediaManagerChild>&& aVideoManager,
   1656    nsTArray<uint32_t>&& namespaces) {
   1657  MOZ_ASSERT(namespaces.Length() == 3);
   1658 
   1659  // Note that for all of the methods below, if it can fail, it should only
   1660  // return false if the failure is an IPDL error. In such situations,
   1661  // ContentChild can reason about whether or not to wait for
   1662  // RecvReinitRendering (because we surmised the GPU process crashed), or if it
   1663  // should crash itself (because we are actually talking to the UI process). If
   1664  // there are localized failures (e.g. failed to spawn a thread), then it
   1665  // should MOZ_RELEASE_ASSERT or MOZ_CRASH as necessary instead.
   1666  if (!CompositorManagerChild::Init(std::move(aCompositor), namespaces[0])) {
   1667    return GetResultForRenderingInitFailure(aCompositor.OtherChildID());
   1668  }
   1669  if (!CompositorManagerChild::CreateContentCompositorBridge(namespaces[1])) {
   1670    return GetResultForRenderingInitFailure(aCompositor.OtherChildID());
   1671  }
   1672  if (!ImageBridgeChild::InitForContent(std::move(aImageBridge),
   1673                                        namespaces[2])) {
   1674    return GetResultForRenderingInitFailure(aImageBridge.OtherChildID());
   1675  }
   1676  if (!gfx::VRManagerChild::InitForContent(std::move(aVRBridge))) {
   1677    return GetResultForRenderingInitFailure(aVRBridge.OtherChildID());
   1678  }
   1679  RemoteMediaManagerChild::InitForGPUProcess(std::move(aVideoManager));
   1680 
   1681 #if defined(XP_MACOSX) && !defined(MOZ_SANDBOX)
   1682  // Close all current connections to the WindowServer. This ensures that the
   1683  // Activity Monitor will not label the content process as "Not responding"
   1684  // because it's not running a native event loop. See bug 1384336. When the
   1685  // build is configured with sandbox support, this is called during sandbox
   1686  // setup.
   1687  CGSShutdownServerConnections();
   1688 #endif
   1689 
   1690  return IPC_OK();
   1691 }
   1692 
   1693 mozilla::ipc::IPCResult ContentChild::RecvReinitRendering(
   1694    Endpoint<PCompositorManagerChild>&& aCompositor,
   1695    Endpoint<PImageBridgeChild>&& aImageBridge,
   1696    Endpoint<PVRManagerChild>&& aVRBridge,
   1697    Endpoint<PRemoteMediaManagerChild>&& aVideoManager,
   1698    nsTArray<uint32_t>&& namespaces) {
   1699  MOZ_ASSERT(namespaces.Length() == 3);
   1700  nsTArray<RefPtr<BrowserChild>> tabs = BrowserChild::GetAll();
   1701 
   1702  // Re-establish singleton bridges to the compositor.
   1703  if (!CompositorManagerChild::Init(std::move(aCompositor), namespaces[0])) {
   1704    return GetResultForRenderingInitFailure(aCompositor.OtherChildID());
   1705  }
   1706  if (!CompositorManagerChild::CreateContentCompositorBridge(namespaces[1])) {
   1707    return GetResultForRenderingInitFailure(aCompositor.OtherChildID());
   1708  }
   1709  if (!ImageBridgeChild::ReinitForContent(std::move(aImageBridge),
   1710                                          namespaces[2])) {
   1711    return GetResultForRenderingInitFailure(aImageBridge.OtherChildID());
   1712  }
   1713  if (!gfx::VRManagerChild::InitForContent(std::move(aVRBridge))) {
   1714    return GetResultForRenderingInitFailure(aVRBridge.OtherChildID());
   1715  }
   1716  gfxPlatform::GetPlatform()->CompositorUpdated();
   1717 
   1718  // Establish new PLayerTransactions.
   1719  for (const auto& browserChild : tabs) {
   1720    if (browserChild->GetLayersId().IsValid()) {
   1721      browserChild->ReinitRendering();
   1722    }
   1723  }
   1724 
   1725  // Notify any observers that the compositor has been reinitialized,
   1726  // eg the ZoomConstraintsClients for documents in this process.
   1727  // This must occur after the ReinitRendering call above so that the
   1728  // APZCTreeManagers have been connected.
   1729  nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
   1730  if (observerService) {
   1731    observerService->NotifyObservers(nullptr, "compositor-reinitialized",
   1732                                     nullptr);
   1733  }
   1734 
   1735  RemoteMediaManagerChild::InitForGPUProcess(std::move(aVideoManager));
   1736  return IPC_OK();
   1737 }
   1738 
   1739 mozilla::ipc::IPCResult ContentChild::RecvReinitRenderingForDeviceReset() {
   1740  gfxPlatform::GetPlatform()->CompositorUpdated();
   1741 
   1742  nsTArray<RefPtr<BrowserChild>> tabs = BrowserChild::GetAll();
   1743  for (const auto& browserChild : tabs) {
   1744    if (browserChild->GetLayersId().IsValid()) {
   1745      browserChild->ReinitRenderingForDeviceReset();
   1746    }
   1747  }
   1748  return IPC_OK();
   1749 }
   1750 
   1751 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
   1752 extern "C" {
   1753 CGError CGSSetDenyWindowServerConnections(bool);
   1754 };
   1755 
   1756 static void DisconnectWindowServer(bool aIsSandboxEnabled) {
   1757  // Close all current connections to the WindowServer. This ensures that the
   1758  // Activity Monitor will not label the content process as "Not responding"
   1759  // because it's not running a native event loop. See bug 1384336.
   1760  // This is required with or without the sandbox enabled. Until the
   1761  // window server is blocked as the policy level, this should be called
   1762  // just before CGSSetDenyWindowServerConnections() so there are no
   1763  // windowserver connections active when CGSSetDenyWindowServerConnections()
   1764  // is called.
   1765  CGSShutdownServerConnections();
   1766 
   1767  // Actual security benefits are only achieved when we additionally deny
   1768  // future connections using the sandbox policy. WebGL must be remoted if
   1769  // the windowserver connections are blocked. WebGL remoting is disabled
   1770  // for some tests.
   1771  if (aIsSandboxEnabled &&
   1772      Preferences::GetBool(
   1773          "security.sandbox.content.mac.disconnect-windowserver") &&
   1774      Preferences::GetBool("webgl.out-of-process")) {
   1775    CGError result = CGSSetDenyWindowServerConnections(true);
   1776    MOZ_DIAGNOSTIC_ASSERT(result == kCGErrorSuccess);
   1777 #  if !MOZ_DIAGNOSTIC_ASSERT_ENABLED
   1778    (void)result;
   1779 #  endif
   1780  }
   1781 }
   1782 #endif
   1783 
   1784 mozilla::ipc::IPCResult ContentChild::RecvSetProcessSandbox(
   1785    const Maybe<mozilla::ipc::FileDescriptor>& aBroker) {
   1786  // We may want to move the sandbox initialization somewhere else
   1787  // at some point; see bug 880808.
   1788 #if defined(MOZ_SANDBOX)
   1789 
   1790  bool sandboxEnabled = true;
   1791 #  if defined(XP_LINUX)
   1792  // On Linux, we have to support systems that can't use any sandboxing.
   1793  sandboxEnabled = SandboxInfo::Get().CanSandboxContent();
   1794 
   1795  if (sandboxEnabled && !StaticPrefs::media_cubeb_sandbox()) {
   1796    // Pre-start audio before sandboxing; see bug 1443612.
   1797    (void)CubebUtils::GetCubeb();
   1798  }
   1799 
   1800  if (sandboxEnabled) {
   1801    RegisterProfilerObserversForSandboxProfiler();
   1802    sandboxEnabled = SetContentProcessSandbox(
   1803        ContentProcessSandboxParams::ForThisProcess(aBroker));
   1804  }
   1805 #  elif defined(XP_WIN)
   1806  if (GetEffectiveContentSandboxLevel() > 7) {
   1807    // Libraries required by Network Security Services (NSS).
   1808    ::LoadLibraryW(L"freebl3.dll");
   1809    ::LoadLibraryW(L"softokn3.dll");
   1810    // Cache value that is retrieved from a registry entry.
   1811    (void)GetCpuFrequencyMHz();
   1812  }
   1813  mozilla::SandboxTarget::Instance()->StartSandbox();
   1814 #  elif defined(XP_MACOSX)
   1815  sandboxEnabled = (GetEffectiveContentSandboxLevel() >= 1);
   1816  DisconnectWindowServer(sandboxEnabled);
   1817 #  elif defined(XP_IOS)
   1818  LockdownExtensionKitProcess(ExtensionKitSandboxRevision::Revision1);
   1819 #  endif
   1820 
   1821  CrashReporter::RecordAnnotationBool(
   1822      CrashReporter::Annotation::ContentSandboxEnabled, sandboxEnabled);
   1823 #  if defined(XP_LINUX) && !defined(ANDROID)
   1824  CrashReporter::RecordAnnotationU32(
   1825      CrashReporter::Annotation::ContentSandboxCapabilities,
   1826      SandboxInfo::Get().AsInteger());
   1827 #  endif /* XP_LINUX && !ANDROID */
   1828 #endif   /* MOZ_SANDBOX */
   1829 
   1830  return IPC_OK();
   1831 }
   1832 
   1833 mozilla::ipc::IPCResult ContentChild::RecvBidiKeyboardNotify(
   1834    const bool& aIsLangRTL, const bool& aHaveBidiKeyboards) {
   1835  // bidi is always of type PuppetBidiKeyboard* (because in the child, the only
   1836  // possible implementation of nsIBidiKeyboard is PuppetBidiKeyboard).
   1837  PuppetBidiKeyboard* bidi =
   1838      static_cast<PuppetBidiKeyboard*>(nsContentUtils::GetBidiKeyboard());
   1839  if (bidi) {
   1840    bidi->SetBidiKeyboardInfo(aIsLangRTL, aHaveBidiKeyboards);
   1841  }
   1842  return IPC_OK();
   1843 }
   1844 
   1845 static StaticRefPtr<CancelableRunnable> gFirstIdleTask;
   1846 
   1847 static void FirstIdle(void) {
   1848  MOZ_ASSERT(gFirstIdleTask);
   1849  gFirstIdleTask = nullptr;
   1850 
   1851  ContentChild::GetSingleton()->SendFirstIdle();
   1852 }
   1853 
   1854 mozilla::ipc::IPCResult ContentChild::RecvConstructBrowser(
   1855    ManagedEndpoint<PBrowserChild>&& aBrowserEp,
   1856    ManagedEndpoint<PWindowGlobalChild>&& aWindowEp, const TabId& aTabId,
   1857    const IPCTabContext& aContext, const WindowGlobalInit& aWindowInit,
   1858    const uint32_t& aChromeFlags, const ContentParentId& aCpID,
   1859    const bool& aIsForBrowser, const bool& aIsTopLevel) {
   1860  MOZ_DIAGNOSTIC_ASSERT(!IsShuttingDown());
   1861 
   1862  static bool hasRunOnce = false;
   1863  if (!hasRunOnce) {
   1864    hasRunOnce = true;
   1865    MOZ_ASSERT(!gFirstIdleTask);
   1866    RefPtr<CancelableRunnable> firstIdleTask =
   1867        NewCancelableRunnableFunction("FirstIdleRunnable", FirstIdle);
   1868    gFirstIdleTask = firstIdleTask;
   1869    if (NS_FAILED(NS_DispatchToCurrentThreadQueue(firstIdleTask.forget(),
   1870                                                  EventQueuePriority::Idle))) {
   1871      gFirstIdleTask = nullptr;
   1872      hasRunOnce = false;
   1873    }
   1874  }
   1875 
   1876  RefPtr<BrowsingContext> browsingContext =
   1877      BrowsingContext::Get(aWindowInit.context().mBrowsingContextId);
   1878  if (!browsingContext || browsingContext->IsDiscarded()) {
   1879    nsPrintfCString reason("%s initial %s BrowsingContext",
   1880                           browsingContext ? "discarded" : "missing",
   1881                           aIsTopLevel ? "top" : "frame");
   1882    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Warning, ("%s", reason.get()));
   1883    if (!aIsTopLevel) {
   1884      // Recover if the BrowsingContext is missing for a new subframe. The
   1885      // `ManagedEndpoint` instances will be automatically destroyed.
   1886      NS_WARNING(reason.get());
   1887      return IPC_OK();
   1888    }
   1889 
   1890    // (these are the only possible values of `reason` at this point)
   1891    return browsingContext
   1892               ? IPC_FAIL(this, "discarded initial top BrowsingContext")
   1893               : IPC_FAIL(this, "missing initial top BrowsingContext");
   1894  }
   1895 
   1896  if (xpc::IsInAutomation() &&
   1897      StaticPrefs::
   1898          browser_tabs_remote_testOnly_failPBrowserCreation_enabled()) {
   1899    nsAutoCString idString;
   1900    if (NS_SUCCEEDED(Preferences::GetCString(
   1901            "browser.tabs.remote.testOnly.failPBrowserCreation.browsingContext",
   1902            idString))) {
   1903      nsresult rv = NS_OK;
   1904      uint64_t bcid = idString.ToInteger64(&rv);
   1905      if (NS_SUCCEEDED(rv) && bcid == browsingContext->Id()) {
   1906        NS_WARNING("Injecting artificial PBrowser creation failure");
   1907        return IPC_OK();
   1908      }
   1909    }
   1910  }
   1911 
   1912  if (!aWindowInit.isInitialDocument() ||
   1913      !NS_IsAboutBlank(aWindowInit.documentURI())) {
   1914    return IPC_FAIL(this,
   1915                    "Logic in CreateDocumentViewerForActor currently requires "
   1916                    "actors to be initial about:blank documents");
   1917  }
   1918 
   1919  // We'll happily accept any kind of IPCTabContext here; we don't need to
   1920  // check that it's of a certain type for security purposes, because we
   1921  // believe whatever the parent process tells us.
   1922  MaybeInvalidTabContext tc(aContext);
   1923  if (!tc.IsValid()) {
   1924    NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
   1925                             "the parent process. (%s)  Crashing...",
   1926                             tc.GetInvalidReason())
   1927                 .get());
   1928    MOZ_CRASH("Invalid TabContext received from the parent process.");
   1929  }
   1930 
   1931  RefPtr<WindowGlobalChild> windowChild =
   1932      WindowGlobalChild::CreateDisconnected(aWindowInit);
   1933  if (!windowChild) {
   1934    return IPC_FAIL(this, "Failed to create initial WindowGlobalChild");
   1935  }
   1936 
   1937  RefPtr<BrowserChild> browserChild =
   1938      BrowserChild::Create(this, aTabId, tc.GetTabContext(), browsingContext,
   1939                           aChromeFlags, aIsTopLevel);
   1940 
   1941  // Bind the created BrowserChild to IPC to actually link the actor.
   1942  if (NS_WARN_IF(!BindPBrowserEndpoint(std::move(aBrowserEp), browserChild))) {
   1943    return IPC_FAIL(this, "BindPBrowserEndpoint failed");
   1944  }
   1945 
   1946  if (NS_WARN_IF(!browserChild->BindPWindowGlobalEndpoint(std::move(aWindowEp),
   1947                                                          windowChild))) {
   1948    return IPC_FAIL(this, "BindPWindowGlobalEndpoint failed");
   1949  }
   1950  windowChild->Init();
   1951  auto guardNullWindowGlobal = MakeScopeExit([&] {
   1952    if (!windowChild->GetWindowGlobal()) {
   1953      windowChild->Destroy();
   1954    }
   1955  });
   1956 
   1957  // Ensure that a BrowsingContext is set for our BrowserChild before
   1958  // running `Init`.
   1959  MOZ_RELEASE_ASSERT(browserChild->mBrowsingContext->Id() ==
   1960                     aWindowInit.context().mBrowsingContextId);
   1961 
   1962  RefPtr<nsOpenWindowInfo> openWindowInfo = new nsOpenWindowInfo();
   1963  openWindowInfo->mPrincipalToInheritForAboutBlank = aWindowInit.principal();
   1964  // XXX We should consider moving this to CreateAboutBlankDocumentViewer (bug
   1965  // 2004943)
   1966  openWindowInfo->mPolicyContainerToInheritForAboutBlank =
   1967      new PolicyContainer();
   1968 
   1969  {
   1970    // Block the script runner that notifies about the creation of the script
   1971    // global for the initial about:blank.
   1972    nsAutoScriptBlocker blockScripts;
   1973 
   1974    if (NS_WARN_IF(NS_FAILED(browserChild->Init(
   1975            /* aOpener */ nullptr, windowChild, openWindowInfo)))) {
   1976      return IPC_FAIL(browserChild, "BrowserChild::Init failed");
   1977    }
   1978  }
   1979 
   1980  nsCOMPtr<nsIObserverService> os = services::GetObserverService();
   1981  if (os) {
   1982    os->NotifyObservers(static_cast<nsIBrowserChild*>(browserChild),
   1983                        "tab-child-created", nullptr);
   1984  }
   1985  // Notify parent that we are ready to handle input events.
   1986  browserChild->SendRemoteIsReadyToHandleInputEvents();
   1987  return IPC_OK();
   1988 }
   1989 
   1990 void ContentChild::GetAvailableDictionaries(
   1991    nsTArray<nsCString>& aDictionaries) {
   1992  aDictionaries = mAvailableDictionaries.Clone();
   1993 }
   1994 
   1995 mozilla::PRemoteSpellcheckEngineChild*
   1996 ContentChild::AllocPRemoteSpellcheckEngineChild() {
   1997  MOZ_CRASH(
   1998      "Default Constructor for PRemoteSpellcheckEngineChild should never be "
   1999      "called");
   2000  return nullptr;
   2001 }
   2002 
   2003 bool ContentChild::DeallocPRemoteSpellcheckEngineChild(
   2004    PRemoteSpellcheckEngineChild* child) {
   2005  delete child;
   2006  return true;
   2007 }
   2008 
   2009 mozilla::ipc::IPCResult ContentChild::RecvNotifyEmptyHTTPCache() {
   2010  MOZ_ASSERT(NS_IsMainThread());
   2011  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   2012  obs->NotifyObservers(nullptr, "cacheservice:empty-cache", nullptr);
   2013  return IPC_OK();
   2014 }
   2015 
   2016 PHalChild* ContentChild::AllocPHalChild() { return CreateHalChild(); }
   2017 
   2018 bool ContentChild::DeallocPHalChild(PHalChild* aHal) {
   2019  delete aHal;
   2020  return true;
   2021 }
   2022 
   2023 devtools::PHeapSnapshotTempFileHelperChild*
   2024 ContentChild::AllocPHeapSnapshotTempFileHelperChild() {
   2025  return devtools::HeapSnapshotTempFileHelperChild::Create();
   2026 }
   2027 
   2028 bool ContentChild::DeallocPHeapSnapshotTempFileHelperChild(
   2029    devtools::PHeapSnapshotTempFileHelperChild* aHeapSnapshotHelper) {
   2030  delete aHeapSnapshotHelper;
   2031  return true;
   2032 }
   2033 
   2034 already_AddRefed<PTestShellChild> ContentChild::AllocPTestShellChild() {
   2035  return MakeAndAddRef<TestShellChild>();
   2036 }
   2037 
   2038 mozilla::ipc::IPCResult ContentChild::RecvPTestShellConstructor(
   2039    PTestShellChild* actor) {
   2040  return IPC_OK();
   2041 }
   2042 
   2043 RefPtr<GenericPromise> ContentChild::UpdateCookieStatus(nsIChannel* aChannel) {
   2044  RefPtr<CookieServiceChild> csChild = CookieServiceChild::GetSingleton();
   2045  NS_ASSERTION(csChild, "Couldn't get CookieServiceChild");
   2046 
   2047  return csChild->TrackCookieLoad(aChannel);
   2048 }
   2049 
   2050 PScriptCacheChild* ContentChild::AllocPScriptCacheChild(
   2051    const FileDescOrError& cacheFile, const bool& wantCacheData) {
   2052  return new loader::ScriptCacheChild();
   2053 }
   2054 
   2055 bool ContentChild::DeallocPScriptCacheChild(PScriptCacheChild* cache) {
   2056  delete static_cast<loader::ScriptCacheChild*>(cache);
   2057  return true;
   2058 }
   2059 
   2060 mozilla::ipc::IPCResult ContentChild::RecvPScriptCacheConstructor(
   2061    PScriptCacheChild* actor, const FileDescOrError& cacheFile,
   2062    const bool& wantCacheData) {
   2063  Maybe<FileDescriptor> fd;
   2064  if (cacheFile.type() == cacheFile.TFileDescriptor) {
   2065    fd.emplace(cacheFile.get_FileDescriptor());
   2066  }
   2067 
   2068  static_cast<loader::ScriptCacheChild*>(actor)->Init(fd, wantCacheData);
   2069 
   2070  // Some scripts listen for "app-startup" to start. However, in the content
   2071  // process, this category runs before the ScriptPreloader is initialized so
   2072  // these scripts wouldn't be added to the cache. Instead, if a script needs to
   2073  // run on start up in the content process, it should listen for this category.
   2074  NS_CreateServicesFromCategory("content-process-ready-for-script", nullptr,
   2075                                "content-process-ready-for-script", nullptr);
   2076 
   2077  return IPC_OK();
   2078 }
   2079 
   2080 mozilla::ipc::IPCResult ContentChild::RecvNetworkLinkTypeChange(
   2081    const uint32_t& aType) {
   2082  mNetworkLinkType = aType;
   2083  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   2084  if (obs) {
   2085    obs->NotifyObservers(nullptr, "contentchild:network-link-type-changed",
   2086                         nullptr);
   2087  }
   2088  return IPC_OK();
   2089 }
   2090 
   2091 mozilla::ipc::IPCResult ContentChild::RecvSocketProcessCrashed() {
   2092  nsIOService::IncreaseSocketProcessCrashCount();
   2093  return IPC_OK();
   2094 }
   2095 
   2096 PRemotePrintJobChild* ContentChild::AllocPRemotePrintJobChild() {
   2097 #ifdef NS_PRINTING
   2098  return new RemotePrintJobChild();
   2099 #else
   2100  return nullptr;
   2101 #endif
   2102 }
   2103 
   2104 media::PMediaChild* ContentChild::AllocPMediaChild() {
   2105  return media::AllocPMediaChild();
   2106 }
   2107 
   2108 bool ContentChild::DeallocPMediaChild(media::PMediaChild* aActor) {
   2109  return media::DeallocPMediaChild(aActor);
   2110 }
   2111 
   2112 #ifdef MOZ_WEBRTC
   2113 PWebrtcGlobalChild* ContentChild::AllocPWebrtcGlobalChild() {
   2114  auto* child = new WebrtcGlobalChild();
   2115  return child;
   2116 }
   2117 
   2118 bool ContentChild::DeallocPWebrtcGlobalChild(PWebrtcGlobalChild* aActor) {
   2119  delete static_cast<WebrtcGlobalChild*>(aActor);
   2120  return true;
   2121 }
   2122 #endif
   2123 
   2124 mozilla::ipc::IPCResult ContentChild::RecvRegisterChrome(
   2125    nsTArray<ChromePackage>&& packages,
   2126    nsTArray<SubstitutionMapping>&& resources,
   2127    nsTArray<OverrideMapping>&& overrides, const nsCString& locale,
   2128    const bool& reset) {
   2129  nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
   2130  nsChromeRegistryContent* chromeRegistry =
   2131      static_cast<nsChromeRegistryContent*>(registrySvc.get());
   2132  if (!chromeRegistry) {
   2133    return IPC_FAIL(this, "ChromeRegistryContent is null!");
   2134  }
   2135  chromeRegistry->RegisterRemoteChrome(packages, resources, overrides, locale,
   2136                                       reset);
   2137  return IPC_OK();
   2138 }
   2139 
   2140 mozilla::ipc::IPCResult ContentChild::RecvRegisterChromeItem(
   2141    const ChromeRegistryItem& item) {
   2142  nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
   2143  nsChromeRegistryContent* chromeRegistry =
   2144      static_cast<nsChromeRegistryContent*>(registrySvc.get());
   2145  if (!chromeRegistry) {
   2146    return IPC_FAIL(this, "ChromeRegistryContent is null!");
   2147  }
   2148  switch (item.type()) {
   2149    case ChromeRegistryItem::TChromePackage:
   2150      chromeRegistry->RegisterPackage(item.get_ChromePackage());
   2151      break;
   2152 
   2153    case ChromeRegistryItem::TOverrideMapping:
   2154      chromeRegistry->RegisterOverride(item.get_OverrideMapping());
   2155      break;
   2156 
   2157    case ChromeRegistryItem::TSubstitutionMapping:
   2158      chromeRegistry->RegisterSubstitution(item.get_SubstitutionMapping());
   2159      break;
   2160 
   2161    default:
   2162      MOZ_ASSERT(false, "bad chrome item");
   2163      return IPC_FAIL_NO_REASON(this);
   2164  }
   2165 
   2166  return IPC_OK();
   2167 }
   2168 mozilla::ipc::IPCResult ContentChild::RecvClearStyleSheetCache(
   2169    const Maybe<bool>& aChrome, const Maybe<RefPtr<nsIPrincipal>>& aPrincipal,
   2170    const Maybe<nsCString>& aSchemelessSite,
   2171    const Maybe<OriginAttributesPattern>& aPattern,
   2172    const Maybe<nsCString>& aURL) {
   2173  SharedStyleSheetCache::Clear(aChrome, aPrincipal, aSchemelessSite, aPattern,
   2174                               aURL);
   2175  return IPC_OK();
   2176 }
   2177 
   2178 mozilla::ipc::IPCResult ContentChild::RecvClearScriptCache(
   2179    const Maybe<bool>& aChrome, const Maybe<RefPtr<nsIPrincipal>>& aPrincipal,
   2180    const Maybe<nsCString>& aSchemelessSite,
   2181    const Maybe<OriginAttributesPattern>& aPattern,
   2182    const Maybe<nsCString>& aURL) {
   2183  SharedScriptCache::Clear(aChrome, aPrincipal, aSchemelessSite, aPattern,
   2184                           aURL);
   2185  return IPC_OK();
   2186 }
   2187 
   2188 mozilla::ipc::IPCResult ContentChild::RecvInvalidateScriptCache() {
   2189  SharedScriptCache::Invalidate();
   2190  return IPC_OK();
   2191 }
   2192 
   2193 mozilla::ipc::IPCResult ContentChild::RecvClearImageCache(
   2194    const Maybe<bool>& aPrivateLoader, const Maybe<bool>& aChrome,
   2195    const Maybe<RefPtr<nsIPrincipal>>& aPrincipal,
   2196    const Maybe<nsCString>& aSchemelessSite,
   2197    const Maybe<OriginAttributesPattern>& aPattern,
   2198    const Maybe<nsCString>& aURL) {
   2199  imgLoader::ClearCache(aPrincipal, aChrome, aPrincipal, aSchemelessSite,
   2200                        aPattern, aURL);
   2201  return IPC_OK();
   2202 }
   2203 
   2204 mozilla::ipc::IPCResult ContentChild::RecvSetOffline(const bool& offline) {
   2205  nsCOMPtr<nsIIOService> io(do_GetIOService());
   2206  NS_ASSERTION(io, "IO Service can not be null");
   2207 
   2208  io->SetOffline(offline);
   2209 
   2210  return IPC_OK();
   2211 }
   2212 
   2213 mozilla::ipc::IPCResult ContentChild::RecvSetConnectivity(
   2214    const bool& connectivity) {
   2215  nsCOMPtr<nsIIOService> io(do_GetIOService());
   2216  nsCOMPtr<nsIIOServiceInternal> ioInternal(do_QueryInterface(io));
   2217  NS_ASSERTION(ioInternal, "IO Service can not be null");
   2218 
   2219  ioInternal->SetConnectivity(connectivity);
   2220 
   2221  return IPC_OK();
   2222 }
   2223 
   2224 mozilla::ipc::IPCResult ContentChild::RecvSetCaptivePortalState(
   2225    const int32_t& aState) {
   2226  nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID);
   2227  if (!cps) {
   2228    return IPC_OK();
   2229  }
   2230 
   2231  mozilla::net::CaptivePortalService* portal =
   2232      static_cast<mozilla::net::CaptivePortalService*>(cps.get());
   2233  portal->SetStateInChild(aState);
   2234 
   2235  return IPC_OK();
   2236 }
   2237 
   2238 mozilla::ipc::IPCResult ContentChild::RecvSetTRRMode(
   2239    const nsIDNSService::ResolverMode& mode,
   2240    const nsIDNSService::ResolverMode& modeFromPref) {
   2241  RefPtr<net::ChildDNSService> dnsServiceChild =
   2242      dont_AddRef(net::ChildDNSService::GetSingleton());
   2243  if (dnsServiceChild) {
   2244    dnsServiceChild->SetTRRModeInChild(mode, modeFromPref);
   2245  }
   2246  return IPC_OK();
   2247 }
   2248 
   2249 void ContentChild::ActorDestroy(ActorDestroyReason why) {
   2250 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
   2251  DestroySandboxProfiler();
   2252 #endif
   2253 
   2254  if (mForceKillTimer) {
   2255    mForceKillTimer->Cancel();
   2256    mForceKillTimer = nullptr;
   2257  }
   2258 
   2259  if (AbnormalShutdown == why) {
   2260    NS_WARNING("shutting down early because of crash!");
   2261    ProcessChild::QuickExit();
   2262  }
   2263 
   2264 #ifndef NS_FREE_PERMANENT_DATA
   2265  // In release builds, there's no point in the content process
   2266  // going through the full XPCOM shutdown path, because it doesn't
   2267  // keep persistent state.
   2268  ProcessChild::QuickExit();
   2269 #else
   2270  // Destroy our JSProcessActors, and reject any pending queries.
   2271  JSActorDidDestroy();
   2272 
   2273 #  if defined(XP_WIN)
   2274  RefPtr<DllServices> dllSvc(DllServices::Get());
   2275  dllSvc->DisableFull();
   2276 #  endif  // defined(XP_WIN)
   2277 
   2278  if (gFirstIdleTask) {
   2279    gFirstIdleTask->Cancel();
   2280    gFirstIdleTask = nullptr;
   2281  }
   2282 
   2283  BlobURLProtocolHandler::RemoveDataEntries();
   2284 
   2285  mSharedData = nullptr;
   2286 
   2287  mIdleObservers.Clear();
   2288 
   2289  if (mConsoleListener) {
   2290    nsCOMPtr<nsIConsoleService> svc(
   2291        do_GetService(NS_CONSOLESERVICE_CONTRACTID));
   2292    if (svc) {
   2293      svc->UnregisterListener(mConsoleListener);
   2294      mConsoleListener->mChild = nullptr;
   2295    }
   2296  }
   2297  mIsAlive = false;
   2298 
   2299  CrashReporterClient::DestroySingleton();
   2300 
   2301  XRE_ShutdownChildProcess();
   2302 #endif    // NS_FREE_PERMANENT_DATA
   2303 }
   2304 
   2305 void ContentChild::ProcessingError(Result aCode, const char* aReason) {
   2306  switch (aCode) {
   2307    case MsgDropped:
   2308      NS_WARNING("MsgDropped in ContentChild");
   2309      return;
   2310 
   2311    case MsgNotKnown:
   2312    case MsgNotAllowed:
   2313    case MsgPayloadError:
   2314    case MsgProcessingError:
   2315    case MsgValueError:
   2316      break;
   2317 
   2318    default:
   2319      MOZ_CRASH("not reached");
   2320  }
   2321 
   2322  CrashReporter::RecordAnnotationCString(
   2323      CrashReporter::Annotation::ipc_channel_error, aReason);
   2324 
   2325  MOZ_CRASH("Content child abort due to IPC error");
   2326 }
   2327 
   2328 mozilla::ipc::IPCResult ContentChild::RecvPreferenceUpdate(const Pref& aPref) {
   2329  Preferences::SetPreference(aPref);
   2330  return IPC_OK();
   2331 }
   2332 
   2333 mozilla::ipc::IPCResult ContentChild::RecvVarUpdate(
   2334    const nsTArray<GfxVarUpdate>& aVar) {
   2335  gfx::gfxVars::ApplyUpdate(aVar);
   2336  return IPC_OK();
   2337 }
   2338 
   2339 mozilla::ipc::IPCResult ContentChild::RecvUpdatePerfStatsCollectionMask(
   2340    const uint64_t& aMask) {
   2341  PerfStats::SetCollectionMask(static_cast<PerfStats::MetricMask>(aMask));
   2342  return IPC_OK();
   2343 }
   2344 
   2345 mozilla::ipc::IPCResult ContentChild::RecvCollectPerfStatsJSON(
   2346    CollectPerfStatsJSONResolver&& aResolver) {
   2347  aResolver(PerfStats::CollectLocalPerfStatsJSON());
   2348  return IPC_OK();
   2349 }
   2350 
   2351 mozilla::ipc::IPCResult ContentChild::RecvCollectScrollingMetrics(
   2352    CollectScrollingMetricsResolver&& aResolver) {
   2353  auto metrics = ScrollingMetrics::CollectLocalScrollingMetrics();
   2354  using ResolverArgs = std::tuple<const uint32_t&, const uint32_t&>;
   2355  aResolver(ResolverArgs(std::get<0>(metrics), std::get<1>(metrics)));
   2356  return IPC_OK();
   2357 }
   2358 
   2359 mozilla::ipc::IPCResult ContentChild::RecvNotifyVisited(
   2360    nsTArray<VisitedQueryResult>&& aURIs) {
   2361  nsCOMPtr<IHistory> history = components::History::Service();
   2362  if (!history) {
   2363    return IPC_OK();
   2364  }
   2365  for (const VisitedQueryResult& result : aURIs) {
   2366    nsCOMPtr<nsIURI> newURI = result.uri();
   2367    if (!newURI) {
   2368      return IPC_FAIL_NO_REASON(this);
   2369    }
   2370    auto status = result.visited() ? IHistory::VisitedStatus::Visited
   2371                                   : IHistory::VisitedStatus::Unvisited;
   2372    history->NotifyVisited(newURI, status);
   2373  }
   2374  return IPC_OK();
   2375 }
   2376 
   2377 mozilla::ipc::IPCResult ContentChild::RecvThemeChanged(
   2378    FullLookAndFeel&& aLookAndFeelData, widget::ThemeChangeKind aKind) {
   2379  LookAndFeel::SetData(std::move(aLookAndFeelData));
   2380  LookAndFeel::NotifyChangedAllWindows(aKind);
   2381  return IPC_OK();
   2382 }
   2383 
   2384 mozilla::ipc::IPCResult ContentChild::RecvLoadProcessScript(
   2385    const nsString& aURL) {
   2386  auto* global = ContentProcessMessageManager::Get();
   2387  if (global && global->LoadScript(aURL)) {
   2388    return IPC_OK();
   2389  }
   2390  return IPC_FAIL(this, "ContentProcessMessageManager::LoadScript failed");
   2391 }
   2392 
   2393 mozilla::ipc::IPCResult ContentChild::RecvAsyncMessage(
   2394    const nsString& aMsg, const ClonedMessageData& aData) {
   2395  AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("ContentChild::RecvAsyncMessage",
   2396                                             OTHER, aMsg);
   2397  MMPrinter::Print("ContentChild::RecvAsyncMessage", aMsg, aData);
   2398 
   2399  RefPtr<nsFrameMessageManager> cpm =
   2400      nsFrameMessageManager::GetChildProcessManager();
   2401  if (cpm) {
   2402    StructuredCloneData data;
   2403    ipc::UnpackClonedMessageData(aData, data);
   2404    cpm->ReceiveMessage(cpm, nullptr, aMsg, false, &data, nullptr,
   2405                        IgnoreErrors());
   2406  }
   2407  return IPC_OK();
   2408 }
   2409 
   2410 mozilla::ipc::IPCResult ContentChild::RecvRegisterStringBundles(
   2411    nsTArray<mozilla::dom::StringBundleDescriptor>&& aDescriptors) {
   2412  nsCOMPtr<nsIStringBundleService> stringBundleService =
   2413      components::StringBundle::Service();
   2414 
   2415  for (auto& descriptor : aDescriptors) {
   2416    stringBundleService->RegisterContentBundle(
   2417        descriptor.bundleURL(), std::move(descriptor.mapHandle()));
   2418  }
   2419 
   2420  return IPC_OK();
   2421 }
   2422 
   2423 mozilla::ipc::IPCResult ContentChild::RecvSimpleURIUnknownRemoteSchemes(
   2424    nsTArray<nsCString>&& aRemoteSchemes) {
   2425  RefPtr<nsIOService> io = nsIOService::GetInstance();
   2426  io->SetSimpleURIUnknownRemoteSchemes(aRemoteSchemes);
   2427  return IPC_OK();
   2428 }
   2429 
   2430 mozilla::ipc::IPCResult ContentChild::RecvUpdateL10nFileSources(
   2431    nsTArray<mozilla::dom::L10nFileSourceDescriptor>&& aDescriptors) {
   2432  L10nRegistry::RegisterFileSourcesFromParentProcess(aDescriptors);
   2433  return IPC_OK();
   2434 }
   2435 
   2436 mozilla::ipc::IPCResult ContentChild::RecvUpdateSharedData(
   2437    mozilla::ipc::ReadOnlySharedMemoryHandle&& aMapHandle,
   2438    nsTArray<IPCBlob>&& aBlobs, nsTArray<nsCString>&& aChangedKeys) {
   2439  nsTArray<RefPtr<BlobImpl>> blobImpls(aBlobs.Length());
   2440  for (auto& ipcBlob : aBlobs) {
   2441    blobImpls.AppendElement(IPCBlobUtils::Deserialize(ipcBlob));
   2442  }
   2443 
   2444  if (mSharedData) {
   2445    mSharedData->Update(std::move(aMapHandle), std::move(blobImpls),
   2446                        std::move(aChangedKeys));
   2447  } else {
   2448    mSharedData =
   2449        new SharedMap(ContentProcessMessageManager::Get()->GetParentObject(),
   2450                      std::move(aMapHandle), std::move(blobImpls));
   2451  }
   2452 
   2453  return IPC_OK();
   2454 }
   2455 
   2456 mozilla::ipc::IPCResult ContentChild::RecvForceGlobalReflow(
   2457    const gfxPlatform::GlobalReflowFlags& aFlags) {
   2458  gfxPlatform::ForceGlobalReflow(aFlags);
   2459 
   2460  return IPC_OK();
   2461 }
   2462 
   2463 mozilla::ipc::IPCResult ContentChild::RecvGeolocationUpdate(
   2464    nsIDOMGeoPosition* aPosition) {
   2465  RefPtr<nsGeolocationService> gs =
   2466      nsGeolocationService::GetGeolocationService();
   2467  if (!gs) {
   2468    return IPC_OK();
   2469  }
   2470  gs->Update(aPosition);
   2471  return IPC_OK();
   2472 }
   2473 
   2474 mozilla::ipc::IPCResult ContentChild::RecvGeolocationError(
   2475    const uint16_t& errorCode) {
   2476  RefPtr<nsGeolocationService> gs =
   2477      nsGeolocationService::GetGeolocationService();
   2478  if (!gs) {
   2479    return IPC_OK();
   2480  }
   2481  gs->NotifyError(errorCode);
   2482  return IPC_OK();
   2483 }
   2484 
   2485 mozilla::ipc::IPCResult ContentChild::RecvUpdateDictionaryList(
   2486    nsTArray<nsCString>&& aDictionaries) {
   2487  mAvailableDictionaries = std::move(aDictionaries);
   2488  mozInlineSpellChecker::UpdateCanEnableInlineSpellChecking();
   2489  return IPC_OK();
   2490 }
   2491 
   2492 mozilla::ipc::IPCResult ContentChild::RecvUpdateFontList(
   2493    dom::SystemFontList&& aFontList) {
   2494  mFontList = std::move(aFontList);
   2495  if (gfxPlatform::Initialized()) {
   2496    gfxPlatform::GetPlatform()->UpdateFontList(true);
   2497  }
   2498  return IPC_OK();
   2499 }
   2500 
   2501 mozilla::ipc::IPCResult ContentChild::RecvRebuildFontList(
   2502    const bool& aFullRebuild) {
   2503  if (gfxPlatform::Initialized()) {
   2504    gfxPlatform::GetPlatform()->UpdateFontList(aFullRebuild);
   2505  }
   2506  return IPC_OK();
   2507 }
   2508 
   2509 mozilla::ipc::IPCResult ContentChild::RecvFontListShmBlockAdded(
   2510    const uint32_t& aGeneration, const uint32_t& aIndex,
   2511    mozilla::ipc::ReadOnlySharedMemoryHandle&& aHandle) {
   2512  if (gfxPlatform::Initialized()) {
   2513    gfxPlatformFontList::PlatformFontList()->ShmBlockAdded(aGeneration, aIndex,
   2514                                                           std::move(aHandle));
   2515  }
   2516  return IPC_OK();
   2517 }
   2518 
   2519 mozilla::ipc::IPCResult ContentChild::RecvUpdateAppLocales(
   2520    nsTArray<nsCString>&& aAppLocales) {
   2521  LocaleService::GetInstance()->AssignAppLocales(aAppLocales);
   2522  return IPC_OK();
   2523 }
   2524 
   2525 mozilla::ipc::IPCResult ContentChild::RecvUpdateRequestedLocales(
   2526    nsTArray<nsCString>&& aRequestedLocales) {
   2527  LocaleService::GetInstance()->AssignRequestedLocales(aRequestedLocales);
   2528  return IPC_OK();
   2529 }
   2530 
   2531 mozilla::ipc::IPCResult ContentChild::RecvSystemTimezoneChanged() {
   2532  nsJSUtils::ResetTimeZone();
   2533  return IPC_OK();
   2534 }
   2535 
   2536 mozilla::ipc::IPCResult ContentChild::RecvAddPermission(
   2537    const IPC::Permission& permission) {
   2538  RefPtr<PermissionManager> permissionManager =
   2539      PermissionManager::GetInstance();
   2540  MOZ_ASSERT(permissionManager,
   2541             "We have no permissionManager in the Content process !");
   2542 
   2543  // note we do not need to force mUserContextId to the default here because
   2544  // the permission manager does that internally.
   2545  nsAutoCString originNoSuffix;
   2546  OriginAttributes attrs;
   2547  bool success = attrs.PopulateFromOrigin(permission.origin, originNoSuffix);
   2548  NS_ENSURE_TRUE(success, IPC_FAIL_NO_REASON(this));
   2549 
   2550  nsCOMPtr<nsIURI> uri;
   2551  nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
   2552  NS_ENSURE_SUCCESS(rv, IPC_OK());
   2553 
   2554  nsCOMPtr<nsIPrincipal> principal =
   2555      mozilla::BasePrincipal::CreateContentPrincipal(uri, attrs);
   2556 
   2557  // child processes don't care about modification time.
   2558  int64_t modificationTime = 0;
   2559 
   2560  permissionManager->Add(
   2561      principal, nsCString(permission.type), permission.capability, 0,
   2562      permission.expireType, permission.expireTime, modificationTime,
   2563      PermissionManager::eNotify, PermissionManager::eNoDBOperation);
   2564 
   2565  return IPC_OK();
   2566 }
   2567 
   2568 mozilla::ipc::IPCResult ContentChild::RecvRemoveAllPermissions() {
   2569  RefPtr<PermissionManager> permissionManager =
   2570      PermissionManager::GetInstance();
   2571  MOZ_ASSERT(permissionManager,
   2572             "We have no permissionManager in the Content process !");
   2573 
   2574  permissionManager->RemoveAllFromIPC();
   2575  return IPC_OK();
   2576 }
   2577 
   2578 mozilla::ipc::IPCResult ContentChild::RecvFlushMemory(const nsString& reason) {
   2579  nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   2580  if (!mShuttingDown && os) {
   2581    os->NotifyObservers(nullptr, "memory-pressure", reason.get());
   2582  }
   2583  return IPC_OK();
   2584 }
   2585 
   2586 mozilla::ipc::IPCResult ContentChild::RecvActivateA11y(uint64_t aCacheDomains) {
   2587 #ifdef ACCESSIBILITY
   2588  // Start accessibility in content process if it's running in chrome
   2589  // process.
   2590  GetOrCreateAccService(nsAccessibilityService::eMainProcess, aCacheDomains);
   2591 #endif  // ACCESSIBILITY
   2592  return IPC_OK();
   2593 }
   2594 
   2595 mozilla::ipc::IPCResult ContentChild::RecvShutdownA11y() {
   2596 #ifdef ACCESSIBILITY
   2597  // Try to shutdown accessibility in content process if it's shutting down in
   2598  // chrome process.
   2599  MaybeShutdownAccService(nsAccessibilityService::eMainProcess);
   2600 #endif
   2601  return IPC_OK();
   2602 }
   2603 
   2604 mozilla::ipc::IPCResult ContentChild::RecvSetCacheDomains(
   2605    uint64_t aCacheDomains) {
   2606 #ifdef ACCESSIBILITY
   2607  nsAccessibilityService* accService = GetAccService();
   2608  if (!accService) {
   2609    return IPC_FAIL(this, "Accessibility service should exist");
   2610  }
   2611  accService->SetCacheDomains(aCacheDomains);
   2612 #endif
   2613  return IPC_OK();
   2614 }
   2615 
   2616 mozilla::ipc::IPCResult ContentChild::RecvApplicationForeground() {
   2617  // Rebroadcast the "application-foreground"
   2618  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   2619  if (obs) {
   2620    obs->NotifyObservers(nullptr, "application-foreground", nullptr);
   2621  }
   2622  return IPC_OK();
   2623 }
   2624 
   2625 mozilla::ipc::IPCResult ContentChild::RecvApplicationBackground() {
   2626  // Rebroadcast the "application-background"
   2627  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   2628  if (obs) {
   2629    obs->NotifyObservers(nullptr, "application-background", nullptr);
   2630  }
   2631  return IPC_OK();
   2632 }
   2633 
   2634 mozilla::ipc::IPCResult ContentChild::RecvGarbageCollect() {
   2635  // Rebroadcast the "child-gc-request" so that workers will GC.
   2636  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   2637  if (obs) {
   2638    obs->NotifyObservers(nullptr, "child-gc-request", nullptr);
   2639  }
   2640  nsJSContext::GarbageCollectNow(JS::GCReason::DOM_IPC);
   2641  return IPC_OK();
   2642 }
   2643 
   2644 mozilla::ipc::IPCResult ContentChild::RecvCycleCollect() {
   2645  // Rebroadcast the "child-cc-request" so that workers will CC.
   2646  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   2647  if (obs) {
   2648    obs->NotifyObservers(nullptr, "child-cc-request", nullptr);
   2649  }
   2650  nsJSContext::CycleCollectNow(CCReason::IPC_MESSAGE);
   2651  return IPC_OK();
   2652 }
   2653 
   2654 mozilla::ipc::IPCResult ContentChild::RecvUnlinkGhosts() {
   2655 #ifdef DEBUG
   2656  nsWindowMemoryReporter::UnlinkGhostWindows();
   2657 #endif
   2658  return IPC_OK();
   2659 }
   2660 
   2661 mozilla::ipc::IPCResult ContentChild::RecvAppInfo(
   2662    const nsCString& version, const nsCString& buildID, const nsCString& name,
   2663    const nsCString& UAName, const nsCString& ID, const nsCString& vendor,
   2664    const nsCString& sourceURL, const nsCString& updateURL) {
   2665  mAppInfo.version.Assign(version);
   2666  mAppInfo.buildID.Assign(buildID);
   2667  mAppInfo.name.Assign(name);
   2668  mAppInfo.UAName.Assign(UAName);
   2669  mAppInfo.ID.Assign(ID);
   2670  mAppInfo.vendor.Assign(vendor);
   2671  mAppInfo.sourceURL.Assign(sourceURL);
   2672  mAppInfo.updateURL.Assign(updateURL);
   2673 
   2674  return IPC_OK();
   2675 }
   2676 
   2677 mozilla::ipc::IPCResult ContentChild::RecvRemoteType(
   2678    const nsCString& aRemoteType, const nsCString& aProfile) {
   2679  if (aRemoteType == mRemoteType) {
   2680    // Allocation of preallocated processes that are still launching can
   2681    // cause this
   2682    return IPC_OK();
   2683  }
   2684 
   2685  if (!mRemoteType.IsVoid()) {
   2686    // Preallocated processes are type PREALLOC_REMOTE_TYPE; they may not
   2687    // become a File: process, or Privileged About Content Process
   2688    MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
   2689            ("Changing remoteType of process %d from %s to %s", getpid(),
   2690             mRemoteType.get(), aRemoteType.get()));
   2691    // prealloc->anything (but file) or web->web allowed, and no-change
   2692    MOZ_RELEASE_ASSERT(mRemoteType == PREALLOC_REMOTE_TYPE &&
   2693                       aRemoteType != FILE_REMOTE_TYPE &&
   2694                       aRemoteType != PRIVILEGEDABOUT_REMOTE_TYPE);
   2695  } else {
   2696    // Initial setting of remote type.  Either to 'prealloc' or the actual
   2697    // final type (if we didn't use a preallocated process)
   2698    MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
   2699            ("Setting remoteType of process %d to %s", getpid(),
   2700             aRemoteType.get()));
   2701 
   2702    if (aRemoteType == PREALLOC_REMOTE_TYPE) {
   2703      PreallocInit();
   2704    }
   2705  }
   2706 
   2707  auto remoteTypePrefix = RemoteTypePrefix(aRemoteType);
   2708 
   2709  // Must do before SetProcessName
   2710  mRemoteType.Assign(aRemoteType);
   2711 
   2712  // Update the process name so about:memory's process names are more obvious.
   2713  if (aRemoteType == FILE_REMOTE_TYPE) {
   2714    SetProcessName("file:// Content"_ns, nullptr, &aProfile);
   2715  } else if (aRemoteType == EXTENSION_REMOTE_TYPE) {
   2716    SetProcessName("WebExtensions"_ns, nullptr, &aProfile);
   2717  } else if (aRemoteType == PRIVILEGEDABOUT_REMOTE_TYPE) {
   2718    SetProcessName("Privileged Content"_ns, nullptr, &aProfile);
   2719  } else if (aRemoteType == PRIVILEGEDMOZILLA_REMOTE_TYPE) {
   2720    SetProcessName("Privileged Mozilla"_ns, nullptr, &aProfile);
   2721  } else if (aRemoteType == INFERENCE_REMOTE_TYPE) {
   2722    SetProcessName("Inference"_ns, nullptr, &aProfile);
   2723  } else if (remoteTypePrefix == WITH_COOP_COEP_REMOTE_TYPE) {
   2724    // The profiler can sanitize out the eTLD+1
   2725    nsDependentCSubstring etld =
   2726        Substring(aRemoteType, WITH_COOP_COEP_REMOTE_TYPE.Length() + 1);
   2727 #ifdef NIGHTLY_BUILD
   2728    SetProcessName("WebCOOP+COEP Content"_ns, &etld, &aProfile);
   2729 #else
   2730    SetProcessName("Isolated Web Content"_ns, &etld,
   2731                   &aProfile);  // to avoid confusing people
   2732 #endif
   2733  } else if (remoteTypePrefix == FISSION_WEB_REMOTE_TYPE) {
   2734    // The profiler can sanitize out the eTLD+1
   2735    nsDependentCSubstring etld =
   2736        Substring(aRemoteType, FISSION_WEB_REMOTE_TYPE.Length() + 1);
   2737    SetProcessName("Isolated Web Content"_ns, &etld, &aProfile);
   2738  } else if (remoteTypePrefix == SERVICEWORKER_REMOTE_TYPE) {
   2739    // The profiler can sanitize out the eTLD+1
   2740    nsDependentCSubstring etld =
   2741        Substring(aRemoteType, SERVICEWORKER_REMOTE_TYPE.Length() + 1);
   2742    SetProcessName("Isolated Service Worker"_ns, &etld, &aProfile);
   2743  } else {
   2744    // else "prealloc" or "web" type -> "Web Content"
   2745    SetProcessName("Web Content"_ns, nullptr, &aProfile);
   2746  }
   2747 
   2748  // Turn off Spectre mitigations in isolated web content processes.
   2749  if (StaticPrefs::javascript_options_spectre_disable_for_isolated_content() &&
   2750      StaticPrefs::browser_opaqueResponseBlocking() &&
   2751      (remoteTypePrefix == FISSION_WEB_REMOTE_TYPE ||
   2752       remoteTypePrefix == SERVICEWORKER_REMOTE_TYPE ||
   2753       remoteTypePrefix == WITH_COOP_COEP_REMOTE_TYPE ||
   2754       aRemoteType == PRIVILEGEDABOUT_REMOTE_TYPE ||
   2755       aRemoteType == PRIVILEGEDMOZILLA_REMOTE_TYPE)) {
   2756    JS::DisableSpectreMitigationsAfterInit();
   2757  }
   2758 
   2759  // Use the prefix to avoid URIs from Fission isolated processes.
   2760  CrashReporter::RecordAnnotationNSCString(
   2761      CrashReporter::Annotation::RemoteType, remoteTypePrefix);
   2762 
   2763  return IPC_OK();
   2764 }
   2765 
   2766 // A method to initialize anything we need during the preallocation phase
   2767 void ContentChild::PreallocInit() {
   2768  EnsureNSSInitializedChromeOrContent();
   2769 
   2770  // SetAcceptLanguages() needs to read localized strings (file access),
   2771  // which is slow, so do this in prealloc
   2772  nsHttpHandler::PresetAcceptLanguages();
   2773 }
   2774 
   2775 // Call RemoteTypePrefix() on the result to remove URIs if you want to use this
   2776 // for telemetry.
   2777 const nsACString& ContentChild::GetRemoteType() const { return mRemoteType; }
   2778 
   2779 mozilla::ipc::IPCResult ContentChild::RecvInitRemoteWorkerService(
   2780    Endpoint<PRemoteWorkerServiceChild>&& aEndpoint,
   2781    Endpoint<PRemoteWorkerDebuggerManagerChild>&& aDebuggerChiledEp) {
   2782  RemoteWorkerService::InitializeChild(std::move(aEndpoint),
   2783                                       std::move(aDebuggerChiledEp));
   2784  return IPC_OK();
   2785 }
   2786 
   2787 mozilla::ipc::IPCResult ContentChild::RecvInitBlobURLs(
   2788    nsTArray<BlobURLRegistrationData>&& aRegistrations) {
   2789  for (uint32_t i = 0; i < aRegistrations.Length(); ++i) {
   2790    BlobURLRegistrationData& registration = aRegistrations[i];
   2791    RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(registration.blob());
   2792    MOZ_ASSERT(blobImpl);
   2793 
   2794    BlobURLProtocolHandler::AddDataEntry(registration.url(),
   2795                                         registration.principal(),
   2796                                         registration.partitionKey(), blobImpl);
   2797    // If we have received an already-revoked blobURL, we have to keep it alive
   2798    // for a while (see BlobURLProtocolHandler) in order to support pending
   2799    // operations such as navigation, download and so on.
   2800    if (registration.revoked()) {
   2801      BlobURLProtocolHandler::RemoveDataEntries(nsTArray{registration.url()},
   2802                                                false);
   2803    }
   2804  }
   2805 
   2806  return IPC_OK();
   2807 }
   2808 
   2809 mozilla::ipc::IPCResult ContentChild::RecvInitJSActorInfos(
   2810    nsTArray<JSProcessActorInfo>&& aContentInfos,
   2811    nsTArray<JSWindowActorInfo>&& aWindowInfos) {
   2812  RefPtr<JSActorService> actSvc = JSActorService::GetSingleton();
   2813  actSvc->LoadJSActorInfos(aContentInfos, aWindowInfos);
   2814  return IPC_OK();
   2815 }
   2816 
   2817 mozilla::ipc::IPCResult ContentChild::RecvUnregisterJSWindowActor(
   2818    const nsCString& aName) {
   2819  RefPtr<JSActorService> actSvc = JSActorService::GetSingleton();
   2820  actSvc->UnregisterWindowActor(aName);
   2821  return IPC_OK();
   2822 }
   2823 
   2824 mozilla::ipc::IPCResult ContentChild::RecvUnregisterJSProcessActor(
   2825    const nsCString& aName) {
   2826  RefPtr<JSActorService> actSvc = JSActorService::GetSingleton();
   2827  actSvc->UnregisterProcessActor(aName);
   2828  return IPC_OK();
   2829 }
   2830 
   2831 mozilla::ipc::IPCResult ContentChild::RecvLastPrivateDocShellDestroyed() {
   2832  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   2833  obs->NotifyObservers(nullptr, "last-pb-context-exited", nullptr);
   2834  return IPC_OK();
   2835 }
   2836 
   2837 mozilla::ipc::IPCResult ContentChild::RecvNotifyProcessPriorityChanged(
   2838    const hal::ProcessPriority& aPriority) {
   2839  nsCOMPtr<nsIObserverService> os = services::GetObserverService();
   2840  NS_ENSURE_TRUE(os, IPC_OK());
   2841 
   2842  RefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
   2843  props->SetPropertyAsInt32(u"priority"_ns, static_cast<int32_t>(aPriority));
   2844 
   2845  PROFILER_MARKER("Process Priority", OTHER,
   2846                  mozilla::MarkerThreadId::MainThread(), ProcessPriorityChange,
   2847                  ProfilerString8View::WrapNullTerminatedString(
   2848                      ProcessPriorityToString(mProcessPriority)),
   2849                  ProfilerString8View::WrapNullTerminatedString(
   2850                      ProcessPriorityToString(aPriority)));
   2851 
   2852  // Record FOG data before the priority change.
   2853  // Ignore the change if it's the first time we set the process priority.
   2854  if (mProcessPriority != hal::PROCESS_PRIORITY_UNKNOWN) {
   2855    glean::RecordPowerMetrics();
   2856  }
   2857 
   2858  ConfigureThreadPerformanceHints(aPriority);
   2859 
   2860  mProcessPriority = aPriority;
   2861 
   2862  os->NotifyObservers(static_cast<nsIPropertyBag2*>(props),
   2863                      "ipc:process-priority-changed", nullptr);
   2864  if (StaticPrefs::
   2865          dom_memory_foreground_content_processes_have_larger_page_cache()) {
   2866 #ifdef MOZ_MEMORY
   2867    if (mProcessPriority >= hal::PROCESS_PRIORITY_FOREGROUND) {
   2868      // Note: keep this in sync with the JS shell (js/src/shell/js.cpp).
   2869      moz_set_max_dirty_page_modifier(4);
   2870    }
   2871 #endif
   2872    if (mProcessPriority == hal::PROCESS_PRIORITY_BACKGROUND) {
   2873 #ifdef MOZ_MEMORY
   2874      moz_set_max_dirty_page_modifier(-2);
   2875 
   2876      if (StaticPrefs::dom_memory_memory_pressure_on_background() == 1) {
   2877        jemalloc_free_dirty_pages();
   2878      }
   2879 #endif
   2880      if (StaticPrefs::dom_memory_memory_pressure_on_background() == 2) {
   2881        nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService();
   2882        obsServ->NotifyObservers(nullptr, "memory-pressure", u"heap-minimize");
   2883      } else if (StaticPrefs::dom_memory_memory_pressure_on_background() == 3) {
   2884        nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService();
   2885        obsServ->NotifyObservers(nullptr, "memory-pressure", u"low-memory");
   2886      }
   2887 #ifdef MOZ_MEMORY
   2888    } else {
   2889      moz_set_max_dirty_page_modifier(0);
   2890 #endif
   2891    }
   2892  }
   2893 
   2894  return IPC_OK();
   2895 }
   2896 
   2897 mozilla::ipc::IPCResult ContentChild::RecvMinimizeMemoryUsage() {
   2898  nsCOMPtr<nsIMemoryReporterManager> mgr =
   2899      do_GetService("@mozilla.org/memory-reporter-manager;1");
   2900  NS_ENSURE_TRUE(mgr, IPC_OK());
   2901 
   2902  (void)mgr->MinimizeMemoryUsage(/* callback = */ nullptr);
   2903  return IPC_OK();
   2904 }
   2905 
   2906 void ContentChild::AddIdleObserver(nsIObserver* aObserver,
   2907                                   uint32_t aIdleTimeInS) {
   2908  MOZ_ASSERT(aObserver, "null idle observer");
   2909  // Make sure aObserver isn't released while we wait for the parent
   2910  aObserver->AddRef();
   2911  SendAddIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS);
   2912  mIdleObservers.Insert(aObserver);
   2913 }
   2914 
   2915 void ContentChild::RemoveIdleObserver(nsIObserver* aObserver,
   2916                                      uint32_t aIdleTimeInS) {
   2917  MOZ_ASSERT(aObserver, "null idle observer");
   2918  SendRemoveIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS);
   2919  aObserver->Release();
   2920  mIdleObservers.Remove(aObserver);
   2921 }
   2922 
   2923 mozilla::ipc::IPCResult ContentChild::RecvNotifyIdleObserver(
   2924    const uint64_t& aObserver, const nsCString& aTopic,
   2925    const nsString& aTimeStr) {
   2926  nsIObserver* observer = reinterpret_cast<nsIObserver*>(aObserver);
   2927  if (mIdleObservers.Contains(observer)) {
   2928    observer->Observe(nullptr, aTopic.get(), aTimeStr.get());
   2929  } else {
   2930    NS_WARNING("Received notification for an idle observer that was removed.");
   2931  }
   2932  return IPC_OK();
   2933 }
   2934 
   2935 mozilla::ipc::IPCResult ContentChild::RecvLoadAndRegisterSheet(
   2936    nsIURI* aURI, const uint32_t& aType) {
   2937  if (!aURI) {
   2938    return IPC_OK();
   2939  }
   2940 
   2941  nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance();
   2942  if (sheetService) {
   2943    sheetService->LoadAndRegisterSheet(aURI, aType);
   2944  }
   2945 
   2946  return IPC_OK();
   2947 }
   2948 
   2949 mozilla::ipc::IPCResult ContentChild::RecvUnregisterSheet(
   2950    nsIURI* aURI, const uint32_t& aType) {
   2951  if (!aURI) {
   2952    return IPC_OK();
   2953  }
   2954 
   2955  nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance();
   2956  if (sheetService) {
   2957    sheetService->UnregisterSheet(aURI, aType);
   2958  }
   2959 
   2960  return IPC_OK();
   2961 }
   2962 
   2963 mozilla::ipc::IPCResult ContentChild::RecvDomainSetChanged(
   2964    const uint32_t& aSetType, const uint32_t& aChangeType, nsIURI* aDomain) {
   2965  if (aChangeType == ACTIVATE_POLICY) {
   2966    if (mPolicy) {
   2967      return IPC_OK();
   2968    }
   2969    nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
   2970    MOZ_ASSERT(ssm);
   2971    ssm->ActivateDomainPolicyInternal(getter_AddRefs(mPolicy));
   2972    if (!mPolicy) {
   2973      return IPC_FAIL_NO_REASON(this);
   2974    }
   2975    return IPC_OK();
   2976  }
   2977  if (!mPolicy) {
   2978    MOZ_ASSERT_UNREACHABLE(
   2979        "If the domain policy is not active yet,"
   2980        " the first message should be ACTIVATE_POLICY");
   2981    return IPC_FAIL_NO_REASON(this);
   2982  }
   2983 
   2984  NS_ENSURE_TRUE(mPolicy, IPC_FAIL_NO_REASON(this));
   2985 
   2986  if (aChangeType == DEACTIVATE_POLICY) {
   2987    mPolicy->Deactivate();
   2988    mPolicy = nullptr;
   2989    return IPC_OK();
   2990  }
   2991 
   2992  nsCOMPtr<nsIDomainSet> set;
   2993  switch (aSetType) {
   2994    case BLOCKLIST:
   2995      mPolicy->GetBlocklist(getter_AddRefs(set));
   2996      break;
   2997    case SUPER_BLOCKLIST:
   2998      mPolicy->GetSuperBlocklist(getter_AddRefs(set));
   2999      break;
   3000    case ALLOWLIST:
   3001      mPolicy->GetAllowlist(getter_AddRefs(set));
   3002      break;
   3003    case SUPER_ALLOWLIST:
   3004      mPolicy->GetSuperAllowlist(getter_AddRefs(set));
   3005      break;
   3006    default:
   3007      MOZ_ASSERT_UNREACHABLE("Unexpected setType");
   3008      return IPC_FAIL_NO_REASON(this);
   3009  }
   3010 
   3011  MOZ_ASSERT(set);
   3012 
   3013  switch (aChangeType) {
   3014    case ADD_DOMAIN:
   3015      NS_ENSURE_TRUE(aDomain, IPC_FAIL_NO_REASON(this));
   3016      set->Add(aDomain);
   3017      break;
   3018    case REMOVE_DOMAIN:
   3019      NS_ENSURE_TRUE(aDomain, IPC_FAIL_NO_REASON(this));
   3020      set->Remove(aDomain);
   3021      break;
   3022    case CLEAR_DOMAINS:
   3023      set->Clear();
   3024      break;
   3025    default:
   3026      MOZ_ASSERT_UNREACHABLE("Unexpected changeType");
   3027      return IPC_FAIL_NO_REASON(this);
   3028  }
   3029 
   3030  return IPC_OK();
   3031 }
   3032 
   3033 void ContentChild::StartForceKillTimer() {
   3034  if (mForceKillTimer) {
   3035    return;
   3036  }
   3037 
   3038  int32_t timeoutSecs = StaticPrefs::dom_ipc_tabs_shutdownTimeoutSecs();
   3039  if (timeoutSecs > 0) {
   3040    NS_NewTimerWithFuncCallback(getter_AddRefs(mForceKillTimer),
   3041                                ContentChild::ForceKillTimerCallback, this,
   3042                                timeoutSecs * 1000, nsITimer::TYPE_ONE_SHOT,
   3043                                "dom::ContentChild::StartForceKillTimer"_ns);
   3044    MOZ_ASSERT(mForceKillTimer);
   3045  }
   3046 }
   3047 
   3048 /* static */
   3049 void ContentChild::ForceKillTimerCallback(nsITimer* aTimer, void* aClosure) {
   3050  ProcessChild::QuickExit();
   3051 }
   3052 
   3053 mozilla::ipc::IPCResult ContentChild::RecvShutdown() {
   3054  ProcessChild::AppendToIPCShutdownStateAnnotation("RecvShutdown entry"_ns);
   3055 
   3056  // Signal the ongoing shutdown to AppShutdown, this
   3057  // will make abort nested SpinEventLoopUntilOrQuit loops
   3058  AppShutdown::AdvanceShutdownPhaseWithoutNotify(
   3059      ShutdownPhase::AppShutdownConfirmed);
   3060 
   3061  nsCOMPtr<nsIObserverService> os = services::GetObserverService();
   3062  if (os) {
   3063    ProcessChild::AppendToIPCShutdownStateAnnotation(
   3064        "content-child-will-shutdown started"_ns);
   3065 
   3066    os->NotifyObservers(ToSupports(this), "content-child-will-shutdown",
   3067                        nullptr);
   3068  }
   3069 
   3070  ShutdownInternal();
   3071  return IPC_OK();
   3072 }
   3073 
   3074 void ContentChild::ShutdownInternal() {
   3075  ProcessChild::AppendToIPCShutdownStateAnnotation("ShutdownInternal entry"_ns);
   3076 
   3077  // If we receive the shutdown message from within a nested event loop, we want
   3078  // to wait for that event loop to finish. Otherwise we could prematurely
   3079  // terminate an "unload" or "pagehide" event handler (which might be doing a
   3080  // sync XHR, for example).
   3081 
   3082  MOZ_ASSERT(NS_IsMainThread());
   3083  RefPtr<nsThread> mainThread = nsThreadManager::get().GetCurrentThread();
   3084  // Note that we only have to check the recursion count for the current
   3085  // cooperative thread. Since the Shutdown message is not labeled with a
   3086  // SchedulerGroup, there can be no other cooperative threads doing work while
   3087  // we're running.
   3088  if (mainThread && mainThread->RecursionDepth() > 1) {
   3089    // We're in a nested event loop. Let's delay for an arbitrary period of
   3090    // time (100ms) in the hopes that the event loop will have finished by
   3091    // then.
   3092    GetCurrentSerialEventTarget()->DelayedDispatch(
   3093        NewRunnableMethod("dom::ContentChild::RecvShutdown", this,
   3094                          &ContentChild::ShutdownInternal),
   3095        100);
   3096    return;
   3097  }
   3098 
   3099  mShuttingDown = true;
   3100 
   3101 #ifdef NIGHTLY_BUILD
   3102  BackgroundHangMonitor::UnregisterAnnotator(
   3103      PendingInputEventHangAnnotator::sSingleton);
   3104 #endif
   3105 
   3106  if (mPolicy) {
   3107    mPolicy->Deactivate();
   3108    mPolicy = nullptr;
   3109  }
   3110 
   3111  nsCOMPtr<nsIObserverService> os = services::GetObserverService();
   3112  if (os) {
   3113    ProcessChild::AppendToIPCShutdownStateAnnotation(
   3114        "content-child-shutdown started"_ns);
   3115    os->NotifyObservers(ToSupports(this), "content-child-shutdown", nullptr);
   3116  }
   3117 
   3118  GetIPCChannel()->SetAbortOnError(false);
   3119 
   3120  if (mProfilerController) {
   3121    const bool isProfiling = profiler_is_active();
   3122    CrashReporter::RecordAnnotationCString(
   3123        CrashReporter::Annotation::ProfilerChildShutdownPhase,
   3124        isProfiling ? "Profiling - GrabShutdownProfileAndShutdown"
   3125                    : "Not profiling - GrabShutdownProfileAndShutdown");
   3126    ProfileAndAdditionalInformation shutdownProfileAndAdditionalInformation =
   3127        mProfilerController->GrabShutdownProfileAndShutdown();
   3128    CrashReporter::RecordAnnotationCString(
   3129        CrashReporter::Annotation::ProfilerChildShutdownPhase,
   3130        isProfiling ? "Profiling - Destroying ChildProfilerController"
   3131                    : "Not profiling - Destroying ChildProfilerController");
   3132    mProfilerController = nullptr;
   3133    CrashReporter::RecordAnnotationCString(
   3134        CrashReporter::Annotation::ProfilerChildShutdownPhase,
   3135        isProfiling ? "Profiling - SendShutdownProfile (sending)"
   3136                    : "Not profiling - SendShutdownProfile (sending)");
   3137    if (const size_t len = shutdownProfileAndAdditionalInformation.SizeOf();
   3138        len >= size_t(IPC::Channel::kMaximumMessageSize)) {
   3139      shutdownProfileAndAdditionalInformation.mProfile = nsPrintfCString(
   3140          "*Profile from pid %u bigger (%zu) than IPC max (%zu)",
   3141          unsigned(profiler_current_process_id().ToNumber()), len,
   3142          size_t(IPC::Channel::kMaximumMessageSize));
   3143    }
   3144    // Send the shutdown profile to the parent process through our own
   3145    // message channel, which we know will survive for long enough.
   3146    bool sent =
   3147        SendShutdownProfile(shutdownProfileAndAdditionalInformation.mProfile);
   3148    CrashReporter::RecordAnnotationCString(
   3149        CrashReporter::Annotation::ProfilerChildShutdownPhase,
   3150        sent ? (isProfiling ? "Profiling - SendShutdownProfile (sent)"
   3151                            : "Not profiling - SendShutdownProfile (sent)")
   3152             : (isProfiling ? "Profiling - SendShutdownProfile (failed)"
   3153                            : "Not profiling - SendShutdownProfile (failed)"));
   3154  }
   3155 
   3156  if (PerfStats::GetCollectionMask() != 0) {
   3157    SendShutdownPerfStats(PerfStats::CollectLocalPerfStatsJSON());
   3158  }
   3159 
   3160  // Start a timer that will ensure we quickly exit after a reasonable period
   3161  // of time. Prevents shutdown hangs after our connection to the parent
   3162  // closes or when the parent is too busy to ever kill us.
   3163  ProcessChild::AppendToIPCShutdownStateAnnotation("StartForceKillTimer"_ns);
   3164  StartForceKillTimer();
   3165 
   3166  ProcessChild::AppendToIPCShutdownStateAnnotation(
   3167      "SendFinishShutdown (sending)"_ns);
   3168 
   3169  // Notify the parent that we are done with shutdown. This is sent with high
   3170  // priority and will just flag we are done.
   3171  (void)SendNotifyShutdownSuccess();
   3172 
   3173  // Now tell the parent to actually destroy our channel which will make end
   3174  // our process. This is expected to be the last event the parent will
   3175  // ever process for this ContentChild.
   3176  bool sent = SendFinishShutdown();
   3177 
   3178  ProcessChild::AppendToIPCShutdownStateAnnotation(
   3179      sent ? "SendFinishShutdown (sent)"_ns : "SendFinishShutdown (failed)"_ns);
   3180 }
   3181 
   3182 mozilla::ipc::IPCResult ContentChild::RecvUpdateWindow(
   3183    const uintptr_t& aChildId) {
   3184  MOZ_ASSERT(
   3185      false,
   3186      "ContentChild::RecvUpdateWindow calls unexpected on this platform.");
   3187  return IPC_FAIL_NO_REASON(this);
   3188 }
   3189 
   3190 PContentPermissionRequestChild*
   3191 ContentChild::AllocPContentPermissionRequestChild(
   3192    Span<const PermissionRequest> aRequests, nsIPrincipal* aPrincipal,
   3193    nsIPrincipal* aTopLevelPrincipal, const bool& aIsHandlingUserInput,
   3194    const bool& aMaybeUnsafePermissionDelegate, const TabId& aTabId) {
   3195  MOZ_CRASH("unused");
   3196  return nullptr;
   3197 }
   3198 
   3199 bool ContentChild::DeallocPContentPermissionRequestChild(
   3200    PContentPermissionRequestChild* actor) {
   3201  nsContentPermissionUtils::NotifyRemoveContentPermissionRequestChild(actor);
   3202  auto child = static_cast<RemotePermissionRequest*>(actor);
   3203  child->IPDLRelease();
   3204  return true;
   3205 }
   3206 
   3207 already_AddRefed<PWebBrowserPersistDocumentChild>
   3208 ContentChild::AllocPWebBrowserPersistDocumentChild(
   3209    PBrowserChild* aBrowser, const MaybeDiscarded<BrowsingContext>& aContext) {
   3210  return MakeAndAddRef<WebBrowserPersistDocumentChild>();
   3211 }
   3212 
   3213 mozilla::ipc::IPCResult ContentChild::RecvPWebBrowserPersistDocumentConstructor(
   3214    PWebBrowserPersistDocumentChild* aActor, PBrowserChild* aBrowser,
   3215    const MaybeDiscarded<BrowsingContext>& aContext) {
   3216  if (NS_WARN_IF(!aBrowser)) {
   3217    return IPC_FAIL_NO_REASON(this);
   3218  }
   3219 
   3220  if (aContext.IsNullOrDiscarded()) {
   3221    aActor->SendInitFailure(NS_ERROR_NO_CONTENT);
   3222    return IPC_OK();
   3223  }
   3224 
   3225  nsCOMPtr<Document> foundDoc = aContext.get()->GetDocument();
   3226 
   3227  if (!foundDoc) {
   3228    aActor->SendInitFailure(NS_ERROR_NO_CONTENT);
   3229  } else {
   3230    static_cast<WebBrowserPersistDocumentChild*>(aActor)->Start(foundDoc);
   3231  }
   3232  return IPC_OK();
   3233 }
   3234 
   3235 mozilla::ipc::IPCResult ContentChild::RecvPush(const nsCString& aScope,
   3236                                               nsIPrincipal* aPrincipal,
   3237                                               const nsString& aMessageId) {
   3238  PushMessageDispatcher dispatcher(aScope, aPrincipal, aMessageId, Nothing());
   3239  (void)NS_WARN_IF(NS_FAILED(dispatcher.NotifyObserversAndWorkers()));
   3240  return IPC_OK();
   3241 }
   3242 
   3243 mozilla::ipc::IPCResult ContentChild::RecvPushWithData(
   3244    const nsCString& aScope, nsIPrincipal* aPrincipal,
   3245    const nsString& aMessageId, nsTArray<uint8_t>&& aData) {
   3246  PushMessageDispatcher dispatcher(aScope, aPrincipal, aMessageId,
   3247                                   Some(std::move(aData)));
   3248  (void)NS_WARN_IF(NS_FAILED(dispatcher.NotifyObserversAndWorkers()));
   3249  return IPC_OK();
   3250 }
   3251 
   3252 mozilla::ipc::IPCResult ContentChild::RecvPushError(const nsCString& aScope,
   3253                                                    nsIPrincipal* aPrincipal,
   3254                                                    const nsString& aMessage,
   3255                                                    const uint32_t& aFlags) {
   3256  PushErrorDispatcher dispatcher(aScope, aPrincipal, aMessage, aFlags);
   3257  (void)NS_WARN_IF(NS_FAILED(dispatcher.NotifyObserversAndWorkers()));
   3258  return IPC_OK();
   3259 }
   3260 
   3261 mozilla::ipc::IPCResult
   3262 ContentChild::RecvNotifyPushSubscriptionModifiedObservers(
   3263    const nsCString& aScope, nsIPrincipal* aPrincipal) {
   3264  PushSubscriptionModifiedDispatcher dispatcher(aScope, aPrincipal);
   3265  (void)NS_WARN_IF(NS_FAILED(dispatcher.NotifyObservers()));
   3266  return IPC_OK();
   3267 }
   3268 
   3269 mozilla::ipc::IPCResult ContentChild::RecvBlobURLRegistration(
   3270    const nsCString& aURI, const IPCBlob& aBlob, nsIPrincipal* aPrincipal,
   3271    const nsCString& aPartitionKey) {
   3272  RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(aBlob);
   3273  MOZ_ASSERT(blobImpl);
   3274 
   3275  BlobURLProtocolHandler::AddDataEntry(aURI, aPrincipal, aPartitionKey,
   3276                                       blobImpl);
   3277  return IPC_OK();
   3278 }
   3279 
   3280 mozilla::ipc::IPCResult ContentChild::RecvBlobURLUnregistration(
   3281    const nsTArray<nsCString>& aURIs) {
   3282  BlobURLProtocolHandler::RemoveDataEntries(
   3283      aURIs,
   3284      /* aBroadcastToOtherProcesses = */ false);
   3285  return IPC_OK();
   3286 }
   3287 
   3288 void ContentChild::CreateGetFilesRequest(nsTArray<nsString>&& aDirectoryPaths,
   3289                                         bool aRecursiveFlag, nsID& aUUID,
   3290                                         GetFilesHelperChild* aChild) {
   3291  MOZ_ASSERT(aChild);
   3292  MOZ_ASSERT(!mGetFilesPendingRequests.Contains(aUUID));
   3293 
   3294  (void)SendGetFilesRequest(aUUID, aDirectoryPaths, aRecursiveFlag);
   3295  mGetFilesPendingRequests.InsertOrUpdate(aUUID, RefPtr{aChild});
   3296 }
   3297 
   3298 void ContentChild::DeleteGetFilesRequest(nsID& aUUID,
   3299                                         GetFilesHelperChild* aChild) {
   3300  MOZ_ASSERT(aChild);
   3301  MOZ_ASSERT(mGetFilesPendingRequests.Contains(aUUID));
   3302 
   3303  (void)SendDeleteGetFilesRequest(aUUID);
   3304  mGetFilesPendingRequests.Remove(aUUID);
   3305 }
   3306 
   3307 mozilla::ipc::IPCResult ContentChild::RecvGetFilesResponse(
   3308    const nsID& aUUID, const GetFilesResponseResult& aResult) {
   3309  RefPtr<GetFilesHelperChild> child;
   3310 
   3311  // This object can already been deleted in case DeleteGetFilesRequest has
   3312  // been called when the response was sending by the parent.
   3313  if (!mGetFilesPendingRequests.Remove(aUUID, getter_AddRefs(child))) {
   3314    return IPC_OK();
   3315  }
   3316 
   3317  if (aResult.type() == GetFilesResponseResult::TGetFilesResponseFailure) {
   3318    child->Finished(aResult.get_GetFilesResponseFailure().errorCode());
   3319  } else {
   3320    MOZ_ASSERT(aResult.type() ==
   3321               GetFilesResponseResult::TGetFilesResponseSuccess);
   3322 
   3323    const nsTArray<IPCBlob>& ipcBlobs =
   3324        aResult.get_GetFilesResponseSuccess().blobs();
   3325 
   3326    bool succeeded = true;
   3327    for (uint32_t i = 0; succeeded && i < ipcBlobs.Length(); ++i) {
   3328      RefPtr<BlobImpl> impl = IPCBlobUtils::Deserialize(ipcBlobs[i]);
   3329      succeeded = child->AppendBlobImpl(impl);
   3330    }
   3331 
   3332    child->Finished(succeeded ? NS_OK : NS_ERROR_OUT_OF_MEMORY);
   3333  }
   3334  return IPC_OK();
   3335 }
   3336 
   3337 /* static */
   3338 void ContentChild::FatalErrorIfNotUsingGPUProcess(const char* const aErrorMsg,
   3339                                                  GeckoChildID aChildID) {
   3340  // If we're communicating with the same process or the UI process then we
   3341  // want to crash normally. Otherwise we want to just warn as the other end
   3342  // must be the GPU process and it crashing shouldn't be fatal for us.
   3343  if (aChildID == XRE_GetChildID() || aChildID == 0) {
   3344    mozilla::ipc::FatalError(aErrorMsg, false);
   3345  } else {
   3346    nsAutoCString formattedMessage("IPDL error: \"");
   3347    formattedMessage.AppendASCII(aErrorMsg);
   3348    formattedMessage.AppendLiteral(R"(".)");
   3349    NS_WARNING(formattedMessage.get());
   3350  }
   3351 }
   3352 
   3353 PURLClassifierChild* ContentChild::AllocPURLClassifierChild(
   3354    nsIPrincipal* aPrincipal, bool* aSuccess) {
   3355  *aSuccess = true;
   3356  return new URLClassifierChild();
   3357 }
   3358 
   3359 bool ContentChild::DeallocPURLClassifierChild(PURLClassifierChild* aActor) {
   3360  MOZ_ASSERT(aActor);
   3361  delete aActor;
   3362  return true;
   3363 }
   3364 
   3365 PURLClassifierLocalChild* ContentChild::AllocPURLClassifierLocalChild(
   3366    nsIURI* aUri, Span<const IPCURLClassifierFeature> aFeatures) {
   3367  return new URLClassifierLocalChild();
   3368 }
   3369 
   3370 bool ContentChild::DeallocPURLClassifierLocalChild(
   3371    PURLClassifierLocalChild* aActor) {
   3372  MOZ_ASSERT(aActor);
   3373  delete aActor;
   3374  return true;
   3375 }
   3376 
   3377 PURLClassifierLocalByNameChild*
   3378 ContentChild::AllocPURLClassifierLocalByNameChild(
   3379    nsIURI* aUri, Span<const nsCString> aFeatures,
   3380    const nsIUrlClassifierFeature::listType& aListType) {
   3381  return new URLClassifierLocalByNameChild();
   3382 }
   3383 
   3384 bool ContentChild::DeallocPURLClassifierLocalByNameChild(
   3385    PURLClassifierLocalByNameChild* aActor) {
   3386  MOZ_ASSERT(aActor);
   3387  delete aActor;
   3388  return true;
   3389 }
   3390 
   3391 PSessionStorageObserverChild*
   3392 ContentChild::AllocPSessionStorageObserverChild() {
   3393  MOZ_CRASH(
   3394      "PSessionStorageObserverChild actors should be manually constructed!");
   3395 }
   3396 
   3397 bool ContentChild::DeallocPSessionStorageObserverChild(
   3398    PSessionStorageObserverChild* aActor) {
   3399  MOZ_ASSERT(aActor);
   3400 
   3401  delete aActor;
   3402  return true;
   3403 }
   3404 
   3405 mozilla::ipc::IPCResult ContentChild::RecvProvideAnonymousTemporaryFile(
   3406    const uint64_t& aID, const FileDescOrError& aFDOrError) {
   3407  mozilla::UniquePtr<AnonymousTemporaryFileCallback> callback;
   3408  mPendingAnonymousTemporaryFiles.Remove(aID, &callback);
   3409  MOZ_ASSERT(callback);
   3410 
   3411  PRFileDesc* prfile = nullptr;
   3412  if (aFDOrError.type() == FileDescOrError::Tnsresult) {
   3413    DebugOnly<nsresult> rv = aFDOrError.get_nsresult();
   3414    MOZ_ASSERT(NS_FAILED(rv));
   3415  } else {
   3416    auto rawFD = aFDOrError.get_FileDescriptor().ClonePlatformHandle();
   3417    prfile = PR_ImportFile(PROsfd(rawFD.release()));
   3418  }
   3419  (*callback)(prfile);
   3420  return IPC_OK();
   3421 }
   3422 
   3423 nsresult ContentChild::AsyncOpenAnonymousTemporaryFile(
   3424    const AnonymousTemporaryFileCallback& aCallback) {
   3425  MOZ_ASSERT(NS_IsMainThread());
   3426 
   3427  static uint64_t id = 0;
   3428  auto newID = id++;
   3429  if (!SendRequestAnonymousTemporaryFile(newID)) {
   3430    return NS_ERROR_FAILURE;
   3431  }
   3432 
   3433  // Remember the association with the callback.
   3434  MOZ_ASSERT(!mPendingAnonymousTemporaryFiles.Get(newID));
   3435  mPendingAnonymousTemporaryFiles.GetOrInsertNew(newID, aCallback);
   3436  return NS_OK;
   3437 }
   3438 
   3439 mozilla::ipc::IPCResult ContentChild::RecvSetPermissionsWithKey(
   3440    const nsCString& aPermissionKey, nsTArray<IPC::Permission>&& aPerms) {
   3441  RefPtr<PermissionManager> permManager = PermissionManager::GetInstance();
   3442  if (permManager) {
   3443    permManager->SetPermissionsWithKey(aPermissionKey, aPerms);
   3444  }
   3445 
   3446  return IPC_OK();
   3447 }
   3448 
   3449 mozilla::ipc::IPCResult ContentChild::RecvRefreshScreens(
   3450    nsTArray<ScreenDetails>&& aScreens) {
   3451  ScreenManager& screenManager = ScreenManager::GetSingleton();
   3452  screenManager.Refresh(std::move(aScreens));
   3453  return IPC_OK();
   3454 }
   3455 
   3456 mozilla::ipc::IPCResult ContentChild::RecvShareCodeCoverageMutex(
   3457    CrossProcessMutexHandle aHandle) {
   3458 #ifdef MOZ_CODE_COVERAGE
   3459  CodeCoverageHandler::Init(std::move(aHandle));
   3460  return IPC_OK();
   3461 #else
   3462  MOZ_CRASH("Shouldn't receive this message in non-code coverage builds!");
   3463 #endif
   3464 }
   3465 
   3466 mozilla::ipc::IPCResult ContentChild::RecvFlushCodeCoverageCounters(
   3467    FlushCodeCoverageCountersResolver&& aResolver) {
   3468 #ifdef MOZ_CODE_COVERAGE
   3469  CodeCoverageHandler::FlushCounters();
   3470  aResolver(/* unused */ true);
   3471  return IPC_OK();
   3472 #else
   3473  MOZ_CRASH("Shouldn't receive this message in non-code coverage builds!");
   3474 #endif
   3475 }
   3476 
   3477 mozilla::ipc::IPCResult ContentChild::RecvSetInputEventQueueEnabled() {
   3478  nsThreadManager::get().EnableMainThreadEventPrioritization();
   3479  return IPC_OK();
   3480 }
   3481 
   3482 mozilla::ipc::IPCResult ContentChild::RecvFlushInputEventQueue() {
   3483  nsThreadManager::get().FlushInputEventPrioritization();
   3484  return IPC_OK();
   3485 }
   3486 
   3487 mozilla::ipc::IPCResult ContentChild::RecvSuspendInputEventQueue() {
   3488  nsThreadManager::get().SuspendInputEventPrioritization();
   3489  return IPC_OK();
   3490 }
   3491 
   3492 mozilla::ipc::IPCResult ContentChild::RecvResumeInputEventQueue() {
   3493  nsThreadManager::get().ResumeInputEventPrioritization();
   3494  return IPC_OK();
   3495 }
   3496 
   3497 mozilla::ipc::IPCResult ContentChild::RecvAddDynamicScalars(
   3498    nsTArray<DynamicScalarDefinition>&& aDefs) {
   3499  TelemetryIPC::AddDynamicScalarDefinitions(aDefs);
   3500  return IPC_OK();
   3501 }
   3502 
   3503 mozilla::ipc::IPCResult ContentChild::RecvCrossProcessRedirect(
   3504    RedirectToRealChannelArgs&& aArgs,
   3505    nsTArray<Endpoint<extensions::PStreamFilterParent>>&& aEndpoints,
   3506    CrossProcessRedirectResolver&& aResolve) {
   3507  nsCOMPtr<nsILoadInfo> loadInfo;
   3508  nsresult rv = mozilla::ipc::LoadInfoArgsToLoadInfo(
   3509      aArgs.loadInfo(), NOT_REMOTE_TYPE, getter_AddRefs(loadInfo));
   3510  if (NS_FAILED(rv)) {
   3511    MOZ_DIAGNOSTIC_CRASH("LoadInfoArgsToLoadInfo failed");
   3512    return IPC_OK();
   3513  }
   3514 
   3515  nsCOMPtr<nsIChannel> newChannel;
   3516  MOZ_ASSERT((aArgs.loadStateInternalLoadFlags() &
   3517              nsDocShell::InternalLoad::INTERNAL_LOAD_FLAGS_IS_SRCDOC) ||
   3518             aArgs.srcdocData().IsVoid());
   3519  rv = nsDocShell::CreateRealChannelForDocument(
   3520      getter_AddRefs(newChannel), aArgs.uri(), loadInfo, nullptr,
   3521      aArgs.newLoadFlags(), aArgs.srcdocData(), aArgs.baseUri());
   3522 
   3523  if (RefPtr<HttpBaseChannel> httpChannel = do_QueryObject(newChannel)) {
   3524    httpChannel->SetEarlyHints(std::move(aArgs.earlyHints()));
   3525    httpChannel->SetEarlyHintLinkType(aArgs.earlyHintLinkType());
   3526  }
   3527 
   3528  // This is used to report any errors back to the parent by calling
   3529  // CrossProcessRedirectFinished.
   3530  RefPtr<HttpChannelChild> httpChild = do_QueryObject(newChannel);
   3531  auto resolve = [=](const nsresult& aRv) {
   3532    nsresult rv = aRv;
   3533    if (httpChild) {
   3534      rv = httpChild->CrossProcessRedirectFinished(rv);
   3535    }
   3536    aResolve(rv);
   3537  };
   3538  auto scopeExit = MakeScopeExit([&]() { resolve(rv); });
   3539 
   3540  if (NS_FAILED(rv)) {
   3541    return IPC_OK();
   3542  }
   3543 
   3544  if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel)) {
   3545    rv = httpChannel->SetChannelId(aArgs.channelId());
   3546  }
   3547  if (NS_FAILED(rv)) {
   3548    return IPC_OK();
   3549  }
   3550 
   3551  rv = newChannel->SetOriginalURI(aArgs.originalURI());
   3552  if (NS_FAILED(rv)) {
   3553    return IPC_OK();
   3554  }
   3555 
   3556  if (nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal =
   3557          do_QueryInterface(newChannel)) {
   3558    rv = httpChannelInternal->SetRedirectMode(aArgs.redirectMode());
   3559  }
   3560  if (NS_FAILED(rv)) {
   3561    return IPC_OK();
   3562  }
   3563 
   3564  if (aArgs.init()) {
   3565    HttpBaseChannel::ReplacementChannelConfig config(std::move(*aArgs.init()));
   3566    HttpBaseChannel::ConfigureReplacementChannel(
   3567        newChannel, config,
   3568        HttpBaseChannel::ReplacementReason::DocumentChannel);
   3569  }
   3570 
   3571  if (aArgs.contentDisposition()) {
   3572    newChannel->SetContentDisposition(*aArgs.contentDisposition());
   3573  }
   3574 
   3575  if (aArgs.contentDispositionFilename()) {
   3576    newChannel->SetContentDispositionFilename(
   3577        *aArgs.contentDispositionFilename());
   3578  }
   3579 
   3580  if (nsCOMPtr<nsIChildChannel> childChannel = do_QueryInterface(newChannel)) {
   3581    // Connect to the parent if this is a remote channel. If it's entirely
   3582    // handled locally, then we'll call AsyncOpen from the docshell when
   3583    // we complete the setup
   3584    rv = childChannel->ConnectParent(
   3585        aArgs.registrarId());  // creates parent channel
   3586    if (NS_FAILED(rv)) {
   3587      return IPC_OK();
   3588    }
   3589  }
   3590 
   3591  // We need to copy the property bag before signaling that the channel
   3592  // is ready so that the nsDocShell can retrieve the history data when called.
   3593  if (nsCOMPtr<nsIWritablePropertyBag> bag = do_QueryInterface(newChannel)) {
   3594    nsHashPropertyBag::CopyFrom(bag, aArgs.properties());
   3595  }
   3596 
   3597  RefPtr<nsDocShellLoadState> loadState;
   3598  rv = nsDocShellLoadState::CreateFromPendingChannel(
   3599      newChannel, aArgs.loadIdentifier(), aArgs.registrarId(),
   3600      getter_AddRefs(loadState));
   3601  if (NS_WARN_IF(NS_FAILED(rv))) {
   3602    return IPC_OK();
   3603  }
   3604  loadState->SetLoadFlags(aArgs.loadStateExternalLoadFlags());
   3605  loadState->SetInternalLoadFlags(aArgs.loadStateInternalLoadFlags());
   3606  if (IsValidLoadType(aArgs.loadStateLoadType())) {
   3607    loadState->SetLoadType(aArgs.loadStateLoadType());
   3608  }
   3609 
   3610  if (aArgs.loadingSessionHistoryInfo().isSome()) {
   3611    loadState->SetLoadingSessionHistoryInfo(
   3612        aArgs.loadingSessionHistoryInfo().ref());
   3613  }
   3614  if (aArgs.originalUriString().isSome()) {
   3615    loadState->SetOriginalURIString(aArgs.originalUriString().ref());
   3616  }
   3617 
   3618  RefPtr<ChildProcessChannelListener> processListener =
   3619      ChildProcessChannelListener::GetSingleton();
   3620  // The listener will call completeRedirectSetup or asyncOpen on the channel.
   3621  processListener->OnChannelReady(loadState, aArgs.loadIdentifier(),
   3622                                  std::move(aEndpoints), aArgs.timing(),
   3623                                  std::move(resolve));
   3624  scopeExit.release();
   3625 
   3626  // scopeExit will call CrossProcessRedirectFinished(rv) here
   3627  return IPC_OK();
   3628 }
   3629 
   3630 mozilla::ipc::IPCResult ContentChild::RecvStartDelayedAutoplayMediaComponents(
   3631    const MaybeDiscarded<BrowsingContext>& aContext) {
   3632  if (NS_WARN_IF(aContext.IsNullOrDiscarded())) {
   3633    return IPC_OK();
   3634  }
   3635 
   3636  aContext.get()->StartDelayedAutoplayMediaComponents();
   3637  return IPC_OK();
   3638 }
   3639 
   3640 mozilla::ipc::IPCResult ContentChild::RecvUpdateMediaControlAction(
   3641    const MaybeDiscarded<BrowsingContext>& aContext,
   3642    const MediaControlAction& aAction) {
   3643  if (NS_WARN_IF(aContext.IsNullOrDiscarded())) {
   3644    return IPC_OK();
   3645  }
   3646 
   3647  ContentMediaControlKeyHandler::HandleMediaControlAction(aContext.get(),
   3648                                                          aAction);
   3649  return IPC_OK();
   3650 }
   3651 
   3652 mozilla::ipc::IPCResult ContentChild::RecvOnAllowAccessFor(
   3653    const MaybeDiscarded<BrowsingContext>& aContext,
   3654    const nsCString& aTrackingOrigin, uint32_t aCookieBehavior,
   3655    const ContentBlockingNotifier::StorageAccessPermissionGrantedReason&
   3656        aReason) {
   3657  MOZ_ASSERT(!aContext.IsNull(), "Browsing context cannot be null");
   3658 
   3659  StorageAccessAPIHelper::OnAllowAccessFor(
   3660      aContext.GetMaybeDiscarded(), aTrackingOrigin, aCookieBehavior, aReason);
   3661 
   3662  return IPC_OK();
   3663 }
   3664 
   3665 mozilla::ipc::IPCResult ContentChild::RecvOnContentBlockingDecision(
   3666    const MaybeDiscarded<BrowsingContext>& aContext,
   3667    const ContentBlockingNotifier::BlockingDecision& aDecision,
   3668    uint32_t aRejectedReason) {
   3669  MOZ_ASSERT(!aContext.IsNull(), "Browsing context cannot be null");
   3670 
   3671  nsCOMPtr<nsPIDOMWindowOuter> outer = aContext.get()->GetDOMWindow();
   3672  if (!outer) {
   3673    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
   3674            ("ChildIPC: Trying to send a message to a context without a outer "
   3675             "window"));
   3676    return IPC_OK();
   3677  }
   3678 
   3679  nsCOMPtr<nsPIDOMWindowInner> inner = outer->GetCurrentInnerWindow();
   3680  if (!inner) {
   3681    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
   3682            ("ChildIPC: Trying to send a message to a context without a inner "
   3683             "window"));
   3684    return IPC_OK();
   3685  }
   3686 
   3687  ContentBlockingNotifier::OnDecision(inner, aDecision, aRejectedReason);
   3688  return IPC_OK();
   3689 }
   3690 
   3691 #ifdef NIGHTLY_BUILD
   3692 void ContentChild::OnChannelReceivedMessage(const Message& aMsg) {
   3693  if (nsContentUtils::IsMessageInputEvent(aMsg)) {
   3694    mPendingInputEvents++;
   3695  }
   3696 }
   3697 
   3698 PContentChild::Result ContentChild::OnMessageReceived(const Message& aMsg) {
   3699  if (nsContentUtils::IsMessageInputEvent(aMsg)) {
   3700    DebugOnly<uint32_t> prevEvts = mPendingInputEvents--;
   3701    MOZ_ASSERT(prevEvts > 0);
   3702  }
   3703 
   3704  return PContentChild::OnMessageReceived(aMsg);
   3705 }
   3706 
   3707 PContentChild::Result ContentChild::OnMessageReceived(
   3708    const Message& aMsg, UniquePtr<Message>& aReply) {
   3709  return PContentChild::OnMessageReceived(aMsg, aReply);
   3710 }
   3711 #endif
   3712 
   3713 mozilla::ipc::IPCResult ContentChild::RecvCreateBrowsingContext(
   3714    uint64_t aGroupId, BrowsingContext::IPCInitializer&& aInit) {
   3715  // We can't already have a BrowsingContext with this ID.
   3716  if (RefPtr<BrowsingContext> existing = BrowsingContext::Get(aInit.mId)) {
   3717    return IPC_FAIL(this, "Browsing context already exists");
   3718  }
   3719 
   3720  RefPtr<WindowContext> parent = WindowContext::GetById(aInit.mParentId);
   3721  if (!parent && aInit.mParentId != 0) {
   3722    // Handle this case by ignoring the request, as parent must be in the
   3723    // process of being discarded.
   3724    // In the future it would be nice to avoid sending this message to the child
   3725    // at all.
   3726    NS_WARNING("Attempt to attach BrowsingContext to discarded parent");
   3727    return IPC_OK();
   3728  }
   3729 
   3730  RefPtr<BrowsingContextGroup> group =
   3731      BrowsingContextGroup::GetOrCreate(aGroupId);
   3732  return BrowsingContext::CreateFromIPC(std::move(aInit), group, nullptr);
   3733 }
   3734 
   3735 mozilla::ipc::IPCResult ContentChild::RecvDiscardBrowsingContext(
   3736    const MaybeDiscarded<BrowsingContext>& aContext, bool aDoDiscard,
   3737    DiscardBrowsingContextResolver&& aResolve) {
   3738  if (BrowsingContext* context = aContext.GetMaybeDiscarded()) {
   3739    if (aDoDiscard && !context->IsDiscarded()) {
   3740      context->Detach(/* aFromIPC */ true);
   3741    }
   3742    context->AddDiscardListener(aResolve);
   3743    return IPC_OK();
   3744  }
   3745 
   3746  // Immediately resolve the promise, as we've received the message. This will
   3747  // allow the parent process to discard references to this BC.
   3748  aResolve(true);
   3749  return IPC_OK();
   3750 }
   3751 
   3752 mozilla::ipc::IPCResult ContentChild::RecvRegisterBrowsingContextGroup(
   3753    uint64_t aGroupId, nsTArray<SyncedContextInitializer>&& aInits,
   3754    nsTArray<OriginAgentClusterInitializer>&& aUseOriginAgentCluster) {
   3755  RefPtr<BrowsingContextGroup> group =
   3756      BrowsingContextGroup::GetOrCreate(aGroupId);
   3757 
   3758  for (auto& entry : aUseOriginAgentCluster) {
   3759    group->SetUseOriginAgentClusterFromIPC(entry.principal(),
   3760                                           entry.useOriginAgentCluster());
   3761  }
   3762 
   3763  // Each of the initializers in aInits is sorted in pre-order, so our parent
   3764  // should always be available before the element itself.
   3765  for (auto& initUnion : aInits) {
   3766    switch (initUnion.type()) {
   3767      case SyncedContextInitializer::TBrowsingContextInitializer: {
   3768        auto& init = initUnion.get_BrowsingContextInitializer();
   3769 #ifdef DEBUG
   3770        RefPtr<BrowsingContext> existing = BrowsingContext::Get(init.mId);
   3771        MOZ_ASSERT(!existing, "BrowsingContext must not exist yet!");
   3772 
   3773        RefPtr<WindowContext> parent = init.GetParent();
   3774        MOZ_ASSERT_IF(parent, parent->Group() == group);
   3775 #endif
   3776 
   3777        BrowsingContext::CreateFromIPC(std::move(init), group, nullptr);
   3778        break;
   3779      }
   3780      case SyncedContextInitializer::TWindowContextInitializer: {
   3781        auto& init = initUnion.get_WindowContextInitializer();
   3782 #ifdef DEBUG
   3783        RefPtr<WindowContext> existing =
   3784            WindowContext::GetById(init.mInnerWindowId);
   3785        MOZ_ASSERT(!existing, "WindowContext must not exist yet!");
   3786        RefPtr<BrowsingContext> parent =
   3787            BrowsingContext::Get(init.mBrowsingContextId);
   3788        MOZ_ASSERT(parent && parent->Group() == group);
   3789 #endif
   3790 
   3791        WindowContext::CreateFromIPC(std::move(init));
   3792        break;
   3793      };
   3794      default:
   3795        MOZ_ASSERT_UNREACHABLE();
   3796    }
   3797  }
   3798 
   3799  return IPC_OK();
   3800 }
   3801 
   3802 mozilla::ipc::IPCResult ContentChild::RecvDestroyBrowsingContextGroup(
   3803    uint64_t aGroupId) {
   3804  if (RefPtr<BrowsingContextGroup> group =
   3805          BrowsingContextGroup::GetExisting(aGroupId)) {
   3806    group->ChildDestroy();
   3807  }
   3808  return IPC_OK();
   3809 }
   3810 
   3811 mozilla::ipc::IPCResult ContentChild::RecvSetUseOriginAgentCluster(
   3812    uint64_t aGroupId, nsIPrincipal* aPrincipal, bool aUseOriginAgentCluster) {
   3813  RefPtr<BrowsingContextGroup> group =
   3814      BrowsingContextGroup::GetOrCreate(aGroupId);
   3815  group->SetUseOriginAgentClusterFromIPC(aPrincipal, aUseOriginAgentCluster);
   3816  return IPC_OK();
   3817 }
   3818 
   3819 mozilla::ipc::IPCResult ContentChild::RecvWindowClose(
   3820    const MaybeDiscarded<BrowsingContext>& aContext, bool aTrustedCaller) {
   3821  if (aContext.IsNullOrDiscarded()) {
   3822    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
   3823            ("ChildIPC: Trying to send a message to dead or detached context"));
   3824    return IPC_OK();
   3825  }
   3826 
   3827  nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow();
   3828  if (!window) {
   3829    MOZ_LOG(
   3830        BrowsingContext::GetLog(), LogLevel::Debug,
   3831        ("ChildIPC: Trying to send a message to a context without a window"));
   3832    return IPC_OK();
   3833  }
   3834 
   3835  // Call `GetDocument()` to force the document and its inner window to be
   3836  // created, as it would be forced to be created if this call was being
   3837  // performed in-process.
   3838  if (NS_WARN_IF(!aContext.get()->GetDocument())) {
   3839    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
   3840            ("ChildIPC: Trying to send a message to a context but document "
   3841             "creation failed"));
   3842    return IPC_OK();
   3843  }
   3844 
   3845  nsGlobalWindowOuter::Cast(window)->CloseOuter(aTrustedCaller);
   3846  return IPC_OK();
   3847 }
   3848 
   3849 mozilla::ipc::IPCResult ContentChild::RecvWindowFocus(
   3850    const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType,
   3851    uint64_t aActionId) {
   3852  if (aContext.IsNullOrDiscarded()) {
   3853    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
   3854            ("ChildIPC: Trying to send a message to dead or detached context"));
   3855    return IPC_OK();
   3856  }
   3857 
   3858  nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow();
   3859  if (!window) {
   3860    MOZ_LOG(
   3861        BrowsingContext::GetLog(), LogLevel::Debug,
   3862        ("ChildIPC: Trying to send a message to a context without a window"));
   3863    return IPC_OK();
   3864  }
   3865 
   3866  // Call `GetDocument()` to force the document and its inner window to be
   3867  // created, as it would be forced to be created if this call was being
   3868  // performed in-process.
   3869  if (NS_WARN_IF(!aContext.get()->GetDocument())) {
   3870    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
   3871            ("ChildIPC: Trying to send a message to a context but document "
   3872             "creation failed"));
   3873    return IPC_OK();
   3874  }
   3875 
   3876  nsGlobalWindowOuter::Cast(window)->FocusOuter(
   3877      aCallerType, /* aFromOtherProcess */ true, aActionId);
   3878  return IPC_OK();
   3879 }
   3880 
   3881 mozilla::ipc::IPCResult ContentChild::RecvWindowBlur(
   3882    const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType) {
   3883  if (aContext.IsNullOrDiscarded()) {
   3884    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
   3885            ("ChildIPC: Trying to send a message to dead or detached context"));
   3886    return IPC_OK();
   3887  }
   3888 
   3889  nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow();
   3890  if (!window) {
   3891    MOZ_LOG(
   3892        BrowsingContext::GetLog(), LogLevel::Debug,
   3893        ("ChildIPC: Trying to send a message to a context without a window"));
   3894    return IPC_OK();
   3895  }
   3896 
   3897  // Call `GetDocument()` to force the document and its inner window to be
   3898  // created, as it would be forced to be created if this call was being
   3899  // performed in-process.
   3900  if (NS_WARN_IF(!aContext.get()->GetDocument())) {
   3901    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
   3902            ("ChildIPC: Trying to send a message to a context but document "
   3903             "creation failed"));
   3904    return IPC_OK();
   3905  }
   3906 
   3907  nsGlobalWindowOuter::Cast(window)->BlurOuter(aCallerType);
   3908  return IPC_OK();
   3909 }
   3910 
   3911 mozilla::ipc::IPCResult ContentChild::RecvRaiseWindow(
   3912    const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType,
   3913    uint64_t aActionId) {
   3914  if (aContext.IsNullOrDiscarded()) {
   3915    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
   3916            ("ChildIPC: Trying to send a message to dead or detached context"));
   3917    return IPC_OK();
   3918  }
   3919 
   3920  nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow();
   3921  if (!window) {
   3922    MOZ_LOG(
   3923        BrowsingContext::GetLog(), LogLevel::Debug,
   3924        ("ChildIPC: Trying to send a message to a context without a window"));
   3925    return IPC_OK();
   3926  }
   3927 
   3928  if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
   3929    fm->RaiseWindow(window, aCallerType, aActionId);
   3930  }
   3931  return IPC_OK();
   3932 }
   3933 
   3934 mozilla::ipc::IPCResult ContentChild::RecvAdjustWindowFocus(
   3935    const MaybeDiscarded<BrowsingContext>& aContext, bool aIsVisible,
   3936    uint64_t aActionId, bool aShouldClearAncestorFocus,
   3937    const MaybeDiscarded<BrowsingContext>& aAncestorBrowsingContextToFocus) {
   3938  if (aContext.IsNullOrDiscarded()) {
   3939    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
   3940            ("ChildIPC: Trying to send a message to dead or detached context"));
   3941    return IPC_OK();
   3942  }
   3943 
   3944  if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
   3945    RefPtr<BrowsingContext> bc = aContext.get();
   3946    RefPtr<BrowsingContext> ancestor =
   3947        aAncestorBrowsingContextToFocus.IsNullOrDiscarded()
   3948            ? nullptr
   3949            : aAncestorBrowsingContextToFocus.get();
   3950    fm->AdjustInProcessWindowFocus(bc, false, aIsVisible, aActionId,
   3951                                   aShouldClearAncestorFocus, ancestor);
   3952  }
   3953  return IPC_OK();
   3954 }
   3955 
   3956 mozilla::ipc::IPCResult ContentChild::RecvClearFocus(
   3957    const MaybeDiscarded<BrowsingContext>& aContext) {
   3958  if (aContext.IsNullOrDiscarded()) {
   3959    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
   3960            ("ChildIPC: Trying to send a message to dead or detached context"));
   3961    return IPC_OK();
   3962  }
   3963 
   3964  nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow();
   3965  if (!window) {
   3966    MOZ_LOG(
   3967        BrowsingContext::GetLog(), LogLevel::Debug,
   3968        ("ChildIPC: Trying to send a message to a context without a window"));
   3969    return IPC_OK();
   3970  }
   3971 
   3972  if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
   3973    fm->ClearFocus(window);
   3974  }
   3975  return IPC_OK();
   3976 }
   3977 
   3978 mozilla::ipc::IPCResult ContentChild::RecvSetFocusedBrowsingContext(
   3979    const MaybeDiscarded<BrowsingContext>& aContext, uint64_t aActionId) {
   3980  if (aContext.IsNullOrDiscarded()) {
   3981    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
   3982            ("ChildIPC: Trying to send a message to dead or detached context"));
   3983    return IPC_OK();
   3984  }
   3985 
   3986  nsFocusManager* fm = nsFocusManager::GetFocusManager();
   3987  if (fm) {
   3988    fm->SetFocusedBrowsingContextFromOtherProcess(aContext.get(), aActionId);
   3989  }
   3990  return IPC_OK();
   3991 }
   3992 
   3993 mozilla::ipc::IPCResult ContentChild::RecvSetActiveBrowsingContext(
   3994    const MaybeDiscarded<BrowsingContext>& aContext, uint64_t aActionId) {
   3995  if (aContext.IsNullOrDiscarded()) {
   3996    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
   3997            ("ChildIPC: Trying to send a message to dead or detached context"));
   3998    return IPC_OK();
   3999  }
   4000 
   4001  nsFocusManager* fm = nsFocusManager::GetFocusManager();
   4002  if (fm) {
   4003    fm->SetActiveBrowsingContextFromOtherProcess(aContext.get(), aActionId);
   4004  }
   4005  return IPC_OK();
   4006 }
   4007 
   4008 mozilla::ipc::IPCResult ContentChild::RecvAbortOrientationPendingPromises(
   4009    const MaybeDiscarded<BrowsingContext>& aContext) {
   4010  if (aContext.IsNullOrDiscarded()) {
   4011    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
   4012            ("ChildIPC: Trying to send a message to dead or detached context"));
   4013    return IPC_OK();
   4014  }
   4015 
   4016  dom::ScreenOrientation::AbortInProcessOrientationPromises(aContext.get());
   4017  return IPC_OK();
   4018 }
   4019 
   4020 mozilla::ipc::IPCResult ContentChild::RecvUnsetActiveBrowsingContext(
   4021    const MaybeDiscarded<BrowsingContext>& aContext, uint64_t aActionId) {
   4022  if (aContext.IsNullOrDiscarded()) {
   4023    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
   4024            ("ChildIPC: Trying to send a message to dead or detached context"));
   4025    return IPC_OK();
   4026  }
   4027 
   4028  nsFocusManager* fm = nsFocusManager::GetFocusManager();
   4029  if (fm) {
   4030    fm->UnsetActiveBrowsingContextFromOtherProcess(aContext.get(), aActionId);
   4031  }
   4032  return IPC_OK();
   4033 }
   4034 
   4035 mozilla::ipc::IPCResult ContentChild::RecvSetFocusedElement(
   4036    const MaybeDiscarded<BrowsingContext>& aContext, bool aNeedsFocus) {
   4037  if (aContext.IsNullOrDiscarded()) {
   4038    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
   4039            ("ChildIPC: Trying to send a message to dead or detached context"));
   4040    return IPC_OK();
   4041  }
   4042 
   4043  nsCOMPtr<nsPIDOMWindowOuter> window = aContext.get()->GetDOMWindow();
   4044  if (!window) {
   4045    MOZ_LOG(
   4046        BrowsingContext::GetLog(), LogLevel::Debug,
   4047        ("ChildIPC: Trying to send a message to a context without a window"));
   4048    return IPC_OK();
   4049  }
   4050 
   4051  window->SetFocusedElement(nullptr, 0, aNeedsFocus);
   4052  return IPC_OK();
   4053 }
   4054 
   4055 mozilla::ipc::IPCResult ContentChild::RecvFinalizeFocusOuter(
   4056    const MaybeDiscarded<BrowsingContext>& aContext, bool aCanFocus,
   4057    CallerType aCallerType) {
   4058  if (aContext.IsNullOrDiscarded()) {
   4059    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
   4060            ("ChildIPC: Trying to send a message to dead or detached context"));
   4061    return IPC_OK();
   4062  }
   4063 
   4064  if (Element* frame = aContext.get()->GetEmbedderElement()) {
   4065    nsContentUtils::RequestFrameFocus(*frame, aCanFocus, aCallerType);
   4066  }
   4067 
   4068  return IPC_OK();
   4069 }
   4070 
   4071 mozilla::ipc::IPCResult ContentChild::RecvBlurToChild(
   4072    const MaybeDiscarded<BrowsingContext>& aFocusedBrowsingContext,
   4073    const MaybeDiscarded<BrowsingContext>& aBrowsingContextToClear,
   4074    const MaybeDiscarded<BrowsingContext>& aAncestorBrowsingContextToFocus,
   4075    bool aIsLeavingDocument, bool aAdjustWidget, uint64_t aActionId) {
   4076  if (aFocusedBrowsingContext.IsNullOrDiscarded()) {
   4077    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
   4078            ("ChildIPC: Trying to send a message to dead or detached context"));
   4079    return IPC_OK();
   4080  }
   4081 
   4082  RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager();
   4083  if (MOZ_UNLIKELY(!fm)) {
   4084    return IPC_OK();
   4085  }
   4086 
   4087  RefPtr<BrowsingContext> toClear = aBrowsingContextToClear.IsDiscarded()
   4088                                        ? nullptr
   4089                                        : aBrowsingContextToClear.get();
   4090  RefPtr<BrowsingContext> toFocus =
   4091      aAncestorBrowsingContextToFocus.IsDiscarded()
   4092          ? nullptr
   4093          : aAncestorBrowsingContextToFocus.get();
   4094 
   4095  RefPtr<BrowsingContext> focusedBrowsingContext =
   4096      aFocusedBrowsingContext.get();
   4097 
   4098  fm->BlurFromOtherProcess(focusedBrowsingContext, toClear, toFocus,
   4099                           aIsLeavingDocument, aAdjustWidget, aActionId);
   4100  return IPC_OK();
   4101 }
   4102 
   4103 mozilla::ipc::IPCResult ContentChild::RecvSetupFocusedAndActive(
   4104    const MaybeDiscarded<BrowsingContext>& aFocusedBrowsingContext,
   4105    uint64_t aActionIdForFocused,
   4106    const MaybeDiscarded<BrowsingContext>& aActiveBrowsingContext,
   4107    uint64_t aActionIdForActive) {
   4108  nsFocusManager* fm = nsFocusManager::GetFocusManager();
   4109  if (fm) {
   4110    if (!aActiveBrowsingContext.IsNullOrDiscarded()) {
   4111      fm->SetActiveBrowsingContextFromOtherProcess(aActiveBrowsingContext.get(),
   4112                                                   aActionIdForActive);
   4113    }
   4114    if (!aFocusedBrowsingContext.IsNullOrDiscarded()) {
   4115      fm->SetFocusedBrowsingContextFromOtherProcess(
   4116          aFocusedBrowsingContext.get(), aActionIdForFocused);
   4117    }
   4118  }
   4119  return IPC_OK();
   4120 }
   4121 
   4122 mozilla::ipc::IPCResult ContentChild::RecvReviseActiveBrowsingContext(
   4123    uint64_t aOldActionId,
   4124    const MaybeDiscarded<BrowsingContext>& aActiveBrowsingContext,
   4125    uint64_t aNewActionId) {
   4126  nsFocusManager* fm = nsFocusManager::GetFocusManager();
   4127  if (fm && !aActiveBrowsingContext.IsNullOrDiscarded()) {
   4128    fm->ReviseActiveBrowsingContext(aOldActionId, aActiveBrowsingContext.get(),
   4129                                    aNewActionId);
   4130  }
   4131  return IPC_OK();
   4132 }
   4133 
   4134 mozilla::ipc::IPCResult ContentChild::RecvReviseFocusedBrowsingContext(
   4135    uint64_t aOldActionId,
   4136    const MaybeDiscarded<BrowsingContext>& aFocusedBrowsingContext,
   4137    uint64_t aNewActionId) {
   4138  nsFocusManager* fm = nsFocusManager::GetFocusManager();
   4139  if (fm && !aFocusedBrowsingContext.IsNullOrDiscarded()) {
   4140    fm->ReviseFocusedBrowsingContext(
   4141        aOldActionId, aFocusedBrowsingContext.get(), aNewActionId);
   4142  }
   4143  return IPC_OK();
   4144 }
   4145 
   4146 mozilla::ipc::IPCResult ContentChild::RecvMaybeExitFullscreen(
   4147    const MaybeDiscarded<BrowsingContext>& aContext) {
   4148  if (aContext.IsNullOrDiscarded()) {
   4149    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
   4150            ("ChildIPC: Trying to send a message to dead or detached context"));
   4151    return IPC_OK();
   4152  }
   4153 
   4154  nsIDocShell* shell = aContext.get()->GetDocShell();
   4155  if (!shell) {
   4156    return IPC_OK();
   4157  }
   4158 
   4159  Document* doc = shell->GetDocument();
   4160  if (doc && doc->GetFullscreenElement()) {
   4161    Document::AsyncExitFullscreen(doc);
   4162  }
   4163 
   4164  return IPC_OK();
   4165 }
   4166 
   4167 mozilla::ipc::IPCResult ContentChild::RecvWindowPostMessage(
   4168    const MaybeDiscarded<BrowsingContext>& aContext,
   4169    const ClonedOrErrorMessageData& aMessage, const PostMessageData& aData) {
   4170  if (aContext.IsNullOrDiscarded()) {
   4171    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
   4172            ("ChildIPC: Trying to send a message to dead or detached context"));
   4173    return IPC_OK();
   4174  }
   4175 
   4176  RefPtr<nsGlobalWindowOuter> window =
   4177      nsGlobalWindowOuter::Cast(aContext.get()->GetDOMWindow());
   4178  if (!window) {
   4179    MOZ_LOG(
   4180        BrowsingContext::GetLog(), LogLevel::Debug,
   4181        ("ChildIPC: Trying to send a message to a context without a window"));
   4182    return IPC_OK();
   4183  }
   4184 
   4185  nsCOMPtr<nsIPrincipal> providedPrincipal;
   4186  if (!window->GetPrincipalForPostMessage(
   4187          aData.targetOrigin(), aData.targetOriginURI(),
   4188          aData.callerPrincipal(), *aData.subjectPrincipal(),
   4189          getter_AddRefs(providedPrincipal))) {
   4190    return IPC_OK();
   4191  }
   4192 
   4193  // Call `GetDocument()` to force the document and its inner window to be
   4194  // created, as it would be forced to be created if this call was being
   4195  // performed in-process.
   4196  if (NS_WARN_IF(!aContext.get()->GetDocument())) {
   4197    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
   4198            ("ChildIPC: Trying to send a message to a context but document "
   4199             "creation failed"));
   4200    return IPC_OK();
   4201  }
   4202 
   4203  // It's OK if `sourceBc` has already been discarded, so long as we can
   4204  // continue to wrap it.
   4205  RefPtr<BrowsingContext> sourceBc = aData.source().GetMaybeDiscarded();
   4206 
   4207  // Create and asynchronously dispatch a runnable which will handle actual DOM
   4208  // event creation and dispatch.
   4209  RefPtr<PostMessageEvent> event =
   4210      new PostMessageEvent(sourceBc, aData.origin(), window, providedPrincipal,
   4211                           aData.innerWindowId(), aData.callerURI(),
   4212                           aData.scriptLocation(), aData.isFromPrivateWindow());
   4213  event->UnpackFrom(aMessage);
   4214 
   4215  event->DispatchToTargetThread(IgnoredErrorResult());
   4216  return IPC_OK();
   4217 }
   4218 
   4219 mozilla::ipc::IPCResult ContentChild::RecvCommitBrowsingContextTransaction(
   4220    const MaybeDiscarded<BrowsingContext>& aContext,
   4221    BrowsingContext::BaseTransaction&& aTransaction, uint64_t aEpoch) {
   4222  return aTransaction.CommitFromIPC(aContext, aEpoch, this);
   4223 }
   4224 
   4225 mozilla::ipc::IPCResult ContentChild::RecvCommitWindowContextTransaction(
   4226    const MaybeDiscarded<WindowContext>& aContext,
   4227    WindowContext::BaseTransaction&& aTransaction, uint64_t aEpoch) {
   4228  return aTransaction.CommitFromIPC(aContext, aEpoch, this);
   4229 }
   4230 
   4231 mozilla::ipc::IPCResult ContentChild::RecvCreateWindowContext(
   4232    WindowContext::IPCInitializer&& aInit) {
   4233  RefPtr<BrowsingContext> bc = BrowsingContext::Get(aInit.mBrowsingContextId);
   4234  if (!bc) {
   4235    // Handle this case by ignoring the request, as bc must be in the process of
   4236    // being discarded.
   4237    // In the future it would be nice to avoid sending this message to the child
   4238    // at all.
   4239    NS_WARNING("Attempt to attach WindowContext to discarded parent");
   4240    return IPC_OK();
   4241  }
   4242 
   4243  WindowContext::CreateFromIPC(std::move(aInit));
   4244  return IPC_OK();
   4245 }
   4246 
   4247 mozilla::ipc::IPCResult ContentChild::RecvDiscardWindowContext(
   4248    uint64_t aContextId, DiscardWindowContextResolver&& aResolve) {
   4249  // Resolve immediately to acknowledge call
   4250  aResolve(true);
   4251 
   4252  RefPtr<WindowContext> window = WindowContext::GetById(aContextId);
   4253  if (NS_WARN_IF(!window) || NS_WARN_IF(window->IsDiscarded())) {
   4254    return IPC_OK();
   4255  }
   4256 
   4257  window->Discard();
   4258  return IPC_OK();
   4259 }
   4260 
   4261 mozilla::ipc::IPCResult ContentChild::RecvScriptError(
   4262    const nsString& aMessage, const nsCString& aSourceName,
   4263    const uint32_t& aLineNumber, const uint32_t& aColNumber,
   4264    const uint32_t& aFlags, const nsCString& aCategory,
   4265    const bool& aFromPrivateWindow, const uint64_t& aInnerWindowId,
   4266    const bool& aFromChromeContext) {
   4267  nsresult rv = NS_OK;
   4268  nsCOMPtr<nsIConsoleService> consoleService =
   4269      do_GetService(NS_CONSOLESERVICE_CONTRACTID, &rv);
   4270  NS_ENSURE_SUCCESS(rv, IPC_FAIL(this, "Failed to get console service"));
   4271 
   4272  nsCOMPtr<nsIScriptError> scriptError(
   4273      do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
   4274  NS_ENSURE_TRUE(scriptError,
   4275                 IPC_FAIL(this, "Failed to construct nsIScriptError"));
   4276 
   4277  scriptError->InitWithWindowID(aMessage, aSourceName, aLineNumber, aColNumber,
   4278                                aFlags, aCategory, aInnerWindowId,
   4279                                aFromChromeContext);
   4280  rv = consoleService->LogMessage(scriptError);
   4281  NS_ENSURE_SUCCESS(rv, IPC_FAIL(this, "Failed to log script error"));
   4282 
   4283  return IPC_OK();
   4284 }
   4285 
   4286 mozilla::ipc::IPCResult ContentChild::RecvReportFrameTimingData(
   4287    const LoadInfoArgs& loadInfoArgs, const nsString& entryName,
   4288    const nsString& initiatorType, UniquePtr<PerformanceTimingData>&& aData) {
   4289  if (!aData) {
   4290    return IPC_FAIL(this, "aData should not be null");
   4291  }
   4292 
   4293  nsCOMPtr<nsILoadInfo> loadInfo;
   4294  nsresult rv = mozilla::ipc::LoadInfoArgsToLoadInfo(
   4295      loadInfoArgs, NOT_REMOTE_TYPE, getter_AddRefs(loadInfo));
   4296  if (NS_FAILED(rv)) {
   4297    MOZ_DIAGNOSTIC_CRASH("LoadInfoArgsToLoadInfo failed");
   4298    return IPC_OK();
   4299  }
   4300 
   4301  // It is important to call LoadInfo::GetPerformanceStorage instead of simply
   4302  // getting the performance object via the innerWindowID in order to perform
   4303  // necessary cross origin checks.
   4304  if (PerformanceStorage* storage = loadInfo->GetPerformanceStorage()) {
   4305    storage->AddEntry(entryName, initiatorType, std::move(aData));
   4306  }
   4307  return IPC_OK();
   4308 }
   4309 
   4310 mozilla::ipc::IPCResult ContentChild::RecvLoadURI(
   4311    const MaybeDiscarded<BrowsingContext>& aContext,
   4312    nsDocShellLoadState* aLoadState, bool aSetNavigating,
   4313    LoadURIResolver&& aResolve) {
   4314  auto resolveOnExit = MakeScopeExit([&] { aResolve(true); });
   4315 
   4316  if (aContext.IsNullOrDiscarded()) {
   4317    return IPC_OK();
   4318  }
   4319  RefPtr<BrowsingContext> context = aContext.get();
   4320  if (!context->IsInProcess()) {
   4321    // The DocShell has been torn down or the BrowsingContext has changed
   4322    // process in the middle of the load request. There's not much we can do at
   4323    // this point, so just give up.
   4324    return IPC_OK();
   4325  }
   4326 
   4327  context->LoadURI(aLoadState, aSetNavigating);
   4328 
   4329  nsCOMPtr<nsPIDOMWindowOuter> window = context->GetDOMWindow();
   4330  BrowserChild* bc = BrowserChild::GetFrom(window);
   4331  if (bc) {
   4332    bc->NotifyNavigationFinished();
   4333  }
   4334 
   4335 #ifdef MOZ_CRASHREPORTER
   4336  if (CrashReporter::GetEnabled()) {
   4337    nsCOMPtr<nsIURI> annotationURI;
   4338 
   4339    nsresult rv = NS_MutateURI(aLoadState->URI())
   4340                      .SetUserPass(""_ns)
   4341                      .Finalize(annotationURI);
   4342 
   4343    if (NS_FAILED(rv)) {
   4344      // Ignore failures on about: URIs.
   4345      annotationURI = aLoadState->URI();
   4346    }
   4347 
   4348    CrashReporter::RecordAnnotationNSCString(CrashReporter::Annotation::URL,
   4349                                             annotationURI->GetSpecOrDefault());
   4350  }
   4351 #endif
   4352 
   4353  return IPC_OK();
   4354 }
   4355 
   4356 mozilla::ipc::IPCResult ContentChild::RecvInternalLoad(
   4357    nsDocShellLoadState* aLoadState) {
   4358  if (!aLoadState->Target().IsEmpty() ||
   4359      aLoadState->TargetBrowsingContext().IsNull()) {
   4360    return IPC_FAIL(this, "must already be retargeted");
   4361  }
   4362  if (aLoadState->TargetBrowsingContext().IsDiscarded()) {
   4363    return IPC_OK();
   4364  }
   4365  RefPtr<BrowsingContext> context = aLoadState->TargetBrowsingContext().get();
   4366 
   4367  context->InternalLoad(aLoadState);
   4368 
   4369 #ifdef MOZ_CRASHREPORTER
   4370  if (CrashReporter::GetEnabled()) {
   4371    nsCOMPtr<nsIURI> annotationURI;
   4372 
   4373    nsresult rv = NS_MutateURI(aLoadState->URI())
   4374                      .SetUserPass(""_ns)
   4375                      .Finalize(annotationURI);
   4376 
   4377    if (NS_FAILED(rv)) {
   4378      // Ignore failures on about: URIs.
   4379      annotationURI = aLoadState->URI();
   4380    }
   4381 
   4382    CrashReporter::RecordAnnotationNSCString(CrashReporter::Annotation::URL,
   4383                                             annotationURI->GetSpecOrDefault());
   4384  }
   4385 #endif
   4386 
   4387  return IPC_OK();
   4388 }
   4389 
   4390 mozilla::ipc::IPCResult ContentChild::RecvDisplayLoadError(
   4391    const MaybeDiscarded<BrowsingContext>& aContext, const nsAString& aURI) {
   4392  if (aContext.IsNullOrDiscarded()) {
   4393    return IPC_OK();
   4394  }
   4395  RefPtr<BrowsingContext> context = aContext.get();
   4396 
   4397  context->DisplayLoadError(aURI);
   4398 
   4399  nsCOMPtr<nsPIDOMWindowOuter> window = context->GetDOMWindow();
   4400  BrowserChild* bc = BrowserChild::GetFrom(window);
   4401  if (bc) {
   4402    bc->NotifyNavigationFinished();
   4403  }
   4404  return IPC_OK();
   4405 }
   4406 
   4407 mozilla::ipc::IPCResult ContentChild::RecvHistoryCommitIndexAndLength(
   4408    const MaybeDiscarded<BrowsingContext>& aContext, const uint32_t& aIndex,
   4409    const uint32_t& aLength, const nsID& aChangeID) {
   4410  if (!aContext.IsNullOrDiscarded()) {
   4411    ChildSHistory* shistory = aContext.get()->GetChildSessionHistory();
   4412    if (shistory) {
   4413      shistory->SetIndexAndLength(aIndex, aLength, aChangeID);
   4414    }
   4415  }
   4416  return IPC_OK();
   4417 }
   4418 
   4419 mozilla::ipc::IPCResult ContentChild::RecvConsumeHistoryActivation(
   4420    const MaybeDiscarded<BrowsingContext>& aTop) {
   4421  if (!aTop.IsNullOrDiscarded()) {
   4422    aTop->ConsumeHistoryActivation();
   4423  }
   4424  return IPC_OK();
   4425 }
   4426 
   4427 mozilla::ipc::IPCResult ContentChild::RecvGetLayoutHistoryState(
   4428    const MaybeDiscarded<BrowsingContext>& aContext,
   4429    GetLayoutHistoryStateResolver&& aResolver) {
   4430  nsCOMPtr<nsILayoutHistoryState> state;
   4431  nsIDocShell* docShell;
   4432  mozilla::Maybe<mozilla::dom::Wireframe> wireframe;
   4433  if (!aContext.IsNullOrDiscarded() &&
   4434      (docShell = aContext.get()->GetDocShell())) {
   4435    docShell->PersistLayoutHistoryState();
   4436    docShell->GetLayoutHistoryState(getter_AddRefs(state));
   4437    wireframe = static_cast<nsDocShell*>(docShell)->GetWireframe();
   4438  }
   4439  aResolver(
   4440      std::tuple<nsILayoutHistoryState*, const mozilla::Maybe<Wireframe>&>(
   4441          state, wireframe));
   4442 
   4443  return IPC_OK();
   4444 }
   4445 
   4446 mozilla::ipc::IPCResult ContentChild::RecvDispatchLocationChangeEvent(
   4447    const MaybeDiscarded<BrowsingContext>& aContext) {
   4448  if (!aContext.IsNullOrDiscarded() && aContext.get()->GetDocShell()) {
   4449    aContext.get()->GetDocShell()->DispatchLocationChangeEvent();
   4450  }
   4451  return IPC_OK();
   4452 }
   4453 
   4454 mozilla::ipc::IPCResult ContentChild::RecvDispatchBeforeUnloadToSubtree(
   4455    const MaybeDiscarded<BrowsingContext>& aStartingAt,
   4456    const mozilla::Maybe<SessionHistoryInfo>& aInfo,
   4457    DispatchBeforeUnloadToSubtreeResolver&& aResolver) {
   4458  if (aStartingAt.IsNullOrDiscarded()) {
   4459    aResolver(nsIDocumentViewer::eContinue);
   4460  } else {
   4461    DispatchBeforeUnloadToSubtree(aStartingAt.get(), aInfo, aResolver);
   4462  }
   4463  return IPC_OK();
   4464 }
   4465 
   4466 /* static */ void ContentChild::DispatchBeforeUnloadToSubtree(
   4467    BrowsingContext* aStartingAt,
   4468    const mozilla::Maybe<SessionHistoryInfo>& aInfo,
   4469    const DispatchBeforeUnloadToSubtreeResolver& aResolver) {
   4470  bool resolved = false;
   4471 
   4472  aStartingAt->PreOrderWalk(
   4473      [&](const RefPtr<dom::BrowsingContext>& aBC)
   4474          MOZ_CAN_RUN_SCRIPT_BOUNDARY_LAMBDA {
   4475            if (RefPtr docShell = nsDocShell::Cast(aBC->GetDocShell())) {
   4476              nsCOMPtr<nsIDocumentViewer> viewer;
   4477              docShell->GetDocViewer(getter_AddRefs(viewer));
   4478              nsIDocumentViewer::PermitUnloadResult finalStatus =
   4479                  nsIDocumentViewer::eContinue;
   4480              if (viewer) {
   4481                finalStatus = viewer->DispatchBeforeUnload();
   4482              }
   4483 
   4484              if (finalStatus == nsIDocumentViewer::eContinue && aBC->IsTop() &&
   4485                  aInfo) {
   4486                // https://html.spec.whatwg.org/#preventing-navigation:fire-a-traverse-navigate-event.
   4487                // If this is the top-level navigable and we've passed `aInfo`,
   4488                // we should perform #fire-a-traverse-navigate-event.
   4489                // #checking-if-unloading-is-canceled will block the navigation
   4490                // if the "navigate" event handler for the top level window's
   4491                // navigation object returns false.
   4492                // This should send the correct user involvment. See bug
   4493                // 1903552.
   4494                finalStatus = docShell->MaybeFireTraversableTraverseHistory(
   4495                    *aInfo, Nothing());
   4496              }
   4497 
   4498              if (!resolved && finalStatus != nsIDocumentViewer::eContinue) {
   4499                // Send our response as soon as we find any blocker, so that we
   4500                // can show the permit unload prompt as soon as possible,
   4501                // without giving subsequent handlers a chance to delay it.
   4502                aResolver(finalStatus);
   4503                resolved = true;
   4504              }
   4505            }
   4506          });
   4507 
   4508  if (!resolved) {
   4509    aResolver(nsIDocumentViewer::eContinue);
   4510  }
   4511 }
   4512 
   4513 mozilla::ipc::IPCResult ContentChild::RecvDispatchNavigateToTraversable(
   4514    const MaybeDiscarded<BrowsingContext>& aTraversable,
   4515    const mozilla::Maybe<SessionHistoryInfo>& aInfo,
   4516    DispatchNavigateToTraversableResolver&& aResolver) {
   4517  if (aTraversable.IsNullOrDiscarded() || !aTraversable->GetDocShell()) {
   4518    aResolver(nsIDocumentViewer::eContinue);
   4519  } else {
   4520    RefPtr docShell = nsDocShell::Cast(aTraversable->GetDocShell());
   4521    aResolver(docShell->MaybeFireTraversableTraverseHistory(*aInfo, Nothing()));
   4522  }
   4523  return IPC_OK();
   4524 }
   4525 
   4526 mozilla::ipc::IPCResult ContentChild::RecvInitNextGenLocalStorageEnabled(
   4527    const bool& aEnabled) {
   4528  mozilla::dom::RecvInitNextGenLocalStorageEnabled(aEnabled);
   4529 
   4530  return IPC_OK();
   4531 }
   4532 
   4533 mozilla::ipc::IPCResult ContentChild::RecvGoBack(
   4534    const MaybeDiscarded<BrowsingContext>& aContext,
   4535    const Maybe<int32_t>& aCancelContentJSEpoch, bool aRequireUserInteraction,
   4536    bool aUserActivation) {
   4537  if (aContext.IsNullOrDiscarded()) {
   4538    return IPC_OK();
   4539  }
   4540  BrowsingContext* bc = aContext.get();
   4541 
   4542  if (RefPtr<nsDocShell> docShell = nsDocShell::Cast(bc->GetDocShell())) {
   4543    if (aCancelContentJSEpoch) {
   4544      docShell->SetCancelContentJSEpoch(*aCancelContentJSEpoch);
   4545    }
   4546    docShell->GoBack(aRequireUserInteraction, aUserActivation);
   4547 
   4548    if (BrowserChild* browserChild = BrowserChild::GetFrom(docShell)) {
   4549      browserChild->NotifyNavigationFinished();
   4550    }
   4551  }
   4552 
   4553  return IPC_OK();
   4554 }
   4555 
   4556 mozilla::ipc::IPCResult ContentChild::RecvGoForward(
   4557    const MaybeDiscarded<BrowsingContext>& aContext,
   4558    const Maybe<int32_t>& aCancelContentJSEpoch, bool aRequireUserInteraction,
   4559    bool aUserActivation) {
   4560  if (aContext.IsNullOrDiscarded()) {
   4561    return IPC_OK();
   4562  }
   4563  BrowsingContext* bc = aContext.get();
   4564 
   4565  if (RefPtr<nsDocShell> docShell = nsDocShell::Cast(bc->GetDocShell())) {
   4566    if (aCancelContentJSEpoch) {
   4567      docShell->SetCancelContentJSEpoch(*aCancelContentJSEpoch);
   4568    }
   4569    docShell->GoForward(aRequireUserInteraction, aUserActivation);
   4570 
   4571    if (BrowserChild* browserChild = BrowserChild::GetFrom(docShell)) {
   4572      browserChild->NotifyNavigationFinished();
   4573    }
   4574  }
   4575 
   4576  return IPC_OK();
   4577 }
   4578 
   4579 mozilla::ipc::IPCResult ContentChild::RecvGoToIndex(
   4580    const MaybeDiscarded<BrowsingContext>& aContext, const int32_t& aIndex,
   4581    const Maybe<int32_t>& aCancelContentJSEpoch, bool aUserActivation) {
   4582  if (aContext.IsNullOrDiscarded()) {
   4583    return IPC_OK();
   4584  }
   4585  BrowsingContext* bc = aContext.get();
   4586 
   4587  if (RefPtr<nsDocShell> docShell = nsDocShell::Cast(bc->GetDocShell())) {
   4588    if (aCancelContentJSEpoch) {
   4589      docShell->SetCancelContentJSEpoch(*aCancelContentJSEpoch);
   4590    }
   4591    docShell->GotoIndex(aIndex, aUserActivation);
   4592 
   4593    if (BrowserChild* browserChild = BrowserChild::GetFrom(docShell)) {
   4594      browserChild->NotifyNavigationFinished();
   4595    }
   4596  }
   4597 
   4598  return IPC_OK();
   4599 }
   4600 
   4601 mozilla::ipc::IPCResult ContentChild::RecvReload(
   4602    const MaybeDiscarded<BrowsingContext>& aContext,
   4603    const uint32_t aReloadFlags) {
   4604  if (aContext.IsNullOrDiscarded()) {
   4605    return IPC_OK();
   4606  }
   4607  BrowsingContext* bc = aContext.get();
   4608 
   4609  if (RefPtr<nsDocShell> docShell = nsDocShell::Cast(bc->GetDocShell())) {
   4610    docShell->Reload(aReloadFlags);
   4611  }
   4612 
   4613  return IPC_OK();
   4614 }
   4615 
   4616 mozilla::ipc::IPCResult ContentChild::RecvStopLoad(
   4617    const MaybeDiscarded<BrowsingContext>& aContext,
   4618    const uint32_t aStopFlags) {
   4619  if (aContext.IsNullOrDiscarded()) {
   4620    return IPC_OK();
   4621  }
   4622  BrowsingContext* bc = aContext.get();
   4623 
   4624  if (auto* docShell = nsDocShell::Cast(bc->GetDocShell())) {
   4625    docShell->Stop(aStopFlags);
   4626  }
   4627 
   4628  return IPC_OK();
   4629 }
   4630 
   4631 #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
   4632 mozilla::ipc::IPCResult ContentChild::RecvInitSandboxTesting(
   4633    Endpoint<PSandboxTestingChild>&& aEndpoint) {
   4634  if (!SandboxTestingChild::Initialize(std::move(aEndpoint))) {
   4635    return IPC_FAIL(
   4636        this, "InitSandboxTesting failed to initialise the child process.");
   4637  }
   4638  return IPC_OK();
   4639 }
   4640 #endif
   4641 
   4642 NS_IMETHODIMP ContentChild::GetChildID(uint64_t* aOut) {
   4643  *aOut = XRE_GetChildID();
   4644  return NS_OK;
   4645 }
   4646 
   4647 NS_IMETHODIMP ContentChild::GetActor(const nsACString& aName, JSContext* aCx,
   4648                                     JSProcessActorChild** retval) {
   4649  ErrorResult error;
   4650  RefPtr<JSProcessActorChild> actor =
   4651      JSActorManager::GetActor(aCx, aName, error)
   4652          .downcast<JSProcessActorChild>();
   4653  if (error.MaybeSetPendingException(aCx)) {
   4654    return NS_ERROR_FAILURE;
   4655  }
   4656  actor.forget(retval);
   4657  return NS_OK;
   4658 }
   4659 
   4660 NS_IMETHODIMP ContentChild::GetExistingActor(const nsACString& aName,
   4661                                             JSProcessActorChild** retval) {
   4662  RefPtr<JSProcessActorChild> actor =
   4663      JSActorManager::GetExistingActor(aName).downcast<JSProcessActorChild>();
   4664  actor.forget(retval);
   4665  return NS_OK;
   4666 }
   4667 
   4668 already_AddRefed<JSActor> ContentChild::InitJSActor(
   4669    JS::Handle<JSObject*> aMaybeActor, const nsACString& aName,
   4670    ErrorResult& aRv) {
   4671  RefPtr<JSProcessActorChild> actor;
   4672  if (aMaybeActor.get()) {
   4673    aRv = UNWRAP_OBJECT(JSProcessActorChild, aMaybeActor.get(), actor);
   4674    if (aRv.Failed()) {
   4675      return nullptr;
   4676    }
   4677  } else {
   4678    actor = new JSProcessActorChild();
   4679  }
   4680 
   4681  MOZ_RELEASE_ASSERT(!actor->Manager(),
   4682                     "mManager was already initialized once!");
   4683  actor->Init(aName, this);
   4684  return actor.forget();
   4685 }
   4686 
   4687 IPCResult ContentChild::RecvRawMessage(
   4688    const JSActorMessageMeta& aMeta, JSIPCValue&& aData,
   4689    const UniquePtr<ClonedMessageData>& aStack) {
   4690  UniquePtr<StructuredCloneData> stack;
   4691  if (aStack) {
   4692    stack = MakeUnique<StructuredCloneData>();
   4693    stack->BorrowFromClonedMessageData(*aStack);
   4694  }
   4695  ReceiveRawMessage(aMeta, std::move(aData), std::move(stack));
   4696  return IPC_OK();
   4697 }
   4698 
   4699 NS_IMETHODIMP ContentChild::GetCanSend(bool* aCanSend) {
   4700  *aCanSend = CanSend();
   4701  return NS_OK;
   4702 }
   4703 
   4704 ContentChild* ContentChild::AsContentChild() { return this; }
   4705 
   4706 JSActorManager* ContentChild::AsJSActorManager() { return this; }
   4707 
   4708 IPCResult ContentChild::RecvFlushFOGData(FlushFOGDataResolver&& aResolver) {
   4709  glean::FlushFOGData(std::move(aResolver));
   4710  return IPC_OK();
   4711 }
   4712 
   4713 IPCResult ContentChild::RecvUpdateMediaCodecsSupported(
   4714    RemoteMediaIn aLocation, const media::MediaCodecsSupported& aSupported) {
   4715  RemoteMediaManagerChild::SetSupported(aLocation, aSupported);
   4716 
   4717  return IPC_OK();
   4718 }
   4719 
   4720 void ContentChild::ConfigureThreadPerformanceHints(
   4721    const hal::ProcessPriority& aPriority) {
   4722  if (aPriority >= hal::PROCESS_PRIORITY_FOREGROUND) {
   4723    static bool canUsePerformanceHintSession = true;
   4724    if (!mPerformanceHintSession && canUsePerformanceHintSession) {
   4725      nsTArray<PlatformThreadHandle> threads;
   4726      Servo_ThreadPool_GetThreadHandles(&threads);
   4727 #ifdef XP_WIN
   4728      threads.AppendElement(GetCurrentThread());
   4729 #else
   4730      threads.AppendElement(pthread_self());
   4731 #endif
   4732 
   4733      mPerformanceHintSession = hal::CreatePerformanceHintSession(
   4734          threads, GetPerformanceHintTarget(TimeDuration::FromMilliseconds(
   4735                       nsRefreshDriver::DefaultInterval())));
   4736 
   4737      // Avoid repeatedly attempting to create a session if it is not
   4738      // supported.
   4739      canUsePerformanceHintSession = mPerformanceHintSession != nullptr;
   4740    }
   4741 
   4742 #ifdef MOZ_WIDGET_ANDROID
   4743    // On Android if we are unable to use PerformanceHintManager then fall back
   4744    // to setting the stylo threads' affinities to the performant cores. Android
   4745    // automatically sets each thread's affinity to all cores when a process is
   4746    // foregrounded, and to a subset of cores when the process is backgrounded.
   4747    // We must therefore override this each time the process is foregrounded,
   4748    // but we don't have to do anything when backgrounded.
   4749    if (!mPerformanceHintSession) {
   4750      if (const auto& cpuInfo = hal::GetHeterogeneousCpuInfo()) {
   4751        // If CPUs are homogeneous there is no point setting affinity.
   4752        if (cpuInfo->mBigCpus.Count() != cpuInfo->mTotalNumCpus) {
   4753          BitSet<hal::HeterogeneousCpuInfo::MAX_CPUS> cpus = cpuInfo->mBigCpus;
   4754          if (cpus.Count() < 2) {
   4755            // From testing on a variety of devices it appears using only the
   4756            // big cores gives best performance when there are 2 or more big
   4757            // cores. If there are fewer than 2 big cores then additionally
   4758            // using the medium cores performs better.
   4759            cpus |= cpuInfo->mMediumCpus;
   4760          }
   4761 
   4762          static_assert(
   4763              hal::HeterogeneousCpuInfo::MAX_CPUS <= CPU_SETSIZE,
   4764              "HeterogeneousCpuInfo::MAX_CPUS is too large for CPU_SETSIZE");
   4765 
   4766          cpu_set_t cpuset;
   4767          CPU_ZERO(&cpuset);
   4768          for (size_t i = 0; i < cpuInfo->mTotalNumCpus; i++) {
   4769            if (cpus.test(i)) {
   4770              CPU_SET(i, &cpuset);
   4771            }
   4772          }
   4773 
   4774          // Only set the affinity for the stylo threads, not the main thread.
   4775          // Testing showed no difference in performance between the two
   4776          // options, and as newly spawned threads automatically inherit their
   4777          // parent's affinity mask there may be unintended consequences to
   4778          // setting the main thread affinity.
   4779          nsTArray<PlatformThreadHandle> threads;
   4780          Servo_ThreadPool_GetThreadHandles(&threads);
   4781          for (pthread_t thread : threads) {
   4782            int ret = sched_setaffinity(pthread_gettid_np(thread),
   4783                                        sizeof(cpu_set_t), &cpuset);
   4784            // Occasionally sched_setaffinity fails, presumably due to a race
   4785            // between us receiving the process foreground signal and whatever
   4786            // is responsible for restricting which processes can use certain
   4787            // cores. Trying again in a runnable seems to do the trick, but if
   4788            // that still fails it's not the end of the world.
   4789            if (ret < 0) {
   4790              NS_DispatchToCurrentThread(NS_NewRunnableFunction(
   4791                  "ContentChild::ConfigureThreadPerformanceHints",
   4792                  [threads = std::move(threads), cpuset] {
   4793                    for (pthread_t thread : threads) {
   4794                      sched_setaffinity(pthread_gettid_np(thread),
   4795                                        sizeof(cpu_set_t), &cpuset);
   4796                    }
   4797                  }));
   4798              break;
   4799            }
   4800          }
   4801        }
   4802      }
   4803    }
   4804 #endif
   4805  } else {
   4806    mPerformanceHintSession = nullptr;
   4807  }
   4808 }
   4809 
   4810 #ifdef MOZ_WMF_CDM
   4811 mozilla::ipc::IPCResult ContentChild::RecvUpdateMFCDMOriginEntries(
   4812    const nsTArray<IPCOriginStatusEntry>& aEntries) {
   4813  MediaKeySystemAccess::UpdateMFCDMOriginEntries(aEntries);
   4814  return IPC_OK();
   4815 }
   4816 #endif
   4817 
   4818 }  // namespace dom
   4819 
   4820 #if defined(__OpenBSD__) && defined(MOZ_SANDBOX)
   4821 
   4822 static LazyLogModule sPledgeLog("OpenBSDSandbox");
   4823 
   4824 NS_IMETHODIMP
   4825 OpenBSDFindPledgeUnveilFilePath(const char* file, nsACString& result) {
   4826  struct stat st;
   4827 
   4828  // Allow overriding files in /etc/$MOZ_APP_NAME
   4829  result.Assign(nsPrintfCString("/etc/%s/%s", MOZ_APP_NAME, file));
   4830  if (stat(PromiseFlatCString(result).get(), &st) == 0) {
   4831    return NS_OK;
   4832  }
   4833 
   4834  // Or look in the system default directory
   4835  result.Assign(nsPrintfCString(
   4836      "/usr/local/lib/%s/browser/defaults/preferences/%s", MOZ_APP_NAME, file));
   4837  if (stat(PromiseFlatCString(result).get(), &st) == 0) {
   4838    return NS_OK;
   4839  }
   4840 
   4841  errx(1, "can't locate %s", file);
   4842 }
   4843 
   4844 NS_IMETHODIMP
   4845 OpenBSDPledgePromises(const nsACString& aPath) {
   4846  // Using NS_LOCAL_FILE_CONTRACTID/NS_LOCALFILEINPUTSTREAM_CONTRACTID requires
   4847  // a lot of setup before they are supported and we want to pledge early on
   4848  // before all of that, so read the file directly
   4849  std::ifstream input(PromiseFlatCString(aPath).get());
   4850 
   4851  // Build up one line of pledge promises without comments
   4852  nsAutoCString promises;
   4853  bool disabled = false;
   4854  int linenum = 0;
   4855  for (std::string tLine; std::getline(input, tLine);) {
   4856    nsAutoCString line(tLine.c_str());
   4857    linenum++;
   4858 
   4859    // Cut off any comments at the end of the line, also catches lines
   4860    // that are entirely a comment
   4861    int32_t hash = line.FindChar('#');
   4862    if (hash >= 0) {
   4863      line = Substring(line, 0, hash);
   4864    }
   4865    line.CompressWhitespace(true, true);
   4866    if (line.IsEmpty()) {
   4867      continue;
   4868    }
   4869 
   4870    if (linenum == 1 && line.EqualsLiteral("disable")) {
   4871      disabled = true;
   4872      break;
   4873    }
   4874 
   4875    if (!promises.IsEmpty()) {
   4876      promises.Append(" ");
   4877    }
   4878    promises.Append(line);
   4879  }
   4880  input.close();
   4881 
   4882  if (disabled) {
   4883    warnx("%s: disabled", PromiseFlatCString(aPath).get());
   4884  } else {
   4885    MOZ_LOG(
   4886        sPledgeLog, LogLevel::Debug,
   4887        ("%s: pledge(%s)\n", PromiseFlatCString(aPath).get(), promises.get()));
   4888    if (pledge(promises.get(), nullptr) != 0) {
   4889      err(1, "%s: pledge(%s) failed", PromiseFlatCString(aPath).get(),
   4890          promises.get());
   4891    }
   4892  }
   4893 
   4894  return NS_OK;
   4895 }
   4896 
   4897 void ExpandUnveilPath(nsAutoCString& path) {
   4898  // Expand $XDG_RUNTIME_DIR to the environment variable, or ~/.cache
   4899  nsCString xdgRuntimeDir(PR_GetEnv("XDG_RUNTIME_DIR"));
   4900  if (xdgRuntimeDir.IsEmpty()) {
   4901    xdgRuntimeDir = "~/.cache";
   4902  }
   4903  path.ReplaceSubstring("$XDG_RUNTIME_DIR", xdgRuntimeDir.get());
   4904 
   4905  // Expand $XDG_CONFIG_HOME to the environment variable, or ~/.config
   4906  nsCString xdgConfigHome(PR_GetEnv("XDG_CONFIG_HOME"));
   4907  if (xdgConfigHome.IsEmpty()) {
   4908    xdgConfigHome = "~/.config";
   4909  }
   4910  path.ReplaceSubstring("$XDG_CONFIG_HOME", xdgConfigHome.get());
   4911 
   4912  // Expand $XDG_CACHE_HOME to the environment variable, or ~/.cache
   4913  nsCString xdgCacheHome(PR_GetEnv("XDG_CACHE_HOME"));
   4914  if (xdgCacheHome.IsEmpty()) {
   4915    xdgCacheHome = "~/.cache";
   4916  }
   4917  path.ReplaceSubstring("$XDG_CACHE_HOME", xdgCacheHome.get());
   4918 
   4919  // Expand $XDG_DATA_HOME to the environment variable, or ~/.local/share
   4920  nsCString xdgDataHome(PR_GetEnv("XDG_DATA_HOME"));
   4921  if (xdgDataHome.IsEmpty()) {
   4922    xdgDataHome = "~/.local/share";
   4923  }
   4924  path.ReplaceSubstring("$XDG_DATA_HOME", xdgDataHome.get());
   4925 
   4926  // Expand leading ~ to the user's home directory
   4927  nsCOMPtr<nsIFile> homeDir;
   4928  nsresult rv =
   4929      GetSpecialSystemDirectory(Unix_HomeDirectory, getter_AddRefs(homeDir));
   4930  if (NS_FAILED(rv)) {
   4931    errx(1, "failed getting home directory");
   4932  }
   4933  if (path.FindChar('~') == 0) {
   4934    nsCString tHome(homeDir->NativePath());
   4935    tHome.Append(Substring(path, 1, path.Length() - 1));
   4936    path = tHome.get();
   4937  }
   4938 }
   4939 
   4940 void MkdirP(nsAutoCString& path) {
   4941  // nsLocalFile::CreateAllAncestors would be nice to use
   4942 
   4943  nsAutoCString tPath("");
   4944  for (const nsACString& dir : path.Split('/')) {
   4945    struct stat st;
   4946 
   4947    if (dir.IsEmpty()) {
   4948      continue;
   4949    }
   4950 
   4951    tPath.Append("/");
   4952    tPath.Append(dir);
   4953 
   4954    if (stat(tPath.get(), &st) == -1) {
   4955      if (mkdir(tPath.get(), 0700) == -1) {
   4956        err(1, "failed mkdir(%s) while MkdirP(%s)",
   4957            PromiseFlatCString(tPath).get(), PromiseFlatCString(path).get());
   4958      }
   4959    }
   4960  }
   4961 }
   4962 
   4963 NS_IMETHODIMP
   4964 OpenBSDUnveilPaths(const nsACString& uPath, const nsACString& pledgePath) {
   4965  // Using NS_LOCAL_FILE_CONTRACTID/NS_LOCALFILEINPUTSTREAM_CONTRACTID requires
   4966  // a lot of setup before they are allowed/supported and we want to pledge and
   4967  // unveil early on before all of that is setup
   4968  std::ifstream input(PromiseFlatCString(uPath).get());
   4969 
   4970  bool disabled = false;
   4971  int linenum = 0;
   4972  for (std::string tLine; std::getline(input, tLine);) {
   4973    nsAutoCString line(tLine.c_str());
   4974    linenum++;
   4975 
   4976    // Cut off any comments at the end of the line, also catches lines
   4977    // that are entirely a comment
   4978    int32_t hash = line.FindChar('#');
   4979    if (hash >= 0) {
   4980      line = Substring(line, 0, hash);
   4981    }
   4982    line.CompressWhitespace(true, true);
   4983    if (line.IsEmpty()) {
   4984      continue;
   4985    }
   4986 
   4987    if (linenum == 1 && line.EqualsLiteral("disable")) {
   4988      disabled = true;
   4989      break;
   4990    }
   4991 
   4992    int32_t space = line.FindChar(' ');
   4993    if (space <= 0) {
   4994      errx(1, "%s: line %d: invalid format", PromiseFlatCString(uPath).get(),
   4995           linenum);
   4996    }
   4997 
   4998    nsAutoCString uPath(Substring(line, 0, space));
   4999    ExpandUnveilPath(uPath);
   5000 
   5001    nsAutoCString perms(Substring(line, space + 1, line.Length() - space - 1));
   5002 
   5003    MOZ_LOG(sPledgeLog, LogLevel::Debug,
   5004            ("%s: unveil(%s, %s)\n", PromiseFlatCString(uPath).get(),
   5005             uPath.get(), perms.get()));
   5006    if (unveil(uPath.get(), perms.get()) == -1 && errno != ENOENT) {
   5007      err(1, "%s: unveil(%s, %s) failed", PromiseFlatCString(uPath).get(),
   5008          uPath.get(), perms.get());
   5009    }
   5010  }
   5011  input.close();
   5012 
   5013  if (disabled) {
   5014    warnx("%s: disabled", PromiseFlatCString(uPath).get());
   5015  } else {
   5016    struct stat st;
   5017 
   5018    // Only unveil the pledgePath file if it's not already unveiled, otherwise
   5019    // some containing directory will lose visibility.
   5020    if (stat(PromiseFlatCString(pledgePath).get(), &st) == -1) {
   5021      if (errno == ENOENT) {
   5022        if (unveil(PromiseFlatCString(pledgePath).get(), "r") == -1) {
   5023          err(1, "unveil(%s, r) failed", PromiseFlatCString(pledgePath).get());
   5024        }
   5025      } else {
   5026        err(1, "stat(%s)", PromiseFlatCString(pledgePath).get());
   5027      }
   5028    }
   5029  }
   5030 
   5031  return NS_OK;
   5032 }
   5033 
   5034 bool StartOpenBSDSandbox(GeckoProcessType type, ipc::SandboxingKind kind) {
   5035  nsAutoCString pledgeFile;
   5036  nsAutoCString unveilFile;
   5037  char binaryPath[MAXPATHLEN];
   5038 
   5039  switch (type) {
   5040    case GeckoProcessType_Default: {
   5041      OpenBSDFindPledgeUnveilFilePath("pledge.main", pledgeFile);
   5042      OpenBSDFindPledgeUnveilFilePath("unveil.main", unveilFile);
   5043 
   5044      // Ensure dconf dir exists before we veil the filesystem
   5045      nsAutoCString dConf("$XDG_RUNTIME_DIR/dconf");
   5046      ExpandUnveilPath(dConf);
   5047      MkdirP(dConf);
   5048      break;
   5049    }
   5050 
   5051    case GeckoProcessType_Content:
   5052      OpenBSDFindPledgeUnveilFilePath("pledge.content", pledgeFile);
   5053      OpenBSDFindPledgeUnveilFilePath("unveil.content", unveilFile);
   5054      break;
   5055 
   5056    case GeckoProcessType_GPU:
   5057      OpenBSDFindPledgeUnveilFilePath("pledge.gpu", pledgeFile);
   5058      OpenBSDFindPledgeUnveilFilePath("unveil.gpu", unveilFile);
   5059      break;
   5060 
   5061    case GeckoProcessType_Socket:
   5062      OpenBSDFindPledgeUnveilFilePath("pledge.socket", pledgeFile);
   5063      OpenBSDFindPledgeUnveilFilePath("unveil.socket", unveilFile);
   5064      break;
   5065 
   5066    case GeckoProcessType_RDD:
   5067      OpenBSDFindPledgeUnveilFilePath("pledge.rdd", pledgeFile);
   5068      OpenBSDFindPledgeUnveilFilePath("unveil.rdd", unveilFile);
   5069      break;
   5070 
   5071    case GeckoProcessType_Utility: {
   5072      MOZ_RELEASE_ASSERT(kind <= SandboxingKind::COUNT,
   5073                         "Should define a sandbox");
   5074      switch (kind) {
   5075        case ipc::SandboxingKind::GENERIC_UTILITY:
   5076        default:
   5077          OpenBSDFindPledgeUnveilFilePath("pledge.utility", pledgeFile);
   5078          OpenBSDFindPledgeUnveilFilePath("unveil.utility", unveilFile);
   5079          break;
   5080      }
   5081    } break;
   5082 
   5083    default:
   5084      MOZ_ASSERT(false, "unknown process type");
   5085      return false;
   5086  }
   5087 
   5088  nsresult rv = mozilla::BinaryPath::Get(binaryPath);
   5089  if (NS_FAILED(rv)) {
   5090    errx(1, "failed to cache binary path ?");
   5091  }
   5092 
   5093  if (NS_WARN_IF(NS_FAILED(OpenBSDUnveilPaths(unveilFile, pledgeFile)))) {
   5094    errx(1, "failed reading/parsing %s", unveilFile.get());
   5095  }
   5096 
   5097  if (NS_WARN_IF(NS_FAILED(OpenBSDPledgePromises(pledgeFile)))) {
   5098    errx(1, "failed reading/parsing %s", pledgeFile.get());
   5099  }
   5100 
   5101  // Don't overwrite an existing session dbus address, but ensure it is set
   5102  if (!PR_GetEnv("DBUS_SESSION_BUS_ADDRESS")) {
   5103    PR_SetEnv("DBUS_SESSION_BUS_ADDRESS=");
   5104  }
   5105 
   5106  return true;
   5107 }
   5108 #endif
   5109 
   5110 }  // namespace mozilla
   5111 
   5112 /* static */
   5113 nsIDOMProcessChild* nsIDOMProcessChild::GetSingleton() {
   5114  if (XRE_IsContentProcess()) {
   5115    return mozilla::dom::ContentChild::GetSingleton();
   5116  }
   5117  return mozilla::dom::InProcessChild::Singleton();
   5118 }