Bug 1515083 - Extend urlbar telemetry tests to cover most reported result types. r=adw
authorMark Banner <standard8@mozilla.com>
Fri, 15 Feb 2019 14:57:13 +0000
changeset 459544 e90244ffbb1318d6984328408bb6ab33f9477427
parent 459543 4c7b508eb10d6743cc53c0b798a62569aa492cf5
child 459545 a8d8de1df9e4f8ee5b671480d0a789d1631322b6
push id111964
push usercsabou@mozilla.com
push dateFri, 15 Feb 2019 18:54:44 +0000
treeherdermozilla-inbound@db3c4f905082 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersadw
bugs1515083, 1527888
milestone67.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 1515083 - Extend urlbar telemetry tests to cover most reported result types. r=adw This add checks for everything bar 'preloaded-top-site' which isn't used/enabled at the moment (bug 1527888). Depends on D19709 Differential Revision: https://phabricator.services.mozilla.com/D19784
browser/modules/test/browser/browser.ini
browser/modules/test/browser/browser_UsageTelemetry_urlbar.js
browser/modules/test/browser/browser_UsageTelemetry_urlbar_extension.js
browser/modules/test/browser/browser_UsageTelemetry_urlbar_places.js
browser/modules/test/browser/browser_UsageTelemetry_urlbar_remotetab.js
--- a/browser/modules/test/browser/browser.ini
+++ b/browser/modules/test/browser/browser.ini
@@ -28,16 +28,19 @@ skip-if = os != win || (os == win && bit
 [browser_UnsubmittedCrashHandler.js]
 run-if = crashreporter
 [browser_urlBar_zoom.js]
 [browser_UsageTelemetry.js]
 [browser_UsageTelemetry_domains.js]
 [browser_UsageTelemetry_private_and_restore.js]
 skip-if = verify && debug
 [browser_UsageTelemetry_uniqueOriginsVisitedInPast24Hours.js]
+[browser_UsageTelemetry_urlbar_extension.js]
+[browser_UsageTelemetry_urlbar_places.js]
+[browser_UsageTelemetry_urlbar_remotetab.js]
 [browser_UsageTelemetry_urlbar.js]
 support-files =
   usageTelemetrySearchSuggestions.sjs
   usageTelemetrySearchSuggestions.xml
 [browser_UsageTelemetry_searchbar.js]
 support-files =
   usageTelemetrySearchSuggestions.sjs
   usageTelemetrySearchSuggestions.xml
--- a/browser/modules/test/browser/browser_UsageTelemetry_urlbar.js
+++ b/browser/modules/test/browser/browser_UsageTelemetry_urlbar.js
@@ -1,8 +1,16 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/**
+ * This file tests urlbar telemetry with search related actions.
+ */
+
 "use strict";
 
 const SCALAR_URLBAR = "browser.engagement.navigation.urlbar";
 
 // The preference to enable suggestions in the urlbar.
 const SUGGEST_URLBAR_PREF = "browser.urlbar.suggest.searches";
 // The name of the search engine used to generate suggestions.
 const SUGGESTION_ENGINE_NAME = "browser_UsageTelemetry usageTelemetrySearchSuggestions.xml";
new file mode 100644
--- /dev/null
+++ b/browser/modules/test/browser/browser_UsageTelemetry_urlbar_extension.js
@@ -0,0 +1,134 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/**
+ * This file tests urlbar telemetry with extension actions.
+ */
+
+"use strict";
+
+const SCALAR_URLBAR = "browser.engagement.navigation.urlbar";
+
+XPCOMUtils.defineLazyModuleGetters(this, {
+  UrlbarTestUtils: "resource://testing-common/UrlbarTestUtils.jsm",
+  URLBAR_SELECTED_RESULT_TYPES: "resource:///modules/BrowserUsageTelemetry.jsm",
+  URLBAR_SELECTED_RESULT_METHODS: "resource:///modules/BrowserUsageTelemetry.jsm",
+});
+
+function assertSearchTelemetryEmpty(search_hist) {
+  const scalars = TelemetryTestUtils.getProcessScalars("parent", true, false);
+  Assert.equal(Object.keys(scalars).length, 0,
+    `Should not have recorded ${SCALAR_URLBAR}`);
+
+  // Make sure SEARCH_COUNTS contains identical values.
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.urlbar", undefined);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.alias", undefined);
+
+  // Also check events.
+  let events = Services.telemetry.snapshotEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
+  events = (events.parent || []).filter(e => e[1] == "navigation" && e[2] == "search");
+  Assert.equal(events.length, 0, "Should not have recorded any events");
+}
+
+function snapshotHistograms() {
+  Services.telemetry.clearScalars();
+  Services.telemetry.clearEvents();
+  return {
+    resultIndexHist: TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_INDEX"),
+    resultTypeHist: TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_TYPE"),
+    resultIndexByTypeHist: TelemetryTestUtils.getAndClearKeyedHistogram("FX_URLBAR_SELECTED_RESULT_INDEX_BY_TYPE"),
+    resultMethodHist: TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD"),
+    search_hist: TelemetryTestUtils.getAndClearKeyedHistogram("SEARCH_COUNTS"),
+  };
+}
+
+function assertHistogramResults(histograms, type, index, method) {
+  TelemetryTestUtils.assertHistogram(histograms.resultIndexHist, index, 1);
+
+  TelemetryTestUtils.assertHistogram(histograms.resultTypeHist,
+    URLBAR_SELECTED_RESULT_TYPES[type], 1);
+
+  TelemetryTestUtils.assertKeyedHistogramValue(histograms.resultIndexByTypeHist,
+    type, index, 1);
+
+  TelemetryTestUtils.assertHistogram(histograms.resultMethodHist,
+    method, 1);
+}
+
+
+add_task(async function setup() {
+  await SpecialPowers.pushPrefEnv({
+    set: [
+      // Disable search suggestions in the urlbar.
+      ["browser.urlbar.suggest.searches", false],
+      // Clear historical search suggestions to avoid interference from previous
+      // tests.
+      ["browser.urlbar.maxHistoricalSearchSuggestions", 0],
+      // Use the default matching bucket configuration.
+      ["browser.urlbar.matchBuckets", "general:5,suggestion:4"],
+      // Turn autofill off.
+      ["browser.urlbar.autoFill", false],
+    ],
+  });
+
+  // Enable local telemetry recording for the duration of the tests.
+  let oldCanRecord = Services.telemetry.canRecordExtended;
+  Services.telemetry.canRecordExtended = true;
+
+  // Enable event recording for the events tested here.
+  Services.telemetry.setEventRecordingEnabled("navigation", true);
+
+  // Clear history so that history added by previous tests doesn't mess up this
+  // test when it selects results in the urlbar.
+  await PlacesUtils.history.clear();
+  await PlacesUtils.bookmarks.eraseEverything();
+
+  // Make sure to restore the engine once we're done.
+  registerCleanupFunction(async function() {
+    Services.telemetry.canRecordExtended = oldCanRecord;
+    await PlacesUtils.history.clear();
+    await PlacesUtils.bookmarks.eraseEverything();
+    Services.telemetry.setEventRecordingEnabled("navigation", false);
+  });
+});
+
+add_task(async function test_extension() {
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      "omnibox": {
+        "keyword": "omniboxtest",
+      },
+
+      background() {
+        /* global browser */
+        browser.omnibox.setDefaultSuggestion({
+          description: "doit",
+        });
+        // Just do nothing for this test.
+        browser.omnibox.onInputEntered.addListener(() => {
+        });
+        browser.omnibox.onInputChanged.addListener((text, suggest) => {
+          suggest([]);
+        });
+      },
+    },
+  });
+
+  await extension.startup();
+
+  const histograms = snapshotHistograms();
+
+  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
+
+  await UrlbarTestUtils.promiseAutocompleteResultPopup(window, "omniboxtest ",
+    waitForFocus, true);
+  EventUtils.synthesizeKey("KEY_Enter");
+
+  assertSearchTelemetryEmpty(histograms.search_hist);
+  assertHistogramResults(histograms, "extension", 0,
+    URLBAR_SELECTED_RESULT_METHODS.enter);
+
+  await extension.unload();
+  BrowserTestUtils.removeTab(tab);
+});
new file mode 100644
--- /dev/null
+++ b/browser/modules/test/browser/browser_UsageTelemetry_urlbar_places.js
@@ -0,0 +1,263 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/**
+ * This file tests urlbar telemetry with places related actions (e.g. history/
+ * bookmark selection).
+ */
+
+"use strict";
+
+const SCALAR_URLBAR = "browser.engagement.navigation.urlbar";
+
+const TEST_URL = getRootDirectory(gTestPath)
+  .replace("chrome://mochitests/content", "http://mochi.test:8888");
+
+XPCOMUtils.defineLazyModuleGetters(this, {
+  UrlbarTestUtils: "resource://testing-common/UrlbarTestUtils.jsm",
+  URLBAR_SELECTED_RESULT_TYPES: "resource:///modules/BrowserUsageTelemetry.jsm",
+  URLBAR_SELECTED_RESULT_METHODS: "resource:///modules/BrowserUsageTelemetry.jsm",
+});
+
+function searchInAwesomebar(inputText, win = window) {
+  return UrlbarTestUtils.promiseAutocompleteResultPopup(win, inputText, waitForFocus, true);
+}
+
+function assertSearchTelemetryEmpty(search_hist) {
+  const scalars = TelemetryTestUtils.getProcessScalars("parent", true, false);
+  Assert.equal(Object.keys(scalars).length, 0,
+    `Should not have recorded ${SCALAR_URLBAR}`);
+
+  // Make sure SEARCH_COUNTS contains identical values.
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.urlbar", undefined);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.alias", undefined);
+
+  // Also check events.
+  let events = Services.telemetry.snapshotEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
+  events = (events.parent || []).filter(e => e[1] == "navigation" && e[2] == "search");
+  Assert.equal(events.length, 0, "Should not have recorded any events");
+}
+
+function snapshotHistograms() {
+  Services.telemetry.clearScalars();
+  Services.telemetry.clearEvents();
+  return {
+    resultIndexHist: TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_INDEX"),
+    resultTypeHist: TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_TYPE"),
+    resultIndexByTypeHist: TelemetryTestUtils.getAndClearKeyedHistogram("FX_URLBAR_SELECTED_RESULT_INDEX_BY_TYPE"),
+    resultMethodHist: TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD"),
+    search_hist: TelemetryTestUtils.getAndClearKeyedHistogram("SEARCH_COUNTS"),
+  };
+}
+
+function assertHistogramResults(histograms, type, index, method) {
+  TelemetryTestUtils.assertHistogram(histograms.resultIndexHist, index, 1);
+
+  TelemetryTestUtils.assertHistogram(histograms.resultTypeHist,
+    URLBAR_SELECTED_RESULT_TYPES[type], 1);
+
+  TelemetryTestUtils.assertKeyedHistogramValue(histograms.resultIndexByTypeHist,
+    type, index, 1);
+
+  TelemetryTestUtils.assertHistogram(histograms.resultMethodHist,
+    method, 1);
+}
+
+
+add_task(async function setup() {
+  await SpecialPowers.pushPrefEnv({
+    set: [
+      // Disable search suggestions in the urlbar.
+      ["browser.urlbar.suggest.searches", false],
+      // Clear historical search suggestions to avoid interference from previous
+      // tests.
+      ["browser.urlbar.maxHistoricalSearchSuggestions", 0],
+      // Use the default matching bucket configuration.
+      ["browser.urlbar.matchBuckets", "general:5,suggestion:4"],
+      // Turn autofill off.
+      ["browser.urlbar.autoFill", false],
+    ],
+  });
+
+  // Enable local telemetry recording for the duration of the tests.
+  let oldCanRecord = Services.telemetry.canRecordExtended;
+  Services.telemetry.canRecordExtended = true;
+
+  // Enable event recording for the events tested here.
+  Services.telemetry.setEventRecordingEnabled("navigation", true);
+
+  // Clear history so that history added by previous tests doesn't mess up this
+  // test when it selects results in the urlbar.
+  await PlacesUtils.history.clear();
+  await PlacesUtils.bookmarks.eraseEverything();
+
+  await PlacesUtils.keywords.insert({ keyword: "get",
+                                      url: TEST_URL + "?q=%s" });
+
+  // Make sure to restore the engine once we're done.
+  registerCleanupFunction(async function() {
+    await PlacesUtils.keywords.remove("get");
+    Services.telemetry.canRecordExtended = oldCanRecord;
+    await PlacesUtils.history.clear();
+    await PlacesUtils.bookmarks.eraseEverything();
+    Services.telemetry.setEventRecordingEnabled("navigation", false);
+  });
+});
+
+add_task(async function test_history() {
+  const histograms = snapshotHistograms();
+
+  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
+
+  await PlacesTestUtils.addVisits([{
+    uri: "http://example.com",
+    title: "example",
+    transition: Ci.nsINavHistoryService.TRANSITION_TYPED,
+  }]);
+
+  let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+  await searchInAwesomebar("example");
+  EventUtils.synthesizeKey("KEY_ArrowDown");
+  EventUtils.synthesizeKey("KEY_Enter");
+  await p;
+
+  assertSearchTelemetryEmpty(histograms.search_hist);
+  assertHistogramResults(histograms, "history", 1,
+    URLBAR_SELECTED_RESULT_METHODS.arrowEnterSelection);
+
+  BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function test_bookmark() {
+  const histograms = snapshotHistograms();
+
+  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
+
+  let bm = await PlacesUtils.bookmarks.insert({
+    url: "http://example.com",
+    title: "example",
+    parentGuid: PlacesUtils.bookmarks.menuGuid,
+  });
+
+  let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+  await searchInAwesomebar("example");
+  EventUtils.synthesizeKey("KEY_ArrowDown");
+  EventUtils.synthesizeKey("KEY_Enter");
+  await p;
+
+  assertSearchTelemetryEmpty(histograms.search_hist);
+  assertHistogramResults(histograms, "bookmark", 1,
+    URLBAR_SELECTED_RESULT_METHODS.arrowEnterSelection);
+
+  await PlacesUtils.bookmarks.remove(bm);
+
+  BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function test_keyword() {
+  const histograms = snapshotHistograms();
+
+  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
+
+  let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+  await searchInAwesomebar("get example");
+  EventUtils.synthesizeKey("KEY_Enter");
+  await p;
+
+  assertSearchTelemetryEmpty(histograms.search_hist);
+  assertHistogramResults(histograms, "keyword", 0,
+    URLBAR_SELECTED_RESULT_METHODS.enter);
+
+  BrowserTestUtils.removeTab(tab);
+});
+
+
+add_task(async function test_switchtab() {
+  const histograms = snapshotHistograms();
+
+  let homeTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:buildconfig");
+  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:mozilla");
+
+  let p = BrowserTestUtils.waitForEvent(gBrowser, "TabSwitchDone");
+  await searchInAwesomebar("about:buildconfig");
+  EventUtils.synthesizeKey("KEY_ArrowDown");
+  EventUtils.synthesizeKey("KEY_Enter");
+  await p;
+
+  assertSearchTelemetryEmpty(histograms.search_hist);
+  assertHistogramResults(histograms, "switchtab", 1,
+    URLBAR_SELECTED_RESULT_METHODS.arrowEnterSelection);
+
+  BrowserTestUtils.removeTab(tab);
+  BrowserTestUtils.removeTab(homeTab);
+});
+
+add_task(async function test_tag() {
+  if (UrlbarPrefs.get("quantumbar")) {
+    return;
+  }
+  const histograms = snapshotHistograms();
+
+  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
+
+  Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false);
+
+  PlacesUtils.tagging.tagURI(Services.io.newURI("http://example.com"), ["tag"]);
+
+  let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+  await searchInAwesomebar("tag");
+  EventUtils.synthesizeKey("KEY_ArrowDown");
+  EventUtils.synthesizeKey("KEY_Enter");
+  await p;
+
+  assertSearchTelemetryEmpty(histograms.search_hist);
+  assertHistogramResults(histograms, "tag", 1,
+    URLBAR_SELECTED_RESULT_METHODS.arrowEnterSelection);
+
+  PlacesUtils.tagging.untagURI(Services.io.newURI("http://example.com"), ["tag"]);
+  Services.prefs.clearUserPref("browser.urlbar.suggest.bookmark");
+  BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function test_visitURL() {
+  const histograms = snapshotHistograms();
+
+  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
+
+  let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+  await searchInAwesomebar("http://example.com");
+  EventUtils.synthesizeKey("KEY_Enter");
+  await p;
+
+  assertSearchTelemetryEmpty(histograms.search_hist);
+  assertHistogramResults(histograms, "visiturl", 0,
+    URLBAR_SELECTED_RESULT_METHODS.enter);
+
+  BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function test_autofill() {
+  const histograms = snapshotHistograms();
+
+  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
+
+  await PlacesTestUtils.addVisits([{
+    uri: "http://example.com/mypage",
+    title: "example",
+    transition: Ci.nsINavHistoryService.TRANSITION_TYPED,
+  }]);
+
+  Services.prefs.setBoolPref("browser.urlbar.autoFill", true);
+
+  let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+  await searchInAwesomebar("example.com/my");
+  EventUtils.synthesizeKey("KEY_Enter");
+  await p;
+
+  assertSearchTelemetryEmpty(histograms.search_hist);
+  assertHistogramResults(histograms, "autofill", 0,
+    URLBAR_SELECTED_RESULT_METHODS.enter);
+
+  BrowserTestUtils.removeTab(tab);
+});
new file mode 100644
--- /dev/null
+++ b/browser/modules/test/browser/browser_UsageTelemetry_urlbar_remotetab.js
@@ -0,0 +1,161 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/**
+ * This file tests urlbar telemetry with remote tab action.
+ */
+
+"use strict";
+
+const SCALAR_URLBAR = "browser.engagement.navigation.urlbar";
+
+XPCOMUtils.defineLazyModuleGetters(this, {
+  SyncedTabs: "resource://services-sync/SyncedTabs.jsm",
+  UrlbarTestUtils: "resource://testing-common/UrlbarTestUtils.jsm",
+  URLBAR_SELECTED_RESULT_TYPES: "resource:///modules/BrowserUsageTelemetry.jsm",
+  URLBAR_SELECTED_RESULT_METHODS: "resource:///modules/BrowserUsageTelemetry.jsm",
+});
+
+function assertSearchTelemetryEmpty(search_hist) {
+  const scalars = TelemetryTestUtils.getProcessScalars("parent", true, false);
+  Assert.equal(Object.keys(scalars).length, 0,
+    `Should not have recorded ${SCALAR_URLBAR}`);
+
+  // Make sure SEARCH_COUNTS contains identical values.
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.urlbar", undefined);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.alias", undefined);
+
+  // Also check events.
+  let events = Services.telemetry.snapshotEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
+  events = (events.parent || []).filter(e => e[1] == "navigation" && e[2] == "search");
+  Assert.equal(events.length, 0, "Should not have recorded any events");
+}
+
+function snapshotHistograms() {
+  Services.telemetry.clearScalars();
+  Services.telemetry.clearEvents();
+  return {
+    resultIndexHist: TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_INDEX"),
+    resultTypeHist: TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_TYPE"),
+    resultIndexByTypeHist: TelemetryTestUtils.getAndClearKeyedHistogram("FX_URLBAR_SELECTED_RESULT_INDEX_BY_TYPE"),
+    resultMethodHist: TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD"),
+    search_hist: TelemetryTestUtils.getAndClearKeyedHistogram("SEARCH_COUNTS"),
+  };
+}
+
+function assertHistogramResults(histograms, type, index, method) {
+  TelemetryTestUtils.assertHistogram(histograms.resultIndexHist, index, 1);
+
+  TelemetryTestUtils.assertHistogram(histograms.resultTypeHist,
+    URLBAR_SELECTED_RESULT_TYPES[type], 1);
+
+  TelemetryTestUtils.assertKeyedHistogramValue(histograms.resultIndexByTypeHist,
+    type, index, 1);
+
+  TelemetryTestUtils.assertHistogram(histograms.resultMethodHist,
+    method, 1);
+}
+
+
+add_task(async function setup() {
+  /* global sinon */
+  Services.scriptloader.loadSubScript("resource://testing-common/sinon-2.3.2.js");
+
+  await SpecialPowers.pushPrefEnv({
+    set: [
+      // Disable search suggestions in the urlbar.
+      ["browser.urlbar.suggest.searches", false],
+      // Clear historical search suggestions to avoid interference from previous
+      // tests.
+      ["browser.urlbar.maxHistoricalSearchSuggestions", 0],
+      // Use the default matching bucket configuration.
+      ["browser.urlbar.matchBuckets", "general:5,suggestion:4"],
+      // Turn autofill off.
+      ["browser.urlbar.autoFill", false],
+      // Special prefs for remote tabs.
+      ["services.sync.username", "fake"],
+      ["services.sync.syncedTabs.showRemoteTabs", true],
+    ],
+  });
+
+  // Enable local telemetry recording for the duration of the tests.
+  let oldCanRecord = Services.telemetry.canRecordExtended;
+  Services.telemetry.canRecordExtended = true;
+
+  // Enable event recording for the events tested here.
+  Services.telemetry.setEventRecordingEnabled("navigation", true);
+
+  // Clear history so that history added by previous tests doesn't mess up this
+  // test when it selects results in the urlbar.
+  await PlacesUtils.history.clear();
+  await PlacesUtils.bookmarks.eraseEverything();
+
+  const REMOTE_TAB = {
+    "id": "7cqCr77ptzX3",
+    "type": "client",
+    "lastModified": 1492201200,
+    "name": "zcarter's Nightly on MacBook-Pro-25",
+    "clientType": "desktop",
+    "tabs": [
+      {
+        "type": "tab",
+        "title": "Test Remote",
+        "url": "http://example.com",
+        "icon": UrlbarUtils.ICON.DEFAULT,
+        "client": "7cqCr77ptzX3",
+        "lastUsed": 1452124677,
+      },
+    ],
+  };
+
+  const sandbox = sinon.sandbox.create();
+
+  let originalSyncedTabsInternal = SyncedTabs._internal;
+  SyncedTabs._internal = {
+    isConfiguredToSyncTabs: true,
+    hasSyncedThisSession: true,
+    getTabClients() { return Promise.resolve([]); },
+    syncTabs() { return Promise.resolve(); },
+  };
+
+  // Tell the Sync XPCOM service it is initialized.
+  let weaveXPCService = Cc["@mozilla.org/weave/service;1"]
+                          .getService(Ci.nsISupports)
+                          .wrappedJSObject;
+  let oldWeaveServiceReady = weaveXPCService.ready;
+  weaveXPCService.ready = true;
+
+  sandbox.stub(SyncedTabs._internal, "getTabClients")
+         .callsFake(() => Promise.resolve(Cu.cloneInto([REMOTE_TAB], {})));
+
+  // Make sure to restore the engine once we're done.
+  registerCleanupFunction(async function() {
+    sandbox.restore();
+    weaveXPCService.ready = oldWeaveServiceReady;
+    SyncedTabs._internal = originalSyncedTabsInternal;
+    Services.telemetry.canRecordExtended = oldCanRecord;
+    await PlacesUtils.history.clear();
+    await PlacesUtils.bookmarks.eraseEverything();
+    Services.telemetry.setEventRecordingEnabled("navigation", false);
+    delete window.sinon;
+  });
+});
+
+add_task(async function test_remotetab() {
+  const histograms = snapshotHistograms();
+
+  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
+
+  let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+  await UrlbarTestUtils.promiseAutocompleteResultPopup(window, "example", waitForFocus, true);
+  EventUtils.synthesizeKey("KEY_ArrowDown");
+  EventUtils.synthesizeKey("KEY_Enter");
+  await p;
+
+  assertSearchTelemetryEmpty(histograms.search_hist);
+  assertHistogramResults(histograms, "remotetab", 1,
+    URLBAR_SELECTED_RESULT_METHODS.arrowEnterSelection);
+
+  BrowserTestUtils.removeTab(tab);
+});