Bug 1938392 - Add integratedSidebar pref to Nimbus. r=shopping-reviewers,firefox-desktop-core-reviewers ,sidebar-reviewers,mossop,Gijs,rking

Adds the integratedSidebar pref to the `shopping2023` Nimbus feature and separates the enabling prefs for the migrated Review Checker in the main sidebar and the Shopping sidebar.

- Updates `browser.shopping.experience2023.integratedSidebar` to be the only enabling pref for the migrated Review Checker sidebar.
- Prevents `browser.shopping.experience2023.enabled` from disabling the migrate sidebar and uses it as the pref for the ShoppingSidebar actors.
- Removes the `browser.shopping.experience2023.shoppingSidebar` pref as it is no longer needed.
- Updates any tests the used these prefs to the new use.
- Init's the two sidebar differently in `ShoppingUtils` based on the Nimbus prefs.
- Unset the `SidebarController._state.command` when a sidebar tool pref sets it to `visible=false` otherwise it will try to re-open when the sidebar is opened again.

Differential Revision: https://phabricator.services.mozilla.com/D242053
This commit is contained in:
Fred Chasen
2025-03-27 00:05:15 +00:00
parent 7e4cb3f680
commit 8fa2242721
17 changed files with 55 additions and 90 deletions

View File

@@ -835,9 +835,8 @@ pref("browser.search.widget.removeAfterDaysUnused", 120);
// capped at 100.
pref("browser.search.totalSearches", 0);
// Enable new experimental shopping features. This is solely intended as a
// rollout/"emergency stop" button - it will go away once the feature has
// rolled out. There will be separate controls for user opt-in/opt-out.
// Enables the Review Checker feature in the Shopping sidebar.
// There are separate controls for user opt-in/opt-out.
pref("browser.shopping.experience2023.enabled", false);
// Ternary int-valued pref indicating if the user has opted into the new
@@ -886,16 +885,11 @@ pref("browser.shopping.experience2023.sidebarClosedCount", 0);
// When conditions are met, shows a prompt on the shopping sidebar asking users if they want to disable auto-open behavior
pref("browser.shopping.experience2023.showKeepSidebarClosedMessage", true);
// Integrates the Review Checker shopping feature into the global sidebar
// shoppingSidebar pref should be opposite of this to disable
// Integrates the Review Checker feature into the global sidebar.
// `enabled` pref should be opposite of this to disable
// the custom shopping sidebar.
pref("browser.shopping.experience2023.integratedSidebar", false);
// Enables showing the Review Checker in the Shopping sidebar.
// integratedSidebar pref should be opposite of this to disable
// the Review Checker sidebar panel.
pref("browser.shopping.experience2023.shoppingSidebar", true);
// If true, users have already seen a card in the Review Checker sidebar panel
// notifying users of the feature's new location and asking if they want to
// move the sidebar to the left or right side. Else if false, users are yet to

View File

@@ -881,7 +881,7 @@ let JSWINDOWACTORS = {
matches: ["about:shoppingsidebar"],
remoteTypes: ["privilegedabout"],
messageManagerGroups: ["shopping-sidebar", "browsers"],
enablePreference: "browser.shopping.experience2023.shoppingSidebar",
enablePreference: "browser.shopping.experience2023.enabled",
},
SpeechDispatcher: {

View File

@@ -41,23 +41,29 @@ export const ShoppingUtils = {
handledAutoActivate: false,
nimbusEnabled: false,
nimbusControl: false,
nimbusIntegratedSidebar: false,
everyWindowCallbackId: `shoppingutils-${Services.uuid.generateUUID()}`,
managers: new WeakMap(),
_updateNimbusVariables() {
this.nimbusIntegratedSidebar =
lazy.NimbusFeatures.shopping2023.getVariable("integratedSidebar");
this.nimbusEnabled =
this.nimbusIntegratedSidebar ||
lazy.NimbusFeatures.shopping2023.getVariable("enabled");
this.nimbusControl =
lazy.NimbusFeatures.shopping2023.getVariable("control");
},
onNimbusUpdate() {
if (this.initialized) {
ShoppingUtils.uninit();
}
this._updateNimbusVariables();
if (this.nimbusEnabled) {
ShoppingUtils.init();
Glean.shoppingSettings.nimbusDisabledShopping.set(false);
} else {
ShoppingUtils.uninit();
Glean.shoppingSettings.nimbusDisabledShopping.set(true);
}
},
@@ -71,7 +77,6 @@ export const ShoppingUtils = {
}
this.onNimbusUpdate = this.onNimbusUpdate.bind(this);
this.onActiveUpdate = this.onActiveUpdate.bind(this);
this.onIntegratedSidebarUpdate = this.onIntegratedSidebarUpdate.bind(this);
this._addManagerForWindow = this._addManagerForWindow.bind(this);
this._removeManagerForWindow = this._removeManagerForWindow.bind(this);
@@ -95,22 +100,17 @@ export const ShoppingUtils = {
this.recordUserAdsPreference();
this.recordUserAutoOpenPreference();
if (this.isAutoOpenEligible()) {
Services.prefs.setBoolPref(ACTIVE_PREF, true);
if (this.nimbusIntegratedSidebar) {
this._addReviewCheckerManagers();
} else {
if (this.isAutoOpenEligible()) {
Services.prefs.setBoolPref(ACTIVE_PREF, true);
}
Services.prefs.addObserver(ACTIVE_PREF, this.onActiveUpdate);
}
Services.prefs.addObserver(ACTIVE_PREF, this.onActiveUpdate);
Services.prefs.addObserver(
INTEGRATED_SIDEBAR_PREF,
this.onIntegratedSidebarUpdate
);
Services.prefs.setIntPref(SIDEBAR_CLOSED_COUNT_PREF, 0);
if (ShoppingUtils.integratedSidebar) {
this._addReviewCheckerManagers();
}
this.initialized = true;
},
@@ -127,11 +127,6 @@ export const ShoppingUtils = {
Services.prefs.removeObserver(ACTIVE_PREF, this.onActiveUpdate);
Services.prefs.removeObserver(
INTEGRATED_SIDEBAR_PREF,
this.onIntegratedSidebarUpdate
);
if (this.managers.size) {
this._removeReviewCheckerManagers();
}

View File

@@ -21,7 +21,6 @@ prefs = [
"toolkit.shopping.ohttpRelayURL=https://example.com/relay", # These URLs don't actually host a relay or gateway config, but are needed to stop us making outside network connections.
"toolkit.shopping.ohttpConfigURL=https://example.com/ohttp-config",
"browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features=false", # Disable the fakespot feature callouts to avoid interference. Individual tests that need them can re-enable them as needed.
"browser.shopping.experience2023.shoppingSidebar=true",
"browser.shopping.experience2023.integratedSidebar=false",
]

View File

@@ -12,7 +12,9 @@ support-files = [
]
prefs = [
"browser.shopping.experience2023.enabled=true",
"sidebar.revamp=true",
"browser.shopping.experience2023.integratedSidebar=true",
"browser.shopping.experience2023.enabled=false",
"browser.shopping.experience2023.optedIn=1",
"browser.shopping.experience2023.ads.enabled=true",
"browser.shopping.experience2023.ads.userEnabled=true",
@@ -22,9 +24,6 @@ prefs = [
"toolkit.shopping.ohttpRelayURL=https://example.com/relay", # These URLs don't actually host a relay or gateway config, but are needed to stop us making outside network connections.
"toolkit.shopping.ohttpConfigURL=https://example.com/ohttp-config",
"browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features=false", # Disable the fakespot feature callouts to avoid interference. Individual tests that need them can re-enable them as needed.
"sidebar.revamp=true",
"browser.shopping.experience2023.shoppingSidebar=false",
"browser.shopping.experience2023.integratedSidebar=true",
"browser.shopping.experience2023.newPositionCard.hasSeen=true",
]

View File

@@ -16,7 +16,7 @@ add_setup(async function setup() {
set: [
["sidebar.revamp", true],
["browser.shopping.experience2023.integratedSidebar", true],
["browser.shopping.experience2023.shoppingSidebar", false],
["browser.shopping.experience2023.enabled", false],
["sidebar.main.tools", "aichat,reviewchecker,syncedtabs,history"],
["toolkit.shopping.ohttpRelayURL", ""],
["toolkit.shopping.ohttpConfigURL", ""],

View File

@@ -49,7 +49,7 @@ add_setup(async function setup() {
set: [
["sidebar.revamp", true],
["browser.shopping.experience2023.integratedSidebar", true],
["browser.shopping.experience2023.shoppingSidebar", false],
["browser.shopping.experience2023.enabled", false],
["sidebar.main.tools", "aichat,reviewchecker,syncedtabs,history"],
["toolkit.shopping.ohttpRelayURL", ""],
["toolkit.shopping.ohttpConfigURL", ""],

View File

@@ -96,7 +96,7 @@ add_setup(async function setup() {
set: [
["sidebar.revamp", true],
["browser.shopping.experience2023.integratedSidebar", true],
["browser.shopping.experience2023.shoppingSidebar", false],
["browser.shopping.experience2023.enabled", false],
["browser.shopping.experience2023.autoOpen.enabled", true],
["browser.shopping.experience2023.autoOpen.userEnabled", true],
["sidebar.main.tools", "aichat,reviewchecker,syncedtabs,history"],

View File

@@ -10,11 +10,11 @@ const PRODUCT_PAGE = "https://example.com/product/Y4YM0Z1LL4";
let verifySidebarPanelNotAdded = async win => {
const { document } = win;
let sidebar = document.querySelector("sidebar-main");
await TestUtils.waitForCondition(
() => sidebar.toolButtons,
"Sidebar tools have been added."
);
let sidebar;
await TestUtils.waitForCondition(() => {
sidebar = document.querySelector("sidebar-main");
return sidebar.toolButtons;
}, "Sidebar tools have been added.");
let reviewCheckerButton = sidebar.shadowRoot.querySelector(
"moz-button[view=viewReviewCheckerSidebar]"
);
@@ -36,8 +36,14 @@ add_task(async function test_bug_1901979_pref_toggle_private_windows() {
verifySidebarPanelNotAdded(privateWindow);
// Flip the prefs to trigger the bug.
Services.prefs.setBoolPref("browser.shopping.experience2023.enabled", false);
Services.prefs.setBoolPref("browser.shopping.experience2023.enabled", true);
Services.prefs.setBoolPref(
"browser.shopping.experience2023.integratedSidebar",
false
);
Services.prefs.setBoolPref(
"browser.shopping.experience2023.integratedSidebar",
true
);
// Verify we still haven't displayed the sidebar.
verifySidebarPanelNotAdded(privateWindow);

View File

@@ -131,7 +131,7 @@ add_setup(async function setup() {
set: [
["sidebar.revamp", true],
["browser.shopping.experience2023.integratedSidebar", true],
["browser.shopping.experience2023.shoppingSidebar", false],
["browser.shopping.experience2023.enabled", false],
["browser.shopping.experience2023.autoOpen.enabled", true],
["browser.shopping.experience2023.autoOpen.userEnabled", true],
["sidebar.main.tools", "aichat,reviewchecker,syncedtabs,history"],

View File

@@ -17,7 +17,7 @@ add_setup(async function setup() {
set: [
["sidebar.revamp", true],
["browser.shopping.experience2023.integratedSidebar", true],
["browser.shopping.experience2023.shoppingSidebar", false],
["browser.shopping.experience2023.enabled", false],
["sidebar.main.tools", "aichat,reviewchecker,syncedtabs,history"],
["toolkit.shopping.ohttpRelayURL", ""],
["toolkit.shopping.ohttpConfigURL", ""],

View File

@@ -16,7 +16,7 @@ add_setup(async function setup() {
set: [
["sidebar.revamp", true],
["browser.shopping.experience2023.integratedSidebar", true],
["browser.shopping.experience2023.shoppingSidebar", false],
["browser.shopping.experience2023.enabled", false],
["sidebar.main.tools", "aichat,reviewchecker,syncedtabs,history"],
["toolkit.shopping.ohttpRelayURL", ""],
["toolkit.shopping.ohttpConfigURL", ""],

View File

@@ -357,6 +357,7 @@ add_task(async function test_onboarding_resets_after_opt_out() {
["browser.shopping.experience2023.survey.pdpVisits", 5],
["browser.shopping.experience2023.survey.optedInTime", time25HrsAgo],
["browser.shopping.experience2023.integratedSidebar", false],
["browser.shopping.experience2023.enabled", true],
],
});
await BrowserTestUtils.withNewTab(
@@ -463,7 +464,7 @@ add_task(
["browser.shopping.experience2023.survey.pdpVisits", 5],
["browser.shopping.experience2023.survey.optedInTime", time25HrsAgo],
["browser.shopping.experience2023.integratedSidebar", true],
["browser.shopping.experience2023.shoppingSidebar", false],
["browser.shopping.experience2023.enabled", false],
],
});
await BrowserTestUtils.withNewTab(

View File

@@ -211,7 +211,7 @@ add_task(async function test_hideOnboarding_onClose() {
await SpecialPowers.pushPrefEnv({
set: [
["browser.shopping.experience2023.integratedSidebar", false],
["browser.shopping.experience2023.shoppingSidebar", true],
["browser.shopping.experience2023.enabled", true],
],
});

View File

@@ -23,19 +23,6 @@ let verifySidebarNotShown = win => {
);
};
let verifySidebarPanelNotAdded = async win => {
const { document } = win;
let sidebar = document.querySelector("sidebar-main");
await TestUtils.waitForCondition(
() => sidebar.toolButtons,
"Sidebar tools have been added."
);
let reviewCheckerButton = sidebar.shadowRoot.querySelector(
"moz-button[view=viewReviewCheckerSidebar]"
);
Assert.equal(reviewCheckerButton, null, "Review Checker should not exist.");
};
add_task(async function test_private_window_disabled() {
let privateWindow = await BrowserTestUtils.openNewBrowserWindow({
private: true,
@@ -76,27 +63,3 @@ add_task(async function test_bug_1901979_pref_toggle_private_windows() {
await BrowserTestUtils.closeWindow(privateWindow);
});
add_task(async function test_private_window_does_not_have_integrated_sidebar() {
await SpecialPowers.pushPrefEnv({
set: [
["sidebar.revamp", true],
["sidebar.verticalTabs", true],
["browser.shopping.experience2023.integratedSidebar", true],
],
});
let privateWindow = await BrowserTestUtils.openNewBrowserWindow({
private: true,
});
let browser = privateWindow.gBrowser.selectedBrowser;
BrowserTestUtils.startLoadingURIString(browser, PRODUCT_PAGE);
await BrowserTestUtils.browserLoaded(browser);
verifySidebarPanelNotAdded(privateWindow);
await BrowserTestUtils.closeWindow(privateWindow);
await SpecialPowers.popPrefEnv();
});

View File

@@ -47,8 +47,12 @@ var SidebarController = {
let switcherMenuitem;
const updateMenus = visible => {
// Hide the sidebar if it is open and should not be visible.
if (!visible && this.isOpen && this.currentID == commandID) {
// Hide the sidebar if it is open and should not be visible,
// and unset the current command and lastOpenedId so they do not
// re-open the next time the sidebar does.
if (!visible && this._state.command == commandID) {
this._state.command = "";
this.lastOpenedId = null;
this.hide();
}

View File

@@ -3600,13 +3600,17 @@ shopping2023:
the shopping feature.
variables:
enabled:
description: True if the experience is enabled (experimental treatment group)
description: True if the shopping sidebar is enabled (experimental treatment group)
type: boolean
fallbackPref: browser.shopping.experience2023.enabled
control:
description: True if the experiment is enabled but experience is disabled (experimental control group)
type: boolean
fallbackPref: browser.shopping.experience2023.control
integratedSidebar:
description: True if the integrated sidebar is enabled.
type: boolean
fallbackPref: browser.shopping.experience2023.integratedSidebar
adsEnabled:
description: True if showing recommended products is enabled
type: boolean