Bug 1500944 - Part 2: Expose WindowGlobal actors to Chrome JS, r=farre
☠☠ backed out by 9bfe29337ffe ☠ ☠
authorNika Layzell <nika@thelayzells.com>
Fri, 19 Oct 2018 19:02:56 -0400
changeset 504876 784b3b56e2abeb125faad7738975f502e556d376
parent 504875 0bad27401ddb5372cabc01e63d4ea0a2f9743e6f
child 504877 71c3b3677db81f3d07bf67f839c6a48e78cf85f3
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [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 2: Expose WindowGlobal actors to Chrome JS, r=farre This serves 2 purposes: 1. Provides an object corresponding to an inner window which Chrome JS can hold onto. 2. Provides the object to JS which Chrome JS per-window actors will be attached to. 3. Provides useful information to Chrome JS in the parent process. Differential Revision: https://phabricator.services.mozilla.com/D9394
docshell/base/BrowsingContext.h
docshell/base/ChromeBrowsingContext.cpp
docshell/base/ChromeBrowsingContext.h
dom/chrome-webidl/BrowsingContext.webidl
dom/chrome-webidl/WindowGlobalActors.webidl
dom/chrome-webidl/moz.build
dom/ipc/WindowGlobalChild.cpp
dom/ipc/WindowGlobalChild.h
dom/ipc/WindowGlobalParent.cpp
dom/ipc/WindowGlobalParent.h
--- a/docshell/base/BrowsingContext.h
+++ b/docshell/base/BrowsingContext.h
@@ -119,18 +119,18 @@ public:
   }
 
   void SetOpener(BrowsingContext* aOpener);
 
   static void GetRootBrowsingContexts(
     nsTArray<RefPtr<BrowsingContext>>& aBrowsingContexts);
 
   nsISupports* GetParentObject() const;
-  virtual JSObject* WrapObject(JSContext* aCx,
-                               JS::Handle<JSObject*> aGivenProto) override;
+  JSObject* WrapObject(JSContext* aCx,
+                       JS::Handle<JSObject*> aGivenProto) override;
 
   MOZ_DECLARE_WEAKREFERENCE_TYPENAME(BrowsingContext)
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(BrowsingContext)
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(BrowsingContext)
 
   using Children = AutoCleanLinkedList<RefPtr<BrowsingContext>>;
 
 protected:
--- a/docshell/base/ChromeBrowsingContext.cpp
+++ b/docshell/base/ChromeBrowsingContext.cpp
@@ -59,29 +59,45 @@ ChromeBrowsingContext::Cast(BrowsingCont
 /* static */ const ChromeBrowsingContext*
 ChromeBrowsingContext::Cast(const BrowsingContext* aContext)
 {
   MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
   return static_cast<const ChromeBrowsingContext*>(aContext);
 }
 
 void
+ChromeBrowsingContext::GetWindowGlobals(nsTArray<RefPtr<WindowGlobalParent>>& aWindows)
+{
+  aWindows.SetCapacity(mWindowGlobals.Count());
+  for (auto iter = mWindowGlobals.Iter(); !iter.Done(); iter.Next()) {
+    aWindows.AppendElement(iter.Get()->GetKey());
+  }
+}
+
+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);
 }
 
+JSObject*
+ChromeBrowsingContext::WrapObject(JSContext* aCx,
+                                  JS::Handle<JSObject*> aGivenProto)
+{
+  return ChromeBrowsingContext_Binding::Wrap(aCx, this, aGivenProto);
+}
+
 void
 ChromeBrowsingContext::Traverse(nsCycleCollectionTraversalCallback& cb)
 {
   ChromeBrowsingContext* tmp = this;
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindowGlobals);
 }
 
 void
--- a/docshell/base/ChromeBrowsingContext.h
+++ b/docshell/base/ChromeBrowsingContext.h
@@ -33,20 +33,25 @@ public:
   static ChromeBrowsingContext* Cast(BrowsingContext* aContext);
   static const ChromeBrowsingContext* Cast(const BrowsingContext* aContext);
 
   bool IsOwnedByProcess(uint64_t aProcessId) const
   {
     return mProcessId == aProcessId;
   }
 
+  void GetWindowGlobals(nsTArray<RefPtr<WindowGlobalParent>>& aWindows);
+
   // Called by WindowGlobalParent to register and unregister window globals.
   void RegisterWindowGlobal(WindowGlobalParent* aGlobal);
   void UnregisterWindowGlobal(WindowGlobalParent* aGlobal);
 
+  JSObject* WrapObject(JSContext* aCx,
+                       JS::Handle<JSObject*> aGivenProto) override;
+
 protected:
   void Traverse(nsCycleCollectionTraversalCallback& cb);
   void Unlink();
 
   using Type = BrowsingContext::Type;
   ChromeBrowsingContext(BrowsingContext* aParent,
                         BrowsingContext* aOpener,
                         const nsAString& aName,
--- a/dom/chrome-webidl/BrowsingContext.webidl
+++ b/dom/chrome-webidl/BrowsingContext.webidl
@@ -12,8 +12,13 @@ interface BrowsingContext {
   sequence<BrowsingContext> getChildren();
 
   readonly attribute nsIDocShell? docShell;
 
   readonly attribute unsigned long long id;
 
   readonly attribute BrowsingContext? opener;
 };
+
+[Exposed=Window, ChromeOnly]
+interface ChromeBrowsingContext : BrowsingContext {
+  sequence<WindowGlobalParent> getWindowGlobals();
+};
new file mode 100644
--- /dev/null
+++ b/dom/chrome-webidl/WindowGlobalActors.webidl
@@ -0,0 +1,33 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+interface Principal;
+interface URI;
+interface nsIDocShell;
+
+[Exposed=Window, ChromeOnly]
+interface WindowGlobalParent {
+  readonly attribute boolean isClosed;
+  readonly attribute boolean isInProcess;
+  readonly attribute ChromeBrowsingContext browsingContext;
+
+  // 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;
+};
+
+[Exposed=Window, ChromeOnly]
+interface WindowGlobalChild {
+  readonly attribute boolean isClosed;
+  readonly attribute boolean isInProcess;
+  readonly attribute BrowsingContext browsingContext;
+
+  readonly attribute WindowGlobalParent? parentActor; // in-process only
+};
--- a/dom/chrome-webidl/moz.build
+++ b/dom/chrome-webidl/moz.build
@@ -49,16 +49,17 @@ WEBIDL_FILES = [
     'MozStorageStatementParams.webidl',
     'MozStorageStatementRow.webidl',
     'PrecompiledScript.webidl',
     'PromiseDebugging.webidl',
     'StructuredCloneHolder.webidl',
     'TelemetryStopwatch.webidl',
     'WebExtensionContentScript.webidl',
     'WebExtensionPolicy.webidl',
+    'WindowGlobalActors.webidl',
     'XULFrameElement.webidl',
     'XULMenuElement.webidl',
     'XULScrollElement.webidl',
     'XULTextElement.webidl'
 ]
 
 if CONFIG['MOZ_PLACES']:
     WEBIDL_FILES += [
--- a/dom/ipc/WindowGlobalChild.cpp
+++ b/dom/ipc/WindowGlobalChild.cpp
@@ -2,16 +2,17 @@
 /* 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/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)
   : mWindowGlobal(aWindow)
   , mBrowsingContext(aBrowsingContext)
   , mIPCClosed(false)
@@ -49,17 +50,17 @@ WindowGlobalChild::Create(nsGlobalWindow
     // Note: ref is released in DeallocPWindowGlobalChild
     tabChild->SendPWindowGlobalConstructor(do_AddRef(wgc).take(), init);
   }
 
   return wgc.forget();
 }
 
 already_AddRefed<WindowGlobalParent>
-WindowGlobalChild::GetOtherSide()
+WindowGlobalChild::GetParentActor()
 {
   if (mIPCClosed) {
     return nullptr;
   }
   IProtocol* otherSide = InProcessChild::ParentActorFor(this);
   return do_AddRef(static_cast<WindowGlobalParent*>(otherSide));
 }
 
@@ -68,14 +69,30 @@ WindowGlobalChild::ActorDestroy(ActorDes
 {
   mIPCClosed = true;
 }
 
 WindowGlobalChild::~WindowGlobalChild()
 {
 }
 
-NS_IMPL_CYCLE_COLLECTION(WindowGlobalChild, mWindowGlobal, mBrowsingContext)
+JSObject*
+WindowGlobalChild::WrapObject(JSContext* aCx,
+                               JS::Handle<JSObject*> aGivenProto)
+{
+  return WindowGlobalChild_Binding::Wrap(aCx, this, aGivenProto);
+}
+
+nsISupports*
+WindowGlobalChild::GetParentObject()
+{
+  return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
+}
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WindowGlobalChild,
+                                      mWindowGlobal,
+                                      mBrowsingContext)
+
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WindowGlobalChild, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WindowGlobalChild, Release)
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/WindowGlobalChild.h
+++ b/dom/ipc/WindowGlobalChild.h
@@ -4,54 +4,60 @@
  * 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 mozilla_dom_WindowGlobalChild_h
 #define mozilla_dom_WindowGlobalChild_h
 
 #include "mozilla/RefPtr.h"
 #include "mozilla/dom/PWindowGlobalChild.h"
+#include "nsWrapperCache.h"
 
 class nsGlobalWindowInner;
 class nsDocShell;
 
 namespace mozilla {
 namespace dom  {
 
 class BrowsingContext;
 class WindowGlobalParent;
 
 /**
  * Actor for a single nsGlobalWindowInner. This actor is used to communicate
  * information to the parent process asynchronously.
  */
-class WindowGlobalChild : public PWindowGlobalChild
+class WindowGlobalChild : public nsWrapperCache
+                        , public PWindowGlobalChild
 {
 public:
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WindowGlobalChild)
-  NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(WindowGlobalChild)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WindowGlobalChild)
 
   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(); }
 
   // 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> GetOtherSide();
+  already_AddRefed<WindowGlobalParent> GetParentActor();
 
   // Create and initialize the WindowGlobalChild object.
   static already_AddRefed<WindowGlobalChild>
   Create(nsGlobalWindowInner* aWindow);
 
+  nsISupports* GetParentObject();
+  JSObject* WrapObject(JSContext* aCx,
+                       JS::Handle<JSObject*> aGivenProto) override;
+
 protected:
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
 private:
   WindowGlobalChild(nsGlobalWindowInner* aWindow, dom::BrowsingContext* aBc);
   ~WindowGlobalChild();
 
   RefPtr<nsGlobalWindowInner> mWindowGlobal;
--- a/dom/ipc/WindowGlobalParent.cpp
+++ b/dom/ipc/WindowGlobalParent.cpp
@@ -2,16 +2,17 @@
 /* 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/ChromeBrowsingContext.h"
+#include "mozilla/dom/WindowGlobalActorsBinding.h"
 
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace dom {
 
 WindowGlobalParent::WindowGlobalParent(const WindowGlobalInit& aInit,
                                        bool aInProcess)
@@ -54,17 +55,17 @@ WindowGlobalParent::Init(const WindowGlo
 
   // 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();
+    RefPtr<WindowGlobalChild> otherSide = GetChildActor();
     if (otherSide && otherSide->WindowGlobal()) {
       // Get the toplevel window from the other side.
       RefPtr<nsDocShell> docShell = nsDocShell::Cast(otherSide->WindowGlobal()->GetDocShell());
       if (docShell) {
         docShell->GetTopFrameElement(getter_AddRefs(frameElement));
       }
     }
   } else {
@@ -77,17 +78,17 @@ WindowGlobalParent::Init(const WindowGlo
   // nsFrameLoader if we are a chrome document.
   nsCOMPtr<nsIFrameLoaderOwner> flOwner = do_QueryInterface(frameElement);
   if (flOwner) {
     mFrameLoader = flOwner->GetFrameLoader();
   }
 }
 
 already_AddRefed<WindowGlobalChild>
-WindowGlobalParent::GetOtherSide()
+WindowGlobalParent::GetChildActor()
 {
   if (mIPCClosed) {
     return nullptr;
   }
   IProtocol* otherSide = InProcessParent::ChildActorFor(this);
   return do_AddRef(static_cast<WindowGlobalChild*>(otherSide));
 }
 
@@ -106,14 +107,30 @@ WindowGlobalParent::ActorDestroy(ActorDe
   mIPCClosed = true;
   mBrowsingContext->UnregisterWindowGlobal(this);
 }
 
 WindowGlobalParent::~WindowGlobalParent()
 {
 }
 
-NS_IMPL_CYCLE_COLLECTION(WindowGlobalParent, mFrameLoader, mBrowsingContext)
+JSObject*
+WindowGlobalParent::WrapObject(JSContext* aCx,
+                               JS::Handle<JSObject*> aGivenProto)
+{
+  return WindowGlobalParent_Binding::Wrap(aCx, this, aGivenProto);
+}
+
+nsISupports*
+WindowGlobalParent::GetParentObject()
+{
+  return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
+}
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(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
@@ -4,46 +4,48 @@
  * 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 mozilla_dom_WindowGlobalParent_h
 #define mozilla_dom_WindowGlobalParent_h
 
 #include "mozilla/RefPtr.h"
 #include "mozilla/dom/PWindowGlobalParent.h"
+#include "nsWrapperCache.h"
 
 class nsIPrincipal;
 class nsIURI;
 class nsFrameLoader;
 
 namespace mozilla {
 namespace dom  {
 
 class ChromeBrowsingContext;
 class WindowGlobalChild;
 
 /**
  * A handle in the parent process to a specific nsGlobalWindowInner object.
  */
-class WindowGlobalParent final : public PWindowGlobalParent
+class WindowGlobalParent final : public nsWrapperCache
+                               , public PWindowGlobalParent
 {
 public:
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WindowGlobalParent)
-  NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(WindowGlobalParent)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WindowGlobalParent)
 
   // 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
   // |nullptr| if the actor has been torn down, or is not in-process.
-  already_AddRefed<WindowGlobalChild> GetOtherSide();
+  already_AddRefed<WindowGlobalChild> GetChildActor();
 
   // 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.
   ChromeBrowsingContext* BrowsingContext() { return mBrowsingContext; }
@@ -60,16 +62,20 @@ public:
   // 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;
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
 private:
   ~WindowGlobalParent();