зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1495881 - Compare existing autofill entries using a whitespace-free, case-insensitive, and accent-folding approach. r=MattN
Differential Revision: https://phabricator.services.mozilla.com/D14338 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
7c05f8cf84
Коммит
67d66fdc0a
|
@ -1549,6 +1549,8 @@ class Addresses extends AutofillRecords {
|
|||
this._normalizeRecord(addressToMerge, strict);
|
||||
let hasMatchingField = false;
|
||||
|
||||
let country = addressFound.country || addressToMerge.country || FormAutofill.DEFAULT_REGION;
|
||||
let collators = FormAutofillUtils.getSearchCollators(country);
|
||||
for (let field of this.VALID_FIELDS) {
|
||||
let existingField = addressFound[field];
|
||||
let incomingField = addressToMerge[field];
|
||||
|
@ -1557,14 +1559,17 @@ class Addresses extends AutofillRecords {
|
|||
// Treat "street-address" as mergeable if their single-line versions
|
||||
// match each other.
|
||||
if (field == "street-address" &&
|
||||
FormAutofillUtils.compareStreetAddress(existingField, incomingField)) {
|
||||
// Keep the value in storage if its amount of lines is greater than
|
||||
FormAutofillUtils.compareStreetAddress(existingField, incomingField, collators)) {
|
||||
// Keep the street-address in storage if its amount of lines is greater than
|
||||
// or equal to the incoming one.
|
||||
if (existingField.split("\n").length >= incomingField.split("\n").length) {
|
||||
// Replace the incoming field with the one in storage so it will
|
||||
// be further merged back to storage.
|
||||
addressToMerge[field] = existingField;
|
||||
}
|
||||
} else if (field != "street-address" &&
|
||||
FormAutofillUtils.strCompare(existingField, incomingField, collators)) {
|
||||
addressToMerge[field] = existingField;
|
||||
} else {
|
||||
this.log.debug("Conflicts: field", field, "has different value.");
|
||||
return false;
|
||||
|
|
|
@ -311,7 +311,7 @@ this.FormAutofillUtils = {
|
|||
* Internal method to split an address to multiple parts per the provided delimiter,
|
||||
* removing blank parts.
|
||||
* @param {string} address The address the split
|
||||
* @param {string} delimiter The separator that is used between lines in the address
|
||||
* @param {string} [delimiter] The separator that is used between lines in the address
|
||||
* @returns {string[]}
|
||||
*/
|
||||
_toStreetAddressParts(address, delimiter = "\n") {
|
||||
|
@ -328,7 +328,7 @@ this.FormAutofillUtils = {
|
|||
/**
|
||||
* Converts a street address to a single line, removing linebreaks marked by the delimiter
|
||||
* @param {string} address The address the convert
|
||||
* @param {string} delimiter The separator that is used between lines in the address
|
||||
* @param {string} [delimiter] The separator that is used between lines in the address
|
||||
* @returns {string}
|
||||
*/
|
||||
toOneLineAddress(address, delimiter = "\n") {
|
||||
|
@ -340,13 +340,14 @@ this.FormAutofillUtils = {
|
|||
* Compares two addresses, removing internal whitespace
|
||||
* @param {string} a The first address to compare
|
||||
* @param {string} b The second address to compare
|
||||
* @param {string} delimiter The separator that is used between lines in the address
|
||||
* @param {array} collators Search collators that will be used for comparison
|
||||
* @param {string} [delimiter="\n"] The separator that is used between lines in the address
|
||||
* @returns {boolean} True if the addresses are equal, false otherwise
|
||||
*/
|
||||
compareStreetAddress(a, b, delimiter = "\n") {
|
||||
compareStreetAddress(a, b, collators, delimiter = "\n") {
|
||||
let oneLineA = this._toStreetAddressParts(a, delimiter).map(p => p.replace(/\s/g, "")).join("");
|
||||
let oneLineB = this._toStreetAddressParts(b, delimiter).map(p => p.replace(/\s/g, "")).join("");
|
||||
return oneLineA == oneLineB;
|
||||
return this.strCompare(oneLineA, oneLineB, collators);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -466,7 +467,7 @@ this.FormAutofillUtils = {
|
|||
* @param {string} country The specified country.
|
||||
* @returns {array} An array containing several collator objects.
|
||||
*/
|
||||
getCollators(country) {
|
||||
getSearchCollators(country) {
|
||||
// TODO: Only one language should be used at a time per country. The locale
|
||||
// of the page should be taken into account to do this properly.
|
||||
// We are going to support more countries in bug 1370193 and this
|
||||
|
@ -475,7 +476,12 @@ this.FormAutofillUtils = {
|
|||
if (!this._collators[country]) {
|
||||
let dataset = this.getCountryAddressData(country);
|
||||
let languages = dataset.languages || [dataset.lang];
|
||||
this._collators[country] = languages.map(lang => new Intl.Collator(lang, {sensitivity: "base", ignorePunctuation: true}));
|
||||
let options = {
|
||||
ignorePunctuation: true,
|
||||
sensitivity: "base",
|
||||
usage: "search",
|
||||
};
|
||||
this._collators[country] = languages.map(lang => new Intl.Collator(lang, options));
|
||||
}
|
||||
return this._collators[country];
|
||||
},
|
||||
|
@ -559,7 +565,7 @@ this.FormAutofillUtils = {
|
|||
let countries = countrySpecified ? [countrySpecified] : [...FormAutofill.countries.keys()];
|
||||
|
||||
for (let country of countries) {
|
||||
let collators = this.getCollators(country);
|
||||
let collators = this.getSearchCollators(country);
|
||||
let metadata = this.getCountryAddressData(country);
|
||||
if (country != metadata.key) {
|
||||
// We hit the fallback logic in getCountryAddressRawData so ignore it as
|
||||
|
@ -611,7 +617,7 @@ this.FormAutofillUtils = {
|
|||
getAbbreviatedSubregionName(subregionValues, country) {
|
||||
let values = Array.isArray(subregionValues) ? subregionValues : [subregionValues];
|
||||
|
||||
let collators = this.getCollators(country);
|
||||
let collators = this.getSearchCollators(country);
|
||||
for (let metadata of this.getCountryAddressDataWithLocales(country)) {
|
||||
let {sub_keys: subKeys, sub_names: subNames, sub_lnames: subLnames} = metadata;
|
||||
if (!subKeys) {
|
||||
|
@ -662,7 +668,7 @@ this.FormAutofillUtils = {
|
|||
return null;
|
||||
}
|
||||
|
||||
let collators = this.getCollators(address.country);
|
||||
let collators = this.getSearchCollators(address.country);
|
||||
|
||||
for (let option of selectEl.options) {
|
||||
if (this.strCompare(value, option.value, collators) ||
|
||||
|
|
|
@ -288,6 +288,59 @@ const MERGE_TESTCASES = [
|
|||
country: "US",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Merge an address with punctuation and mIxEd-cAsE",
|
||||
addressInStorage: {
|
||||
"given-name": "Timothy",
|
||||
"street-address": "331 E. Evelyn Avenue",
|
||||
"tel": "+16509030800",
|
||||
},
|
||||
addressToMerge: {
|
||||
"street-address": "331.e.EVELYN AVENUE",
|
||||
country: "US",
|
||||
},
|
||||
expectedAddress: {
|
||||
"given-name": "Timothy",
|
||||
"street-address": "331 E. Evelyn Avenue",
|
||||
"tel": "+16509030800",
|
||||
country: "US",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Merge an address with accent characters",
|
||||
addressInStorage: {
|
||||
"given-name": "Timothy",
|
||||
"street-address": "331 E. Evelyn Straße",
|
||||
"tel": "+16509030800",
|
||||
},
|
||||
addressToMerge: {
|
||||
"street-address": "331.e.EVELYN Strasse",
|
||||
country: "US",
|
||||
},
|
||||
expectedAddress: {
|
||||
"given-name": "Timothy",
|
||||
"street-address": "331 E. Evelyn Straße",
|
||||
"tel": "+16509030800",
|
||||
country: "US",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Merge an address with a mIxEd-cAsE name",
|
||||
addressInStorage: {
|
||||
"given-name": "Timothy",
|
||||
"tel": "+16509030800",
|
||||
},
|
||||
addressToMerge: {
|
||||
"given-name": "TIMOTHY",
|
||||
"tel": "+16509030800",
|
||||
country: "US",
|
||||
},
|
||||
expectedAddress: {
|
||||
"given-name": "Timothy",
|
||||
"tel": "+16509030800",
|
||||
country: "US",
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
ChromeUtils.defineModuleGetter(this, "Preferences",
|
||||
|
|
Загрузка…
Ссылка в новой задаче