tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit dd58ea232aa7f441015c1ea245c7bee9593f340f
parent c04c964cc11d046e24be066ed97a4686621af148
Author: James Teow <jteow@mozilla.com>
Date:   Fri,  9 Jan 2026 17:14:46 +0000

Bug 2009081 - Add adaptive history result type to address bar telemetry - r=mak,urlbar-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D278227

Diffstat:
Mbrowser/components/urlbar/UrlbarUtils.sys.mjs | 7+++++--
Mbrowser/components/urlbar/metrics.yaml | 21+++++++++++++++++++++
Mbrowser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_abandonment_groups.js | 78+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mbrowser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_groups.js | 2+-
Mbrowser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_selected_result.js | 238+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mbrowser/components/urlbar/tests/engagementTelemetry/browser/head-groups.js | 121+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 463 insertions(+), 4 deletions(-)

diff --git a/browser/components/urlbar/UrlbarUtils.sys.mjs b/browser/components/urlbar/UrlbarUtils.sys.mjs @@ -1510,11 +1510,14 @@ export var UrlbarUtils = { // Appends subtype to certain result types. function checkForSubType(type, res) { - if (res.providerName == "UrlbarProviderSemanticHistorySearch") { + if (res.providerName == "UrlbarProviderInputHistory") { + type += "_adaptive"; + } else if (res.providerName == "UrlbarProviderSemanticHistorySearch") { type += "_semantic"; } if ( lazy.UrlbarSearchUtils.resultIsSERP(res, [ + UrlbarUtils.RESULT_SOURCE.BOOKMARKS, UrlbarUtils.RESULT_SOURCE.HISTORY, UrlbarUtils.RESULT_SOURCE.TABS, ]) @@ -1611,7 +1614,7 @@ export var UrlbarUtils = { return "clipboard"; } if (result.source === this.RESULT_SOURCE.BOOKMARKS) { - return "bookmark"; + return checkForSubType("bookmark", result); } return checkForSubType("history", result); case this.RESULT_TYPE.RESTRICT: diff --git a/browser/components/urlbar/metrics.yaml b/browser/components/urlbar/metrics.yaml @@ -102,10 +102,15 @@ urlbar: `autofill_unknown`, `autofill_url`, `bookmark`, + `bookmark_adaptive`, + `bookmark_adaptive_serp`, + `bookmark_serp`, `calc`, `clipboard`, `fxsuggest_data_sharing_opt_in`, `history`, + `history_adaptive`, + `history_adaptive_serp`, `history_semantic`, `history_semantic_serp`, `history_serp`, @@ -139,6 +144,8 @@ urlbar: `search_suggest`, `search_suggest_rich`, `tab`, + `tab_adaptive`, + `tab_adaptive_serp`, `tab_semantic`, `tab_semantic_serp`, `tab_serp`, @@ -467,11 +474,16 @@ urlbar: `autofill_unknown`, `autofill_url`, `bookmark`, + `bookmark_adaptive`, + `bookmark_adaptive_serp`, + `bookmark_serp`, `calc`, `clipboard`, `experimental_addon`, `fxsuggest_data_sharing_opt_in`, `history`, + `history_adaptive`, + `history_adaptive_serp`, `history_semantic`, `history_semantic_serp`, `history_serp`, @@ -508,6 +520,8 @@ urlbar: `search_suggest_rich`, `site_specific_contextual_search`, `tab`, + `tab_adaptive`, + `tab_adaptive_serp`, `tab_semantic`, `tab_semantic_serp`, `tab_serp`, @@ -596,10 +610,15 @@ urlbar: `autofill_unknown`, `autofill_url`, `bookmark`, + `bookmark_adaptive`, + `bookmark_adaptive_serp`, + `bookmark_serp`, `calc`, `clipboard`, `fxsuggest_data_sharing_opt_in`, `history`, + `history_adaptive`, + `history_adaptive_serp`, `history_semantic`, `history_semantic_serp`, `history_serp`, @@ -633,6 +652,8 @@ urlbar: `search_suggest`, `search_suggest_rich`, `tab`, + `tab_adaptive`, + `tab_adaptive_serp`, `tab_semantic`, `tab_semantic_serp`, `tab_serp`, diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_abandonment_groups.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_abandonment_groups.js @@ -32,7 +32,19 @@ add_task(async function adaptive_history() { assertAbandonmentTelemetry([ { groups: "heuristic,adaptive_history", - results: "search_engine,history", + results: "search_engine,history_adaptive", + n_results: 2, + }, + ]), + }); + + await doAdaptiveHistoryBookmarkTest({ + trigger: () => doBlur(), + assert: () => + assertAbandonmentTelemetry([ + { + groups: "heuristic,adaptive_history", + results: "search_engine,bookmark_adaptive", n_results: 2, }, ]), @@ -279,6 +291,70 @@ add_task(async function history_serp() { }, ]), }); + + await doBookmarkSerpHistoryTest({ + trigger: () => doBlur(), + assert: () => + assertAbandonmentTelemetry([ + { + groups: "heuristic,general", + results: "search_engine,bookmark_serp", + n_results: 2, + }, + ]), + }); + + await doAdaptiveHistorySerpHistoryTest({ + trigger: () => doBlur(), + assert: () => + assertAbandonmentTelemetry([ + { + groups: "heuristic,adaptive_history", + results: "search_engine,history_adaptive_serp", + n_results: 2, + }, + ]), + }); + + await doAdaptiveHistoryBookmarkSerpHistoryTest({ + trigger: () => doBlur(), + assert: () => + assertAbandonmentTelemetry([ + { + groups: "heuristic,adaptive_history", + results: "search_engine,bookmark_adaptive_serp", + n_results: 2, + }, + ]), + }); +}); + +add_task(async function tab_adaptive() { + await doTabAdaptiveTest({ + trigger: () => doBlur(), + assert: () => + assertAbandonmentTelemetry([ + { + groups: "heuristic,adaptive_history", + results: "search_engine,tab_adaptive", + n_results: 2, + }, + ]), + }); +}); + +add_task(async function tab_adaptive_serp() { + await doTabAdaptiveSerpHistoryTest({ + trigger: () => doBlur(), + assert: () => + assertAbandonmentTelemetry([ + { + groups: "heuristic,adaptive_history", + results: "search_engine,tab_adaptive_serp", + n_results: 2, + }, + ]), + }); }); add_task(async function tab_serp() { diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_groups.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_groups.js @@ -32,7 +32,7 @@ add_task(async function adaptive_history() { assertEngagementTelemetry([ { groups: "heuristic,adaptive_history", - results: "search_engine,history", + results: "search_engine,history_adaptive", n_results: 2, }, ]), diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_selected_result.js b/browser/components/urlbar/tests/engagementTelemetry/browser/browser_glean_telemetry_engagement_selected_result.js @@ -123,6 +123,101 @@ add_task(async function selected_result_bookmark() { }); }); +add_task(async function selected_result_bookmark_adaptive() { + await doTest(async () => { + await PlacesTestUtils.addVisits("https://example.com/test"); + + await PlacesUtils.bookmarks.insert({ + parentGuid: PlacesUtils.bookmarks.unfiledGuid, + url: "https://example.com/test", + title: "bookmark", + }); + + await UrlbarUtils.addToInputHistory("https://example.com/test", "test"); + + await openPopup("test"); + await selectRowByProvider("UrlbarProviderInputHistory"); + await doEnter(); + + assertEngagementTelemetry([ + { + selected_result: "bookmark_adaptive", + selected_position: 2, + provider: "UrlbarProviderInputHistory", + results: "search_engine,bookmark_adaptive", + }, + ]); + }); +}); + +add_task(async function selected_result_bookmark_serp() { + await doTest(async () => { + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.urlbar.autoFill", false], + ["browser.urlbar.secondaryActions.featureGate", false], + ], + }); + + let defaultEngine = await Services.search.getDefault(); + let serpUrl = defaultEngine.getSubmission("test search", null).uri.spec; + + await PlacesTestUtils.addVisits(serpUrl); + + await PlacesUtils.bookmarks.insert({ + parentGuid: PlacesUtils.bookmarks.unfiledGuid, + url: serpUrl, + title: "bookmark", + }); + + await openPopup("test"); + await selectRowByURL(serpUrl); + await doEnter(); + + assertEngagementTelemetry([ + { + selected_result: "bookmark_serp", + selected_position: 2, + provider: "UrlbarProviderPlaces", + results: "search_engine,bookmark_serp", + }, + ]); + }); +}); + +add_task(async function selected_result_bookmark_adaptive_serp() { + await doTest(async () => { + await SpecialPowers.pushPrefEnv({ + set: [["browser.urlbar.autoFill", false]], + }); + + let defaultEngine = await Services.search.getDefault(); + let serpUrl = defaultEngine.getSubmission("test search", null).uri.spec; + + await PlacesUtils.bookmarks.insert({ + parentGuid: PlacesUtils.bookmarks.unfiledGuid, + url: serpUrl, + title: "bookmark", + }); + + await PlacesTestUtils.addVisits(serpUrl); + await UrlbarUtils.addToInputHistory(serpUrl, "test"); + + await openPopup("test"); + await selectRowByProvider("UrlbarProviderInputHistory"); + await doEnter(); + + assertEngagementTelemetry([ + { + selected_result: "bookmark_adaptive_serp", + selected_position: 2, + provider: "UrlbarProviderInputHistory", + results: "search_engine,bookmark_adaptive_serp", + }, + ]); + }); +}); + add_task(async function selected_result_history() { await SpecialPowers.pushPrefEnv({ set: [["browser.urlbar.autoFill", false]], @@ -148,6 +243,49 @@ add_task(async function selected_result_history() { await SpecialPowers.popPrefEnv(); }); +add_task(async function selected_result_history_adaptive() { + await doTest(async () => { + await PlacesTestUtils.addVisits("https://example.com/test"); + await UrlbarUtils.addToInputHistory("https://example.com/test", "exa"); + + await openPopup("exa"); + await selectRowByProvider("UrlbarProviderInputHistory"); + await doEnter(); + + assertEngagementTelemetry([ + { + selected_result: "history_adaptive", + selected_position: 2, + provider: "UrlbarProviderInputHistory", + results: "search_engine,history_adaptive", + }, + ]); + }); +}); + +add_task(async function selected_result_history_adaptive_serp() { + await doTest(async () => { + let defaultEngine = await Services.search.getDefault(); + let serpUrl = defaultEngine.getSubmission("test search", null).uri.spec; + + await PlacesTestUtils.addVisits(serpUrl); + await UrlbarUtils.addToInputHistory(serpUrl, "test sea"); + + await openPopup("test sea"); + await selectRowByProvider("UrlbarProviderInputHistory"); + await doEnter(); + + assertEngagementTelemetry([ + { + selected_result: "history_adaptive_serp", + selected_position: 2, + provider: "UrlbarProviderInputHistory", + results: "search_engine,history_adaptive_serp", + }, + ]); + }); +}); + add_task(async function selected_result_keyword() { await doTest(async () => { await PlacesUtils.keywords.insert({ @@ -280,6 +418,106 @@ add_task(async function selected_result_tab() { BrowserTestUtils.removeTab(tab); }); +add_task(async function selected_result_tab_adaptive() { + await SpecialPowers.pushPrefEnv({ + set: [["browser.urlbar.suggest.searches", false]], + }); + + const tab = BrowserTestUtils.addTab(gBrowser, "https://example.com/"); + + await doTest(async () => { + await PlacesTestUtils.addVisits("https://example.com/"); + await UrlbarUtils.addToInputHistory("https://example.com/", "exa"); + + await openPopup("exa"); + await selectRowByProvider("UrlbarProviderInputHistory"); + EventUtils.synthesizeKey("KEY_Enter"); + await BrowserTestUtils.waitForCondition(() => gBrowser.selectedTab === tab); + + assertEngagementTelemetry([ + { + selected_result: "tab_adaptive", + selected_position: 2, + provider: "UrlbarProviderInputHistory", + results: "search_engine,tab_adaptive", + }, + ]); + }); + + await SpecialPowers.popPrefEnv(); + BrowserTestUtils.removeTab(tab); +}); + +add_task(async function selected_result_tab_adaptive_serp() { + await SpecialPowers.pushPrefEnv({ + set: [["browser.urlbar.suggest.searches", false]], + }); + + let defaultEngine = await Services.search.getDefault(); + let serpUrl = defaultEngine.getSubmission("test search", null).uri.spec; + let tab = BrowserTestUtils.addTab(gBrowser, serpUrl); + + await doTest(async () => { + await PlacesTestUtils.addVisits(serpUrl); + await UrlbarUtils.addToInputHistory(serpUrl, "test sea"); + + // For some reason, when this test is run first the provider is + // UrlbarProviderPlaces instead of InputHistory. So do a simple warm up + // operation. + await openPopup("warmup"); + await UrlbarTestUtils.promisePopupClose(window); + + await openPopup("test sea"); + await selectRowByProvider("UrlbarProviderInputHistory"); + + EventUtils.synthesizeKey("KEY_Enter"); + await BrowserTestUtils.waitForCondition(() => gBrowser.selectedTab === tab); + + assertEngagementTelemetry([ + { + selected_result: "tab_adaptive_serp", + selected_position: 2, + provider: "UrlbarProviderInputHistory", + results: "search_engine,tab_adaptive_serp", + }, + ]); + }); + + await SpecialPowers.popPrefEnv(); + BrowserTestUtils.removeTab(tab); +}); + +add_task(async function selected_result_tab_serp() { + await SpecialPowers.pushPrefEnv({ + set: [["browser.urlbar.suggest.searches", false]], + }); + + let defaultEngine = await Services.search.getDefault(); + let serpUrl = defaultEngine.getSubmission("test search", null).uri.spec; + let tab = BrowserTestUtils.addTab(gBrowser, serpUrl); + + await doTest(async () => { + await PlacesTestUtils.addVisits(serpUrl); + + await openPopup("test sea"); + await selectRowByProvider("UrlbarProviderPlaces"); + EventUtils.synthesizeKey("KEY_Enter"); + await BrowserTestUtils.waitForCondition(() => gBrowser.selectedTab === tab); + + assertEngagementTelemetry([ + { + selected_result: "tab_serp", + selected_position: 2, + provider: "UrlbarProviderPlaces", + results: "search_engine,tab_serp", + }, + ]); + }); + + await SpecialPowers.popPrefEnv(); + BrowserTestUtils.removeTab(tab); +}); + add_task(async function selected_result_remote_tab() { const remoteTab = await loadRemoteTab("https://example.com"); diff --git a/browser/components/urlbar/tests/engagementTelemetry/browser/head-groups.js b/browser/components/urlbar/tests/engagementTelemetry/browser/head-groups.js @@ -37,6 +37,64 @@ async function doAdaptiveHistoryTest({ trigger, assert }) { await SpecialPowers.popPrefEnv(); } +async function doAdaptiveHistorySerpHistoryTest({ trigger, assert }) { + let defaultEngine = await Services.search.getDefault(); + let serpUrl = defaultEngine.getSubmission("test search", null).uri.spec; + + await doTest(async () => { + await PlacesTestUtils.addVisits(serpUrl); + await UrlbarUtils.addToInputHistory(serpUrl, "test sea"); + + await openPopup("test sea"); + await selectRowByProvider("UrlbarProviderInputHistory"); + + await trigger(); + await assert(); + }); +} + +async function doAdaptiveHistoryBookmarkTest({ trigger, assert }) { + await doTest(async () => { + await PlacesTestUtils.addVisits("https://example.com/test"); + + await PlacesUtils.bookmarks.insert({ + parentGuid: PlacesUtils.bookmarks.unfiledGuid, + url: "https://example.com/test", + title: "bookmark", + }); + + await UrlbarUtils.addToInputHistory("https://example.com/test", "test"); + + await openPopup("test"); + await selectRowByProvider("UrlbarProviderInputHistory"); + + await trigger(); + await assert(); + }); +} + +async function doAdaptiveHistoryBookmarkSerpHistoryTest({ trigger, assert }) { + await doTest(async () => { + let defaultEngine = await Services.search.getDefault(); + let serpUrl = defaultEngine.getSubmission("test search", null).uri.spec; + + await PlacesUtils.bookmarks.insert({ + parentGuid: PlacesUtils.bookmarks.unfiledGuid, + url: serpUrl, + title: "bookmark", + }); + + await PlacesTestUtils.addVisits(serpUrl); + await UrlbarUtils.addToInputHistory(serpUrl, "test"); + + await openPopup("test"); + await selectRowByProvider("UrlbarProviderInputHistory"); + + await trigger(); + await assert(); + }); +} + async function doSearchHistoryTest({ trigger, assert }) { await SpecialPowers.pushPrefEnv({ set: [ @@ -350,6 +408,69 @@ async function doSerpHistoryTest({ trigger, assert }) { }); } +async function doBookmarkSerpHistoryTest({ trigger, assert }) { + await doTest(async () => { + let defaultEngine = await Services.search.getDefault(); + let serpUrl = defaultEngine.getSubmission("test search", null).uri.spec; + + await PlacesUtils.bookmarks.insert({ + parentGuid: PlacesUtils.bookmarks.unfiledGuid, + url: serpUrl, + title: "bookmark", + }); + + await openPopup("test"); + await selectRowByURL(serpUrl); + + await trigger(); + await assert(); + }); +} + +async function doTabAdaptiveTest({ trigger, assert }) { + let visited = PlacesTestUtils.waitForNotification("page-visited", visits => + visits.some(({ url }) => url == "https://example.com/") + ); + let tab = BrowserTestUtils.addTab(gBrowser, "https://example.com/"); + await visited; + + await doTest(async () => { + await PlacesTestUtils.addVisits("https://example.com/"); + await UrlbarUtils.addToInputHistory("https://example.com/", "exa"); + + await openPopup("exa"); + await selectRowByProvider("UrlbarProviderInputHistory"); + + await trigger(); + await assert(); + }); + + BrowserTestUtils.removeTab(tab); +} + +async function doTabAdaptiveSerpHistoryTest({ trigger, assert }) { + let defaultEngine = await Services.search.getDefault(); + const searchUrl = defaultEngine.getSubmission("serp history", null).uri.spec; + let visited = PlacesTestUtils.waitForNotification("page-visited", visits => + visits.some(({ url }) => url == searchUrl) + ); + let tab = BrowserTestUtils.addTab(gBrowser, searchUrl); + await visited; + + await doTest(async () => { + await PlacesTestUtils.addVisits(searchUrl); + await UrlbarUtils.addToInputHistory(searchUrl, "serp"); + + await openPopup("serp"); + await selectRowByURL(searchUrl); + + await trigger(); + await assert(); + }); + + BrowserTestUtils.removeTab(tab); +} + async function doTabSerpHistoryTest({ trigger, assert }) { let defaultEngine = await Services.search.getDefault(); const searchUrl = defaultEngine.getSubmission("serp history", null).uri.spec;