diff options
author | georgey@chromium.org <georgey@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-23 18:24:32 +0000 |
---|---|---|
committer | georgey@chromium.org <georgey@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-23 18:24:32 +0000 |
commit | 11c2bdd10912ce3c4a8b9e1f67399e18014d2a19 (patch) | |
tree | 3ffbc51e575c7ea7daa582c6b3d41891870e9d7d | |
parent | e430bd8865e9444cd8cb742145395addaa4918bd (diff) | |
download | chromium_src-11c2bdd10912ce3c4a8b9e1f67399e18014d2a19.zip chromium_src-11c2bdd10912ce3c4a8b9e1f67399e18014d2a19.tar.gz chromium_src-11c2bdd10912ce3c4a8b9e1f67399e18014d2a19.tar.bz2 |
Autofill phone number enhancements and integration of Phone Number Util Library: part 3
BUG=71443
TEST=unit-tested
Review URL: http://codereview.chromium.org/6877130
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@86305 0039d316-1c4b-4281-b951-d872f2087c98
21 files changed, 642 insertions, 472 deletions
diff --git a/chrome/browser/autofill/autofill_ie_toolbar_import_win.cc b/chrome/browser/autofill/autofill_ie_toolbar_import_win.cc index 5829c5c..96a4ba1 100644 --- a/chrome/browser/autofill/autofill_ie_toolbar_import_win.cc +++ b/chrome/browser/autofill/autofill_ie_toolbar_import_win.cc @@ -19,6 +19,8 @@ #include "chrome/browser/autofill/field_types.h" #include "chrome/browser/autofill/form_group.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/sync/util/data_encryption.h" using base::win::RegKey; @@ -131,6 +133,10 @@ bool ImportSingleProfile(FormGroup* profile, bool has_non_empty_fields = false; + // Phones need to be rebuilt. + PhoneNumber::PhoneCombineHelper home(AutofillType::PHONE_HOME); + PhoneNumber::PhoneCombineHelper fax(AutofillType::PHONE_FAX); + for (uint32 value_index = 0; value_index < key->ValueCount(); ++value_index) { std::wstring value_name; if (key->ReadName(value_index, &value_name) != ERROR_SUCCESS) @@ -144,9 +150,21 @@ bool ImportSingleProfile(FormGroup* profile, if (it->second == CREDIT_CARD_NUMBER) { field_value = DecryptCCNumber(field_value); } - profile->SetInfo(it->second, field_value); + // We need to store phone data in the variables, before building the whole + // number at the end. The rest of the fields are set "as is". + if (!home.SetInfo(it->second, field_value) && + !fax.SetInfo(it->second, field_value)) { + profile->SetInfo(it->second, field_value); + } } } + // Now re-construct the phones if needed. + string16 constructed_number; + if (!home.empty() && home.ParseNumber(std::string("US"), &constructed_number)) + profile->SetInfo(PHONE_HOME_WHOLE_NUMBER, constructed_number); + if (!fax.empty() && fax.ParseNumber(std::string("US"), &constructed_number)) + profile->SetInfo(PHONE_FAX_WHOLE_NUMBER, constructed_number); + return has_non_empty_fields; } @@ -219,15 +237,6 @@ bool ImportCurrentUserProfiles(std::vector<AutofillProfile>* profiles, AutofillProfile profile; if (ImportSingleProfile(&profile, &key, reg_to_field)) { // Combine phones into whole phone #. - string16 phone; - phone = profile.GetInfo(PHONE_HOME_COUNTRY_CODE); - phone.append(profile.GetInfo(PHONE_HOME_CITY_CODE)); - phone.append(profile.GetInfo(PHONE_HOME_NUMBER)); - profile.SetInfo(PHONE_HOME_WHOLE_NUMBER, phone); - phone = profile.GetInfo(PHONE_FAX_COUNTRY_CODE); - phone.append(profile.GetInfo(PHONE_FAX_CITY_CODE)); - phone.append(profile.GetInfo(PHONE_FAX_NUMBER)); - profile.SetInfo(PHONE_FAX_WHOLE_NUMBER, phone); profiles->push_back(profile); } } diff --git a/chrome/browser/autofill/autofill_ie_toolbar_import_win_unittest.cc b/chrome/browser/autofill/autofill_ie_toolbar_import_win_unittest.cc index b115038..240055f 100644 --- a/chrome/browser/autofill/autofill_ie_toolbar_import_win_unittest.cc +++ b/chrome/browser/autofill/autofill_ie_toolbar_import_win_unittest.cc @@ -44,7 +44,7 @@ ValueDescription profile1[] = { { L"email", L"jdoe@test.com" }, { L"company_name", L"Testcompany" }, { L"phone_home_number", L"555-5555" }, - { L"phone_home_city_code", L"444" }, + { L"phone_home_city_code", L"650" }, { L"phone_home_country_code", L"1" }, }; @@ -54,8 +54,8 @@ ValueDescription profile2[] = { { L"email", L"janedoe@test.com" }, { L"company_name", L"Testcompany" }, { L"phone_fax_number", L"555-6666" }, - { L"phone_fax_city_code", L"777" }, - { L"phone_fax_country_code", L"2" }, + { L"phone_fax_city_code", L"812" }, + { L"phone_fax_country_code", L"7" }, }; ValueDescription credit_card[] = { @@ -171,7 +171,7 @@ TEST_F(AutofillIeToolbarImportTest, TestAutofillImport) { EXPECT_EQ(profiles[1].GetInfo(PHONE_HOME_COUNTRY_CODE), profile1[7].value); EXPECT_EQ(profiles[1].GetInfo(PHONE_HOME_CITY_CODE), profile1[6].value); EXPECT_EQ(profiles[1].GetInfo(PHONE_HOME_NUMBER), L"5555555"); - EXPECT_EQ(profiles[1].GetInfo(PHONE_HOME_WHOLE_NUMBER), L"14445555555"); + EXPECT_EQ(profiles[1].GetInfo(PHONE_HOME_WHOLE_NUMBER), L"+16505555555"); EXPECT_EQ(profiles[0].GetInfo(NAME_FIRST), profile2[0].value); EXPECT_EQ(profiles[0].GetInfo(NAME_LAST), profile2[1].value); @@ -180,7 +180,7 @@ TEST_F(AutofillIeToolbarImportTest, TestAutofillImport) { EXPECT_EQ(profiles[0].GetInfo(PHONE_FAX_COUNTRY_CODE), profile2[6].value); EXPECT_EQ(profiles[0].GetInfo(PHONE_FAX_CITY_CODE), profile2[5].value); EXPECT_EQ(profiles[0].GetInfo(PHONE_FAX_NUMBER), L"5556666"); - EXPECT_EQ(profiles[0].GetInfo(PHONE_FAX_WHOLE_NUMBER), L"27775556666"); + EXPECT_EQ(profiles[0].GetInfo(PHONE_FAX_WHOLE_NUMBER), L"+78125556666"); ASSERT_EQ(credit_cards.size(), 1); EXPECT_EQ(credit_cards[0].GetInfo(CREDIT_CARD_NAME), credit_card[0].value); diff --git a/chrome/browser/autofill/autofill_manager_unittest.cc b/chrome/browser/autofill/autofill_manager_unittest.cc index 35ae16e..f576f64 100644 --- a/chrome/browser/autofill/autofill_manager_unittest.cc +++ b/chrome/browser/autofill/autofill_manager_unittest.cc @@ -1879,16 +1879,15 @@ TEST_F(AutofillManagerTest, FillPhoneNumber) { AutofillProfile *work_profile = autofill_manager_->GetProfileWithGUID( "00000000-0000-0000-0000-000000000002"); ASSERT_TRUE(work_profile != NULL); - string16 saved_phone = work_profile->GetInfo(PHONE_HOME_NUMBER); GUIDPair guid(work_profile->guid(), 0); GUIDPair empty(std::string(), 0); - char test_data[] = "1234567890123456"; + char test_data[] = "16505554567890123456"; for (int i = arraysize(test_data) - 1; i >= 0; --i) { test_data[i] = 0; SCOPED_TRACE(StringPrintf("Testing phone: %s", test_data)); - work_profile->SetInfo(PHONE_HOME_NUMBER, ASCIIToUTF16(test_data)); + work_profile->SetInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16(test_data)); // The page ID sent to the AutofillManager from the RenderView, used to send // an IPC message back to the renderer. int page_id = 100 - i; @@ -1899,17 +1898,15 @@ TEST_F(AutofillManagerTest, FillPhoneNumber) { FormData results; EXPECT_TRUE(GetAutofillFormDataFilledMessage(&page_id, &results)); - if (i != 7) { - EXPECT_EQ(ASCIIToUTF16(test_data), results.fields[2].value); - EXPECT_EQ(ASCIIToUTF16(test_data), results.fields[3].value); + if (i != 11) { + // The only parsable phone is 16505554567. + EXPECT_EQ(string16(), results.fields[2].value); + EXPECT_EQ(string16(), results.fields[3].value); } else { - // The only size that is parsed and split, right now is 7: - EXPECT_EQ(ASCIIToUTF16("123"), results.fields[2].value); + EXPECT_EQ(ASCIIToUTF16("555"), results.fields[2].value); EXPECT_EQ(ASCIIToUTF16("4567"), results.fields[3].value); } } - - work_profile->SetInfo(PHONE_HOME_NUMBER, saved_phone); } // Test that we can still fill a form when a field has been removed from it. diff --git a/chrome/browser/autofill/autofill_profile.cc b/chrome/browser/autofill/autofill_profile.cc index f359799..4df95bd 100644 --- a/chrome/browser/autofill/autofill_profile.cc +++ b/chrome/browser/autofill/autofill_profile.cc @@ -15,8 +15,8 @@ #include "chrome/browser/autofill/address.h" #include "chrome/browser/autofill/autofill_type.h" #include "chrome/browser/autofill/contact_info.h" -#include "chrome/browser/autofill/fax_number.h" -#include "chrome/browser/autofill/home_phone_number.h" +#include "chrome/browser/autofill/phone_number.h" +#include "chrome/browser/autofill/phone_number_i18n.h" #include "chrome/common/guid.h" #include "grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" @@ -117,13 +117,14 @@ const string16 MultiString(const AutofillProfile& p, AutofillFieldType type) { template <class T> void CopyValuesToItems(AutofillFieldType type, const std::vector<string16>& values, - std::vector<T>* form_group_items) { + std::vector<T>* form_group_items, + const T& prototype) { form_group_items->resize(values.size()); for (size_t i = 0; i < form_group_items->size(); ++i) (*form_group_items)[i].SetInfo(type, CollapseWhitespace(values[i], false)); // Must have at least one (possibly empty) element. if (form_group_items->empty()) - form_group_items->resize(1); + form_group_items->resize(1, prototype); } template <class T> @@ -174,18 +175,42 @@ void CollapseCompoundFieldTypes(FieldTypeSet* type_set) { std::swap(*type_set, collapsed_set); } +class FindByPhone { + public: + FindByPhone(const string16& phone, const std::string& country_code) + : phone_(phone), + country_code_(country_code) { + } + + bool operator()(const string16& phone) { + return autofill_i18n::PhoneNumbersMatch(phone, phone_, country_code_); + } + + bool operator()(const string16* phone) { + return autofill_i18n::PhoneNumbersMatch(*phone, phone_, country_code_); + } + + private: + string16 phone_; + std::string country_code_; +}; + } // namespace AutofillProfile::AutofillProfile(const std::string& guid) - : guid_(guid), name_(1), email_(1), home_number_(1), fax_number_(1) { + : guid_(guid), + name_(1), + email_(1), + home_number_(1, PhoneNumber(AutofillType::PHONE_HOME)), + fax_number_(1, PhoneNumber(AutofillType::PHONE_FAX)) { } AutofillProfile::AutofillProfile() : guid_(guid::GenerateGUID()), name_(1), email_(1), - home_number_(1), - fax_number_(1) { + home_number_(1, PhoneNumber(AutofillType::PHONE_HOME)), + fax_number_(1, PhoneNumber(AutofillType::PHONE_FAX)) { } AutofillProfile::AutofillProfile(const AutofillProfile& profile) @@ -246,16 +271,22 @@ void AutofillProfile::SetMultiInfo(AutofillFieldType type, const std::vector<string16>& values) { switch (AutofillType(type).group()) { case AutofillType::NAME: - CopyValuesToItems(type, values, &name_); + CopyValuesToItems(type, values, &name_, NameInfo()); break; case AutofillType::EMAIL: - CopyValuesToItems(type, values, &email_); + CopyValuesToItems(type, values, &email_, EmailInfo()); break; case AutofillType::PHONE_HOME: - CopyValuesToItems(type, values, &home_number_); + CopyValuesToItems(type, + values, + &home_number_, + PhoneNumber(AutofillType::PHONE_HOME)); break; case AutofillType::PHONE_FAX: - CopyValuesToItems(type, values, &fax_number_); + CopyValuesToItems(type, + values, + &fax_number_, + PhoneNumber(AutofillType::PHONE_FAX)); break; default: if (values.size() == 1) { @@ -463,6 +494,22 @@ const string16 AutofillProfile::PrimaryValue() const { GetInfo(ADDRESS_HOME_CITY); } +bool AutofillProfile::NormalizePhones() { + // Successful either if nothing to parse, or everything is parsed correctly. + bool success = true; + for (size_t i = 0; i < home_number_.size(); ++i) { + home_number_[i].set_locale(CountryCode()); + if (!home_number_[i].NormalizePhone()) + success = false; + } + for (size_t i = 0; i < fax_number_.size(); ++i) { + fax_number_[i].set_locale(CountryCode()); + if (!fax_number_[i].NormalizePhone()) + success = false; + } + return success; +} + void AutofillProfile::OverwriteWithOrAddTo(const AutofillProfile& profile) { FieldTypeSet field_types; profile.GetNonEmptyTypes(&field_types); @@ -478,12 +525,18 @@ void AutofillProfile::OverwriteWithOrAddTo(const AutofillProfile& profile) { profile.GetMultiInfo(*iter, &new_values); std::vector<string16> existing_values; GetMultiInfo(*iter, &existing_values); + FieldTypeGroup group = AutofillType(*iter).group(); for (std::vector<string16>::iterator value_iter = new_values.begin(); value_iter != new_values.end(); ++value_iter) { // Don't add duplicates. - if (std::find(existing_values.begin(), existing_values.end(), - *value_iter) == existing_values.end()) { - existing_values.insert(existing_values.end(), *value_iter); + if (group == AutofillType::PHONE_HOME || + group == AutofillType::PHONE_FAX) { + AddPhoneIfUnique(*value_iter, &existing_values); + } else { + if (std::find(existing_values.begin(), existing_values.end(), + *value_iter) == existing_values.end()) { + existing_values.insert(existing_values.end(), *value_iter); + } } } SetMultiInfo(*iter, existing_values); @@ -493,6 +546,19 @@ void AutofillProfile::OverwriteWithOrAddTo(const AutofillProfile& profile) { } } +void AutofillProfile::AddPhoneIfUnique(const string16& phone, + std::vector<string16>* existing_phones) { + DCHECK(existing_phones); + // Phones allow "fuzzy" matching, so "1-800-FLOWERS", "18003569377", + // "(800)356-9377" and "356-9377" are considered the same. + std::vector<string16>::const_iterator phone_iter; + if (std::find_if(existing_phones->begin(), existing_phones->end(), + FindByPhone(phone, CountryCode())) == + existing_phones->end()) { + existing_phones->push_back(phone); + } +} + string16 AutofillProfile::ConstructInferredLabel( const std::vector<AutofillFieldType>& included_fields, size_t num_fields_to_use) const { diff --git a/chrome/browser/autofill/autofill_profile.h b/chrome/browser/autofill/autofill_profile.h index 80a54e8..1ff9d8d 100644 --- a/chrome/browser/autofill/autofill_profile.h +++ b/chrome/browser/autofill/autofill_profile.h @@ -119,6 +119,13 @@ class AutofillProfile : public FormGroup { // aid with correct aggregation of new data. const string16 PrimaryValue() const; + // Normalizes the home phone and fax numbers. + // Should be called after all of the form data is imported into profile. + // Drops unparsable numbers, so the numbers that are incomplete or wrong + // are not saved. Returns true if all numbers were successfully parsed, + // false otherwise. + bool NormalizePhones(); + // Overwrites the single-valued field data in |profile| with this // Profile. Or, for multi-valued fields append the new values. void OverwriteWithOrAddTo(const AutofillProfile& profile); @@ -126,6 +133,13 @@ class AutofillProfile : public FormGroup { private: typedef std::vector<const FormGroup*> FormGroupList; + // Checks if the |phone| is in the |existing_phones| using fuzzy matching: + // for example, "1-800-FLOWERS", "18003569377", "(800)356-9377" and "356-9377" + // are considered the same. + // Adds the |phone| to the |existing_phones| if not already there. + void AddPhoneIfUnique(const string16& phone, + std::vector<string16>* existing_phones); + // Builds inferred label from the first |num_fields_to_include| non-empty // fields in |label_fields|. Uses as many fields as possible if there are not // enough non-empty fields. @@ -161,8 +175,8 @@ class AutofillProfile : public FormGroup { std::vector<NameInfo> name_; std::vector<EmailInfo> email_; CompanyInfo company_; - std::vector<HomePhoneNumber> home_number_; - std::vector<FaxNumber> fax_number_; + std::vector<PhoneNumber> home_number_; + std::vector<PhoneNumber> fax_number_; Address address_; }; diff --git a/chrome/browser/autofill/autofill_profile_unittest.cc b/chrome/browser/autofill/autofill_profile_unittest.cc index 28b5f84..8bfb3ba 100644 --- a/chrome/browser/autofill/autofill_profile_unittest.cc +++ b/chrome/browser/autofill/autofill_profile_unittest.cc @@ -39,7 +39,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) { AutofillProfile profile00; autofill_test::SetProfileInfo(&profile00, "", "Mitchell", "", "johnwayne@me.xyz", "Fox", "", "unit 5", "Hollywood", "CA", "91601", "US", - "12345678910", "01987654321"); + "16505678910", "78127654321"); EXPECT_TRUE(UpdateProfileLabel(&profile00)); string16 summary00 = profile00.Label(); EXPECT_EQ(ASCIIToUTF16("Hollywood, CA"), summary00); @@ -48,7 +48,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) { AutofillProfile profile1; autofill_test::SetProfileInfo(&profile1, "", "Mitchell", "", "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA", - "91601", "US", "12345678910", "01987654321"); + "91601", "US", "16505678910", "78127654321"); EXPECT_TRUE(UpdateProfileLabel(&profile1)); string16 summary1 = profile1.Label(); EXPECT_EQ(ASCIIToUTF16("123 Zoo St., Hollywood"), summary1); @@ -57,7 +57,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) { AutofillProfile profile2; autofill_test::SetProfileInfo(&profile2, "", "Mitchell", "Morrison", "johnwayne@me.xyz", "Fox", "", "unit 5", "Hollywood", "CA", - "91601", "US", "12345678910", "01987654321"); + "91601", "US", "16505678910", "78127654321"); EXPECT_TRUE(UpdateProfileLabel(&profile2)); string16 summary2 = profile2.Label(); // Summary does include full name which is empty if the first name is empty. @@ -67,7 +67,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) { AutofillProfile profile3; autofill_test::SetProfileInfo(&profile3, "", "Mitchell", "Morrison", "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", - "Hollywood", "CA", "91601", "US", "12345678910", "01987654321"); + "Hollywood", "CA", "91601", "US", "16505678910", "78127654321"); EXPECT_TRUE(UpdateProfileLabel(&profile3)); string16 summary3 = profile3.Label(); EXPECT_EQ(ASCIIToUTF16("123 Zoo St., Hollywood"), summary3); @@ -76,7 +76,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) { AutofillProfile profile4; autofill_test::SetProfileInfo(&profile4, "Marion", "Mitchell", "", "johnwayne@me.xyz", "Fox", "", "unit 5", "Hollywood", "CA", "91601", "US", - "12345678910", "01987654321"); + "16505678910", "01987654321"); EXPECT_TRUE(UpdateProfileLabel(&profile4)); string16 summary4 = profile4.Label(); EXPECT_EQ(ASCIIToUTF16("Marion Mitchell, Hollywood"), summary4); @@ -85,7 +85,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) { AutofillProfile profile5; autofill_test::SetProfileInfo(&profile5, "Marion", "Mitchell", "", "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA", - "91601", "US", "12345678910", "01987654321"); + "91601", "US", "16505678910", "78127654321"); EXPECT_TRUE(UpdateProfileLabel(&profile5)); string16 summary5 = profile5.Label(); EXPECT_EQ(ASCIIToUTF16("Marion Mitchell, 123 Zoo St."), summary5); @@ -94,7 +94,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) { AutofillProfile profile6; autofill_test::SetProfileInfo(&profile6, "Marion", "Mitchell", "Morrison", "johnwayne@me.xyz", "Fox", "", "unit 5", "Hollywood", "CA", - "91601", "US", "12345678910", "01987654321"); + "91601", "US", "16505678910", "78127654321"); EXPECT_TRUE(UpdateProfileLabel(&profile6)); string16 summary6 = profile6.Label(); EXPECT_EQ(ASCIIToUTF16("Marion Mitchell Morrison, Hollywood"), @@ -104,7 +104,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) { AutofillProfile profile7; autofill_test::SetProfileInfo(&profile7, "Marion", "Mitchell", "Morrison", "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", - "Hollywood", "CA", "91601", "US", "12345678910", "01987654321"); + "Hollywood", "CA", "91601", "US", "16505678910", "78127654321"); EXPECT_TRUE(UpdateProfileLabel(&profile7)); string16 summary7 = profile7.Label(); EXPECT_EQ(ASCIIToUTF16("Marion Mitchell Morrison, 123 Zoo St."), @@ -115,7 +115,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) { AutofillProfile profile7a; autofill_test::SetProfileInfo(&profile7a, "Marion", "Mitchell", "Morrison", "marion@me.xyz", "Fox", "123 Zoo St.", "unit 5", - "Hollywood", "CA", "91601", "US", "12345678910", "01987654321"); + "Hollywood", "CA", "91601", "US", "16505678910", "78127654321"); std::vector<AutofillProfile*> profiles; profiles.push_back(&profile7); profiles.push_back(&profile7a); @@ -143,8 +143,8 @@ TEST(AutofillProfileTest, AdjustInferredLabels) { "Elysium", "CA", "91111", "US", - "11111111111", - "22222222222"); + "16502111111", + "16502222222"); profiles.push_back(new AutofillProfile); autofill_test::SetProfileInfo( profiles[1], @@ -182,8 +182,8 @@ TEST(AutofillProfileTest, AdjustInferredLabels) { "Elysium", "CA", "91111", "US", - "11111111111", - "22222222222"); + "16502111111", + "16502222222"); EXPECT_TRUE(AutofillProfile::AdjustInferredLabels(&profiles)); // Profile 0 and 2 inferred label now includes an e-mail. @@ -210,17 +210,17 @@ TEST(AutofillProfileTest, AdjustInferredLabels) { "Elysium", "CA", "91111", "US", - "11111111111", - "33333333333"); // Fax is different + "16502111111", + "16503333333"); // Fax is different EXPECT_TRUE(AutofillProfile::AdjustInferredLabels(&profiles)); // Profile 0 and 2 inferred label now includes a fax number. - EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., fax:#22222222222"), + EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., fax:#16502222222"), profiles[0]->Label()); EXPECT_EQ(ASCIIToUTF16("Jane Doe, 123 Letha Shore."), profiles[1]->Label()); - EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., fax:#33333333333"), + EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., fax:#16503333333"), profiles[2]->Label()); profiles.push_back(new AutofillProfile); @@ -236,22 +236,22 @@ TEST(AutofillProfileTest, AdjustInferredLabels) { "Elysium", "CA", "91111", "US", - "44444444444", // Phone is different for some. - "33333333333"); // Fax is different for some. + "16504444444", // Phone is different for some. + "16503333333"); // Fax is different for some. EXPECT_TRUE(AutofillProfile::AdjustInferredLabels(&profiles)); - EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., 11111111111," - " fax:#22222222222"), + EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., 16502111111," + " fax:#16502222222"), profiles[0]->Label()); EXPECT_EQ(ASCIIToUTF16("Jane Doe, 123 Letha Shore."), profiles[1]->Label()); - EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., 11111111111," - " fax:#33333333333"), + EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., 16502111111," + " fax:#16503333333"), profiles[2]->Label()); // This one differs from other ones by unique phone, so no need for extra // information. - EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., 44444444444"), + EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., 16504444444"), profiles[3]->Label()); profiles.push_back(new AutofillProfile); @@ -267,21 +267,21 @@ TEST(AutofillProfileTest, AdjustInferredLabels) { "Elysium", "CA", "91111", "US", - "44444444444", // Phone is different for some. - "33333333333"); // Fax is different for some. + "16504444444", // Phone is different for some. + "16503333333"); // Fax is different for some. EXPECT_TRUE(AutofillProfile::AdjustInferredLabels(&profiles)); EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., johndoe@hades.com," - " 11111111111, fax:#22222222222"), + " 16502111111, fax:#16502222222"), profiles[0]->Label()); EXPECT_EQ(ASCIIToUTF16("Jane Doe, 123 Letha Shore."), profiles[1]->Label()); EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., johndoe@hades.com," - " 11111111111, fax:#33333333333"), + " 16502111111, fax:#16503333333"), profiles[2]->Label()); EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., johndoe@hades.com," - " 44444444444, fax:#33333333333"), + " 16504444444, fax:#16503333333"), profiles[3]->Label()); // This one differs from other ones by unique e-mail, so no need for extra // information. @@ -308,8 +308,8 @@ TEST(AutofillProfileTest, CreateInferredLabels) { "Elysium", "CA", "91111", "US", - "11111111111", - "22222222222"); + "16502111111", + "16502222222"); profiles.push_back(new AutofillProfile); autofill_test::SetProfileInfo(profiles[1], "Jane", @@ -754,7 +754,7 @@ TEST(AutofillProfileTest, MultiValuePhone) { AutofillProfile p2 = p; EXPECT_EQ(0, p.Compare(p2)); EXPECT_EQ(0, p.CompareMulti(p2)); - const string16 kNoOne(ASCIIToUTF16("4151110000")); + const string16 kNoOne(ASCIIToUTF16("4152110000")); set_values[1] = kNoOne; p.SetMultiInfo(PHONE_HOME_WHOLE_NUMBER, set_values); p.GetMultiInfo(PHONE_HOME_WHOLE_NUMBER, &get_values); @@ -777,8 +777,8 @@ TEST(AutofillProfileTest, MultiValuePhone) { TEST(AutofillProfileTest, MultiValueFax) { AutofillProfile p; - const string16 kJohnDoe(ASCIIToUTF16("4151112222")); - const string16 kJohnPDoe(ASCIIToUTF16("4151113333")); + const string16 kJohnDoe(ASCIIToUTF16("4152112222")); + const string16 kJohnPDoe(ASCIIToUTF16("4153113333")); std::vector<string16> set_values; set_values.push_back(kJohnDoe); set_values.push_back(kJohnPDoe); diff --git a/chrome/browser/autofill/personal_data_manager.cc b/chrome/browser/autofill/personal_data_manager.cc index 3135044..03eb64e 100644 --- a/chrome/browser/autofill/personal_data_manager.cc +++ b/chrome/browser/autofill/personal_data_manager.cc @@ -15,6 +15,7 @@ #include "chrome/browser/autofill/autofill_metrics.h" #include "chrome/browser/autofill/form_structure.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" @@ -225,6 +226,11 @@ bool PersonalDataManager::ImportFormData( // Detect and discard forms with multiple fields of the same type. std::set<AutofillFieldType> types_seen; + // We only set complete phone, so aggregate phone parts in these vars and set + // complete at the end. + PhoneNumber::PhoneCombineHelper home(AutofillType::PHONE_HOME); + PhoneNumber::PhoneCombineHelper fax(AutofillType::PHONE_FAX); + for (size_t i = 0; i < form.field_count(); ++i) { const AutofillField* field = form.field(i); string16 value = CollapseWhitespace(field->value, false); @@ -262,51 +268,12 @@ bool PersonalDataManager::ImportFormData( } ++importable_credit_card_fields; } else { - // In the case of a phone number, if the whole phone number was entered - // into a single field, then parse it and set the sub components. - if (AutofillType(field_type).subgroup() == - AutofillType::PHONE_WHOLE_NUMBER) { - string16 number; - string16 city_code; - string16 country_code; - PhoneNumber::ParsePhoneNumber(value, - &number, - &city_code, - &country_code); - if (number.empty()) - continue; - - if (group == AutofillType::PHONE_HOME) { - imported_profile->SetInfo(PHONE_HOME_COUNTRY_CODE, country_code); - imported_profile->SetInfo(PHONE_HOME_CITY_CODE, city_code); - imported_profile->SetInfo(PHONE_HOME_NUMBER, number); - } else if (group == AutofillType::PHONE_FAX) { - imported_profile->SetInfo(PHONE_FAX_COUNTRY_CODE, country_code); - imported_profile->SetInfo(PHONE_FAX_CITY_CODE, city_code); - imported_profile->SetInfo(PHONE_FAX_NUMBER, number); - } - - continue; - } - - // Phone and fax numbers can be split across multiple fields, so we - // might have already stored the prefix, and now be at the suffix. - // If so, combine them to form the full number. - if (group == AutofillType::PHONE_HOME || - group == AutofillType::PHONE_FAX) { - AutofillFieldType number_type = PHONE_HOME_NUMBER; - if (group == AutofillType::PHONE_FAX) - number_type = PHONE_FAX_NUMBER; - - string16 stored_number = imported_profile->GetInfo(number_type); - if (stored_number.size() == - static_cast<size_t>(PhoneNumber::kPrefixLength) && - value.size() == static_cast<size_t>(PhoneNumber::kSuffixLength)) { - value = stored_number + value; - } - } - - imported_profile->SetInfo(field_type, value); + // We need to store phone data in the variables, before building the whole + // number at the end. The rest of the fields are set "as is". + // If the fields are not the phone fields in question both home.SetInfo() + // and fax.SetInfo() are going to return false. + if (!home.SetInfo(field_type, value) && !fax.SetInfo(field_type, value)) + imported_profile->SetInfo(field_type, value); // Reject profiles with invalid country information. if (field_type == ADDRESS_HOME_COUNTRY && @@ -317,6 +284,33 @@ bool PersonalDataManager::ImportFormData( } } + // Build phone numbers if they are from parts. + if (imported_profile.get()) { + string16 constructed_number; + if (!home.empty()) { + if (!home.ParseNumber(imported_profile->CountryCode(), + &constructed_number)) { + imported_profile.reset(); + } else { + imported_profile->SetInfo(PHONE_HOME_WHOLE_NUMBER, constructed_number); + } + } + if (!fax.empty()) { + if (!fax.ParseNumber(imported_profile->CountryCode(), + &constructed_number)) { + imported_profile.reset(); + } else { + imported_profile->SetInfo(PHONE_FAX_WHOLE_NUMBER, constructed_number); + } + } + } + // Normalize phone numbers. + if (imported_profile.get()) { + // Reject profile if even one of the phones is invalid. + if (!imported_profile->NormalizePhones()) + imported_profile.reset(); + } + // Reject the profile if minimum address and validation requirements are not // met. if (imported_profile.get() && !IsValidLearnableProfile(*imported_profile)) diff --git a/chrome/browser/autofill/personal_data_manager_mac.mm b/chrome/browser/autofill/personal_data_manager_mac.mm index c1f9ebe..5d02166 100644 --- a/chrome/browser/autofill/personal_data_manager_mac.mm +++ b/chrome/browser/autofill/personal_data_manager_mac.mm @@ -189,10 +189,6 @@ void AuxiliaryProfilesImpl::GetAddressBookPhoneNumbers( ABPerson* me, NSString* addressLabelRaw, AutofillProfile* profile) { - string16 number; - string16 city_code; - string16 country_code; - ABMultiValue* phoneNumbers = [me valueForProperty:kABPhoneProperty]; for (NSUInteger k = 0, phoneCount = [phoneNumbers count]; k < phoneCount; k++) { @@ -202,40 +198,25 @@ void AuxiliaryProfilesImpl::GetAddressBookPhoneNumbers( [phoneLabelRaw isEqualToString:kABPhoneHomeLabel]) { string16 homePhone = base::SysNSStringToUTF16( [phoneNumbers valueAtIndex:reverseK]); - PhoneNumber::ParsePhoneNumber( - homePhone, &number, &city_code, &country_code); - profile->SetInfo(PHONE_HOME_NUMBER, number); - profile->SetInfo(PHONE_HOME_CITY_CODE, city_code); - profile->SetInfo(PHONE_HOME_COUNTRY_CODE, country_code); + profile->SetInfo(PHONE_HOME_WHOLE_NUMBER, homePhone); } else if ([addressLabelRaw isEqualToString:kABAddressHomeLabel] && [phoneLabelRaw isEqualToString:kABPhoneHomeFAXLabel]) { string16 homeFax = base::SysNSStringToUTF16( [phoneNumbers valueAtIndex:reverseK]); - PhoneNumber::ParsePhoneNumber(homeFax, - &number, &city_code, &country_code); - profile->SetInfo(PHONE_FAX_NUMBER, number); - profile->SetInfo(PHONE_FAX_CITY_CODE, city_code); - profile->SetInfo(PHONE_FAX_COUNTRY_CODE, country_code); + profile->SetInfo(PHONE_FAX_WHOLE_NUMBER, homeFax); } else if ([addressLabelRaw isEqualToString:kABAddressWorkLabel] && [phoneLabelRaw isEqualToString:kABPhoneWorkLabel]) { string16 workPhone = base::SysNSStringToUTF16( [phoneNumbers valueAtIndex:reverseK]); - PhoneNumber::ParsePhoneNumber(workPhone, - &number, &city_code, &country_code); - profile->SetInfo(PHONE_HOME_NUMBER, number); - profile->SetInfo(PHONE_HOME_CITY_CODE, city_code); - profile->SetInfo(PHONE_HOME_COUNTRY_CODE, country_code); + profile->SetInfo(PHONE_HOME_WHOLE_NUMBER, workPhone); } else if ([addressLabelRaw isEqualToString:kABAddressWorkLabel] && [phoneLabelRaw isEqualToString:kABPhoneWorkFAXLabel]) { string16 workFax = base::SysNSStringToUTF16( [phoneNumbers valueAtIndex:reverseK]); - PhoneNumber::ParsePhoneNumber(workFax, - &number, &city_code, &country_code); - profile->SetInfo(PHONE_FAX_NUMBER, number); - profile->SetInfo(PHONE_FAX_CITY_CODE, city_code); - profile->SetInfo(PHONE_FAX_COUNTRY_CODE, country_code); + profile->SetInfo(PHONE_FAX_WHOLE_NUMBER, workFax); } } + profile->NormalizePhones(); } } // namespace diff --git a/chrome/browser/autofill/personal_data_manager_unittest.cc b/chrome/browser/autofill/personal_data_manager_unittest.cc index 2ddb0c7..5d1b57f 100644 --- a/chrome/browser/autofill/personal_data_manager_unittest.cc +++ b/chrome/browser/autofill/personal_data_manager_unittest.cc @@ -889,7 +889,7 @@ TEST_F(PersonalDataManagerTest, AggregateSameProfileWithConflict) { form1.fields.push_back(field); // Phone gets updated. autofill_test::CreateTestFormField( - "Phone:", "phone", "4445556666", "text", &field); + "Phone:", "phone", "6505556666", "text", &field); form1.fields.push_back(field); FormStructure form_structure1(form1); @@ -907,7 +907,7 @@ TEST_F(PersonalDataManagerTest, AggregateSameProfileWithConflict) { AutofillProfile expected; autofill_test::SetProfileInfo(&expected, "George", NULL, "Washington", "theprez@gmail.com", NULL, "1600 Pennsylvania Avenue", - "Suite A", "San Francisco", "California", "94102", NULL, "4445556666", + "Suite A", "San Francisco", "California", "94102", NULL, "4085556666", NULL); const std::vector<AutofillProfile*>& results1 = personal_data_->profiles(); ASSERT_EQ(1U, results1.size()); @@ -945,7 +945,7 @@ TEST_F(PersonalDataManagerTest, AggregateSameProfileWithConflict) { form2.fields.push_back(field); // Phone gets updated. autofill_test::CreateTestFormField( - "Phone:", "phone", "1231231234", "text", &field); + "Phone:", "phone", "6502231234", "text", &field); form2.fields.push_back(field); FormStructure form_structure2(form2); @@ -964,7 +964,7 @@ TEST_F(PersonalDataManagerTest, AggregateSameProfileWithConflict) { // Add multi-valued phone number to expectation. Also, country gets added. std::vector<string16> values; expected.GetMultiInfo(PHONE_HOME_WHOLE_NUMBER, &values); - values.push_back(ASCIIToUTF16("1231231234")); + values.push_back(ASCIIToUTF16("6502231234")); expected.SetMultiInfo(PHONE_HOME_WHOLE_NUMBER, values); expected.SetInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("United States")); ASSERT_EQ(1U, results2.size()); @@ -1632,7 +1632,7 @@ TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) { autofill_test::SetProfileInfo(&profile0, "Marion", NULL, "Morrison", "johnwayne@me.xyz", NULL, "123 Zoo St.", NULL, "Hollywood", "CA", - "91601", "US", "2345678910", NULL); + "91601", "US", "14155678910", NULL); personal_data_->AddProfile(profile0); @@ -1642,7 +1642,7 @@ TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) { MessageLoop::current()->Run(); personal_data_->GetNonEmptyTypes(&non_empty_types); - EXPECT_EQ(13U, non_empty_types.size()); + EXPECT_EQ(14U, non_empty_types.size()); EXPECT_TRUE(non_empty_types.count(NAME_FIRST)); EXPECT_TRUE(non_empty_types.count(NAME_LAST)); EXPECT_TRUE(non_empty_types.count(NAME_FULL)); @@ -1653,6 +1653,7 @@ TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) { EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_ZIP)); EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_COUNTRY)); EXPECT_TRUE(non_empty_types.count(PHONE_HOME_NUMBER)); + EXPECT_TRUE(non_empty_types.count(PHONE_HOME_COUNTRY_CODE)); EXPECT_TRUE(non_empty_types.count(PHONE_HOME_CITY_CODE)); EXPECT_TRUE(non_empty_types.count(PHONE_HOME_CITY_AND_NUMBER)); EXPECT_TRUE(non_empty_types.count(PHONE_HOME_WHOLE_NUMBER)); @@ -1662,13 +1663,13 @@ TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) { autofill_test::SetProfileInfo(&profile1, "Josephine", "Alicia", "Saenz", "joewayne@me.xyz", "Fox", "903 Apple Ct.", NULL, "Orlando", "FL", "32801", - "US", "19482937549", "13502849239"); + "US", "16502937549", "14082849239"); AutofillProfile profile2; autofill_test::SetProfileInfo(&profile2, "Josephine", "Alicia", "Saenz", "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL", - "32801", "US", "19482937549", "13502849239"); + "32801", "US", "16502937549", "14152849239"); personal_data_->AddProfile(profile1); personal_data_->AddProfile(profile2); diff --git a/chrome/browser/autofill/phone_field.cc b/chrome/browser/autofill/phone_field.cc index c5045aa..d1ba987 100644 --- a/chrome/browser/autofill/phone_field.cc +++ b/chrome/browser/autofill/phone_field.cc @@ -330,9 +330,9 @@ void PhoneField::SetPhoneType(PhoneType phone_type) { // Field types are different as well, so we create a temporary phone number, // to get relevant field types. if (phone_type == HOME_PHONE) - number_.reset(new HomePhoneNumber); + number_.reset(new PhoneNumber(AutofillType::PHONE_HOME)); else - number_.reset(new FaxNumber); + number_.reset(new PhoneNumber(AutofillType::PHONE_FAX)); phone_type_ = phone_type; } diff --git a/chrome/browser/autofill/phone_number.cc b/chrome/browser/autofill/phone_number.cc index d1ca32a..1eca43a 100644 --- a/chrome/browser/autofill/phone_number.cc +++ b/chrome/browser/autofill/phone_number.cc @@ -5,10 +5,13 @@ #include "chrome/browser/autofill/phone_number.h" #include "base/basictypes.h" +#include "base/string_number_conversions.h" #include "base/string_util.h" +#include "base/utf_string_conversions.h" #include "chrome/browser/autofill/autofill_profile.h" #include "chrome/browser/autofill/autofill_type.h" #include "chrome/browser/autofill/field_types.h" +#include "chrome/browser/autofill/phone_number_i18n.h" namespace { @@ -32,7 +35,13 @@ const int kAutofillPhoneLength = arraysize(kAutofillPhoneTypes); } // namespace -PhoneNumber::PhoneNumber() {} +PhoneNumber::PhoneNumber() + : phone_group_(AutofillType::NO_GROUP) { +} + +PhoneNumber::PhoneNumber(AutofillType::FieldTypeGroup phone_group) + : phone_group_(phone_group) { +} PhoneNumber::PhoneNumber(const PhoneNumber& number) : FormGroup() { *this = number; @@ -43,10 +52,8 @@ PhoneNumber::~PhoneNumber() {} PhoneNumber& PhoneNumber::operator=(const PhoneNumber& number) { if (this == &number) return *this; - country_code_ = number.country_code_; - city_code_ = number.city_code_; number_ = number.number_; - extension_ = number.extension_; + phone_group_ = number.phone_group_; return *this; } @@ -54,194 +61,247 @@ void PhoneNumber::GetMatchingTypes(const string16& text, FieldTypeSet* matching_types) const { string16 stripped_text(text); StripPunctuation(&stripped_text); - if (!Validate(stripped_text)) + + 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)) return; - if (IsNumber(stripped_text)) + if (IsNumber(stripped_text, number)) matching_types->insert(GetNumberType()); - if (IsCityCode(stripped_text)) + if (stripped_text == city_code) matching_types->insert(GetCityCodeType()); - if (IsCountryCode(stripped_text)) + if (stripped_text == country_code) matching_types->insert(GetCountryCodeType()); - if (IsCityAndNumber(stripped_text)) + city_code.append(number); + if (stripped_text == city_code) matching_types->insert(GetCityAndNumberType()); - if (IsWholeNumber(stripped_text)) + // Whole number is compared to unfiltered text - it would be parsed for phone + // comparision (e.g. 1-800-FLOWERS and 18003569377 are the same) + if (IsWholeNumber(text)) matching_types->insert(GetWholeNumberType()); } -void PhoneNumber::GetNonEmptyTypes(FieldTypeSet* non_empty_typess) const { - DCHECK(non_empty_typess); +void PhoneNumber::GetNonEmptyTypes(FieldTypeSet* non_empty_types) const { + DCHECK(non_empty_types); - if (!number().empty()) - non_empty_typess->insert(GetNumberType()); + if (number_.empty()) + return; + + non_empty_types->insert(GetWholeNumberType()); - if (!city_code().empty()) - non_empty_typess->insert(GetCityCodeType()); + 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)) + return; - if (!country_code().empty()) - non_empty_typess->insert(GetCountryCodeType()); + non_empty_types->insert(GetNumberType()); - if (!CityAndNumber().empty()) - non_empty_typess->insert(GetCityAndNumberType()); + if (!city_code.empty()) { + non_empty_types->insert(GetCityCodeType()); + non_empty_types->insert(GetCityAndNumberType()); + } - if (!WholeNumber().empty()) - non_empty_typess->insert(GetWholeNumberType()); + if (!country_code.empty()) + non_empty_types->insert(GetCountryCodeType()); } string16 PhoneNumber::GetInfo(AutofillFieldType type) const { + if (type == GetWholeNumberType()) + return number_; + + 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)) + return string16(); + if (type == GetNumberType()) - return number(); + return number; if (type == GetCityCodeType()) - return city_code(); + return city_code; if (type == GetCountryCodeType()) - return country_code(); + return country_code; + city_code.append(number); if (type == GetCityAndNumberType()) - return CityAndNumber(); - - if (type == GetWholeNumberType()) - return WholeNumber(); + return city_code; return string16(); } void PhoneNumber::SetInfo(AutofillFieldType type, const string16& value) { - string16 number(value); - StripPunctuation(&number); - if (!Validate(number)) - return; - FieldTypeSubGroup subgroup = AutofillType(type).subgroup(); - if (subgroup == AutofillType::PHONE_NUMBER) - set_number(number); - else if (subgroup == AutofillType::PHONE_CITY_CODE) - set_city_code(number); - else if (subgroup == AutofillType::PHONE_COUNTRY_CODE) - set_country_code(number); - else if (subgroup == AutofillType::PHONE_CITY_AND_NUMBER || - subgroup == AutofillType::PHONE_WHOLE_NUMBER) - set_whole_number(number); - else + FieldTypeGroup group = AutofillType(type).group(); + if (phone_group_ == AutofillType::NO_GROUP) + phone_group_ = group; // First call on empty phone - set the group. + if (subgroup == AutofillType::PHONE_NUMBER) { + // Should not be set directly. NOTREACHED(); + } else if (subgroup == AutofillType::PHONE_CITY_CODE) { + // Should not be set directly. + NOTREACHED(); + } else if (subgroup == AutofillType::PHONE_COUNTRY_CODE) { + // Should not be set directly. + NOTREACHED(); + } else if (subgroup == AutofillType::PHONE_CITY_AND_NUMBER || + subgroup == AutofillType::PHONE_WHOLE_NUMBER) { + number_ = value; + StripPunctuation(&number_); + } else { + NOTREACHED(); + } } -// Static. -bool PhoneNumber::ParsePhoneNumber(const string16& value, - string16* number, - string16* city_code, - string16* country_code) { - DCHECK(number); - DCHECK(city_code); - DCHECK(country_code); - - // Make a working copy of value. - string16 working = value; - - *number = string16(); - *city_code = string16(); - *country_code = string16(); - - // First remove any punctuation. - StripPunctuation(&working); - - if (working.size() < kPhoneNumberLength) - return false; - - // Treat the last 7 digits as the number. - *number = working.substr(working.size() - kPhoneNumberLength, - kPhoneNumberLength); - working.resize(working.size() - kPhoneNumberLength); - if (working.size() < kPhoneCityCodeLength) +bool PhoneNumber::NormalizePhone() { + bool success = true; + // Empty number does not need normalization. + if (number_.empty()) return true; - // Treat the next three digits as the city code. - *city_code = working.substr(working.size() - kPhoneCityCodeLength, - kPhoneCityCodeLength); - working.resize(working.size() - kPhoneCityCodeLength); - if (working.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; +} - // Treat any remaining digits as the country code. - *country_code = working; - return true; +void PhoneNumber::set_locale(const std::string& locale) { + locale_ = locale; } -string16 PhoneNumber::WholeNumber() const { - string16 whole_number; - if (!country_code_.empty()) - whole_number.append(country_code_); +AutofillFieldType PhoneNumber::GetNumberType() const { + if (phone_group_ == AutofillType::PHONE_HOME) + return PHONE_HOME_NUMBER; + else if (phone_group_ == AutofillType::PHONE_FAX) + return PHONE_FAX_NUMBER; + else + NOTREACHED(); + return UNKNOWN_TYPE; +} - if (!city_code_.empty()) - whole_number.append(city_code_); +AutofillFieldType PhoneNumber::GetCityCodeType() const { + if (phone_group_ == AutofillType::PHONE_HOME) + return PHONE_HOME_CITY_CODE; + else if (phone_group_ == AutofillType::PHONE_FAX) + return PHONE_FAX_CITY_CODE; + else + NOTREACHED(); + return UNKNOWN_TYPE; +} - if (!number_.empty()) - whole_number.append(number_); +AutofillFieldType PhoneNumber::GetCountryCodeType() const { + if (phone_group_ == AutofillType::PHONE_HOME) + return PHONE_HOME_COUNTRY_CODE; + else if (phone_group_ == AutofillType::PHONE_FAX) + return PHONE_FAX_COUNTRY_CODE; + else + NOTREACHED(); + return UNKNOWN_TYPE; +} - return whole_number; +AutofillFieldType PhoneNumber::GetCityAndNumberType() const { + if (phone_group_ == AutofillType::PHONE_HOME) + return PHONE_HOME_CITY_AND_NUMBER; + else if (phone_group_ == AutofillType::PHONE_FAX) + return PHONE_FAX_CITY_AND_NUMBER; + else + NOTREACHED(); + return UNKNOWN_TYPE; } -void PhoneNumber::set_number(const string16& number) { - string16 digits(number); - StripPunctuation(&digits); - number_ = digits; +AutofillFieldType PhoneNumber::GetWholeNumberType() const { + if (phone_group_ == AutofillType::PHONE_HOME) + return PHONE_HOME_WHOLE_NUMBER; + else if (phone_group_ == AutofillType::PHONE_FAX) + return PHONE_FAX_WHOLE_NUMBER; + else + NOTREACHED(); + return UNKNOWN_TYPE; } -void PhoneNumber::set_whole_number(const string16& whole_number) { - string16 number, city_code, country_code; - ParsePhoneNumber(whole_number, &number, &city_code, &country_code); - set_number(number); - set_city_code(city_code); - set_country_code(country_code); +bool PhoneNumber::PhoneCombineHelper::SetInfo(AutofillFieldType field_type, + const string16& value) { + PhoneNumber temp(phone_group_); + + if (field_type == temp.GetCountryCodeType()) { + country_ = value; + return true; + } else if (field_type == temp.GetCityCodeType()) { + city_ = value; + return true; + } else if (field_type == temp.GetCityAndNumberType()) { + phone_ = value; + return true; + } else if (field_type == temp.GetNumberType()) { + phone_.append(value); + return true; + } else { + return false; + } +} + +bool PhoneNumber::PhoneCombineHelper::ParseNumber(const std::string& locale, + string16* value) { + DCHECK(value); + return autofill_i18n::ConstructPhoneNumber( + country_, city_, phone_, + locale, + (country_.empty() ? + autofill_i18n::NATIONAL : autofill_i18n::INTERNATIONAL), + value); } -bool PhoneNumber::IsNumber(const string16& text) const { - // TODO(isherman): This will need to be updated once we add support for +bool PhoneNumber::IsNumber(const string16& text, const string16& number) const { + // TODO(georgey): This will need to be updated once we add support for // international phone numbers. const size_t kPrefixLength = 3; const size_t kSuffixLength = 4; - if (text == number_) + if (text == number) return true; - if (text.length() == kPrefixLength && StartsWith(number_, text, true)) + if (text.length() == kPrefixLength && StartsWith(number, text, true)) return true; - if (text.length() == kSuffixLength && EndsWith(number_, text, true)) + if (text.length() == kSuffixLength && EndsWith(number, text, true)) return true; return false; } -bool PhoneNumber::IsCityCode(const string16& text) const { - return text == city_code_; -} - -bool PhoneNumber::IsCountryCode(const string16& text) const { - return text == country_code_; -} - -bool PhoneNumber::IsCityAndNumber(const string16& text) const { - return text == CityAndNumber(); -} - bool PhoneNumber::IsWholeNumber(const string16& text) const { - return text == WholeNumber(); -} - -bool PhoneNumber::Validate(const string16& number) const { - for (size_t i = 0; i < number.length(); ++i) { - if (!IsAsciiDigit(number[i])) - return false; - } - - return true; + return autofill_i18n::ComparePhones(text, number_, locale_) == + autofill_i18n::PHONES_EQUAL; } // Static. void PhoneNumber::StripPunctuation(string16* number) { RemoveChars(*number, kPhoneNumberSeparators, number); } + diff --git a/chrome/browser/autofill/phone_number.h b/chrome/browser/autofill/phone_number.h index 9cbb6b2..2790f9c 100644 --- a/chrome/browser/autofill/phone_number.h +++ b/chrome/browser/autofill/phone_number.h @@ -6,6 +6,7 @@ #define CHROME_BROWSER_AUTOFILL_PHONE_NUMBER_H_ #pragma once +#include <string> #include <vector> #include "base/gtest_prod_util.h" @@ -17,7 +18,8 @@ class PhoneNumber : public FormGroup { public: PhoneNumber(); - explicit PhoneNumber(const PhoneNumber& number); + explicit PhoneNumber(AutofillType::FieldTypeGroup phone_group); + PhoneNumber(const PhoneNumber& number); virtual ~PhoneNumber(); PhoneNumber& operator=(const PhoneNumber& number); @@ -29,15 +31,9 @@ class PhoneNumber : public FormGroup { virtual string16 GetInfo(AutofillFieldType type) const; virtual void SetInfo(AutofillFieldType type, const string16& value); - // Parses |value| to extract the components of a phone number. |number| - // returns the trailing 7 digits, |city_code| returns the next 3 digits, and - // |country_code| returns any remaining digits. - // Separator characters are stripped before parsing the digits. - // Returns true if parsing was successful, false otherwise. - static bool ParsePhoneNumber(const string16& value, - string16* number, - string16* city_code, - string16* country_code); + // Validates |number_| and translates it into digits-only format. + // Locale must be set. + bool NormalizePhone(); // Size and offset of the prefix and suffix portions of phone numbers. static const int kPrefixOffset = 0; @@ -45,53 +41,55 @@ class PhoneNumber : public FormGroup { static const int kSuffixOffset = 3; static const int kSuffixLength = 4; + // Sets locale for normalizing phone numbers. Must be called if you get + // normalized number or use NormalizePhone() function; + // Setting it to "", actually sets it to default locale - "US". + void set_locale(const std::string& locale); + // The following functions should return the field type for each part of the // phone number. Currently, these are either fax or home phone number types. - virtual AutofillFieldType GetNumberType() const = 0; - virtual AutofillFieldType GetCityCodeType() const = 0; - virtual AutofillFieldType GetCountryCodeType() const = 0; - virtual AutofillFieldType GetCityAndNumberType() const = 0; - virtual AutofillFieldType GetWholeNumberType() const = 0; + AutofillFieldType GetNumberType() const; + AutofillFieldType GetCityCodeType() const; + AutofillFieldType GetCountryCodeType() const; + AutofillFieldType GetCityAndNumberType() const; + AutofillFieldType GetWholeNumberType() const; + + // The class used to combine home phone or fax parts into a whole number. + class PhoneCombineHelper { + public: + explicit PhoneCombineHelper(AutofillType::FieldTypeGroup phone_group) + : phone_group_(phone_group) { } + // Sets PHONE_HOME/FAX_CITY_CODE, PHONE_HOME/FAX_COUNTRY_CODE, + // PHONE_HOME/FAX_CITY_AND_NUMBER, PHONE_HOME/FAX_NUMBER and returns true. + // For all other field types returs false. + bool SetInfo(AutofillFieldType type, const string16& value); + // Returns true if parsing was successful, false otherwise. + bool ParseNumber(const std::string& locale, string16* value); + + bool empty() const { return phone_.empty(); } + private: + string16 country_; + string16 city_; + string16 phone_; + AutofillType::FieldTypeGroup phone_group_; + }; private: FRIEND_TEST_ALL_PREFIXES(PhoneNumberTest, Matcher); - const string16& country_code() const { return country_code_; } - const string16& city_code() const { return city_code_; } - const string16& number() const { return number_; } - const string16& extension() const { return extension_; } - string16 CityAndNumber() const { return city_code_ + number_; } - - // Returns the entire phone number as a string, without punctuation. - virtual string16 WholeNumber() const; - - void set_country_code(const string16& country_code) { - country_code_ = country_code; - } - void set_city_code(const string16& city_code) { city_code_ = city_code; } - void set_number(const string16& number); - void set_extension(const string16& extension) { extension_ = extension; } - void set_whole_number(const string16& whole_number); - // The numbers will be digits only (no punctuation), so any call to the IsX() // functions should first call StripPunctuation on the text. - bool IsNumber(const string16& text) const; - bool IsCityCode(const string16& text) const; - bool IsCountryCode(const string16& text) const; - bool IsCityAndNumber(const string16& text) const; + bool IsNumber(const string16& text, const string16& number) const; bool IsWholeNumber(const string16& text) const; - // Verifies that |number| is a valid phone number. - bool Validate(const string16& number) const; - - // Removes any punctuation characters from |number|. static void StripPunctuation(string16* number); + // Phone group - currently it is PHONE_HOME and PHONE_FAX. + AutofillType::FieldTypeGroup phone_group_; + // Locale for phone normalizing. + std::string locale_; // The pieces of the phone number. - string16 country_code_; - string16 city_code_; // city or area code. string16 number_; - string16 extension_; }; #endif // CHROME_BROWSER_AUTOFILL_PHONE_NUMBER_H_ diff --git a/chrome/browser/autofill/phone_number_i18n.cc b/chrome/browser/autofill/phone_number_i18n.cc index 2217fb9..73ee97c 100644 --- a/chrome/browser/autofill/phone_number_i18n.cc +++ b/chrome/browser/autofill/phone_number_i18n.cc @@ -9,6 +9,7 @@ #include "base/stringprintf.h" #include "base/string_number_conversions.h" #include "base/utf_string_conversions.h" +#include "chrome/browser/autofill/autofill_country.h" #include "third_party/libphonenumber/cpp/src/phonenumberutil.h" namespace { @@ -16,8 +17,8 @@ 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"); + return AutofillCountry::CountryCodeForLocale( + AutofillCountry::ApplicationLocale()); } i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat UtilsTypeToPhoneLibType( @@ -162,6 +163,12 @@ bool ConstructPhoneNumber(const string16& country_code, 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 formatted_number; phone_util->Format(i18n_number, UtilsTypeToPhoneLibType(phone_format), diff --git a/chrome/browser/autofill/phone_number_i18n_unittest.cc b/chrome/browser/autofill/phone_number_i18n_unittest.cc index 4134a82..22a349e 100644 --- a/chrome/browser/autofill/phone_number_i18n_unittest.cc +++ b/chrome/browser/autofill/phone_number_i18n_unittest.cc @@ -283,20 +283,29 @@ TEST(PhoneNumberI18NTest, ConstructPhoneNumber) { &number)); EXPECT_EQ(number, string16()); // Italian number - EXPECT_TRUE(ConstructPhoneNumber(ASCIIToUTF16("39"), - ASCIIToUTF16(""), - ASCIIToUTF16("236618300"), - "US", + EXPECT_TRUE(ConstructPhoneNumber(ASCIIToUTF16(""), + ASCIIToUTF16("347"), + ASCIIToUTF16("2345678"), + "IT", autofill_i18n::INTERNATIONAL, &number)); - EXPECT_EQ(number, ASCIIToUTF16("+39 236618300")); - EXPECT_TRUE(ConstructPhoneNumber(ASCIIToUTF16("39"), - ASCIIToUTF16(""), - ASCIIToUTF16("236618300"), - "US", + EXPECT_EQ(number, ASCIIToUTF16("+39 347 234 5678")); + // German number. + EXPECT_TRUE(ConstructPhoneNumber(ASCIIToUTF16("49"), + ASCIIToUTF16("024"), + ASCIIToUTF16("2345678901"), + "DE", autofill_i18n::NATIONAL, &number)); - EXPECT_EQ(number, ASCIIToUTF16("236618300")); + EXPECT_EQ(number, ASCIIToUTF16("02423/45678901")); + + EXPECT_TRUE(ConstructPhoneNumber(ASCIIToUTF16("49"), + ASCIIToUTF16("024"), + ASCIIToUTF16("2345678901"), + "DE", + autofill_i18n::INTERNATIONAL, + &number)); + EXPECT_EQ(number, ASCIIToUTF16("+49 2423/45678901")); } TEST(PhoneNumberI18NTest, FormatPhone) { diff --git a/chrome/browser/autofill/phone_number_unittest.cc b/chrome/browser/autofill/phone_number_unittest.cc index 8766398..65b5952 100644 --- a/chrome/browser/autofill/phone_number_unittest.cc +++ b/chrome/browser/autofill/phone_number_unittest.cc @@ -3,126 +3,160 @@ // found in the LICENSE file. #include "base/utf_string_conversions.h" -#include "chrome/browser/autofill/home_phone_number.h" +#include "chrome/browser/autofill/field_types.h" #include "chrome/browser/autofill/phone_number.h" +#include "chrome/browser/autofill/phone_number_i18n.h" #include "testing/gtest/include/gtest/gtest.h" -// Tests the phone number parser. -TEST(PhoneNumberTest, Parser) { - string16 number; - string16 city_code; - string16 country_code; - - // Test for empty string. Should give back empty strings. - string16 phone0; - PhoneNumber::ParsePhoneNumber(phone0, &number, &city_code, &country_code); - 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")); - PhoneNumber::ParsePhoneNumber(phone1, &number, &city_code, &country_code); - EXPECT_EQ(string16(), number); - EXPECT_EQ(string16(), city_code); - EXPECT_EQ(string16(), country_code); - - // Test for string with exactly 7 digits. Should give back only phone number. - string16 phone2(ASCIIToUTF16("1234567")); - PhoneNumber::ParsePhoneNumber(phone2, &number, &city_code, &country_code); - EXPECT_EQ(ASCIIToUTF16("1234567"), number); - EXPECT_EQ(string16(), city_code); - EXPECT_EQ(string16(), country_code); - - // Test for string with exactly 7 digits and separators. Should give back - // only phone number. - string16 phone_separator2(ASCIIToUTF16("123-4567")); - PhoneNumber::ParsePhoneNumber(phone_separator2, - &number, &city_code, &country_code); - EXPECT_EQ(ASCIIToUTF16("1234567"), 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 give back only phone number. - string16 phone3(ASCIIToUTF16("123456789")); - PhoneNumber::ParsePhoneNumber(phone3, &number, &city_code, &country_code); - EXPECT_EQ(ASCIIToUTF16("3456789"), 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 give back only phone number. - string16 phone_separator3(ASCIIToUTF16("12.345-6789")); - PhoneNumber::ParsePhoneNumber(phone3, &number, &city_code, &country_code); - EXPECT_EQ(ASCIIToUTF16("3456789"), 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. - string16 phone4(ASCIIToUTF16("1234567890")); - PhoneNumber::ParsePhoneNumber(phone4, &number, &city_code, &country_code); - EXPECT_EQ(ASCIIToUTF16("4567890"), number); - EXPECT_EQ(ASCIIToUTF16("123"), 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_separator4(ASCIIToUTF16("(123) 456-7890")); - PhoneNumber::ParsePhoneNumber(phone_separator4, - &number, &city_code, &country_code); - EXPECT_EQ(ASCIIToUTF16("4567890"), number); - EXPECT_EQ(ASCIIToUTF16("123"), city_code); - EXPECT_EQ(string16(), country_code); - - // Test for string with over 10 digits. - // Should give back phone number, city code, and country code. - string16 phone5(ASCIIToUTF16("011234567890")); - PhoneNumber::ParsePhoneNumber(phone5, &number, &city_code, &country_code); - EXPECT_EQ(ASCIIToUTF16("4567890"), number); - EXPECT_EQ(ASCIIToUTF16("123"), city_code); - EXPECT_EQ(ASCIIToUTF16("01"), country_code); - - // Test for string with over 10 digits with separator characters. - // Should give back phone number, city code, and country code. - string16 phone6(ASCIIToUTF16("(01) 123-456.7890")); - PhoneNumber::ParsePhoneNumber(phone6, &number, &city_code, &country_code); - EXPECT_EQ(ASCIIToUTF16("4567890"), number); - EXPECT_EQ(ASCIIToUTF16("123"), city_code); - EXPECT_EQ(ASCIIToUTF16("01"), country_code); -} - TEST(PhoneNumberTest, Matcher) { - // Set phone number so country_code == 12, city_code = 123, number = 1234567. - string16 phone(ASCIIToUTF16("121231234567")); - HomePhoneNumber phone_number; - phone_number.set_whole_number(phone); - - EXPECT_FALSE(phone_number.IsCountryCode(ASCIIToUTF16(""))); - EXPECT_FALSE(phone_number.IsCountryCode(ASCIIToUTF16("1"))); - EXPECT_TRUE(phone_number.IsCountryCode(ASCIIToUTF16("12"))); - EXPECT_FALSE(phone_number.IsCountryCode(ASCIIToUTF16("123"))); - - EXPECT_FALSE(phone_number.IsCityCode(ASCIIToUTF16(""))); - EXPECT_FALSE(phone_number.IsCityCode(ASCIIToUTF16("1"))); - EXPECT_FALSE(phone_number.IsCityCode(ASCIIToUTF16("12"))); - EXPECT_TRUE(phone_number.IsCityCode(ASCIIToUTF16("123"))); - EXPECT_FALSE(phone_number.IsCityCode(ASCIIToUTF16("1234"))); + // Set phone number so country_code == 1, city_code = 650, number = 2345678. + string16 phone(ASCIIToUTF16("1 [650] 234-5678")); + PhoneNumber phone_number(AutofillType::PHONE_HOME); + phone_number.SetInfo(PHONE_HOME_WHOLE_NUMBER, phone); + phone_number.set_locale(std::string("US")); + phone_number.NormalizePhone(); + + FieldTypeSet matching_types; + phone_number.GetMatchingTypes(ASCIIToUTF16(""), &matching_types); + EXPECT_EQ(0U, matching_types.size()); + matching_types.clear(); + phone_number.GetMatchingTypes(ASCIIToUTF16("1"), &matching_types); + EXPECT_EQ(1U, matching_types.size()); + EXPECT_TRUE(matching_types.find(PHONE_HOME_COUNTRY_CODE) != + matching_types.end()); + matching_types.clear(); + phone_number.GetMatchingTypes(ASCIIToUTF16("16"), &matching_types); + EXPECT_EQ(0U, matching_types.size()); + phone_number.GetMatchingTypes(ASCIIToUTF16("165"), &matching_types); + EXPECT_EQ(0U, matching_types.size()); + phone_number.GetMatchingTypes(ASCIIToUTF16("1650"), &matching_types); + EXPECT_EQ(0U, matching_types.size()); + phone_number.GetMatchingTypes(ASCIIToUTF16("16502"), &matching_types); + EXPECT_EQ(0U, matching_types.size()); + phone_number.GetMatchingTypes(ASCIIToUTF16("165023"), &matching_types); + EXPECT_EQ(0U, matching_types.size()); + phone_number.GetMatchingTypes(ASCIIToUTF16("1650234"), &matching_types); + EXPECT_EQ(0U, matching_types.size()); + matching_types.clear(); + phone_number.GetMatchingTypes(ASCIIToUTF16("16502345678"), &matching_types); + EXPECT_EQ(1U, matching_types.size()); + EXPECT_TRUE(matching_types.find(PHONE_HOME_WHOLE_NUMBER) != + matching_types.end()); + matching_types.clear(); + phone_number.GetMatchingTypes(ASCIIToUTF16("650"), &matching_types); + EXPECT_EQ(1U, matching_types.size()); + EXPECT_TRUE(matching_types.find(PHONE_HOME_CITY_CODE) != + matching_types.end()); + matching_types.clear(); + phone_number.GetMatchingTypes(ASCIIToUTF16("2345678"), &matching_types); + EXPECT_EQ(1U, matching_types.size()); + EXPECT_TRUE(matching_types.find(PHONE_HOME_NUMBER) != matching_types.end()); + matching_types.clear(); + phone_number.GetMatchingTypes(ASCIIToUTF16("234"), &matching_types); + EXPECT_EQ(1U, matching_types.size()); + EXPECT_TRUE(matching_types.find(PHONE_HOME_NUMBER) != matching_types.end()); + matching_types.clear(); + phone_number.GetMatchingTypes(ASCIIToUTF16("5678"), &matching_types); + EXPECT_EQ(1U, matching_types.size()); + EXPECT_TRUE(matching_types.find(PHONE_HOME_NUMBER) != matching_types.end()); + matching_types.clear(); + phone_number.GetMatchingTypes(ASCIIToUTF16("2345"), &matching_types); + EXPECT_EQ(0U, matching_types.size()); + matching_types.clear(); + phone_number.GetMatchingTypes(ASCIIToUTF16("6502345678"), &matching_types); + EXPECT_EQ(2U, matching_types.size()); + EXPECT_TRUE(matching_types.find(PHONE_HOME_CITY_AND_NUMBER) != + matching_types.end()); + EXPECT_TRUE(matching_types.find(PHONE_HOME_WHOLE_NUMBER) != + matching_types.end()); + matching_types.clear(); + phone_number.GetMatchingTypes(ASCIIToUTF16("(650)2345678"), &matching_types); + EXPECT_EQ(2U, matching_types.size()); + EXPECT_TRUE(matching_types.find(PHONE_HOME_CITY_AND_NUMBER) != + matching_types.end()); + EXPECT_TRUE(matching_types.find(PHONE_HOME_WHOLE_NUMBER) != + matching_types.end()); + + string16 fax(ASCIIToUTF16("+1(650)650-5678")); + PhoneNumber fax_number; + fax_number.set_locale(std::string("US")); + fax_number.SetInfo(PHONE_FAX_WHOLE_NUMBER, fax); + + matching_types.clear(); + fax_number.GetMatchingTypes(ASCIIToUTF16("16506505678"), &matching_types); + EXPECT_EQ(1U, matching_types.size()); + EXPECT_TRUE(matching_types.find(PHONE_FAX_WHOLE_NUMBER) != + matching_types.end()); + + matching_types.clear(); + fax_number.GetMatchingTypes(ASCIIToUTF16("650"), &matching_types); + EXPECT_EQ(2U, matching_types.size()); + EXPECT_TRUE(matching_types.find(PHONE_FAX_CITY_CODE) != + matching_types.end()); + EXPECT_TRUE(matching_types.find(PHONE_FAX_NUMBER) != + matching_types.end()); +} - EXPECT_FALSE(phone_number.IsNumber(ASCIIToUTF16(""))); - EXPECT_FALSE(phone_number.IsNumber(ASCIIToUTF16("1"))); - EXPECT_FALSE(phone_number.IsNumber(ASCIIToUTF16("12"))); - EXPECT_TRUE(phone_number.IsNumber(ASCIIToUTF16("123"))); - EXPECT_FALSE(phone_number.IsNumber(ASCIIToUTF16("1234"))); - EXPECT_FALSE(phone_number.IsNumber(ASCIIToUTF16("12345"))); - EXPECT_FALSE(phone_number.IsNumber(ASCIIToUTF16("123456"))); - EXPECT_TRUE(phone_number.IsNumber(ASCIIToUTF16("1234567"))); - EXPECT_FALSE(phone_number.IsNumber(ASCIIToUTF16("234567"))); - EXPECT_FALSE(phone_number.IsNumber(ASCIIToUTF16("34567"))); - EXPECT_TRUE(phone_number.IsNumber(ASCIIToUTF16("4567"))); - EXPECT_FALSE(phone_number.IsNumber(ASCIIToUTF16("567"))); - EXPECT_FALSE(phone_number.IsNumber(ASCIIToUTF16("67"))); - EXPECT_FALSE(phone_number.IsNumber(ASCIIToUTF16("7"))); +TEST(PhoneNumberTest, PhoneCombineHelper) { + PhoneNumber::PhoneCombineHelper number1(AutofillType::PHONE_HOME); + EXPECT_FALSE(number1.SetInfo(ADDRESS_BILLING_CITY, + ASCIIToUTF16("1"))); + EXPECT_FALSE(number1.SetInfo(PHONE_FAX_COUNTRY_CODE, + ASCIIToUTF16("1"))); + EXPECT_TRUE(number1.SetInfo(PHONE_HOME_COUNTRY_CODE, + ASCIIToUTF16("1"))); + EXPECT_TRUE(number1.SetInfo(PHONE_HOME_CITY_CODE, + ASCIIToUTF16("650"))); + EXPECT_TRUE(number1.SetInfo(PHONE_HOME_NUMBER, + ASCIIToUTF16("2345678"))); + string16 parsed_phone; + EXPECT_TRUE(number1.ParseNumber("US", &parsed_phone)); + // International format as it has a country code. + EXPECT_EQ(ASCIIToUTF16("+1 650-234-5678"), parsed_phone); + + PhoneNumber::PhoneCombineHelper number2(AutofillType::PHONE_FAX); + EXPECT_FALSE(number2.SetInfo(PHONE_HOME_COUNTRY_CODE, + ASCIIToUTF16("1"))); + EXPECT_TRUE(number2.SetInfo(PHONE_FAX_COUNTRY_CODE, + ASCIIToUTF16("1"))); + EXPECT_TRUE(number2.SetInfo(PHONE_FAX_CITY_CODE, + ASCIIToUTF16("650"))); + EXPECT_TRUE(number2.SetInfo(PHONE_FAX_NUMBER, + ASCIIToUTF16("2345679"))); + EXPECT_TRUE(number2.ParseNumber("US", &parsed_phone)); + // International format as it has a country code. + EXPECT_EQ(ASCIIToUTF16("+1 650-234-5679"), parsed_phone); + + PhoneNumber::PhoneCombineHelper number3(AutofillType::PHONE_HOME); + EXPECT_TRUE(number3.SetInfo(PHONE_HOME_CITY_CODE, + ASCIIToUTF16("650"))); + EXPECT_TRUE(number3.SetInfo(PHONE_HOME_NUMBER, + ASCIIToUTF16("2345680"))); + EXPECT_TRUE(number3.ParseNumber("US", &parsed_phone)); + // National format as it does not have a country code. + EXPECT_EQ(ASCIIToUTF16("(650) 234-5680"), parsed_phone); + + PhoneNumber::PhoneCombineHelper number4(AutofillType::PHONE_HOME); + EXPECT_TRUE(number4.SetInfo(PHONE_HOME_CITY_CODE, + ASCIIToUTF16("123"))); // Incorrect city code. + EXPECT_TRUE(number4.SetInfo(PHONE_HOME_NUMBER, + ASCIIToUTF16("2345680"))); + EXPECT_FALSE(number4.ParseNumber("US", &parsed_phone)); + EXPECT_EQ(string16(), parsed_phone); + + PhoneNumber::PhoneCombineHelper number5(AutofillType::PHONE_HOME); + EXPECT_TRUE(number5.SetInfo(PHONE_HOME_CITY_AND_NUMBER, + ASCIIToUTF16("6502345681"))); + EXPECT_TRUE(number5.ParseNumber("US", &parsed_phone)); + EXPECT_EQ(ASCIIToUTF16("(650) 234-5681"), parsed_phone); + + PhoneNumber::PhoneCombineHelper number6(AutofillType::PHONE_HOME); + EXPECT_TRUE(number6.SetInfo(PHONE_HOME_CITY_CODE, + ASCIIToUTF16("650"))); + EXPECT_TRUE(number6.SetInfo(PHONE_HOME_NUMBER, + ASCIIToUTF16("234"))); + EXPECT_TRUE(number6.SetInfo(PHONE_HOME_NUMBER, + ASCIIToUTF16("5682"))); + EXPECT_TRUE(number6.ParseNumber("US", &parsed_phone)); + EXPECT_EQ(ASCIIToUTF16("(650) 234-5682"), parsed_phone); } diff --git a/chrome/test/data/autofill/merge/input/multimerge.in b/chrome/test/data/autofill/merge/input/multimerge.in index 9906c27..1a90fcf 100644 --- a/chrome/test/data/autofill/merge/input/multimerge.in +++ b/chrome/test/data/autofill/merge/input/multimerge.in @@ -10,8 +10,8 @@ ADDRESS_HOME_CITY: San Francisco ADDRESS_HOME_STATE: CA ADDRESS_HOME_ZIP: 94102 ADDRESS_HOME_COUNTRY: United States -PHONE_HOME_WHOLE_NUMBER: 1110001111 -PHONE_FAX_WHOLE_NUMBER: 8880008888 +PHONE_HOME_WHOLE_NUMBER: 16502101111 +PHONE_FAX_WHOLE_NUMBER: 7812008888 --- NAME_FIRST: Billy NAME_MIDDLE: Bob @@ -24,5 +24,5 @@ ADDRESS_HOME_CITY: San Francisco ADDRESS_HOME_STATE: CA ADDRESS_HOME_ZIP: 94102 ADDRESS_HOME_COUNTRY: United States -PHONE_HOME_WHOLE_NUMBER: 2220003333 -PHONE_FAX_WHOLE_NUMBER: 8880008888 +PHONE_HOME_WHOLE_NUMBER: 6502343333 +PHONE_FAX_WHOLE_NUMBER: 7812008888 diff --git a/chrome/test/data/autofill/merge/input/primarycase.in b/chrome/test/data/autofill/merge/input/primarycase.in index e546f1d3..73dc04b6 100644 --- a/chrome/test/data/autofill/merge/input/primarycase.in +++ b/chrome/test/data/autofill/merge/input/primarycase.in @@ -10,8 +10,8 @@ ADDRESS_HOME_CITY: SAN FRANCISCO ADDRESS_HOME_STATE: CA ADDRESS_HOME_ZIP: 94102 ADDRESS_HOME_COUNTRY: United States -PHONE_HOME_WHOLE_NUMBER: 1110001111 -PHONE_FAX_WHOLE_NUMBER: 8880008888 +PHONE_HOME_WHOLE_NUMBER: 16502101111 +PHONE_FAX_WHOLE_NUMBER: 7812008888 --- NAME_FIRST: Billy NAME_MIDDLE: Bob @@ -24,5 +24,5 @@ ADDRESS_HOME_CITY: San Francisco ADDRESS_HOME_STATE: CA ADDRESS_HOME_ZIP: 94102 ADDRESS_HOME_COUNTRY: United States -PHONE_HOME_WHOLE_NUMBER: 2220003333 -PHONE_FAX_WHOLE_NUMBER: 8880008888 +PHONE_HOME_WHOLE_NUMBER: 6502343333 +PHONE_FAX_WHOLE_NUMBER: 7812008888 diff --git a/chrome/test/data/autofill/merge/input/singlemerge.in b/chrome/test/data/autofill/merge/input/singlemerge.in index f264015..58231f4 100644 --- a/chrome/test/data/autofill/merge/input/singlemerge.in +++ b/chrome/test/data/autofill/merge/input/singlemerge.in @@ -10,8 +10,8 @@ ADDRESS_HOME_CITY: San Francisco ADDRESS_HOME_STATE: CA ADDRESS_HOME_ZIP: 94102 ADDRESS_HOME_COUNTRY: United States -PHONE_HOME_WHOLE_NUMBER: 1110001111 -PHONE_FAX_WHOLE_NUMBER: 8880008888 +PHONE_HOME_WHOLE_NUMBER: 16502101111 +PHONE_FAX_WHOLE_NUMBER: 7812008888 --- NAME_FIRST: Alice NAME_MIDDLE: Anne @@ -24,5 +24,5 @@ ADDRESS_HOME_CITY: San Francisco ADDRESS_HOME_STATE: NY ADDRESS_HOME_ZIP: 11001 ADDRESS_HOME_COUNTRY: Canada -PHONE_HOME_WHOLE_NUMBER: 1110001111 -PHONE_FAX_WHOLE_NUMBER: 8880008888 +PHONE_HOME_WHOLE_NUMBER: 16502101111 +PHONE_FAX_WHOLE_NUMBER: 7812008888 diff --git a/chrome/test/data/autofill/merge/output/multimerge.out b/chrome/test/data/autofill/merge/output/multimerge.out index 260f8bb..c0ca01d 100644 --- a/chrome/test/data/autofill/merge/output/multimerge.out +++ b/chrome/test/data/autofill/merge/output/multimerge.out @@ -14,6 +14,6 @@ ADDRESS_HOME_CITY: San Francisco ADDRESS_HOME_STATE: CA ADDRESS_HOME_ZIP: 94102 ADDRESS_HOME_COUNTRY: United States -PHONE_HOME_WHOLE_NUMBER: 1110001111 -PHONE_HOME_WHOLE_NUMBER: 2220003333 -PHONE_FAX_WHOLE_NUMBER: 8880008888 +PHONE_HOME_WHOLE_NUMBER: 16502101111 +PHONE_HOME_WHOLE_NUMBER: 6502343333 +PHONE_FAX_WHOLE_NUMBER: 7812008888 diff --git a/chrome/test/data/autofill/merge/output/primarycase.out b/chrome/test/data/autofill/merge/output/primarycase.out index 260f8bb..c0ca01d 100644 --- a/chrome/test/data/autofill/merge/output/primarycase.out +++ b/chrome/test/data/autofill/merge/output/primarycase.out @@ -14,6 +14,6 @@ ADDRESS_HOME_CITY: San Francisco ADDRESS_HOME_STATE: CA ADDRESS_HOME_ZIP: 94102 ADDRESS_HOME_COUNTRY: United States -PHONE_HOME_WHOLE_NUMBER: 1110001111 -PHONE_HOME_WHOLE_NUMBER: 2220003333 -PHONE_FAX_WHOLE_NUMBER: 8880008888 +PHONE_HOME_WHOLE_NUMBER: 16502101111 +PHONE_HOME_WHOLE_NUMBER: 6502343333 +PHONE_FAX_WHOLE_NUMBER: 7812008888 diff --git a/chrome/test/data/autofill/merge/output/singlemerge.out b/chrome/test/data/autofill/merge/output/singlemerge.out index 3181458..c0a25903 100644 --- a/chrome/test/data/autofill/merge/output/singlemerge.out +++ b/chrome/test/data/autofill/merge/output/singlemerge.out @@ -10,5 +10,5 @@ ADDRESS_HOME_CITY: San Francisco ADDRESS_HOME_STATE: NY ADDRESS_HOME_ZIP: 11001 ADDRESS_HOME_COUNTRY: Canada -PHONE_HOME_WHOLE_NUMBER: 1110001111 -PHONE_FAX_WHOLE_NUMBER: 8880008888 +PHONE_HOME_WHOLE_NUMBER: 16502101111 +PHONE_FAX_WHOLE_NUMBER: 7812008888 |