summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgeorgey@chromium.org <georgey@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-10 18:24:56 +0000
committergeorgey@chromium.org <georgey@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-10 18:24:56 +0000
commit5b37cb72a5bfbcc1daa57249319a8235d0d4874a (patch)
treee2d51912bbcadb97537d09c41bf223d53536050c
parent65c03a0d3f341785989199b5fc2263e8cd41b3cc (diff)
downloadchromium_src-5b37cb72a5bfbcc1daa57249319a8235d0d4874a.zip
chromium_src-5b37cb72a5bfbcc1daa57249319a8235d0d4874a.tar.gz
chromium_src-5b37cb72a5bfbcc1daa57249319a8235d0d4874a.tar.bz2
Autofill phone number enhancements and integration of Phone Number Util Library: part 2
Internal utility library with unit-test BUG=71443 TEST=Unit-tested Review URL: http://codereview.chromium.org/6929059 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@84822 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/autofill/phone_number_i18n.cc242
-rw-r--r--chrome/browser/autofill/phone_number_i18n.h71
-rw-r--r--chrome/browser/autofill/phone_number_i18n_unittest.cc341
3 files changed, 634 insertions, 20 deletions
diff --git a/chrome/browser/autofill/phone_number_i18n.cc b/chrome/browser/autofill/phone_number_i18n.cc
index 8966d00..7c8a3c6 100644
--- a/chrome/browser/autofill/phone_number_i18n.cc
+++ b/chrome/browser/autofill/phone_number_i18n.cc
@@ -4,34 +4,238 @@
#include "chrome/browser/autofill/phone_number_i18n.h"
-#include "base/logging.h"
+#include "base/basictypes.h"
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "third_party/libphonenumber/cpp/src/phonenumberutil.h"
-using i18n::phonenumbers::PhoneNumber;
-using i18n::phonenumbers::PhoneNumberUtil;
+namespace {
+
+std::string SanitizeLocaleCode(const std::string& locale_code) {
+ if (locale_code.length() == 2)
+ return locale_code;
+ // Use USA for incomplete locales.
+ return std::string("US");
+}
+
+i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat UtilsTypeToPhoneLibType(
+ autofill_i18n::FullPhoneFormat phone_format) {
+ switch (phone_format) {
+ case autofill_i18n::E164:
+ return i18n::phonenumbers::PhoneNumberUtil::E164;
+ case autofill_i18n::INTERNATIONAL:
+ return i18n::phonenumbers::PhoneNumberUtil::INTERNATIONAL;
+ case autofill_i18n::NATIONAL:
+ return i18n::phonenumbers::PhoneNumberUtil::NATIONAL;
+ case autofill_i18n::RFC3966:
+ return i18n::phonenumbers::PhoneNumberUtil::RFC3966;
+ default:
+ NOTREACHED();
+ }
+ return i18n::phonenumbers::PhoneNumberUtil::NATIONAL;
+}
+
+} // namespace
namespace autofill_i18n {
+string16 NormalizePhoneNumber(const string16& value) {
+ std::string number(UTF16ToUTF8(value));
+ i18n::phonenumbers::PhoneNumberUtil::NormalizeDigitsOnly(&number);
+ return UTF8ToUTF16(number);
+}
+
+bool ParsePhoneNumber(const string16& value,
+ const std::string& locale,
+ string16* country_code,
+ string16* city_code,
+ string16* number) {
+ DCHECK(number);
+ DCHECK(city_code);
+ DCHECK(country_code);
+
+ number->clear();
+ city_code->clear();
+ country_code->clear();
+
+ std::string number_text(UTF16ToUTF8(value));
+
+ // Parse phone number based on the locale.
+ i18n::phonenumbers::PhoneNumber i18n_number;
+ i18n::phonenumbers::PhoneNumberUtil* phone_util =
+ i18n::phonenumbers::PhoneNumberUtil::GetInstance();
+ DCHECK(phone_util);
+
+ if (phone_util->Parse(number_text, SanitizeLocaleCode(locale).c_str(),
+ &i18n_number) !=
+ i18n::phonenumbers::PhoneNumberUtil::NO_PARSING_ERROR) {
+ return false;
+ }
+
+ i18n::phonenumbers::PhoneNumberUtil::ValidationResult validation =
+ phone_util->IsPossibleNumberWithReason(i18n_number);
+ if (validation != i18n::phonenumbers::PhoneNumberUtil::IS_POSSIBLE)
+ return false;
+
+ // This verifies that number has a valid area code (that in some cases could
+ // be empty) for parsed country code. Also verifies that this is a valid
+ // number (in US 1234567 is not valid, because numbers do not start with 1).
+ if (!phone_util->IsValidNumber(i18n_number))
+ return false;
+
+ std::string national_significant_number;
+ phone_util->GetNationalSignificantNumber(i18n_number,
+ &national_significant_number);
+
+ std::string area_code;
+ std::string subscriber_number;
+
+ int area_length = phone_util->GetLengthOfGeographicalAreaCode(i18n_number);
+ if (area_length > 0) {
+ area_code = national_significant_number.substr(0, area_length);
+ subscriber_number = national_significant_number.substr(area_length);
+ } else {
+ subscriber_number = national_significant_number;
+ }
+ *number = UTF8ToUTF16(subscriber_number);
+ *city_code = UTF8ToUTF16(area_code);
+ *country_code = string16();
+
+ i18n::phonenumbers::PhoneNumberUtil::NormalizeDigitsOnly(&number_text);
+ string16 normalized_number(UTF8ToUTF16(number_text));
+ // Check if parsed number has country code and it was not inferred from the
+ // locale.
+ if (i18n_number.has_country_code()) {
+ *country_code = UTF8ToUTF16(base::StringPrintf("%d",
+ i18n_number.country_code()));
+ if (normalized_number.length() <= national_significant_number.length() &&
+ (normalized_number.length() < country_code->length() ||
+ normalized_number.compare(0, country_code->length(), *country_code))) {
+ country_code->clear();
+ }
+ }
+
+ return true;
+}
+
+bool ConstructPhoneNumber(const string16& country_code,
+ const string16& city_code,
+ const string16& number,
+ const std::string& locale,
+ FullPhoneFormat phone_format,
+ string16* whole_number) {
+ DCHECK(whole_number);
+
+ whole_number->clear();
+
+ std::string normalized_number(UTF16ToUTF8(city_code));
+ normalized_number.append(UTF16ToUTF8(number));
+
+ i18n::phonenumbers::PhoneNumberUtil::NormalizeDigitsOnly(&normalized_number);
+
+ int64 number_int = 0;
+ if (!base::StringToInt64(normalized_number, &number_int) || !number_int)
+ return false;
+
+ i18n::phonenumbers::PhoneNumber i18n_number;
+ i18n_number.set_national_number(static_cast<uint64>(number_int));
+
+ i18n::phonenumbers::PhoneNumberUtil* phone_util =
+ i18n::phonenumbers::PhoneNumberUtil::GetInstance();
+ DCHECK(phone_util);
+
+ int country_int = phone_util->GetCountryCodeForRegion(
+ std::string(SanitizeLocaleCode(locale).c_str()));
+ if (!country_code.empty()) {
+ string16 country_code_stripped(country_code);
+ country_code_stripped = NormalizePhoneNumber(country_code_stripped);
+ if (!base::StringToInt(country_code_stripped, &country_int))
+ return false;
+ }
+ if (country_int)
+ i18n_number.set_country_code(country_int);
+
+ i18n::phonenumbers::PhoneNumberUtil::ValidationResult validation =
+ phone_util->IsPossibleNumberWithReason(i18n_number);
+ if (validation != i18n::phonenumbers::PhoneNumberUtil::IS_POSSIBLE)
+ return false;
+
+ std::string formatted_number;
+
+ phone_util->Format(i18n_number, UtilsTypeToPhoneLibType(phone_format),
+ &formatted_number);
+ *whole_number = UTF8ToUTF16(formatted_number);
+ return true;
+}
+
+string16 FormatPhone(const string16& phone, const std::string& locale,
+ FullPhoneFormat phone_format) {
+ std::string number_text(UTF16ToUTF8(phone));
+
+ i18n::phonenumbers::PhoneNumberUtil::NormalizeDigitsOnly(&number_text);
+
+ // Parse phone number based on the locale
+ i18n::phonenumbers::PhoneNumber i18n_number;
+ i18n::phonenumbers::PhoneNumberUtil* phone_util =
+ i18n::phonenumbers::PhoneNumberUtil::GetInstance();
+ DCHECK(phone_util);
+
+ if (phone_util->Parse(number_text, SanitizeLocaleCode(locale).c_str(),
+ &i18n_number) !=
+ i18n::phonenumbers::PhoneNumberUtil::NO_PARSING_ERROR) {
+ return string16();
+ }
+ std::string formatted_number;
+ phone_util->Format(i18n_number, UtilsTypeToPhoneLibType(phone_format),
+ &formatted_number);
+ return UTF8ToUTF16(formatted_number);
+}
+
+PhoneMatch ComparePhones(const string16& phone1, const string16& phone2,
+ const std::string& locale) {
+ std::string number_text(UTF16ToUTF8(phone1));
+
+ // Parse phone number based on the locale
+ i18n::phonenumbers::PhoneNumber i18n_number1;
+ i18n::phonenumbers::PhoneNumberUtil* phone_util =
+ i18n::phonenumbers::PhoneNumberUtil::GetInstance();
+ DCHECK(phone_util);
+
+ if (phone_util->Parse(number_text, SanitizeLocaleCode(locale).c_str(),
+ &i18n_number1) !=
+ i18n::phonenumbers::PhoneNumberUtil::NO_PARSING_ERROR) {
+ return PHONES_NOT_EQUAL;
+ }
+ number_text = UTF16ToUTF8(phone2);
+
+ // Parse phone number based on the locale
+ i18n::phonenumbers::PhoneNumber i18n_number2;
+ if (phone_util->Parse(number_text, SanitizeLocaleCode(locale).c_str(),
+ &i18n_number2) !=
+ i18n::phonenumbers::PhoneNumberUtil::NO_PARSING_ERROR) {
+ return PHONES_NOT_EQUAL;
+ }
+ switch (phone_util->IsNumberMatch(i18n_number1, i18n_number2)) {
+ case i18n::phonenumbers::PhoneNumberUtil::INVALID_NUMBER:
+ case i18n::phonenumbers::PhoneNumberUtil::NO_MATCH:
+ return PHONES_NOT_EQUAL;
+ case i18n::phonenumbers::PhoneNumberUtil::SHORT_NSN_MATCH:
+ return PHONES_SUBMATCH;
+ case i18n::phonenumbers::PhoneNumberUtil::NSN_MATCH:
+ case i18n::phonenumbers::PhoneNumberUtil::EXACT_MATCH:
+ return PHONES_EQUAL;
+ default:
+ NOTREACHED();
+ }
+ return PHONES_NOT_EQUAL;
+}
+
bool PhoneNumbersMatch(const string16& number_a,
const string16& number_b,
const std::string& country_code) {
- DCHECK(country_code.size() == 0 || country_code.size() == 2);
- std::string safe_country_code(country_code);
- if (safe_country_code.size() == 0)
- safe_country_code = "US";
-
- PhoneNumberUtil *phone_util = PhoneNumberUtil::GetInstance();
- PhoneNumber phone_number_a;
- phone_util->Parse(UTF16ToUTF8(number_a), safe_country_code, &phone_number_a);
- PhoneNumber phone_number_b;
- phone_util->Parse(UTF16ToUTF8(number_b), safe_country_code, &phone_number_b);
-
- PhoneNumberUtil::MatchType match = phone_util->IsNumberMatch(phone_number_a,
- phone_number_b);
- // Allow |NSN_MATCH| for implied country code if one is not set.
- return match == PhoneNumberUtil::NSN_MATCH ||
- match == PhoneNumberUtil::EXACT_MATCH;
+ return ComparePhones(number_a, number_b, country_code) == PHONES_EQUAL;
}
} // namespace autofill_i18n
+
diff --git a/chrome/browser/autofill/phone_number_i18n.h b/chrome/browser/autofill/phone_number_i18n.h
index 28b4c42..75541ad 100644
--- a/chrome/browser/autofill/phone_number_i18n.h
+++ b/chrome/browser/autofill/phone_number_i18n.h
@@ -7,11 +7,82 @@
#pragma once
#include <string>
+#include <vector>
+#include "base/compiler_specific.h"
#include "base/string16.h"
+// Utilities to process, normalize and compare international phone numbers.
+
namespace autofill_i18n {
+// Most of the following functions require |locale| to operate. The |locale| is
+// a ISO 3166 standard code ("US" for USA, "CZ" for Czech Republic, etc.).
+
+// Normalizes phone number, by changing digits in the extended fonts
+// (such as \xFF1x) into '0'-'9'. Also strips out non-digit characters.
+string16 NormalizePhoneNumber(const string16& value);
+
+// Parses |value| to extract the components of a phone number. |number|
+// returns the local number, |city_code| returns the city code, and
+// |country_code| returns country code. For some regions the |city_code| is
+// empty.
+// The parsing is based on current locale - |locale|.
+// Separator characters are stripped before parsing the digits.
+// Returns true if parsing was successful, false otherwise.
+bool ParsePhoneNumber(const string16& value,
+ const std::string& locale,
+ string16* country_code,
+ string16* city_code,
+ string16* number) WARN_UNUSED_RESULT;
+
+enum FullPhoneFormat {
+ E164, // Example: +16502345678
+ INTERNATIONAL, // Example: +1 650-234-5678
+ NATIONAL, // Example: (650) 234-5678
+ RFC3966 // Example: +1-650-234-5678
+};
+
+// Constructs whole phone number from parts.
+// |city_code| - area code, could be empty.
+// |country_code| - country code, could be empty
+// |number| - local number, should not be empty.
+// |locale| - current locale, the parsing is based on.
+// |phone_format| - whole number constructed in that format,
+// |whole_number| - constructed whole number.
+// Separator characters are stripped before parsing the digits.
+// Returns true if parsing was successful, false otherwise.
+bool ConstructPhoneNumber(const string16& country_code,
+ const string16& city_code,
+ const string16& number,
+ const std::string& locale,
+ FullPhoneFormat phone_format,
+ string16* whole_number) WARN_UNUSED_RESULT;
+
+// Parses and then formats phone number either nationally or internationally.
+// |phone| - raw, unsanitized phone number, as entered by user.
+// |locale| - country locale code, such as "US".
+// |phone_format| - the phone type format.
+// The same as calling ParsePhoneNumber(phone, locale, &country, &city,
+// &number); ConstructPhoneNumber(country, city, number, locale, phone_format,
+// &formatted_phone); but almost twice as fast, as parsing done only once.
+// Returns formatted phone on success, empty string on error.
+string16 FormatPhone(const string16& phone,
+ const std::string& locale,
+ FullPhoneFormat phone_format);
+
+enum PhoneMatch {
+ PHONES_NOT_EQUAL,
+ PHONES_EQUAL, // +1(650)2345678 is equal to 1-650-234-56-78.
+ PHONES_SUBMATCH, // 650-234-56-78 or 2345678 is a submatch for
+ // +1(650)2345678. The submatch is symmetric.
+};
+
+// Compares two phones, normalizing them before comparision.
+PhoneMatch ComparePhones(const string16& phone1,
+ const string16& phone2,
+ const std::string& locale);
+
bool PhoneNumbersMatch(const string16& number_a,
const string16& number_b,
const std::string& country_code);
diff --git a/chrome/browser/autofill/phone_number_i18n_unittest.cc b/chrome/browser/autofill/phone_number_i18n_unittest.cc
index d74d124..4134a82 100644
--- a/chrome/browser/autofill/phone_number_i18n_unittest.cc
+++ b/chrome/browser/autofill/phone_number_i18n_unittest.cc
@@ -6,7 +6,346 @@
#include "chrome/browser/autofill/phone_number_i18n.h"
#include "testing/gtest/include/gtest/gtest.h"
-using namespace autofill_i18n;
+using autofill_i18n::NormalizePhoneNumber;
+using autofill_i18n::ParsePhoneNumber;
+using autofill_i18n::ConstructPhoneNumber;
+using autofill_i18n::FormatPhone;
+using autofill_i18n::ComparePhones;
+using autofill_i18n::PhoneNumbersMatch;
+
+TEST(PhoneNumberI18NTest, NormalizePhoneNumber) {
+ // The string is split to avoid problem with MSVC compiler when it thinks
+ // 123 is a part of character code.
+ string16 phone1(UTF8ToUTF16("\x92\x32" "123\xe2\x8a\x90"));
+ EXPECT_EQ(NormalizePhoneNumber(phone1), ASCIIToUTF16("2123"));
+
+ string16 phone2(UTF8ToUTF16(
+ "\xef\xbc\x92\x32\x92\x37\xd9\xa9\xce\xb2\xe2\x8a\x90"));
+ EXPECT_EQ(NormalizePhoneNumber(phone2), ASCIIToUTF16("2279"));
+
+ string16 phone3(UTF8ToUTF16("\xef\xbc\x92\x35\xd9\xa5"));
+ EXPECT_EQ(NormalizePhoneNumber(phone3), ASCIIToUTF16("255"));
+
+ string16 phone4(UTF8ToUTF16("+1(650)2346789"));
+ EXPECT_EQ(NormalizePhoneNumber(phone4), ASCIIToUTF16("16502346789"));
+
+ string16 phone5(UTF8ToUTF16("6502346789"));
+ EXPECT_EQ(NormalizePhoneNumber(phone5), ASCIIToUTF16("6502346789"));
+}
+
+TEST(PhoneNumberI18NTest, ParsePhoneNumber) {
+ string16 number;
+ string16 city_code;
+ string16 country_code;
+
+ // Test for empty string. Should give back empty strings.
+ string16 phone0;
+ EXPECT_FALSE(ParsePhoneNumber(phone0, "US",
+ &country_code,
+ &city_code,
+ &number));
+ EXPECT_EQ(string16(), number);
+ EXPECT_EQ(string16(), city_code);
+ EXPECT_EQ(string16(), country_code);
+
+ // Test for string with less than 7 digits. Should give back empty strings.
+ string16 phone1(ASCIIToUTF16("1234"));
+ EXPECT_FALSE(ParsePhoneNumber(phone1, "US",
+ &country_code,
+ &city_code,
+ &number));
+ EXPECT_EQ(string16(), number);
+ EXPECT_EQ(string16(), city_code);
+ EXPECT_EQ(string16(), country_code);
+
+ // Test for string with exactly 7 digits.
+ // Not a valid number - starts with 1
+ string16 phone2(ASCIIToUTF16("1234567"));
+ EXPECT_FALSE(ParsePhoneNumber(phone2, "US",
+ &country_code,
+ &city_code,
+ &number));
+ EXPECT_EQ(string16(), number);
+ EXPECT_EQ(string16(), city_code);
+ EXPECT_EQ(string16(), country_code);
+
+ // Not a valid number - does not have area code.
+ string16 phone3(ASCIIToUTF16("2234567"));
+ EXPECT_FALSE(ParsePhoneNumber(phone3, "US",
+ &country_code,
+ &city_code,
+ &number));
+ EXPECT_EQ(string16(), number);
+ EXPECT_EQ(string16(), city_code);
+ EXPECT_EQ(string16(), country_code);
+
+ // Test for string with greater than 7 digits but less than 10 digits.
+ // Should fail parsing in US.
+ string16 phone4(ASCIIToUTF16("123456789"));
+ EXPECT_FALSE(ParsePhoneNumber(phone4, "US",
+ &country_code,
+ &city_code,
+ &number));
+ EXPECT_EQ(string16(), number);
+ EXPECT_EQ(string16(), city_code);
+ EXPECT_EQ(string16(), country_code);
+
+ // Test for string with greater than 7 digits but less than 10 digits and
+ // separators.
+ // Should fail parsing in US.
+ string16 phone_separator4(ASCIIToUTF16("12.345-6789"));
+ EXPECT_FALSE(ParsePhoneNumber(phone_separator4, "US",
+ &country_code,
+ &city_code,
+ &number));
+ EXPECT_EQ(string16(), number);
+ EXPECT_EQ(string16(), city_code);
+ EXPECT_EQ(string16(), country_code);
+
+ // Test for string with exactly 10 digits.
+ // Should give back phone number and city code.
+ // This one going to fail because of the incorrect area code.
+ string16 phone5(ASCIIToUTF16("1234567890"));
+ EXPECT_FALSE(ParsePhoneNumber(phone5, "US",
+ &country_code,
+ &city_code,
+ &number));
+ EXPECT_EQ(string16(), number);
+ EXPECT_EQ(string16(), city_code);
+ EXPECT_EQ(string16(), country_code);
+
+ string16 phone6(ASCIIToUTF16("6501567890"));
+ // This one going to fail because of the incorrect number (starts with 1).
+ EXPECT_FALSE(ParsePhoneNumber(phone6, "US",
+ &country_code,
+ &city_code,
+ &number));
+ EXPECT_EQ(string16(), number);
+ EXPECT_EQ(string16(), city_code);
+ EXPECT_EQ(string16(), country_code);
+
+ string16 phone7(ASCIIToUTF16("6504567890"));
+ EXPECT_TRUE(ParsePhoneNumber(phone7, "US",
+ &country_code,
+ &city_code,
+ &number));
+ EXPECT_EQ(ASCIIToUTF16("4567890"), number);
+ EXPECT_EQ(ASCIIToUTF16("650"), city_code);
+ EXPECT_EQ(string16(), country_code);
+
+ // Test for string with exactly 10 digits and separators.
+ // Should give back phone number and city code.
+ string16 phone_separator7(ASCIIToUTF16("(650) 456-7890"));
+ EXPECT_TRUE(ParsePhoneNumber(phone_separator7, "US",
+ &country_code,
+ &city_code,
+ &number));
+ EXPECT_EQ(ASCIIToUTF16("4567890"), number);
+ EXPECT_EQ(ASCIIToUTF16("650"), city_code);
+ EXPECT_EQ(string16(), country_code);
+
+ // Tests for string with over 10 digits.
+ // 01 is incorrect prefix in the USA, and if we interpret 011 as prefix, the
+ // rest is too short for international number - the parsing should fail.
+ string16 phone8(ASCIIToUTF16("0116504567890"));
+ EXPECT_FALSE(ParsePhoneNumber(phone8, "US",
+ &country_code,
+ &city_code,
+ &number));
+ EXPECT_EQ(string16(), number);
+ EXPECT_EQ(string16(), city_code);
+ EXPECT_EQ(string16(), country_code);
+
+ // 011 is a correct "dial out" prefix in the USA - the parsing should succeed.
+ string16 phone9(ASCIIToUTF16("01116504567890"));
+ EXPECT_TRUE(ParsePhoneNumber(phone9, "US",
+ &country_code,
+ &city_code,
+ &number));
+ EXPECT_EQ(ASCIIToUTF16("4567890"), number);
+ EXPECT_EQ(ASCIIToUTF16("650"), city_code);
+ EXPECT_EQ(ASCIIToUTF16("1"), country_code);
+
+ // 011 is a correct "dial out" prefix in the USA - the parsing should succeed.
+ string16 phone10(ASCIIToUTF16("01178124567890"));
+ EXPECT_TRUE(ParsePhoneNumber(phone10, "US",
+ &country_code,
+ &city_code,
+ &number));
+ EXPECT_EQ(ASCIIToUTF16("4567890"), number);
+ EXPECT_EQ(ASCIIToUTF16("812"), city_code);
+ EXPECT_EQ(ASCIIToUTF16("7"), country_code);
+
+ // Test for string with over 10 digits with separator characters.
+ // Should give back phone number, city code, and country code. "011" is
+ // US "dial out" code, which is discarded.
+ string16 phone11(ASCIIToUTF16("(0111) 650-456.7890"));
+ EXPECT_TRUE(ParsePhoneNumber(phone11, "US",
+ &country_code,
+ &city_code,
+ &number));
+ EXPECT_EQ(ASCIIToUTF16("4567890"), number);
+ EXPECT_EQ(ASCIIToUTF16("650"), city_code);
+ EXPECT_EQ(ASCIIToUTF16("1"), country_code);
+
+ // Now try phone from Chech republic - it has 00 dial out code, 420 country
+ // code and variable length area codes.
+ string16 phone12(ASCIIToUTF16("+420 27-89.10.112"));
+ EXPECT_TRUE(ParsePhoneNumber(phone12, "US",
+ &country_code,
+ &city_code,
+ &number));
+ EXPECT_EQ(ASCIIToUTF16("278910112"), number);
+ EXPECT_EQ(ASCIIToUTF16(""), city_code);
+ EXPECT_EQ(ASCIIToUTF16("420"), country_code);
+
+ EXPECT_TRUE(ParsePhoneNumber(phone12, "CZ",
+ &country_code,
+ &city_code,
+ &number));
+ EXPECT_EQ(ASCIIToUTF16("278910112"), number);
+ EXPECT_EQ(ASCIIToUTF16(""), city_code);
+ EXPECT_EQ(ASCIIToUTF16("420"), country_code);
+
+ string16 phone13(ASCIIToUTF16("420 57-89.10.112"));
+ EXPECT_FALSE(ParsePhoneNumber(phone13, "US",
+ &country_code,
+ &city_code,
+ &number));
+ EXPECT_TRUE(ParsePhoneNumber(phone13, "CZ",
+ &country_code,
+ &city_code,
+ &number));
+ EXPECT_EQ(ASCIIToUTF16("578910112"), number);
+ EXPECT_EQ(ASCIIToUTF16(""), city_code);
+ EXPECT_EQ(ASCIIToUTF16("420"), country_code);
+
+ string16 phone14(ASCIIToUTF16("1-650-FLOWERS"));
+ EXPECT_TRUE(ParsePhoneNumber(phone14, "US",
+ &country_code,
+ &city_code,
+ &number));
+ EXPECT_EQ(ASCIIToUTF16("3569377"), number);
+ EXPECT_EQ(ASCIIToUTF16("650"), city_code);
+ EXPECT_EQ(ASCIIToUTF16("1"), country_code);
+}
+
+TEST(PhoneNumberI18NTest, ConstructPhoneNumber) {
+ string16 number;
+ EXPECT_TRUE(ConstructPhoneNumber(ASCIIToUTF16("1"),
+ ASCIIToUTF16("650"),
+ ASCIIToUTF16("2345678"),
+ "US",
+ autofill_i18n::E164,
+ &number));
+ EXPECT_EQ(number, ASCIIToUTF16("+16502345678"));
+ EXPECT_TRUE(ConstructPhoneNumber(ASCIIToUTF16("1"),
+ ASCIIToUTF16("650"),
+ ASCIIToUTF16("2345678"),
+ "US",
+ autofill_i18n::INTERNATIONAL,
+ &number));
+ EXPECT_EQ(number, ASCIIToUTF16("+1 650-234-5678"));
+ EXPECT_TRUE(ConstructPhoneNumber(ASCIIToUTF16("1"),
+ ASCIIToUTF16("650"),
+ ASCIIToUTF16("2345678"),
+ "US",
+ autofill_i18n::NATIONAL,
+ &number));
+ EXPECT_EQ(number, ASCIIToUTF16("(650) 234-5678"));
+ EXPECT_TRUE(ConstructPhoneNumber(ASCIIToUTF16("1"),
+ ASCIIToUTF16("650"),
+ ASCIIToUTF16("2345678"),
+ "US",
+ autofill_i18n::RFC3966,
+ &number));
+ EXPECT_EQ(number, ASCIIToUTF16("+1-650-234-5678"));
+ EXPECT_TRUE(ConstructPhoneNumber(ASCIIToUTF16(""),
+ ASCIIToUTF16("650"),
+ ASCIIToUTF16("2345678"),
+ "US",
+ autofill_i18n::INTERNATIONAL,
+ &number));
+ EXPECT_EQ(number, ASCIIToUTF16("+1 650-234-5678"));
+ EXPECT_TRUE(ConstructPhoneNumber(ASCIIToUTF16(""),
+ ASCIIToUTF16(""),
+ ASCIIToUTF16("6502345678"),
+ "US",
+ autofill_i18n::INTERNATIONAL,
+ &number));
+ EXPECT_EQ(number, ASCIIToUTF16("+1 650-234-5678"));
+
+ EXPECT_FALSE(ConstructPhoneNumber(ASCIIToUTF16(""),
+ ASCIIToUTF16("650"),
+ ASCIIToUTF16("234567890"),
+ "US",
+ autofill_i18n::INTERNATIONAL,
+ &number));
+ EXPECT_EQ(number, string16());
+ // Italian number
+ EXPECT_TRUE(ConstructPhoneNumber(ASCIIToUTF16("39"),
+ ASCIIToUTF16(""),
+ ASCIIToUTF16("236618300"),
+ "US",
+ autofill_i18n::INTERNATIONAL,
+ &number));
+ EXPECT_EQ(number, ASCIIToUTF16("+39 236618300"));
+ EXPECT_TRUE(ConstructPhoneNumber(ASCIIToUTF16("39"),
+ ASCIIToUTF16(""),
+ ASCIIToUTF16("236618300"),
+ "US",
+ autofill_i18n::NATIONAL,
+ &number));
+ EXPECT_EQ(number, ASCIIToUTF16("236618300"));
+}
+
+TEST(PhoneNumberI18NTest, FormatPhone) {
+ EXPECT_EQ(FormatPhone(ASCIIToUTF16("1[650]234-56-78"), "US",
+ autofill_i18n::NATIONAL),
+ ASCIIToUTF16("(650) 234-5678"));
+ EXPECT_EQ(FormatPhone(ASCIIToUTF16("(650)234-56-78"), "US",
+ autofill_i18n::NATIONAL),
+ ASCIIToUTF16("(650) 234-5678"));
+ EXPECT_EQ(FormatPhone(ASCIIToUTF16("(650)234-56-78"), "US",
+ autofill_i18n::INTERNATIONAL),
+ ASCIIToUTF16("+1 650-234-5678"));
+ EXPECT_EQ(FormatPhone(ASCIIToUTF16("01139236618300"), "US",
+ autofill_i18n::INTERNATIONAL),
+ ASCIIToUTF16("+39 236618300"));
+ EXPECT_EQ(FormatPhone(ASCIIToUTF16("1(650)234-56-78"), "CZ",
+ autofill_i18n::NATIONAL),
+ ASCIIToUTF16("16502345678"));
+ EXPECT_EQ(FormatPhone(ASCIIToUTF16("1(650)234-56-78"), "CZ",
+ autofill_i18n::INTERNATIONAL),
+ ASCIIToUTF16("+420 16502345678"));
+}
+
+TEST(PhoneNumberI18NTest, ComparePhones) {
+ EXPECT_EQ(ComparePhones(ASCIIToUTF16("1(650)234-56-78"),
+ ASCIIToUTF16("+16502345678"),
+ "US"),
+ autofill_i18n::PHONES_EQUAL);
+ EXPECT_EQ(ComparePhones(ASCIIToUTF16("1(650)234-56-78"),
+ ASCIIToUTF16("6502345678"),
+ "US"),
+ autofill_i18n::PHONES_EQUAL);
+ EXPECT_EQ(ComparePhones(ASCIIToUTF16("1-800-FLOWERS"),
+ ASCIIToUTF16("18003569377"),
+ "US"),
+ autofill_i18n::PHONES_EQUAL);
+ EXPECT_EQ(ComparePhones(ASCIIToUTF16("1(650)234-56-78"),
+ ASCIIToUTF16("2345678"),
+ "US"),
+ autofill_i18n::PHONES_SUBMATCH);
+ EXPECT_EQ(ComparePhones(ASCIIToUTF16("234-56-78"),
+ ASCIIToUTF16("+16502345678"),
+ "US"),
+ autofill_i18n::PHONES_SUBMATCH);
+ EXPECT_EQ(ComparePhones(ASCIIToUTF16("1650234"),
+ ASCIIToUTF16("+16502345678"),
+ "US"),
+ autofill_i18n::PHONES_NOT_EQUAL);
+}
TEST(PhoneNumberI18NTest, PhoneNumbersMatch) {
// Same numbers, defined country code.