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:
Jared Wein 2018-12-15 19:58:16 +00:00
Родитель 7c05f8cf84
Коммит 67d66fdc0a
3 изменённых файлов: 76 добавлений и 12 удалений

Просмотреть файл

@ -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",