Bug 1357880 - Add a telemetry probe for mousemove event listeners r?smaug draft
authorRyan Hunt <rhunt@eqrion.net>
Wed, 26 Apr 2017 18:56:51 -0400
changeset 570317 2079cb87101972dbce8b4d4ea2c70625fa599c34
parent 570312 e8ca5396e4e6519d713eb20f3d5b0224dd3f3678
child 626464 be29605de0d5330018ef5fa4b623ef08214eaa38
push id56458
push userbmo:rhunt@eqrion.net
push dateFri, 28 Apr 2017 18:46:56 +0000
reviewerssmaug
bugs1357880
milestone55.0a1
Bug 1357880 - Add a telemetry probe for mousemove event listeners r?smaug This commit adds a telemetry probe to determine the percentage of pages that ever have a 'mousemove' event listener added to the DOM. This is for determining how often APZ key scrolling could handle interleaved mousemove events. A flag is added to nsPIDOMWindow to track whether a qualifying event listener was ever added to the DOM for this window, and is updated by EventListenerManager. There are several other similar flags to this. The probe is reported in nsGlobalWindow::FreeInnerObjects() so that it can be compared exactly with the non-passive keyboard listener APZ probe. MozReview-Commit-ID: DqqCfrdRCGp
dom/base/nsGlobalWindow.cpp
dom/base/nsNodeUtils.cpp
dom/base/nsPIDOMWindow.h
dom/events/EventListenerManager.cpp
dom/events/EventListenerManager.h
toolkit/components/telemetry/Histograms.json
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -973,16 +973,17 @@ NextWindowID();
 
 template<class T>
 nsPIDOMWindow<T>::nsPIDOMWindow(nsPIDOMWindowOuter *aOuterWindow)
 : mFrameElement(nullptr), mDocShell(nullptr), mModalStateDepth(0),
   mMutationBits(0), mIsDocumentLoaded(false),
   mIsHandlingResizeEvent(false), mIsInnerWindow(aOuterWindow != nullptr),
   mMayHavePaintEventListener(false), mMayHaveTouchEventListener(false),
   mMayHaveMouseEnterLeaveEventListener(false),
+  mMayHaveMouseMoveEventListener(false),
   mMayHavePointerEnterLeaveEventListener(false),
   mInnerObjectsFreed(false),
   mIsModalContentWindow(false),
   mIsActive(false), mIsBackground(false),
   mMediaSuspend(Preferences::GetBool("media.block-autoplay-until-in-foreground", true) ?
     nsISuspendedTypes::SUSPENDED_BLOCK : nsISuspendedTypes::NONE_SUSPENDED),
   mAudioMuted(false), mAudioVolume(1.0), mAudioCaptured(false),
   mDesktopModeViewport(false), mIsRootOuterWindow(false), mInnerWindow(nullptr),
@@ -2034,21 +2035,24 @@ nsGlobalWindow::FreeInnerObjects()
 {
   NS_ASSERTION(IsInnerWindow(), "Don't free inner objects on an outer window");
 
   if (mDoc && !nsContentUtils::IsSystemPrincipal(mDoc->NodePrincipal())) {
     EventTarget* win = this;
     EventTarget* html = mDoc->GetHtmlElement();
     EventTarget* body = mDoc->GetBodyElement();
 
+    bool mouseAware = AsInner()->HasMouseMoveEventListeners();
     bool keyboardAware = win->MayHaveAPZAwareKeyEventListener() ||
                          mDoc->MayHaveAPZAwareKeyEventListener() ||
                          (html && html->MayHaveAPZAwareKeyEventListener()) ||
                          (body && body->MayHaveAPZAwareKeyEventListener());
 
+    Telemetry::Accumulate(Telemetry::APZ_AWARE_MOUSEMOVE_LISTENERS,
+                          mouseAware ? 1 : 0);
     Telemetry::Accumulate(Telemetry::APZ_AWARE_KEY_LISTENERS,
                           keyboardAware ? 1 : 0);
   }
 
   // Make sure that this is called before we null out the document and
   // other members that the window destroyed observers could
   // re-create.
   NotifyDOMWindowDestroyed(this);
--- a/dom/base/nsNodeUtils.cpp
+++ b/dom/base/nsNodeUtils.cpp
@@ -534,16 +534,19 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNod
         if (elm) {
           window->SetMutationListeners(elm->MutationListenerBits());
           if (elm->MayHavePaintEventListener()) {
             window->SetHasPaintEventListeners();
           }
           if (elm->MayHaveTouchEventListener()) {
             window->SetHasTouchEventListeners();
           }
+          if (elm->MayHaveMouseMoveEventListener()) {
+            window->SetHasMouseMoveEventListeners();
+          }
           if (elm->MayHaveMouseEnterLeaveEventListener()) {
             window->SetHasMouseEnterLeaveEventListeners();
           }
           if (elm->MayHavePointerEnterLeaveEventListener()) {
             window->SetHasPointerEnterLeaveEventListeners();
           }
         }
       }
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -664,16 +664,17 @@ protected:
   uint32_t               mMutationBits;
 
   bool                   mIsDocumentLoaded;
   bool                   mIsHandlingResizeEvent;
   bool                   mIsInnerWindow;
   bool                   mMayHavePaintEventListener;
   bool                   mMayHaveTouchEventListener;
   bool                   mMayHaveMouseEnterLeaveEventListener;
+  bool                   mMayHaveMouseMoveEventListener;
   bool                   mMayHavePointerEnterLeaveEventListener;
 
   // Used to detect whether we have called FreeInnerObjects() (e.g. to ensure
   // that a call to ResumeTimeouts() after FreeInnerObjects() does nothing).
   // This member is only used by inner windows.
   bool                   mInnerObjectsFreed;
 
 
@@ -811,16 +812,34 @@ public:
       return;
     }
 
     mMutationBits |= aType;
   }
 
   /**
    * Call this to check whether some node (this window, its document,
+   * or content in that document) has or had a mousemove event listener.
+   */
+  bool HasMouseMoveEventListeners()
+  {
+    return mMayHaveMouseMoveEventListener;
+  }
+
+  /**
+   * Call this to indicate that some node (this window, its document,
+   * or content in that document) has or had a mousemove event listener.
+   */
+  void SetHasMouseMoveEventListeners()
+  {
+    mMayHaveMouseMoveEventListener = true;
+  }
+
+  /**
+   * Call this to check whether some node (this window, its document,
    * or content in that document) has a mouseenter/leave event listener.
    */
   bool HasMouseEnterLeaveEventListeners()
   {
     return mMayHaveMouseEnterLeaveEventListener;
   }
 
   /**
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -122,16 +122,17 @@ IsWebkitPrefixSupportEnabled()
 
 EventListenerManagerBase::EventListenerManagerBase()
   : mNoListenerForEvent(eVoidEvent)
   , mMayHavePaintEventListener(false)
   , mMayHaveMutationListeners(false)
   , mMayHaveCapturingListeners(false)
   , mMayHaveSystemGroupListeners(false)
   , mMayHaveTouchEventListener(false)
+  , mMayHaveMouseMoveEventListener(false)
   , mMayHaveMouseEnterLeaveEventListener(false)
   , mMayHavePointerEnterLeaveEventListener(false)
   , mMayHaveAPZAwareKeyEventListener(false)
   , mMayHaveKeyEventListener(false)
   , mMayHaveInputOrCompositionEventListener(false)
   , mClearingListeners(false)
   , mIsMainThreadELM(NS_IsMainThread())
 {
@@ -417,16 +418,21 @@ EventListenerManager::AddEventListenerIn
     }
   } else if (aTypeAtom == nsGkAtoms::oncompositionend ||
              aTypeAtom == nsGkAtoms::oncompositionstart ||
              aTypeAtom == nsGkAtoms::oncompositionupdate ||
              aTypeAtom == nsGkAtoms::oninput) {
     if (!aFlags.mInSystemGroup) {
       mMayHaveInputOrCompositionEventListener = true;
     }
+  } else if (aTypeAtom == nsGkAtoms::onmousemove) {
+    mMayHaveMouseMoveEventListener = true;
+    if (nsPIDOMWindowInner* window = GetInnerWindowForTarget()) {
+      window->SetHasMouseMoveEventListeners();
+    }
   }
 
   if (IsApzAwareListener(listener)) {
     ProcessApzAwareEventListenerAdd();
   }
 
   if (mTarget) {
     if (aTypeAtom) {
--- a/dom/events/EventListenerManager.h
+++ b/dom/events/EventListenerManager.h
@@ -156,24 +156,25 @@ protected:
   EventListenerManagerBase();
 
   EventMessage mNoListenerForEvent;
   uint16_t mMayHavePaintEventListener : 1;
   uint16_t mMayHaveMutationListeners : 1;
   uint16_t mMayHaveCapturingListeners : 1;
   uint16_t mMayHaveSystemGroupListeners : 1;
   uint16_t mMayHaveTouchEventListener : 1;
+  uint16_t mMayHaveMouseMoveEventListener : 1;
   uint16_t mMayHaveMouseEnterLeaveEventListener : 1;
   uint16_t mMayHavePointerEnterLeaveEventListener : 1;
   uint16_t mMayHaveAPZAwareKeyEventListener : 1;
   uint16_t mMayHaveKeyEventListener : 1;
   uint16_t mMayHaveInputOrCompositionEventListener : 1;
   uint16_t mClearingListeners : 1;
   uint16_t mIsMainThreadELM : 1;
-  // uint16_t mUnused : 4;
+  // uint16_t mUnused : 3;
 };
 
 /*
  * Event listener manager
  */
 
 class EventListenerManager final : public EventListenerManagerBase
 {
@@ -435,16 +436,18 @@ public:
   bool MayHavePaintEventListener() { return mMayHavePaintEventListener; }
 
   /**
    * Returns true if there may be a touch event listener registered,
    * false if there definitely isn't.
    */
   bool MayHaveTouchEventListener() { return mMayHaveTouchEventListener; }
 
+  bool MayHaveMouseMoveEventListener() { return mMayHaveMouseMoveEventListener; }
+
   bool MayHaveMouseEnterLeaveEventListener() { return mMayHaveMouseEnterLeaveEventListener; }
   bool MayHavePointerEnterLeaveEventListener() { return mMayHavePointerEnterLeaveEventListener; }
 
   bool MayHaveAPZAwareKeyEventListener() const { return mMayHaveAPZAwareKeyEventListener; }
 
   /**
    * Returns true if there may be a key event listener (keydown, keypress,
    * or keyup) registered, or false if there definitely isn't.
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -10430,16 +10430,23 @@
   },
   "APZ_AWARE_KEY_LISTENERS": {
     "alert_emails": ["rhunt@mozilla.com"],
     "bug_numbers": [1352654],
     "expires_in_version": "58",
     "kind": "boolean",
     "description": "The percentage of pages with a non-passive key event on the path to the root scrolling element that would disable APZ key scrolling."
   },
+  "APZ_AWARE_MOUSEMOVE_LISTENERS": {
+    "alert_emails": ["rhunt@mozilla.com"],
+    "bug_numbers": [1352654],
+    "expires_in_version": "58",
+    "kind": "boolean",
+    "description": "The percentage of pages with a mousemove listener anywhere in the document that would disable APZ key scrolling."
+  },
   "SCROLL_INPUT_METHODS": {
     "alert_emails": ["botond@mozilla.com"],
     "bug_numbers": [1238137],
     "expires_in_version": "60",
     "kind": "enumerated",
     "n_values": 64,
     "description": "Count of scroll actions triggered by different input methods. See gfx/layers/apz/util/ScrollInputMethods.h for a list of possible values and their meanings."
   },