tor-browser

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

commit d675f72925235c31495d00146b8d404aa2b8de2a
parent 224aca34f75894f977596fb4fb711d8ce9554727
Author: Tanvi Manku <tanvi.manku@gmail.com>
Date:   Tue, 16 Dec 2025 02:05:29 +0000

Bug 2001254 - Create a subpage for managing addresses. r=dimi,fluent-reviewers,mkennedy,akulyk,desktop-theme-reviewers,flod,mtigley,hjones

Differential Revision: https://phabricator.services.mozilla.com/D273365

Diffstat:
Mbrowser/components/preferences/main.js | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mbrowser/components/preferences/preferences.js | 5+++++
Mbrowser/extensions/formautofill/content/manageDialog.mjs | 13++++---------
Mbrowser/locales/en-US/browser/preferences/preferences.ftl | 38+++++++++++++++++++++++++++++---------
Mbrowser/themes/shared/preferences/preferences.css | 5+++++
Mtoolkit/components/formautofill/FormAutofillPreferences.sys.mjs | 150+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
6 files changed, 285 insertions(+), 23 deletions(-)

diff --git a/browser/components/preferences/main.js b/browser/components/preferences/main.js @@ -1785,6 +1785,85 @@ Preferences.addSetting({ }, }); +Preferences.addSetting({ + /** @type {{ _removeAddressDialogStrings: string[] } & SettingConfig} */ + id: "address-item", + _removeAddressDialogStrings: [], + onUserClick(e) { + const action = e.target.getAttribute("action"); + const guid = e.target.getAttribute("guid"); + if (action === "remove") { + let [title, confirm, cancel] = this._removeAddressDialogStrings; + FormAutofillPreferences.prototype.openRemoveAddressDialog( + guid, + window.browsingContext.topChromeWindow.browsingContext, + title, + confirm, + cancel + ); + } else if (action === "edit") { + FormAutofillPreferences.prototype.openEditAddressDialog(guid, window); + } + }, + setup(emitChange) { + document.l10n + .formatValues([ + { id: "addresses-delete-address-prompt-title" }, + { id: "addresses-delete-address-prompt-confirm-button" }, + { id: "addresses-delete-address-prompt-cancel-button" }, + ]) + .then(val => (this._removeAddressDialogStrings = val)) + .then(emitChange); + }, + disabled() { + return !!this._removeAddressDialogStrings.length; + }, +}); + +Preferences.addSetting({ + id: "add-address-button", + deps: ["saveAndFillAddresses"], + onUserClick: () => { + FormAutofillPreferences.prototype.openEditAddressDialog(undefined, window); + }, + disabled: ({ saveAndFillAddresses }) => !saveAndFillAddresses.value, +}); + +Preferences.addSetting({ + id: "addresses-list-header", +}); + +Preferences.addSetting( + class extends Preferences.AsyncSetting { + static id = "addresses-list"; + + async getAddresses() { + await FormAutofillPreferences.prototype.initializeAddressesStorage(); + return FormAutofillPreferences.prototype.makeAddressesListItems(); + } + + async getControlConfig() { + return { + items: await this.getAddresses(), + }; + } + + setup() { + Services.obs.addObserver(this.emitChange, "formautofill-storage-changed"); + return () => + Services.obs.removeObserver( + this.emitChange, + "formautofill-storage-changed" + ); + } + + async visible() { + const items = await this.getAddresses(); + return !!items.length; + } + } +); + SettingGroupManager.registerGroups({ containers: { // This section is marked as in progress for testing purposes @@ -3109,9 +3188,7 @@ SettingGroupManager.registerGroups({ { id: "payments-list", control: "moz-box-group", - l10nId: "payments-list-header", controlAttrs: { - hasHeader: true, type: "list", }, }, @@ -3323,6 +3400,22 @@ SettingGroupManager.registerGroups({ }, ], }, + manageAddresses: { + items: [ + { + id: "add-address-button", + control: "moz-button", + l10nId: "autofill-addresses-add-button", + }, + { + id: "addresses-list", + control: "moz-box-group", + controlAttrs: { + type: "list", + }, + }, + ], + }, sync: { inProgress: true, l10nId: "sync-group-label", diff --git a/browser/components/preferences/preferences.js b/browser/components/preferences/preferences.js @@ -291,6 +291,11 @@ const CONFIG_PANES = Object.freeze({ l10nId: "preferences-etp-header", groupIds: ["etpBanner", "etpAdvanced"], }, + manageAddresses: { + parent: "privacy", + l10nId: "autofill-addresses-manage-addresses-title", + groupIds: ["manageAddresses"], + }, }); var gLastCategory = { category: undefined, subcategory: undefined }; diff --git a/browser/extensions/formautofill/content/manageDialog.mjs b/browser/extensions/formautofill/content/manageDialog.mjs @@ -2,8 +2,6 @@ * 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/. */ -const EDIT_ADDRESS_URL = "chrome://formautofill/content/editAddress.xhtml"; - const { AppConstants } = ChromeUtils.importESModule( "resource://gre/modules/AppConstants.sys.mjs" ); @@ -336,13 +334,10 @@ export class ManageAddresses extends ManageRecords { * @param {object} address [optional] */ openEditDialog(address) { - this.prefWin.gSubDialog.open(EDIT_ADDRESS_URL, undefined, { - record: address, - // Don't validate in preferences since it's fine for fields to be missing - // for autofill purposes. For PaymentRequest addresses get more validation. - noValidate: true, - l10nStrings: ManageAddresses.getAddressL10nStrings(), - }); + return lazy.FormAutofillPreferences.openEditAddressDialog( + address, + this.prefWin + ); } getLabelInfo(address) { diff --git a/browser/locales/en-US/browser/preferences/preferences.ftl b/browser/locales/en-US/browser/preferences/preferences.ftl @@ -1341,10 +1341,19 @@ autofill-reauth-payment-methods-checkbox-2 = autofill-payment-methods-add-button = Add new payment method payments-list-header = .label = Payment methods -payments-list-item-label = <strong>Payment methods</strong> payments-delete-payment-prompt-title = Delete this payment method? payments-delete-payment-prompt-confirm-button = Delete payments-delete-payment-prompt-cancel-button = Cancel + +# These values are displayed for each credit card record listed on the Manage Payment methods +# settings page. +# Variables: +# $cardNumber (string) - The obscured credit card number (for example: 2423 *********) +# $expDate (string) - The obscured expiry date of the credit card (for example: XX/2027) +payment-moz-box-item = + .label = { $cardNumber } + .description = { $expDate } + autofill-addresses-title = Addresses and more autofill-addresses-header = .aria-label = Addresses and more @@ -1354,15 +1363,26 @@ autofill-addresses-checkbox-message = autofill-addresses-manage-addresses-button = .label = Manage addresses and more .accesskey = M - -# These values are displayed for each credit card record listed on the Manage Payment methods -# settings page. +addresses-list-header = + .label = Addresses +addreses-delete-address-button-label = + .aria-label = Delete +addreses-edit-address-button-label = + .aria-label = Edit +addresses-delete-address-prompt-title = Delete this address? +addresses-delete-address-prompt-confirm-button = Delete +addresses-delete-address-prompt-cancel-button = Cancel +autofill-addresses-add-button = Add new address +autofill-addresses-manage-addresses-title = + .heading = Manage addresses and more + +# These values are displayed for each address record listed on the "Manage addresses and more" subpage. # Variables: -# $cardNumber (string) - The obscured credit card number (for example: 2423 *********) -# $expDate (string) - The obscured expiry date of the credit card (for example: XX/2027) -payment-moz-box-item = - .label = { $cardNumber } - .description = { $expDate } +# $name (string) - The name associated with the address +# $address (string) - The address +address-moz-box-item = + .label = { $name } + .description = { $address } ## Privacy Section - History diff --git a/browser/themes/shared/preferences/preferences.css b/browser/themes/shared/preferences/preferences.css @@ -1529,3 +1529,8 @@ setting-group[groupid="home"] { #etpLevelWarning { --promo-image-position: top; } + +#addresses-list-header, +#payments-list-header { + --box-label-font-weight: var(--heading-font-weight); +} diff --git a/toolkit/components/formautofill/FormAutofillPreferences.sys.mjs b/toolkit/components/formautofill/FormAutofillPreferences.sys.mjs @@ -8,6 +8,7 @@ const MANAGE_ADDRESSES_URL = "chrome://formautofill/content/manageAddresses.xhtml"; +const EDIT_ADDRESS_URL = "chrome://formautofill/content/editAddress.xhtml"; const MANAGE_CREDITCARDS_URL = "chrome://formautofill/content/manageCreditCards.xhtml"; const EDIT_CREDIT_CARD_URL = @@ -20,6 +21,7 @@ const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { OSKeyStore: "resource://gre/modules/OSKeyStore.sys.mjs", formAutofillStorage: "resource://autofill/FormAutofillStorage.sys.mjs", + ManageAddresses: "chrome://formautofill/content/manageDialog.mjs", }); ChromeUtils.defineLazyGetter( @@ -137,8 +139,13 @@ export class FormAutofillPreferences { id: "savedAddressesButton", pref: null, visible: () => FormAutofill.isAutofillAddressesAvailable, - onUserClick: ({ target }) => { - target.ownerGlobal.gSubDialog.open(MANAGE_ADDRESSES_URL); + onUserClick: e => { + e.preventDefault(); + if (Services.prefs.getBoolPref("browser.settings-redesign.enabled")) { + e.target.ownerGlobal.gotoPref("paneManageAddresses"); + } else { + e.target.ownerGlobal.gSubDialog.open(MANAGE_ADDRESSES_URL); + } }, }); @@ -197,6 +204,10 @@ export class FormAutofillPreferences { await lazy.formAutofillStorage.initialize(); } + async initializeAddressesStorage() { + await lazy.formAutofillStorage.initialize(); + } + async trySetOSAuthEnabled(win, checked) { let messageText = await lazy.l10n.formatValueSync( "autofill-creditcard-os-dialog-message" @@ -280,7 +291,76 @@ export class FormAutofillPreferences { { id: "payments-list-header", control: "moz-box-item", - l10nId: "payments-list-item-label", + l10nId: "payments-list-header", + slot: "header", + }, + ...items, + ]; + } + + async makeAddressesListItems() { + const addresses = await lazy.formAutofillStorage.addresses.getAll(); + const records = addresses.slice().reverse(); + + if (!records.length) { + return []; + } + + const items = records.map(record => { + const addressFormatted = [ + record["street-address"], + record["address-level2"], + record["address-level1"], + record.country, + record["postal-code"], + ] + .filter(Boolean) + .join(", "); + + const config = { + id: "address-item", + control: "moz-box-item", + l10nId: "address-moz-box-item", + iconSrc: "chrome://browser/skin/notification-icons/geo.svg", + l10nArgs: { + name: `${record.name}`, + address: addressFormatted, + }, + options: [ + { + control: "moz-button", + iconSrc: "chrome://global/skin/icons/delete.svg", + type: "icon", + l10nId: "addreses-delete-address-button-label", + controlAttrs: { + slot: "actions", + action: "remove", + guid: record.guid, + }, + }, + { + control: "moz-button", + iconSrc: "chrome://global/skin/icons/edit.svg", + type: "icon", + l10nId: "addreses-edit-address-button-label", + controlAttrs: { + slot: "actions", + action: "edit", + guid: record.guid, + }, + }, + ], + }; + + return config; + }); + + return [ + { + id: "addresses-list-header", + control: "moz-box-item", + l10nId: "addresses-list-header", + slot: "header", }, ...items, ]; @@ -408,4 +488,68 @@ export class FormAutofillPreferences { } ); } + /** + * Open the browser window modal to prompt the user whether + * or they want to remove their address. + * + * @param {string} guid + * The guid of the address item we are prompting to remove. + * @param {object} browsingContext + * Browsing context to open the prompt in + * @param {string} title + * The title text displayed in the modal to prompt the user with + * @param {string} confirmBtn + * The text for confirming the removal of an address + * @param {string} cancelBtn + * The text for cancelling removal of an address + */ + async openRemoveAddressDialog( + guid, + browsingContext, + title, + confirmBtn, + cancelBtn + ) { + const flags = + Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_0 + + Services.prompt.BUTTON_TITLE_CANCEL * Services.prompt.BUTTON_POS_1; + const result = await Services.prompt.asyncConfirmEx( + browsingContext, + Services.prompt.MODAL_TYPE_INTERNAL_WINDOW, + title, + null, + flags, + confirmBtn, + cancelBtn, + null, + null, + false + ); + + const propBag = result.QueryInterface(Ci.nsIPropertyBag2); + // Confirmed + if (propBag.get("buttonNumClicked") === 0) { + lazy.formAutofillStorage.addresses.remove(guid); + } + } + + async openEditAddressDialog(guid, window) { + const address = await lazy.formAutofillStorage.addresses.get(guid); + return FormAutofillPreferences.openEditAddressDialog(address, window); + } + /** + * Open the edit address dialog to create/edit an address. + * + * @param {object} address + * The address we want to edit. + */ + static async openEditAddressDialog(address, window) { + window.gSubDialog.open(EDIT_ADDRESS_URL, undefined, { + record: address ?? undefined, + // Don't validate in preferences since it's fine for fields to be missing + // for autofill purposes. For PaymentRequest addresses get more validation. + noValidate: true, + l10nStrings: lazy.ManageAddresses.getAddressL10nStrings(), + }); + } }