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