summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorisherman@chromium.org <isherman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-22 08:29:32 +0000
committerisherman@chromium.org <isherman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-22 08:29:32 +0000
commitfcfece45185268c1a55260a1d5c0abfbceaffe1f (patch)
treebab09f97a07ef8931e297f3801d792f0067ae407 /chrome
parentb4291aefaf817107e62694d540c427a7d115bdea (diff)
downloadchromium_src-fcfece45185268c1a55260a1d5c0abfbceaffe1f.zip
chromium_src-fcfece45185268c1a55260a1d5c0abfbceaffe1f.tar.gz
chromium_src-fcfece45185268c1a55260a1d5c0abfbceaffe1f.tar.bz2
Consolidate Autofill possible type detection code, and enforce greater match precision.
* Only consider submitted field values to match locally stored data if the strings match exactly + This means we will send fewer false positives to the server, at the cost of some false negatives. Most importantly, we should stop identifying ADDRESS_LINE_2 fields as ADDRESS_LINE_1. + There are a few excpetions for structured fields with canonicalized values, like countries (which are canonicalized to country codes) * Eliminate FormGroup::GetMatchingTypes() -- all of this work is now done in a consistent way within AutofillManager * Refactor FormGroup::GetNonEmptyTypes() to be shared code. BUG=81867, 76992 TEST=unit_tests --gtest_filter=AutofillManagerTest.DeterminePossibleFieldTypesForUpload Review URL: http://codereview.chromium.org/7398019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93582 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/autofill/address.cc173
-rw-r--r--chrome/browser/autofill/address.h41
-rw-r--r--chrome/browser/autofill/autofill_ie_toolbar_import_win.cc12
-rw-r--r--chrome/browser/autofill/autofill_ie_toolbar_import_win_unittest.cc58
-rw-r--r--chrome/browser/autofill/autofill_manager.cc76
-rw-r--r--chrome/browser/autofill/autofill_manager.h2
-rw-r--r--chrome/browser/autofill/autofill_manager_unittest.cc294
-rw-r--r--chrome/browser/autofill/autofill_metrics_unittest.cc24
-rw-r--r--chrome/browser/autofill/autofill_profile.cc96
-rw-r--r--chrome/browser/autofill/autofill_profile.h27
-rw-r--r--chrome/browser/autofill/autofill_profile_unittest.cc3
-rw-r--r--chrome/browser/autofill/contact_info.cc253
-rw-r--r--chrome/browser/autofill/contact_info.h75
-rw-r--r--chrome/browser/autofill/credit_card.cc137
-rw-r--r--chrome/browser/autofill/credit_card.h36
-rw-r--r--chrome/browser/autofill/fax_number.cc9
-rw-r--r--chrome/browser/autofill/fax_number.h2
-rw-r--r--chrome/browser/autofill/form_group.cc39
-rw-r--r--chrome/browser/autofill/form_group.h27
-rw-r--r--chrome/browser/autofill/home_phone_number.cc7
-rw-r--r--chrome/browser/autofill/home_phone_number.h2
-rw-r--r--chrome/browser/autofill/personal_data_manager.cc85
-rw-r--r--chrome/browser/autofill/personal_data_manager.h5
-rw-r--r--chrome/browser/autofill/personal_data_manager_mac.mm1
-rw-r--r--chrome/browser/autofill/phone_field.cc4
-rw-r--r--chrome/browser/autofill/phone_number.cc238
-rw-r--r--chrome/browser/autofill/phone_number.h69
-rw-r--r--chrome/browser/autofill/phone_number_i18n.cc1
-rw-r--r--chrome/browser/autofill/phone_number_unittest.cc20
-rw-r--r--chrome/browser/autofill/select_control_handler.cc2
-rw-r--r--chrome/browser/webdata/autofill_table.cc6
-rw-r--r--chrome/test/data/autofill/merge/output/case.out4
-rw-r--r--chrome/test/data/autofill/merge/output/identical.out4
-rw-r--r--chrome/test/data/autofill/merge/output/multimerge.out6
-rw-r--r--chrome/test/data/autofill/merge/output/primarycase.out6
-rw-r--r--chrome/test/data/autofill/merge/output/singlemerge.out4
-rw-r--r--chrome/test/data/autofill/merge/output/validation.out4
37 files changed, 870 insertions, 982 deletions
diff --git a/chrome/browser/autofill/address.cc b/chrome/browser/autofill/address.cc
index 0a687a1..6b2d345 100644
--- a/chrome/browser/autofill/address.cc
+++ b/chrome/browser/autofill/address.cc
@@ -28,6 +28,13 @@ const AutofillType::FieldTypeSubGroup kAutofillAddressTypes[] = {
const int kAutofillAddressLength = arraysize(kAutofillAddressTypes);
+// Returns the country code corresponding to |country|, which should be a
+// localized country name.
+std::string ToCountryCode(const string16& country) {
+ std::string app_locale = AutofillCountry::ApplicationLocale();
+ return AutofillCountry::GetCountryCode(country, app_locale);
+}
+
} // namespace
Address::Address() {}
@@ -42,8 +49,6 @@ Address& Address::operator=(const Address& address) {
if (this == &address)
return *this;
- line1_tokens_ = address.line1_tokens_;
- line2_tokens_= address.line2_tokens_;
line1_ = address.line1_;
line2_ = address.line2_;
city_ = address.city_;
@@ -53,54 +58,13 @@ Address& Address::operator=(const Address& address) {
return *this;
}
-void Address::GetMatchingTypes(const string16& text,
- FieldTypeSet* matching_types) const {
- DCHECK(matching_types);
-
- // If the text to match against the field types is empty, then no results will
- // match.
- if (text.empty())
- return;
-
- if (IsLine1(text))
- matching_types->insert(ADDRESS_HOME_LINE1);
-
- if (IsLine2(text))
- matching_types->insert(ADDRESS_HOME_LINE2);
-
- if (IsCity(text))
- matching_types->insert(ADDRESS_HOME_CITY);
-
- if (IsState(text))
- matching_types->insert(ADDRESS_HOME_STATE);
-
- if (IsZipCode(text))
- matching_types->insert(ADDRESS_HOME_ZIP);
-
- if (IsCountry(text))
- matching_types->insert(ADDRESS_HOME_COUNTRY);
-}
-
-void Address::GetNonEmptyTypes(FieldTypeSet* non_empty_types) const {
- DCHECK(non_empty_types);
-
- if (!line1_.empty())
- non_empty_types->insert(ADDRESS_HOME_LINE1);
-
- if (!line2_.empty())
- non_empty_types->insert(ADDRESS_HOME_LINE2);
-
- if (!city_.empty())
- non_empty_types->insert(ADDRESS_HOME_CITY);
-
- if (!state_.empty())
- non_empty_types->insert(ADDRESS_HOME_STATE);
-
- if (!zip_code_.empty())
- non_empty_types->insert(ADDRESS_HOME_ZIP);
-
- if (!country_code_.empty())
- non_empty_types->insert(ADDRESS_HOME_COUNTRY);
+void Address::GetSupportedTypes(FieldTypeSet* supported_types) const {
+ supported_types->insert(ADDRESS_HOME_LINE1);
+ supported_types->insert(ADDRESS_HOME_LINE2);
+ supported_types->insert(ADDRESS_HOME_CITY);
+ supported_types->insert(ADDRESS_HOME_STATE);
+ supported_types->insert(ADDRESS_HOME_ZIP);
+ supported_types->insert(ADDRESS_HOME_COUNTRY);
}
string16 Address::GetInfo(AutofillFieldType type) const {
@@ -128,30 +92,29 @@ string16 Address::GetInfo(AutofillFieldType type) const {
void Address::SetInfo(AutofillFieldType type, const string16& value) {
FieldTypeSubGroup subgroup = AutofillType(type).subgroup();
if (subgroup == AutofillType::ADDRESS_LINE1)
- set_line1(value);
+ line1_ = value;
else if (subgroup == AutofillType::ADDRESS_LINE2)
- set_line2(value);
+ line2_ = value;
else if (subgroup == AutofillType::ADDRESS_CITY)
city_ = value;
else if (subgroup == AutofillType::ADDRESS_STATE)
state_ = value;
else if (subgroup == AutofillType::ADDRESS_COUNTRY)
- SetCountry(value);
+ country_code_ = ToCountryCode(value);
else if (subgroup == AutofillType::ADDRESS_ZIP)
zip_code_ = value;
else
NOTREACHED();
}
-void Address::Clear() {
- line1_tokens_.clear();
- line1_.clear();
- line2_tokens_.clear();
- line2_.clear();
- city_.clear();
- state_.clear();
- country_code_.clear();
- zip_code_.clear();
+void Address::GetMatchingTypes(const string16& text,
+ FieldTypeSet* matching_types) const {
+ FormGroup::GetMatchingTypes(text, matching_types);
+
+ // Check to see if the |text| canonicalized as a country name is a match.
+ std::string country_code = ToCountryCode(text);
+ if (!country_code.empty() && country_code_ == country_code)
+ matching_types->insert(ADDRESS_HOME_COUNTRY);
}
string16 Address::Country() const {
@@ -161,89 +124,3 @@ string16 Address::Country() const {
std::string app_locale = AutofillCountry::ApplicationLocale();
return AutofillCountry(country_code(), app_locale).name();
}
-
-void Address::set_line1(const string16& line1) {
- line1_ = line1;
- line1_tokens_.clear();
- Tokenize(line1, kAddressSplitChars, &line1_tokens_);
- LineTokens::iterator iter;
- for (iter = line1_tokens_.begin(); iter != line1_tokens_.end(); ++iter)
- *iter = StringToLowerASCII(*iter);
-}
-
-void Address::set_line2(const string16& line2) {
- line2_ = line2;
- line2_tokens_.clear();
- Tokenize(line2, kAddressSplitChars, &line2_tokens_);
- LineTokens::iterator iter;
- for (iter = line2_tokens_.begin(); iter != line2_tokens_.end(); ++iter)
- *iter = StringToLowerASCII(*iter);
-}
-
-void Address::SetCountry(const string16& country) {
- std::string app_locale = AutofillCountry::ApplicationLocale();
- country_code_ = AutofillCountry::GetCountryCode(country, app_locale);
-}
-
-bool Address::IsLine1(const string16& text) const {
- return IsLineMatch(text, line1_tokens_);
-}
-
-bool Address::IsLine2(const string16& text) const {
- return IsLineMatch(text, line2_tokens_);
-}
-
-bool Address::IsCity(const string16& text) const {
- return (StringToLowerASCII(city_) == StringToLowerASCII(text));
-}
-
-bool Address::IsState(const string16& text) const {
- return (StringToLowerASCII(state_) == StringToLowerASCII(text));
-}
-
-bool Address::IsCountry(const string16& text) const {
- std::string app_locale = AutofillCountry::ApplicationLocale();
- std::string country_code = AutofillCountry::GetCountryCode(text, app_locale);
- return (!country_code.empty() && country_code_ == country_code);
-}
-
-bool Address::IsZipCode(const string16& text) const {
- return zip_code_ == text;
-}
-
-bool Address::IsLineMatch(const string16& text,
- const LineTokens& line_tokens) const {
- size_t line_tokens_size = line_tokens.size();
- if (line_tokens_size == 0)
- return false;
-
- LineTokens text_tokens;
- Tokenize(text, kAddressSplitChars, &text_tokens);
- size_t text_tokens_size = text_tokens.size();
- if (text_tokens_size == 0)
- return false;
-
- if (text_tokens_size > line_tokens_size)
- return false;
-
- // If each of the 'words' contained in the text are also present in the line,
- // then we will consider the text to match the line.
- LineTokens::iterator iter;
- for (iter = text_tokens.begin(); iter != text_tokens.end(); ++iter) {
- if (!IsWordInLine(*iter, line_tokens))
- return false;
- }
-
- return true;
-}
-
-bool Address::IsWordInLine(const string16& word,
- const LineTokens& line_tokens) const {
- LineTokens::const_iterator iter;
- for (iter = line_tokens.begin(); iter != line_tokens.end(); ++iter) {
- if (StringToLowerASCII(word) == *iter)
- return true;
- }
-
- return false;
-}
diff --git a/chrome/browser/autofill/address.h b/chrome/browser/autofill/address.h
index 1a4cf04..f03bbf1 100644
--- a/chrome/browser/autofill/address.h
+++ b/chrome/browser/autofill/address.h
@@ -24,54 +24,23 @@ class Address : public FormGroup {
Address& operator=(const Address& address);
// FormGroup:
+ virtual string16 GetInfo(AutofillFieldType type) const OVERRIDE;
+ virtual void SetInfo(AutofillFieldType type, const string16& value) OVERRIDE;
virtual void GetMatchingTypes(const string16& text,
- FieldTypeSet* matching_types) const;
- virtual void GetNonEmptyTypes(FieldTypeSet* non_empty_types) const;
- virtual string16 GetInfo(AutofillFieldType type) const;
- virtual void SetInfo(AutofillFieldType type, const string16& value);
+ FieldTypeSet* matching_types) const OVERRIDE;
const std::string& country_code() const { return country_code_; }
void set_country_code(const std::string& country_code) {
country_code_ = country_code;
}
- // Sets all of the fields to the empty string.
- void Clear();
-
private:
- // Vector of tokens in an address line.
- typedef std::vector<string16> LineTokens;
+ // FormGroup:
+ virtual void GetSupportedTypes(FieldTypeSet* supported_types) const OVERRIDE;
// Returns the localized country name corresponding to |country_code_|.
string16 Country() const;
- void set_line1(const string16& line1);
- void set_line2(const string16& line2);
-
- // Sets the |country_code_| based on |country|, which should be a localized
- // country name.
- void SetCountry(const string16& country);
-
- // The following functions match |text| against the various values of the
- // address, returning true on match.
- virtual bool IsLine1(const string16& text) const;
- virtual bool IsLine2(const string16& text) const;
- virtual bool IsCity(const string16& text) const;
- virtual bool IsState(const string16& text) const;
- virtual bool IsCountry(const string16& text) const;
- virtual bool IsZipCode(const string16& text) const;
-
- // Returns true if all of the tokens in |text| match the tokens in
- // |line_tokens|.
- bool IsLineMatch(const string16& text, const LineTokens& line_tokens) const;
-
- // Returns true if |word| is one of the tokens in |line_tokens|.
- bool IsWordInLine(const string16& word, const LineTokens& line_tokens) const;
-
- // List of tokens in each part of |line1_| and |line2_|.
- LineTokens line1_tokens_;
- LineTokens line2_tokens_;
-
// The address.
string16 line1_;
string16 line2_;
diff --git a/chrome/browser/autofill/autofill_ie_toolbar_import_win.cc b/chrome/browser/autofill/autofill_ie_toolbar_import_win.cc
index 96a4ba1..eacbacb 100644
--- a/chrome/browser/autofill/autofill_ie_toolbar_import_win.cc
+++ b/chrome/browser/autofill/autofill_ie_toolbar_import_win.cc
@@ -160,10 +160,14 @@ bool ImportSingleProfile(FormGroup* profile,
}
// 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);
+ if (!home.IsEmpty() &&
+ home.ParseNumber(std::string("US"), &constructed_number)) {
+ profile->SetCanonicalizedInfo(PHONE_HOME_WHOLE_NUMBER, constructed_number);
+ }
+ if (!fax.IsEmpty() &&
+ fax.ParseNumber(std::string("US"), &constructed_number)) {
+ profile->SetCanonicalizedInfo(PHONE_FAX_WHOLE_NUMBER, constructed_number);
+ }
return has_non_empty_fields;
}
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 240055f..f98e52a 100644
--- a/chrome/browser/autofill/autofill_ie_toolbar_import_win_unittest.cc
+++ b/chrome/browser/autofill/autofill_ie_toolbar_import_win_unittest.cc
@@ -161,34 +161,34 @@ TEST_F(AutofillIeToolbarImportTest, TestAutofillImport) {
std::vector<AutofillProfile> profiles;
std::vector<CreditCard> credit_cards;
EXPECT_TRUE(ImportCurrentUserProfiles(&profiles, &credit_cards));
- ASSERT_EQ(profiles.size(), 2);
+ ASSERT_EQ(2U, profiles.size());
// The profiles are read in reverse order.
- EXPECT_EQ(profiles[1].GetInfo(NAME_FIRST), profile1[0].value);
- EXPECT_EQ(profiles[1].GetInfo(NAME_MIDDLE), profile1[1].value);
- EXPECT_EQ(profiles[1].GetInfo(NAME_LAST), profile1[2].value);
- EXPECT_EQ(profiles[1].GetInfo(EMAIL_ADDRESS), profile1[3].value);
- EXPECT_EQ(profiles[1].GetInfo(COMPANY_NAME), profile1[4].value);
- 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"+16505555555");
-
- EXPECT_EQ(profiles[0].GetInfo(NAME_FIRST), profile2[0].value);
- EXPECT_EQ(profiles[0].GetInfo(NAME_LAST), profile2[1].value);
- EXPECT_EQ(profiles[0].GetInfo(EMAIL_ADDRESS), profile2[2].value);
- EXPECT_EQ(profiles[0].GetInfo(COMPANY_NAME), profile2[3].value);
- 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"+78125556666");
-
- ASSERT_EQ(credit_cards.size(), 1);
- EXPECT_EQ(credit_cards[0].GetInfo(CREDIT_CARD_NAME), credit_card[0].value);
- EXPECT_EQ(credit_cards[0].GetInfo(CREDIT_CARD_NUMBER), L"4111111111111111");
- EXPECT_EQ(credit_cards[0].GetInfo(CREDIT_CARD_EXP_MONTH),
- credit_card[2].value);
- EXPECT_EQ(credit_cards[0].GetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR),
- credit_card[3].value);
+ EXPECT_EQ(profile1[0].value, profiles[1].GetInfo(NAME_FIRST));
+ EXPECT_EQ(profile1[1].value, profiles[1].GetInfo(NAME_MIDDLE));
+ EXPECT_EQ(profile1[2].value, profiles[1].GetInfo(NAME_LAST));
+ EXPECT_EQ(profile1[3].value, profiles[1].GetInfo(EMAIL_ADDRESS));
+ EXPECT_EQ(profile1[4].value, profiles[1].GetInfo(COMPANY_NAME));
+ EXPECT_EQ(profile1[7].value, profiles[1].GetInfo(PHONE_HOME_COUNTRY_CODE));
+ EXPECT_EQ(profile1[6].value, profiles[1].GetInfo(PHONE_HOME_CITY_CODE));
+ EXPECT_EQ(L"5555555", profiles[1].GetInfo(PHONE_HOME_NUMBER));
+ EXPECT_EQ(L"+1 650-555-5555", profiles[1].GetInfo(PHONE_HOME_WHOLE_NUMBER));
+
+ EXPECT_EQ(profile2[0].value, profiles[0].GetInfo(NAME_FIRST));
+ EXPECT_EQ(profile2[1].value, profiles[0].GetInfo(NAME_LAST));
+ EXPECT_EQ(profile2[2].value, profiles[0].GetInfo(EMAIL_ADDRESS));
+ EXPECT_EQ(profile2[3].value, profiles[0].GetInfo(COMPANY_NAME));
+ EXPECT_EQ(profile2[6].value, profiles[0].GetInfo(PHONE_FAX_COUNTRY_CODE));
+ EXPECT_EQ(profile2[5].value, profiles[0].GetInfo(PHONE_FAX_CITY_CODE));
+ EXPECT_EQ(L"5556666", profiles[0].GetInfo(PHONE_FAX_NUMBER));
+ EXPECT_EQ(L"+7 812 555-66-66", profiles[0].GetInfo(PHONE_FAX_WHOLE_NUMBER));
+
+ ASSERT_EQ(1U, credit_cards.size());
+ EXPECT_EQ(credit_card[0].value, credit_cards[0].GetInfo(CREDIT_CARD_NAME));
+ EXPECT_EQ(L"4111111111111111", credit_cards[0].GetInfo(CREDIT_CARD_NUMBER));
+ EXPECT_EQ(credit_card[2].value,
+ credit_cards[0].GetInfo(CREDIT_CARD_EXP_MONTH));
+ EXPECT_EQ(credit_card[3].value,
+ credit_cards[0].GetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
// Mock password encrypted cc.
cc_key.Open(HKEY_CURRENT_USER, kCreditCardKey, KEY_ALL_ACCESS);
@@ -201,8 +201,8 @@ TEST_F(AutofillIeToolbarImportTest, TestAutofillImport) {
credit_cards.clear();
EXPECT_TRUE(ImportCurrentUserProfiles(&profiles, &credit_cards));
// Profiles are not protected.
- EXPECT_EQ(profiles.size(), 2);
+ EXPECT_EQ(2U, profiles.size());
// Credit cards are.
- EXPECT_EQ(credit_cards.size(), 0);
+ EXPECT_EQ(0U, credit_cards.size());
}
diff --git a/chrome/browser/autofill/autofill_manager.cc b/chrome/browser/autofill/autofill_manager.cc
index b9d133e..7e339e9 100644
--- a/chrome/browser/autofill/autofill_manager.cc
+++ b/chrome/browser/autofill/autofill_manager.cc
@@ -227,30 +227,6 @@ 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;
- }
-}
-
// Check for unidentified forms among those with the most query or upload
// requests. If found, present an infobar prompting the user to send Google
// Feedback identifying these forms. Only executes if the appropriate flag is
@@ -751,13 +727,30 @@ bool AutofillManager::IsAutofillEnabled() const {
void AutofillManager::DeterminePossibleFieldTypesForUpload(
FormStructure* submitted_form) {
+ // Combine all the profiles and credit cards stored in |personal_data_| into
+ // one vector for ease of iteration.
+ const std::vector<AutofillProfile*>& profiles = personal_data_->profiles();
+ const std::vector<CreditCard*>& credit_cards = personal_data_->credit_cards();
+ std::vector<FormGroup*> stored_data;
+ stored_data.insert(stored_data.end(), profiles.begin(), profiles.end());
+ stored_data.insert(stored_data.end(), credit_cards.begin(),
+ credit_cards.end());
+
+ // For each field in the |submitted_form|, extract the value. Then for each
+ // profile or credit card, identify any stored types that match the value.
for (size_t i = 0; i < submitted_form->field_count(); i++) {
const AutofillField* field = submitted_form->field(i);
- FieldTypeSet field_types;
- personal_data_->GetMatchingTypes(field->value, &field_types);
+ string16 value = CollapseWhitespace(field->value, false);
+ FieldTypeSet matching_types;
+ for (std::vector<FormGroup*>::const_iterator it = stored_data.begin();
+ it != stored_data.end(); ++it) {
+ (*it)->GetMatchingTypes(value, &matching_types);
+ }
+
+ if (matching_types.empty())
+ matching_types.insert(UNKNOWN_TYPE);
- DCHECK(!field_types.empty());
- submitted_form->set_possible_types(i, field_types);
+ submitted_form->set_possible_types(i, matching_types);
}
}
@@ -904,8 +897,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);
+ profile->GetCanonicalizedMultiInfo(type, &multi_values);
for (size_t i = 0; i < multi_values.size(); ++i) {
if (!multi_values[i].empty() &&
@@ -938,8 +930,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);
+ profile->GetCanonicalizedMultiInfo(type, &multi_values);
for (size_t i = 0; i < multi_values.size(); ++i) {
if (multi_values[i].empty())
@@ -991,7 +982,8 @@ void AutofillManager::GetCreditCardSuggestions(FormStructure* form,
CreditCard* credit_card = *iter;
// The value of the stored data for this field type in the |credit_card|.
- string16 creditcard_field_value = credit_card->GetInfo(type);
+ string16 creditcard_field_value =
+ credit_card->GetCanonicalizedInfo(type);
if (!creditcard_field_value.empty() &&
StartsWith(creditcard_field_value, field.value, false)) {
if (type == CREDIT_CARD_NUMBER)
@@ -1000,7 +992,7 @@ void AutofillManager::GetCreditCardSuggestions(FormStructure* form,
string16 label;
if (credit_card->number().empty()) {
// If there is no CC number, return name to show something.
- label = credit_card->GetInfo(CREDIT_CARD_NAME);
+ label = credit_card->GetCanonicalizedInfo(CREDIT_CARD_NAME);
} else {
label = kCreditCardPrefix;
label.append(credit_card->LastFourDigits());
@@ -1026,18 +1018,16 @@ void AutofillManager::FillCreditCardFormField(const CreditCard* credit_card,
autofill::FillSelectControl(*credit_card, type, field);
} else if (field->form_control_type == ASCIIToUTF16("month")) {
// HTML5 input="month" consists of year-month.
- string16 year = credit_card->GetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR);
- string16 month = credit_card->GetInfo(CREDIT_CARD_EXP_MONTH);
+ string16 year =
+ credit_card->GetCanonicalizedInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR);
+ string16 month = credit_card->GetCanonicalizedInfo(CREDIT_CARD_EXP_MONTH);
if (!year.empty() && !month.empty()) {
// Fill the value only if |credit_card| includes both year and month
// information.
field->value = year + ASCIIToUTF16("-") + month;
}
} else {
- string16 value = credit_card->GetInfo(type);
- if (type == CREDIT_CARD_NUMBER)
- value = CreditCard::StripSeparators(value);
- field->value = value;
+ field->value = credit_card->GetCanonicalizedInfo(type);
}
}
@@ -1056,8 +1046,7 @@ void AutofillManager::FillFormField(const AutofillProfile* profile,
autofill::FillSelectControl(*profile, type, field);
} else {
std::vector<string16> values;
- profile->GetMultiInfo(type, &values);
- NormalizePhoneMultiInfo(type, profile->CountryCode(), &values);
+ profile->GetCanonicalizedMultiInfo(type, &values);
DCHECK(variant < values.size());
field->value = values[variant];
}
@@ -1071,8 +1060,7 @@ void AutofillManager::FillPhoneNumberField(const AutofillProfile* profile,
// If we are filling a phone number, check to see if the size field
// matches the "prefix" or "suffix" sizes and fill accordingly.
std::vector<string16> values;
- profile->GetMultiInfo(type, &values);
- NormalizePhoneMultiInfo(type, profile->CountryCode(), &values);
+ profile->GetCanonicalizedMultiInfo(type, &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.h b/chrome/browser/autofill/autofill_manager.h
index 91d819c..ce2d133 100644
--- a/chrome/browser/autofill/autofill_manager.h
+++ b/chrome/browser/autofill/autofill_manager.h
@@ -251,6 +251,8 @@ class AutofillManager : public TabContentsObserver,
FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest, FormSubmittedWithDefaultValues);
FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest,
DeterminePossibleFieldTypesForUpload);
+ FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest,
+ DeterminePossibleFieldTypesForUploadStressTest);
FRIEND_TEST_ALL_PREFIXES(AutofillMetricsTest, AddressSuggestionsCount);
FRIEND_TEST_ALL_PREFIXES(AutofillMetricsTest, AutofillIsEnabledAtPageLoad);
FRIEND_TEST_ALL_PREFIXES(AutofillMetricsTest,
diff --git a/chrome/browser/autofill/autofill_manager_unittest.cc b/chrome/browser/autofill/autofill_manager_unittest.cc
index 21d2281..74df40c 100644
--- a/chrome/browser/autofill/autofill_manager_unittest.cc
+++ b/chrome/browser/autofill/autofill_manager_unittest.cc
@@ -2190,6 +2190,300 @@ TEST_F(AutofillManagerTest, AuxiliaryProfilesReset) {
}
TEST_F(AutofillManagerTest, DeterminePossibleFieldTypesForUpload) {
+ FormData form;
+ form.name = ASCIIToUTF16("MyForm");
+ form.method = ASCIIToUTF16("POST");
+ form.origin = GURL("http://myform.com/form.html");
+ form.action = GURL("http://myform.com/submit.html");
+ form.user_submitted = true;
+
+ std::vector<FieldTypeSet> expected_types;
+
+ // These fields should all match.
+ FormField field;
+ FieldTypeSet types;
+ autofill_test::CreateTestFormField("", "1", "Elvis", "text", &field);
+ types.clear();
+ types.insert(NAME_FIRST);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "2", "Aaron", "text", &field);
+ types.clear();
+ types.insert(NAME_MIDDLE);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "3", "A", "text", &field);
+ types.clear();
+ types.insert(NAME_MIDDLE_INITIAL);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "4", "Presley", "text", &field);
+ types.clear();
+ types.insert(NAME_LAST);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "5", "Elvis Presley", "text", &field);
+ types.clear();
+ types.insert(CREDIT_CARD_NAME);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "6", "Elvis Aaron Presley", "text",
+ &field);
+ types.clear();
+ types.insert(NAME_FULL);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "7", "theking@gmail.com", "email",
+ &field);
+ types.clear();
+ types.insert(EMAIL_ADDRESS);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "8", "RCA", "text", &field);
+ types.clear();
+ types.insert(COMPANY_NAME);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "9", "3734 Elvis Presley Blvd.",
+ "text", &field);
+ types.clear();
+ types.insert(ADDRESS_HOME_LINE1);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "10", "Apt. 10", "text", &field);
+ types.clear();
+ types.insert(ADDRESS_HOME_LINE2);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "11", "Memphis", "text", &field);
+ types.clear();
+ types.insert(ADDRESS_HOME_CITY);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "12", "Tennessee", "text", &field);
+ types.clear();
+ types.insert(ADDRESS_HOME_STATE);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "13", "38116", "text", &field);
+ types.clear();
+ types.insert(ADDRESS_HOME_ZIP);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "14", "USA", "text", &field);
+ types.clear();
+ types.insert(ADDRESS_HOME_COUNTRY);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "15", "United States", "text", &field);
+ types.clear();
+ types.insert(ADDRESS_HOME_COUNTRY);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "16", "+1 (234) 567-8901", "text",
+ &field);
+ types.clear();
+ types.insert(PHONE_HOME_WHOLE_NUMBER);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "17", "2345678901", "text", &field);
+ types.clear();
+ types.insert(PHONE_HOME_CITY_AND_NUMBER);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "18", "1", "text", &field);
+ types.clear();
+ types.insert(PHONE_HOME_COUNTRY_CODE);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "19", "234", "text", &field);
+ types.clear();
+ types.insert(PHONE_HOME_CITY_CODE);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "20", "5678901", "text", &field);
+ types.clear();
+ types.insert(PHONE_HOME_NUMBER);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "21", "567", "text", &field);
+ types.clear();
+ types.insert(PHONE_HOME_NUMBER);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "22", "8901", "text", &field);
+ types.clear();
+ types.insert(PHONE_HOME_NUMBER);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "23", "4234-5678-9012-3456", "text",
+ &field);
+ types.clear();
+ types.insert(CREDIT_CARD_NUMBER);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "24", "04", "text", &field);
+ types.clear();
+ types.insert(CREDIT_CARD_EXP_MONTH);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "25", "April", "text", &field);
+ types.clear();
+ types.insert(CREDIT_CARD_EXP_MONTH);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "26", "2012", "text", &field);
+ types.clear();
+ types.insert(CREDIT_CARD_EXP_4_DIGIT_YEAR);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "27", "12", "text", &field);
+ types.clear();
+ types.insert(CREDIT_CARD_EXP_2_DIGIT_YEAR);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "28", "04/2012", "text", &field);
+ types.clear();
+ types.insert(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ // Make sure that we trim whitespace properly.
+ autofill_test::CreateTestFormField("", "29", "", "text", &field);
+ types.clear();
+ types.insert(EMPTY_TYPE);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "30", " ", "text", &field);
+ types.clear();
+ types.insert(EMPTY_TYPE);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "31", " Elvis", "text", &field);
+ types.clear();
+ types.insert(NAME_FIRST);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "32", "Elvis ", "text", &field);
+ types.clear();
+ types.insert(NAME_FIRST);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ // These fields should not match, as they differ by case.
+ autofill_test::CreateTestFormField("", "33", "elvis", "text", &field);
+ types.clear();
+ types.insert(UNKNOWN_TYPE);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "34", "3734 Elvis Presley BLVD",
+ "text", &field);
+ types.clear();
+ types.insert(UNKNOWN_TYPE);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ // These fields should not match, as they are unsupported variants.
+ autofill_test::CreateTestFormField("", "35", "Elvis Aaron", "text", &field);
+ types.clear();
+ types.insert(UNKNOWN_TYPE);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "36", "Mr. Presley", "text", &field);
+ types.clear();
+ types.insert(UNKNOWN_TYPE);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "37", "3734 Elvis Presley", "text",
+ &field);
+ types.clear();
+ types.insert(UNKNOWN_TYPE);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "38", "TN", "text", &field);
+ types.clear();
+ types.insert(UNKNOWN_TYPE);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "39", "38116-1023", "text", &field);
+ types.clear();
+ types.insert(UNKNOWN_TYPE);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "20", "5", "text", &field);
+ types.clear();
+ types.insert(UNKNOWN_TYPE);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "20", "56", "text", &field);
+ types.clear();
+ types.insert(UNKNOWN_TYPE);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ autofill_test::CreateTestFormField("", "20", "901", "text", &field);
+ types.clear();
+ types.insert(UNKNOWN_TYPE);
+ form.fields.push_back(field);
+ expected_types.push_back(types);
+
+ FormStructure form_structure(form);
+ autofill_manager_->DeterminePossibleFieldTypesForUpload(&form_structure);
+
+ ASSERT_EQ(expected_types.size(), form_structure.field_count());
+ for (size_t i = 0; i < expected_types.size(); ++i) {
+ SCOPED_TRACE(
+ StringPrintf("Field %d with value %s", static_cast<int>(i),
+ UTF16ToUTF8(form_structure.field(i)->value).c_str()));
+ const FieldTypeSet& possible_types =
+ form_structure.field(i)->possible_types();
+ EXPECT_EQ(expected_types[i].size(), possible_types.size());
+ for (FieldTypeSet::const_iterator it = expected_types[i].begin();
+ it != expected_types[i].end(); ++it) {
+ EXPECT_TRUE(possible_types.count(*it))
+ << "Expected type: " << AutofillType::FieldTypeToString(*it);
+ }
+ }
+}
+
+TEST_F(AutofillManagerTest, DeterminePossibleFieldTypesForUploadStressTest) {
test_personal_data_->ClearAutofillProfiles();
const int kNumProfiles = 5;
for (int i = 0; i < kNumProfiles; ++i) {
diff --git a/chrome/browser/autofill/autofill_metrics_unittest.cc b/chrome/browser/autofill/autofill_metrics_unittest.cc
index e5c53c8..f0c4a33 100644
--- a/chrome/browser/autofill/autofill_metrics_unittest.cc
+++ b/chrome/browser/autofill/autofill_metrics_unittest.cc
@@ -263,7 +263,7 @@ TEST_F(AutofillMetricsTest, QualityMetrics) {
FormField field;
autofill_test::CreateTestFormField(
- "Autofilled", "autofilled", "Elvis Presley", "text", &field);
+ "Autofilled", "autofilled", "Elvis Aaron Presley", "text", &field);
field.is_autofilled = true;
form.fields.push_back(field);
heuristic_types.push_back(NAME_FULL);
@@ -314,13 +314,13 @@ TEST_F(AutofillMetricsTest, QualityMetrics) {
std::string()));
EXPECT_CALL(*autofill_manager_->metric_logger(),
LogHeuristicTypePrediction(AutofillMetrics::TYPE_MATCH,
- UNKNOWN_TYPE, std::string()));
+ NAME_FULL, std::string()));
EXPECT_CALL(*autofill_manager_->metric_logger(),
LogServerTypePrediction(AutofillMetrics::TYPE_MISMATCH,
- UNKNOWN_TYPE, std::string()));
+ NAME_FULL, std::string()));
EXPECT_CALL(*autofill_manager_->metric_logger(),
LogOverallTypePrediction(AutofillMetrics::TYPE_MISMATCH,
- UNKNOWN_TYPE, std::string()));
+ NAME_FULL, std::string()));
EXPECT_CALL(*autofill_manager_->metric_logger(),
LogQualityMetric(AutofillMetrics::FIELD_AUTOFILLED,
std::string()));
@@ -522,7 +522,7 @@ TEST_F(AutofillMetricsTest, SaneMetricsWithCacheMismatch) {
FormField field;
autofill_test::CreateTestFormField(
- "Both match", "match", "Elvis Presley", "text", &field);
+ "Both match", "match", "Elvis Aaron Presley", "text", &field);
field.is_autofilled = true;
form.fields.push_back(field);
heuristic_types.push_back(NAME_FULL);
@@ -646,13 +646,13 @@ TEST_F(AutofillMetricsTest, SaneMetricsWithCacheMismatch) {
std::string()));
EXPECT_CALL(*autofill_manager_->metric_logger(),
LogHeuristicTypePrediction(AutofillMetrics::TYPE_MATCH,
- UNKNOWN_TYPE, std::string()));
+ NAME_FULL, std::string()));
EXPECT_CALL(*autofill_manager_->metric_logger(),
LogServerTypePrediction(AutofillMetrics::TYPE_MATCH,
- UNKNOWN_TYPE, std::string()));
+ NAME_FULL, std::string()));
EXPECT_CALL(*autofill_manager_->metric_logger(),
LogOverallTypePrediction(AutofillMetrics::TYPE_MATCH,
- UNKNOWN_TYPE, std::string()));
+ NAME_FULL, std::string()));
EXPECT_CALL(*autofill_manager_->metric_logger(),
LogQualityMetric(AutofillMetrics::FIELD_AUTOFILLED,
std::string()));
@@ -713,7 +713,7 @@ TEST_F(AutofillMetricsTest, QualityMetricsWithExperimentId) {
FormField field;
autofill_test::CreateTestFormField(
- "Autofilled", "autofilled", "Elvis Presley", "text", &field);
+ "Autofilled", "autofilled", "Elvis Aaron Presley", "text", &field);
field.is_autofilled = true;
form.fields.push_back(field);
heuristic_types.push_back(NAME_FULL);
@@ -760,13 +760,13 @@ TEST_F(AutofillMetricsTest, QualityMetricsWithExperimentId) {
experiment_id));
EXPECT_CALL(*autofill_manager_->metric_logger(),
LogHeuristicTypePrediction(AutofillMetrics::TYPE_MATCH,
- UNKNOWN_TYPE, experiment_id));
+ NAME_FULL, experiment_id));
EXPECT_CALL(*autofill_manager_->metric_logger(),
LogServerTypePrediction(AutofillMetrics::TYPE_MISMATCH,
- UNKNOWN_TYPE, experiment_id));
+ NAME_FULL, experiment_id));
EXPECT_CALL(*autofill_manager_->metric_logger(),
LogOverallTypePrediction(AutofillMetrics::TYPE_MISMATCH,
- UNKNOWN_TYPE, experiment_id));
+ NAME_FULL, experiment_id));
EXPECT_CALL(*autofill_manager_->metric_logger(),
LogQualityMetric(AutofillMetrics::FIELD_AUTOFILLED,
experiment_id));
diff --git a/chrome/browser/autofill/autofill_profile.cc b/chrome/browser/autofill/autofill_profile.cc
index 4df95bd..482cef8 100644
--- a/chrome/browser/autofill/autofill_profile.cc
+++ b/chrome/browser/autofill/autofill_profile.cc
@@ -119,7 +119,7 @@ void CopyValuesToItems(AutofillFieldType type,
const std::vector<string16>& values,
std::vector<T>* form_group_items,
const T& prototype) {
- form_group_items->resize(values.size());
+ form_group_items->resize(values.size(), prototype);
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.
@@ -130,10 +130,15 @@ void CopyValuesToItems(AutofillFieldType type,
template <class T>
void CopyItemsToValues(AutofillFieldType type,
const std::vector<T>& form_group_items,
+ bool canonicalize,
std::vector<string16>* values) {
values->resize(form_group_items.size());
- for (size_t i = 0; i < values->size(); ++i)
- (*values)[i] = form_group_items[i].GetInfo(type);
+ for (size_t i = 0; i < values->size(); ++i) {
+ if (canonicalize)
+ (*values)[i] = form_group_items[i].GetCanonicalizedInfo(type);
+ else
+ (*values)[i] = form_group_items[i].GetInfo(type);
+ }
}
// Collapse compound field types to their "full" type. I.e. First name
@@ -201,16 +206,16 @@ AutofillProfile::AutofillProfile(const std::string& guid)
: guid_(guid),
name_(1),
email_(1),
- home_number_(1, PhoneNumber(AutofillType::PHONE_HOME)),
- fax_number_(1, PhoneNumber(AutofillType::PHONE_FAX)) {
+ home_number_(1, PhoneNumber(AutofillType::PHONE_HOME, this)),
+ fax_number_(1, PhoneNumber(AutofillType::PHONE_FAX, this)) {
}
AutofillProfile::AutofillProfile()
: guid_(guid::GenerateGUID()),
name_(1),
email_(1),
- home_number_(1, PhoneNumber(AutofillType::PHONE_HOME)),
- fax_number_(1, PhoneNumber(AutofillType::PHONE_FAX)) {
+ home_number_(1, PhoneNumber(AutofillType::PHONE_HOME, this)),
+ fax_number_(1, PhoneNumber(AutofillType::PHONE_FAX, this)) {
}
AutofillProfile::AutofillProfile(const AutofillProfile& profile)
@@ -232,26 +237,32 @@ AutofillProfile& AutofillProfile::operator=(const AutofillProfile& profile) {
email_ = profile.email_;
company_ = profile.company_;
home_number_ = profile.home_number_;
+ for (size_t i = 0; i < home_number_.size(); ++i) {
+ home_number_[i].set_profile(this);
+ }
fax_number_ = profile.fax_number_;
+ for (size_t i = 0; i < fax_number_.size(); ++i) {
+ fax_number_[i].set_profile(this);
+ }
address_ = profile.address_;
return *this;
}
-void AutofillProfile::GetMatchingTypes(const string16& text,
- FieldTypeSet* matching_types) const {
+void AutofillProfile::GetSupportedTypes(FieldTypeSet* supported_types) const {
FormGroupList info = FormGroups();
for (FormGroupList::const_iterator it = info.begin(); it != info.end(); ++it)
- (*it)->GetMatchingTypes(text, matching_types);
+ (*it)->GetSupportedTypes(supported_types);
}
-void AutofillProfile::GetNonEmptyTypes(
- FieldTypeSet* non_empty_types) const {
+void AutofillProfile::GetMatchingTypes(const string16& text,
+ FieldTypeSet* matching_types) const {
FormGroupList info = FormGroups();
for (FormGroupList::const_iterator it = info.begin(); it != info.end(); ++it)
- (*it)->GetNonEmptyTypes(non_empty_types);
+ (*it)->GetMatchingTypes(text, matching_types);
}
+
string16 AutofillProfile::GetInfo(AutofillFieldType type) const {
AutofillFieldType return_type = AutofillType::GetEquivalentFieldType(type);
const FormGroup* form_group = FormGroupForType(return_type);
@@ -267,6 +278,26 @@ void AutofillProfile::SetInfo(AutofillFieldType type, const string16& value) {
form_group->SetInfo(type, CollapseWhitespace(value, false));
}
+string16 AutofillProfile::GetCanonicalizedInfo(AutofillFieldType type) const {
+ AutofillFieldType return_type = AutofillType::GetEquivalentFieldType(type);
+ const FormGroup* form_group = FormGroupForType(return_type);
+ if (!form_group)
+ return string16();
+
+ return form_group->GetCanonicalizedInfo(return_type);
+}
+
+bool AutofillProfile::SetCanonicalizedInfo(AutofillFieldType type,
+ const string16& value) {
+ FormGroup* form_group = MutableFormGroupForType(type);
+ if (form_group) {
+ return form_group->SetCanonicalizedInfo(type,
+ CollapseWhitespace(value, false));
+ }
+
+ return false;
+}
+
void AutofillProfile::SetMultiInfo(AutofillFieldType type,
const std::vector<string16>& values) {
switch (AutofillType(type).group()) {
@@ -280,13 +311,13 @@ void AutofillProfile::SetMultiInfo(AutofillFieldType type,
CopyValuesToItems(type,
values,
&home_number_,
- PhoneNumber(AutofillType::PHONE_HOME));
+ PhoneNumber(AutofillType::PHONE_HOME, this));
break;
case AutofillType::PHONE_FAX:
CopyValuesToItems(type,
values,
&fax_number_,
- PhoneNumber(AutofillType::PHONE_FAX));
+ PhoneNumber(AutofillType::PHONE_FAX, this));
break;
default:
if (values.size() == 1) {
@@ -303,18 +334,29 @@ void AutofillProfile::SetMultiInfo(AutofillFieldType type,
void AutofillProfile::GetMultiInfo(AutofillFieldType type,
std::vector<string16>* values) const {
+ GetMultiInfoImpl(type, false, values);
+}
+
+void AutofillProfile::GetCanonicalizedMultiInfo(
+ AutofillFieldType type, std::vector<string16>* values) const {
+ GetMultiInfoImpl(type, true, values);
+}
+
+void AutofillProfile::GetMultiInfoImpl(AutofillFieldType type,
+ bool canonicalize,
+ std::vector<string16>* values) const {
switch (AutofillType(type).group()) {
case AutofillType::NAME:
- CopyItemsToValues(type, name_, values);
+ CopyItemsToValues(type, name_, canonicalize, values);
break;
case AutofillType::EMAIL:
- CopyItemsToValues(type, email_, values);
+ CopyItemsToValues(type, email_, canonicalize, values);
break;
case AutofillType::PHONE_HOME:
- CopyItemsToValues(type, home_number_, values);
+ CopyItemsToValues(type, home_number_, canonicalize, values);
break;
case AutofillType::PHONE_FAX:
- CopyItemsToValues(type, fax_number_, values);
+ CopyItemsToValues(type, fax_number_, canonicalize, values);
break;
default:
values->resize(1);
@@ -494,22 +536,6 @@ 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);
diff --git a/chrome/browser/autofill/autofill_profile.h b/chrome/browser/autofill/autofill_profile.h
index 1ff9d8d..4dbb94a 100644
--- a/chrome/browser/autofill/autofill_profile.h
+++ b/chrome/browser/autofill/autofill_profile.h
@@ -38,16 +38,20 @@ class AutofillProfile : public FormGroup {
// FormGroup:
virtual void GetMatchingTypes(const string16& text,
- FieldTypeSet* matching_types) const;
- virtual void GetNonEmptyTypes(FieldTypeSet* non_empty_types) const;
- virtual string16 GetInfo(AutofillFieldType type) const;
- virtual void SetInfo(AutofillFieldType type, const string16& value);
+ FieldTypeSet* matching_types) const OVERRIDE;
+ virtual string16 GetInfo(AutofillFieldType type) const OVERRIDE;
+ virtual void SetInfo(AutofillFieldType type, const string16& value) OVERRIDE;
+ virtual string16 GetCanonicalizedInfo(AutofillFieldType type) const OVERRIDE;
+ virtual bool SetCanonicalizedInfo(AutofillFieldType type,
+ const string16& value) OVERRIDE;
// Multi-value equivalents to |GetInfo| and |SetInfo|.
void SetMultiInfo(AutofillFieldType type,
const std::vector<string16>& values);
void GetMultiInfo(AutofillFieldType type,
std::vector<string16>* values) const;
+ void GetCanonicalizedMultiInfo(AutofillFieldType type,
+ std::vector<string16>* values) const;
// Returns |true| if |type| accepts multi-values.
static bool SupportsMultiValue(AutofillFieldType type);
@@ -119,13 +123,6 @@ 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);
@@ -133,6 +130,14 @@ class AutofillProfile : public FormGroup {
private:
typedef std::vector<const FormGroup*> FormGroupList;
+ // FormGroup:
+ virtual void GetSupportedTypes(FieldTypeSet* supported_types) const OVERRIDE;
+
+ // Shared implementation for GetMultiInfo() and GetCanonicalizedMultiInfo().
+ void GetMultiInfoImpl(AutofillFieldType type,
+ bool canonicalize,
+ std::vector<string16>* values) const;
+
// 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.
diff --git a/chrome/browser/autofill/autofill_profile_unittest.cc b/chrome/browser/autofill/autofill_profile_unittest.cc
index 28bf838..a5fa207 100644
--- a/chrome/browser/autofill/autofill_profile_unittest.cc
+++ b/chrome/browser/autofill/autofill_profile_unittest.cc
@@ -481,8 +481,7 @@ TEST(AutofillProfileTest, CreateInferredLabelsSkipsEmptyFields) {
// A field must have a non-empty value for each profile to be considered a
// distinguishing field.
- profiles[1]->SetInfo(ADDRESS_HOME_LINE1,
- ASCIIToUTF16("88 Nowhere Ave."));
+ profiles[1]->SetInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("88 Nowhere Ave."));
AutofillProfile::CreateInferredLabels(&profiles.get(), NULL, UNKNOWN_TYPE, 1,
&labels);
ASSERT_EQ(3U, labels.size());
diff --git a/chrome/browser/autofill/contact_info.cc b/chrome/browser/autofill/contact_info.cc
index 7010d2a..57b08fc 100644
--- a/chrome/browser/autofill/contact_info.cc
+++ b/chrome/browser/autofill/contact_info.cc
@@ -38,52 +38,18 @@ NameInfo& NameInfo::operator=(const NameInfo& info) {
if (this == &info)
return *this;
- first_tokens_ = info.first_tokens_;
- middle_tokens_ = info.middle_tokens_;
- last_tokens_ = info.last_tokens_;
first_ = info.first_;
middle_ = info.middle_;
last_ = info.last_;
return *this;
}
-void NameInfo::GetMatchingTypes(const string16& text,
- FieldTypeSet* matching_types) const {
- DCHECK(matching_types);
-
- if (IsFirstName(text))
- matching_types->insert(NAME_FIRST);
-
- if (IsMiddleName(text))
- matching_types->insert(NAME_MIDDLE);
-
- if (IsLastName(text))
- matching_types->insert(NAME_LAST);
-
- if (IsMiddleInitial(text))
- matching_types->insert(NAME_MIDDLE_INITIAL);
-
- if (IsFullName(text))
- matching_types->insert(NAME_FULL);
-}
-
-void NameInfo::GetNonEmptyTypes(FieldTypeSet* non_empty_types) const {
- DCHECK(non_empty_types);
-
- if (!first().empty())
- non_empty_types->insert(NAME_FIRST);
-
- if (!middle().empty())
- non_empty_types->insert(NAME_MIDDLE);
-
- if (!last().empty())
- non_empty_types->insert(NAME_LAST);
-
- if (!MiddleInitial().empty())
- non_empty_types->insert(NAME_MIDDLE_INITIAL);
-
- if (!FullName().empty())
- non_empty_types->insert(NAME_FULL);
+void NameInfo::GetSupportedTypes(FieldTypeSet* supported_types) const {
+ supported_types->insert(NAME_FIRST);
+ supported_types->insert(NAME_MIDDLE);
+ supported_types->insert(NAME_LAST);
+ supported_types->insert(NAME_MIDDLE_INITIAL);
+ supported_types->insert(NAME_FULL);
}
string16 NameInfo::GetInfo(AutofillFieldType type) const {
@@ -108,11 +74,11 @@ string16 NameInfo::GetInfo(AutofillFieldType type) const {
void NameInfo::SetInfo(AutofillFieldType type, const string16& value) {
DCHECK_EQ(AutofillType::NAME, AutofillType(type).group());
if (type == NAME_FIRST)
- SetFirst(value);
+ first_ = value;
else if (type == NAME_MIDDLE || type == NAME_MIDDLE_INITIAL)
- SetMiddle(value);
+ middle_ = value;
else if (type == NAME_LAST)
- SetLast(value);
+ last_ = value;
else if (type == NAME_FULL)
SetFullName(value);
else
@@ -145,181 +111,25 @@ string16 NameInfo::MiddleInitial() const {
return initial;
}
-// If each of the 'words' contained in the text are also present in the first
-// name then we will consider the text to be of type kFirstName. This means
-// that people with multiple first names will be able to enter any one of
-// their first names and have it correctly recognized.
-bool NameInfo::IsFirstName(const string16& text) const {
- return IsNameMatch(text, first_tokens_);
-}
-
-// If each of the 'words' contained in the text are also present in the middle
-// name then we will consider the text to be of type kMiddleName.
-bool NameInfo::IsMiddleName(const string16& text) const {
- return IsNameMatch(text, middle_tokens_);
-}
-
-// If each of the 'words' contained in the text are also present in the last
-// name then we will consider the text to be of type kLastName.
-bool NameInfo::IsLastName(const string16& text) const {
- return IsNameMatch(text, last_tokens_);
-}
-
-bool NameInfo::IsMiddleInitial(const string16& text) const {
- if (text.length() != 1)
- return false;
-
- string16 lower_case = StringToLowerASCII(text);
- // If the text entered was a single character and it matches the first letter
- // of any of the given middle names then we consider it to be a middle
- // initial field.
- size_t middle_tokens_size = middle_tokens_.size();
- for (size_t i = 0; i < middle_tokens_size; ++i) {
- if (middle_tokens_[i][0] == lower_case[0])
- return true;
- }
-
- return false;
-}
-
-// A field will be considered to be of type NAME_FULL if:
-// 1) it contains at least one word from the first name.
-// 2) it contains at least one word from the last name.
-// 3) all of the words in the field match a word in either the first,
-// middle, or last name.
-bool NameInfo::IsFullName(const string16& text) const {
- size_t first_tokens_size = first_tokens_.size();
- if (first_tokens_size == 0)
- return false;
-
- size_t middle_tokens_size = middle_tokens_.size();
-
- size_t last_tokens_size = last_tokens_.size();
- if (last_tokens_size == 0)
- return false;
-
- std::vector<string16> text_tokens;
- Tokenize(text, kNameSplitChars, &text_tokens);
- size_t text_tokens_size = text_tokens.size();
- if (text_tokens_size == 0 || text_tokens_size < 2)
- return false;
-
- size_t name_tokens_size =
- first_tokens_size + middle_tokens_size + last_tokens_size;
- if (text_tokens_size > name_tokens_size)
- return false;
-
- bool first_name_match = false;
- bool last_name_match = false;
- for (std::vector<string16>::iterator iter = text_tokens.begin();
- iter != text_tokens.end(); ++iter) {
- bool match = false;
- if (IsWordInName(*iter, first_tokens_)) {
- match = true;
- first_name_match = true;
- }
-
- if (IsWordInName(*iter, last_tokens_)) {
- match = true;
- last_name_match = true;
- }
-
- if (IsWordInName(*iter, middle_tokens_))
- match = true;
-
- if (!match)
- return false;
- }
-
- return (first_name_match && last_name_match);
-}
-
-bool NameInfo::IsNameMatch(const string16& text,
- const std::vector<string16>& name_tokens) const {
- size_t name_tokens_size = name_tokens.size();
- if (name_tokens_size == 0)
- return false;
-
- std::vector<string16> text_tokens;
- Tokenize(text, kNameSplitChars, &text_tokens);
- size_t text_tokens_size = text_tokens.size();
- if (text_tokens_size == 0)
- return false;
-
- if (text_tokens_size > name_tokens_size)
- return false;
-
- // If each of the 'words' contained in the text are also present in the name,
- // then we will consider the text to match the name.
- for (std::vector<string16>::iterator iter = text_tokens.begin();
- iter != text_tokens.end(); ++iter) {
- if (!IsWordInName(*iter, name_tokens))
- return false;
- }
-
- return true;
-}
-
-bool NameInfo::IsWordInName(const string16& word,
- const std::vector<string16>& name_tokens) const {
- for (std::vector<string16>::const_iterator iter = name_tokens.begin();
- iter != name_tokens.end(); ++iter) {
- // |*iter| is already lower-cased.
- if (StringToLowerASCII(word) == *iter)
- return true;
- }
-
- return false;
-}
-
-void NameInfo::SetFirst(const string16& first) {
- first_ = first;
- first_tokens_.clear();
- Tokenize(first, kNameSplitChars, &first_tokens_);
- for (std::vector<string16>::iterator iter = first_tokens_.begin();
- iter != first_tokens_.end(); ++iter) {
- *iter = StringToLowerASCII(*iter);
- }
-}
-
-void NameInfo::SetMiddle(const string16& middle) {
- middle_ = middle;
- middle_tokens_.clear();
- Tokenize(middle, kNameSplitChars, &middle_tokens_);
- for (std::vector<string16>::iterator iter = middle_tokens_.begin();
- iter != middle_tokens_.end(); ++iter) {
- *iter = StringToLowerASCII(*iter);
- }
-}
-
-void NameInfo::SetLast(const string16& last) {
- last_ = last;
- last_tokens_.clear();
- Tokenize(last, kNameSplitChars, &last_tokens_);
- for (std::vector<string16>::iterator iter = last_tokens_.begin();
- iter != last_tokens_.end(); ++iter) {
- *iter = StringToLowerASCII(*iter);
- }
-}
-
void NameInfo::SetFullName(const string16& full) {
+ // Clear the names.
+ first_ = string16();
+ middle_ = string16();
+ last_ = string16();
+
std::vector<string16> full_name_tokens;
Tokenize(full, ASCIIToUTF16(" "), &full_name_tokens);
- // Clear the names.
- SetFirst(string16());
- SetMiddle(string16());
- SetLast(string16());
// There are four possibilities: empty; first name; first and last names;
// first, middle (possibly multiple strings) and then the last name.
if (full_name_tokens.size() > 0) {
- SetFirst(full_name_tokens[0]);
+ first_ = full_name_tokens[0];
if (full_name_tokens.size() > 1) {
- SetLast(full_name_tokens.back());
+ last_ = full_name_tokens.back();
if (full_name_tokens.size() > 2) {
full_name_tokens.erase(full_name_tokens.begin());
full_name_tokens.pop_back();
- SetMiddle(JoinString(full_name_tokens, ' '));
+ middle_ = JoinString(full_name_tokens, ' ');
}
}
}
@@ -341,18 +151,8 @@ EmailInfo& EmailInfo::operator=(const EmailInfo& info) {
return *this;
}
-void EmailInfo::GetMatchingTypes(const string16& text,
- FieldTypeSet* matching_types) const {
- DCHECK(matching_types);
- // TODO(isherman): Investigate case-insensitive comparison.
- if (email_ == text)
- matching_types->insert(EMAIL_ADDRESS);
-}
-
-void EmailInfo::GetNonEmptyTypes(FieldTypeSet* non_empty_types) const {
- DCHECK(non_empty_types);
- if (!email_.empty())
- non_empty_types->insert(EMAIL_ADDRESS);
+void EmailInfo::GetSupportedTypes(FieldTypeSet* supported_types) const {
+ supported_types->insert(EMAIL_ADDRESS);
}
string16 EmailInfo::GetInfo(AutofillFieldType type) const {
@@ -383,19 +183,8 @@ CompanyInfo& CompanyInfo::operator=(const CompanyInfo& info) {
return *this;
}
-void CompanyInfo::GetMatchingTypes(const string16& text,
- FieldTypeSet* matching_types) const {
- DCHECK(matching_types);
-
- if (company_name_ == text)
- matching_types->insert(COMPANY_NAME);
-}
-
-void CompanyInfo::GetNonEmptyTypes(FieldTypeSet* non_empty_types) const {
- DCHECK(non_empty_types);
-
- if (!company_name_.empty())
- non_empty_types->insert(COMPANY_NAME);
+void CompanyInfo::GetSupportedTypes(FieldTypeSet* supported_types) const {
+ supported_types->insert(COMPANY_NAME);
}
string16 CompanyInfo::GetInfo(AutofillFieldType type) const {
diff --git a/chrome/browser/autofill/contact_info.h b/chrome/browser/autofill/contact_info.h
index 2d9d043..ac6ed2b 100644
--- a/chrome/browser/autofill/contact_info.h
+++ b/chrome/browser/autofill/contact_info.h
@@ -23,15 +23,15 @@ class NameInfo : public FormGroup {
NameInfo& operator=(const NameInfo& info);
// FormGroup:
- virtual void GetMatchingTypes(const string16& text,
- FieldTypeSet* matching_types) const;
- virtual void GetNonEmptyTypes(FieldTypeSet* non_empty_types) const;
- virtual string16 GetInfo(AutofillFieldType type) const;
- virtual void SetInfo(AutofillFieldType type, const string16& value);
+ virtual string16 GetInfo(AutofillFieldType type) const OVERRIDE;
+ virtual void SetInfo(AutofillFieldType type, const string16& value) OVERRIDE;
private:
FRIEND_TEST_ALL_PREFIXES(NameInfoTest, TestSetFullName);
+ // FormGroup:
+ virtual void GetSupportedTypes(FieldTypeSet* supported_types) const OVERRIDE;
+
// Returns the full name, which can include up to the first, middle, and last
// name.
string16 FullName() const;
@@ -44,51 +44,10 @@ class NameInfo : public FormGroup {
const string16& middle() const { return middle_; }
const string16& last() const { return last_; }
- // Returns true if |text| is the first name.
- bool IsFirstName(const string16& text) const;
-
- // Returns true if |text| is the middle name.
- bool IsMiddleName(const string16& text) const;
-
- // Returns true if |text| is the last name.
- bool IsLastName(const string16& text) const;
-
- // Returns true if |text| is the middle initial.
- bool IsMiddleInitial(const string16& text) const;
-
- // Returns true if |text| is the last name.
- bool IsFullName(const string16& text) const;
-
- // Returns true if all of the tokens in |text| match the tokens in
- // |name_tokens|.
- bool IsNameMatch(const string16& text,
- const std::vector<string16>& name_tokens) const;
-
- // Returns true if |word| is one of the tokens in |name_tokens|.
- bool IsWordInName(const string16& word,
- const std::vector<string16>& name_tokens) const;
-
- // Sets |first_| to |first| and |first_tokens_| to the set of tokens in
- // |first|, made lowercase.
- void SetFirst(const string16& first);
-
- // Sets |middle_| to |middle| and |middle_tokens_| to the set of tokens in
- // |middle|, made lowercase.
- void SetMiddle(const string16& middle);
-
- // Sets |last_| to |last| and |last_tokens_| to the set of tokens in |last|,
- // made lowercase.
- void SetLast(const string16& last);
-
- // Sets |first_|, |middle_|, |last_| and |*_tokens_| to the tokenized
- // |full|. It is tokenized on a space only.
+ // Sets |first_|, |middle_|, and |last_| to the tokenized |full|.
+ // It is tokenized on a space only.
void SetFullName(const string16& full);
- // List of tokens in each part of the name.
- std::vector<string16> first_tokens_;
- std::vector<string16> middle_tokens_;
- std::vector<string16> last_tokens_;
-
string16 first_;
string16 middle_;
string16 last_;
@@ -103,13 +62,13 @@ class EmailInfo : public FormGroup {
EmailInfo& operator=(const EmailInfo& info);
// FormGroup:
- virtual void GetMatchingTypes(const string16& text,
- FieldTypeSet* matching_types) const;
- virtual void GetNonEmptyTypes(FieldTypeSet* non_empty_types) const;
- virtual string16 GetInfo(AutofillFieldType type) const;
- virtual void SetInfo(AutofillFieldType type, const string16& value);
+ virtual string16 GetInfo(AutofillFieldType type) const OVERRIDE;
+ virtual void SetInfo(AutofillFieldType type, const string16& value) OVERRIDE;
private:
+ // FormGroup:
+ virtual void GetSupportedTypes(FieldTypeSet* supported_types) const OVERRIDE;
+
string16 email_;
};
@@ -122,13 +81,13 @@ class CompanyInfo : public FormGroup {
CompanyInfo& operator=(const CompanyInfo& info);
// FormGroup:
- virtual void GetMatchingTypes(const string16& text,
- FieldTypeSet* matching_types) const;
- virtual void GetNonEmptyTypes(FieldTypeSet* non_empty_types) const;
- virtual string16 GetInfo(AutofillFieldType type) const;
- virtual void SetInfo(AutofillFieldType type, const string16& value);
+ virtual string16 GetInfo(AutofillFieldType type) const OVERRIDE;
+ virtual void SetInfo(AutofillFieldType type, const string16& value) OVERRIDE;
private:
+ // FormGroup:
+ virtual void GetSupportedTypes(FieldTypeSet* supported_types) const OVERRIDE;
+
string16 company_name_;
};
diff --git a/chrome/browser/autofill/credit_card.cc b/chrome/browser/autofill/credit_card.cc
index b6803bc..81f8e9d 100644
--- a/chrome/browser/autofill/credit_card.cc
+++ b/chrome/browser/autofill/credit_card.cc
@@ -38,6 +38,14 @@ const AutofillFieldType kAutofillCreditCardTypes[] = {
const int kAutofillCreditCardLength = arraysize(kAutofillCreditCardTypes);
+// Returns a version of |number| that has any separator characters removed.
+const string16 StripSeparators(const string16& number) {
+ const char16 kSeparators[] = {'-', ' ', '\0'};
+ string16 stripped;
+ RemoveChars(number, kSeparators, &stripped);
+ return stripped;
+}
+
std::string GetCreditCardType(const string16& number) {
// Don't check for a specific type if this is not a credit card number.
if (!CreditCard::IsValidCreditCardNumber(number))
@@ -133,7 +141,6 @@ bool ConvertYear(const string16& year, int* num) {
if (base::StringToInt(year, num))
return true;
- NOTREACHED();
*num = 0;
return false;
}
@@ -179,7 +186,6 @@ bool ConvertMonth(const string16& month, int* num) {
}
}
- NOTREACHED();
*num = 0;
return false;
}
@@ -206,53 +212,14 @@ CreditCard::CreditCard(const CreditCard& credit_card) : FormGroup() {
CreditCard::~CreditCard() {}
-void CreditCard::GetMatchingTypes(const string16& text,
- FieldTypeSet* matching_types) const {
- if (IsNameOnCard(text))
- matching_types->insert(CREDIT_CARD_NAME);
-
- if (IsNumber(text))
- matching_types->insert(CREDIT_CARD_NUMBER);
-
- if (IsExpirationMonth(text))
- matching_types->insert(CREDIT_CARD_EXP_MONTH);
-
- if (Is2DigitExpirationYear(text))
- matching_types->insert(CREDIT_CARD_EXP_2_DIGIT_YEAR);
-
- if (Is4DigitExpirationYear(text))
- matching_types->insert(CREDIT_CARD_EXP_4_DIGIT_YEAR);
-
- if (text == GetInfo(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR))
- matching_types->insert(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR);
-
- if (text == GetInfo(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR))
- matching_types->insert(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR);
-}
-
-void CreditCard::GetNonEmptyTypes(FieldTypeSet* non_empty_types) const {
- DCHECK(non_empty_types);
-
- if (!name_on_card_.empty())
- non_empty_types->insert(CREDIT_CARD_NAME);
-
- if (!number_.empty())
- non_empty_types->insert(CREDIT_CARD_NUMBER);
-
- if (!ExpirationMonthAsString().empty())
- non_empty_types->insert(CREDIT_CARD_EXP_MONTH);
-
- if (!Expiration2DigitYearAsString().empty())
- non_empty_types->insert(CREDIT_CARD_EXP_2_DIGIT_YEAR);
-
- if (!Expiration4DigitYearAsString().empty())
- non_empty_types->insert(CREDIT_CARD_EXP_4_DIGIT_YEAR);
-
- if (!GetInfo(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR).empty())
- non_empty_types->insert(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR);
-
- if (!GetInfo(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR).empty())
- non_empty_types->insert(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR);
+void CreditCard::GetSupportedTypes(FieldTypeSet* supported_types) const {
+ supported_types->insert(CREDIT_CARD_NAME);
+ supported_types->insert(CREDIT_CARD_NUMBER);
+ supported_types->insert(CREDIT_CARD_EXP_MONTH);
+ supported_types->insert(CREDIT_CARD_EXP_2_DIGIT_YEAR);
+ supported_types->insert(CREDIT_CARD_EXP_4_DIGIT_YEAR);
+ supported_types->insert(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR);
+ supported_types->insert(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR);
}
string16 CreditCard::GetInfo(AutofillFieldType type) const {
@@ -290,7 +257,7 @@ string16 CreditCard::GetInfo(AutofillFieldType type) const {
return string16();
case CREDIT_CARD_NUMBER:
- return number();
+ return number_;
case CREDIT_CARD_VERIFICATION_CODE:
NOTREACHED();
@@ -349,6 +316,36 @@ void CreditCard::SetInfo(AutofillFieldType type, const string16& value) {
}
}
+string16 CreditCard::GetCanonicalizedInfo(AutofillFieldType type) const {
+ if (type == CREDIT_CARD_NUMBER)
+ return StripSeparators(number_);
+
+ return GetInfo(type);
+}
+
+bool CreditCard::SetCanonicalizedInfo(AutofillFieldType type,
+ const string16& value) {
+ if (type == CREDIT_CARD_NUMBER)
+ SetInfo(type, StripSeparators(value));
+ else
+ SetInfo(type, value);
+
+ return true;
+}
+
+void CreditCard::GetMatchingTypes(const string16& text,
+ FieldTypeSet* matching_types) const {
+ FormGroup::GetMatchingTypes(text, matching_types);
+
+ string16 card_number = GetCanonicalizedInfo(CREDIT_CARD_NUMBER);
+ if (!card_number.empty() && StripSeparators(text) == card_number)
+ matching_types->insert(CREDIT_CARD_NUMBER);
+
+ int month;
+ if (ConvertMonth(text, &month) && month != 0 && month == expiration_month_)
+ matching_types->insert(CREDIT_CARD_EXP_MONTH);
+}
+
const string16 CreditCard::Label() const {
string16 label;
if (number().empty())
@@ -455,14 +452,6 @@ bool CreditCard::operator!=(const CreditCard& credit_card) const {
}
// static
-const string16 CreditCard::StripSeparators(const string16& number) {
- const char16 kSeparators[] = {'-', ' ', '\0'};
- string16 stripped;
- RemoveChars(number, kSeparators, &stripped);
- return stripped;
-}
-
-// static
bool CreditCard::IsValidCreditCardNumber(const string16& text) {
string16 number = StripSeparators(text);
@@ -576,38 +565,6 @@ void CreditCard::SetExpirationYear(int expiration_year) {
expiration_year_ = expiration_year;
}
-bool CreditCard::IsNumber(const string16& text) const {
- return StripSeparators(text) == StripSeparators(number_);
-}
-
-bool CreditCard::IsNameOnCard(const string16& text) const {
- return StringToLowerASCII(text) == StringToLowerASCII(name_on_card_);
-}
-
-bool CreditCard::IsExpirationMonth(const string16& text) const {
- int month;
- if (!base::StringToInt(text, &month))
- return false;
-
- return expiration_month_ == month;
-}
-
-bool CreditCard::Is2DigitExpirationYear(const string16& text) const {
- int year;
- if (!base::StringToInt(text, &year))
- return false;
-
- return year < 100 && (expiration_year_ % 100) == year;
-}
-
-bool CreditCard::Is4DigitExpirationYear(const string16& text) const {
- int year;
- if (!base::StringToInt(text, &year))
- return false;
-
- return expiration_year_ == year;
-}
-
// So we can compare CreditCards with EXPECT_EQ().
std::ostream& operator<<(std::ostream& os, const CreditCard& credit_card) {
return os
diff --git a/chrome/browser/autofill/credit_card.h b/chrome/browser/autofill/credit_card.h
index 124ae79..8ec8969 100644
--- a/chrome/browser/autofill/credit_card.h
+++ b/chrome/browser/autofill/credit_card.h
@@ -25,11 +25,13 @@ class CreditCard : public FormGroup {
virtual ~CreditCard();
// FormGroup implementation:
+ virtual string16 GetInfo(AutofillFieldType type) const OVERRIDE;
+ virtual void SetInfo(AutofillFieldType type, const string16& value) OVERRIDE;
+ virtual string16 GetCanonicalizedInfo(AutofillFieldType type) const OVERRIDE;
+ virtual bool SetCanonicalizedInfo(AutofillFieldType type,
+ const string16& value) OVERRIDE;
virtual void GetMatchingTypes(const string16& text,
- FieldTypeSet* matching_types) const;
- virtual void GetNonEmptyTypes(FieldTypeSet* non_empty_types) const;
- virtual string16 GetInfo(AutofillFieldType type) const;
- virtual void SetInfo(AutofillFieldType type, const string16& value);
+ FieldTypeSet* matching_types) const OVERRIDE;
// Credit card preview summary, for example: ******1234, Exp: 01/2020
virtual const string16 Label() const;
@@ -66,9 +68,6 @@ class CreditCard : public FormGroup {
bool operator==(const CreditCard& credit_card) const;
bool operator!=(const CreditCard& credit_card) const;
- // Return a version of |number| that has any separator characters removed.
- static const string16 StripSeparators(const string16& number);
-
// Returns true if |text| looks like a valid credit card number.
// Uses the Luhn formula to validate the number.
static bool IsValidCreditCardNumber(const string16& text);
@@ -83,6 +82,9 @@ class CreditCard : public FormGroup {
const string16& number() const { return number_; }
private:
+ // FormGroup:
+ virtual void GetSupportedTypes(FieldTypeSet* supported_types) const OVERRIDE;
+
// The month and year are zero if not present.
int Expiration4DigitYear() const { return expiration_year_; }
int Expiration2DigitYear() const { return expiration_year_ % 100; }
@@ -96,7 +98,7 @@ class CreditCard : public FormGroup {
// Sets |expiration_year_| to the integer conversion of |text|.
void SetExpirationYearFromString(const string16& text);
- // Sets |number_| to the stripped version of |number|, containing only digits.
+ // Sets |number_| to |number| and computes the appropriate card |type_|.
void SetNumber(const string16& number);
// These setters verify that the month and year are within appropriate
@@ -104,24 +106,6 @@ class CreditCard : public FormGroup {
void SetExpirationMonth(int expiration_month);
void SetExpirationYear(int expiration_year);
- // Returns true if |text| matches the name on the card. The comparison is
- // case-insensitive.
- bool IsNameOnCard(const string16& text) const;
-
- // Returns true if |text| matches the card number.
- bool IsNumber(const string16& text) const;
-
- // Returns true if |text| matches the expiration month of the card.
- bool IsExpirationMonth(const string16& text) const;
-
- // Returns true if the integer value of |text| matches the 2-digit expiration
- // year.
- bool Is2DigitExpirationYear(const string16& text) const;
-
- // Returns true if the integer value of |text| matches the 4-digit expiration
- // year.
- bool Is4DigitExpirationYear(const string16& text) const;
-
string16 number_; // The credit card number.
string16 name_on_card_; // The cardholder's name.
std::string type_; // The type of the card.
diff --git a/chrome/browser/autofill/fax_number.cc b/chrome/browser/autofill/fax_number.cc
index 3d1a651..baef644 100644
--- a/chrome/browser/autofill/fax_number.cc
+++ b/chrome/browser/autofill/fax_number.cc
@@ -4,11 +4,14 @@
#include "chrome/browser/autofill/fax_number.h"
-FaxNumber::FaxNumber() {}
+FaxNumber::FaxNumber(AutofillProfile* profile) : PhoneNumber(profile) {
+}
-FaxNumber::FaxNumber(const FaxNumber& fax) : PhoneNumber(fax) {}
+FaxNumber::FaxNumber(const FaxNumber& fax) : PhoneNumber(fax) {
+}
-FaxNumber::~FaxNumber() {}
+FaxNumber::~FaxNumber() {
+}
FaxNumber& FaxNumber::operator=(const FaxNumber& fax) {
PhoneNumber::operator=(fax);
diff --git a/chrome/browser/autofill/fax_number.h b/chrome/browser/autofill/fax_number.h
index 292a169a5..c65e7ae 100644
--- a/chrome/browser/autofill/fax_number.h
+++ b/chrome/browser/autofill/fax_number.h
@@ -11,7 +11,7 @@
class FaxNumber : public PhoneNumber {
public:
- FaxNumber();
+ explicit FaxNumber(AutofillProfile* profile);
FaxNumber(const FaxNumber& fax);
virtual ~FaxNumber();
diff --git a/chrome/browser/autofill/form_group.cc b/chrome/browser/autofill/form_group.cc
index ace91f4..ae7f316 100644
--- a/chrome/browser/autofill/form_group.cc
+++ b/chrome/browser/autofill/form_group.cc
@@ -8,6 +8,45 @@
#include <iterator>
+void FormGroup::GetMatchingTypes(const string16& text,
+ FieldTypeSet* matching_types) const {
+ if (text.empty()) {
+ matching_types->insert(EMPTY_TYPE);
+ return;
+ }
+
+ FieldTypeSet types;
+ GetSupportedTypes(&types);
+ for (FieldTypeSet::const_iterator type = types.begin();
+ type != types.end(); ++type) {
+ // TODO(isherman): Matches are case-sensitive for now. Let's keep an eye on
+ // this and decide whether there are compelling reasons to add case-
+ // insensitivity.
+ if (GetInfo(*type) == text)
+ matching_types->insert(*type);
+ }
+}
+
+void FormGroup::GetNonEmptyTypes(FieldTypeSet* non_empty_types) const {
+ FieldTypeSet types;
+ GetSupportedTypes(&types);
+ for (FieldTypeSet::const_iterator type = types.begin();
+ type != types.end(); ++type) {
+ if (!GetInfo(*type).empty())
+ non_empty_types->insert(*type);
+ }
+}
+
+string16 FormGroup::GetCanonicalizedInfo(AutofillFieldType type) const {
+ return GetInfo(type);
+}
+
+bool FormGroup::SetCanonicalizedInfo(AutofillFieldType type,
+ const string16& value) {
+ SetInfo(type, value);
+ return true;
+}
+
const string16 FormGroup::Label() const { return string16(); }
bool FormGroup::operator!=(const FormGroup& form_group) const {
diff --git a/chrome/browser/autofill/form_group.h b/chrome/browser/autofill/form_group.h
index c976dc3..d940682 100644
--- a/chrome/browser/autofill/form_group.h
+++ b/chrome/browser/autofill/form_group.h
@@ -23,19 +23,27 @@ class FormGroup {
// into the field. The field types can then be reported back to the server.
// This method is additive on |matching_types|.
virtual void GetMatchingTypes(const string16& text,
- FieldTypeSet* matching_types) const = 0;
+ FieldTypeSet* matching_types) const;
// Returns a set of AutofillFieldTypes for which this FormGroup has non-empty
- // data.
- virtual void GetNonEmptyTypes(FieldTypeSet* non_empty_types) const = 0;
+ // data. This method is additive on |non_empty_types|.
+ virtual void GetNonEmptyTypes(FieldTypeSet* non_empty_types) const;
- // Returns the string that should be auto-filled into a text field given the
- // type of that field.
+ // Returns the literal string associated with |type|.
virtual string16 GetInfo(AutofillFieldType type) const = 0;
// Used to populate this FormGroup object with data.
virtual void SetInfo(AutofillFieldType type, const string16& value) = 0;
+ // Returns the string that should be auto-filled into a text field given the
+ // type of that field.
+ virtual string16 GetCanonicalizedInfo(AutofillFieldType type) const;
+
+ // Used to populate this FormGroup object with data. Canonicalizes the data
+ // prior to storing, if appropriate.
+ virtual bool SetCanonicalizedInfo(AutofillFieldType type,
+ const string16& value);
+
// Returns the label for this FormGroup item. This should be overridden for
// form group items that implement a label.
virtual const string16 Label() const;
@@ -57,6 +65,15 @@ class FormGroup {
// Overwrites the field data in |form_group| with this FormGroup.
void OverwriteWith(const FormGroup& form_group);
+
+ protected:
+ // AutofillProfile needs to call into GetSupportedTypes() for objects of
+ // non-AutofillProfile type, for which mere inheritance is insufficient.
+ friend class AutofillProfile;
+
+ // Returns a set of AutofillFieldTypes for which this FormGroup can store
+ // data. This method is additive on |supported_types|.
+ virtual void GetSupportedTypes(FieldTypeSet* supported_types) const = 0;
};
#endif // CHROME_BROWSER_AUTOFILL_FORM_GROUP_H_
diff --git a/chrome/browser/autofill/home_phone_number.cc b/chrome/browser/autofill/home_phone_number.cc
index 9425df5..6f4ecea 100644
--- a/chrome/browser/autofill/home_phone_number.cc
+++ b/chrome/browser/autofill/home_phone_number.cc
@@ -4,13 +4,16 @@
#include "chrome/browser/autofill/home_phone_number.h"
-HomePhoneNumber::HomePhoneNumber() {}
+HomePhoneNumber::HomePhoneNumber(AutofillProfile* profile)
+ : PhoneNumber(profile) {
+}
HomePhoneNumber::HomePhoneNumber(const HomePhoneNumber& phone)
: PhoneNumber(phone) {
}
-HomePhoneNumber::~HomePhoneNumber() {}
+HomePhoneNumber::~HomePhoneNumber() {
+}
HomePhoneNumber& HomePhoneNumber::operator=(const HomePhoneNumber& phone) {
PhoneNumber::operator=(phone);
diff --git a/chrome/browser/autofill/home_phone_number.h b/chrome/browser/autofill/home_phone_number.h
index 8c3a10b..eee1162 100644
--- a/chrome/browser/autofill/home_phone_number.h
+++ b/chrome/browser/autofill/home_phone_number.h
@@ -12,7 +12,7 @@ class FormGroup;
class HomePhoneNumber : public PhoneNumber {
public:
- HomePhoneNumber();
+ explicit HomePhoneNumber(AutofillProfile* profile);
HomePhoneNumber(const HomePhoneNumber& phone);
virtual ~HomePhoneNumber();
diff --git a/chrome/browser/autofill/personal_data_manager.cc b/chrome/browser/autofill/personal_data_manager.cc
index 91c44f3..65b0e9a 100644
--- a/chrome/browser/autofill/personal_data_manager.cc
+++ b/chrome/browser/autofill/personal_data_manager.cc
@@ -166,8 +166,8 @@ void PersonalDataManager::OnWebDataServiceRequestDone(
// PersonalDataManager,
// views::ButtonListener implementations
void PersonalDataManager::SetObserver(PersonalDataManager::Observer* observer) {
- // TODO: RemoveObserver is for compatibility with old code, it should be
- // nuked.
+ // TODO(dhollowa): RemoveObserver is for compatibility with old code, it
+ // should be nuked.
observers_.RemoveObserver(observer);
observers_.AddObserver(observer);
}
@@ -244,17 +244,11 @@ bool PersonalDataManager::ImportFormData(
types_seen.insert(field_type);
if (group == AutofillType::CREDIT_CARD) {
- // If the user has a password set, we have no way of setting credit
- // card numbers.
if (LowerCaseEqualsASCII(field->form_control_type, "month")) {
DCHECK_EQ(CREDIT_CARD_EXP_MONTH, field_type);
local_imported_credit_card->SetInfoForMonthInputType(value);
} else {
- if (field_type == CREDIT_CARD_NUMBER) {
- // Clean up any imported credit card numbers.
- value = CreditCard::StripSeparators(value);
- }
- local_imported_credit_card->SetInfo(field_type, value);
+ local_imported_credit_card->SetCanonicalizedInfo(field_type, value);
}
++importable_credit_card_fields;
} else {
@@ -263,7 +257,7 @@ bool PersonalDataManager::ImportFormData(
// 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);
+ imported_profile->SetCanonicalizedInfo(field_type, value);
// Reject profiles with invalid country information.
if (field_type == ADDRESS_HOME_COUNTRY &&
@@ -274,31 +268,25 @@ bool PersonalDataManager::ImportFormData(
}
}
- // Build phone numbers if they are from parts.
- if (imported_profile.get()) {
+ // Construct the phone and fax numbers. Reject the profile if either number
+ // is invalid.
+ if (imported_profile.get() && !home.IsEmpty()) {
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);
- }
+ if (!home.ParseNumber(imported_profile->CountryCode(),
+ &constructed_number) ||
+ !imported_profile->SetCanonicalizedInfo(PHONE_HOME_WHOLE_NUMBER,
+ constructed_number)) {
+ imported_profile.reset();
}
}
- // Normalize phone numbers.
- if (imported_profile.get()) {
- // Reject profile if even one of the phones is invalid.
- if (!imported_profile->NormalizePhones())
+ if (imported_profile.get() && !fax.IsEmpty()) {
+ string16 constructed_number;
+ if (!fax.ParseNumber(imported_profile->CountryCode(),
+ &constructed_number) ||
+ !imported_profile->SetCanonicalizedInfo(PHONE_FAX_WHOLE_NUMBER,
+ constructed_number)) {
imported_profile.reset();
+ }
}
// Reject the profile if minimum address and validation requirements are not
@@ -486,41 +474,6 @@ CreditCard* PersonalDataManager::GetCreditCardByGUID(const std::string& guid) {
return NULL;
}
-void PersonalDataManager::GetMatchingTypes(const string16& text,
- FieldTypeSet* matching_types) const {
- string16 clean_info = StringToLowerASCII(CollapseWhitespace(text, false));
- if (clean_info.empty()) {
- matching_types->insert(EMPTY_TYPE);
- return;
- }
-
- const std::vector<AutofillProfile*>& profiles = this->profiles();
- for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin();
- iter != profiles.end(); ++iter) {
- const FormGroup* profile = *iter;
- if (!profile) {
- DLOG(ERROR) << "NULL information in profiles list";
- continue;
- }
-
- profile->GetMatchingTypes(clean_info, matching_types);
- }
-
- for (ScopedVector<CreditCard>::const_iterator iter = credit_cards_.begin();
- iter != credit_cards_.end(); ++iter) {
- const FormGroup* credit_card = *iter;
- if (!credit_card) {
- DLOG(ERROR) << "NULL information in credit cards list";
- continue;
- }
-
- credit_card->GetMatchingTypes(clean_info, matching_types);
- }
-
- if (matching_types->empty())
- matching_types->insert(UNKNOWN_TYPE);
-}
-
void PersonalDataManager::GetNonEmptyTypes(
FieldTypeSet* non_empty_types) const {
const std::vector<AutofillProfile*>& profiles = this->profiles();
diff --git a/chrome/browser/autofill/personal_data_manager.h b/chrome/browser/autofill/personal_data_manager.h
index dce2acf..da7b0b8 100644
--- a/chrome/browser/autofill/personal_data_manager.h
+++ b/chrome/browser/autofill/personal_data_manager.h
@@ -96,11 +96,6 @@ class PersonalDataManager
// no credit card with the specified |guid|.
CreditCard* GetCreditCardByGUID(const std::string& guid);
- // Gets the possible field types for the given text, determined by matching
- // the text with all known personal information and returning matching types.
- void GetMatchingTypes(const string16& text,
- FieldTypeSet* matching_types) const;
-
// Gets the field types availabe in the stored address and credit card data.
void GetNonEmptyTypes(FieldTypeSet* non_empty_types) const;
diff --git a/chrome/browser/autofill/personal_data_manager_mac.mm b/chrome/browser/autofill/personal_data_manager_mac.mm
index 5d02166..253fcdf 100644
--- a/chrome/browser/autofill/personal_data_manager_mac.mm
+++ b/chrome/browser/autofill/personal_data_manager_mac.mm
@@ -216,7 +216,6 @@ void AuxiliaryProfilesImpl::GetAddressBookPhoneNumbers(
profile->SetInfo(PHONE_FAX_WHOLE_NUMBER, workFax);
}
}
- profile->NormalizePhones();
}
} // namespace
diff --git a/chrome/browser/autofill/phone_field.cc b/chrome/browser/autofill/phone_field.cc
index f9fc036..f310073 100644
--- a/chrome/browser/autofill/phone_field.cc
+++ b/chrome/browser/autofill/phone_field.cc
@@ -348,9 +348,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 PhoneNumber(AutofillType::PHONE_HOME));
+ number_.reset(new PhoneNumber(AutofillType::PHONE_HOME, NULL));
else
- number_.reset(new PhoneNumber(AutofillType::PHONE_FAX));
+ number_.reset(new PhoneNumber(AutofillType::PHONE_FAX, NULL));
phone_type_ = phone_type;
}
diff --git a/chrome/browser/autofill/phone_number.cc b/chrome/browser/autofill/phone_number.cc
index 57d44a1..72b5517 100644
--- a/chrome/browser/autofill/phone_number.cc
+++ b/chrome/browser/autofill/phone_number.cc
@@ -33,14 +33,21 @@ const AutofillType::FieldTypeSubGroup kAutofillPhoneTypes[] = {
const int kAutofillPhoneLength = arraysize(kAutofillPhoneTypes);
+void StripPunctuation(string16* number) {
+ RemoveChars(*number, kPhoneNumberSeparators, number);
+}
+
} // namespace
-PhoneNumber::PhoneNumber()
- : phone_group_(AutofillType::NO_GROUP) {
+PhoneNumber::PhoneNumber(AutofillProfile* profile)
+ : phone_group_(AutofillType::NO_GROUP),
+ profile_(profile) {
}
-PhoneNumber::PhoneNumber(AutofillType::FieldTypeGroup phone_group)
- : phone_group_(phone_group) {
+PhoneNumber::PhoneNumber(AutofillType::FieldTypeGroup phone_group,
+ AutofillProfile* profile)
+ : phone_group_(phone_group),
+ profile_(profile) {
}
PhoneNumber::PhoneNumber(const PhoneNumber& number) : FormGroup() {
@@ -52,66 +59,26 @@ PhoneNumber::~PhoneNumber() {}
PhoneNumber& PhoneNumber::operator=(const PhoneNumber& number) {
if (this == &number)
return *this;
- number_ = number.number_;
phone_group_ = number.phone_group_;
+ number_ = number.number_;
+ profile_ = number.profile_;
cached_parsed_phone_ = number.cached_parsed_phone_;
return *this;
}
-void PhoneNumber::GetMatchingTypes(const string16& text,
- FieldTypeSet* matching_types) const {
- string16 stripped_text(text);
- StripPunctuation(&stripped_text);
-
- if (!cached_parsed_phone_.IsValidNumber())
- return;
-
- if (IsNumber(stripped_text, cached_parsed_phone_.GetNumber()))
- matching_types->insert(GetNumberType());
-
- if (stripped_text == cached_parsed_phone_.GetCityCode())
- matching_types->insert(GetCityCodeType());
-
- if (stripped_text == cached_parsed_phone_.GetCountryCode())
- matching_types->insert(GetCountryCodeType());
-
- string16 city_and_local(cached_parsed_phone_.GetCityCode());
- city_and_local.append(cached_parsed_phone_.GetNumber());
- if (stripped_text == city_and_local)
- matching_types->insert(GetCityAndNumberType());
-
- // 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_types) const {
- DCHECK(non_empty_types);
-
- if (number_.empty())
- return;
-
- non_empty_types->insert(GetWholeNumberType());
-
- if (!cached_parsed_phone_.IsValidNumber())
- return;
-
- non_empty_types->insert(GetNumberType());
-
- if (!cached_parsed_phone_.GetCityCode().empty()) {
- non_empty_types->insert(GetCityCodeType());
- non_empty_types->insert(GetCityAndNumberType());
- }
-
- if (!cached_parsed_phone_.GetCountryCode().empty())
- non_empty_types->insert(GetCountryCodeType());
+void PhoneNumber::GetSupportedTypes(FieldTypeSet* supported_types) const {
+ supported_types->insert(GetWholeNumberType());
+ supported_types->insert(GetNumberType());
+ supported_types->insert(GetCityCodeType());
+ supported_types->insert(GetCityAndNumberType());
+ supported_types->insert(GetCountryCodeType());
}
string16 PhoneNumber::GetInfo(AutofillFieldType type) const {
if (type == GetWholeNumberType())
return number_;
+ UpdateCacheIfNeeded();
if (!cached_parsed_phone_.IsValidNumber())
return string16();
@@ -124,35 +91,78 @@ string16 PhoneNumber::GetInfo(AutofillFieldType type) const {
if (type == GetCountryCodeType())
return cached_parsed_phone_.GetCountryCode();
- string16 city_and_local(cached_parsed_phone_.GetCityCode());
- city_and_local.append(cached_parsed_phone_.GetNumber());
- if (type == GetCityAndNumberType())
+ if (type == GetCityAndNumberType()) {
+ string16 city_and_local(cached_parsed_phone_.GetCityCode());
+ city_and_local.append(cached_parsed_phone_.GetNumber());
return city_and_local;
+ }
return string16();
}
void PhoneNumber::SetInfo(AutofillFieldType type, const string16& value) {
- FieldTypeSubGroup subgroup = AutofillType(type).subgroup();
- FieldTypeGroup group = AutofillType(type).group();
+ // Store the group the first time we set some info.
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;
- cached_parsed_phone_ = autofill_i18n::PhoneObject(number_, locale_);
- StripPunctuation(&number_);
- } else {
+ phone_group_ = AutofillType(type).group();
+
+ FieldTypeSubGroup subgroup = AutofillType(type).subgroup();
+ if (subgroup != AutofillType::PHONE_CITY_AND_NUMBER &&
+ subgroup != AutofillType::PHONE_WHOLE_NUMBER) {
+ // Only full phone numbers should be set directly.
NOTREACHED();
+ return;
+ }
+
+ number_ = value;
+ cached_parsed_phone_ = autofill_i18n::PhoneObject(number_, locale());
+}
+
+// Normalize phones if |type| is a whole number:
+// (650)2345678 -> 6502345678
+// 1-800-FLOWERS -> 18003569377
+// If the phone cannot be normalized, returns the stored value verbatim.
+string16 PhoneNumber::GetCanonicalizedInfo(AutofillFieldType type) const {
+ string16 phone = GetInfo(type);
+ if (type != GetWholeNumberType())
+ return phone;
+
+ string16 normalized_phone = autofill_i18n::NormalizePhoneNumber(phone,
+ locale());
+ if (!normalized_phone.empty())
+ return normalized_phone;
+
+ return phone;
+}
+
+bool PhoneNumber::SetCanonicalizedInfo(AutofillFieldType type,
+ const string16& value) {
+ string16 number = value;
+ StripPunctuation(&number);
+ SetInfo(type, number);
+
+ return NormalizePhone();
+}
+
+void PhoneNumber::GetMatchingTypes(const string16& text,
+ FieldTypeSet* matching_types) const {
+ string16 stripped_text = text;
+ StripPunctuation(&stripped_text);
+ FormGroup::GetMatchingTypes(stripped_text, matching_types);
+
+ // For US numbers, also compare to the three-digit prefix and the four-digit
+ // suffix, since websites often split numbers into these two fields.
+ string16 number = GetCanonicalizedInfo(GetNumberType());
+ if (locale() == "US" && number.size() == (kPrefixLength + kSuffixLength)) {
+ string16 prefix = number.substr(kPrefixOffset, kPrefixLength);
+ string16 suffix = number.substr(kSuffixOffset, kSuffixLength);
+ if (text == prefix || text == suffix)
+ matching_types->insert(GetNumberType());
+ }
+
+ string16 whole_number = GetCanonicalizedInfo(GetWholeNumberType());
+ if (!whole_number.empty() &&
+ autofill_i18n::NormalizePhoneNumber(text, locale()) == whole_number) {
+ matching_types->insert(GetWholeNumberType());
}
}
@@ -161,14 +171,23 @@ bool PhoneNumber::NormalizePhone() {
if (number_.empty())
return true;
+ UpdateCacheIfNeeded();
number_ = cached_parsed_phone_.GetWholeNumber();
return !number_.empty();
}
-void PhoneNumber::set_locale(const std::string& locale) {
- locale_ = locale;
- if (!number_.empty() && cached_parsed_phone_.GetLocale() != locale_)
- cached_parsed_phone_ = autofill_i18n::PhoneObject(number_, locale_);
+std::string PhoneNumber::locale() const {
+ if (!profile_) {
+ NOTREACHED();
+ return "US";
+ }
+
+ return profile_->CountryCode();
+}
+
+void PhoneNumber::UpdateCacheIfNeeded() const {
+ if (!number_.empty() && cached_parsed_phone_.GetLocale() != locale())
+ cached_parsed_phone_ = autofill_i18n::PhoneObject(number_, locale());
}
AutofillFieldType PhoneNumber::GetNumberType() const {
@@ -221,30 +240,53 @@ AutofillFieldType PhoneNumber::GetWholeNumberType() const {
return UNKNOWN_TYPE;
}
+PhoneNumber::PhoneCombineHelper::PhoneCombineHelper(
+ AutofillType::FieldTypeGroup phone_group)
+ : phone_group_(phone_group) {
+}
+
+PhoneNumber::PhoneCombineHelper::~PhoneCombineHelper() {
+}
+
bool PhoneNumber::PhoneCombineHelper::SetInfo(AutofillFieldType field_type,
const string16& value) {
- PhoneNumber temp(phone_group_);
+ PhoneNumber temp(phone_group_, NULL);
if (field_type == temp.GetCountryCodeType()) {
country_ = value;
return true;
- } else if (field_type == temp.GetCityCodeType()) {
+ }
+
+ if (field_type == temp.GetCityCodeType()) {
city_ = value;
return true;
- } else if (field_type == temp.GetCityAndNumberType()) {
+ }
+
+ if (field_type == temp.GetCityAndNumberType()) {
phone_ = value;
return true;
- } else if (field_type == temp.GetNumberType()) {
+ }
+
+ if (field_type == temp.GetWholeNumberType()) {
+ whole_number_ = value;
+ return true;
+ }
+
+ if (field_type == temp.GetNumberType()) {
phone_.append(value);
return true;
- } else {
- return false;
}
+
+ return false;
}
bool PhoneNumber::PhoneCombineHelper::ParseNumber(const std::string& locale,
string16* value) {
- DCHECK(value);
+ if (!whole_number_.empty()) {
+ *value = whole_number_;
+ return true;
+ }
+
return autofill_i18n::ConstructPhoneNumber(
country_, city_, phone_,
locale,
@@ -253,28 +295,6 @@ bool PhoneNumber::PhoneCombineHelper::ParseNumber(const std::string& locale,
value);
}
-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)
- return true;
- if (text.length() == kPrefixLength && StartsWith(number, text, true))
- return true;
- if (text.length() == kSuffixLength && EndsWith(number, text, true))
- return true;
-
- return false;
-}
-
-bool PhoneNumber::IsWholeNumber(const string16& text) const {
- return cached_parsed_phone_.ComparePhones(text) ==
- autofill_i18n::PHONES_EQUAL;
-}
-
-// Static.
-void PhoneNumber::StripPunctuation(string16* number) {
- RemoveChars(*number, kPhoneNumberSeparators, number);
+bool PhoneNumber::PhoneCombineHelper::IsEmpty() const {
+ return phone_.empty() && whole_number_.empty();
}
diff --git a/chrome/browser/autofill/phone_number.h b/chrome/browser/autofill/phone_number.h
index cd168c9..13261d01 100644
--- a/chrome/browser/autofill/phone_number.h
+++ b/chrome/browser/autofill/phone_number.h
@@ -15,26 +15,32 @@
#include "chrome/browser/autofill/form_group.h"
#include "chrome/browser/autofill/phone_number_i18n.h"
+class AutofillProfile;
+
// A form group that stores phone number information.
class PhoneNumber : public FormGroup {
public:
- PhoneNumber();
- explicit PhoneNumber(AutofillType::FieldTypeGroup phone_group);
+ explicit PhoneNumber(AutofillProfile* profile);
+ // The |profile| can be NULL; but if so, clients should avoid calling
+ // |GetInfo()| or |SetInfo()|. This is typically only useful if you want to
+ // call into the |GetNumberType()| (etc.) functions.
+ PhoneNumber(AutofillType::FieldTypeGroup phone_group,
+ AutofillProfile* profile);
PhoneNumber(const PhoneNumber& number);
virtual ~PhoneNumber();
PhoneNumber& operator=(const PhoneNumber& number);
+ void set_profile(AutofillProfile* profile) { profile_ = profile; }
+
// FormGroup implementation:
virtual void GetMatchingTypes(const string16& text,
- FieldTypeSet* matching_types) const;
- virtual void GetNonEmptyTypes(FieldTypeSet* non_empty_typess) const;
- virtual string16 GetInfo(AutofillFieldType type) const;
- virtual void SetInfo(AutofillFieldType type, const string16& value);
-
- // Validates |number_| and translates it into digits-only format.
- // Locale must be set.
- bool NormalizePhone();
+ FieldTypeSet* matching_types) const OVERRIDE;
+ virtual string16 GetInfo(AutofillFieldType type) const OVERRIDE;
+ virtual void SetInfo(AutofillFieldType type, const string16& value) OVERRIDE;
+ virtual string16 GetCanonicalizedInfo(AutofillFieldType type) const OVERRIDE;
+ virtual bool SetCanonicalizedInfo(AutofillFieldType type,
+ const string16& value) OVERRIDE;
// Size and offset of the prefix and suffix portions of phone numbers.
static const int kPrefixOffset = 0;
@@ -42,11 +48,6 @@ 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.
AutofillFieldType GetNumberType() const;
@@ -58,42 +59,52 @@ class PhoneNumber : public FormGroup {
// 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.
+ explicit PhoneCombineHelper(AutofillType::FieldTypeGroup phone_group);
+ ~PhoneCombineHelper();
+
+ // If |type| is a phone field type, saves the |value| accordingly 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(); }
+ // Returns true if both |phone_| and |whole_number_| are empty.
+ bool IsEmpty() const;
+
private:
string16 country_;
string16 city_;
string16 phone_;
+ string16 whole_number_;
AutofillType::FieldTypeGroup phone_group_;
};
private:
FRIEND_TEST_ALL_PREFIXES(PhoneNumberTest, Matcher);
- // 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 string16& number) const;
- bool IsWholeNumber(const string16& text) const;
+ // FormGroup:
+ virtual void GetSupportedTypes(FieldTypeSet* supported_types) const OVERRIDE;
+
+ // Validates |number_| and translates it into digits-only format.
+ bool NormalizePhone();
+
+ // Returns the locale for this phone number, based on the |profile_|.
+ std::string locale() const;
- static void StripPunctuation(string16* number);
+ // Updates the cached parsed number if the profile's locale has changed
+ // since the last time the cache was updated.
+ void UpdateCacheIfNeeded() const;
// Phone group - currently it is PHONE_HOME and PHONE_FAX.
AutofillType::FieldTypeGroup phone_group_;
- // Locale for phone normalizing.
- std::string locale_;
// The phone number.
string16 number_;
+ // Profile which stores the locale used as hint when normalizing the number.
+ AutofillProfile* profile_; // WEAK
// Cached number.
- autofill_i18n::PhoneObject cached_parsed_phone_;
+ mutable autofill_i18n::PhoneObject cached_parsed_phone_;
};
#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 c26f7c5..1ad2508 100644
--- a/chrome/browser/autofill/phone_number_i18n.cc
+++ b/chrome/browser/autofill/phone_number_i18n.cc
@@ -315,7 +315,6 @@ string16 PhoneObject::GetWholeNumber() const {
i18n::phonenumbers::PhoneNumberUtil* phone_util =
i18n::phonenumbers::PhoneNumberUtil::GetInstance();
phone_util->Format(*i18n_number_, format, &formatted_number);
- i18n::phonenumbers::PhoneNumberUtil::NormalizeDigitsOnly(&formatted_number);
whole_number_ = UTF8ToUTF16(formatted_number);
}
return whole_number_;
diff --git a/chrome/browser/autofill/phone_number_unittest.cc b/chrome/browser/autofill/phone_number_unittest.cc
index 65b5952..9a06418 100644
--- a/chrome/browser/autofill/phone_number_unittest.cc
+++ b/chrome/browser/autofill/phone_number_unittest.cc
@@ -3,22 +3,25 @@
// found in the LICENSE file.
#include "base/utf_string_conversions.h"
+#include "chrome/browser/autofill/autofill_profile.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"
TEST(PhoneNumberTest, Matcher) {
+ AutofillProfile profile;
+ profile.SetCountryCode("US");
// 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);
+ PhoneNumber phone_number(AutofillType::PHONE_HOME, &profile);
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());
+ EXPECT_EQ(1U, matching_types.size());
+ EXPECT_TRUE(matching_types.find(EMPTY_TYPE) != matching_types.end());
matching_types.clear();
phone_number.GetMatchingTypes(ASCIIToUTF16("1"), &matching_types);
EXPECT_EQ(1U, matching_types.size());
@@ -64,22 +67,17 @@ TEST(PhoneNumberTest, Matcher) {
EXPECT_EQ(0U, matching_types.size());
matching_types.clear();
phone_number.GetMatchingTypes(ASCIIToUTF16("6502345678"), &matching_types);
- EXPECT_EQ(2U, matching_types.size());
+ EXPECT_EQ(1U, 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_EQ(1U, 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"));
+ PhoneNumber fax_number(&profile);
fax_number.SetInfo(PHONE_FAX_WHOLE_NUMBER, fax);
matching_types.clear();
diff --git a/chrome/browser/autofill/select_control_handler.cc b/chrome/browser/autofill/select_control_handler.cc
index fe81b88..f2cf81d 100644
--- a/chrome/browser/autofill/select_control_handler.cc
+++ b/chrome/browser/autofill/select_control_handler.cc
@@ -205,7 +205,7 @@ void FillSelectControl(const FormGroup& form_group,
DCHECK_EQ(ASCIIToUTF16("select-one"), field->form_control_type);
DCHECK_EQ(field->option_values.size(), field->option_contents.size());
- string16 field_text = form_group.GetInfo(type);
+ string16 field_text = form_group.GetCanonicalizedInfo(type);
string16 field_text_lower = StringToLowerASCII(field_text);
if (field_text.empty())
return;
diff --git a/chrome/browser/webdata/autofill_table.cc b/chrome/browser/webdata/autofill_table.cc
index ff687c7..c387d86 100644
--- a/chrome/browser/webdata/autofill_table.cc
+++ b/chrome/browser/webdata/autofill_table.cc
@@ -126,10 +126,8 @@ CreditCard* CreditCardFromStatement(const sql::Statement& s) {
DCHECK(guid::IsValidGUID(credit_card->guid()));
credit_card->SetInfo(CREDIT_CARD_NAME, s.ColumnString16(1));
- credit_card->SetInfo(CREDIT_CARD_EXP_MONTH,
- s.ColumnString16(2));
- credit_card->SetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR,
- s.ColumnString16(3));
+ credit_card->SetInfo(CREDIT_CARD_EXP_MONTH, s.ColumnString16(2));
+ credit_card->SetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, s.ColumnString16(3));
int encrypted_number_len = s.ColumnByteLength(4);
string16 credit_card_number;
if (encrypted_number_len) {
diff --git a/chrome/test/data/autofill/merge/output/case.out b/chrome/test/data/autofill/merge/output/case.out
index 8c6fb81..3ed4808 100644
--- a/chrome/test/data/autofill/merge/output/case.out
+++ b/chrome/test/data/autofill/merge/output/case.out
@@ -10,5 +10,5 @@ ADDRESS_HOME_CITY: Mountain View
ADDRESS_HOME_STATE: CA
ADDRESS_HOME_ZIP: 94043
ADDRESS_HOME_COUNTRY: United States
-PHONE_HOME_WHOLE_NUMBER: 6505558888
-PHONE_FAX_WHOLE_NUMBER: 6505556789
+PHONE_HOME_WHOLE_NUMBER: (650) 555-8888
+PHONE_FAX_WHOLE_NUMBER: (650) 555-6789
diff --git a/chrome/test/data/autofill/merge/output/identical.out b/chrome/test/data/autofill/merge/output/identical.out
index 8c6fb81..3ed4808 100644
--- a/chrome/test/data/autofill/merge/output/identical.out
+++ b/chrome/test/data/autofill/merge/output/identical.out
@@ -10,5 +10,5 @@ ADDRESS_HOME_CITY: Mountain View
ADDRESS_HOME_STATE: CA
ADDRESS_HOME_ZIP: 94043
ADDRESS_HOME_COUNTRY: United States
-PHONE_HOME_WHOLE_NUMBER: 6505558888
-PHONE_FAX_WHOLE_NUMBER: 6505556789
+PHONE_HOME_WHOLE_NUMBER: (650) 555-8888
+PHONE_FAX_WHOLE_NUMBER: (650) 555-6789
diff --git a/chrome/test/data/autofill/merge/output/multimerge.out b/chrome/test/data/autofill/merge/output/multimerge.out
index c0ca01d..f14e5e2 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: 16502101111
-PHONE_HOME_WHOLE_NUMBER: 6502343333
-PHONE_FAX_WHOLE_NUMBER: 7812008888
+PHONE_HOME_WHOLE_NUMBER: +1 650-210-1111
+PHONE_HOME_WHOLE_NUMBER: (650) 234-3333
+PHONE_FAX_WHOLE_NUMBER: (781) 200-8888
diff --git a/chrome/test/data/autofill/merge/output/primarycase.out b/chrome/test/data/autofill/merge/output/primarycase.out
index c0ca01d..f14e5e2 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: 16502101111
-PHONE_HOME_WHOLE_NUMBER: 6502343333
-PHONE_FAX_WHOLE_NUMBER: 7812008888
+PHONE_HOME_WHOLE_NUMBER: +1 650-210-1111
+PHONE_HOME_WHOLE_NUMBER: (650) 234-3333
+PHONE_FAX_WHOLE_NUMBER: (781) 200-8888
diff --git a/chrome/test/data/autofill/merge/output/singlemerge.out b/chrome/test/data/autofill/merge/output/singlemerge.out
index c0a25903..62843bc 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: 16502101111
-PHONE_FAX_WHOLE_NUMBER: 7812008888
+PHONE_HOME_WHOLE_NUMBER: +1 650-210-1111
+PHONE_FAX_WHOLE_NUMBER: (781) 200-8888
diff --git a/chrome/test/data/autofill/merge/output/validation.out b/chrome/test/data/autofill/merge/output/validation.out
index 2925154..1462b59 100644
--- a/chrome/test/data/autofill/merge/output/validation.out
+++ b/chrome/test/data/autofill/merge/output/validation.out
@@ -10,5 +10,5 @@ ADDRESS_HOME_CITY: Mountain View
ADDRESS_HOME_STATE: CA
ADDRESS_HOME_ZIP: 94043
ADDRESS_HOME_COUNTRY: United States
-PHONE_HOME_WHOLE_NUMBER: 6505558888
-PHONE_FAX_WHOLE_NUMBER: 6505556789
+PHONE_HOME_WHOLE_NUMBER: (650) 555-8888
+PHONE_FAX_WHOLE_NUMBER: (650) 555-6789