Bug 1765595 - Add a Nimbus variable to load Firefox Suggest suggestions with a different type on RS. r=nanj

This adds a new `quickSuggestRemoteSettingsDataType` Nimbus variable whose value
will be used as the `type` filter when fetching data from remote settings.

Differential Revision: https://phabricator.services.mozilla.com/D145266
This commit is contained in:
Drew Willcoxon 2022-05-03 18:23:56 +00:00
parent 18f85bb221
commit 6c9788ddd7
5 changed files with 80 additions and 7 deletions

View File

@ -353,6 +353,7 @@ const PREF_OTHER_DEFAULTS = new Map([
const NIMBUS_DEFAULTS = {
experimentType: "",
isBestMatchExperiment: false,
quickSuggestRemoteSettingsDataType: "data",
};
// Maps preferences under browser.urlbar.suggest to behavior names, as defined

View File

@ -404,8 +404,8 @@ class QuickSuggest extends EventEmitter {
* The event object passed to the "sync" event listener if you're calling
* this from the listener.
*/
_queueSettingsSync(event = null) {
this._settingsTaskQueue.queue(async () => {
async _queueSettingsSync(event = null) {
await this._settingsTaskQueue.queue(async () => {
// Remove local files of deleted records
if (event?.data?.deleted) {
await Promise.all(
@ -420,9 +420,12 @@ class QuickSuggest extends EventEmitter {
);
}
let dataType = UrlbarPrefs.get("quickSuggestRemoteSettingsDataType");
log.debug("Loading data with type:", dataType);
let [configArray, data] = await Promise.all([
this._rs.get({ filters: { type: "configuration" } }),
this._rs.get({ filters: { type: "data" } }),
this._rs.get({ filters: { type: dataType } }),
this._rs
.get({ filters: { type: "icon" } })
.then(icons =>
@ -435,9 +438,11 @@ class QuickSuggest extends EventEmitter {
this._resultsByKeyword.clear();
log.debug(`Got data with ${data.length} records`);
for (let record of data) {
let { buffer } = await this._rs.attachments.download(record);
let results = JSON.parse(new TextDecoder("utf-8").decode(buffer));
log.debug(`Adding ${results.length} results`);
this._addResults(results);
}
});

View File

@ -204,10 +204,17 @@ class QSTestUtils {
}
/**
* Enrolls in a mock Nimbus rollout.
*
* If you call UrlbarPrefs.updateFirefoxSuggestScenario() from an xpcshell
* test, you must call this first to intialize the Nimbus urlbar feature.
*
* @param {object} value
* Define any desired Nimbus variables in this object.
* @returns {function}
* A cleanup function that will remove the mock rollout.
*/
async initNimbusFeature() {
async initNimbusFeature(value = {}) {
this.info?.("initNimbusFeature awaiting ExperimentManager.onStartup");
await ExperimentManager.onStartup();
@ -217,12 +224,20 @@ class QSTestUtils {
this.info?.("initNimbusFeature awaiting ExperimentFakes.enrollWithRollout");
let doCleanup = await ExperimentFakes.enrollWithRollout({
featureId: NimbusFeatures.urlbar.featureId,
value: { enabled: true },
value: { enabled: true, ...value },
});
this.info?.("initNimbusFeature done");
this.registerCleanupFunction(doCleanup);
this.registerCleanupFunction?.(() => {
// If `doCleanup()` has already been called (i.e., by the caller), it will
// throw an error here.
try {
doCleanup();
} catch (error) {}
});
return doCleanup;
}
/**

View File

@ -167,6 +167,8 @@ const EXPECTED_HTTPS_RESULT = {
},
};
let cleanUpQuickSuggest;
add_task(async function init() {
UrlbarPrefs.set("quicksuggest.enabled", true);
UrlbarPrefs.set("quicksuggest.shouldShowOnboardingDialog", false);
@ -177,7 +179,9 @@ add_task(async function init() {
let engine = await addTestSuggestionsEngine();
await Services.search.setDefault(engine);
await QuickSuggestTestUtils.ensureQuickSuggestInit(REMOTE_SETTINGS_DATA);
cleanUpQuickSuggest = await QuickSuggestTestUtils.ensureQuickSuggestInit(
REMOTE_SETTINGS_DATA
);
});
// Tests with only non-sponsored suggestions enabled with a matching search
@ -1204,3 +1208,48 @@ add_task(async function block() {
await UrlbarProviderQuickSuggest.clearBlockedSuggestions();
});
// Makes sure remote settings data is fetched using the correct `type` based on
// the value of the `quickSuggestRemoteSettingsDataType` Nimbus variable.
add_task(async function remoteSettingsDataType() {
// `QuickSuggestTestUtils.ensureQuickSuggestInit()` stubs
// `UrlbarQuickSuggest._queueSettingsSync()`, which we want to test below, so
// remove the stub by calling the cleanup function it returned.
await cleanUpQuickSuggest();
// We need to spy on `UrlbarQuickSuggest._rs.get()`, but `_rs` is created
// lazily. Set `suggest.quicksuggest.sponsored` to trigger its creation.
UrlbarPrefs.set("suggest.quicksuggest.sponsored", true);
await UrlbarQuickSuggest.readyPromise;
let sandbox = sinon.createSandbox();
let spy = sandbox.spy(UrlbarQuickSuggest._rs, "get");
for (let dataType of [undefined, "test-data-type"]) {
// Set up a mock Nimbus rollout with the data type.
let value = {};
if (dataType) {
value.quickSuggestRemoteSettingsDataType = dataType;
}
let cleanUpNimbus = await QuickSuggestTestUtils.initNimbusFeature(value);
// This call will trigger `UrlbarQuickSuggest._rs.get()`.
await UrlbarQuickSuggest._queueSettingsSync();
let expectedDataType = dataType || "data";
Assert.ok(
spy.calledWith({ filters: { type: expectedDataType } }),
"_rs.get() called with expected data type: " + expectedDataType
);
spy.resetHistory();
await cleanUpNimbus();
}
sandbox.restore();
// Restore the stub for the remainder of the test.
cleanUpQuickSuggest = await QuickSuggestTestUtils.ensureQuickSuggestInit(
REMOTE_SETTINGS_DATA
);
});

View File

@ -103,6 +103,9 @@ urlbar:
type: string
description: >-
Specify the messages/UI variation for QuickSuggest onboarding dialog. This value is case insensitive.
quickSuggestRemoteSettingsDataType:
type: string
description: The `type` of the suggestions data in remote settings. If not specified, "data" is used.
quickSuggestRemoteSettingsEnabled:
type: boolean
fallbackPref: browser.urlbar.quicksuggest.remoteSettings.enabled