Bug 1500949 - Include innerWindowId/outerWindowId in PWindowGlobal, r=farre
☠☠ backed out by 62f498382b14 ☠ ☠
authorNika Layzell <nika@thelayzells.com>
Sat, 20 Oct 2018 16:04:00 -0400
changeset 449283 622d4bf1c0efe87d3128bc89903cb515487d69f4
parent 449282 8f8c74fb660dd36cf873f9aa82c3487aea951876
child 449284 9fe159adaef4b0ab58cf16969f70a75e4ef2e546
push id110347
push usernika@thelayzells.com
push dateTue, 04 Dec 2018 16:25:58 +0000
treeherdermozilla-inbound@788d4d999843 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfarre
bugs1500949
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 1500949 - Include innerWindowId/outerWindowId in PWindowGlobal, r=farre This will be useful as both an ID for PWindowGlobal, as well as a mechanism for taking advantage of already synchronized information. As an example, LoadInfo objects contain the inner window IDs of the window requesting the load, which can now be used to obtain a reference to the corresponding WindowGlobalParent in the parent process. Differential Revision: https://phabricator.services.mozilla.com/D9396
dom/chrome-webidl/WindowGlobalActors.webidl
dom/ipc/DOMTypes.ipdlh
dom/ipc/WindowGlobalChild.cpp
dom/ipc/WindowGlobalChild.h
dom/ipc/WindowGlobalParent.cpp
dom/ipc/WindowGlobalParent.h
--- a/dom/chrome-webidl/WindowGlobalActors.webidl
+++ b/dom/chrome-webidl/WindowGlobalActors.webidl
@@ -8,26 +8,36 @@ interface URI;
 interface nsIDocShell;
 
 [Exposed=Window, ChromeOnly]
 interface WindowGlobalParent {
   readonly attribute boolean isClosed;
   readonly attribute boolean isInProcess;
   readonly attribute ChromeBrowsingContext browsingContext;
 
+  readonly attribute unsigned long long innerWindowId;
+  readonly attribute unsigned long long outerWindowId;
+
   // XXX(nika): We would want to expose this, but |FrameLoader| isn't exposed on System.
   // readonly attribute FrameLoader? rootFrameLoader; // Embedded (browser) only
 
   readonly attribute WindowGlobalChild? childActor; // in-process only
 
   // Information about the currently loaded document.
   readonly attribute Principal documentPrincipal;
   readonly attribute URI? documentURI;
+
+  static WindowGlobalParent? getByInnerWindowId(unsigned long long innerWindowId);
 };
 
 [Exposed=Window, ChromeOnly]
 interface WindowGlobalChild {
   readonly attribute boolean isClosed;
   readonly attribute boolean isInProcess;
   readonly attribute BrowsingContext browsingContext;
 
+  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/DOMTypes.ipdlh
+++ b/dom/ipc/DOMTypes.ipdlh
@@ -184,12 +184,14 @@ struct PerformanceInfo
   // Counters per category. For workers, a single entry
   CategoryDispatch[] items;
 };
 
 struct WindowGlobalInit
 {
   nsIPrincipal principal;
   BrowsingContextId browsingContextId;
+  uint64_t innerWindowId;
+  uint64_t outerWindowId;
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/WindowGlobalChild.cpp
+++ b/dom/ipc/WindowGlobalChild.cpp
@@ -7,37 +7,46 @@
 #include "mozilla/dom/WindowGlobalChild.h"
 #include "mozilla/ipc/InProcessChild.h"
 #include "mozilla/dom/BrowsingContext.h"
 #include "mozilla/dom/WindowGlobalActorsBinding.h"
 
 namespace mozilla {
 namespace dom {
 
-WindowGlobalChild::WindowGlobalChild(nsGlobalWindowInner* aWindow, dom::BrowsingContext* aBrowsingContext)
+typedef nsRefPtrHashtable<nsUint64HashKey, WindowGlobalChild> WGCByIdMap;
+static StaticAutoPtr<WGCByIdMap> gWindowGlobalChildById;
+
+WindowGlobalChild::WindowGlobalChild(nsGlobalWindowInner* aWindow,
+                                     dom::BrowsingContext* aBrowsingContext)
   : mWindowGlobal(aWindow)
   , mBrowsingContext(aBrowsingContext)
-  , mIPCClosed(false)
+  , mInnerWindowId(aWindow->WindowID())
+  , mOuterWindowId(aWindow->GetOuterWindow()->WindowID())
+  , mIPCClosed(true)
 {
 }
 
 already_AddRefed<WindowGlobalChild>
 WindowGlobalChild::Create(nsGlobalWindowInner* aWindow)
 {
   nsCOMPtr<nsIPrincipal> principal = aWindow->GetPrincipal();
   MOZ_ASSERT(principal);
 
   RefPtr<nsDocShell> docshell = nsDocShell::Cast(aWindow->GetDocShell());
   MOZ_ASSERT(docshell);
 
   // Initalize our WindowGlobalChild object.
   RefPtr<dom::BrowsingContext> bc = docshell->GetBrowsingContext();
   RefPtr<WindowGlobalChild> wgc = new WindowGlobalChild(aWindow, bc);
 
-  WindowGlobalInit init(principal, BrowsingContextId(wgc->BrowsingContext()->Id()));
+  WindowGlobalInit init(principal,
+                        BrowsingContextId(wgc->BrowsingContext()->Id()),
+                        wgc->mInnerWindowId,
+                        wgc->mOuterWindowId);
 
   // Send the link constructor over PInProcessChild or PBrowser.
   if (XRE_IsParentProcess()) {
     InProcessChild* ipc = InProcessChild::Singleton();
     if (!ipc) {
       return nullptr;
     }
 
@@ -45,38 +54,60 @@ WindowGlobalChild::Create(nsGlobalWindow
     ipc->SendPWindowGlobalConstructor(do_AddRef(wgc).take(), init);
   } else {
     RefPtr<TabChild> tabChild = TabChild::GetFrom(static_cast<mozIDOMWindow*>(aWindow));
     MOZ_ASSERT(tabChild);
 
     // Note: ref is released in DeallocPWindowGlobalChild
     tabChild->SendPWindowGlobalConstructor(do_AddRef(wgc).take(), init);
   }
+  wgc->mIPCClosed = false;
+
+  // Register this WindowGlobal in the gWindowGlobalParentsById map.
+  if (!gWindowGlobalChildById) {
+    gWindowGlobalChildById = new WGCByIdMap();
+    ClearOnShutdown(&gWindowGlobalChildById);
+  }
+  auto entry = gWindowGlobalChildById->LookupForAdd(wgc->mInnerWindowId);
+  MOZ_RELEASE_ASSERT(!entry, "Duplicate WindowGlobalChild entry for ID!");
+  entry.OrInsert([&] { return wgc; });
 
   return wgc.forget();
 }
 
+/* static */ already_AddRefed<WindowGlobalChild>
+WindowGlobalChild::GetByInnerWindowId(uint64_t aInnerWindowId)
+{
+  if (!gWindowGlobalChildById) {
+    return nullptr;
+  }
+  return gWindowGlobalChildById->Get(aInnerWindowId);
+}
+
 already_AddRefed<WindowGlobalParent>
 WindowGlobalChild::GetParentActor()
 {
   if (mIPCClosed) {
     return nullptr;
   }
   IProtocol* otherSide = InProcessChild::ParentActorFor(this);
   return do_AddRef(static_cast<WindowGlobalParent*>(otherSide));
 }
 
 void
 WindowGlobalChild::ActorDestroy(ActorDestroyReason aWhy)
 {
   mIPCClosed = true;
+  gWindowGlobalChildById->Remove(mInnerWindowId);
 }
 
 WindowGlobalChild::~WindowGlobalChild()
 {
+  MOZ_ASSERT(!gWindowGlobalChildById ||
+             !gWindowGlobalChildById->Contains(mInnerWindowId));
 }
 
 JSObject*
 WindowGlobalChild::WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto)
 {
   return WindowGlobalChild_Binding::Wrap(aCx, this, aGivenProto);
 }
--- a/dom/ipc/WindowGlobalChild.h
+++ b/dom/ipc/WindowGlobalChild.h
@@ -26,26 +26,38 @@ class WindowGlobalParent;
  */
 class WindowGlobalChild : public nsWrapperCache
                         , public PWindowGlobalChild
 {
 public:
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WindowGlobalChild)
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WindowGlobalChild)
 
+  static already_AddRefed<WindowGlobalChild>
+  GetByInnerWindowId(uint64_t aInnerWindowId);
+
+  static already_AddRefed<WindowGlobalChild>
+  GetByInnerWindowId(const GlobalObject& aGlobal, uint64_t aInnerWindowId) {
+    return GetByInnerWindowId(aInnerWindowId);
+  }
+
   dom::BrowsingContext* BrowsingContext() { return mBrowsingContext; }
   nsGlobalWindowInner* WindowGlobal() { return mWindowGlobal; }
 
   // Has this actor been shut down
   bool IsClosed() { return mIPCClosed; }
 
   // 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; }
+
   // 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);
 
@@ -57,15 +69,17 @@ protected:
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
 private:
   WindowGlobalChild(nsGlobalWindowInner* aWindow, dom::BrowsingContext* aBc);
   ~WindowGlobalChild();
 
   RefPtr<nsGlobalWindowInner> mWindowGlobal;
   RefPtr<dom::BrowsingContext> mBrowsingContext;
+  uint64_t mInnerWindowId;
+  uint64_t mOuterWindowId;
   bool mIPCClosed;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // !defined(mozilla_dom_WindowGlobalChild_h)
--- a/dom/ipc/WindowGlobalParent.cpp
+++ b/dom/ipc/WindowGlobalParent.cpp
@@ -9,19 +9,24 @@
 #include "mozilla/dom/ChromeBrowsingContext.h"
 #include "mozilla/dom/WindowGlobalActorsBinding.h"
 
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace dom {
 
+typedef nsRefPtrHashtable<nsUint64HashKey, WindowGlobalParent> WGPByIdMap;
+static StaticAutoPtr<WGPByIdMap> gWindowGlobalParentsById;
+
 WindowGlobalParent::WindowGlobalParent(const WindowGlobalInit& aInit,
                                        bool aInProcess)
   : mDocumentPrincipal(aInit.principal())
+  , mInnerWindowId(aInit.innerWindowId())
+  , mOuterWindowId(aInit.outerWindowId())
   , mInProcess(aInProcess)
   , mIPCClosed(true)  // Closed until WGP::Init
 {
   MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess(), "Parent process only");
   MOZ_RELEASE_ASSERT(mDocumentPrincipal, "Must have a valid principal");
 
   // NOTE: mBrowsingContext initialized in Init()
   MOZ_RELEASE_ASSERT(aInit.browsingContextId() != 0,
@@ -32,16 +37,25 @@ void
 WindowGlobalParent::Init(const WindowGlobalInit& aInit)
 {
   MOZ_ASSERT(Manager(), "Should have a manager!");
   MOZ_ASSERT(!mFrameLoader, "Cannot Init() a WindowGlobalParent twice!");
 
   MOZ_ASSERT(mIPCClosed, "IPC shouldn't be open yet");
   mIPCClosed = false;
 
+  // Register this WindowGlobal in the gWindowGlobalParentsById map.
+  if (!gWindowGlobalParentsById) {
+    gWindowGlobalParentsById = new WGPByIdMap();
+    ClearOnShutdown(&gWindowGlobalParentsById);
+  }
+  auto entry = gWindowGlobalParentsById->LookupForAdd(mInnerWindowId);
+  MOZ_RELEASE_ASSERT(!entry, "Duplicate WindowGlobalParent entry for ID!");
+  entry.OrInsert([&] { return this; });
+
   // Determine which content process the window global is coming from.
   ContentParentId processId(0);
   if (!mInProcess) {
     processId = static_cast<ContentParent*>(Manager()->Manager())->ChildID();
   }
 
   mBrowsingContext = ChromeBrowsingContext::Get(aInit.browsingContextId());
   MOZ_ASSERT(mBrowsingContext);
@@ -77,16 +91,25 @@ WindowGlobalParent::Init(const WindowGlo
   // Extract the nsFrameLoader from the current frame element. We may not have a
   // nsFrameLoader if we are a chrome document.
   nsCOMPtr<nsIFrameLoaderOwner> flOwner = do_QueryInterface(frameElement);
   if (flOwner) {
     mFrameLoader = flOwner->GetFrameLoader();
   }
 }
 
+/* static */ already_AddRefed<WindowGlobalParent>
+WindowGlobalParent::GetByInnerWindowId(uint64_t aInnerWindowId)
+{
+  if (!gWindowGlobalParentsById) {
+    return nullptr;
+  }
+  return gWindowGlobalParentsById->Get(aInnerWindowId);
+}
+
 already_AddRefed<WindowGlobalChild>
 WindowGlobalParent::GetChildActor()
 {
   if (mIPCClosed) {
     return nullptr;
   }
   IProtocol* otherSide = InProcessParent::ChildActorFor(this);
   return do_AddRef(static_cast<WindowGlobalChild*>(otherSide));
@@ -100,21 +123,24 @@ WindowGlobalParent::RecvUpdateDocumentUR
   mDocumentURI = aURI;
   return IPC_OK();
 }
 
 void
 WindowGlobalParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   mIPCClosed = true;
+  gWindowGlobalParentsById->Remove(mInnerWindowId);
   mBrowsingContext->UnregisterWindowGlobal(this);
 }
 
 WindowGlobalParent::~WindowGlobalParent()
 {
+  MOZ_ASSERT(!gWindowGlobalParentsById ||
+             !gWindowGlobalParentsById->Contains(mInnerWindowId));
 }
 
 JSObject*
 WindowGlobalParent::WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto)
 {
   return WindowGlobalParent_Binding::Wrap(aCx, this, aGivenProto);
 }
--- a/dom/ipc/WindowGlobalParent.h
+++ b/dom/ipc/WindowGlobalParent.h
@@ -26,16 +26,24 @@ class WindowGlobalChild;
  */
 class WindowGlobalParent final : public nsWrapperCache
                                , public PWindowGlobalParent
 {
 public:
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WindowGlobalParent)
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WindowGlobalParent)
 
+  static already_AddRefed<WindowGlobalParent>
+  GetByInnerWindowId(uint64_t aInnerWindowId);
+
+  static already_AddRefed<WindowGlobalParent>
+  GetByInnerWindowId(const GlobalObject& aGlobal, uint64_t aInnerWindowId) {
+    return GetByInnerWindowId(aInnerWindowId);
+  }
+
   // Has this actor been shut down
   bool IsClosed() { return mIPCClosed; }
 
   // Check if this actor is managed by PInProcess, as-in the document is loaded
   // in-process.
   bool IsInProcess() { return mInProcess; }
 
   // Get the other side of this actor if it is an in-process actor. Returns
@@ -54,16 +62,20 @@ public:
   // which this WindowGlobal is a part of. This will be the nsFrameLoader
   // holding the TabParent for remote tabs, and the root content frameloader for
   // non-remote tabs.
   nsFrameLoader* GetRootFrameLoader() { return mFrameLoader; }
 
   // 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; }
+
   // 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);
 
@@ -81,16 +93,18 @@ private:
   ~WindowGlobalParent();
 
   // NOTE: This document principal doesn't reflect possible |document.domain|
   // mutations which may have been made in the actual document.
   nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
   nsCOMPtr<nsIURI> mDocumentURI;
   RefPtr<nsFrameLoader> mFrameLoader;
   RefPtr<ChromeBrowsingContext> mBrowsingContext;
+  uint64_t mInnerWindowId;
+  uint64_t mOuterWindowId;
   bool mInProcess;
   bool mIPCClosed;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // !defined(mozilla_dom_WindowGlobalParent_h)