tor-browser

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

commit 4a06d092ba692a88e92ca9b30d0f3070d77e3618
parent 0d35cf32e8542433880cb5b4e33a1dbf89d11df7
Author: Neil Deakin <neil@mozilla.com>
Date:   Tue, 16 Dec 2025 14:47:40 +0000

Bug 1999525, when filling tel-country-code dropdowns, use the country name when looking for matching options, then use the country code, also allowing matching for country codes with multiple regions, r=dimi,credential-management-reviewers

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

Diffstat:
Mtoolkit/components/formautofill/shared/FormAutofillHandler.sys.mjs | 26+++++++++++++++++++++++---
Mtoolkit/components/formautofill/shared/FormAutofillUtils.sys.mjs | 43+++++++++++++++++++++++++++++++++----------
Mtoolkit/components/formautofill/shared/PhoneNumber.sys.mjs | 23+++++++++++++++++++++++
3 files changed, 79 insertions(+), 13 deletions(-)

diff --git a/toolkit/components/formautofill/shared/FormAutofillHandler.sys.mjs b/toolkit/components/formautofill/shared/FormAutofillHandler.sys.mjs @@ -17,6 +17,7 @@ ChromeUtils.defineESModuleGetters(lazy, { FormAutofillNameUtils: "resource://gre/modules/shared/FormAutofillNameUtils.sys.mjs", LabelUtils: "resource://gre/modules/shared/LabelUtils.sys.mjs", + PhoneNumber: "resource://gre/modules/shared/PhoneNumber.sys.mjs", clearTimeout: "resource://gre/modules/Timer.sys.mjs", setTimeout: "resource://gre/modules/Timer.sys.mjs", }); @@ -949,12 +950,31 @@ export class FormAutofillHandler { } const cache = this.#matchingSelectOption.get(element) || {}; - const value = profile[fieldName]; - let option = cache[value]?.deref(); + let value; + if (fieldName == "tel-country-code") { + // Since some telephone country codes are for multiple countries, search + // the options by the country name instead. + let countries = lazy.PhoneNumber.FindCountriesForCountryCode( + profile[fieldName] + ); + if (countries.length > 1 && countries.includes(profile.country)) { + value = profile.country; + } else { + value = countries[0]; + } + } else { + value = profile[fieldName]; + } + let option = cache[value]?.deref(); if (!option || !option.isConnected) { - option = FormAutofillUtils.findSelectOption(element, profile, fieldName); + option = FormAutofillUtils.findSelectOption( + element, + profile, + fieldName, + value + ); if (option) { cache[value] = new WeakRef(option); diff --git a/toolkit/components/formautofill/shared/FormAutofillUtils.sys.mjs b/toolkit/components/formautofill/shared/FormAutofillUtils.sys.mjs @@ -793,9 +793,14 @@ FormAutofillUtils = { return null; }, - findSelectOption(selectEl, record, fieldName) { + findSelectOption(selectEl, record, fieldName, value) { if (this.isAddressField(fieldName)) { - return this.findAddressSelectOption(selectEl.options, record, fieldName); + return this.findAddressSelectOption( + selectEl.options, + record, + fieldName, + value || record[fieldName] + ); } if (this.isCreditCardField(fieldName)) { return this.findCreditCardSelectOption(selectEl, record, fieldName); @@ -921,18 +926,15 @@ FormAutofillUtils = { * @param {Array<{text: string, value: string}>} options * @param {object} address * @param {string} fieldName + * @param {string} value * @returns {DOMElement} */ - findAddressSelectOption(options, address, fieldName) { - if (options.length > 512) { + findAddressSelectOption(options, address, fieldName, value) { + if (!value || options.length > 512) { // Allow enough space for all countries (roughly 300 distinct values) and all // timezones (roughly 400 distinct values), plus some extra wiggle room. return null; } - let value = address[fieldName]; - if (!value) { - return null; - } let collators = this.getSearchCollators(address.country); @@ -1000,6 +1002,7 @@ FormAutofillUtils = { } break; } + case "tel-country-code": case "country": { if (this.getCountryAddressData(value)) { for (const option of options) { @@ -1010,6 +1013,20 @@ FormAutofillUtils = { return option; } } + + // If the country name was not found, look for an option that + // matches the telephone country code next. + const countryCode = address["tel-country-code"]; + if (fieldName == "tel-country-code" && countryCode) { + for (const option of options) { + if ( + option.text.includes(countryCode) || + option.value.includes(countryCode) + ) { + return option; + } + } + } } break; } @@ -1041,7 +1058,12 @@ FormAutofillUtils = { menuitem, })); - return this.findAddressSelectOption(options, address, fieldName)?.menuitem; + return this.findAddressSelectOption( + options, + address, + fieldName, + address[fieldName] + )?.menuitem; }, findCreditCardSelectOption(selectEl, creditCard, fieldName) { @@ -1316,7 +1338,8 @@ FormAutofillUtils = { ? this.findAddressSelectOption( addressLevel1Options, record, - "address-level1" + "address-level1", + record["address-level1"] )?.value : record["address-level1"]; diff --git a/toolkit/components/formautofill/shared/PhoneNumber.sys.mjs b/toolkit/components/formautofill/shared/PhoneNumber.sys.mjs @@ -140,6 +140,28 @@ export var PhoneNumber = (function (dataBase) { } } + // Given a telephone country code, optionally prefixed with +, return an + // array of two-character country codes that use that telephone country + // code. For example, '+590' returns ["GP", "BL", "MF"]. + function FindCountriesForCountryCode(countryCode) { + if (countryCode[0] === "+") { + countryCode = countryCode.substring(1); + } + + let entry = dataBase[countryCode]; + if (entry) { + if (Array.isArray(entry)) { + return entry.map(i => i.substr(2, 2)); + } + + if (typeof entry == "string") { + return [entry.substr(2, 2)]; + } + } + + return []; + } + // Format a national number for a given region. The boolean flag "intl" // indicates whether we want the national or international format. function FormatNumber(regionMetaData, number, intl) { @@ -470,5 +492,6 @@ export var PhoneNumber = (function (dataBase) { IsValid: IsValidNumber, Parse: ParseNumber, FindMetaDataForRegion, + FindCountriesForCountryCode, }; })(PHONE_NUMBER_META_DATA);