Bug 1855375: Basic implementation for Yelp Suggestions r=fluent-reviewers,flod,adw

Differential Revision: https://phabricator.services.mozilla.com/D189335
This commit is contained in:
Daisuke Akatsuka 2024-01-18 15:54:41 +00:00
Родитель 9f649d62fd
Коммит 645131edfa
12 изменённых файлов: 398 добавлений и 0 удалений

Просмотреть файл

@ -641,6 +641,10 @@ pref("browser.urlbar.suggest.addons", true);
// mdn suggestions are turned on.
pref("browser.urlbar.suggest.mdn", true);
// If `browser.urlbar.yelp.featureGate` is true, this controls whether
// Yelp suggestions are turned on.
pref("browser.urlbar.suggest.yelp", true);
// The minimum prefix length of addons keyword the user must type to trigger
// the suggestion. 0 means the min length should be taken from Nimbus.
pref("browser.urlbar.addons.minKeywordLength", 0);

Просмотреть файл

@ -29,6 +29,7 @@ const FEATURES = {
SuggestBackendRust:
"resource:///modules/urlbar/private/SuggestBackendRust.sys.mjs",
Weather: "resource:///modules/urlbar/private/Weather.sys.mjs",
YelpSuggestions: "resource:///modules/urlbar/private/YelpSuggestions.sys.mjs",
};
const TIMESTAMP_TEMPLATE = "%YYYYMMDDHH%";

Просмотреть файл

@ -299,6 +299,13 @@ const PREF_URLBAR_DEFAULTS = new Map([
// recentsearches are turned on.
["suggest.recentsearches", true],
// If `browser.urlbar.yelp.featureGate` is true, this controls whether
// Yelp suggestions are turned on.
["suggest.yelp", true],
// Feature gate pref for Yelp suggestions in the urlbar.
["yelp.featureGate", false],
// JSON'ed array of blocked quick suggest URL digests.
["quicksuggest.blockedDigests", ""],

Просмотреть файл

@ -141,6 +141,12 @@ firefox-suggest-mdn-bottom-text = { -mdn-brand-name }
# $keywordSubstringNotTyped (string) - The part of the suggestion keyword that the user did not yet type
firefox-suggest-pocket-bottom-text = { -pocket-brand-name } · Related to <strong>{ $keywordSubstringTyped }</strong>{ $keywordSubstringNotTyped }
## These strings are used for Yelp suggestions in the urlbar.
# This string is shown in Yelp suggestions and indicates the suggestion is for
# Yelp.
firefox-suggest-yelp-bottom-text = Yelp
## These strings are used in the preferences UI (about:preferences). Their names
## follow the naming conventions of other strings used in the preferences UI.

Просмотреть файл

@ -200,6 +200,10 @@ browser.urlbar.suggest.pocket (boolean, default: true)
If ``browser.urlbar.pocket.featureGate`` is true, this controls whether Pocket
suggestions are turned on. Otherwise they won't be shown.
browser.urlbar.suggest.yelp (boolean, default: true)
If ``browser.urlbar.yelp.featureGate`` is true, this controls whether Yelp
suggestions are turned on. Otherwise they won't be shown.
browser.urlbar.switchTabs.adoptIntoActiveWindow (boolean, default: false)
When using switch to tabs, if set to true this will move the tab into the
active window, instead of just switching to it.

Просмотреть файл

@ -69,6 +69,7 @@ EXTRA_JS_MODULES["urlbar/private"] += [
"private/SuggestBackendJs.sys.mjs",
"private/SuggestBackendRust.sys.mjs",
"private/Weather.sys.mjs",
"private/YelpSuggestions.sys.mjs",
]
TESTING_JS_MODULES += [

Просмотреть файл

@ -0,0 +1,59 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import { BaseFeature } from "resource:///modules/urlbar/private/BaseFeature.sys.mjs";
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
UrlbarPrefs: "resource:///modules/UrlbarPrefs.sys.mjs",
UrlbarResult: "resource:///modules/UrlbarResult.sys.mjs",
UrlbarUtils: "resource:///modules/UrlbarUtils.sys.mjs",
});
/**
* A feature for Yelp suggestions.
*/
export class YelpSuggestions extends BaseFeature {
get shouldEnable() {
return (
lazy.UrlbarPrefs.get("yelpFeatureGate") &&
lazy.UrlbarPrefs.get("suggest.yelp")
);
}
get enablingPreferences() {
return ["suggest.yelp"];
}
get rustSuggestionTypes() {
return ["Yelp"];
}
getSuggestionTelemetryType(suggestion) {
return "yelp";
}
makeResult(queryContext, suggestion, searchString) {
return Object.assign(
new lazy.UrlbarResult(
lazy.UrlbarUtils.RESULT_TYPE.URL,
lazy.UrlbarUtils.RESULT_SOURCE.SEARCH,
...lazy.UrlbarResult.payloadAndSimpleHighlights(queryContext.tokens, {
// TODO: Should define Yelp icon here. Bug 1874624.
url: suggestion.url,
title: suggestion.title,
shouldShowUrl: true,
bottomTextL10n: { id: "firefox-suggest-yelp-bottom-text" },
})
),
{
isBestMatch: true,
suggestedIndex: 1,
isRichSuggestion: true,
richSuggestionIconSize: 24,
}
);
}
}

Просмотреть файл

@ -31,6 +31,8 @@ skip-if = ["os == 'linux' && bits == 64"] # Bug 1773830
["browser_quicksuggest_pocket.js"]
tags = "search-telemetry"
["browser_quicksuggest_yelp.js"]
["browser_telemetry_dynamicWikipedia.js"]
tags = "search-telemetry"

Просмотреть файл

@ -0,0 +1,58 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test for Yelp suggestions.
const REMOTE_SETTINGS_RECORDS = [
{
type: "yelp-suggestions",
attachment: {
subjects: ["ramen"],
preModifiers: ["best"],
postModifiers: ["delivery"],
locationSigns: [{ keyword: "in", needLocation: true }],
},
},
];
add_setup(async function () {
Services.prefs.setBoolPref("browser.search.suggest.enabled", false);
await QuickSuggestTestUtils.ensureQuickSuggestInit({
remoteSettingsRecords: REMOTE_SETTINGS_RECORDS,
prefs: [
["quicksuggest.rustEnabled", true],
["suggest.quicksuggest.nonsponsored", true],
["suggest.yelp", true],
["yelp.featureGate", true],
],
});
});
add_task(async function basic() {
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "RaMeN iN tOkYo",
});
Assert.equal(UrlbarTestUtils.getResultCount(window), 2);
const { result } = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
Assert.equal(
result.providerName,
UrlbarProviderQuickSuggest.name,
"The result should be from the expected provider"
);
Assert.equal(result.payload.provider, "Yelp");
// TODO: After fixing bug 1868922, need to change the value to case-sensitive.
// This value should be "https://www.yelp.com/search?find_desc=RaMeN&find_loc=tOkYo".
Assert.equal(
result.payload.url,
"https://www.yelp.com/search?find_desc=ramen&find_loc=tokyo"
);
// TODO: After fixing bug 1868922, need to change the value to case-sensitive.
// This value should be "RaMeN iN tOkYo".
Assert.equal(result.payload.title, "ramen in tokyo");
});

Просмотреть файл

@ -0,0 +1,248 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Tests Yelp suggestions.
"use strict";
const REMOTE_SETTINGS_RECORDS = [
{
type: "yelp-suggestions",
attachment: {
subjects: ["ramen"],
preModifiers: ["best"],
postModifiers: ["delivery"],
locationSigns: [{ keyword: "in", needLocation: true }],
},
},
];
add_setup(async function () {
Services.prefs.setBoolPref("browser.search.suggest.enabled", false);
await QuickSuggestTestUtils.ensureQuickSuggestInit({
remoteSettingsRecords: REMOTE_SETTINGS_RECORDS,
prefs: [
["quicksuggest.rustEnabled", true],
["suggest.quicksuggest.nonsponsored", true],
["suggest.yelp", true],
["yelp.featureGate", true],
],
});
});
add_task(async function basic() {
const TEST_DATA = [
{
description: "Basic",
query: "best ramen delivery in tokyo",
expected: {
url: "https://www.yelp.com/search?find_desc=best+ramen+delivery&find_loc=tokyo",
title: "best ramen delivery in tokyo",
},
},
{
description: "With upper case",
query: "BeSt RaMeN dElIvErY iN tOkYo",
expected: {
// TODO: After fixing bug 1868922, need to change the value to case-sensitive.
// This value should be "https://www.yelp.com/search?find_desc=BeSt+RaMeN+dElIvErY&find_loc=tOkYo".
url: "https://www.yelp.com/search?find_desc=best+ramen+delivery&find_loc=tokyo",
// TODO: After fixing bug 1868922, need to change the value to case-sensitive.
// This value should be "BeSt RaMeN dElIvErY iN tOkYo".
title: "best ramen delivery in tokyo",
},
},
];
for (let { query, expected } of TEST_DATA) {
info(`Test for ${query}`);
await check_results({
context: createContext(query, {
providers: [UrlbarProviderQuickSuggest.name],
isPrivate: false,
}),
matches: expected ? [makeExpectedResult(expected)] : [],
});
}
});
add_task(async function telemetryType() {
Assert.equal(
QuickSuggest.getFeature("YelpSuggestions").getSuggestionTelemetryType({}),
"yelp",
"Telemetry type should be 'yelp'"
);
});
// When non-sponsored suggestions are disabled, Yelp suggestions should be
// disabled.
add_task(async function nonsponsoredDisabled() {
UrlbarPrefs.set("suggest.quicksuggest.sponsored", false);
// First make sure the suggestion is added when non-sponsored
// suggestions are enabled, if the rust is enabled.
await check_results({
context: createContext("ramen", {
providers: [UrlbarProviderQuickSuggest.name],
isPrivate: false,
}),
matches: [
makeExpectedResult({
url: "https://www.yelp.com/search?find_desc=ramen",
title: "ramen",
}),
],
});
// Now disable the pref.
UrlbarPrefs.set("suggest.quicksuggest.nonsponsored", false);
await check_results({
context: createContext("ramen", {
providers: [UrlbarProviderQuickSuggest.name],
isPrivate: false,
}),
matches: [],
});
UrlbarPrefs.set("suggest.quicksuggest.nonsponsored", true);
UrlbarPrefs.clear("suggest.quicksuggest.sponsored");
await QuickSuggestTestUtils.forceSync();
});
// When Yelp-specific preferences are disabled, suggestions should not be
// added.
add_task(async function yelpSpecificPrefsDisabled() {
const prefs = ["suggest.yelp", "yelp.featureGate"];
for (const pref of prefs) {
// First make sure the suggestion is added, if the rust is enabled.
await check_results({
context: createContext("ramen", {
providers: [UrlbarProviderQuickSuggest.name],
isPrivate: false,
}),
matches: [
makeExpectedResult({
url: "https://www.yelp.com/search?find_desc=ramen",
title: "ramen",
}),
],
});
// Now disable the pref.
UrlbarPrefs.set(pref, false);
await check_results({
context: createContext("ramen", {
providers: [UrlbarProviderQuickSuggest.name],
isPrivate: false,
}),
matches: [],
});
// Revert.
UrlbarPrefs.set(pref, true);
await QuickSuggestTestUtils.forceSync();
}
});
// Check wheather the Yelp suggestions will be shown by the setup of Nimbus
// variable.
add_task(async function nimbus() {
// Disable the fature gate.
UrlbarPrefs.set("yelp.featureGate", false);
await check_results({
context: createContext("ramem", {
providers: [UrlbarProviderQuickSuggest.name],
isPrivate: false,
}),
matches: [],
});
// Enable by Nimbus.
const cleanUpNimbusEnable = await UrlbarTestUtils.initNimbusFeature({
yelpFeatureGate: true,
});
await QuickSuggestTestUtils.forceSync();
await check_results({
context: createContext("ramen", {
providers: [UrlbarProviderQuickSuggest.name],
isPrivate: false,
}),
matches: [
makeExpectedResult({
url: "https://www.yelp.com/search?find_desc=ramen",
title: "ramen",
}),
],
});
await cleanUpNimbusEnable();
// Enable locally.
UrlbarPrefs.set("yelp.featureGate", true);
await QuickSuggestTestUtils.forceSync();
// Disable by Nimbus.
const cleanUpNimbusDisable = await UrlbarTestUtils.initNimbusFeature({
yelpFeatureGate: false,
});
await check_results({
context: createContext("ramen", {
providers: [UrlbarProviderQuickSuggest.name],
isPrivate: false,
}),
matches: [],
});
await cleanUpNimbusDisable();
// Revert.
UrlbarPrefs.set("yelp.featureGate", true);
await QuickSuggestTestUtils.forceSync();
});
// The `Yelp` Rust provider should be passed to the Rust component when
// querying depending on whether Yelp suggestions are enabled.
add_task(async function rustProviders() {
await doRustProvidersTests({
searchString: "ramen",
tests: [
{
prefs: {
"suggest.yelp": true,
},
expectedUrls: ["https://www.yelp.com/search?find_desc=ramen"],
},
{
prefs: {
"suggest.yelp": false,
},
expectedUrls: [],
},
],
});
UrlbarPrefs.clear("suggest.yelp");
await QuickSuggestTestUtils.forceSync();
});
function makeExpectedResult(expected) {
return {
type: UrlbarUtils.RESULT_TYPE.URL,
source: UrlbarUtils.RESULT_SOURCE.SEARCH,
isBestMatch: true,
heuristic: false,
payload: {
source: "rust",
provider: "Yelp",
telemetryType: "yelp",
shouldShowUrl: true,
bottomTextL10n: { id: "firefox-suggest-yelp-bottom-text" },
url: expected.url,
title: expected.title,
displayUrl: expected.url
.replace(/^https:\/\/www[.]/, "")
.replace("%20", " "),
},
};
}

Просмотреть файл

@ -37,6 +37,8 @@ firefox-appdir = "browser"
["test_quicksuggest_topPicks.js"]
["test_quicksuggest_yelp.js"]
["test_rust_ingest.js"]
["test_suggestionsMap.js"]

Просмотреть файл

@ -400,6 +400,12 @@ urlbar:
If neither Nimbus nor remote settings defines a cap, no cap will be
used, and the user will be able to increment the minimum length without
any limit.
yelpFeatureGate:
type: boolean
fallbackPref: browser.urlbar.yelp.featureGate
description: >-
Feature gate that controls whether all aspects of the Yelp suggestion
feature are exposed to the user.
frecency:
description: "The address bar ranking algorithm"