Bug 1820522 - Implement heuristics to determine whether two telephone numbers are the same, different, or mergeable r=mtigley

Differential Revision: https://phabricator.services.mozilla.com/D173802
This commit is contained in:
Dimi 2023-05-17 08:44:38 +00:00
Родитель 159fb3427a
Коммит 2f30c1322c
4 изменённых файлов: 153 добавлений и 3 удалений

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

@ -0,0 +1,76 @@
/* import-globals-from head_addressComponent.js */
"use strict";
// prettier-ignore
const VALID_TESTS = [
// US Valid format (XXX-XXX-XXXX) and first digit is between 2-9
["200-234-5678", true], // First digit should between 2-9
["100-234-5678", true], // First digit is not between 2-9, but currently not being checked
// when no country code is specified
["555-abc-1234", true], // Non-digit characters are normalized according to ITU E.161 standard
["55-555-5555", false], // The national number is too short (9 digits)
["2-800-555-1234", false], // "2" is not US country code so we treat
// 2-800-555-1234 as the national number, which is too long (11 digits)
// Phone numbers with country code
["1-800-555-1234", true], // Country code without plus sign
["+1 200-234-5678", true], // Country code with plus sign and with a valid national number
["+1 100-234-5678", false], // National number should be between 2-9
["+1 55-555-5555", false], // National number is too short (9 digits)
["+1 1-800-555-1234", true], // "+1" and "1" are both treated as coutnry code so national number
// is a valid number (800-555-1234)
["+1 2-800-555-1234", false], // The national number is too long (11 digits)
["+1 555-abc-1234", true], // Non-digit characters are normalized according to ITU E.161 standard
];
const COMPARE_TESTS = [
["+1 520-248-6621", "+15202486621", SAME],
["+1 520-248-6621", "1-520-248-6621", SAME],
["+1 520-248-6621", "1(520)248-6621", SAME],
["520-248-6621", "520-248-6621", SAME], // Both phone numbers don't have coutry code
["520-248-6621", "+1 520-248-6621", SAME], // Compare phone number with and without country code
["+1 520-248-6621", "248-6621", A_CONTAINS_B],
["520-248-6621", "248-6621", A_CONTAINS_B],
["0520-248-6621", "520-248-6621", A_CONTAINS_B],
["48-6621", "6621", A_CONTAINS_B], // Both phone number are invalid
["+1 520-248-6621", "+91 520-248-6622", DIFFERENT], // different national prefix and number
["+1 520-248-6621", "+91 520-248-6621", DIFFERENT], // Same number, different national prefix
["+1 520-248-6621", "+1 520-248-6622", DIFFERENT], // Same national prefix, different number
["520-248-6621", "+91 520-248-6622", DIFFERENT], // Same test as above but with default region
["520-248-6621", "+91 520-248-6621", DIFFERENT], // Same test as above but with default region
["520-248-6621", "+1 520-248-6622", DIFFERENT], // Same test as above but with default region
["520-248-6621", "520-248-6622", DIFFERENT],
// Normalize
["+1 520-248-6621", "+1 ja0-bgt-mnc1", SAME],
["+1 1-800-555-1234", "+1 800-555-1234", SAME],
// TODO: Support extension
//["+64 3 331-6005", "3 331 6005#1234", A_CONTAINS_B],
];
const TEST_FIELD_NAME = "Tel";
add_setup(async () => {
Services.prefs.setBoolPref("browser.search.region", "US");
registerCleanupFunction(function head_cleanup() {
Services.prefs.clearUserPref("browser.search.region");
});
});
add_task(async function test_isValid() {
runIsValidTest(VALID_TESTS, TEST_FIELD_NAME, value => {
return { tel: value };
});
});
add_task(async function test_compare() {
runCompareTest(COMPARE_TESTS, TEST_FIELD_NAME, value => {
return { tel: value };
});
});

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

@ -12,6 +12,8 @@ support-files =
head = head_addressComponent.js head = head_addressComponent.js
[test_addressComponent_organization.js] [test_addressComponent_organization.js]
head = head_addressComponent.js head = head_addressComponent.js
[test_addressComponent_tel.js]
head = head_addressComponent.js
[test_addressDataLoader.js] [test_addressDataLoader.js]
[test_addressRecords.js] [test_addressRecords.js]
skip-if = skip-if =

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

@ -7,9 +7,12 @@ import { FormAutofill } from "resource://autofill/FormAutofill.sys.mjs";
const lazy = {}; const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, { ChromeUtils.defineESModuleGetters(lazy, {
FormAutofillUtils: "resource://gre/modules/shared/FormAutofillUtils.sys.mjs",
FormAutofillNameUtils: FormAutofillNameUtils:
"resource://gre/modules/shared/FormAutofillNameUtils.sys.mjs", "resource://gre/modules/shared/FormAutofillNameUtils.sys.mjs",
FormAutofillUtils: "resource://gre/modules/shared/FormAutofillUtils.sys.mjs",
PhoneNumber: "resource://autofill/phonenumberutils/PhoneNumber.sys.mjs",
PhoneNumberNormalizer:
"resource://autofill/phonenumberutils/PhoneNumberNormalizer.sys.mjs",
}); });
/** /**
@ -255,7 +258,75 @@ class Name extends AddressField {}
* A full telephone number, including the country code. * A full telephone number, including the country code.
* See autocomplete="tel" * See autocomplete="tel"
*/ */
class Tel extends AddressField {} class Tel extends AddressField {
#valid = false;
// The country code part of a telphone number, such as "1" for the United States
#country_code = null;
// The national part of a telphone number. For example, the phone number "+1 520-248-6621"
// national part is "520-248-6621".
#national_number = null;
constructor(value, region) {
super(value, region);
if (!this.userValue) {
return;
}
// TODO: Support parse telephone extension
// We compress all tel-related fields into a single tel field when an an form
// is submitted, so we need to decompress it here.
const parsed_tel = lazy.PhoneNumber.Parse(this.userValue, region);
if (parsed_tel) {
this.#national_number = parsed_tel?.nationalNumber;
this.#country_code = parsed_tel?.countryCode;
this.#valid = true;
} else {
this.#national_number = lazy.PhoneNumberNormalizer.Normalize(
this.userValue
);
const md = lazy.PhoneNumber.FindMetaDataForRegion(region);
this.#country_code = md ? "+" + md.nationalPrefix : null;
this.#valid = lazy.PhoneNumber.IsValid(this.#national_number, md);
}
}
get country_code() {
return this.#country_code;
}
get national_number() {
return this.#national_number;
}
isValid() {
return this.#valid;
}
equals(other) {
return (
this.national_number == other.national_number &&
this.country_code == other.country_code
);
}
contains(other) {
if (!this.country_code || this.country_code != other.country_code) {
return false;
}
return this.national_number.endsWith(other.national_number);
}
toString() {
return `${this.constructor.name}: ${this.country_code} ${this.national_number}\n`;
}
}
/** /**
* A company or organization name. * A company or organization name.

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

@ -416,7 +416,6 @@ export var PhoneNumber = (function(dataBase) {
// Lookup the meta data for the given region. // Lookup the meta data for the given region.
let md = FindMetaDataForRegion(defaultRegion.toUpperCase()); let md = FindMetaDataForRegion(defaultRegion.toUpperCase());
if (!md) { if (!md) {
dump("Couldn't find Meta Data for region: " + defaultRegion + "\n"); dump("Couldn't find Meta Data for region: " + defaultRegion + "\n");
return null; return null;
@ -468,6 +467,8 @@ export var PhoneNumber = (function(dataBase) {
return { return {
IsPlain: IsPlainPhoneNumber, IsPlain: IsPlainPhoneNumber,
IsValid: IsValidNumber,
Parse: ParseNumber, Parse: ParseNumber,
FindMetaDataForRegion,
}; };
})(PHONE_NUMBER_META_DATA); })(PHONE_NUMBER_META_DATA);