Bug 1510460 - Record the current WindowGlobal on ChromeBrowsingContext, r=farre
☠☠ backed out by 62f498382b14 ☠ ☠
authorNika Layzell <nika@thelayzells.com>
Tue, 27 Nov 2018 15:03:05 -0500
changeset 508607 78d93dade802d5a285fe718284310a397be97acb
parent 508606 7e23a1b903356b3bdfbf1844bee62513969b93a6
child 508608 788d4d99984316782178133ba3bdab6b5742644a
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfarre
bugs1510460
milestone65.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 1510460 - Record the current WindowGlobal on ChromeBrowsingContext, r=farre Differential Revision: https://phabricator.services.mozilla.com/D13156
docshell/base/ChromeBrowsingContext.cpp
docshell/base/ChromeBrowsingContext.h
dom/base/nsGlobalWindowOuter.cpp
dom/chrome-webidl/BrowsingContext.webidl
dom/chrome-webidl/WindowGlobalActors.webidl
dom/ipc/PWindowGlobal.ipdl
dom/ipc/WindowGlobalChild.cpp
dom/ipc/WindowGlobalChild.h
dom/ipc/WindowGlobalParent.cpp
dom/ipc/WindowGlobalParent.h
--- a/docshell/base/ChromeBrowsingContext.cpp
+++ b/docshell/base/ChromeBrowsingContext.cpp
@@ -69,16 +69,30 @@ void ChromeBrowsingContext::RegisterWind
   MOZ_ASSERT(!mWindowGlobals.Contains(aGlobal), "Global already registered!");
   mWindowGlobals.PutEntry(aGlobal);
 }
 
 void ChromeBrowsingContext::UnregisterWindowGlobal(
     WindowGlobalParent* aGlobal) {
   MOZ_ASSERT(mWindowGlobals.Contains(aGlobal), "Global not registered!");
   mWindowGlobals.RemoveEntry(aGlobal);
+
+  // Our current window global should be in our mWindowGlobals set. If it's not
+  // anymore, clear that reference.
+  if (aGlobal == mCurrentWindowGlobal) {
+    mCurrentWindowGlobal = nullptr;
+  }
+}
+
+void ChromeBrowsingContext::SetCurrentWindowGlobal(
+    WindowGlobalParent* aGlobal) {
+  MOZ_ASSERT(mWindowGlobals.Contains(aGlobal), "Global not registered!");
+
+  // TODO: This should probably assert that the processes match.
+  mCurrentWindowGlobal = aGlobal;
 }
 
 JSObject* ChromeBrowsingContext::WrapObject(JSContext* aCx,
                                             JS::Handle<JSObject*> aGivenProto) {
   return ChromeBrowsingContext_Binding::Wrap(aCx, this, aGivenProto);
 }
 
 void ChromeBrowsingContext::Traverse(nsCycleCollectionTraversalCallback& cb) {
--- a/docshell/base/ChromeBrowsingContext.h
+++ b/docshell/base/ChromeBrowsingContext.h
@@ -36,16 +36,22 @@ class ChromeBrowsingContext final : publ
   }
 
   void GetWindowGlobals(nsTArray<RefPtr<WindowGlobalParent>>& aWindows);
 
   // Called by WindowGlobalParent to register and unregister window globals.
   void RegisterWindowGlobal(WindowGlobalParent* aGlobal);
   void UnregisterWindowGlobal(WindowGlobalParent* aGlobal);
 
+  // The current active WindowGlobal.
+  WindowGlobalParent* GetCurrentWindowGlobal() const {
+    return mCurrentWindowGlobal;
+  }
+  void SetCurrentWindowGlobal(WindowGlobalParent* aGlobal);
+
   JSObject* WrapObject(JSContext* aCx,
                        JS::Handle<JSObject*> aGivenProto) override;
 
  protected:
   void Traverse(nsCycleCollectionTraversalCallback& cb);
   void Unlink();
 
   using Type = BrowsingContext::Type;
@@ -57,14 +63,15 @@ class ChromeBrowsingContext final : publ
   friend class BrowsingContext;
 
   // XXX(farre): Store a ContentParent pointer here rather than mProcessId?
   // Indicates which process owns the docshell.
   uint64_t mProcessId;
 
   // All live window globals within this browsing context.
   nsTHashtable<nsRefPtrHashKey<WindowGlobalParent>> mWindowGlobals;
+  RefPtr<WindowGlobalParent> mCurrentWindowGlobal;
 };
 
 }  // namespace dom
 }  // namespace mozilla
 
 #endif  // !defined(mozilla_dom_ChromeBrowsingContext_h)
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -63,16 +63,17 @@
 #include "WindowNamedPropertiesHandler.h"
 #include "nsFrameSelection.h"
 #include "nsNetUtil.h"
 #include "nsVariant.h"
 #include "nsPrintfCString.h"
 #include "mozilla/intl/LocaleService.h"
 #include "WindowDestroyedEvent.h"
 #include "nsDocShellLoadState.h"
+#include "mozilla/dom/WindowGlobalChild.h"
 
 // Helper Classes
 #include "nsJSUtils.h"
 #include "jsapi.h"
 #include "js/Wrapper.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsReadableUtils.h"
 #include "nsJSEnvironment.h"
@@ -1957,16 +1958,20 @@ nsresult nsGlobalWindowOuter::SetNewDocu
   }
 
   // Handle any document.open() logic after we setup the new inner window
   // so that any bound DETH objects can see the top window, document, etc.
   if (handleDocumentOpen) {
     newInnerWindow->MigrateStateForDocumentOpen(currentInner);
   }
 
+  // Tell the WindowGlobalParent that it should become the current window global
+  // for our BrowsingContext if it isn't already.
+  mInnerWindow->GetWindowGlobalChild()->SendBecomeCurrentWindowGlobal();
+
   // We no longer need the old inner window.  Start its destruction if
   // its not being reused and clear our reference.
   if (doomCurrentInner) {
     currentInner->FreeInnerObjects(handleDocumentOpen);
   }
   currentInner = nullptr;
 
   // Ask the JS engine to assert that it's valid to access our DocGroup whenever
--- a/dom/chrome-webidl/BrowsingContext.webidl
+++ b/dom/chrome-webidl/BrowsingContext.webidl
@@ -16,9 +16,11 @@ interface BrowsingContext {
   readonly attribute unsigned long long id;
 
   readonly attribute BrowsingContext? opener;
 };
 
 [Exposed=Window, ChromeOnly]
 interface ChromeBrowsingContext : BrowsingContext {
   sequence<WindowGlobalParent> getWindowGlobals();
+
+  readonly attribute WindowGlobalParent? currentWindowGlobal;
 };
--- a/dom/chrome-webidl/WindowGlobalActors.webidl
+++ b/dom/chrome-webidl/WindowGlobalActors.webidl
@@ -8,16 +8,18 @@ interface URI;
 interface nsIDocShell;
 
 [Exposed=Window, ChromeOnly]
 interface WindowGlobalParent {
   readonly attribute boolean isClosed;
   readonly attribute boolean isInProcess;
   readonly attribute ChromeBrowsingContext browsingContext;
 
+  readonly attribute boolean isCurrentGlobal;
+
   readonly attribute unsigned long long innerWindowId;
   readonly attribute unsigned long long outerWindowId;
 
   readonly attribute FrameLoader? rootFrameLoader; // Embedded (browser) only
 
   readonly attribute WindowGlobalChild? childActor; // in-process only
 
   // Information about the currently loaded document.
@@ -28,15 +30,17 @@ interface WindowGlobalParent {
 };
 
 [Exposed=Window, ChromeOnly]
 interface WindowGlobalChild {
   readonly attribute boolean isClosed;
   readonly attribute boolean isInProcess;
   readonly attribute BrowsingContext browsingContext;
 
+  readonly attribute boolean isCurrentGlobal;
+
   readonly attribute unsigned long long innerWindowId;
   readonly attribute unsigned long long outerWindowId;
 
   readonly attribute WindowGlobalParent? parentActor; // in-process only
 
   static WindowGlobalChild? getByInnerWindowId(unsigned long long innerWIndowId);
 };
--- a/dom/ipc/PWindowGlobal.ipdl
+++ b/dom/ipc/PWindowGlobal.ipdl
@@ -23,13 +23,16 @@ namespace dom {
 async protocol PWindowGlobal
 {
   manager PBrowser or PInProcess;
 
 parent:
   /// Update the URI of the document in this WindowGlobal.
   async UpdateDocumentURI(nsIURI aUri);
 
+  /// Notify the parent that this PWindowGlobal is now the current global.
+  async BecomeCurrentWindowGlobal();
+
   async __delete__();
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/WindowGlobalChild.cpp
+++ b/dom/ipc/WindowGlobalChild.cpp
@@ -77,16 +77,22 @@ WindowGlobalChild::Create(nsGlobalWindow
 WindowGlobalChild::GetByInnerWindowId(uint64_t aInnerWindowId)
 {
   if (!gWindowGlobalChildById) {
     return nullptr;
   }
   return gWindowGlobalChildById->Get(aInnerWindowId);
 }
 
+bool
+WindowGlobalChild::IsCurrentGlobal()
+{
+  return !mIPCClosed && mWindowGlobal->IsCurrentInnerWindow();
+}
+
 already_AddRefed<WindowGlobalParent>
 WindowGlobalChild::GetParentActor()
 {
   if (mIPCClosed) {
     return nullptr;
   }
   IProtocol* otherSide = InProcessChild::ParentActorFor(this);
   return do_AddRef(static_cast<WindowGlobalParent*>(otherSide));
--- a/dom/ipc/WindowGlobalChild.h
+++ b/dom/ipc/WindowGlobalChild.h
@@ -48,16 +48,18 @@ public:
   // Check if this actor is managed by PInProcess, as-in the document is loaded
   // in the chrome process.
   bool IsInProcess() { return XRE_IsParentProcess(); }
 
   // The Window ID for this WindowGlobal
   uint64_t InnerWindowId() { return mInnerWindowId; }
   uint64_t OuterWindowId() { return mOuterWindowId; }
 
+  bool IsCurrentGlobal();
+
   // Get the other side of this actor if it is an in-process actor. Returns
   // |nullptr| if the actor has been torn down, or is not in-process.
   already_AddRefed<WindowGlobalParent> GetParentActor();
 
   // Create and initialize the WindowGlobalChild object.
   static already_AddRefed<WindowGlobalChild>
   Create(nsGlobalWindowInner* aWindow);
 
--- a/dom/ipc/WindowGlobalParent.cpp
+++ b/dom/ipc/WindowGlobalParent.cpp
@@ -119,16 +119,29 @@ IPCResult
 WindowGlobalParent::RecvUpdateDocumentURI(nsIURI* aURI)
 {
   // XXX(nika): Assert that the URI change was one which makes sense (either
   // about:blank -> a real URI, or a legal push/popstate URI change?)
   mDocumentURI = aURI;
   return IPC_OK();
 }
 
+IPCResult
+WindowGlobalParent::RecvBecomeCurrentWindowGlobal()
+{
+  mBrowsingContext->SetCurrentWindowGlobal(this);
+  return IPC_OK();
+}
+
+bool
+WindowGlobalParent::IsCurrentGlobal()
+{
+  return !mIPCClosed && mBrowsingContext->GetCurrentWindowGlobal() == this;
+}
+
 void
 WindowGlobalParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   mIPCClosed = true;
   gWindowGlobalParentsById->Remove(mInnerWindowId);
   mBrowsingContext->UnregisterWindowGlobal(this);
 }
 
--- a/dom/ipc/WindowGlobalParent.h
+++ b/dom/ipc/WindowGlobalParent.h
@@ -66,31 +66,34 @@ public:
 
   // The current URI which loaded in the document.
   nsIURI* GetDocumentURI() { return mDocumentURI; }
 
   // Window IDs for inner/outer windows.
   uint64_t OuterWindowId() { return mOuterWindowId; }
   uint64_t InnerWindowId() { return mInnerWindowId; }
 
+  bool IsCurrentGlobal();
+
   // Create a WindowGlobalParent from over IPC. This method should not be called
   // from outside of the IPC constructors.
   WindowGlobalParent(const WindowGlobalInit& aInit, bool aInProcess);
 
   // Initialize the mFrameLoader fields for a created WindowGlobalParent. Must
   // be called after setting the Manager actor.
   void Init(const WindowGlobalInit& aInit);
 
   nsISupports* GetParentObject();
   JSObject* WrapObject(JSContext* aCx,
                        JS::Handle<JSObject*> aGivenProto) override;
 
 protected:
   // IPC messages
   mozilla::ipc::IPCResult RecvUpdateDocumentURI(nsIURI* aURI) override;
+  mozilla::ipc::IPCResult RecvBecomeCurrentWindowGlobal() override;
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
 private:
   ~WindowGlobalParent();
 
   // NOTE: This document principal doesn't reflect possible |document.domain|
   // mutations which may have been made in the actual document.