Bug 1788088 - Correctly record SERP sources when searches are opened in new tabs. r=jteow

Differential Revision: https://phabricator.services.mozilla.com/D243793
This commit is contained in:
Moritz Beier
2025-04-22 16:56:56 +00:00
parent da5b84210f
commit 0817f89625
3 changed files with 182 additions and 29 deletions

View File

@@ -388,13 +388,6 @@
this.telemetrySelectedIndex = -1;
lazy.BrowserSearchTelemetry.recordSearch(
gBrowser.selectedBrowser,
engine,
"searchbar",
details
);
// Record when the user uses the search bar
Services.prefs.setStringPref(
"browser.search.widget.lastUsed",
@@ -413,6 +406,28 @@
params[key] = aParams[key];
}
}
if (aWhere == "tab") {
gBrowser.tabContainer.addEventListener(
"TabOpen",
event =>
lazy.BrowserSearchTelemetry.recordSearch(
event.target.linkedBrowser,
engine,
"searchbar",
details
),
{ once: true }
);
} else {
lazy.BrowserSearchTelemetry.recordSearch(
gBrowser.selectedBrowser,
engine,
"searchbar",
details
);
}
openTrustedLinkIn(submission.uri.spec, aWhere, params);
}

View File

@@ -37,7 +37,7 @@ const TEST_PROVIDER_INFO = [
/**
* Returns the index of the first search suggestion in the urlbar results.
*
* @returns {number} An index, or -1 if there are no search suggestions.
* @returns {Promise<number>} An index, or -1 if there are no search suggestions.
*/
async function getFirstSuggestionIndex() {
const matchCount = UrlbarTestUtils.getResultCount(window);
@@ -80,6 +80,7 @@ add_setup(async function () {
suggest_url:
"https://example.org/browser/browser/components/search/test/browser/searchSuggestionEngine.sjs",
suggest_url_get_params: "query={searchTerms}",
name: "Example",
},
{ setAsDefault: true }
);
@@ -203,6 +204,77 @@ add_task(async function test_source_urlbar() {
);
});
add_task(async function test_source_urlbar_newtab() {
let tab;
await track_ad_click(
"urlbar",
"urlbar",
async () => {
// Load a page because alt doesn't open new tabs on about:newtab.
BrowserTestUtils.startLoadingURIString(
gBrowser.selectedBrowser,
"https://example.com"
);
await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "searchSuggestion",
});
let idx = await getFirstSuggestionIndex();
Assert.greaterOrEqual(idx, 0, "there should be a first suggestion");
while (idx--) {
EventUtils.sendKey("down");
}
let newTabPromise = BrowserTestUtils.waitForNewTab(gBrowser);
EventUtils.synthesizeKey("VK_RETURN", { altKey: true });
tab = await newTabPromise;
return tab;
},
async () => {
BrowserTestUtils.removeTab(tab);
}
);
});
add_task(async function test_source_urlbar_oneoffs_newtab() {
// Enable legacy one off buttons.
await SpecialPowers.pushPrefEnv({
set: [["browser.urlbar.scotchBonnet.enableOverride", false]],
});
let tab;
await track_ad_click(
"urlbar",
"urlbar",
async () => {
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "searchSuggestion",
});
let oneOffs =
UrlbarTestUtils.getOneOffSearchButtons(window).getSelectableButtons(
true
);
let engines = await Services.search.getEngines();
let index = engines.findIndex(e => e.name == "Example");
let newTabPromise = BrowserTestUtils.waitForNewTab(gBrowser);
EventUtils.synthesizeMouseAtCenter(oneOffs[index], {
accelKey: true,
shiftKey: true,
});
tab = await newTabPromise;
return tab;
},
async () => {
BrowserTestUtils.removeTab(tab);
}
);
await SpecialPowers.popPrefEnv();
});
add_task(async function test_source_urlbar_handoff() {
let tab;
await track_ad_click(
@@ -324,6 +396,38 @@ add_task(async function test_source_searchbar() {
);
});
add_task(async function test_source_searchbar_newtab() {
let tab;
await track_ad_click(
"searchbar",
"searchbar",
async () => {
let sb = document.getElementById("searchbar");
// Write the search query in the searchbar.
sb.focus();
sb.value = "searchSuggestion";
sb.textbox.controller.startSearch("searchSuggestion");
// Wait for the popup to show.
await BrowserTestUtils.waitForEvent(sb.textbox.popup, "popupshown");
// And then for the search to complete.
await BrowserTestUtils.waitForCondition(
() =>
sb.textbox.controller.searchStatus >=
Ci.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH,
"The search in the searchbar must complete."
);
let newTabPromise = BrowserTestUtils.waitForNewTab(gBrowser);
EventUtils.synthesizeKey("VK_RETURN", { altKey: true });
tab = await newTabPromise;
return tab;
},
async () => {
BrowserTestUtils.removeTab(tab);
}
);
});
add_task(async function test_source_system() {
let tab;
await track_ad_click(

View File

@@ -720,14 +720,14 @@ export class UrlbarInput {
* Where we expect the result to be opened.
* @property {object} openParams
* The parameters related to where the result will be opened.
* @property {Node} engine
* @property {nsISearchEngine} engine
* The selected one-off's engine.
*/
/**
* Handles an event which would cause a URL or text to be opened.
*
* @param {object} [options]
* @param {object} options
* Options for the navigation.
* @param {Event} [options.event]
* The event triggering the open.
@@ -819,7 +819,21 @@ export class UrlbarInput {
oneOffParams.engine,
searchString
);
this._recordSearch(oneOffParams.engine, event);
if (oneOffParams.openWhere == "tab") {
this.window.gBrowser.tabContainer.addEventListener(
"TabOpen",
tabEvent =>
this._recordSearch(
oneOffParams.engine,
event,
{},
tabEvent.target.linkedBrowser
),
{ once: true }
);
} else {
this._recordSearch(oneOffParams.engine, event);
}
lazy.UrlbarUtils.addToFormHistory(
this,
@@ -1288,7 +1302,24 @@ export class UrlbarInput {
alias: result.payload.keyword,
};
const engine = Services.search.getEngineByName(result.payload.engine);
this._recordSearch(engine, event, actionDetails);
if (where == "tab") {
// The TabOpen event is fired synchronously so tabEvent.target
// is guaranteed to be our new search tab.
this.window.gBrowser.tabContainer.addEventListener(
"TabOpen",
tabEvent =>
this._recordSearch(
engine,
event,
actionDetails,
tabEvent.target.linkedBrowser
),
{ once: true }
);
} else {
this._recordSearch(engine, event, actionDetails);
}
if (!result.payload.inPrivateWindow) {
lazy.UrlbarUtils.addToFormHistory(
@@ -2953,18 +2984,26 @@ export class UrlbarInput {
* The engine to generate the query for.
* @param {Event} event
* The event that triggered this query.
* @param {object} searchActionDetails
* @param {object} [searchActionDetails]
* The details associated with this search query.
* @param {boolean} searchActionDetails.isSuggestion
* @param {boolean} [searchActionDetails.isSuggestion]
* True if this query was initiated from a suggestion from the search engine.
* @param {boolean} searchActionDetails.alias
* @param {boolean} [searchActionDetails.alias]
* True if this query was initiated via a search alias.
* @param {boolean} searchActionDetails.isFormHistory
* @param {boolean} [searchActionDetails.isFormHistory]
* True if this query was initiated from a form history result.
* @param {string} searchActionDetails.url
* @param {string} [searchActionDetails.url]
* The url this query was triggered with.
* @param {XULBrowserElement} [browser]
* The browser where the search is being opened.
* Defaults to the window's selected browser.
*/
_recordSearch(engine, event, searchActionDetails = {}) {
_recordSearch(
engine,
event,
searchActionDetails = {},
browser = this.window.gBrowser.selectedBrowser
) {
const isOneOff = this.view.oneOffSearchButtons.eventTargetIsAOneOff(event);
const searchSource = this.getSearchSource(event);
@@ -2984,7 +3023,7 @@ export class UrlbarInput {
// Sending a trigger to ASRouter when a search happens
lazy.ASRouter.sendTriggerMessage({
browser: this.window.gBrowser.selectedBrowser,
browser,
id: "onSearch",
context: {
isSuggestion: searchActionDetails.isSuggestion || false,
@@ -2993,16 +3032,11 @@ export class UrlbarInput {
},
});
lazy.BrowserSearchTelemetry.recordSearch(
this.window.gBrowser.selectedBrowser,
engine,
searchSource,
{
...searchActionDetails,
isOneOff,
newtabSessionId: this._handoffSession,
}
);
lazy.BrowserSearchTelemetry.recordSearch(browser, engine, searchSource, {
...searchActionDetails,
isOneOff,
newtabSessionId: this._handoffSession,
});
}
/**