Bug 1918307 - Allow keyword exposures to be recorded for a subset of exposure results. r=mak

Depends on D221912

Differential Revision: https://phabricator.services.mozilla.com/D221916
This commit is contained in:
Drew Willcoxon
2024-09-12 23:45:42 +00:00
parent 21dfca244b
commit 405e2eb591
5 changed files with 90 additions and 29 deletions

View File

@@ -1237,12 +1237,13 @@ class TelemetryEvent {
// its update process, but we should record at most one exposure per result.
if (!this.#exposureResults.has(result)) {
this.#exposureResults.add(result);
let resultType = lazy.UrlbarUtils.searchEngagementTelemetryType(result);
this.#exposures.push({
resultType,
weakResult: Cu.getWeakReference(result),
resultType: lazy.UrlbarUtils.searchEngagementTelemetryType(result),
keyword:
lazy.UrlbarPrefs.get("recordKeywordExposures") &&
!queryContext.isPrivate
!queryContext.isPrivate &&
lazy.UrlbarPrefs.get("keywordExposureResults").has(resultType)
? queryContext.trimmedLowerCaseSearchString
: null,
});

View File

@@ -157,6 +157,11 @@ const PREF_URLBAR_DEFAULTS = new Map([
// Whether the results panel should be kept open during IME composition.
["keepPanelOpenDuringImeComposition", false],
// Comma-separated list of result types that should trigger keyword-exposure
// telemetry. Only applies to results with an `exposureTelemetry` value other
// than `NONE`.
["keywordExposureResults", ""],
// As a user privacy measure, don't fetch results from remote services for
// searches that start by pasting a string longer than this. The pref name
// indicates search suggestions, but this is used for all remote results.
@@ -331,10 +336,6 @@ const PREF_URLBAR_DEFAULTS = new Map([
// The maximum number of recent searches we will show.
["recentsearches.maxResults", 5],
// Whether keyword exposures should be recorded for results with an
// `exposureTelemetry` value other than `NONE`.
["recordKeywordExposures", false],
// When true, URLs in the user's history that look like search result pages
// are styled to look like search engine results instead of the usual history
// results.
@@ -1585,6 +1586,7 @@ class Preferences {
: parseFloat(nimbusValue);
}
case "exposureResults":
case "keywordExposureResults":
case "quicksuggest.exposureSuggestionTypes":
return new Set(
this._readPref(pref)

View File

@@ -23,7 +23,7 @@ quick-suggest:
urlbar-keyword-exposure:
description: |
This ping is submitted only when urlbar keyword exposures are enabled. See
the `recordKeywordExposures` urlbar Nimbus variable. When enabled, the ping
the `keywordExposureResults` urlbar Nimbus variable. When enabled, the ping
is submitted at the end of urlbar sessions during which one or more exposure
results are matched. (A "session" begins when the user focuses the urlbar
and ends with an engagement or abandonment.) Exposure results include all

View File

@@ -317,6 +317,54 @@ add_task(async function multiWordKeyword() {
});
});
add_task(async function subset_matched() {
await doTest({
// "history" is in `exposureResults` but not `keywordExposureResults`
exposureResults: "bookmark,history",
keywordExposureResults: "bookmark",
keywords: [{ keyword: "example", resultType: "bookmark" }],
searchStrings: ["example"],
expectedEvents: [
{ extra: { keyword: "example", result: "bookmark", terminal: true } },
],
});
});
add_task(async function subset_notMatched() {
await doTest({
// "history" is in `exposureResults` but not `keywordExposureResults`
exposureResults: "bookmark,history",
keywordExposureResults: "bookmark",
keywords: [{ keyword: "example", resultType: "history" }],
searchStrings: ["example"],
expectedEvents: [],
});
});
add_task(async function superset_matched() {
await doTest({
// "history" is in `keywordExposureResults` but not `exposureResults`
exposureResults: "bookmark",
keywordExposureResults: "bookmark,history",
keywords: [{ keyword: "example", resultType: "bookmark" }],
searchStrings: ["example"],
expectedEvents: [
{ extra: { keyword: "example", result: "bookmark", terminal: true } },
],
});
});
add_task(async function superset_notMatched() {
await doTest({
// "history" is in `keywordExposureResults` but not `exposureResults`
exposureResults: "bookmark",
keywordExposureResults: "bookmark,history",
keywords: [{ keyword: "example", resultType: "history" }],
searchStrings: ["example"],
expectedEvents: [],
});
});
// Smoke test that ends a session with an engagement instead of an abandonment
// as other tasks in this file do.
add_task(async function engagement() {
@@ -365,13 +413,14 @@ async function doTest({
keywords,
searchStrings,
expectedEvents,
exposureResults = "history,bookmark",
keywordExposureResults = exposureResults,
useNimbus = false,
win = window,
endSession = () =>
UrlbarTestUtils.promisePopupClose(win, () => win.gURLBar.blur()),
}) {
// Assume all callers are testing with history and/or bookmarks.
let exposureResults = "history,bookmark";
let resultSourceByType = {
history: UrlbarUtils.RESULT_SOURCE.HISTORY,
bookmark: UrlbarUtils.RESULT_SOURCE.BOOKMARKS,
@@ -422,13 +471,13 @@ async function doTest({
if (useNimbus) {
nimbusCleanup = await UrlbarTestUtils.initNimbusFeature({
exposureResults,
recordKeywordExposures: true,
keywordExposureResults,
});
} else {
await SpecialPowers.pushPrefEnv({
set: [
["browser.urlbar.exposureResults", exposureResults],
["browser.urlbar.recordKeywordExposures", true],
["browser.urlbar.keywordExposureResults", keywordExposureResults],
],
});
}
@@ -477,9 +526,10 @@ async function doTest({
[],
"Sanity check: exposureResults is empty after clearing prefs/uninstalling experiment"
);
Assert.ok(
!UrlbarPrefs.get("recordKeywordExposures"),
"Sanity check: recordKeywordExposures is false after clearing prefs/uninstalling experiment"
Assert.strictEqual(
UrlbarPrefs.get("keywordExposureResults").size,
0,
"Sanity check: keywordExposureResults is empty after clearing prefs/uninstalling experiment"
);
}

View File

@@ -249,6 +249,21 @@ urlbar:
description: >-
The index of Fakespot results within the Firefox Suggest section. A
negative index is relative to the end of the section.
keywordExposureResults:
type: string
setPref:
pref: browser.urlbar.keywordExposureResults
branch: user
description: >-
Comma-separated list of result types that should trigger
keyword-exposure telemetry. Keyword exposures can be recorded along with
result exposures. To enable keyword exposures for a result type, you
must add it both to this variable and to `exposureResults`. The only
exception is the "rust_exposure" result type, which can be added to this
variable even if it's not in `exposureResults` since it's enabled by
setting the `quickSuggestExposureSuggestionTypes` variable. Keyword
exposures are recorded in the `urlbar-keyword-exposure` ping. See that
ping's description for more.
mdnFeatureGate:
type: boolean
setPref:
@@ -285,7 +300,12 @@ urlbar:
pref: browser.urlbar.exposureResults
branch: user
description: >-
Comma-separated list of result type combinations, that are used to determine if an exposure event should be fired.
Comma-separated list of result types that should trigger exposure
telemetry, which is recorded in the `exposure` event. By default
exposure results are visible like usual, but they can be hidden by
setting the `showExposureResults` variable to false. To also record
keyword exposures for a result type, include it in the
`keywordExposureResults` variable as well.
showExposureResults:
type: boolean
setPref:
@@ -366,8 +386,8 @@ urlbar:
telemetry with the "rust_exposure" result type. It's not necessary to
include "rust_exposure" in `exposureResults`. Unless you are testing
other results in the same experiment branch, it's also not necessary to
set `showExposureResults: false`. To also record keyword exposures for
the "rust_exposure" result type, set `recordKeywordExposures: true`.
set `showExposureResults: false`. To also record keyword exposures,
include "rust_exposure" in `keywordExposureResults`.
quickSuggestHideSettingsUI:
type: boolean
fallbackPref: browser.urlbar.quicksuggest.hideSettingsUI
@@ -471,18 +491,6 @@ urlbar:
branch: default
pref: browser.urlbar.recentsearches.maxResults
description: The maximum number of recent searches to show.
recordKeywordExposures:
type: boolean
setPref:
pref: browser.urlbar.recordKeywordExposures
branch: user
description: >-
Whether keyword exposures should be recorded. When enabled, keyword
exposures will be recorded for all results defined in the
`exposureResults` variable. They will also be recorded for the
"rust_exposure" result type if `quickSuggestExposureSuggestionTypes` is
defined. Keyword exposures are recorded in the `urlbar-keyword-exposure`
ping. See that ping's description for more.
recordNavigationalSuggestionTelemetry:
type: boolean
description: Whether to record navigational suggestion telemetry. Defaults to false.