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:
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);