tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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:
Mbrowser/components/preferences/main.inc.xhtml | 18+++++++++++++++++-
Mbrowser/components/preferences/main.js | 182+++++--------------------------------------------------------------------------
Mbrowser/components/preferences/preferences.js | 5-----
Mbrowser/components/preferences/preferences.xhtml | 4----
Mbrowser/components/preferences/widgets/setting-control/setting-control.mjs | 4+---
Mbrowser/components/profiles/tests/browser/browser_preferences.js | 165++-----------------------------------------------------------------------------
Mbrowser/locales/en-US/browser/preferences/preferences.ftl | 26+++-----------------------
Dpython/l10n/fluent_migrations/bug_1992201_preferences_profiles.py | 28----------------------------
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, - ), - )