Bug 1500944 - Part 1: Store the set of active WindowGlobalParent objects in ChromeBrowsingContext, r=farre
authorNika Layzell <nika@thelayzells.com>
Fri, 19 Oct 2018 18:00:59 -0400
changeset 508677 80ae3a4f8e444e88a32c37917c1a8bcdfb50e17d
parent 508676 20554da7b303f2f6442ecacfb846a5ad663c8fee
child 508678 6351599e53d47aac03ba4525c761ff74db0d5e1a
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
bugs1500944
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 1500944 - Part 1: Store the set of active WindowGlobalParent objects in ChromeBrowsingContext, r=farre This allows getting the set of all window globals for a given browsing context. This is less useful at the moment as the active window global is not exposed as such. That will be added as a follow-up. Differential Revision: https://phabricator.services.mozilla.com/D9393
docshell/base/BrowsingContext.cpp
docshell/base/BrowsingContext.h
docshell/base/ChromeBrowsingContext.cpp
docshell/base/ChromeBrowsingContext.h
dom/ipc/TabParent.cpp
dom/ipc/WindowGlobalParent.cpp
dom/ipc/WindowGlobalParent.h
ipc/glue/InProcessParent.cpp
--- a/docshell/base/BrowsingContext.cpp
+++ b/docshell/base/BrowsingContext.cpp
@@ -1,15 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "BrowsingContext.h"
+#include "mozilla/dom/BrowsingContext.h"
 
 #include "mozilla/dom/ChromeBrowsingContext.h"
 #include "mozilla/dom/BrowsingContextBinding.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/Logging.h"
--- a/docshell/base/BrowsingContext.h
+++ b/docshell/base/BrowsingContext.h
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef BrowsingContext_h
-#define BrowsingContext_h
+#ifndef mozilla_dom_BrowsingContext_h
+#define mozilla_dom_BrowsingContext_h
 
 #include "mozilla/LinkedList.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/WeakPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsString.h"
@@ -138,9 +138,10 @@ class BrowsingContext : public nsWrapper
   Children mChildren;
   WeakPtr<BrowsingContext> mOpener;
   nsCOMPtr<nsIDocShell> mDocShell;
   nsString mName;
 };
 
 }  // namespace dom
 }  // namespace mozilla
-#endif
+
+#endif  // !defined(mozilla_dom_BrowsingContext_h)
--- a/docshell/base/ChromeBrowsingContext.cpp
+++ b/docshell/base/ChromeBrowsingContext.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "ChromeBrowsingContext.h"
+#include "mozilla/dom/ChromeBrowsingContext.h"
+#include "mozilla/dom/WindowGlobalParent.h"
 
 namespace mozilla {
 namespace dom {
 
 ChromeBrowsingContext::ChromeBrowsingContext(BrowsingContext* aParent,
                                              BrowsingContext* aOpener,
                                              const nsAString& aName,
                                              uint64_t aBrowsingContextId,
@@ -51,10 +52,31 @@ ChromeBrowsingContext::ChromeBrowsingCon
 }
 
 /* static */ const ChromeBrowsingContext* ChromeBrowsingContext::Cast(
     const BrowsingContext* aContext) {
   MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
   return static_cast<const ChromeBrowsingContext*>(aContext);
 }
 
+void ChromeBrowsingContext::RegisterWindowGlobal(WindowGlobalParent* aGlobal) {
+  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);
+}
+
+void ChromeBrowsingContext::Traverse(nsCycleCollectionTraversalCallback& cb) {
+  ChromeBrowsingContext* tmp = this;
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindowGlobals);
+}
+
+void ChromeBrowsingContext::Unlink() {
+  ChromeBrowsingContext* tmp = this;
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindowGlobals);
+}
+
 }  // namespace dom
 }  // namespace mozilla
--- a/docshell/base/ChromeBrowsingContext.h
+++ b/docshell/base/ChromeBrowsingContext.h
@@ -1,53 +1,65 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef ChromeBrowsingContext_h
-#define ChromeBrowsingContext_h
+#ifndef mozilla_dom_ChromeBrowsingContext_h
+#define mozilla_dom_ChromeBrowsingContext_h
 
 #include "mozilla/dom/BrowsingContext.h"
 #include "mozilla/RefPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsWrapperCache.h"
+#include "nsTHashtable.h"
+#include "nsHashKeys.h"
 
 class nsIDocShell;
 
 namespace mozilla {
 namespace dom {
 
+class WindowGlobalParent;
+
 // ChromeBrowsingContext is a BrowsingContext living in the parent
 // process, with whatever extra data that a BrowsingContext in the
 // parent needs.
 class ChromeBrowsingContext final : public BrowsingContext {
  public:
   static void CleanupContexts(uint64_t aProcessId);
   static already_AddRefed<ChromeBrowsingContext> Get(uint64_t aId);
   static ChromeBrowsingContext* Cast(BrowsingContext* aContext);
   static const ChromeBrowsingContext* Cast(const BrowsingContext* aContext);
 
   bool IsOwnedByProcess(uint64_t aProcessId) const {
     return mProcessId == aProcessId;
   }
 
+  // Called by WindowGlobalParent to register and unregister window globals.
+  void RegisterWindowGlobal(WindowGlobalParent* aGlobal);
+  void UnregisterWindowGlobal(WindowGlobalParent* aGlobal);
+
  protected:
-  void Traverse(nsCycleCollectionTraversalCallback& cb) {}
-  void Unlink() {}
+  void Traverse(nsCycleCollectionTraversalCallback& cb);
+  void Unlink();
 
   using Type = BrowsingContext::Type;
   ChromeBrowsingContext(BrowsingContext* aParent, BrowsingContext* aOpener,
                         const nsAString& aName, uint64_t aBrowsingContextId,
                         uint64_t aProcessId, Type aType = Type::Chrome);
 
  private:
   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;
 };
 
 }  // namespace dom
 }  // namespace mozilla
-#endif
+
+#endif  // !defined(mozilla_dom_ChromeBrowsingContext_h)
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -986,17 +986,17 @@ bool TabParent::DeallocPIndexedDBPermiss
   MOZ_ASSERT(aActor);
 
   return mozilla::dom::indexedDB::DeallocPIndexedDBPermissionRequestParent(
       aActor);
 }
 
 IPCResult TabParent::RecvPWindowGlobalConstructor(
     PWindowGlobalParent* aActor, const WindowGlobalInit& aInit) {
-  static_cast<WindowGlobalParent*>(aActor)->Init();
+  static_cast<WindowGlobalParent*>(aActor)->Init(aInit);
   return IPC_OK();
 }
 
 PWindowGlobalParent* TabParent::AllocPWindowGlobalParent(
     const WindowGlobalInit& aInit) {
   // Reference freed in DeallocPWindowGlobalParent.
   return do_AddRef(new WindowGlobalParent(aInit, /* inproc */ false)).take();
 }
--- a/dom/ipc/WindowGlobalParent.cpp
+++ b/dom/ipc/WindowGlobalParent.cpp
@@ -1,41 +1,62 @@
 /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
 /* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/WindowGlobalParent.h"
 #include "mozilla/ipc/InProcessParent.h"
-#include "mozilla/dom/BrowsingContext.h"
+#include "mozilla/dom/ChromeBrowsingContext.h"
 
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace dom {
 
 WindowGlobalParent::WindowGlobalParent(const WindowGlobalInit& aInit,
                                        bool aInProcess)
-  : mBrowsingContextId(aInit.browsingContextId())
-  , mDocumentPrincipal(aInit.principal())
+  : mDocumentPrincipal(aInit.principal())
   , mInProcess(aInProcess)
-  , mIPCClosed(false)
+  , mIPCClosed(true)  // Closed until WGP::Init
 {
   MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess(), "Parent process only");
   MOZ_RELEASE_ASSERT(mDocumentPrincipal, "Must have a valid principal");
-  MOZ_RELEASE_ASSERT(mBrowsingContextId != 0, "Must be made in BrowsingContext");
+
+  // NOTE: mBrowsingContext initialized in Init()
+  MOZ_RELEASE_ASSERT(aInit.browsingContextId() != 0,
+                     "Must be made in BrowsingContext");
 }
 
 void
-WindowGlobalParent::Init()
+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;
+
+  // 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);
+
+  // XXX(nika): This won't be the case soon, but for now this is a good
+  // assertion as we can't switch processes. We should relax this eventually.
+  MOZ_ASSERT(mBrowsingContext->IsOwnedByProcess(processId));
+
+  // Attach ourself to the browsing context.
+  mBrowsingContext->RegisterWindowGlobal(this);
+
   // Determine what toplevel frame element our WindowGlobalParent is being
   // embedded in.
   RefPtr<Element> frameElement;
   if (mInProcess) {
     // In the in-process case, we can get it from the other side's
     // WindowGlobalChild.
     MOZ_ASSERT(Manager()->GetProtocolTypeId() == PInProcessMsgStart);
     RefPtr<WindowGlobalChild> otherSide = GetOtherSide();
@@ -55,22 +76,16 @@ WindowGlobalParent::Init()
   // 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();
   }
 }
 
-already_AddRefed<dom::BrowsingContext>
-WindowGlobalParent::BrowsingContext()
-{
-  return dom::BrowsingContext::Get(mBrowsingContextId);
-}
-
 already_AddRefed<WindowGlobalChild>
 WindowGlobalParent::GetOtherSide()
 {
   if (mIPCClosed) {
     return nullptr;
   }
   IProtocol* otherSide = InProcessParent::ChildActorFor(this);
   return do_AddRef(static_cast<WindowGlobalChild*>(otherSide));
@@ -84,20 +99,21 @@ WindowGlobalParent::RecvUpdateDocumentUR
   mDocumentURI = aURI;
   return IPC_OK();
 }
 
 void
 WindowGlobalParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   mIPCClosed = true;
+  mBrowsingContext->UnregisterWindowGlobal(this);
 }
 
 WindowGlobalParent::~WindowGlobalParent()
 {
 }
 
-NS_IMPL_CYCLE_COLLECTION(WindowGlobalParent, mFrameLoader)
+NS_IMPL_CYCLE_COLLECTION(WindowGlobalParent, mFrameLoader, mBrowsingContext)
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WindowGlobalParent, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WindowGlobalParent, Release)
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/WindowGlobalParent.h
+++ b/dom/ipc/WindowGlobalParent.h
@@ -12,17 +12,17 @@
 
 class nsIPrincipal;
 class nsIURI;
 class nsFrameLoader;
 
 namespace mozilla {
 namespace dom  {
 
-class BrowsingContext;
+class ChromeBrowsingContext;
 class WindowGlobalChild;
 
 /**
  * A handle in the parent process to a specific nsGlobalWindowInner object.
  */
 class WindowGlobalParent final : public PWindowGlobalParent
 {
 public:
@@ -41,55 +41,50 @@ public:
   already_AddRefed<WindowGlobalChild> GetOtherSide();
 
   // The principal of this WindowGlobal. This value will not change over the
   // lifetime of the WindowGlobal object, even to reflect changes in
   // |document.domain|.
   nsIPrincipal* DocumentPrincipal() { return mDocumentPrincipal; }
 
   // The BrowsingContext which this WindowGlobal has been loaded into.
-  already_AddRefed<dom::BrowsingContext> BrowsingContext();
+  ChromeBrowsingContext* BrowsingContext() { return mBrowsingContext; }
 
   // Get the root nsFrameLoader object for the tree of BrowsingContext nodes
   // 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; }
 
   // 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();
+  void Init(const WindowGlobalInit& aInit);
 
 protected:
   // IPC messages
   mozilla::ipc::IPCResult RecvUpdateDocumentURI(nsIURI* aURI) override;
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
 private:
   ~WindowGlobalParent();
 
-  // XXX(nika): We should store the BrowsingContext here. Unfortunately, the
-  // parent process is not sent down the BrowsingContext object until
-  // potentially after the WindowGlobalChild has been created. We should change
-  // this in the future.
-  uint64_t mBrowsingContextId;
-
   // 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;
   bool mInProcess;
   bool mIPCClosed;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // !defined(mozilla_dom_WindowGlobalParent_h)
--- a/ipc/glue/InProcessParent.cpp
+++ b/ipc/glue/InProcessParent.cpp
@@ -13,17 +13,17 @@ namespace mozilla {
 namespace ipc {
 
 NS_IMPL_ISUPPORTS(InProcessParent, nsIObserver)
 
 IPCResult
 InProcessParent::RecvPWindowGlobalConstructor(PWindowGlobalParent* aActor,
                                               const WindowGlobalInit& aInit)
 {
-  static_cast<WindowGlobalParent*>(aActor)->Init();
+  static_cast<WindowGlobalParent*>(aActor)->Init(aInit);
   return IPC_OK();
 }
 
 PWindowGlobalParent*
 InProcessParent::AllocPWindowGlobalParent(const WindowGlobalInit& aInit)
 {
   // Reference freed in DeallocPWindowGlobalParent.
   return do_AddRef(new WindowGlobalParent(aInit, /* inproc */ true)).take();