Bug 1274919 - part5 : add telemetry probe to measure how long the cursor is hovering before opening the tab. draft
authorAlastor Wu <alwu@mozilla.com>
Fri, 14 Jul 2017 16:28:37 +0800
changeset 608877 45daf059d4e812dfd509477c8854111f9ed5920a
parent 608876 3ece1d61de4b2b82837a7c79709eb4d876b8341c
child 637438 f8c361299b0295ddf76f1eeace01cf4e5cb16044
push id68432
push useralwu@mozilla.com
push dateFri, 14 Jul 2017 08:28:55 +0000
bugs1274919
milestone56.0a1
Bug 1274919 - part5 : add telemetry probe to measure how long the cursor is hovering before opening the tab. Measure the time how long the cursor is hovering before opening the tab which contains suspended playing media. If the tab didn't be opened, the data won't be recorded. MozReview-Commit-ID: A3RBfMyCziv
browser/base/content/tabbrowser.xml
toolkit/components/telemetry/Histograms.json
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -5553,16 +5553,17 @@
             // Also support adding event listeners (forward to the tab container)
             addEventListener(a, b, c) { this.self.tabContainer.addEventListener(a, b, c); },
             removeEventListener(a, b, c) { this.self.tabContainer.removeEventListener(a, b, c); }
           });
         ]]>
         </getter>
       </property>
       <field name="_soundPlayingAttrRemovalTimer">0</field>
+      <field name="_hoverTabTimer">0</field>
     </implementation>
 
     <handlers>
       <handler event="DOMWindowClose" phase="capturing">
         <![CDATA[
           if (!event.isTrusted)
             return;
 
@@ -7401,16 +7402,23 @@
           if (val)
             this.setAttribute("visuallyselected", "true");
           else
             this.removeAttribute("visuallyselected");
           this.parentNode.tabbrowser._tabAttrModified(this, ["visuallyselected"]);
 
           this._setPositionAttributes(val);
 
+          // Stop timer when the tab is opened.
+          if (Services.prefs.getBoolPref("media.suspend-bkgnd-video.resume-when-tab-is-hovering-by-cursor") &&
+              val &&
+              TelemetryStopwatch.running("HOVER_UNTIL_MEDIA_TAB_OPENED", this)) {
+            TelemetryStopwatch.finish("HOVER_UNTIL_MEDIA_TAB_OPENED", this);
+          }
+
           return val;
           ]]>
         </setter>
       </property>
 
       <property name="_selected">
         <setter>
           <![CDATA[
@@ -7521,28 +7529,51 @@
           if (!Services.prefs.getBoolPref("media.suspend-bkgnd-video.resume-when-tab-is-hovering-by-cursor")) {
             return;
           }
 
           // When the tab is hovering by cursor, we assume that the user would
           // open that tab soon. Therefore, in advance to resume the background
           // video to avoid user see the incorrect video frame.
           this.linkedBrowser.resumeBackgroundVideo();
+
+          if (!TelemetryStopwatch.running("HOVER_UNTIL_MEDIA_TAB_OPENED", this)) {
+            TelemetryStopwatch.start("HOVER_UNTIL_MEDIA_TAB_OPENED", this);
+          }
+
+          if (this._hoverTabTimer != 0) {
+            clearTimeout(this._hoverTabTimer);
+            this._hoverTabTimer = 0;
+          }
         ]]></body>
       </method>
 
       <method name="suspendBackgroundVideoWhenTabIsNotHoveringByCursor">
         <body><![CDATA[
           if (!Services.prefs.getBoolPref("media.suspend-bkgnd-video.resume-when-tab-is-hovering-by-cursor")) {
             return;
           }
 
           // Suspend the video decoding again for background tab to reduce the
           // power consumption.
           this.linkedBrowser.suspendBackgroundVideo();
+
+          // Since we're listening "mouseout" event, instead of "mouseleave".
+          // Every time the cursor is moving from the tab to its child node (icon),
+          // it would dispatch "mouseout"(for tab) first and then dispatch
+          // "mouseover" (for icon, eg: close button, speaker icon) soon.
+          // It causes we would cancel present TelemetryStopwatch immediately
+          // when cursor is moving on the icon, and then start a new one.
+          // In order to avoid this situation, we could delay cancellation and
+          // remove it if we get "mouseover" within very short period.
+          this._hoverTabTimer = setTimeout(() => {
+            if (TelemetryStopwatch.running("HOVER_UNTIL_MEDIA_TAB_OPENED", this)) {
+              TelemetryStopwatch.cancel("HOVER_UNTIL_MEDIA_TAB_OPENED", this);
+            }
+          }, 100);
         ]]></body>
       </method>
 
       <method name="_mouseenter">
         <body><![CDATA[
           if (this.hidden || this.closing)
             return;
 
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -13626,10 +13626,21 @@
     "bug_numbers": [1368524],
     "expires_in_version": "60",
     "kind": "exponential",
     "low": 3,
     "high": 512,
     "n_buckets": 20,
     "keyed": true,
     "description": "Measures the number of milliseconds we spend synchronously notifying observers, keyed by topic. Note: only NotifyObservers calls which take over 500 microseconds are included in this probe."
+  },
+  "HOVER_UNTIL_MEDIA_TAB_OPENED": {
+    "record_in_processes": ["main"],
+    "alert_emails": ["alwu@mozilla.com"],
+    "expires_in_version": "60",
+    "kind": "exponential",
+    "high": 10000,
+    "n_buckets": 100,
+    "bug_numbers": [1274919],
+    "description": "Measure the time how long the cursor is hovering before opening the tab which contains suspended playing media.",
+    "releaseChannelCollection": "opt-out"
   }
 }