commit 0c5162be20606aa17350019b9147c29cd01da16c
parent 7387ef14c3534dd69cb605bf452bcd14ff9108e1
Author: agoloman <agoloman@mozilla.com>
Date: Sat, 22 Nov 2025 04:23:14 +0200
Revert "Bug 1992201 - Add settings sub-pane for profiles, including copy feature r=profiles-reviewers,fluent-reviewers,desktop-theme-reviewers,bolsson,hjones,niklas" for causing multiple bc leaks.
This reverts commit 97e64235a90fbc419f59ef6be100c818d947661f.
Diffstat:
8 files changed, 35 insertions(+), 397 deletions(-)
diff --git a/browser/components/preferences/main.inc.xhtml b/browser/components/preferences/main.inc.xhtml
@@ -47,7 +47,23 @@
<!-- Profiles -->
<groupbox id="profilesGroup" data-category="paneGeneral" hidden="true">
- <html:setting-group groupid="profiles" data-category="paneGeneral"></html:setting-group>
+ <label><html:h2 data-l10n-id="preferences-profiles-header"/></label>
+
+ <hbox id="profiles" flex="1">
+ <description flex="1" class="description-deemphasized" control="manage-profiles">
+ <html:span data-l10n-id="preferences-manage-profiles-description"></html:span>
+ <html:a
+ is="moz-support-link"
+ id="profile-management-learn-more"
+ support-page="profile-management"
+ data-l10n-id="preferences-manage-profiles-learn-more"
+ />
+ </description>
+ <button id="manage-profiles"
+ is="highlightable-button"
+ class="accessory-button"
+ data-l10n-id="preferences-manage-profiles-button"/>
+ </hbox>
</groupbox>
<!-- Tab preferences -->
diff --git a/browser/components/preferences/main.js b/browser/components/preferences/main.js
@@ -634,120 +634,6 @@ Preferences.addSetting({
onUserClick: () => gMainPane.showConnections(),
});
-Preferences.addSetting({
- id: "profilesPane",
- onUserClick(e) {
- e.preventDefault();
- gotoPref("paneProfiles");
- },
-});
-Preferences.addSetting({
- id: "profilesSettings",
- visible() {
- return SelectableProfileService.isEnabled;
- },
- onUserClick: e => {
- e.preventDefault();
- gotoPref("profiles");
- },
-});
-Preferences.addSetting({
- id: "manageProfiles",
- onUserClick: e => {
- e.preventDefault();
- // Using the existing function for now, since privacy.js also calls it
- gMainPane.manageProfiles();
- },
-});
-Preferences.addSetting({
- id: "copyProfile",
- deps: ["copyProfileSelect"],
- disabled: ({ copyProfileSelect }) => !copyProfileSelect.value,
- onUserClick: (e, { copyProfileSelect }) => {
- e.preventDefault();
- SelectableProfileService.getProfile(copyProfileSelect.value).then(
- profile => {
- profile?.copyProfile();
- copyProfileSelect.config.set("");
- }
- );
- },
-});
-Preferences.addSetting({
- id: "copyProfileBox",
- visible: () => SelectableProfileService.initialized,
-});
-Preferences.addSetting({
- id: "copyProfileError",
- _hasError: false,
- setup(emitChange) {
- this.emitChange = emitChange;
- },
- visible() {
- return this._hasError;
- },
- setError(value) {
- this._hasError = !!value;
- this.emitChange();
- },
-});
-Preferences.addSetting(
- class ProfileList extends Preferences.AsyncSetting {
- static id = "profileList";
- static PROFILE_UPDATED_OBS = "sps-profiles-updated";
- async setup() {
- let emitChange = () => this.emitChange();
- Services.obs.addObserver(emitChange, ProfileList.PROFILE_UPDATED_OBS);
- return () => {
- Services.obs.removeObserver(
- emitChange,
- ProfileList.PROFILE_UPDATED_OBS
- );
- };
- }
-
- async get() {
- let profiles = await SelectableProfileService.getAllProfiles();
- return profiles;
- }
- }
-);
-Preferences.addSetting({
- id: "copyProfileSelect",
- deps: ["profileList"],
- _selectedProfile: null,
- setup(emitChange) {
- this.emitChange = emitChange;
- document.l10n
- .formatValue("preferences-copy-profile-select")
- .then(result => (this.placeholderString = result));
- },
- get() {
- return this._selectedProfile;
- },
- set(inputVal) {
- this._selectedProfile = inputVal;
- this.emitChange();
- },
- getControlConfig(config, { profileList }) {
- config.options = profileList.value.map(profile => {
- return { controlAttrs: { label: profile.name }, value: profile.id };
- });
-
- // Put the placeholder at the front of the list.
- config.options.unshift({
- controlAttrs: { label: this.placeholderString },
- value: "",
- });
-
- return config;
- },
-});
-Preferences.addSetting({
- id: "copyProfileHeader",
- visible: () => SelectableProfileService.initialized,
-});
-
// Downloads
/*
* Preferences:
@@ -1626,62 +1512,6 @@ SettingGroupManager.registerGroups({
},
],
},
- profilePane: {
- headingLevel: 2,
- id: "browserProfilesGroupPane",
- l10nId: "preferences-profiles-subpane-description",
- supportPage: "profile-management",
- items: [
- {
- id: "manageProfiles",
- control: "moz-box-button",
- l10nId: "preferences-manage-profiles-button",
- },
- {
- id: "copyProfileHeader",
- l10nId: "preferences-copy-profile-header",
- headingLevel: 2,
- supportPage: "profile-management",
- control: "moz-fieldset",
- items: [
- {
- id: "copyProfileBox",
- l10nId: "preferences-profile-to-copy",
- control: "moz-box-item",
- items: [
- {
- id: "copyProfileSelect",
- control: "moz-select",
- slot: "actions",
- },
- {
- id: "copyProfile",
- l10nId: "preferences-copy-profile-button",
- control: "moz-button",
- slot: "actions",
- controlAttrs: {
- type: "primary",
- },
- },
- ],
- },
- ],
- },
- ],
- },
- profiles: {
- id: "profilesGroup",
- l10nId: "preferences-profiles-section-header",
- headingLevel: 2,
- supportPage: "profile-management",
- items: [
- {
- id: "profilesSettings",
- control: "moz-box-button",
- l10nId: "preferences-profiles-settings-button",
- },
- ],
- },
startup: {
items: [
{
@@ -3024,8 +2854,6 @@ var gMainPane = {
initSettingGroup("startup");
initSettingGroup("networkProxy");
initSettingGroup("tabs");
- initSettingGroup("profiles");
- initSettingGroup("profilePane");
setEventListener("manageBrowserLanguagesButton", "command", function () {
gMainPane.showBrowserLanguagesSubDialog({ search: false });
@@ -3094,6 +2922,16 @@ var gMainPane = {
document.getElementById("dataMigrationGroup").remove();
}
+ if (!SelectableProfileService.isEnabled) {
+ // Don't want to rely on .hidden for the toplevel groupbox because
+ // of the pane hiding/showing code potentially interfering:
+ document
+ .getElementById("profilesGroup")
+ .setAttribute("style", "display: none !important");
+ } else {
+ setEventListener("manage-profiles", "command", gMainPane.manageProfiles);
+ }
+
// Initializes the fonts dropdowns displayed in this pane.
this._rebuildFonts();
diff --git a/browser/components/preferences/preferences.js b/browser/components/preferences/preferences.js
@@ -281,11 +281,6 @@ const CONFIG_PANES = Object.freeze({
l10nId: "autofill-payment-methods-manage-payments-title",
groupIds: ["managePayments"],
},
- paneProfiles: {
- parent: "general",
- l10nId: "preferences-profiles-group-header",
- groupIds: ["profilePane"],
- },
});
var gLastCategory = { category: undefined, subcategory: undefined };
diff --git a/browser/components/preferences/preferences.xhtml b/browser/components/preferences/preferences.xhtml
@@ -202,10 +202,6 @@
<richlistitem
class="category hidden-category"
- value="paneProfiles"/>
-
- <richlistitem
- class="category hidden-category"
value="paneTranslations"/>
</richlistbox>
diff --git a/browser/components/preferences/widgets/setting-control/setting-control.mjs b/browser/components/preferences/widgets/setting-control/setting-control.mjs
@@ -367,9 +367,7 @@ export class SettingControl extends SettingElement {
.config=${item.config}
.setting=${item.setting}
.getSetting=${this.getSetting}
- slot=${ifDefined(
- item.config.slot || ITEM_SLOT_BY_PARENT.get(control)
- )}
+ slot=${ifDefined(ITEM_SLOT_BY_PARENT.get(control))}
></setting-control>`
);
}
diff --git a/browser/components/profiles/tests/browser/browser_preferences.js b/browser/components/profiles/tests/browser/browser_preferences.js
@@ -7,7 +7,6 @@ const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
ClientID: "resource://gre/modules/ClientID.sys.mjs",
TelemetryUtils: "resource://gre/modules/TelemetryUtils.sys.mjs",
- sinon: "resource://testing-common/Sinon.sys.mjs",
});
// Note: copied from preferences head.js. We can remove this when we migrate
@@ -91,17 +90,6 @@ function promiseLoadSubDialog(aURL) {
});
}
-// Note: copied from preferences head.js. We can remove this when we migrate
-// this test into that component.
-async function waitForPaneChange(paneId) {
- let doc = gBrowser.selectedBrowser.contentDocument;
- let event = await BrowserTestUtils.waitForEvent(doc, "paneshown");
- let expectId = paneId.startsWith("pane")
- ? paneId
- : `pane${paneId[0].toUpperCase()}${paneId.substring(1)}`;
- is(event.detail.category, expectId, "Loaded the correct pane");
-}
-
add_task(async function testHiddenWhenDisabled() {
await SpecialPowers.pushPrefEnv({
set: [["browser.profiles.enabled", false]],
@@ -126,7 +114,6 @@ add_task(async function testEnabled() {
leaveOpen: true,
});
let doc = gBrowser.contentDocument;
- let win = doc.ownerGlobal;
// Verify the profiles section is shown when enabled.
let profilesCategory = doc.getElementById("profilesGroup");
@@ -135,166 +122,22 @@ add_task(async function testEnabled() {
ok(BrowserTestUtils.isVisible(profilesCategory), "The category is visible");
// Verify the Learn More link exists and points to the right place.
- let profilesSettingGroup = doc.querySelector(
- "setting-group[groupid='profiles']"
- ).firstElementChild;
- let learnMore = profilesSettingGroup.shadowRoot.querySelector(
- "a[is='moz-support-link']"
- );
+ let learnMore = doc.getElementById("profile-management-learn-more");
Assert.equal(
"http://127.0.0.1:8888/support-dummy/profile-management",
learnMore.href,
"Learn More link should have expected URL"
);
- // Verify that clicking the button opens the expected subpane.
- let profilesSubPane = doc.querySelector(
- "setting-pane[data-category='paneProfiles']"
- );
- ok(
- !BrowserTestUtils.isVisible(profilesSubPane),
- "Profiles subpane should be hidden"
- );
- let paneLoaded = waitForPaneChange("profiles");
- let subPaneButton = profilesSettingGroup.querySelector("#profilesSettings");
- subPaneButton.scrollIntoView();
- EventUtils.synthesizeMouseAtCenter(subPaneButton, {}, win);
- await paneLoaded;
- ok(
- BrowserTestUtils.isVisible(profilesSubPane),
- "Profiles subpane should be visible"
- );
- await profilesSubPane.updateComplete;
-
- BrowserTestUtils.removeTab(gBrowser.selectedTab);
-});
-
-add_task(async function subpaneContentsWithOneProfile() {
- await openPreferencesViaOpenPreferencesAPI("paneGeneral", {
- leaveOpen: true,
- });
- let doc = gBrowser.contentDocument;
- let win = doc.ownerGlobal;
-
- let paneLoaded = waitForPaneChange("profiles");
- win.gotoPref("paneProfiles");
- await paneLoaded;
-
- let profilesSubPane = doc.querySelector(
- "setting-pane[data-category='paneProfiles']"
- );
- await profilesSubPane.updateComplete;
-
- Assert.equal(
- "preferences-profiles-group-header",
- profilesSubPane
- .querySelector("moz-page-header")
- .getAttribute("data-l10n-id"),
- "Subpane should have expected heading l10nId"
- );
-
- let manageProfilesButton = profilesSubPane.querySelector("#manageProfiles");
- ok(
- BrowserTestUtils.isVisible(manageProfilesButton),
- "Manage profiles button should be visible"
- );
-
- let copyProfilesSection = profilesSubPane.querySelector("#copyProfileHeader");
- ok(
- !BrowserTestUtils.isVisible(copyProfilesSection),
- "Until we create a second profile, the copy section should be hidden"
- );
-
- // Verify the manage profiles button opens the correct subdialog.
- manageProfilesButton.scrollIntoView();
+ // Verify that clicking the button shows the manage screen in a subdialog.
let promiseSubDialogLoaded = promiseLoadSubDialog("about:profilemanager");
- EventUtils.synthesizeMouseAtCenter(manageProfilesButton, {}, win);
+ let profilesButton = doc.getElementById("manage-profiles");
+ profilesButton.click();
await promiseSubDialogLoaded;
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
-add_task(async function copyProfile() {
- // Add an additional profile, then load the subpane, and the copy section should be visible.
- await initGroupDatabase();
- await SelectableProfileService.createNewProfile(false);
-
- await openPreferencesViaOpenPreferencesAPI("paneGeneral", {
- leaveOpen: true,
- });
- let doc = gBrowser.contentDocument;
- let win = doc.ownerGlobal;
-
- let paneLoaded = waitForPaneChange("profiles");
- win.gotoPref("paneProfiles");
- await paneLoaded;
- let profilesSubPane = doc.querySelector(
- "setting-pane[data-category='paneProfiles']"
- );
- await profilesSubPane.updateComplete;
-
- let manageProfilesButton = profilesSubPane.querySelector("#manageProfiles");
- ok(
- BrowserTestUtils.isVisible(manageProfilesButton),
- "Manage profiles button should be visible"
- );
-
- let copyProfilesSection = profilesSubPane.querySelector("#copyProfileHeader");
- ok(
- BrowserTestUtils.isVisible(copyProfilesSection),
- "Copy profile section should be visible"
- );
-
- let profilesCopyButton = copyProfilesSection.querySelector("#copyProfile");
- let profilesSelect = copyProfilesSection.querySelector("#copyProfileSelect");
- ok(
- profilesCopyButton.disabled,
- "Initially the copy button should be disabled"
- );
- ok(!profilesSelect.value, "Initially the select value should be unset");
- Assert.equal(
- profilesSelect.options.length,
- 3,
- "Both profiles and the placeholder should be in the options list"
- );
- Assert.equal(
- profilesSelect.options[1].label,
- "Original profile",
- "The first profile should be listed"
- );
- Assert.equal(
- profilesSelect.options[2].label,
- "Profile 1",
- "The second profile should be listed"
- );
-
- profilesSelect.value = "1";
- profilesSelect.dispatchEvent(new win.Event("change", { bubbles: true }));
- await profilesCopyButton.updateComplete;
- ok(
- !profilesCopyButton.disabled,
- "When a profile is selected, the copy button should be enabled"
- );
-
- let copyCalled = false;
- let mockGetProfile = lazy.sinon
- .stub(SelectableProfileService, "getProfile")
- .resolves({
- copyProfile: () => (copyCalled = true),
- });
- profilesCopyButton.scrollIntoView();
- EventUtils.synthesizeMouseAtCenter(profilesCopyButton, {}, win);
- await profilesSelect.updateComplete;
- ok(copyCalled, "The profile copy method should have been called");
- ok(
- !profilesSelect.value,
- "After copy, select value should be reset to empty value"
- );
-
- mockGetProfile.restore();
- BrowserTestUtils.removeTab(gBrowser.selectedTab);
-});
-
// Tests for the small addition to the privacy section
add_task(async function testPrivacyInfoEnabled() {
ok(SelectableProfileService.isEnabled, "service should be enabled");
diff --git a/browser/locales/en-US/browser/preferences/preferences.ftl b/browser/locales/en-US/browser/preferences/preferences.ftl
@@ -177,31 +177,11 @@ preferences-data-migration-button =
.label = Import Data
.accesskey = m
-preferences-profiles-group-header =
- .heading = Profiles
-preferences-profiles-subpane-description =
- .description = Each profile has separate browsing data and settings, including history, passwords, and more.
-preferences-profiles-section-header =
- .label = Profiles
- .description = Each profile has separate browsing data and settings, including history, passwords, and more.
+preferences-profiles-header = Profiles
+preferences-manage-profiles-description = Each profile has separate browsing data and settings, including history, passwords, and more.
+preferences-manage-profiles-learn-more = Learn more
preferences-manage-profiles-button =
.label = Manage Profiles
-preferences-profiles-settings-button =
- .label = Settings
-# This string labels the entire copy profile section in the profiles sub-pane.
-preferences-copy-profile-header =
- .label = Copy an existing profile
- .description = The new profile will copy your settings, add-ons, history, and saved data like bookmarks and passwords — but not your account or sync info.
-# This string sits next to the copy controls, both the copy-profile-select
-# drop-down and the copy-profile-button, so that the user understands they
-# need to first pick a profile to copy, and then click the copy button.
-preferences-profile-to-copy =
- .label = Profile to copy
-# This string is a placeholder that will be shown in a drop-down list of
-# profiles. The user will select a profile, then click the copy button
-# to make a copy of that profile.
-preferences-copy-profile-select = Select profile
-preferences-copy-profile-button = Copy
tabs-group-header2 =
.label = Tabs
diff --git a/python/l10n/fluent_migrations/bug_1992201_preferences_profiles.py b/python/l10n/fluent_migrations/bug_1992201_preferences_profiles.py
@@ -1,28 +0,0 @@
-# Any copyright is dedicated to the Public Domain.
-# http://creativecommons.org/publicdomain/zero/1.0/
-
-from fluent.migrate import COPY_PATTERN
-from fluent.migrate.helpers import transforms_from
-
-
-def migrate(ctx):
- """Bug 1992201 - Add settings sub-pane for profiles, part {index}."""
- source = "browser/browser/preferences/preferences.ftl"
- target = source
-
- ctx.add_transforms(
- target,
- source,
- transforms_from(
- """
-preferences-profiles-group-header =
- .heading = {COPY_PATTERN(from_path, "preferences-profiles-header")}
-preferences-profiles-subpane-description =
- .description = {COPY_PATTERN(from_path, "preferences-manage-profiles-description")}
-preferences-profiles-section-header =
- .label = {COPY_PATTERN(from_path, "preferences-profiles-header")}
- .description = {COPY_PATTERN(from_path, "preferences-manage-profiles-description")}
-""",
- from_path=source,
- ),
- )