Bug 1481238 - Create WebIDL interface for BrowsingContext. r=peterv
authorAndreas Farre <farre@mozilla.com>
Wed, 29 Aug 2018 05:00:00 +0300
changeset 433892 b5c403ab80f96de0834214cab00996b617df18b1
parent 433891 612ca23ddb81bfa32c2e53484f16e0076fe85841
child 433893 c5b0a8dc8d127d4bee728d1be6907c240b78ed01
push id34523
push usercsabou@mozilla.com
push dateWed, 29 Aug 2018 17:34:43 +0000
treeherdermozilla-central@c2e3be6a1dd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs1481238
milestone63.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 1481238 - Create WebIDL interface for BrowsingContext. r=peterv Expose Chrome only WebIDL to interface with BrowsingContext from script. The API consists of parent, firstChild and nextSibling attributes for BrowsingContext, and the browsingContext attribute for Window.
docshell/base/BrowsingContext.cpp
docshell/base/BrowsingContext.h
docshell/base/nsDocShell.cpp
docshell/base/nsIDocShell.idl
dom/base/ChromeUtils.cpp
dom/base/ChromeUtils.h
dom/chrome-webidl/BrowsingContext.webidl
dom/chrome-webidl/ChromeUtils.webidl
dom/chrome-webidl/moz.build
--- a/docshell/base/BrowsingContext.cpp
+++ b/docshell/base/BrowsingContext.cpp
@@ -1,16 +1,17 @@
 /* -*- 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/BrowsingContextBinding.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/Logging.h"
 #include "mozilla/StaticPtr.h"
 
 #include "nsDataHashtable.h"
 #include "nsRefPtrHashtable.h"
@@ -126,18 +127,18 @@ BrowsingContext::Attach(BrowsingContext*
     return;
   }
 
   bool wasCached = sCachedBrowsingContexts->Remove(Id());
 
   MOZ_LOG(GetLog(),
           LogLevel::Debug,
           ("%s: %s 0x%08" PRIx64 " to 0x%08" PRIx64,
+           XRE_IsParentProcess() ? "Parent" : "Child",
            wasCached ? "Re-connecting" : "Connecting",
-           XRE_IsParentProcess() ? "Parent" : "Child",
            Id(),
            aParent ? aParent->Id() : 0));
 
   auto* children = aParent ? &aParent->mChildren : sRootBrowsingContexts.get();
   children->insertBack(this);
   mParent = aParent;
 
   if (!XRE_IsContentProcess()) {
@@ -225,25 +226,54 @@ BrowsingContext::IsCached()
 
 uint64_t
 BrowsingContext::OwnerProcessId() const
 {
   MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess());
   return mProcessId.value();
 }
 
+void
+BrowsingContext::GetChildren(nsTArray<RefPtr<BrowsingContext>>& aChildren)
+{
+  for (BrowsingContext* context : mChildren) {
+    aChildren.AppendElement(context);
+  }
+}
+
+/* static */ void
+BrowsingContext::GetRootBrowsingContexts(nsTArray<RefPtr<BrowsingContext>>& aBrowsingContexts)
+{
+  for (BrowsingContext* context : *sRootBrowsingContexts) {
+    aBrowsingContexts.AppendElement(context);
+  }
+}
+
 BrowsingContext::~BrowsingContext()
 {
   MOZ_DIAGNOSTIC_ASSERT(!isInList());
 
   if (sBrowsingContexts) {
     sBrowsingContexts->Remove(mBrowsingContextId);
   }
 }
 
+nsISupports*
+BrowsingContext::GetParentObject() const
+{
+  return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
+}
+
+JSObject*
+BrowsingContext::WrapObject(JSContext* aCx,
+                            JS::Handle<JSObject*> aGivenProto)
+{
+  return BrowsingContext_Binding::Wrap(aCx, this, aGivenProto);
+}
+
 static void
 ImplCycleCollectionUnlink(BrowsingContext::Children& aField)
 {
   aField.clear();
 }
 
 static void
 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
@@ -252,14 +282,14 @@ ImplCycleCollectionTraverse(nsCycleColle
                             uint32_t aFlags = 0)
 {
   for (BrowsingContext* aContext : aField) {
     aCallback.NoteNativeChild(aContext,
                               NS_CYCLE_COLLECTION_PARTICIPANT(BrowsingContext));
   }
 }
 
-NS_IMPL_CYCLE_COLLECTION(BrowsingContext, mDocShell, mChildren)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(BrowsingContext, mDocShell, mChildren)
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(BrowsingContext, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(BrowsingContext, Release)
 
 } // namespace dom
 } // namespace mozilla
--- a/docshell/base/BrowsingContext.h
+++ b/docshell/base/BrowsingContext.h
@@ -9,16 +9,18 @@
 
 #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"
+#include "nsTArray.h"
+#include "nsWrapperCache.h"
 
 class nsIDocShell;
 
 namespace mozilla {
 
 class LogModule;
 
 namespace dom {
@@ -31,17 +33,18 @@ namespace dom {
 // The tree of BrowsingContexts in created in step with its
 // corresponding nsDocShell, and when nsDocShells are connected
 // through a parent/child relationship, so are BrowsingContexts. The
 // major difference is that BrowsingContexts are replicated (synced)
 // to the parent process, making it possible to traverse the
 // BrowsingContext tree for a tab, in both the parent and the child
 // process.
 class BrowsingContext
-  : public SupportsWeakPtr<BrowsingContext>
+  : public nsWrapperCache
+  , public SupportsWeakPtr<BrowsingContext>
   , public LinkedListElement<RefPtr<BrowsingContext>>
 {
 public:
   static void Init();
   static LogModule* GetLog();
   static void CleanupContexts(uint64_t aProcessId);
 
   static already_AddRefed<BrowsingContext> Get(uint64_t aId);
@@ -76,26 +79,38 @@ public:
   void SetName(const nsAString& aName) { mName = aName; }
   void GetName(nsAString& aName) { aName = mName; }
   bool NameEquals(const nsAString& aName) { return mName.Equals(aName); }
 
   uint64_t Id() const { return mBrowsingContextId; }
   uint64_t OwnerProcessId() const;
   bool IsOwnedByProcess() const { return mProcessId.isSome(); }
 
-  BrowsingContext* Parent() const { return mParent; }
+  already_AddRefed<BrowsingContext> GetParent()
+  {
+    return do_AddRef(mParent.get());
+  }
+
+  void GetChildren(nsTArray<RefPtr<BrowsingContext>>& aChildren);
+
+  static void GetRootBrowsingContexts(
+    nsTArray<RefPtr<BrowsingContext>>& aBrowsingContexts);
+
+  nsISupports* GetParentObject() const;
+  virtual 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_NATIVE_CLASS(BrowsingContext)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(BrowsingContext)
 
   using Children = AutoCleanLinkedList<RefPtr<BrowsingContext>>;
 
 private:
-  ~BrowsingContext();
+  virtual ~BrowsingContext();
 
   const uint64_t mBrowsingContextId;
 
   // Indicates which process owns the docshell. Only valid in the
   // parent process.
   Maybe<uint64_t> mProcessId;
 
   WeakPtr<BrowsingContext> mParent;
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -14330,16 +14330,23 @@ nsDocShell::IsForceReloading()
 
 already_AddRefed<BrowsingContext>
 nsDocShell::GetBrowsingContext() const
 {
   RefPtr<BrowsingContext> browsingContext = mBrowsingContext;
   return browsingContext.forget();
 }
 
+NS_IMETHODIMP
+nsDocShell::GetBrowsingContext(BrowsingContext** aBrowsingContext)
+{
+  *aBrowsingContext = do_AddRef(mBrowsingContext).take();
+  return NS_OK;
+}
+
 void
 nsIDocShell::AttachBrowsingContext(nsIDocShell* aParentDocShell)
 {
   RefPtr<BrowsingContext> childContext =
     nsDocShell::Cast(this)->GetBrowsingContext();
   RefPtr<BrowsingContext> parentContext;
   if (aParentDocShell) {
     parentContext =
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -60,16 +60,17 @@ interface nsIScrollObserver;
 interface nsITabParent;
 interface nsITabChild;
 interface nsICommandManager;
 interface nsICommandParams;
 interface nsILoadURIDelegate;
 native TabChildRef(already_AddRefed<nsITabChild>);
 native nsDocShellLoadInfoPtr(nsDocShellLoadInfo*);
 
+webidl BrowsingContext;
 webidl ContentFrameMessageManager;
 webidl EventTarget;
 
 [scriptable, builtinclass, uuid(049234fe-da10-478b-bc5d-bc6f9a1ba63d)]
 interface nsIDocShell : nsIDocShellTreeItem
 {
   /**
    * Loads a given URI.  This will give priority to loading the requested URI
@@ -1186,16 +1187,21 @@ interface nsIDocShell : nsIDocShellTreeI
   mozilla::HTMLEditor* GetHTMLEditor();
   nsresult SetHTMLEditor(mozilla::HTMLEditor* aHTMLEditor);
 
   void AttachBrowsingContext(nsIDocShell* aParentDocShell);
   void DetachBrowsingContext();
 %}
 
   /**
+   * BrowsingContext associated with the DocShell.
+   */
+  readonly attribute BrowsingContext browsingContext;
+
+  /**
    * Allowed CSS display modes. This needs to be kept in
    * sync with similar values in nsStyleConsts.h
    */
   const unsigned long DISPLAY_MODE_BROWSER = 0;
   const unsigned long DISPLAY_MODE_MINIMAL_UI = 1;
   const unsigned long DISPLAY_MODE_STANDALONE = 2;
   const unsigned long DISPLAY_MODE_FULLSCREEN = 3;
 
--- a/dom/base/ChromeUtils.cpp
+++ b/dom/base/ChromeUtils.cpp
@@ -12,16 +12,17 @@
 #include "WrapperFactory.h"
 
 #include "mozilla/Base64.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/CycleCollectedJSRuntime.h"
 #include "mozilla/PerformanceMetricsCollector.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/TimeStamp.h"
+#include "mozilla/dom/BrowsingContext.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/IdleDeadline.h"
 #include "mozilla/dom/UnionTypes.h"
 #include "mozilla/dom/WindowBinding.h" // For IdleRequestCallback/Options
 #include "IOActivityMonitor.h"
 #include "nsThreadUtils.h"
 #include "mozJSComponentLoader.h"
 #include "GeckoProfiler.h"
@@ -776,10 +777,17 @@ ChromeUtils::RequestIOActivity(GlobalObj
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
   MOZ_ASSERT(domPromise);
   mozilla::net::IOActivityMonitor::RequestActivities(domPromise);
   return domPromise.forget();
 }
 
+/* static */ void
+ChromeUtils::GetRootBrowsingContexts(GlobalObject& aGlobal,
+                                     nsTArray<RefPtr<BrowsingContext>>& aBrowsingContexts)
+{
+  BrowsingContext::GetRootBrowsingContexts(aBrowsingContexts);
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/base/ChromeUtils.h
+++ b/dom/base/ChromeUtils.h
@@ -16,16 +16,17 @@ namespace mozilla {
 
 namespace devtools {
 class HeapSnapshot;
 } // namespace devtools
 
 namespace dom {
 
 class ArrayBufferViewOrArrayBuffer;
+class BrowsingContext;
 class IdleRequestCallback;
 struct IdleRequestOptions;
 class MozQueryInterface;
 class PrecompiledScript;
 class Promise;
 
 class ChromeUtils
 {
@@ -182,14 +183,18 @@ public:
 
   static void
   CreateError(const GlobalObject& global, const nsAString& message,
               JS::Handle<JSObject*> stack,
               JS::MutableHandle<JSObject*> aRetVal, ErrorResult& aRv);
 
   static already_AddRefed<Promise>
   RequestIOActivity(GlobalObject& aGlobal, ErrorResult& aRv);
+
+  static void
+  GetRootBrowsingContexts(GlobalObject& aGlobal,
+                          nsTArray<RefPtr<BrowsingContext>>& aBrowsingContexts);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_ChromeUtils__
new file mode 100644
--- /dev/null
+++ b/dom/chrome-webidl/BrowsingContext.webidl
@@ -0,0 +1,13 @@
+/* -*- 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/. */
+
+[Exposed=(Window, System), ChromeOnly]
+interface BrowsingContext {
+  readonly attribute BrowsingContext? parent;
+
+  sequence<BrowsingContext> getChildren();
+
+  readonly attribute unsigned long long id;
+};
--- a/dom/chrome-webidl/ChromeUtils.webidl
+++ b/dom/chrome-webidl/ChromeUtils.webidl
@@ -350,16 +350,19 @@ partial namespace ChromeUtils {
   [Throws, Func="DOMPrefs::SchedulerTimingEnabled"]
   Promise<sequence<PerformanceInfoDictionary>> requestPerformanceMetrics();
 
   /**
   * Returns a Promise containing a sequence of I/O activities
   */
   [Throws]
   Promise<sequence<IOActivityDataDictionary>> requestIOActivity();
+
+  [ChromeOnly]
+  sequence<BrowsingContext> getRootBrowsingContexts();
 };
 
 /**
  * Dictionaries duplicating IPDL types in dom/ipc/DOMTypes.ipdlh
  * Used by requestPerformanceMetrics
  */
 dictionary CategoryDispatchDictionary
 {
--- a/dom/chrome-webidl/moz.build
+++ b/dom/chrome-webidl/moz.build
@@ -25,16 +25,17 @@ with Files("MatchPattern.webidl"):
 with Files("WebExtension*.webidl"):
     BUG_COMPONENT = ("WebExtensions", "General")
 
 PREPROCESSED_WEBIDL_FILES = [
     'ChromeUtils.webidl',
 ]
 
 WEBIDL_FILES = [
+    'BrowsingContext.webidl',
     'ChannelWrapper.webidl',
     'DominatorTree.webidl',
     'HeapSnapshot.webidl',
     'InspectorUtils.webidl',
     'IteratorResult.webidl',
     'MatchGlob.webidl',
     'MatchPattern.webidl',
     'MessageManager.webidl',