Bug 1523638 - Part 9: Use provided 'WindowGlobalChild' actors to create the initial about:blank document, r=kmag
☠☠ backed out by 663f5d1ba3f3 ☠ ☠
authorNika Layzell <nika@thelayzells.com>
Tue, 16 Jul 2019 18:47:56 +0000
changeset 543502 0a584a07b696b22135ff1ac9e2afcd71a9dfdcc1
parent 543501 8c5af2289900833e67337de3e898ec9ab5a866c8
child 543503 96372a2ff71d3db3724bde3891d3764a08a4577e
push id11848
push userffxbld-merge
push dateMon, 26 Aug 2019 19:26:25 +0000
treeherdermozilla-beta@9b31bfdfac10 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskmag
bugs1523638
milestone70.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1523638 - Part 9: Use provided 'WindowGlobalChild' actors to create the initial about:blank document, r=kmag Differential Revision: https://phabricator.services.mozilla.com/D37656
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/base/nsIContentViewer.idl
dom/base/Document.cpp
dom/base/nsGlobalWindowInner.cpp
dom/base/nsGlobalWindowInner.h
dom/base/nsGlobalWindowOuter.cpp
dom/base/nsGlobalWindowOuter.h
dom/base/nsPIDOMWindow.h
dom/ipc/BrowserChild.cpp
dom/ipc/WindowGlobalChild.cpp
dom/ipc/WindowGlobalChild.h
gfx/thebes/gfxSVGGlyphs.cpp
image/SVGDocumentWrapper.cpp
layout/base/nsDocumentViewer.cpp
toolkit/components/browser/moz.build
toolkit/components/browser/nsWebBrowser.cpp
toolkit/components/browser/nsWebBrowser.h
xpfe/appshell/nsAppShellService.cpp
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -302,19 +302,20 @@ static void DecreasePrivateDocShellCount
 
     nsCOMPtr<nsIObserverService> obsvc = services::GetObserverService();
     if (obsvc) {
       obsvc->NotifyObservers(nullptr, "last-pb-context-exited", nullptr);
     }
   }
 }
 
-nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext)
+nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
+                       uint64_t aContentWindowID)
     : nsDocLoader(),
-      mContentWindowID(nsContentUtils::GenerateWindowId()),
+      mContentWindowID(aContentWindowID),
       mBrowsingContext(aBrowsingContext),
       mForcedCharset(nullptr),
       mParentCharset(nullptr),
       mTreeOwner(nullptr),
       mDefaultScrollbarPref(Scrollbar_Auto, Scrollbar_Auto),
       mCharsetReloadState(eCharsetReloadInit),
       mOrientationLock(hal::eScreenOrientation_None),
       mParentCharsetSource(0),
@@ -390,16 +391,21 @@ nsDocShell::nsDocShell(BrowsingContext* 
       mIsNavigating(false) {
   mHistoryID.m0 = 0;
   mHistoryID.m1 = 0;
   mHistoryID.m2 = 0;
   AssertOriginAttributesMatchPrivateBrowsing();
 
   nsContentUtils::GenerateUUIDInPlace(mHistoryID);
 
+  // If no outer window ID was provided, generate a new one.
+  if (aContentWindowID == 0) {
+    mContentWindowID = nsContentUtils::GenerateWindowId();
+  }
+
   if (gDocShellCount++ == 0) {
     NS_ASSERTION(sURIFixup == nullptr,
                  "Huh, sURIFixup not null in first nsDocShell ctor!");
 
     nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service();
     uriFixup.forget(&sURIFixup);
   }
 
@@ -456,21 +462,21 @@ nsDocShell::~nsDocShell() {
                   (void*)this, gNumberOfDocShells, getpid(),
                   nsIDToCString(mHistoryID).get(), url.get());
   }
 #endif
 }
 
 /* static */
 already_AddRefed<nsDocShell> nsDocShell::Create(
-    BrowsingContext* aBrowsingContext) {
+    BrowsingContext* aBrowsingContext, uint64_t aContentWindowID) {
   MOZ_ASSERT(aBrowsingContext, "DocShell without a BrowsingContext!");
 
   nsresult rv;
-  RefPtr<nsDocShell> ds = new nsDocShell(aBrowsingContext);
+  RefPtr<nsDocShell> ds = new nsDocShell(aBrowsingContext, aContentWindowID);
 
   // Initialize the underlying nsDocLoader.
   rv = ds->nsDocLoader::Init();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return nullptr;
   }
 
   // Create our ContentListener
@@ -514,16 +520,17 @@ already_AddRefed<nsDocShell> nsDocShell:
   // If our parent is present in this process, set up our parent now.
   RefPtr<BrowsingContext> parent = aBrowsingContext->GetParent();
   if (parent && parent->GetDocShell()) {
     parent->GetDocShell()->AddChild(ds);
   }
 
   // Make |ds| the primary DocShell for the given context.
   aBrowsingContext->SetDocShell(ds);
+
   return ds.forget();
 }
 
 void nsDocShell::DestroyChildren() {
   nsCOMPtr<nsIDocShellTreeItem> shell;
   nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
   while (iter.HasMore()) {
     shell = do_QueryObject(iter.GetNext());
@@ -6360,22 +6367,23 @@ nsresult nsDocShell::RefreshURIFromQueue
         }
       }
     }
   }
 
   return NS_OK;
 }
 
-nsresult nsDocShell::Embed(nsIContentViewer* aContentViewer) {
+nsresult nsDocShell::Embed(nsIContentViewer* aContentViewer,
+                           WindowGlobalChild* aWindowActor) {
   // Save the LayoutHistoryState of the previous document, before
   // setting up new document
   PersistLayoutHistoryState();
 
-  nsresult rv = SetupNewViewer(aContentViewer);
+  nsresult rv = SetupNewViewer(aContentViewer, aWindowActor);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // XXX What if SetupNewViewer fails?
   if (mLSHE) {
     // Restore the editing state, if it's stored in session history.
     if (mLSHE->HasDetachedEditor()) {
       ReattachEditorToWindow(mLSHE);
     }
@@ -7001,16 +7009,17 @@ nsresult nsDocShell::EnsureContentViewer
   if (mIsBeingDestroyed) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIContentSecurityPolicy> cspToInheritForAboutBlank;
   nsCOMPtr<nsIURI> baseURI;
   nsIPrincipal* principal = GetInheritedPrincipal(false);
   nsIPrincipal* storagePrincipal = GetInheritedPrincipal(false, true);
+
   nsCOMPtr<nsIDocShellTreeItem> parentItem;
   GetSameTypeParent(getter_AddRefs(parentItem));
   if (parentItem) {
     if (nsCOMPtr<nsPIDOMWindowOuter> domWin = GetWindow()) {
       nsCOMPtr<Element> parentElement = domWin->GetFrameElementInternal();
       if (parentElement) {
         baseURI = parentElement->GetBaseURI();
         cspToInheritForAboutBlank = parentElement->GetCsp();
@@ -7042,21 +7051,24 @@ nsresult nsDocShell::EnsureContentViewer
   }
 
   return rv;
 }
 
 nsresult nsDocShell::CreateAboutBlankContentViewer(
     nsIPrincipal* aPrincipal, nsIPrincipal* aStoragePrincipal,
     nsIContentSecurityPolicy* aCSP, nsIURI* aBaseURI,
-    bool aTryToSaveOldPresentation, bool aCheckPermitUnload) {
+    bool aTryToSaveOldPresentation, bool aCheckPermitUnload,
+    WindowGlobalChild* aActor) {
   RefPtr<Document> blankDoc;
   nsCOMPtr<nsIContentViewer> viewer;
   nsresult rv = NS_ERROR_FAILURE;
 
+  MOZ_ASSERT_IF(aActor, aActor->DocumentPrincipal() == aPrincipal);
+
   /* mCreatingDocument should never be true at this point. However, it's
      a theoretical possibility. We want to know about it and make it stop,
      and this sounds like a job for an assertion. */
   NS_ASSERTION(!mCreatingDocument,
                "infinite(?) loop creating document averted");
   if (mCreatingDocument) {
     return NS_ERROR_FAILURE;
   }
@@ -7175,17 +7187,17 @@ nsresult nsDocShell::CreateAboutBlankCon
       // create a content viewer for us and the new document
       docFactory->CreateInstanceForDocument(
           NS_ISUPPORTS_CAST(nsIDocShell*, this), blankDoc, "view",
           getter_AddRefs(viewer));
 
       // hook 'em up
       if (viewer) {
         viewer->SetContainer(this);
-        rv = Embed(viewer);
+        rv = Embed(viewer, aActor);
         NS_ENSURE_SUCCESS(rv, rv);
 
         SetCurrentURI(blankDoc->GetDocumentURI(), nullptr, true, 0);
         rv = mIsBeingDestroyed ? NS_ERROR_NOT_AVAILABLE : NS_OK;
       }
     }
   }
 
@@ -7205,16 +7217,42 @@ nsresult nsDocShell::CreateAboutBlankCon
 NS_IMETHODIMP
 nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal,
                                           nsIPrincipal* aStoragePrincipal,
                                           nsIContentSecurityPolicy* aCSP) {
   return CreateAboutBlankContentViewer(aPrincipal, aStoragePrincipal, aCSP,
                                        nullptr);
 }
 
+nsresult nsDocShell::CreateContentViewerForActor(
+    WindowGlobalChild* aWindowActor) {
+  MOZ_ASSERT(aWindowActor);
+
+  // FIXME: WindowGlobalChild should provide the StoragePrincipal.
+  nsresult rv = CreateAboutBlankContentViewer(
+      aWindowActor->DocumentPrincipal(), aWindowActor->DocumentPrincipal(),
+      /* aCsp */ nullptr,
+      /* aBaseURI */ nullptr,
+      /* aTryToSaveOldPresentation */ true,
+      /* aCheckPermitUnload */ true, aWindowActor);
+  if (NS_SUCCEEDED(rv)) {
+    RefPtr<Document> doc(GetDocument());
+    MOZ_ASSERT(
+        doc,
+        "Should have a document if CreateAboutBlankContentViewer succeeded");
+    MOZ_ASSERT(doc->GetOwnerGlobal() == aWindowActor->WindowGlobal(),
+               "New document should be in the same global as our actor");
+
+    // FIXME: We may want to support non-initial documents here.
+    doc->SetIsInitialDocument(true);
+  }
+
+  return rv;
+}
+
 bool nsDocShell::CanSavePresentation(uint32_t aLoadType,
                                      nsIRequest* aNewRequest,
                                      Document* aNewDocument) {
   if (!mOSHE) {
     return false;  // no entry to save into
   }
 
   nsCOMPtr<nsIContentViewer> viewer = mOSHE->GetContentViewer();
@@ -8405,17 +8443,18 @@ nsresult nsDocShell::NewContentViewerObj
       "view", aOpenedChannel, aLoadGroup, aContentType, this, nullptr,
       aContentHandler, aViewer);
   NS_ENSURE_SUCCESS(rv, rv);
 
   (*aViewer)->SetContainer(this);
   return NS_OK;
 }
 
-nsresult nsDocShell::SetupNewViewer(nsIContentViewer* aNewViewer) {
+nsresult nsDocShell::SetupNewViewer(nsIContentViewer* aNewViewer,
+                                    WindowGlobalChild* aWindowActor) {
   MOZ_ASSERT(!mIsBeingDestroyed);
 
   //
   // Copy content viewer state from previous or parent content viewer.
   //
   // The following logic is mirrored in nsHTMLDocument::StartDocumentLoad!
   //
   // Do NOT to maintain a reference to the old content viewer outside
@@ -8529,17 +8568,17 @@ nsresult nsDocShell::SetupNewViewer(nsIC
 
   nsCOMPtr<nsIWidget> widget;
   NS_ENSURE_SUCCESS(GetMainWidget(getter_AddRefs(widget)), NS_ERROR_FAILURE);
 
   nsIntRect bounds(x, y, cx, cy);
 
   mContentViewer->SetNavigationTiming(mTiming);
 
-  if (NS_FAILED(mContentViewer->Init(widget, bounds))) {
+  if (NS_FAILED(mContentViewer->Init(widget, bounds, aWindowActor))) {
     mContentViewer = nullptr;
     NS_WARNING("ContentViewer Initialization failed");
     return NS_ERROR_FAILURE;
   }
 
   // If we have old state to copy, set the old state onto the new content
   // viewer
   if (newCv) {
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -196,17 +196,18 @@ class nsDocShell final : public nsDocLoa
   NS_DECL_NSIAUTHPROMPTPROVIDER
   NS_DECL_NSINETWORKINTERCEPTCONTROLLER
   NS_DECL_NSIDEPRECATIONWARNER
 
   NS_FORWARD_SAFE_NSIDOMSTORAGEMANAGER(TopSessionStorageManager())
 
   // Create a new nsDocShell object, initializing it.
   static already_AddRefed<nsDocShell> Create(
-      mozilla::dom::BrowsingContext* aBrowsingContext);
+      mozilla::dom::BrowsingContext* aBrowsingContext,
+      uint64_t aContentWindowID = 0);
 
   NS_IMETHOD Stop() override {
     // Need this here because otherwise nsIWebNavigation::Stop
     // overrides the docloader's Stop()
     return nsDocLoader::Stop();
   }
 
   /**
@@ -468,16 +469,21 @@ class nsDocShell final : public nsDocLoa
 
   // Clear the document's storage access flag if needed.
   void MaybeClearStorageAccessFlag();
 
   void SkipBrowsingContextDetach() {
     mSkipBrowsingContextDetachOnDestroy = true;
   }
 
+  // Create a content viewer within this nsDocShell for the given
+  // `WindowGlobalChild` actor.
+  nsresult CreateContentViewerForActor(
+      mozilla::dom::WindowGlobalChild* aWindowActor);
+
  private:  // member functions
   friend class nsDSURIContentListener;
   friend class FramingChecker;
   friend class OnLinkClickEvent;
   friend class nsIDocShell;
   friend class mozilla::dom::BrowsingContext;
 
   // It is necessary to allow adding a timeline marker wherever a docshell
@@ -492,17 +498,18 @@ class nsDocShell final : public nsDocLoa
   friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
       nsDocShell*, const char*, const TimeStamp&, MarkerTracingType,
       MarkerStackRequest);
   friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
       nsDocShell*, UniquePtr<AbstractTimelineMarker>&&);
   friend void mozilla::TimelineConsumers::PopMarkers(
       nsDocShell*, JSContext*, nsTArray<dom::ProfileTimelineMarker>&);
 
-  explicit nsDocShell(mozilla::dom::BrowsingContext* aBrowsingContext);
+  nsDocShell(mozilla::dom::BrowsingContext* aBrowsingContext,
+             uint64_t aContentWindowID);
 
   // Security checks to prevent frameset spoofing. See comments at
   // implementation sites.
   static bool CanAccessItem(nsIDocShellTreeItem* aTargetItem,
                             nsIDocShellTreeItem* aAccessingItem,
                             bool aConsiderOpener = true);
   static bool ValidateOrigin(nsIDocShellTreeItem* aOriginTreeItem,
                              nsIDocShellTreeItem* aTargetTreeItem);
@@ -546,33 +553,34 @@ class nsDocShell final : public nsDocLoa
   // Content Viewer Management
   //
 
   nsresult EnsureContentViewer();
 
   // aPrincipal can be passed in if the caller wants. If null is
   // passed in, the about:blank principal will end up being used.
   // aCSP, if any, will be used for the new about:blank load.
-  nsresult CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal,
-                                         nsIPrincipal* aStoragePrincipal,
-                                         nsIContentSecurityPolicy* aCSP,
-                                         nsIURI* aBaseURI,
-                                         bool aTryToSaveOldPresentation = true,
-                                         bool aCheckPermitUnload = true);
+  nsresult CreateAboutBlankContentViewer(
+      nsIPrincipal* aPrincipal, nsIPrincipal* aStoragePrincipal,
+      nsIContentSecurityPolicy* aCSP, nsIURI* aBaseURI,
+      bool aTryToSaveOldPresentation = true, bool aCheckPermitUnload = true,
+      mozilla::dom::WindowGlobalChild* aActor = nullptr);
 
   nsresult CreateContentViewer(const nsACString& aContentType,
                                nsIRequest* aRequest,
                                nsIStreamListener** aContentHandler);
 
   nsresult NewContentViewerObj(const nsACString& aContentType,
                                nsIRequest* aRequest, nsILoadGroup* aLoadGroup,
                                nsIStreamListener** aContentHandler,
                                nsIContentViewer** aViewer);
 
-  nsresult SetupNewViewer(nsIContentViewer* aNewViewer);
+  nsresult SetupNewViewer(
+      nsIContentViewer* aNewViewer,
+      mozilla::dom::WindowGlobalChild* aWindowActor = nullptr);
 
   //
   // Session History
   //
 
   bool ShouldAddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel);
 
   // Either aChannel or aOwner must be null. If aChannel is
@@ -975,17 +983,18 @@ class nsDocShell final : public nsDocLoa
   nsIDOMStorageManager* TopSessionStorageManager();
   nsIChannel* GetCurrentDocChannel();
   nsresult EnsureScriptEnvironment();
   nsresult EnsureEditorData();
   nsresult EnsureTransferableHookData();
   nsresult EnsureFind();
   nsresult EnsureCommandHandler();
   nsresult RefreshURIFromQueue();
-  nsresult Embed(nsIContentViewer* aContentViewer);
+  nsresult Embed(nsIContentViewer* aContentViewer,
+                 mozilla::dom::WindowGlobalChild* aWindowActor = nullptr);
   nsPresContext* GetEldestPresContext();
   nsresult CheckLoadingPermissions();
   nsresult PersistLayoutHistoryState();
   nsresult LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType);
   nsresult GetHttpChannel(nsIChannel* aChannel, nsIHttpChannel** aReturn);
   nsresult ConfirmRepost(bool* aRepost);
   nsresult GetPromptAndStringBundle(nsIPrompt** aPrompt,
                                     nsIStringBundle** aStringBundle);
--- a/docshell/base/nsIContentViewer.idl
+++ b/docshell/base/nsIContentViewer.idl
@@ -16,33 +16,38 @@ webidl Node;
 
 class nsIWidget;
 class nsPresContext;
 class nsView;
 class nsDOMNavigationTiming;
 namespace mozilla {
 class Encoding;
 class PresShell;
-}
+namespace dom {
+class WindowGlobalChild;
+} // namespace dom
+} // namespace mozilla
 %}
 
 [ptr] native nsIWidgetPtr(nsIWidget);
 [ref] native nsIntRectRef(nsIntRect);
 [ptr] native nsPresContextPtr(nsPresContext);
 [ptr] native nsViewPtr(nsView);
 [ptr] native nsDOMNavigationTimingPtr(nsDOMNavigationTiming);
 [ref] native nsIContentViewerTArray(nsTArray<nsCOMPtr<nsIContentViewer> >);
 [ptr] native Encoding(const mozilla::Encoding);
 [ptr] native PresShellPtr(mozilla::PresShell);
+[ptr] native WindowGlobalChildPtr(mozilla::dom::WindowGlobalChild);
 
 [scriptable, builtinclass, uuid(2da17016-7851-4a45-a7a8-00b360e01595)]
 interface nsIContentViewer : nsISupports
 {
   [noscript] void init(in nsIWidgetPtr aParentWidget,
-                       [const] in nsIntRectRef aBounds);
+                       [const] in nsIntRectRef aBounds,
+                       in WindowGlobalChildPtr aWindowActor);
 
   attribute nsIDocShell container;
 
   [noscript,notxpcom,nostdcall] void loadStart(in Document aDoc);
   [can_run_script] void loadComplete(in nsresult aStatus);
   [notxpcom,nostdcall] readonly attribute boolean loadCompleted;
 
   [notxpcom,nostdcall] readonly attribute boolean isStopped;
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -826,17 +826,17 @@ nsresult ExternalResourceMap::AddExterna
       // We don't handle XUL stuff here yet.
       rv = NS_ERROR_NOT_AVAILABLE;
     } else {
       doc->SetDisplayDocument(aDisplayDocument);
 
       // Make sure that hiding our viewer will tear down its presentation.
       aViewer->SetSticky(false);
 
-      rv = aViewer->Init(nullptr, nsIntRect(0, 0, 0, 0));
+      rv = aViewer->Init(nullptr, nsIntRect(0, 0, 0, 0), nullptr);
       if (NS_SUCCEEDED(rv)) {
         rv = aViewer->Open(nullptr, nullptr);
       }
     }
 
     if (NS_FAILED(rv)) {
       doc = nullptr;
       aViewer = nullptr;
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -833,18 +833,19 @@ class PromiseDocumentFlushedResolver fin
   RefPtr<Promise> mPromise;
   RefPtr<PromiseDocumentFlushedCallback> mCallback;
 };
 
 //*****************************************************************************
 //***    nsGlobalWindowInner: Object Management
 //*****************************************************************************
 
-nsGlobalWindowInner::nsGlobalWindowInner(nsGlobalWindowOuter* aOuterWindow)
-    : nsPIDOMWindowInner(aOuterWindow),
+nsGlobalWindowInner::nsGlobalWindowInner(nsGlobalWindowOuter* aOuterWindow,
+                                         WindowGlobalChild* aActor)
+    : nsPIDOMWindowInner(aOuterWindow, aActor),
       mozilla::webgpu::InstanceProvider(this),
       mWasOffline(false),
       mHasHadSlowScript(false),
       mIsChrome(false),
       mCleanMessageManager(false),
       mNeedsFocus(true),
       mHasFocus(false),
       mShowFocusRingForContent(false),
@@ -1610,19 +1611,17 @@ void nsGlobalWindowInner::InnerSetNewDoc
   // could recreate them, calling the getter methods, and store them into the JS
   // slots. If we nullify them after, the slot values and the objects will be
   // out of sync.
   ClearDocumentDependentSlots(aCx);
 
   // FIXME: Currently, devtools can crete a fallback webextension window global
   // in the content process which does not have a corresponding BrowserChild
   // actor. This means we have no actor to be our parent. (Bug 1498293)
-  MOZ_DIAGNOSTIC_ASSERT(!mWindowGlobalChild,
-                        "Shouldn't have created WindowGlobalChild yet!");
-  if (XRE_IsParentProcess() || mBrowserChild) {
+  if (!mWindowGlobalChild && (XRE_IsParentProcess() || mBrowserChild)) {
     mWindowGlobalChild = WindowGlobalChild::Create(this);
   }
 
   if (ShouldResetBrowsingContextUserGestureActivation()) {
     Window()->NotifyResetUserGestureActivation();
   }
 
 #ifdef DEBUG
@@ -7135,23 +7134,29 @@ void nsGlobalWindowInner::StorageAccessG
 }
 
 mozilla::dom::TabGroup* nsPIDOMWindowInner::TabGroup() {
   return nsGlobalWindowInner::Cast(this)->TabGroupInner();
 }
 
 /* static */
 already_AddRefed<nsGlobalWindowInner> nsGlobalWindowInner::Create(
-    nsGlobalWindowOuter* aOuterWindow, bool aIsChrome) {
-  RefPtr<nsGlobalWindowInner> window = new nsGlobalWindowInner(aOuterWindow);
+    nsGlobalWindowOuter* aOuterWindow, bool aIsChrome,
+    WindowGlobalChild* aActor) {
+  RefPtr<nsGlobalWindowInner> window =
+      new nsGlobalWindowInner(aOuterWindow, aActor);
   if (aIsChrome) {
     window->mIsChrome = true;
     window->mCleanMessageManager = true;
   }
 
+  if (aActor) {
+    aActor->InitWindowGlobal(window);
+  }
+
   window->InitWasOffline();
   return window.forget();
 }
 
 nsIURI* nsPIDOMWindowInner::GetDocumentURI() const {
   return mDoc ? mDoc->GetDocumentURI() : mDocumentURI.get();
 }
 
@@ -7194,37 +7199,47 @@ void nsPIDOMWindowInner::SaveStorageAcce
   }
 }
 
 bool nsPIDOMWindowInner::HasStorageAccessGranted(
     const nsACString& aPermissionKey) {
   return mStorageAccessGranted.Contains(aPermissionKey);
 }
 
-nsPIDOMWindowInner::nsPIDOMWindowInner(nsPIDOMWindowOuter* aOuterWindow)
+nsPIDOMWindowInner::nsPIDOMWindowInner(nsPIDOMWindowOuter* aOuterWindow,
+                                       WindowGlobalChild* aActor)
     : mMutationBits(0),
       mActivePeerConnections(0),
       mIsDocumentLoaded(false),
       mIsHandlingResizeEvent(false),
       mMayHavePaintEventListener(false),
       mMayHaveTouchEventListener(false),
       mMayHaveSelectionChangeEventListener(false),
       mMayHaveMouseEnterLeaveEventListener(false),
       mMayHavePointerEnterLeaveEventListener(false),
       mMayHaveTextEventListenerInDefaultGroup(false),
       mOuterWindow(aOuterWindow),
-      mWindowID(nsContentUtils::GenerateWindowId()),
+      mWindowID(0),
       mHasNotifiedGlobalCreated(false),
       mMarkedCCGeneration(0),
       mHasTriedToCacheTopInnerWindow(false),
       mNumOfIndexedDBDatabases(0),
       mNumOfOpenWebSockets(0),
-      mEvent(nullptr) {
+      mEvent(nullptr),
+      mWindowGlobalChild(aActor) {
   MOZ_ASSERT(aOuterWindow);
   mBrowsingContext = aOuterWindow->GetBrowsingContext();
+
+  if (mWindowGlobalChild) {
+    mWindowID = aActor->InnerWindowId();
+
+    MOZ_ASSERT(mWindowGlobalChild->BrowsingContext() == mBrowsingContext);
+  } else {
+    mWindowID = nsContentUtils::GenerateWindowId();
+  }
 }
 
 void nsPIDOMWindowInner::RegisterReportingObserver(ReportingObserver* aObserver,
                                                    bool aBuffered) {
   MOZ_ASSERT(aObserver);
 
   if (mReportingObservers.Contains(aObserver)) {
     return;
--- a/dom/base/nsGlobalWindowInner.h
+++ b/dom/base/nsGlobalWindowInner.h
@@ -227,17 +227,18 @@ class nsGlobalWindowInner final : public
   }
 
   static nsGlobalWindowInner* FromSupports(nsISupports* supports) {
     // Make sure this matches the casts we do in QueryInterface().
     return (nsGlobalWindowInner*)(mozilla::dom::EventTarget*)supports;
   }
 
   static already_AddRefed<nsGlobalWindowInner> Create(
-      nsGlobalWindowOuter* aOuter, bool aIsChrome);
+      nsGlobalWindowOuter* aOuter, bool aIsChrome,
+      mozilla::dom::WindowGlobalChild* aActor);
 
   // nsISupports
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   // nsWrapperCache
   virtual JSObject* WrapObject(JSContext* cx,
                                JS::Handle<JSObject*> aGivenProto) override {
     return GetWrapper();
@@ -613,17 +614,18 @@ class nsGlobalWindowInner final : public
   nsresult Focus() override;
   void Blur(mozilla::ErrorResult& aError);
   mozilla::dom::BrowsingContext* GetFrames(mozilla::ErrorResult& aError);
   uint32_t Length();
   mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> GetTop(
       mozilla::ErrorResult& aError);
 
  protected:
-  explicit nsGlobalWindowInner(nsGlobalWindowOuter* aOuterWindow);
+  explicit nsGlobalWindowInner(nsGlobalWindowOuter* aOuterWindow,
+                               mozilla::dom::WindowGlobalChild* aActor);
   // Initializes the mWasOffline member variable
   void InitWasOffline();
 
  public:
   nsPIDOMWindowOuter* GetOpenerWindow(mozilla::ErrorResult& aError);
   void GetOpener(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
                  mozilla::ErrorResult& aError);
   void SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -1870,17 +1870,18 @@ static nsresult CreateNativeGlobalForInn
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 nsresult nsGlobalWindowOuter::SetNewDocument(Document* aDocument,
                                              nsISupports* aState,
-                                             bool aForceReuseInnerWindow) {
+                                             bool aForceReuseInnerWindow,
+                                             WindowGlobalChild* aActor) {
   MOZ_ASSERT(mDocumentPrincipal == nullptr,
              "mDocumentPrincipal prematurely set!");
   MOZ_ASSERT(mDocumentStoragePrincipal == nullptr,
              "mDocumentStoragePrincipal prematurely set!");
   MOZ_ASSERT(aDocument);
 
   // Bail out early if we're in process of closing down the window.
   NS_ENSURE_STATE(!mCleanedUp);
@@ -2003,17 +2004,17 @@ nsresult nsGlobalWindowOuter::SetNewDocu
 #endif
     JS::SetRealmPrincipals(realm,
                            nsJSPrincipals::get(aDocument->NodePrincipal()));
   } else {
     if (aState) {
       newInnerWindow = wsh->GetInnerWindow();
       newInnerGlobal = newInnerWindow->GetWrapper();
     } else {
-      newInnerWindow = nsGlobalWindowInner::Create(this, thisChrome);
+      newInnerWindow = nsGlobalWindowInner::Create(this, thisChrome, aActor);
       if (StaticPrefs::dom_timeout_defer_during_load()) {
         // ensure the initial loading state is known
         newInnerWindow->SetActiveLoadingState(
             aDocument->GetReadyStateEnum() ==
             Document::ReadyState::READYSTATE_LOADING);
       }
 
       // The outer window is automatically treated as frozen when we
--- a/dom/base/nsGlobalWindowOuter.h
+++ b/dom/base/nsGlobalWindowOuter.h
@@ -307,18 +307,19 @@ class nsGlobalWindowOuter final : public
 
   virtual nsresult FireDelayedDOMEvents() override;
 
   // Outer windows only.
   bool WouldReuseInnerWindow(Document* aNewDocument);
 
   void DetachFromDocShell();
 
-  virtual nsresult SetNewDocument(Document* aDocument, nsISupports* aState,
-                                  bool aForceReuseInnerWindow) override;
+  virtual nsresult SetNewDocument(
+      Document* aDocument, nsISupports* aState, bool aForceReuseInnerWindow,
+      mozilla::dom::WindowGlobalChild* aActor = nullptr) override;
 
   // Outer windows only.
   void DispatchDOMWindowCreated();
 
   virtual void SetOpenerWindow(nsPIDOMWindowOuter* aOpener,
                                bool aOriginalOpener) override;
 
   // Outer windows only.
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -135,17 +135,18 @@ enum class LargeAllocStatus : uint8_t {
   }
 
 class nsPIDOMWindowInner : public mozIDOMWindow {
  protected:
   typedef mozilla::dom::Document Document;
   friend nsGlobalWindowInner;
   friend nsGlobalWindowOuter;
 
-  explicit nsPIDOMWindowInner(nsPIDOMWindowOuter* aOuterWindow);
+  nsPIDOMWindowInner(nsPIDOMWindowOuter* aOuterWindow,
+                     mozilla::dom::WindowGlobalChild* aActor);
 
   ~nsPIDOMWindowInner();
 
  public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_PIDOMWINDOWINNER_IID)
 
   nsIGlobalObject* AsGlobal();
   const nsIGlobalObject* AsGlobal() const;
@@ -870,18 +871,19 @@ class nsPIDOMWindowOuter : public mozIDO
   /**
    * Set a new document in the window. Calling this method will in most cases
    * create a new inner window. This may be called with a pointer to the current
    * document, in that case the document remains unchanged, but a new inner
    * window will be created.
    *
    * aDocument must not be null.
    */
-  virtual nsresult SetNewDocument(Document* aDocument, nsISupports* aState,
-                                  bool aForceReuseInnerWindow) = 0;
+  virtual nsresult SetNewDocument(
+      Document* aDocument, nsISupports* aState, bool aForceReuseInnerWindow,
+      mozilla::dom::WindowGlobalChild* aActor = nullptr) = 0;
 
   /**
    * Set the opener window.  aOriginalOpener is true if and only if this is the
    * original opener for the window.  That is, it can only be true at most once
    * during the life cycle of a window, and then only the first time
    * SetOpenerWindow is called.  It might never be true, of course, if the
    * window does not have an opener when it's created.
    */
--- a/dom/ipc/BrowserChild.cpp
+++ b/dom/ipc/BrowserChild.cpp
@@ -503,17 +503,17 @@ nsresult BrowserChild::Init(mozIDOMWindo
     return NS_ERROR_FAILURE;
   }
   mPuppetWidget->InfallibleCreate(nullptr,
                                   nullptr,  // no parents
                                   LayoutDeviceIntRect(0, 0, 0, 0),
                                   nullptr);  // HandleWidgetEvent
 
   mWebBrowser = nsWebBrowser::Create(this, mPuppetWidget, OriginAttributesRef(),
-                                     mBrowsingContext);
+                                     mBrowsingContext, aInitialWindowChild);
   nsIWebBrowser* webBrowser = mWebBrowser;
 
   mWebNav = do_QueryInterface(webBrowser);
   NS_ASSERTION(mWebNav, "nsWebBrowser doesn't implement nsIWebNavigation?");
 
   // Set the tab context attributes then pass to docShell
   NotifyTabContextUpdated(false);
 
--- a/dom/ipc/WindowGlobalChild.cpp
+++ b/dom/ipc/WindowGlobalChild.cpp
@@ -135,16 +135,20 @@ void WindowGlobalChild::Init() {
     gWindowGlobalChildById = new WGCByIdMap();
     ClearOnShutdown(&gWindowGlobalChildById);
   }
   auto entry = gWindowGlobalChildById->LookupForAdd(mInnerWindowId);
   MOZ_RELEASE_ASSERT(!entry, "Duplicate WindowGlobalChild entry for ID!");
   entry.OrInsert([&] { return this; });
 }
 
+void WindowGlobalChild::InitWindowGlobal(nsGlobalWindowInner* aWindow) {
+  mWindowGlobal = aWindow;
+}
+
 /* static */
 already_AddRefed<WindowGlobalChild> WindowGlobalChild::GetByInnerWindowId(
     uint64_t aInnerWindowId) {
   if (!gWindowGlobalChildById) {
     return nullptr;
   }
   return gWindowGlobalChildById->Get(aInnerWindowId);
 }
--- a/dom/ipc/WindowGlobalChild.h
+++ b/dom/ipc/WindowGlobalChild.h
@@ -55,16 +55,18 @@ class WindowGlobalChild final : public W
 
   // Check if this actor is managed by PInProcess, as-in the document is loaded
   // in the chrome process.
   bool IsInProcess() { return XRE_IsParentProcess(); }
 
   nsIURI* GetDocumentURI() override { return mDocumentURI; }
   void SetDocumentURI(nsIURI* aDocumentURI);
 
+  nsIPrincipal* DocumentPrincipal() { return mDocumentPrincipal; }
+
   // The Window ID for this WindowGlobal
   uint64_t InnerWindowId() { return mInnerWindowId; }
   uint64_t OuterWindowId() { return mOuterWindowId; }
 
   uint64_t ContentParentId();
 
   int64_t BeforeUnloadListeners() { return mBeforeUnloadListeners; }
   void BeforeUnloadAdded();
@@ -93,16 +95,18 @@ class WindowGlobalChild final : public W
   static already_AddRefed<WindowGlobalChild> Create(
       nsGlobalWindowInner* aWindow);
 
   WindowGlobalChild(const WindowGlobalInit& aInit,
                     nsGlobalWindowInner* aWindow);
 
   void Init();
 
+  void InitWindowGlobal(nsGlobalWindowInner* aWindow);
+
   nsISupports* GetParentObject();
   JSObject* WrapObject(JSContext* aCx,
                        JS::Handle<JSObject*> aGivenProto) override;
 
  protected:
   const nsAString& GetRemoteType() override;
   JSWindowActor::Type GetSide() override { return JSWindowActor::Type::Child; }
 
--- a/gfx/thebes/gfxSVGGlyphs.cpp
+++ b/gfx/thebes/gfxSVGGlyphs.cpp
@@ -138,17 +138,17 @@ nsresult gfxSVGGlyphsDocument::SetupPres
       do_GetService(contractId.get());
   NS_ASSERTION(docLoaderFactory, "Couldn't get DocumentLoaderFactory");
 
   nsCOMPtr<nsIContentViewer> viewer;
   rv = docLoaderFactory->CreateInstanceForDocument(nullptr, mDocument, nullptr,
                                                    getter_AddRefs(viewer));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = viewer->Init(nullptr, gfx::IntRect(0, 0, 1000, 1000));
+  rv = viewer->Init(nullptr, gfx::IntRect(0, 0, 1000, 1000), nullptr);
   if (NS_SUCCEEDED(rv)) {
     rv = viewer->Open(nullptr, nullptr);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   RefPtr<PresShell> presShell = viewer->GetPresShell();
   if (!presShell->DidInitialize()) {
     rv = presShell->Initialize();
--- a/image/SVGDocumentWrapper.cpp
+++ b/image/SVGDocumentWrapper.cpp
@@ -195,17 +195,17 @@ NS_IMETHODIMP
 SVGDocumentWrapper::OnStartRequest(nsIRequest* aRequest) {
   nsresult rv = SetupViewer(aRequest, getter_AddRefs(mViewer),
                             getter_AddRefs(mLoadGroup));
 
   if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(mListener->OnStartRequest(aRequest))) {
     mViewer->GetDocument()->SetIsBeingUsedAsImage();
     StopAnimation();  // otherwise animations start automatically in helper doc
 
-    rv = mViewer->Init(nullptr, nsIntRect(0, 0, 0, 0));
+    rv = mViewer->Init(nullptr, nsIntRect(0, 0, 0, 0), nullptr);
     if (NS_SUCCEEDED(rv)) {
       rv = mViewer->Open(nullptr, nullptr);
     }
   }
   return rv;
 }
 
 NS_IMETHODIMP
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -115,16 +115,17 @@
 
 // paint forcing
 #include <stdio.h>
 
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/dom/ScriptLoader.h"
+#include "mozilla/dom/WindowGlobalChild.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 #define BEFOREUNLOAD_DISABLED_PREFNAME "dom.disable_beforeunload"
 #define BEFOREUNLOAD_REQUIRES_INTERACTION_PREFNAME \
   "dom.require_user_interaction_for_beforeunload"
 
@@ -339,16 +340,17 @@ class nsDocumentViewer final : public ns
   /**
    * If aDoCreation is true, this creates the device context, creates a
    * prescontext if necessary, and calls MakeWindow.
    *
    * If aForceSetNewDocument is false, then SetNewDocument won't be
    * called if the window's current document is already mDocument.
    */
   nsresult InitInternal(nsIWidget* aParentWidget, nsISupports* aState,
+                        mozilla::dom::WindowGlobalChild* aActor,
                         const nsIntRect& aBounds, bool aDoCreation,
                         bool aNeedMakeCX = true,
                         bool aForceSetNewDocument = true);
   /**
    * @param aDoInitialReflow set to true if you want to kick off the initial
    * reflow
    */
   MOZ_CAN_RUN_SCRIPT_BOUNDARY
@@ -708,18 +710,19 @@ nsDocumentViewer::GetContainer(nsIDocShe
   NS_ENSURE_ARG_POINTER(aResult);
 
   nsCOMPtr<nsIDocShell> container(mContainer);
   container.swap(*aResult);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDocumentViewer::Init(nsIWidget* aParentWidget, const nsIntRect& aBounds) {
-  return InitInternal(aParentWidget, nullptr, aBounds, true);
+nsDocumentViewer::Init(nsIWidget* aParentWidget, const nsIntRect& aBounds,
+                       WindowGlobalChild* aActor) {
+  return InitInternal(aParentWidget, nullptr, aActor, aBounds, true);
 }
 
 nsresult nsDocumentViewer::InitPresentationStuff(bool aDoInitialReflow) {
   // We assert this because initializing the pres shell could otherwise cause
   // re-entrancy into nsDocumentViewer methods, which might cause a different
   // pres shell to be created.  Callers of InitPresentationStuff should ensure
   // the call is appropriately bounded by an nsAutoScriptBlocker to decide
   // when it is safe for these re-entrant calls to be made.
@@ -840,22 +843,20 @@ static nsPresContext* CreatePresContext(
   if (aContainerView) return new nsPresContext(aDocument, aType);
   return new nsRootPresContext(aDocument, aType);
 }
 
 //-----------------------------------------------
 // This method can be used to initial the "presentation"
 // The aDoCreation indicates whether it should create
 // all the new objects or just initialize the existing ones
-nsresult nsDocumentViewer::InitInternal(nsIWidget* aParentWidget,
-                                        nsISupports* aState,
-                                        const nsIntRect& aBounds,
-                                        bool aDoCreation,
-                                        bool aNeedMakeCX /*= true*/,
-                                        bool aForceSetNewDocument /* = true*/) {
+nsresult nsDocumentViewer::InitInternal(
+    nsIWidget* aParentWidget, nsISupports* aState, WindowGlobalChild* aActor,
+    const nsIntRect& aBounds, bool aDoCreation, bool aNeedMakeCX /*= true*/,
+    bool aForceSetNewDocument /* = true*/) {
   if (mIsPageMode) {
     // XXXbz should the InitInternal in SetPageModeForTesting just pass false
     // here itself?
     aForceSetNewDocument = false;
   }
 
   // We don't want any scripts to run here. That can cause flushing,
   // which can cause reentry into initialization of this document viewer,
@@ -951,17 +952,17 @@ nsresult nsDocumentViewer::InitInternal(
   if (requestor) {
     // Set script-context-owner in the document
 
     nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(requestor);
 
     if (window) {
       nsCOMPtr<Document> curDoc = window->GetExtantDoc();
       if (aForceSetNewDocument || curDoc != mDocument) {
-        rv = window->SetNewDocument(mDocument, aState, false);
+        rv = window->SetNewDocument(mDocument, aState, false, aActor);
         if (NS_FAILED(rv)) {
           Destroy();
           return rv;
         }
       }
     }
   }
 
@@ -1550,17 +1551,17 @@ static void AttachContainerRecurse(nsIDo
 NS_IMETHODIMP
 nsDocumentViewer::Open(nsISupports* aState, nsISHEntry* aSHEntry) {
   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
 
   if (mDocument) {
     mDocument->SetContainer(mContainer);
   }
 
-  nsresult rv = InitInternal(mParentWidget, aState, mBounds, false);
+  nsresult rv = InitInternal(mParentWidget, aState, nullptr, mBounds, false);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mHidden = false;
 
   if (mPresShell) mPresShell->SetForwardingContainer(WeakPtr<nsDocShell>());
 
   // Rehook the child presentations.  The child shells are still in
   // session history, so get them from there.
@@ -2009,17 +2010,18 @@ nsDocumentViewer::SetDocumentInternal(Do
   if (mPresShell) {
     DestroyPresShell();
   }
 
   if (mPresContext) {
     DestroyPresContext();
 
     mWindow = nullptr;
-    rv = InitInternal(mParentWidget, nullptr, mBounds, true, true, false);
+    rv = InitInternal(mParentWidget, nullptr, nullptr, mBounds, true, true,
+                      false);
   }
 
   return rv;
 }
 
 PresShell* nsDocumentViewer::GetPresShell() { return mPresShell; }
 
 nsPresContext* nsDocumentViewer::GetPresContext() { return mPresContext; }
@@ -4124,18 +4126,19 @@ NS_IMETHODIMP nsDocumentViewer::SetPageM
     mPresContext = CreatePresContext(
         mDocument, nsPresContext::eContext_PageLayout, FindContainerView());
     NS_ENSURE_TRUE(mPresContext, NS_ERROR_OUT_OF_MEMORY);
     mPresContext->SetPaginatedScrolling(true);
     mPresContext->SetPrintSettings(aPrintSettings);
     nsresult rv = mPresContext->Init(mDeviceContext);
     NS_ENSURE_SUCCESS(rv, rv);
   }
-  NS_ENSURE_SUCCESS(InitInternal(mParentWidget, nullptr, mBounds, true, false),
-                    NS_ERROR_FAILURE);
+  NS_ENSURE_SUCCESS(
+      InitInternal(mParentWidget, nullptr, nullptr, mBounds, true, false),
+      NS_ERROR_FAILURE);
 
   Show();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocumentViewer::GetHistoryEntry(nsISHEntry** aHistoryEntry) {
   NS_IF_ADDREF(*aHistoryEntry = mSHEntry);
--- a/toolkit/components/browser/moz.build
+++ b/toolkit/components/browser/moz.build
@@ -29,16 +29,18 @@ if CONFIG['NS_PRINTING']:
 
 XPIDL_MODULE = 'webBrowser_core'
 
 UNIFIED_SOURCES += [
     'nsWebBrowser.cpp',
     'nsWebBrowserContentPolicy.cpp',
 ]
 
+include('/ipc/chromium/chromium-config.mozbuild')
+
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/docshell/base',
     '/dom/base',
     '/dom/svg',
     '/layout/style',
 ]
 
--- a/toolkit/components/browser/nsWebBrowser.cpp
+++ b/toolkit/components/browser/nsWebBrowser.cpp
@@ -33,16 +33,17 @@
 #include "nsFocusManager.h"
 #include "Layers.h"
 #include "nsILoadContext.h"
 #include "nsDocShell.h"
 
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/BrowsingContext.h"
 #include "mozilla/dom/LoadURIOptionsBinding.h"
+#include "mozilla/dom/WindowGlobalChild.h"
 
 // for painting the background window
 #include "mozilla/LookAndFeel.h"
 
 // Printing Includes
 #ifdef NS_PRINTING
 #  include "nsIWebBrowserPrint.h"
 #  include "nsIContentViewer.h"
@@ -98,30 +99,38 @@ nsIWidget* nsWebBrowser::EnsureWidget() 
   return mInternalWidget;
 }
 
 /* static */
 already_AddRefed<nsWebBrowser> nsWebBrowser::Create(
     nsIWebBrowserChrome* aContainerWindow, nsIWidget* aParentWidget,
     const OriginAttributes& aOriginAttributes,
     dom::BrowsingContext* aBrowsingContext,
+    dom::WindowGlobalChild* aInitialWindowChild,
     bool aDisableHistory /* = false */) {
+  MOZ_ASSERT_IF(aInitialWindowChild,
+                aInitialWindowChild->BrowsingContext() == aBrowsingContext);
+
   RefPtr<nsWebBrowser> browser = new nsWebBrowser(
       aBrowsingContext->IsContent() ? typeContentWrapper : typeChromeWrapper);
 
   // nsWebBrowser::SetContainer also calls nsWebBrowser::EnsureDocShellTreeOwner
   NS_ENSURE_SUCCESS(browser->SetContainerWindow(aContainerWindow), nullptr);
   NS_ENSURE_SUCCESS(browser->SetParentWidget(aParentWidget), nullptr);
 
   nsCOMPtr<nsIWidget> docShellParentWidget = browser->EnsureWidget();
   if (NS_WARN_IF(!docShellParentWidget)) {
     return nullptr;
   }
 
-  RefPtr<nsDocShell> docShell = nsDocShell::Create(aBrowsingContext);
+  uint64_t outerWindowId =
+      aInitialWindowChild ? aInitialWindowChild->OuterWindowId() : 0;
+
+  RefPtr<nsDocShell> docShell =
+      nsDocShell::Create(aBrowsingContext, outerWindowId);
   if (NS_WARN_IF(!docShell)) {
     return nullptr;
   }
   docShell->SetOriginAttributes(aOriginAttributes);
   browser->SetDocShell(docShell);
 
   // get the system default window background colour
   LookAndFeel::GetColor(LookAndFeel::ColorID::WindowBackground,
@@ -173,16 +182,20 @@ already_AddRefed<nsWebBrowser> nsWebBrow
   if (NS_WARN_IF(!securityUI)) {
     return nullptr;
   }
   securityUI->Init(docShell);
 
   docShellTreeOwner->AddToWatcher();  // evil twin of Remove in SetDocShell(0)
   docShellTreeOwner->AddChromeListeners();
 
+  if (aInitialWindowChild) {
+    docShell->CreateContentViewerForActor(aInitialWindowChild);
+  }
+
   return browser.forget();
 }
 
 NS_IMETHODIMP
 nsWebBrowser::InternalDestroy() {
   if (mInternalWidget) {
     mInternalWidget->SetWidgetListener(nullptr);
     mInternalWidget->Destroy();
--- a/toolkit/components/browser/nsWebBrowser.h
+++ b/toolkit/components/browser/nsWebBrowser.h
@@ -53,16 +53,22 @@ class nsWebBrowserInitInfo {
   {                                                  \
     0xcda5863a, 0xaa9c, 0x411e, {                    \
       0xbe, 0x49, 0xea, 0x0d, 0x52, 0x5a, 0xb4, 0xb5 \
     }                                                \
   }
 
 class mozIDOMWindowProxy;
 
+namespace mozilla {
+namespace dom {
+class WindowGlobalChild;
+}  // namespace dom
+}  // namespace mozilla
+
 class nsWebBrowser final : public nsIWebBrowser,
                            public nsIWebNavigation,
                            public nsIDocShellTreeItem,
                            public nsIBaseWindow,
                            public nsIScrollable,
                            public nsIInterfaceRequestor,
                            public nsIWebBrowserPersist,
                            public nsIWebProgressListener,
@@ -104,16 +110,17 @@ class nsWebBrowser final : public nsIWeb
   void SetAllowDNSPrefetch(bool aAllowPrefetch);
   void FocusActivate();
   void FocusDeactivate();
 
   static already_AddRefed<nsWebBrowser> Create(
       nsIWebBrowserChrome* aContainerWindow, nsIWidget* aParentWidget,
       const mozilla::OriginAttributes& aOriginAttributes,
       mozilla::dom::BrowsingContext* aBrowsingContext,
+      mozilla::dom::WindowGlobalChild* aInitialWindowChild,
       bool aDisableHistory = false);
 
  protected:
   virtual ~nsWebBrowser();
   NS_IMETHOD InternalDestroy();
 
   // XXXbz why are these NS_IMETHOD?  They're not interface methods!
   NS_IMETHOD SetDocShell(nsIDocShell* aDocShell);
--- a/xpfe/appshell/nsAppShellService.cpp
+++ b/xpfe/appshell/nsAppShellService.cpp
@@ -489,19 +489,19 @@ nsAppShellService::CreateWindowlessBrows
   RefPtr<BrowsingContext> browsingContext =
       BrowsingContext::Create(nullptr, nullptr, EmptyString(),
                               aIsChrome ? BrowsingContext::Type::Chrome
                                         : BrowsingContext::Type::Content);
 
   /* Next, we create an instance of nsWebBrowser. Instances of this class have
    * an associated doc shell, which is what we're interested in.
    */
-  nsCOMPtr<nsIWebBrowser> browser =
-      nsWebBrowser::Create(stub, widget, OriginAttributes(), browsingContext,
-                           true /* disable history */);
+  nsCOMPtr<nsIWebBrowser> browser = nsWebBrowser::Create(
+      stub, widget, OriginAttributes(), browsingContext,
+      nullptr /* initialWindowChild */, true /* disable history */);
 
   if (NS_WARN_IF(!browser)) {
     NS_ERROR("Couldn't create instance of nsWebBrowser!");
     return NS_ERROR_FAILURE;
   }
 
   // Make sure the container window owns the the nsWebBrowser instance.
   stub->SetBrowser(browser);