Bug 1383328 - Use TabGroup as event target for browser-status-filter (r=smaug)
authorBill McCloskey <billm@mozilla.com>
Wed, 19 Jul 2017 16:07:39 -0700
changeset 422132 e3e924da5d5fb94aed8093feb0e036e41d6debba
parent 422131 c5d793a1a9f2bd3a241c0018c33b21c379651b58
child 422133 3e04a16b0d583a77a392c8f20fff1683ac36b649
push id1517
push userjlorenzo@mozilla.com
push dateThu, 14 Sep 2017 16:50:54 +0000
treeherdermozilla-release@3b41fd564418 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1383328
milestone56.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 1383328 - Use TabGroup as event target for browser-status-filter (r=smaug) MozReview-Commit-ID: HOSmqr5Vpwh
browser/base/content/tab-content.js
dom/base/TabGroup.h
dom/base/nsFrameMessageManager.cpp
dom/base/nsIMessageManager.idl
dom/base/nsInProcessTabChildGlobal.cpp
dom/base/nsInProcessTabChildGlobal.h
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
toolkit/components/statusfilter/nsBrowserStatusFilter.cpp
toolkit/components/statusfilter/nsBrowserStatusFilter.h
toolkit/content/browser-child.js
tools/lint/eslint/eslint-plugin-mozilla/lib/environments/frame-script.js
uriloader/base/nsDocLoader.cpp
uriloader/base/nsIWebProgress.idl
xpcom/threads/nsIThreadManager.idl
xpcom/threads/nsThreadManager.cpp
--- a/browser/base/content/tab-content.js
+++ b/browser/base/content/tab-content.js
@@ -906,16 +906,17 @@ var RefreshBlocker = {
       }
     }
   },
 
   enable() {
     this._filter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
                      .createInstance(Ci.nsIWebProgress);
     this._filter.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_ALL);
+    this._filter.target = tabEventTarget;
 
     let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                               .getInterface(Ci.nsIWebProgress);
     webProgress.addProgressListener(this._filter, Ci.nsIWebProgress.NOTIFY_ALL);
 
     addMessageListener("RefreshBlocker:Refresh", this);
   },
 
--- a/dom/base/TabGroup.h
+++ b/dom/base/TabGroup.h
@@ -2,16 +2,17 @@
 /* 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 TabGroup_h
 #define TabGroup_h
 
+#include "nsHashKeys.h"
 #include "nsISupportsImpl.h"
 #include "nsIPrincipal.h"
 #include "nsTHashtable.h"
 #include "nsString.h"
 
 #include "mozilla/Atomics.h"
 #include "mozilla/SchedulerGroup.h"
 #include "mozilla/RefPtr.h"
@@ -38,16 +39,17 @@ class TabChild;
 // A TabGroup is a set of browsing contexts which are all "related". Within a
 // TabGroup, browsing contexts are broken into "similar-origin" DocGroups. In
 // more detail, a DocGroup is actually a collection of documents, and a
 // TabGroup is a collection of DocGroups. A TabGroup typically will contain
 // (through its DocGroups) the documents from one or more tabs related by
 // window.opener. A DocGroup is a member of exactly one TabGroup.
 
 class DocGroup;
+class TabChild;
 
 class TabGroup final : public SchedulerGroup
 {
 private:
   class HashEntry : public nsCStringHashKey
   {
   public:
     // NOTE: Weak reference. The DocGroup destructor removes itself from its
--- a/dom/base/nsFrameMessageManager.cpp
+++ b/dom/base/nsFrameMessageManager.cpp
@@ -845,16 +845,23 @@ nsFrameMessageManager::GetContent(mozIDO
 NS_IMETHODIMP
 nsFrameMessageManager::GetDocShell(nsIDocShell** aDocShell)
 {
   *aDocShell = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsFrameMessageManager::GetTabEventTarget(nsIEventTarget** aTarget)
+{
+  *aTarget = nullptr;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsFrameMessageManager::Btoa(const nsAString& aBinaryData,
                             nsAString& aAsciiBase64String)
 {
   return nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
 }
 
 NS_IMETHODIMP
 nsFrameMessageManager::Atob(const nsAString& aAsciiString,
--- a/dom/base/nsIMessageManager.idl
+++ b/dom/base/nsIMessageManager.idl
@@ -3,16 +3,17 @@
  * 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 "nsISupports.idl"
 
 interface mozIDOMWindowProxy;
 interface nsIDocShell;
 interface nsIContent;
+interface nsIEventTarget;
 interface nsIFrameLoader;
 interface nsIPrincipal;
 
 /**
  * Message managers provide a way for chrome-privileged JS code to
  * communicate with each other, even across process boundaries.
  *
  * Message managers are separated into "parent side" and "child side".
@@ -393,16 +394,22 @@ interface nsIContentFrameMessageManager 
    * The current top level window in the frame or null.
    */
   readonly attribute mozIDOMWindowProxy content;
 
   /**
    * The top level docshell or null.
    */
   readonly attribute nsIDocShell docShell;
+
+  /**
+   * Returns the SchedulerEventTarget corresponding to the TabGroup
+   * for this frame.
+   */
+  readonly attribute nsIEventTarget tabEventTarget;
 };
 
 [uuid(b39a3324-b574-4f85-8cdb-274d04f807ef)]
 interface nsIInProcessContentFrameMessageManager : nsIContentFrameMessageManager
 {
   [notxpcom] nsIContent getOwnerContent();
   [notxpcom] void cacheFrameLoader(in nsIFrameLoader aFrameLoader);
 };
--- a/dom/base/nsInProcessTabChildGlobal.cpp
+++ b/dom/base/nsInProcessTabChildGlobal.cpp
@@ -194,16 +194,24 @@ nsInProcessTabChildGlobal::GetContent(mo
 
 NS_IMETHODIMP
 nsInProcessTabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
 {
   NS_IF_ADDREF(*aDocShell = mDocShell);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsInProcessTabChildGlobal::GetTabEventTarget(nsIEventTarget** aTarget)
+{
+  nsCOMPtr<nsIEventTarget> target = GetMainThreadEventTarget();
+  target.forget(aTarget);
+  return NS_OK;
+}
+
 void
 nsInProcessTabChildGlobal::FireUnloadEvent()
 {
   // We're called from nsDocument::MaybeInitializeFinalizeFrameLoaders, so it
   // should be safe to run script.
   MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
 
   // Don't let the unload event propagate to chrome event handlers.
--- a/dom/base/nsInProcessTabChildGlobal.h
+++ b/dom/base/nsInProcessTabChildGlobal.h
@@ -72,16 +72,17 @@ public:
   {
     return mMessageManager
       ? mMessageManager->SendRpcMessage(aMessageName, aObject, aRemote,
                                         aPrincipal, aCx, aArgc, aRetval)
       : NS_ERROR_NULL_POINTER;
   }
   NS_IMETHOD GetContent(mozIDOMWindowProxy** aContent) override;
   NS_IMETHOD GetDocShell(nsIDocShell** aDocShell) override;
+  NS_IMETHOD GetTabEventTarget(nsIEventTarget** aTarget) override;
 
   NS_DECL_NSIINPROCESSCONTENTFRAMEMESSAGEMANAGER
 
   /**
    * MessageManagerCallback methods that we override.
    */
   virtual bool DoSendBlockingMessage(JSContext* aCx,
                                       const nsAString& aMessage,
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -3515,16 +3515,24 @@ TabChildGlobal::GetDocShell(nsIDocShell*
   *aDocShell = nullptr;
   if (!mTabChild)
     return NS_ERROR_NULL_POINTER;
   nsCOMPtr<nsIDocShell> docShell = do_GetInterface(mTabChild->WebNavigation());
   docShell.swap(*aDocShell);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+TabChildGlobal::GetTabEventTarget(nsIEventTarget** aTarget)
+{
+  nsCOMPtr<nsIEventTarget> target = EventTargetFor(TaskCategory::Other);
+  target.forget(aTarget);
+  return NS_OK;
+}
+
 nsIPrincipal*
 TabChildGlobal::GetPrincipal()
 {
   if (!mTabChild)
     return nullptr;
   return mTabChild->GetPrincipal();
 }
 
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -109,16 +109,17 @@ public:
   {
     return mMessageManager
       ? mMessageManager->SendRpcMessage(aMessageName, aObject, aRemote,
                                         aPrincipal, aCx, aArgc, aRetval)
       : NS_ERROR_NULL_POINTER;
   }
   NS_IMETHOD GetContent(mozIDOMWindowProxy** aContent) override;
   NS_IMETHOD GetDocShell(nsIDocShell** aDocShell) override;
+  NS_IMETHOD GetTabEventTarget(nsIEventTarget** aTarget) override;
 
   nsresult AddEventListener(const nsAString& aType,
                             nsIDOMEventListener* aListener,
                             bool aUseCapture)
   {
     // By default add listeners only for trusted events!
     return DOMEventTargetHelper::AddEventListener(aType, aListener,
                                                   aUseCapture, false, 2);
--- a/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp
+++ b/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp
@@ -4,25 +4,27 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsBrowserStatusFilter.h"
 #include "mozilla/SystemGroup.h"
 #include "nsIChannel.h"
 #include "nsITimer.h"
 #include "nsIServiceManager.h"
 #include "nsString.h"
+#include "nsThreadUtils.h"
 
 using namespace mozilla;
 
 //-----------------------------------------------------------------------------
 // nsBrowserStatusFilter <public>
 //-----------------------------------------------------------------------------
 
 nsBrowserStatusFilter::nsBrowserStatusFilter()
-    : mCurProgress(0)
+    : mTarget(GetMainThreadEventTarget())
+    , mCurProgress(0)
     , mMaxProgress(0)
     , mStatusIsDirty(true)
     , mCurrentPercentage(0)
     , mTotalRequests(0)
     , mFinishedRequests(0)
     , mUseRealProgressFlag(false)
     , mDelayedStatus(false)
     , mDelayedProgress(false)
@@ -107,16 +109,31 @@ nsBrowserStatusFilter::GetIsLoadingDocum
 NS_IMETHODIMP
 nsBrowserStatusFilter::GetLoadType(uint32_t *aLoadType)
 {
     *aLoadType = 0;
     NS_NOTREACHED("nsBrowserStatusFilter::GetLoadType");
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+NS_IMETHODIMP
+nsBrowserStatusFilter::GetTarget(nsIEventTarget** aTarget)
+{
+    nsCOMPtr<nsIEventTarget> target = mTarget;
+    target.forget(aTarget);
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBrowserStatusFilter::SetTarget(nsIEventTarget* aTarget)
+{
+    mTarget = aTarget;
+    return NS_OK;
+}
+
 //-----------------------------------------------------------------------------
 // nsBrowserStatusFilter::nsIWebProgressListener
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsBrowserStatusFilter::OnStateChange(nsIWebProgress *aWebProgress,
                                      nsIRequest *aRequest,
                                      uint32_t aStateFlags,
@@ -357,19 +374,17 @@ nsresult
 nsBrowserStatusFilter::StartDelayTimer()
 {
     NS_ASSERTION(!DelayInEffect(), "delay should not be in effect");
 
     mTimer = do_CreateInstance("@mozilla.org/timer;1");
     if (!mTimer)
         return NS_ERROR_FAILURE;
 
-    // Use the system group. The browser status filter is always used by chrome
-    // code.
-    mTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::Other));
+    mTimer->SetTarget(mTarget);
     return mTimer->InitWithNamedFuncCallback(
         TimeoutHandler, this, 160, nsITimer::TYPE_ONE_SHOT,
         "nsBrowserStatusFilter::TimeoutHandler");
 }
 
 void
 nsBrowserStatusFilter::ProcessTimeout()
 {
--- a/toolkit/components/statusfilter/nsBrowserStatusFilter.h
+++ b/toolkit/components/statusfilter/nsBrowserStatusFilter.h
@@ -41,16 +41,17 @@ private:
     void MaybeSendStatus();
     void ResetMembers();
     bool DelayInEffect() { return mDelayedStatus || mDelayedProgress; }
 
     static void TimeoutHandler(nsITimer *aTimer, void *aClosure);
 
 private:
     nsCOMPtr<nsIWebProgressListener> mListener;
+    nsCOMPtr<nsIEventTarget>         mTarget;
     nsCOMPtr<nsITimer>               mTimer;
 
     // delayed values
     nsString                         mStatusMsg;
     int64_t                          mCurProgress;
     int64_t                          mMaxProgress;
 
     nsString                         mCurrentStatusMsg;
--- a/toolkit/content/browser-child.js
+++ b/toolkit/content/browser-child.js
@@ -28,16 +28,17 @@ if (AppConstants.MOZ_CRASHREPORTER) {
                                      "nsICrashReporter");
 }
 
 var WebProgressListener = {
   init() {
     this._filter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
                      .createInstance(Ci.nsIWebProgress);
     this._filter.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_ALL);
+    this._filter.target = tabEventTarget;
 
     let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                               .getInterface(Ci.nsIWebProgress);
     webProgress.addProgressListener(this._filter, Ci.nsIWebProgress.NOTIFY_ALL);
   },
 
   uninit() {
     let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
--- a/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/frame-script.js
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/frame-script.js
@@ -17,11 +17,12 @@ module.exports = {
     content: false,
     docShell: false,
     privateNoteIntentionalCrash: false,
     processMessageManager: false,
     removeMessageListener: false,
     removeWeakMessageListener: false,
     sendAsyncMessage: false,
     sendSyncMessage: false,
-    sendRpcMessage: false
+    sendRpcMessage: false,
+    tabEventTarget: false
   }
 };
--- a/uriloader/base/nsDocLoader.cpp
+++ b/uriloader/base/nsDocLoader.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; 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/. */
 
 #include "nspr.h"
+#include "mozilla/dom/TabGroup.h"
 #include "mozilla/Logging.h"
 #include "mozilla/IntegerPrintfMacros.h"
 
 #include "nsDocLoader.h"
 #include "nsCURILoader.h"
 #include "nsNetUtil.h"
 #include "nsIHttpChannel.h"
 #include "nsIWebProgressListener2.h"
@@ -975,16 +976,37 @@ nsDocLoader::GetIsLoadingDocument(bool *
 NS_IMETHODIMP
 nsDocLoader::GetLoadType(uint32_t *aLoadType)
 {
   *aLoadType = 0;
 
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+NS_IMETHODIMP
+nsDocLoader::GetTarget(nsIEventTarget** aTarget)
+{
+  nsCOMPtr<mozIDOMWindowProxy> window;
+  nsresult rv = GetDOMWindow(getter_AddRefs(window));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsPIDOMWindowOuter> piwindow = nsPIDOMWindowOuter::From(window);
+  NS_ENSURE_STATE(piwindow);
+
+  nsCOMPtr<nsIEventTarget> target = piwindow->TabGroup()->EventTargetFor(mozilla::TaskCategory::Other);
+  target.forget(aTarget);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocLoader::SetTarget(nsIEventTarget* aTarget)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
 int64_t nsDocLoader::GetMaxTotalProgress()
 {
   int64_t newMaxTotal = 0;
 
   uint32_t count = mChildList.Length();
   for (uint32_t i=0; i < count; i++)
   {
     int64_t individualProgress = 0;
--- a/uriloader/base/nsIWebProgress.idl
+++ b/uriloader/base/nsIWebProgress.idl
@@ -2,16 +2,17 @@
  *
  * 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 "nsISupports.idl"
 
 interface mozIDOMWindowProxy;
+interface nsIEventTarget;
 interface nsIWebProgressListener;
 
 /**
  * The nsIWebProgress interface is used to add or remove nsIWebProgressListener
  * instances to observe the loading of asynchronous requests (usually in the
  * context of a DOM window).
  *
  * nsIWebProgress instances may be arranged in a parent-child configuration,
@@ -146,9 +147,16 @@ interface nsIWebProgress : nsISupports
    */
   readonly attribute boolean isLoadingDocument;
 
   /**
    * Contains a load type as specified by the load* constants in
    * nsIDocShellLoadInfo.idl.
    */
   readonly attribute unsigned long loadType;
+
+  /**
+   * Main thread event target to which progress updates should be
+   * dispatched. This typically will be a SchedulerEventTarget
+   * corresponding to the tab requesting updates.
+   */
+  attribute nsIEventTarget target;
 };
--- a/xpcom/threads/nsIThreadManager.idl
+++ b/xpcom/threads/nsIThreadManager.idl
@@ -3,16 +3,17 @@
 /* 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 "nsISupports.idl"
 
 [ptr] native PRThread(PRThread);
 
+interface nsIEventTarget;
 interface nsIRunnable;
 interface nsIThread;
 
 [scriptable, function, uuid(039a227d-0cb7-44a5-a8f9-dbb7071979f2)]
 interface nsINestedEventLoopCondition : nsISupports
 {
   /**
    * Returns true if the current nested event loop should stop spinning.
@@ -121,9 +122,14 @@ interface nsIThreadManager : nsISupports
 
   /**
    * Spin the current thread's event loop until there are no more pending
    * events.  This could be done with spinEventLoopUntil, but that would
    * require access to the current thread from JavaScript, which we are
    * moving away from.
    */
   void spinEventLoopUntilEmpty();
+
+  /**
+   * Return the SchedulerEventTarget for the SystemGroup.
+   */
+  readonly attribute nsIEventTarget systemGroupEventTarget;
 };
--- a/xpcom/threads/nsThreadManager.cpp
+++ b/xpcom/threads/nsThreadManager.cpp
@@ -7,16 +7,17 @@
 #include "nsThreadManager.h"
 #include "nsThread.h"
 #include "nsThreadUtils.h"
 #include "nsIClassInfoImpl.h"
 #include "nsTArray.h"
 #include "nsAutoPtr.h"
 #include "mozilla/AbstractThread.h"
 #include "mozilla/InputEventStatistics.h"
+#include "mozilla/SystemGroup.h"
 #include "mozilla/ThreadLocal.h"
 #include "mozilla/Preferences.h"
 #ifdef MOZ_CANARY
 #include <fcntl.h>
 #include <unistd.h>
 #endif
 
 #include "MainThreadIdlePeriod.h"
@@ -373,16 +374,24 @@ nsThreadManager::SpinEventLoopUntilEmpty
 
   while (NS_HasPendingEvents(thread)) {
     (void)NS_ProcessNextEvent(thread, false);
   }
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsThreadManager::GetSystemGroupEventTarget(nsIEventTarget** aTarget)
+{
+  nsCOMPtr<nsIEventTarget> target = SystemGroup::EventTargetFor(TaskCategory::Other);
+  target.forget(aTarget);
+  return NS_OK;
+}
+
 uint32_t
 nsThreadManager::GetHighestNumberOfThreads()
 {
   OffTheBooksMutexAutoLock lock(mLock);
   return mHighestNumberOfThreads;
 }
 
 NS_IMETHODIMP