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:
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;