diff options
author | georgey@chromium.org <georgey@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-27 07:21:01 +0000 |
---|---|---|
committer | georgey@chromium.org <georgey@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-27 07:21:01 +0000 |
commit | f46724728002380f033e0c7832eac9eb40f59712 (patch) | |
tree | f6ba814130da6287a041222c5ca8917c9c54b2a6 /chrome/browser/autofill | |
parent | 2d0fedabd5a8938dee2dab021b0679944b7e59e5 (diff) | |
download | chromium_src-f46724728002380f033e0c7832eac9eb40f59712.zip chromium_src-f46724728002380f033e0c7832eac9eb40f59712.tar.gz chromium_src-f46724728002380f033e0c7832eac9eb40f59712.tar.bz2 |
Last major phone library change for M13
BUG=80102
TEST=unit-tested
Review URL: http://codereview.chromium.org/7069024
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@86987 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/autofill')
-rw-r--r-- | chrome/browser/autofill/autofill_manager.cc | 47 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_manager_unittest.cc | 51 | ||||
-rw-r--r-- | chrome/browser/autofill/phone_number.cc | 21 | ||||
-rw-r--r-- | chrome/browser/autofill/phone_number_i18n.cc | 40 | ||||
-rw-r--r-- | chrome/browser/autofill/phone_number_i18n.h | 3 | ||||
-rw-r--r-- | chrome/browser/autofill/phone_number_i18n_unittest.cc | 47 |
6 files changed, 159 insertions, 50 deletions
diff --git a/chrome/browser/autofill/autofill_manager.cc b/chrome/browser/autofill/autofill_manager.cc index 953fe7b..d9dff1f 100644 --- a/chrome/browser/autofill/autofill_manager.cc +++ b/chrome/browser/autofill/autofill_manager.cc @@ -25,6 +25,7 @@ #include "chrome/browser/autofill/form_structure.h" #include "chrome/browser/autofill/personal_data_manager.h" #include "chrome/browser/autofill/phone_number.h" +#include "chrome/browser/autofill/phone_number_i18n.h" #include "chrome/browser/autofill/select_control_handler.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profiles/profile.h" @@ -220,6 +221,30 @@ bool FormIsHTTPS(FormStructure* form) { return form->source_url().SchemeIs(chrome::kHttpsScheme); } +// Normalizes phones in multi-info. If |type| is anything but +// PHONE_HOME_WHOLE_NUMBER or PHONE_FAX_WHOLE_NUMBER does nothing, as it is +// either not a phone, or already normalized (parts of the phone parsed and +// normalized from the PHONE_*_WHOLE_NUMBER). |locale| is a profile locale. +// For whole number does normalization: +// (650)2345678 -> 6502345678 +// 1-800-FLOWERS -> 18003569377 +// If phone cannot be normalized, leaves it as it is. +void NormalizePhoneMultiInfo(AutofillFieldType type, + std::string const& locale, + std::vector<string16>* values) { + DCHECK(values); + if (type != PHONE_HOME_WHOLE_NUMBER && type != PHONE_FAX_WHOLE_NUMBER) + return; + for (std::vector<string16>::iterator it = values->begin(); + it != values->end(); + ++it) { + string16 normalized_phone = autofill_i18n::NormalizePhoneNumber(*it, + locale); + if (!normalized_phone.empty()) + *it = normalized_phone; + } +} + } // namespace AutofillManager::AutofillManager(TabContentsWrapper* tab_contents) @@ -780,6 +805,7 @@ void AutofillManager::GetProfileSuggestions(FormStructure* form, // The value of the stored data for this field type in the |profile|. std::vector<string16> multi_values; profile->GetMultiInfo(type, &multi_values); + NormalizePhoneMultiInfo(type, profile->CountryCode(), &multi_values); for (size_t i = 0; i < multi_values.size(); ++i) { if (!multi_values[i].empty() && @@ -813,11 +839,24 @@ void AutofillManager::GetProfileSuggestions(FormStructure* form, // The value of the stored data for this field type in the |profile|. std::vector<string16> multi_values; profile->GetMultiInfo(type, &multi_values); + NormalizePhoneMultiInfo(type, profile->CountryCode(), &multi_values); for (size_t i = 0; i < multi_values.size(); ++i) { - if (!multi_values[i].empty() && - StringToLowerASCII(multi_values[i]) - == StringToLowerASCII(field.value)) { + if (multi_values[i].empty()) + continue; + string16 profile_value_lower_case(StringToLowerASCII(multi_values[i])); + string16 field_value_lower_case(StringToLowerASCII(field.value)); + // Phone numbers could be split in US forms, so field value could be + // either prefix or suffix of the phone. + bool matched_phones = false; + if ((type == PHONE_HOME_NUMBER || type == PHONE_FAX_NUMBER) && + !field_value_lower_case.empty() && + (profile_value_lower_case.find(field_value_lower_case) != + string16::npos)) { + matched_phones = true; + } + if (matched_phones || + profile_value_lower_case == field_value_lower_case) { for (size_t j = 0; j < multi_values.size(); ++j) { if (!multi_values[j].empty()) { values->push_back(multi_values[j]); @@ -918,6 +957,7 @@ void AutofillManager::FillFormField(const AutofillProfile* profile, } else { std::vector<string16> values; profile->GetMultiInfo(type, &values); + NormalizePhoneMultiInfo(type, profile->CountryCode(), &values); DCHECK(variant < values.size()); field->value = values[variant]; } @@ -932,6 +972,7 @@ void AutofillManager::FillPhoneNumberField(const AutofillProfile* profile, // matches the "prefix" or "suffix" sizes and fill accordingly. std::vector<string16> values; profile->GetMultiInfo(type, &values); + NormalizePhoneMultiInfo(type, profile->CountryCode(), &values); DCHECK(variant < values.size()); string16 number = values[variant]; bool has_valid_suffix_and_prefix = (number.length() == diff --git a/chrome/browser/autofill/autofill_manager_unittest.cc b/chrome/browser/autofill/autofill_manager_unittest.cc index f576f64..1937b5f 100644 --- a/chrome/browser/autofill/autofill_manager_unittest.cc +++ b/chrome/browser/autofill/autofill_manager_unittest.cc @@ -1492,6 +1492,57 @@ TEST_F(AutofillManagerTest, GetFieldSuggestionsForMultiValuedProfileFilled) { expected_labels, expected_icons, expected_unique_ids); } +TEST_F(AutofillManagerTest, GetProfileSuggestionsFancyPhone) { + // Set up our form data. + FormData form; + CreateTestAddressFormData(&form); + std::vector<FormData> forms(1, form); + FormsSeen(forms); + + AutofillProfile* profile = new AutofillProfile; + profile->set_guid("00000000-0000-0000-0000-000000000103"); + std::vector<string16> multi_values(1); + multi_values[0] = ASCIIToUTF16("Natty Bumppo"); + profile->SetMultiInfo(NAME_FULL, multi_values); + multi_values[0] = ASCIIToUTF16("1800PRAIRIE"); + profile->SetMultiInfo(PHONE_HOME_WHOLE_NUMBER, multi_values); + autofill_manager_->AddProfile(profile); + + const FormField& field = form.fields[9]; + GetAutofillSuggestions(form, field); + + // No suggestions provided, so send an empty vector as the results. + // This triggers the combined message send. + AutocompleteSuggestionsReturned(std::vector<string16>()); + + // Test that we sent the right message to the renderer. + int page_id = 0; + std::vector<string16> values; + std::vector<string16> labels; + std::vector<string16> icons; + std::vector<int> unique_ids; + GetAutofillSuggestionsMessage( + &page_id, &values, &labels, &icons, &unique_ids); + + string16 expected_values[] = { + ASCIIToUTF16("12345678901"), + ASCIIToUTF16("23456789012"), + ASCIIToUTF16("18007724743"), // 1800PRAIRIE + }; + // Inferred labels include full first relevant field, which in this case is + // the address line 1. + string16 expected_labels[] = { + ASCIIToUTF16("Elvis Aaron Presley"), + ASCIIToUTF16("Charles Hardin Holley"), + ASCIIToUTF16("Natty Bumppo"), + }; + string16 expected_icons[] = {string16(), string16(), string16()}; + int expected_unique_ids[] = {1, 2, 103}; + ExpectSuggestions(page_id, values, labels, icons, unique_ids, + kDefaultPageID, arraysize(expected_values), expected_values, + expected_labels, expected_icons, expected_unique_ids); +} + // Test that we correctly fill an address form. TEST_F(AutofillManagerTest, FillAddressForm) { // Set up our form data. diff --git a/chrome/browser/autofill/phone_number.cc b/chrome/browser/autofill/phone_number.cc index 1eca43a..28e9ed13 100644 --- a/chrome/browser/autofill/phone_number.cc +++ b/chrome/browser/autofill/phone_number.cc @@ -168,29 +168,12 @@ void PhoneNumber::SetInfo(AutofillFieldType type, const string16& value) { } bool PhoneNumber::NormalizePhone() { - bool success = true; // Empty number does not need normalization. if (number_.empty()) return true; - string16 number; - string16 city_code; - string16 country_code; - // Full number - parse it, split it and re-combine into canonical form. - if (!autofill_i18n::ParsePhoneNumber( - number_, locale_, &country_code, &city_code, &number) || - !autofill_i18n::ConstructPhoneNumber( - country_code, city_code, number, - locale_, - (country_code.empty() ? - autofill_i18n::NATIONAL : autofill_i18n::INTERNATIONAL), - &number_)) { - // Parsing failed - do not store phone. - number_.clear(); - success = false; - } - number_ = autofill_i18n::NormalizePhoneNumber(number_); - return success; + number_ = autofill_i18n::NormalizePhoneNumber(number_, locale_); + return !number_.empty(); } void PhoneNumber::set_locale(const std::string& locale) { diff --git a/chrome/browser/autofill/phone_number_i18n.cc b/chrome/browser/autofill/phone_number_i18n.cc index 73ee97c..961058c 100644 --- a/chrome/browser/autofill/phone_number_i18n.cc +++ b/chrome/browser/autofill/phone_number_i18n.cc @@ -42,10 +42,27 @@ i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat UtilsTypeToPhoneLibType( namespace autofill_i18n { -string16 NormalizePhoneNumber(const string16& value) { - std::string number(UTF16ToUTF8(value)); - i18n::phonenumbers::PhoneNumberUtil::NormalizeDigitsOnly(&number); - return UTF8ToUTF16(number); +string16 NormalizePhoneNumber(const string16& value, + std::string const& locale) { + string16 number; + string16 city_code; + string16 country_code; + string16 result; + // Full number - parse it, split it and re-combine into canonical form. + if (!ParsePhoneNumber(value, locale, &country_code, &city_code, &number)) + return string16(); // Parsing failed - do not store phone. + if (!autofill_i18n::ConstructPhoneNumber( + country_code, city_code, number, + locale, + (country_code.empty() ? + autofill_i18n::NATIONAL : autofill_i18n::INTERNATIONAL), + &result)) { + // Reconstruction failed - do not store phone. + return string16(); + } + std::string result_utf8(UTF16ToUTF8(result)); + i18n::phonenumbers::PhoneNumberUtil::NormalizeDigitsOnly(&result_utf8); + return UTF8ToUTF16(result_utf8); } bool ParsePhoneNumber(const string16& value, @@ -94,6 +111,13 @@ bool ParsePhoneNumber(const string16& value, std::string subscriber_number; int area_length = phone_util->GetLengthOfGeographicalAreaCode(i18n_number); + int destination_length = + phone_util->GetLengthOfNationalDestinationCode(i18n_number); + // Some phones have a destination code in lieu of area code: mobile operators + // in Europe, toll and toll-free numbers in USA, etc. From our point of view + // these two types of codes are the same. + if (destination_length > area_length) + area_length = destination_length; if (area_length > 0) { area_code = national_significant_number.substr(0, area_length); subscriber_number = national_significant_number.substr(area_length); @@ -149,12 +173,8 @@ bool ConstructPhoneNumber(const string16& country_code, 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_code.empty() && !base::StringToInt(country_code, &country_int)) + return false; if (country_int) i18n_number.set_country_code(country_int); diff --git a/chrome/browser/autofill/phone_number_i18n.h b/chrome/browser/autofill/phone_number_i18n.h index 75541ad..9d75cab 100644 --- a/chrome/browser/autofill/phone_number_i18n.h +++ b/chrome/browser/autofill/phone_number_i18n.h @@ -21,7 +21,8 @@ namespace autofill_i18n { // 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); +string16 NormalizePhoneNumber(const string16& value, + const std::string& locale); // Parses |value| to extract the components of a phone number. |number| // returns the local number, |city_code| returns the city code, and diff --git a/chrome/browser/autofill/phone_number_i18n_unittest.cc b/chrome/browser/autofill/phone_number_i18n_unittest.cc index 22a349e..0bc466d 100644 --- a/chrome/browser/autofill/phone_number_i18n_unittest.cc +++ b/chrome/browser/autofill/phone_number_i18n_unittest.cc @@ -14,23 +14,25 @@ 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")); + // "Large" digits. + string16 phone1(UTF8ToUTF16("\xEF\xBC\x91\xEF\xBC\x96\xEF\xBC\x95\xEF\xBC\x90" + "\xEF\xBC\x97\xEF\xBC\x94\xEF\xBC\x99\xEF\xBC\x98" + "\xEF\xBC\x93\xEF\xBC\x92\xEF\xBC\x93")); + EXPECT_EQ(NormalizePhoneNumber(phone1, "US"), ASCIIToUTF16("16507498323")); - string16 phone2(UTF8ToUTF16( - "\xef\xbc\x92\x32\x92\x37\xd9\xa9\xce\xb2\xe2\x8a\x90")); - EXPECT_EQ(NormalizePhoneNumber(phone2), ASCIIToUTF16("2279")); + // Devanagari script digits. + string16 phone2(UTF8ToUTF16("\xD9\xA1\xD9\xA6\xD9\xA5\xD9\xA0\xD9\xA8\xD9\xA3" + "\xD9\xA2\xD9\xA3\xD9\xA7\xD9\xA4\xD9\xA9")); + EXPECT_EQ(NormalizePhoneNumber(phone2, "US"), ASCIIToUTF16("16508323749")); - string16 phone3(UTF8ToUTF16("\xef\xbc\x92\x35\xd9\xa5")); - EXPECT_EQ(NormalizePhoneNumber(phone3), ASCIIToUTF16("255")); + string16 phone3(UTF8ToUTF16("16503334\xef\xbc\x92\x35\xd9\xa5")); + EXPECT_EQ(NormalizePhoneNumber(phone3, "US"), ASCIIToUTF16("16503334255")); string16 phone4(UTF8ToUTF16("+1(650)2346789")); - EXPECT_EQ(NormalizePhoneNumber(phone4), ASCIIToUTF16("16502346789")); + EXPECT_EQ(NormalizePhoneNumber(phone4, "US"), ASCIIToUTF16("16502346789")); string16 phone5(UTF8ToUTF16("6502346789")); - EXPECT_EQ(NormalizePhoneNumber(phone5), ASCIIToUTF16("6502346789")); + EXPECT_EQ(NormalizePhoneNumber(phone5, "US"), ASCIIToUTF16("6502346789")); } TEST(PhoneNumberI18NTest, ParsePhoneNumber) { @@ -195,16 +197,16 @@ TEST(PhoneNumberI18NTest, ParsePhoneNumber) { &country_code, &city_code, &number)); - EXPECT_EQ(ASCIIToUTF16("278910112"), number); - EXPECT_EQ(ASCIIToUTF16(""), city_code); + EXPECT_EQ(ASCIIToUTF16("910112"), number); + EXPECT_EQ(ASCIIToUTF16("278"), 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("910112"), number); + EXPECT_EQ(ASCIIToUTF16("278"), city_code); EXPECT_EQ(ASCIIToUTF16("420"), country_code); string16 phone13(ASCIIToUTF16("420 57-89.10.112")); @@ -216,8 +218,8 @@ TEST(PhoneNumberI18NTest, ParsePhoneNumber) { &country_code, &city_code, &number)); - EXPECT_EQ(ASCIIToUTF16("578910112"), number); - EXPECT_EQ(ASCIIToUTF16(""), city_code); + EXPECT_EQ(ASCIIToUTF16("910112"), number); + EXPECT_EQ(ASCIIToUTF16("578"), city_code); EXPECT_EQ(ASCIIToUTF16("420"), country_code); string16 phone14(ASCIIToUTF16("1-650-FLOWERS")); @@ -228,6 +230,17 @@ TEST(PhoneNumberI18NTest, ParsePhoneNumber) { EXPECT_EQ(ASCIIToUTF16("3569377"), number); EXPECT_EQ(ASCIIToUTF16("650"), city_code); EXPECT_EQ(ASCIIToUTF16("1"), country_code); + + // 800 is not an area code, but the destination code. In our library these + // codes should be treated the same as area codes. + string16 phone15(ASCIIToUTF16("1-800-FLOWERS")); + EXPECT_TRUE(ParsePhoneNumber(phone15, "US", + &country_code, + &city_code, + &number)); + EXPECT_EQ(ASCIIToUTF16("3569377"), number); + EXPECT_EQ(ASCIIToUTF16("800"), city_code); + EXPECT_EQ(ASCIIToUTF16("1"), country_code); } TEST(PhoneNumberI18NTest, ConstructPhoneNumber) { |