--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1716,17 +1716,17 @@ pref("extensions.formautofill.creditCard
// 2: saw the doorhanger
// 3: submitted an autofill'ed credit card form
pref("extensions.formautofill.creditCards.used", 0);
pref("extensions.formautofill.firstTimeUse", true);
pref("extensions.formautofill.heuristics.enabled", true);
pref("extensions.formautofill.section.enabled", true);
pref("extensions.formautofill.loglevel", "Warn");
// Comma separated list of countries Form Autofill supports
-pref("extensions.formautofill.supportedCountries", "US");
+pref("extensions.formautofill.supportedCountries", "US,CA,DE");
// Whether or not to restore a session with lazy-browser tabs.
pref("browser.sessionstore.restore_tabs_lazily", true);
pref("browser.suppress_first_window_animation", true);
// Preferences for Photon onboarding system extension
pref("browser.onboarding.enabled", true);
--- a/browser/extensions/formautofill/FormAutofillHandler.jsm
+++ b/browser/extensions/formautofill/FormAutofillHandler.jsm
@@ -637,17 +637,17 @@ class FormAutofillSection {
// assumed to be default along with a meaningless text to users.
if (!value || element.selectedOptions.length != 1) {
// Keep the property and preserve more information for address updating
data[type].record[detail.fieldName] = "";
return;
}
let text = element.selectedOptions[0].text.trim();
- value = FormAutofillUtils.getAbbreviatedStateName([value, text]) || text;
+ value = FormAutofillUtils.getAbbreviatedSubregionName([value, text]) || text;
}
if (!value || value.length > FormAutofillUtils.MAX_FIELD_VALUE_LENGTH) {
// Keep the property and preserve more information for updating
data[type].record[detail.fieldName] = "";
return;
}
--- a/browser/extensions/formautofill/FormAutofillUtils.jsm
+++ b/browser/extensions/formautofill/FormAutofillUtils.jsm
@@ -282,25 +282,41 @@ this.FormAutofillUtils = {
return true;
},
loadDataFromScript(url, sandbox = {}) {
Services.scriptloader.loadSubScript(url, sandbox, "utf-8");
return sandbox;
},
- // Get country address data and fallback to US if not found.
- // See AddressDataLoader.getData for more details of addressData structure.
- getCountryAddressData(country, level1 = null) {
+ /**
+ * Get country address data and fallback to US if not found.
+ * See AddressDataLoader.getData for more details of addressData structure.
+ * @param {string} [country=FormAutofillUtils.DEFAULT_REGION]
+ * The country code for requesting specific country's metadata. It'll be
+ * default region if parameter is not set.
+ * @param {string} [level1=null]
+ * Retrun address level 1/level 2 metadata if parameter is set.
+ * @returns {object}
+ * Return the metadata of specific region.
+ */
+ getCountryAddressData(country = FormAutofillUtils.DEFAULT_REGION, level1 = null) {
let metadata = AddressDataLoader.getData(country, level1);
if (!metadata) {
- metadata = level1 ? null : AddressDataLoader.getData("US");
+ if (level1) {
+ return null;
+ }
+ // Fallback to default region if we couldn't get data from given country.
+ if (country != FormAutofillUtils.DEFAULT_REGION) {
+ metadata = AddressDataLoader.getData(FormAutofillUtils.DEFAULT_REGION);
+ }
}
- return metadata;
+ // Fallback to US if we couldn't get data from default region.
+ return metadata || AddressDataLoader.getData("US");
},
/**
* Get the collators based on the specified country.
* @param {string} country The specified country.
* @returns {array} An array containing several collator objects.
*/
getCollators(country) {
@@ -408,23 +424,23 @@ this.FormAutofillUtils = {
}
if (this.isCreditCardField(fieldName)) {
return this.findCreditCardSelectOption(selectEl, record, fieldName);
}
return null;
},
/**
- * Try to find the abbreviation of the given state name
- * @param {string[]} stateValues A list of inferable state values.
- * @param {string} country A country name to be identified.
- * @returns {string} The matching state abbreviation.
+ * Try to find the abbreviation of the given sub-region name
+ * @param {string[]} subregionValues A list of inferable sub-region values.
+ * @param {string} [country] A country name to be identified.
+ * @returns {string} The matching sub-region abbreviation.
*/
- getAbbreviatedStateName(stateValues, country = this.DEFAULT_COUNTRY_CODE) {
- let values = Array.isArray(stateValues) ? stateValues : [stateValues];
+ getAbbreviatedSubregionName(subregionValues, country) {
+ let values = Array.isArray(subregionValues) ? subregionValues : [subregionValues];
let collators = this.getCollators(country);
let {sub_keys: subKeys, sub_names: subNames} = this.getCountryAddressData(country);
if (!Array.isArray(subKeys)) {
subKeys = subKeys.split("~");
}
if (!Array.isArray(subNames)) {
@@ -463,19 +479,18 @@ this.FormAutofillUtils = {
* @returns {DOMElement}
*/
findAddressSelectOption(selectEl, address, fieldName) {
let value = address[fieldName];
if (!value) {
return null;
}
- let country = address.country || this.DEFAULT_COUNTRY_CODE;
- let dataset = this.getCountryAddressData(country);
- let collators = this.getCollators(country);
+ let dataset = this.getCountryAddressData(address.country);
+ let collators = this.getCollators(address.country);
for (let option of selectEl.options) {
if (this.strCompare(value, option.value, collators) ||
this.strCompare(value, option.text, collators)) {
return option;
}
}
@@ -662,18 +677,18 @@ this.FormAutofillUtils = {
let elements = root.querySelectorAll("[data-localization]");
for (let element of elements) {
element.textContent = bundle.GetStringFromName(element.getAttribute("data-localization"));
element.removeAttribute("data-localization");
}
},
};
-XPCOMUtils.defineLazyGetter(this.FormAutofillUtils, "DEFAULT_COUNTRY_CODE", () => {
- return Services.prefs.getCharPref("browser.search.countryCode", "US");
+XPCOMUtils.defineLazyGetter(this.FormAutofillUtils, "DEFAULT_REGION", () => {
+ return Services.prefs.getCharPref("browser.search.region", "US");
});
this.log = null;
this.FormAutofillUtils.defineLazyLogGetter(this, this.EXPORTED_SYMBOLS[0]);
XPCOMUtils.defineLazyGetter(FormAutofillUtils, "stringBundle", function() {
return Services.strings.createBundle("chrome://formautofill/locale/formautofill.properties");
});
--- a/browser/extensions/formautofill/ProfileStorage.jsm
+++ b/browser/extensions/formautofill/ProfileStorage.jsm
@@ -1272,17 +1272,17 @@ class Addresses extends AutofillRecords
address["country-name"] = "";
}
hasNewComputedFields = true;
}
// Compute tel
if (!("tel-national" in address)) {
if (address.tel) {
- let tel = PhoneNumber.Parse(address.tel, address.country || FormAutofillUtils.DEFAULT_COUNTRY_CODE);
+ let tel = PhoneNumber.Parse(address.tel, address.country || FormAutofillUtils.DEFAULT_REGION);
if (tel) {
if (tel.countryCode) {
address["tel-country-code"] = tel.countryCode;
}
if (tel.nationalNumber) {
address["tel-national"] = tel.nationalNumber;
}
@@ -1372,17 +1372,17 @@ class Addresses extends AutofillRecords
delete address["country-name"];
}
_normalizeTel(address) {
if (address.tel || TEL_COMPONENTS.some(c => !!address[c])) {
FormAutofillUtils.compressTel(address);
- let possibleRegion = address.country || FormAutofillUtils.DEFAULT_COUNTRY_CODE;
+ let possibleRegion = address.country || FormAutofillUtils.DEFAULT_REGION;
let tel = PhoneNumber.Parse(address.tel, possibleRegion);
if (tel && tel.internationalNumber) {
// Force to save numbers in E.164 format if parse success.
address.tel = tel.internationalNumber;
}
}
TEL_COMPONENTS.forEach(c => delete address[c]);
--- a/browser/extensions/formautofill/addressmetadata/addressReferences.js
+++ b/browser/extensions/formautofill/addressmetadata/addressReferences.js
@@ -11,10 +11,13 @@
// https://chromium-i18n.appspot.com/ssl-aggregate-address
// WARNING: DO NOT change any value or add additional properties in addressData.
// We only accept the metadata of the supported countries that is copied from libaddressinput directly.
// Please edit addressReferencesExt.js instead if you want to add new property as complement
// or overwrite the existing properties.
var addressData = {
+ "data/CA": {"lang": "en", "upper": "ACNOSZ", "zipex": "H3Z 2Y7,V8X 3X4,T0L 1K0,T0H 1A0,K1A 0B1", "name": "CANADA", "zip": "[ABCEGHJKLMNPRSTVXY]\\d[ABCEGHJ-NPRSTV-Z] ?\\d[ABCEGHJ-NPRSTV-Z]\\d", "fmt": "%N%n%O%n%A%n%C %S %Z", "id": "data/CA", "languages": "en~fr", "sub_keys": "AB~BC~MB~NB~NL~NT~NS~NU~ON~PE~QC~SK~YT", "key": "CA", "posturl": "https://www.canadapost.ca/cpo/mc/personal/postalcode/fpc.jsf", "require": "ACSZ", "sub_names": "Alberta~British Columbia~Manitoba~New Brunswick~Newfoundland and Labrador~Northwest Territories~Nova Scotia~Nunavut~Ontario~Prince Edward Island~Quebec~Saskatchewan~Yukon", "sub_zips": "T~V~R~E~A~X0E|X0G|X1A~B~X0A|X0B|X0C~K|L|M|N|P~C~G|H|J|K1A~S|R8A~Y"},
+ "data/CA--fr": {"lang": "fr", "upper": "ACNOSZ", "zipex": "H3Z 2Y7,V8X 3X4,T0L 1K0,T0H 1A0,K1A 0B1", "name": "CANADA", "zip": "[ABCEGHJKLMNPRSTVXY]\\d[ABCEGHJ-NPRSTV-Z] ?\\d[ABCEGHJ-NPRSTV-Z]\\d", "fmt": "%N%n%O%n%A%n%C %S %Z", "require": "ACSZ", "sub_keys": "AB~BC~PE~MB~NB~NS~NU~ON~QC~SK~NL~NT~YT", "key": "CA", "posturl": "https://www.canadapost.ca/cpo/mc/personal/postalcode/fpc.jsf", "id": "data/CA--fr", "sub_names": "Alberta~Colombie-Britannique~Île-du-Prince-Édouard~Manitoba~Nouveau-Brunswick~Nouvelle-Écosse~Nunavut~Ontario~Québec~Saskatchewan~Terre-Neuve-et-Labrador~Territoires du Nord-Ouest~Yukon", "sub_zips": "T~V~C~R~E~B~X0A|X0B|X0C~K|L|M|N|P~G|H|J|K1A~S|R8A~A~X0E|X0G|X1A~Y"},
+ "data/DE": {"zipex": "26133,53225", "name": "GERMANY", "zip": "\\d{5}", "fmt": "%N%n%O%n%A%n%Z %C", "id": "data/DE", "key": "DE", "posturl": "http://www.postdirekt.de/plzserver/", "require": "ACZ"},
"data/US": {"lang": "en", "upper": "CS", "sub_zipexs": "35000,36999~99500,99999~96799~85000,86999~71600,72999~34000,34099~09000,09999~96200,96699~90000,96199~80000,81999~06000,06999~19700,19999~20000,56999~32000,34999~30000,39901~96910,96932~96700,96899~83200,83999~60000,62999~46000,47999~50000,52999~66000,67999~40000,42799~70000,71599~03900,04999~96960,96979~20600,21999~01000,05544~48000,49999~96941,96944~55000,56799~38600,39799~63000,65999~59000,59999~68000,69999~88900,89999~03000,03899~07000,08999~87000,88499~10000,00544~27000,28999~58000,58999~96950,96952~43000,45999~73000,74999~97000,97999~96940~15000,19699~00600,00999~02800,02999~29000,29999~57000,57999~37000,38599~75000,73344~84000,84999~05000,05999~00800,00899~20100,24699~98000,99499~24700,26999~53000,54999~82000,83414", "zipex": "95014,22162-1010", "name": "UNITED STATES", "zip": "(\\d{5})(?:[ \\-](\\d{4}))?", "zip_name_type": "zip", "fmt": "%N%n%O%n%A%n%C, %S %Z", "state_name_type": "state", "id": "data/US", "languages": "en", "sub_keys": "AL~AK~AS~AZ~AR~AA~AE~AP~CA~CO~CT~DE~DC~FL~GA~GU~HI~ID~IL~IN~IA~KS~KY~LA~ME~MH~MD~MA~MI~FM~MN~MS~MO~MT~NE~NV~NH~NJ~NM~NY~NC~ND~MP~OH~OK~OR~PW~PA~PR~RI~SC~SD~TN~TX~UT~VT~VI~VA~WA~WV~WI~WY", "key": "US", "posturl": "https://tools.usps.com/go/ZipLookupAction!input.action", "require": "ACSZ", "sub_names": "Alabama~Alaska~American Samoa~Arizona~Arkansas~Armed Forces (AA)~Armed Forces (AE)~Armed Forces (AP)~California~Colorado~Connecticut~Delaware~District of Columbia~Florida~Georgia~Guam~Hawaii~Idaho~Illinois~Indiana~Iowa~Kansas~Kentucky~Louisiana~Maine~Marshall Islands~Maryland~Massachusetts~Michigan~Micronesia~Minnesota~Mississippi~Missouri~Montana~Nebraska~Nevada~New Hampshire~New Jersey~New Mexico~New York~North Carolina~North Dakota~Northern Mariana Islands~Ohio~Oklahoma~Oregon~Palau~Pennsylvania~Puerto Rico~Rhode Island~South Carolina~South Dakota~Tennessee~Texas~Utah~Vermont~Virgin Islands~Virginia~Washington~West Virginia~Wisconsin~Wyoming", "sub_zips": "3[56]~99[5-9]~96799~8[56]~71[6-9]|72~340~09~96[2-6]~9[0-5]|96[01]~8[01]~06~19[7-9]~20[02-5]|569~3[23]|34[1-9]~3[01]|398|39901~969([1-2]\\d|3[12])~967[0-8]|9679[0-8]|968~83[2-9]~6[0-2]~4[67]~5[0-2]~6[67]~4[01]|42[0-7]~70|71[0-5]~039|04~969[67]~20[6-9]|21~01|02[0-7]|05501|05544~4[89]~9694[1-4]~55|56[0-7]~38[6-9]|39[0-7]~6[3-5]~59~6[89]~889|89~03[0-8]~0[78]~87|88[0-4]~1[0-4]|06390|00501|00544~2[78]~58~9695[0-2]~4[3-5]~7[34]~97~969(39|40)~1[5-8]|19[0-6]~00[679]~02[89]~29~57~37|38[0-5]~7[5-9]|885|73301|73344~84~05~008~201|2[23]|24[0-6]~98|99[0-4]~24[7-9]|2[56]~5[34]~82|83[01]|83414"},
};
--- a/browser/extensions/formautofill/test/unit/test_addressDataLoader.js
+++ b/browser/extensions/formautofill/test/unit/test_addressDataLoader.js
@@ -1,12 +1,27 @@
"use strict";
Cu.import("resource://formautofill/FormAutofillUtils.jsm");
+const SUPPORT_COUNTRIES_TESTCASES = [
+ {
+ country: "US",
+ properties: ["languages", "alternative_names", "sub_keys", "sub_names"],
+ },
+ {
+ country: "CA",
+ properties: ["languages", "name", "sub_keys", "sub_names"],
+ },
+ {
+ country: "DE",
+ properties: ["name"],
+ },
+];
+
add_task(async function test_initalState() {
// addressData should not exist
Assert.equal(AddressDataLoader._addressData, undefined);
// Verify _dataLoaded state
Assert.equal(AddressDataLoader._dataLoaded.country, false);
Assert.equal(AddressDataLoader._dataLoaded.level1.size, 0);
});
@@ -42,8 +57,17 @@ add_task(async function test_loadDataSta
AddressDataLoader._loadScripts.reset();
// Load level 1 data again
undefinedMetadata = FormAutofillUtils.getCountryAddressData("US", "AS");
Assert.equal(undefinedMetadata, undefined, "metadata should be undefined");
// _loadScripts should not be called
sinon.assert.notCalled(AddressDataLoader._loadScripts);
});
+
+SUPPORT_COUNTRIES_TESTCASES.forEach(testcase => {
+ add_task(async function test_support_country() {
+ do_print("Starting testcase: Check " + testcase.country + " metadata");
+ let metadata = FormAutofillUtils.getCountryAddressData(testcase.country);
+ Assert.ok(testcase.properties.every(key => metadata[key]),
+ "These properties should exist: " + testcase.properties);
+ });
+});
--- a/browser/extensions/formautofill/test/unit/test_transformFields.js
+++ b/browser/extensions/formautofill/test/unit/test_transformFields.js
@@ -406,17 +406,17 @@ const ADDRESS_NORMALIZE_TESTCASES = [
"country": undefined,
"country-name": undefined,
},
},
{
description: "Has unsupported \"country\"",
address: {
"given-name": "John", // Make sure it won't be an empty record.
- "country": "CA",
+ "country": "TV",
},
expectedResult: {
"country": undefined,
"country-name": undefined,
},
},
// Tel