Bug 1334634 - Add a telemetry probe for the number of clicks on the triangle history menu button. r?adw draft
authorMark Banner <standard8@mozilla.com>
Tue, 07 Mar 2017 14:52:18 +0000
changeset 496745 162d7250f6312e9bb7daa783b4ab61a713c34f67
parent 496661 92c5b7bcd598c55f88979c014acfb79fd1ad7e45
child 548692 c9b45fef6c86c0a0471f81eb6fdaf60b696d2078
push id48683
push userbmo:standard8@mozilla.com
push dateFri, 10 Mar 2017 16:58:45 +0000
reviewersadw
bugs1334634
milestone55.0a1
Bug 1334634 - Add a telemetry probe for the number of clicks on the triangle history menu button. r?adw MozReview-Commit-ID: E4OYN1Eb8wU
browser/base/content/browser.css
browser/base/content/test/urlbar/browser.ini
browser/base/content/test/urlbar/browser_urlbarHistoryButtonTelemetry.js
browser/base/content/test/urlbar/head.js
browser/base/content/urlbarBindings.xml
browser/modules/BrowserUsageTelemetry.jsm
toolkit/components/telemetry/Scalars.yaml
toolkit/content/widgets/autocomplete.xml
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -467,16 +467,25 @@ toolbar:not(#TabsToolbar) > #personal-bo
   display: none;
 }
 
 /* ::::: location bar ::::: */
 #urlbar {
   -moz-binding: url(chrome://browser/content/urlbarBindings.xml#urlbar);
 }
 
+.urlbar-history-dropmarker {
+  display: none;
+}
+
+.urlbar-history-dropmarker[enablehistory="true"] {
+  display: -moz-box;
+  -moz-binding: url(chrome://browser/content/urlbarBindings.xml#urlbar-history-dropmarker);
+}
+
 /* Always show URLs LTR. */
 .ac-url-text:-moz-locale-dir(rtl),
 .ac-title-text[lookslikeurl]:-moz-locale-dir(rtl) {
   direction: ltr !important;
 }
 
 /* For non-action items, hide the action text; for action items, hide the URL
    text. */
--- a/browser/base/content/test/urlbar/browser.ini
+++ b/browser/base/content/test/urlbar/browser.ini
@@ -62,16 +62,17 @@ support-files =
   authenticate.sjs
 [browser_urlbarDecode.js]
 [browser_urlbarDelete.js]
 [browser_urlbarEnter.js]
 [browser_urlbarEnterAfterMouseOver.js]
 skip-if = os == "linux" # Bug 1073339 - Investigate autocomplete test unreliability on Linux/e10s
 [browser_urlbarFocusedCmdK.js]
 [browser_urlbarHashChangeProxyState.js]
+[browser_urlbarHistoryButtonTelemetry.js]
 [browser_urlbarKeepStateAcrossTabSwitches.js]
 [browser_urlbarOneOffs.js]
 [browser_urlbarPrivateBrowsingWindowChange.js]
 [browser_urlbarRaceWithTabs.js]
 [browser_urlbarRevert.js]
 [browser_urlbarSearchSingleWordNotification.js]
 [browser_urlbarSearchSuggestions.js]
 support-files =
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/urlbar/browser_urlbarHistoryButtonTelemetry.js
@@ -0,0 +1,80 @@
+"use strict";
+
+Cu.import("resource:///modules/BrowserUITelemetry.jsm");
+
+const HISTORY_BUTTON_SCALAR = "browser.engagement.navigation.urlbar_history_triangle";
+var expectedButtonClickCount = 0;
+
+function getHistoryButtonScalarCount() {
+  let snapshot = Services.telemetry.snapshotScalars(
+    Services.telemetry.DATASET_RELEASE_CHANNEL_OPTOUT);
+
+  return snapshot["default"][HISTORY_BUTTON_SCALAR];
+}
+
+add_task(function* prepare() {
+  Services.telemetry.clearScalars();
+
+  // Adding a tab would hit switch-to-tab, so it's safer to just add a visit.
+  yield PlacesTestUtils.addVisits([{
+    uri: "http://www.autofilltrimurl.com/whatever",
+    transition: Ci.nsINavHistoryService.TRANSITION_TYPED,
+  }, {
+    uri: "https://www.secureautofillurl.com/whatever",
+    transition: Ci.nsINavHistoryService.TRANSITION_TYPED,
+  }]);
+
+  registerCleanupFunction(function* () {
+    Services.telemetry.clearScalars();
+    yield PlacesTestUtils.clearHistory();
+    gURLBar.handleRevert();
+  });
+});
+
+function* openViaHistoryTriangleAndCheck() {
+  let historyDropMarker = document.getAnonymousElementByAttribute(
+    gURLBar, "anonid", "historydropmarker");
+
+  gURLBar.focus();
+  // Open the urlbar history view.
+  historyDropMarker.click();
+  expectedButtonClickCount++;
+  yield promisePopupShown(gURLBar.popup);
+
+  Assert.equal(getHistoryButtonScalarCount(),
+               expectedButtonClickCount, "Should have recorded one click for opening.");
+
+  // Now close it again - this shouldn't increase the count.
+  historyDropMarker.click();
+  yield promiseAutocompleteResultPopupHidden(gURLBar.popup);
+
+  Assert.equal(getHistoryButtonScalarCount(),
+               expectedButtonClickCount, "Should stay the same count when closing.");
+}
+
+add_task(function* test_openViaHistoryTriangle() {
+  // Open and close once...
+  yield openViaHistoryTriangleAndCheck();
+
+  // and do it again, just to check the correct increment.
+  yield openViaHistoryTriangleAndCheck();
+});
+
+add_task(function* test_otherActivitesDontCount() {
+  let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser);
+  // Open via a different route.
+  gURLBar.focus();
+  yield promiseAutocompleteResultPopup("foo");
+
+  // Now close it again
+  let historyDropMarker = document.getAnonymousElementByAttribute(
+    gURLBar, "anonid", "historydropmarker");
+  historyDropMarker.click();
+  yield promiseAutocompleteResultPopupHidden(gURLBar.popup);
+
+  Assert.equal(getHistoryButtonScalarCount(),
+               expectedButtonClickCount,
+               "Should stay the same count for non-history marker activites.");
+
+  yield BrowserTestUtils.removeTab(tab);
+});
--- a/browser/base/content/test/urlbar/head.js
+++ b/browser/base/content/test/urlbar/head.js
@@ -151,16 +151,22 @@ function promisePopupEvent(popup, eventS
 function promisePopupShown(popup) {
   return promisePopupEvent(popup, "shown");
 }
 
 function promisePopupHidden(popup) {
   return promisePopupEvent(popup, "hidden");
 }
 
+function* promiseAutocompleteResultPopupHidden(popup) {
+  yield promisePopupHidden(popup);
+  yield BrowserTestUtils.waitForCondition(() => !popup.isPopupHidingTick,
+    "Waiting for popup to be closed.")
+}
+
 function promiseSearchComplete(win = window) {
   return promisePopupShown(win.gURLBar.popup).then(() => {
     function searchIsComplete() {
       return win.gURLBar.controller.searchStatus >=
         Ci.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH;
     }
 
     // Wait until there are at least two matches.
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -2656,9 +2656,26 @@ file, You can obtain one at http://mozil
       <constructor><![CDATA[
         this.setAttribute("tooltiptext", this.getAttribute("acceltext"));
         // TODO: Simplify this to this.setAttribute("acceltext", "") once bug
         // 592424 is fixed
         document.getAnonymousElementByAttribute(this, "anonid", "accel").firstChild.setAttribute("value", "");
       ]]></constructor>
     </implementation>
   </binding>
+
+  <!-- This binding extends the one in autocomplete.xml so that we can log telemetry nicely. -->
+  <binding id="urlbar-history-dropmarker"
+           extends="chrome://global/content/bindings/autocomplete.xml#history-dropmarker">
+    <handlers>
+      <!-- This handler overrides the one in autocomplete.xml. -->
+      <handler event="mousedown" button="0"><![CDATA[
+        let parent = document.getBindingParent(this);
+        if (parent.isHistoryPopupClosed()) {
+          // We're going to open the popup, so record the fact in telemetry.
+          BrowserUsageTelemetry.recordUrlbarHistoryMenuOpen();
+        }
+        document.getBindingParent(this).toggleHistoryPopup();
+      ]]></handler>
+    </handlers>
+  </binding>
+
 </bindings>
--- a/browser/modules/BrowserUsageTelemetry.jsm
+++ b/browser/modules/BrowserUsageTelemetry.jsm
@@ -334,16 +334,25 @@ let BrowserUsageTelemetry = {
         // |URICountListener| know about them.
         let browser = event.target.linkedBrowser;
         URICountListener.addRestoredURI(browser, browser.currentURI);
         break;
     }
   },
 
   /**
+   * Records a click on the history menu triangle in the urlbar. It is expected
+   * that this is only called when the history menu opens. It increments the
+   * count for the scalar by 1.
+   */
+  recordUrlbarHistoryMenuOpen() {
+    Services.telemetry.scalarAdd("browser.engagement.navigation.urlbar_history_triangle", 1);
+  },
+
+  /**
    * The main entry point for recording search related Telemetry. This includes
    * search counts and engagement measurements.
    *
    * Telemetry records only search counts per engine and action origin, but
    * nothing pertaining to the search contents themselves.
    *
    * @param {nsISearchEngine} engine
    *        The engine handling the search.
--- a/toolkit/components/telemetry/Scalars.yaml
+++ b/toolkit/components/telemetry/Scalars.yaml
@@ -121,16 +121,30 @@ browser.engagement:
     notification_emails:
       - rweiss@mozilla.com
     release_channel_collection: opt-out
     record_in_processes:
       - 'main'
 
 # The following section contains the browser engagement scalars.
 browser.engagement.navigation:
+  urlbar_history_triangle:
+    bug_numbers:
+      - 1271313
+    description: >
+      The amount of times the urlbar history menu has been opened by clicking on
+      the triangle.
+    expires: "59"
+    kind: uint
+    notification_emails:
+      - bcolloran@mozilla.com
+    release_channel_collection: opt-out
+    record_in_processes:
+      - 'main'
+
   urlbar:
     bug_numbers:
       - 1271313
     description: >
       The count URI loads triggered in a subsession from the urlbar (awesomebar),
       broken down by the originating action.
     expires: never
     kind: uint
--- a/toolkit/content/widgets/autocomplete.xml
+++ b/toolkit/content/widgets/autocomplete.xml
@@ -442,16 +442,22 @@
           // marker is clicked while the popup is still open.
           if (!this.popup.isPopupHidingTick && !this.popup.popupOpen)
             this.showHistoryPopup();
           else
             this.closePopup();
         ]]></body>
       </method>
 
+      <method name="isHistoryPopupClosed">
+        <body><![CDATA[
+          return !this.popup.isPopupHidingTick && !this.popup.popupOpen;
+        ]]></body>
+      </method>
+
       <!-- ::::::::::::: event dispatching ::::::::::::: -->
 
       <method name="initEventHandler">
         <parameter name="aEventType"/>
         <body><![CDATA[
           let handlerString = this.getAttribute("on" + aEventType);
           if (handlerString) {
             return (new Function("eventType", "param", handlerString)).bind(this, aEventType);