Commit 11c2bdd1 authored by georgey@chromium.org's avatar georgey@chromium.org

Autofill phone number enhancements and integration of Phone Number Util Library: part 3

BUG=71443
TEST=unit-tested
Review URL: http://codereview.chromium.org/6877130

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@86305 0039d316-1c4b-4281-b951-d872f2087c98
parent e430bd88
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#include "chrome/browser/autofill/field_types.h" #include "chrome/browser/autofill/field_types.h"
#include "chrome/browser/autofill/form_group.h" #include "chrome/browser/autofill/form_group.h"
#include "chrome/browser/autofill/personal_data_manager.h" #include "chrome/browser/autofill/personal_data_manager.h"
#include "chrome/browser/autofill/phone_number.h"
#include "chrome/browser/autofill/phone_number_i18n.h"
#include "chrome/browser/sync/util/data_encryption.h" #include "chrome/browser/sync/util/data_encryption.h"
using base::win::RegKey; using base::win::RegKey;
...@@ -131,6 +133,10 @@ bool ImportSingleProfile(FormGroup* profile, ...@@ -131,6 +133,10 @@ bool ImportSingleProfile(FormGroup* profile,
bool has_non_empty_fields = false; bool has_non_empty_fields = false;
// Phones need to be rebuilt.
PhoneNumber::PhoneCombineHelper home(AutofillType::PHONE_HOME);
PhoneNumber::PhoneCombineHelper fax(AutofillType::PHONE_FAX);
for (uint32 value_index = 0; value_index < key->ValueCount(); ++value_index) { for (uint32 value_index = 0; value_index < key->ValueCount(); ++value_index) {
std::wstring value_name; std::wstring value_name;
if (key->ReadName(value_index, &value_name) != ERROR_SUCCESS) if (key->ReadName(value_index, &value_name) != ERROR_SUCCESS)
...@@ -144,9 +150,21 @@ bool ImportSingleProfile(FormGroup* profile, ...@@ -144,9 +150,21 @@ bool ImportSingleProfile(FormGroup* profile,
if (it->second == CREDIT_CARD_NUMBER) { if (it->second == CREDIT_CARD_NUMBER) {
field_value = DecryptCCNumber(field_value); field_value = DecryptCCNumber(field_value);
} }
profile->SetInfo(it->second, field_value); // We need to store phone data in the variables, before building the whole
// number at the end. The rest of the fields are set "as is".
if (!home.SetInfo(it->second, field_value) &&
!fax.SetInfo(it->second, field_value)) {
profile->SetInfo(it->second, field_value);
}
} }
} }
// Now re-construct the phones if needed.
string16 constructed_number;
if (!home.empty() && home.ParseNumber(std::string("US"), &constructed_number))
profile->SetInfo(PHONE_HOME_WHOLE_NUMBER, constructed_number);
if (!fax.empty() && fax.ParseNumber(std::string("US"), &constructed_number))
profile->SetInfo(PHONE_FAX_WHOLE_NUMBER, constructed_number);
return has_non_empty_fields; return has_non_empty_fields;
} }
...@@ -219,15 +237,6 @@ bool ImportCurrentUserProfiles(std::vector<AutofillProfile>* profiles, ...@@ -219,15 +237,6 @@ bool ImportCurrentUserProfiles(std::vector<AutofillProfile>* profiles,
AutofillProfile profile; AutofillProfile profile;
if (ImportSingleProfile(&profile, &key, reg_to_field)) { if (ImportSingleProfile(&profile, &key, reg_to_field)) {
// Combine phones into whole phone #. // Combine phones into whole phone #.
string16 phone;
phone = profile.GetInfo(PHONE_HOME_COUNTRY_CODE);
phone.append(profile.GetInfo(PHONE_HOME_CITY_CODE));
phone.append(profile.GetInfo(PHONE_HOME_NUMBER));
profile.SetInfo(PHONE_HOME_WHOLE_NUMBER, phone);
phone = profile.GetInfo(PHONE_FAX_COUNTRY_CODE);
phone.append(profile.GetInfo(PHONE_FAX_CITY_CODE));
phone.append(profile.GetInfo(PHONE_FAX_NUMBER));
profile.SetInfo(PHONE_FAX_WHOLE_NUMBER, phone);
profiles->push_back(profile); profiles->push_back(profile);
} }
} }
......
...@@ -44,7 +44,7 @@ ValueDescription profile1[] = { ...@@ -44,7 +44,7 @@ ValueDescription profile1[] = {
{ L"email", L"jdoe@test.com" }, { L"email", L"jdoe@test.com" },
{ L"company_name", L"Testcompany" }, { L"company_name", L"Testcompany" },
{ L"phone_home_number", L"555-5555" }, { L"phone_home_number", L"555-5555" },
{ L"phone_home_city_code", L"444" }, { L"phone_home_city_code", L"650" },
{ L"phone_home_country_code", L"1" }, { L"phone_home_country_code", L"1" },
}; };
...@@ -54,8 +54,8 @@ ValueDescription profile2[] = { ...@@ -54,8 +54,8 @@ ValueDescription profile2[] = {
{ L"email", L"janedoe@test.com" }, { L"email", L"janedoe@test.com" },
{ L"company_name", L"Testcompany" }, { L"company_name", L"Testcompany" },
{ L"phone_fax_number", L"555-6666" }, { L"phone_fax_number", L"555-6666" },
{ L"phone_fax_city_code", L"777" }, { L"phone_fax_city_code", L"812" },
{ L"phone_fax_country_code", L"2" }, { L"phone_fax_country_code", L"7" },
}; };
ValueDescription credit_card[] = { ValueDescription credit_card[] = {
...@@ -171,7 +171,7 @@ TEST_F(AutofillIeToolbarImportTest, TestAutofillImport) { ...@@ -171,7 +171,7 @@ TEST_F(AutofillIeToolbarImportTest, TestAutofillImport) {
EXPECT_EQ(profiles[1].GetInfo(PHONE_HOME_COUNTRY_CODE), profile1[7].value); EXPECT_EQ(profiles[1].GetInfo(PHONE_HOME_COUNTRY_CODE), profile1[7].value);
EXPECT_EQ(profiles[1].GetInfo(PHONE_HOME_CITY_CODE), profile1[6].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_NUMBER), L"5555555");
EXPECT_EQ(profiles[1].GetInfo(PHONE_HOME_WHOLE_NUMBER), L"14445555555"); EXPECT_EQ(profiles[1].GetInfo(PHONE_HOME_WHOLE_NUMBER), L"+16505555555");
EXPECT_EQ(profiles[0].GetInfo(NAME_FIRST), profile2[0].value); EXPECT_EQ(profiles[0].GetInfo(NAME_FIRST), profile2[0].value);
EXPECT_EQ(profiles[0].GetInfo(NAME_LAST), profile2[1].value); EXPECT_EQ(profiles[0].GetInfo(NAME_LAST), profile2[1].value);
...@@ -180,7 +180,7 @@ TEST_F(AutofillIeToolbarImportTest, TestAutofillImport) { ...@@ -180,7 +180,7 @@ TEST_F(AutofillIeToolbarImportTest, TestAutofillImport) {
EXPECT_EQ(profiles[0].GetInfo(PHONE_FAX_COUNTRY_CODE), profile2[6].value); EXPECT_EQ(profiles[0].GetInfo(PHONE_FAX_COUNTRY_CODE), profile2[6].value);
EXPECT_EQ(profiles[0].GetInfo(PHONE_FAX_CITY_CODE), profile2[5].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_NUMBER), L"5556666");
EXPECT_EQ(profiles[0].GetInfo(PHONE_FAX_WHOLE_NUMBER), L"27775556666"); EXPECT_EQ(profiles[0].GetInfo(PHONE_FAX_WHOLE_NUMBER), L"+78125556666");
ASSERT_EQ(credit_cards.size(), 1); 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_NAME), credit_card[0].value);
......
...@@ -1879,16 +1879,15 @@ TEST_F(AutofillManagerTest, FillPhoneNumber) { ...@@ -1879,16 +1879,15 @@ TEST_F(AutofillManagerTest, FillPhoneNumber) {
AutofillProfile *work_profile = autofill_manager_->GetProfileWithGUID( AutofillProfile *work_profile = autofill_manager_->GetProfileWithGUID(
"00000000-0000-0000-0000-000000000002"); "00000000-0000-0000-0000-000000000002");
ASSERT_TRUE(work_profile != NULL); ASSERT_TRUE(work_profile != NULL);
string16 saved_phone = work_profile->GetInfo(PHONE_HOME_NUMBER);
GUIDPair guid(work_profile->guid(), 0); GUIDPair guid(work_profile->guid(), 0);
GUIDPair empty(std::string(), 0); GUIDPair empty(std::string(), 0);
char test_data[] = "1234567890123456"; char test_data[] = "16505554567890123456";
for (int i = arraysize(test_data) - 1; i >= 0; --i) { for (int i = arraysize(test_data) - 1; i >= 0; --i) {
test_data[i] = 0; test_data[i] = 0;
SCOPED_TRACE(StringPrintf("Testing phone: %s", test_data)); SCOPED_TRACE(StringPrintf("Testing phone: %s", test_data));
work_profile->SetInfo(PHONE_HOME_NUMBER, ASCIIToUTF16(test_data)); work_profile->SetInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16(test_data));
// The page ID sent to the AutofillManager from the RenderView, used to send // The page ID sent to the AutofillManager from the RenderView, used to send
// an IPC message back to the renderer. // an IPC message back to the renderer.
int page_id = 100 - i; int page_id = 100 - i;
...@@ -1899,17 +1898,15 @@ TEST_F(AutofillManagerTest, FillPhoneNumber) { ...@@ -1899,17 +1898,15 @@ TEST_F(AutofillManagerTest, FillPhoneNumber) {
FormData results; FormData results;
EXPECT_TRUE(GetAutofillFormDataFilledMessage(&page_id, &results)); EXPECT_TRUE(GetAutofillFormDataFilledMessage(&page_id, &results));
if (i != 7) { if (i != 11) {
EXPECT_EQ(ASCIIToUTF16(test_data), results.fields[2].value); // The only parsable phone is 16505554567.
EXPECT_EQ(ASCIIToUTF16(test_data), results.fields[3].value); EXPECT_EQ(string16(), results.fields[2].value);
EXPECT_EQ(string16(), results.fields[3].value);
} else { } else {
// The only size that is parsed and split, right now is 7: EXPECT_EQ(ASCIIToUTF16("555"), results.fields[2].value);
EXPECT_EQ(ASCIIToUTF16("123"), results.fields[2].value);
EXPECT_EQ(ASCIIToUTF16("4567"), results.fields[3].value); EXPECT_EQ(ASCIIToUTF16("4567"), results.fields[3].value);
} }
} }
work_profile->SetInfo(PHONE_HOME_NUMBER, saved_phone);
} }
// Test that we can still fill a form when a field has been removed from it. // Test that we can still fill a form when a field has been removed from it.
......
...@@ -15,8 +15,8 @@ ...@@ -15,8 +15,8 @@
#include "chrome/browser/autofill/address.h" #include "chrome/browser/autofill/address.h"
#include "chrome/browser/autofill/autofill_type.h" #include "chrome/browser/autofill/autofill_type.h"
#include "chrome/browser/autofill/contact_info.h" #include "chrome/browser/autofill/contact_info.h"
#include "chrome/browser/autofill/fax_number.h" #include "chrome/browser/autofill/phone_number.h"
#include "chrome/browser/autofill/home_phone_number.h" #include "chrome/browser/autofill/phone_number_i18n.h"
#include "chrome/common/guid.h" #include "chrome/common/guid.h"
#include "grit/generated_resources.h" #include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
...@@ -117,13 +117,14 @@ const string16 MultiString(const AutofillProfile& p, AutofillFieldType type) { ...@@ -117,13 +117,14 @@ const string16 MultiString(const AutofillProfile& p, AutofillFieldType type) {
template <class T> template <class T>
void CopyValuesToItems(AutofillFieldType type, void CopyValuesToItems(AutofillFieldType type,
const std::vector<string16>& values, const std::vector<string16>& values,
std::vector<T>* form_group_items) { std::vector<T>* form_group_items,
const T& prototype) {
form_group_items->resize(values.size()); form_group_items->resize(values.size());
for (size_t i = 0; i < form_group_items->size(); ++i) for (size_t i = 0; i < form_group_items->size(); ++i)
(*form_group_items)[i].SetInfo(type, CollapseWhitespace(values[i], false)); (*form_group_items)[i].SetInfo(type, CollapseWhitespace(values[i], false));
// Must have at least one (possibly empty) element. // Must have at least one (possibly empty) element.
if (form_group_items->empty()) if (form_group_items->empty())
form_group_items->resize(1); form_group_items->resize(1, prototype);
} }
template <class T> template <class T>
...@@ -174,18 +175,42 @@ void CollapseCompoundFieldTypes(FieldTypeSet* type_set) { ...@@ -174,18 +175,42 @@ void CollapseCompoundFieldTypes(FieldTypeSet* type_set) {
std::swap(*type_set, collapsed_set); std::swap(*type_set, collapsed_set);
} }
class FindByPhone {
public:
FindByPhone(const string16& phone, const std::string& country_code)
: phone_(phone),
country_code_(country_code) {
}
bool operator()(const string16& phone) {
return autofill_i18n::PhoneNumbersMatch(phone, phone_, country_code_);
}
bool operator()(const string16* phone) {
return autofill_i18n::PhoneNumbersMatch(*phone, phone_, country_code_);
}
private:
string16 phone_;
std::string country_code_;
};
} // namespace } // namespace
AutofillProfile::AutofillProfile(const std::string& guid) AutofillProfile::AutofillProfile(const std::string& guid)
: guid_(guid), name_(1), email_(1), home_number_(1), fax_number_(1) { : guid_(guid),
name_(1),
email_(1),
home_number_(1, PhoneNumber(AutofillType::PHONE_HOME)),
fax_number_(1, PhoneNumber(AutofillType::PHONE_FAX)) {
} }
AutofillProfile::AutofillProfile() AutofillProfile::AutofillProfile()
: guid_(guid::GenerateGUID()), : guid_(guid::GenerateGUID()),
name_(1), name_(1),
email_(1), email_(1),
home_number_(1), home_number_(1, PhoneNumber(AutofillType::PHONE_HOME)),
fax_number_(1) { fax_number_(1, PhoneNumber(AutofillType::PHONE_FAX)) {
} }
AutofillProfile::AutofillProfile(const AutofillProfile& profile) AutofillProfile::AutofillProfile(const AutofillProfile& profile)
...@@ -246,16 +271,22 @@ void AutofillProfile::SetMultiInfo(AutofillFieldType type, ...@@ -246,16 +271,22 @@ void AutofillProfile::SetMultiInfo(AutofillFieldType type,
const std::vector<string16>& values) { const std::vector<string16>& values) {
switch (AutofillType(type).group()) { switch (AutofillType(type).group()) {
case AutofillType::NAME: case AutofillType::NAME:
CopyValuesToItems(type, values, &name_); CopyValuesToItems(type, values, &name_, NameInfo());
break; break;
case AutofillType::EMAIL: case AutofillType::EMAIL:
CopyValuesToItems(type, values, &email_); CopyValuesToItems(type, values, &email_, EmailInfo());
break; break;
case AutofillType::PHONE_HOME: case AutofillType::PHONE_HOME:
CopyValuesToItems(type, values, &home_number_); CopyValuesToItems(type,
values,
&home_number_,
PhoneNumber(AutofillType::PHONE_HOME));
break; break;
case AutofillType::PHONE_FAX: case AutofillType::PHONE_FAX:
CopyValuesToItems(type, values, &fax_number_); CopyValuesToItems(type,
values,
&fax_number_,
PhoneNumber(AutofillType::PHONE_FAX));
break; break;
default: default:
if (values.size() == 1) { if (values.size() == 1) {
...@@ -463,6 +494,22 @@ const string16 AutofillProfile::PrimaryValue() const { ...@@ -463,6 +494,22 @@ const string16 AutofillProfile::PrimaryValue() const {
GetInfo(ADDRESS_HOME_CITY); 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) { void AutofillProfile::OverwriteWithOrAddTo(const AutofillProfile& profile) {
FieldTypeSet field_types; FieldTypeSet field_types;
profile.GetNonEmptyTypes(&field_types); profile.GetNonEmptyTypes(&field_types);
...@@ -478,12 +525,18 @@ void AutofillProfile::OverwriteWithOrAddTo(const AutofillProfile& profile) { ...@@ -478,12 +525,18 @@ void AutofillProfile::OverwriteWithOrAddTo(const AutofillProfile& profile) {
profile.GetMultiInfo(*iter, &new_values); profile.GetMultiInfo(*iter, &new_values);
std::vector<string16> existing_values; std::vector<string16> existing_values;
GetMultiInfo(*iter, &existing_values); GetMultiInfo(*iter, &existing_values);
FieldTypeGroup group = AutofillType(*iter).group();
for (std::vector<string16>::iterator value_iter = new_values.begin(); for (std::vector<string16>::iterator value_iter = new_values.begin();
value_iter != new_values.end(); ++value_iter) { value_iter != new_values.end(); ++value_iter) {
// Don't add duplicates. // Don't add duplicates.
if (std::find(existing_values.begin(), existing_values.end(), if (group == AutofillType::PHONE_HOME ||
*value_iter) == existing_values.end()) { group == AutofillType::PHONE_FAX) {
existing_values.insert(existing_values.end(), *value_iter); AddPhoneIfUnique(*value_iter, &existing_values);
} else {
if (std::find(existing_values.begin(), existing_values.end(),
*value_iter) == existing_values.end()) {
existing_values.insert(existing_values.end(), *value_iter);
}
} }
} }
SetMultiInfo(*iter, existing_values); SetMultiInfo(*iter, existing_values);
...@@ -493,6 +546,19 @@ void AutofillProfile::OverwriteWithOrAddTo(const AutofillProfile& profile) { ...@@ -493,6 +546,19 @@ void AutofillProfile::OverwriteWithOrAddTo(const AutofillProfile& profile) {
} }
} }
void AutofillProfile::AddPhoneIfUnique(const string16& phone,
std::vector<string16>* existing_phones) {
DCHECK(existing_phones);
// Phones allow "fuzzy" matching, so "1-800-FLOWERS", "18003569377",
// "(800)356-9377" and "356-9377" are considered the same.
std::vector<string16>::const_iterator phone_iter;
if (std::find_if(existing_phones->begin(), existing_phones->end(),
FindByPhone(phone, CountryCode())) ==
existing_phones->end()) {
existing_phones->push_back(phone);
}
}
string16 AutofillProfile::ConstructInferredLabel( string16 AutofillProfile::ConstructInferredLabel(
const std::vector<AutofillFieldType>& included_fields, const std::vector<AutofillFieldType>& included_fields,
size_t num_fields_to_use) const { size_t num_fields_to_use) const {
......
...@@ -119,6 +119,13 @@ class AutofillProfile : public FormGroup { ...@@ -119,6 +119,13 @@ class AutofillProfile : public FormGroup {
// aid with correct aggregation of new data. // aid with correct aggregation of new data.
const string16 PrimaryValue() const; 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 // Overwrites the single-valued field data in |profile| with this
// Profile. Or, for multi-valued fields append the new values. // Profile. Or, for multi-valued fields append the new values.
void OverwriteWithOrAddTo(const AutofillProfile& profile); void OverwriteWithOrAddTo(const AutofillProfile& profile);
...@@ -126,6 +133,13 @@ class AutofillProfile : public FormGroup { ...@@ -126,6 +133,13 @@ class AutofillProfile : public FormGroup {
private: private:
typedef std::vector<const FormGroup*> FormGroupList; typedef std::vector<const FormGroup*> FormGroupList;
// Checks if the |phone| is in the |existing_phones| using fuzzy matching:
// for example, "1-800-FLOWERS", "18003569377", "(800)356-9377" and "356-9377"
// are considered the same.
// Adds the |phone| to the |existing_phones| if not already there.
void AddPhoneIfUnique(const string16& phone,
std::vector<string16>* existing_phones);
// Builds inferred label from the first |num_fields_to_include| non-empty // Builds inferred label from the first |num_fields_to_include| non-empty
// fields in |label_fields|. Uses as many fields as possible if there are not // fields in |label_fields|. Uses as many fields as possible if there are not
// enough non-empty fields. // enough non-empty fields.
...@@ -161,8 +175,8 @@ class AutofillProfile : public FormGroup { ...@@ -161,8 +175,8 @@ class AutofillProfile : public FormGroup {
std::vector<NameInfo> name_; std::vector<NameInfo> name_;
std::vector<EmailInfo> email_; std::vector<EmailInfo> email_;
CompanyInfo company_; CompanyInfo company_;
std::vector<HomePhoneNumber> home_number_; std::vector<PhoneNumber> home_number_;
std::vector<FaxNumber> fax_number_; std::vector<PhoneNumber> fax_number_;
Address address_; Address address_;
}; };
......
...@@ -39,7 +39,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) { ...@@ -39,7 +39,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) {
AutofillProfile profile00; AutofillProfile profile00;
autofill_test::SetProfileInfo(&profile00, "", "Mitchell", "", autofill_test::SetProfileInfo(&profile00, "", "Mitchell", "",
"johnwayne@me.xyz", "Fox", "", "unit 5", "Hollywood", "CA", "91601", "US", "johnwayne@me.xyz", "Fox", "", "unit 5", "Hollywood", "CA", "91601", "US",
"12345678910", "01987654321"); "16505678910", "78127654321");
EXPECT_TRUE(UpdateProfileLabel(&profile00)); EXPECT_TRUE(UpdateProfileLabel(&profile00));
string16 summary00 = profile00.Label(); string16 summary00 = profile00.Label();
EXPECT_EQ(ASCIIToUTF16("Hollywood, CA"), summary00); EXPECT_EQ(ASCIIToUTF16("Hollywood, CA"), summary00);
...@@ -48,7 +48,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) { ...@@ -48,7 +48,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) {
AutofillProfile profile1; AutofillProfile profile1;
autofill_test::SetProfileInfo(&profile1, "", "Mitchell", "", autofill_test::SetProfileInfo(&profile1, "", "Mitchell", "",
"johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA", "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
"91601", "US", "12345678910", "01987654321"); "91601", "US", "16505678910", "78127654321");
EXPECT_TRUE(UpdateProfileLabel(&profile1)); EXPECT_TRUE(UpdateProfileLabel(&profile1));
string16 summary1 = profile1.Label(); string16 summary1 = profile1.Label();
EXPECT_EQ(ASCIIToUTF16("123 Zoo St., Hollywood"), summary1); EXPECT_EQ(ASCIIToUTF16("123 Zoo St., Hollywood"), summary1);
...@@ -57,7 +57,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) { ...@@ -57,7 +57,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) {
AutofillProfile profile2; AutofillProfile profile2;
autofill_test::SetProfileInfo(&profile2, "", "Mitchell", autofill_test::SetProfileInfo(&profile2, "", "Mitchell",
"Morrison", "johnwayne@me.xyz", "Fox", "", "unit 5", "Hollywood", "CA", "Morrison", "johnwayne@me.xyz", "Fox", "", "unit 5", "Hollywood", "CA",
"91601", "US", "12345678910", "01987654321"); "91601", "US", "16505678910", "78127654321");
EXPECT_TRUE(UpdateProfileLabel(&profile2)); EXPECT_TRUE(UpdateProfileLabel(&profile2));
string16 summary2 = profile2.Label(); string16 summary2 = profile2.Label();
// Summary does include full name which is empty if the first name is empty. // Summary does include full name which is empty if the first name is empty.
...@@ -67,7 +67,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) { ...@@ -67,7 +67,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) {
AutofillProfile profile3; AutofillProfile profile3;
autofill_test::SetProfileInfo(&profile3, "", "Mitchell", autofill_test::SetProfileInfo(&profile3, "", "Mitchell",
"Morrison", "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Morrison", "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910", "01987654321"); "Hollywood", "CA", "91601", "US", "16505678910", "78127654321");
EXPECT_TRUE(UpdateProfileLabel(&profile3)); EXPECT_TRUE(UpdateProfileLabel(&profile3));
string16 summary3 = profile3.Label(); string16 summary3 = profile3.Label();
EXPECT_EQ(ASCIIToUTF16("123 Zoo St., Hollywood"), summary3); EXPECT_EQ(ASCIIToUTF16("123 Zoo St., Hollywood"), summary3);
...@@ -76,7 +76,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) { ...@@ -76,7 +76,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) {
AutofillProfile profile4; AutofillProfile profile4;
autofill_test::SetProfileInfo(&profile4, "Marion", "Mitchell", "", autofill_test::SetProfileInfo(&profile4, "Marion", "Mitchell", "",
"johnwayne@me.xyz", "Fox", "", "unit 5", "Hollywood", "CA", "91601", "US", "johnwayne@me.xyz", "Fox", "", "unit 5", "Hollywood", "CA", "91601", "US",
"12345678910", "01987654321"); "16505678910", "01987654321");
EXPECT_TRUE(UpdateProfileLabel(&profile4)); EXPECT_TRUE(UpdateProfileLabel(&profile4));
string16 summary4 = profile4.Label(); string16 summary4 = profile4.Label();
EXPECT_EQ(ASCIIToUTF16("Marion Mitchell, Hollywood"), summary4); EXPECT_EQ(ASCIIToUTF16("Marion Mitchell, Hollywood"), summary4);
...@@ -85,7 +85,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) { ...@@ -85,7 +85,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) {
AutofillProfile profile5; AutofillProfile profile5;
autofill_test::SetProfileInfo(&profile5, "Marion", "Mitchell", "", autofill_test::SetProfileInfo(&profile5, "Marion", "Mitchell", "",
"johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA", "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
"91601", "US", "12345678910", "01987654321"); "91601", "US", "16505678910", "78127654321");
EXPECT_TRUE(UpdateProfileLabel(&profile5)); EXPECT_TRUE(UpdateProfileLabel(&profile5));
string16 summary5 = profile5.Label(); string16 summary5 = profile5.Label();
EXPECT_EQ(ASCIIToUTF16("Marion Mitchell, 123 Zoo St."), summary5); EXPECT_EQ(ASCIIToUTF16("Marion Mitchell, 123 Zoo St."), summary5);
...@@ -94,7 +94,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) { ...@@ -94,7 +94,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) {
AutofillProfile profile6; AutofillProfile profile6;
autofill_test::SetProfileInfo(&profile6, "Marion", "Mitchell", autofill_test::SetProfileInfo(&profile6, "Marion", "Mitchell",
"Morrison", "johnwayne@me.xyz", "Fox", "", "unit 5", "Hollywood", "CA", "Morrison", "johnwayne@me.xyz", "Fox", "", "unit 5", "Hollywood", "CA",
"91601", "US", "12345678910", "01987654321"); "91601", "US", "16505678910", "78127654321");
EXPECT_TRUE(UpdateProfileLabel(&profile6)); EXPECT_TRUE(UpdateProfileLabel(&profile6));
string16 summary6 = profile6.Label(); string16 summary6 = profile6.Label();
EXPECT_EQ(ASCIIToUTF16("Marion Mitchell Morrison, Hollywood"), EXPECT_EQ(ASCIIToUTF16("Marion Mitchell Morrison, Hollywood"),
...@@ -104,7 +104,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) { ...@@ -104,7 +104,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) {
AutofillProfile profile7; AutofillProfile profile7;
autofill_test::SetProfileInfo(&profile7, "Marion", "Mitchell", autofill_test::SetProfileInfo(&profile7, "Marion", "Mitchell",
"Morrison", "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Morrison", "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910", "01987654321"); "Hollywood", "CA", "91601", "US", "16505678910", "78127654321");
EXPECT_TRUE(UpdateProfileLabel(&profile7)); EXPECT_TRUE(UpdateProfileLabel(&profile7));
string16 summary7 = profile7.Label(); string16 summary7 = profile7.Label();
EXPECT_EQ(ASCIIToUTF16("Marion Mitchell Morrison, 123 Zoo St."), EXPECT_EQ(ASCIIToUTF16("Marion Mitchell Morrison, 123 Zoo St."),
...@@ -115,7 +115,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) { ...@@ -115,7 +115,7 @@ TEST(AutofillProfileTest, PreviewSummaryString) {
AutofillProfile profile7a; AutofillProfile profile7a;
autofill_test::SetProfileInfo(&profile7a, "Marion", "Mitchell", autofill_test::SetProfileInfo(&profile7a, "Marion", "Mitchell",
"Morrison", "marion@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Morrison", "marion@me.xyz", "Fox", "123 Zoo St.", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910", "01987654321"); "Hollywood", "CA", "91601", "US", "16505678910", "78127654321");
std::vector<AutofillProfile*> profiles; std::vector<AutofillProfile*> profiles;
profiles.push_back(&profile7); profiles.push_back(&profile7);
profiles.push_back(&profile7a); profiles.push_back(&profile7a);
...@@ -143,8 +143,8 @@ TEST(AutofillProfileTest, AdjustInferredLabels) { ...@@ -143,8 +143,8 @@ TEST(AutofillProfileTest, AdjustInferredLabels) {
"Elysium", "CA", "Elysium", "CA",
"91111", "91111",
"US", "US",
"11111111111", "16502111111",
"22222222222"); "16502222222");
profiles.push_back(new AutofillProfile); profiles.push_back(new AutofillProfile);
autofill_test::SetProfileInfo( autofill_test::SetProfileInfo(
profiles[1], profiles[1],
...@@ -182,8 +182,8 @@ TEST(AutofillProfileTest, AdjustInferredLabels) { ...@@ -182,8 +182,8 @@ TEST(AutofillProfileTest, AdjustInferredLabels) {
"Elysium", "CA", "Elysium", "CA",
"91111", "91111",
"US", "US",
"11111111111", "16502111111",
"22222222222"); "16502222222");
EXPECT_TRUE(AutofillProfile::AdjustInferredLabels(&profiles)); EXPECT_TRUE(AutofillProfile::AdjustInferredLabels(&profiles));
// Profile 0 and 2 inferred label now includes an e-mail. // Profile 0 and 2 inferred label now includes an e-mail.
...@@ -210,17 +210,17 @@ TEST(AutofillProfileTest, AdjustInferredLabels) { ...@@ -210,17 +210,17 @@ TEST(AutofillProfileTest, AdjustInferredLabels) {
"Elysium", "CA", "Elysium", "CA",
"91111", "91111",
"US", "US",
"11111111111", "16502111111",
"33333333333"); // Fax is different "16503333333"); // Fax is different
EXPECT_TRUE(AutofillProfile::AdjustInferredLabels(&profiles)); EXPECT_TRUE(AutofillProfile::AdjustInferredLabels(&profiles));
// Profile 0 and 2 inferred label now includes a fax number. // Profile 0 and 2 inferred label now includes a fax number.
EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., fax:#22222222222"), EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., fax:#16502222222"),
profiles[0]->Label()); profiles[0]->Label());
EXPECT_EQ(ASCIIToUTF16("Jane Doe, 123 Letha Shore."), EXPECT_EQ(ASCIIToUTF16("Jane Doe, 123 Letha Shore."),
profiles[1]->Label()); profiles[1]->Label());
EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., fax:#33333333333"), EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., fax:#16503333333"),
profiles[2]->Label()); profiles[2]->Label());
profiles.push_back(new AutofillProfile); profiles.push_back(new AutofillProfile);
...@@ -236,22 +236,22 @@ TEST(AutofillProfileTest, AdjustInferredLabels) { ...@@ -236,22 +236,22 @@ TEST(AutofillProfileTest, AdjustInferredLabels) {
"Elysium", "CA", "Elysium", "CA",
"91111", "91111",
"US", "US",
"44444444444", // Phone is different for some. "16504444444", // Phone is different for some.
"33333333333"); // Fax is different for some. "16503333333"); // Fax is different for some.
EXPECT_TRUE(AutofillProfile::AdjustInferredLabels(&profiles)); EXPECT_TRUE(AutofillProfile::AdjustInferredLabels(&profiles));
EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., 11111111111," EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., 16502111111,"
" fax:#22222222222"), " fax:#16502222222"),
profiles[0]->Label()); profiles[0]->Label());
EXPECT_EQ(ASCIIToUTF16("Jane Doe, 123 Letha Shore."), EXPECT_EQ(ASCIIToUTF16("Jane Doe, 123 Letha Shore."),
profiles[1]->Label()); profiles[1]->Label());
EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., 11111111111," EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., 16502111111,"
" fax:#33333333333"), " fax:#16503333333"),
profiles[2]->Label()); profiles[2]->Label());
// This one differs from other ones by unique phone, so no need for extra // This one differs from other ones by unique phone, so no need for extra
// information. // information.
EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., 44444444444"), EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., 16504444444"),
profiles[3]->Label()); profiles[3]->Label());
profiles.push_back(new AutofillProfile); profiles.push_back(new AutofillProfile);
...@@ -267,21 +267,21 @@ TEST(AutofillProfileTest, AdjustInferredLabels) { ...@@ -267,21 +267,21 @@ TEST(AutofillProfileTest, AdjustInferredLabels) {
"Elysium", "CA", "Elysium", "CA",
"91111", "91111",
"US", "US",
"44444444444", // Phone is different for some. "16504444444", // Phone is different for some.
"33333333333"); // Fax is different for some. "16503333333"); // Fax is different for some.
EXPECT_TRUE(AutofillProfile::AdjustInferredLabels(&profiles)); EXPECT_TRUE(AutofillProfile::AdjustInferredLabels(&profiles));
EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., johndoe@hades.com," EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., johndoe@hades.com,"
" 11111111111, fax:#22222222222"), " 16502111111, fax:#16502222222"),
profiles[0]->Label()); profiles[0]->Label());
EXPECT_EQ(ASCIIToUTF16("Jane Doe, 123 Letha Shore."), EXPECT_EQ(ASCIIToUTF16("Jane Doe, 123 Letha Shore."),
profiles[1]->Label()); profiles[1]->Label());
EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., johndoe@hades.com," EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., johndoe@hades.com,"
" 11111111111, fax:#33333333333"), " 16502111111, fax:#16503333333"),
profiles[2]->Label()); profiles[2]->Label());
EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., johndoe@hades.com," EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., johndoe@hades.com,"
" 44444444444, fax:#33333333333"), " 16504444444, fax:#16503333333"),
profiles[3]->Label()); profiles[3]->Label());
// This one differs from other ones by unique e-mail, so no need for extra // This one differs from other ones by unique e-mail, so no need for extra
// information. // information.
...@@ -308,8 +308,8 @@ TEST(AutofillProfileTest, CreateInferredLabels) { ...@@ -308,8 +308,8 @@ TEST(AutofillProfileTest, CreateInferredLabels) {
"Elysium", "CA", "Elysium", "CA",
"91111", "91111",
"US", "US",
"11111111111", "16502111111",
"22222222222"); "16502222222");
profiles.push_back(new AutofillProfile); profiles.push_back(new AutofillProfile);
autofill_test::SetProfileInfo(profiles[1], autofill_test::SetProfileInfo(profiles[1],
"Jane", "Jane",
...@@ -754,7 +754,7 @@ TEST(AutofillProfileTest, MultiValuePhone) { ...@@ -754,7 +754,7 @@ TEST(AutofillProfileTest, MultiValuePhone) {
AutofillProfile p2 = p; AutofillProfile p2 = p;
EXPECT_EQ(0, p.Compare(p2)); EXPECT_EQ(0, p.Compare(p2));
EXPECT_EQ(0, p.CompareMulti(p2)); EXPECT_EQ(0, p.CompareMulti(p2));
const string16 kNoOne(ASCIIToUTF16("4151110000")); const string16 kNoOne(ASCIIToUTF16("4152110000"));
set_values[1] = kNoOne; set_values[1] = kNoOne;
p.SetMultiInfo(PHONE_HOME_WHOLE_NUMBER, set_values); p.SetMultiInfo(PHONE_HOME_WHOLE_NUMBER, set_values);
p.GetMultiInfo(PHONE_HOME_WHOLE_NUMBER, &get_values); p.GetMultiInfo(PHONE_HOME_WHOLE_NUMBER, &get_values);
...@@ -777,8 +777,8 @@ TEST(AutofillProfileTest, MultiValuePhone) { ...@@ -777,8 +777,8 @@ TEST(AutofillProfileTest, MultiValuePhone) {
TEST(AutofillProfileTest, MultiValueFax) { TEST(AutofillProfileTest, MultiValueFax) {
AutofillProfile p; AutofillProfile p;
const string16 kJohnDoe(ASCIIToUTF16("4151112222")); const string16 kJohnDoe(ASCIIToUTF16("4152112222"));
const string16 kJohnPDoe(ASCIIToUTF16("4151113333")); const string16 kJohnPDoe(ASCIIToUTF16("4153113333"));
std::vector<string16> set_values; std::vector<string16> set_values;
set_values.push_back(kJohnDoe); set_values.push_back(kJohnDoe);
set_values.push_back(kJohnPDoe); set_values.push_back(kJohnPDoe);
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "chrome/browser/autofill/autofill_metrics.h" #include "chrome/browser/autofill/autofill_metrics.h"
#include "chrome/browser/autofill/form_structure.h" #include "chrome/browser/autofill/form_structure.h"
#include "chrome/browser/autofill/phone_number.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/autofill/select_control_handler.h"
#include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
...@@ -225,6 +226,11 @@ bool PersonalDataManager::ImportFormData( ...@@ -225,6 +226,11 @@ bool PersonalDataManager::ImportFormData(
// Detect and discard forms with multiple fields of the same type. // Detect and discard forms with multiple fields of the same type.
std::set<AutofillFieldType> types_seen; std::set<AutofillFieldType> types_seen;
// We only set complete phone, so aggregate phone parts in these vars and set
// complete at the end.
PhoneNumber::PhoneCombineHelper home(AutofillType::PHONE_HOME);
PhoneNumber::PhoneCombineHelper fax(AutofillType::PHONE_FAX);
for (size_t i = 0; i < form.field_count(); ++i) { for (size_t i = 0; i < form.field_count(); ++i) {
const AutofillField* field = form.field(i); const AutofillField* field = form.field(i);
string16 value = CollapseWhitespace(field->value, false); string16 value = CollapseWhitespace(field->value, false);
...@@ -262,51 +268,12 @@ bool PersonalDataManager::ImportFormData( ...@@ -262,51 +268,12 @@ bool PersonalDataManager::ImportFormData(
} }
++importable_credit_card_fields; ++importable_credit_card_fields;
} else { } else {
// In the case of a phone number, if the whole phone number was entered // We need to store phone data in the variables, before building the whole
// into a single field, then parse it and set the sub components. // number at the end. The rest of the fields are set "as is".
if (AutofillType(field_type).subgroup() == // If the fields are not the phone fields in question both home.SetInfo()
AutofillType::PHONE_WHOLE_NUMBER) { // and fax.SetInfo() are going to return false.
string16 number; if (!home.SetInfo(field_type, value) && !fax.SetInfo(field_type, value))
string16 city_code; imported_profile->SetInfo(field_type, value);
string16 country_code;
PhoneNumber::ParsePhoneNumber(value,
&number,
&city_code,
&country_code);
if (number.empty())
continue;
if (group == AutofillType::PHONE_HOME) {
imported_profile->SetInfo(PHONE_HOME_COUNTRY_CODE, country_code);
imported_profile->SetInfo(PHONE_HOME_CITY_CODE, city_code);
imported_profile->SetInfo(PHONE_HOME_NUMBER, number);
} else if (group == AutofillType::PHONE_FAX) {
imported_profile->SetInfo(PHONE_FAX_COUNTRY_CODE, country_code);
imported_profile->SetInfo(PHONE_FAX_CITY_CODE, city_code);
imported_profile->SetInfo(PHONE_FAX_NUMBER, number);
}
continue;
}
// Phone and fax numbers can be split across multiple fields, so we
// might have already stored the prefix, and now be at the suffix.
// If so, combine them to form the full number.
if (group == AutofillType::PHONE_HOME ||
group == AutofillType::PHONE_FAX) {
AutofillFieldType number_type = PHONE_HOME_NUMBER;
if (group == AutofillType::PHONE_FAX)
number_type = PHONE_FAX_NUMBER;
string16 stored_number = imported_profile->GetInfo(number_type);
if (stored_number.size() ==
static_cast<size_t>(PhoneNumber::kPrefixLength) &&
value.size() == static_cast<size_t>(PhoneNumber::kSuffixLength)) {
value = stored_number + value;
}
}
imported_profile->SetInfo(field_type, value);
// Reject profiles with invalid country information. // Reject profiles with invalid country information.
if (field_type == ADDRESS_HOME_COUNTRY && if (field_type == ADDRESS_HOME_COUNTRY &&
...@@ -317,6 +284,33 @@ bool PersonalDataManager::ImportFormData( ...@@ -317,6 +284,33 @@ bool PersonalDataManager::ImportFormData(
} }
} }
// Build phone numbers if they are from parts.
if (imported_profile.get()) {
string16 constructed_number;
if (!home.empty()) {
if (!home.ParseNumber(imported_profile->CountryCode(),
&constructed_number)) {
imported_profile.reset();
} else {
imported_profile->SetInfo(PHONE_HOME_WHOLE_NUMBER, constructed_number);
}
}
if (!fax.empty()) {
if (!fax.ParseNumber(imported_profile->CountryCode(),
&constructed_number)) {
imported_profile.reset();
} else {
imported_profile->SetInfo(PHONE_FAX_WHOLE_NUMBER, constructed_number);
}
}
}
// Normalize phone numbers.
if (imported_profile.get()) {
// Reject profile if even one of the phones is invalid.
if (!imported_profile->NormalizePhones())
imported_profile.reset();
}
// Reject the profile if minimum address and validation requirements are not // Reject the profile if minimum address and validation requirements are not
// met. // met.
if (imported_profile.get() && !IsValidLearnableProfile(*imported_profile)) if (imported_profile.get() && !IsValidLearnableProfile(*imported_profile))
......
...@@ -189,10 +189,6 @@ void AuxiliaryProfilesImpl::GetAddressBookPhoneNumbers( ...@@ -189,10 +189,6 @@ void AuxiliaryProfilesImpl::GetAddressBookPhoneNumbers(
ABPerson* me, ABPerson* me,
NSString* addressLabelRaw, NSString* addressLabelRaw,
AutofillProfile* profile) { AutofillProfile* profile) {
string16 number;
string16 city_code;
string16 country_code;
ABMultiValue* phoneNumbers = [me valueForProperty:kABPhoneProperty]; ABMultiValue* phoneNumbers = [me valueForProperty:kABPhoneProperty];
for (NSUInteger k = 0, phoneCount = [phoneNumbers count]; for (NSUInteger k = 0, phoneCount = [phoneNumbers count];
k < phoneCount; k++) { k < phoneCount; k++) {
...@@ -202,40 +198,25 @@ void AuxiliaryProfilesImpl::GetAddressBookPhoneNumbers( ...@@ -202,40 +198,25 @@ void AuxiliaryProfilesImpl::GetAddressBookPhoneNumbers(
[phoneLabelRaw isEqualToString:kABPhoneHomeLabel]) { [phoneLabelRaw isEqualToString:kABPhoneHomeLabel]) {
string16 homePhone = base::SysNSStringToUTF16( string16 homePhone = base::SysNSStringToUTF16(
[phoneNumbers valueAtIndex:reverseK]); [phoneNumbers valueAtIndex:reverseK]);
PhoneNumber::ParsePhoneNumber( profile->SetInfo(PHONE_HOME_WHOLE_NUMBER, homePhone);
homePhone, &number, &city_code, &country_code);
profile->SetInfo(PHONE_HOME_NUMBER, number);
profile->SetInfo(PHONE_HOME_CITY_CODE, city_code);
profile->SetInfo(PHONE_HOME_COUNTRY_CODE, country_code);
} else if ([addressLabelRaw isEqualToString:kABAddressHomeLabel] && } else if ([addressLabelRaw isEqualToString:kABAddressHomeLabel] &&
[phoneLabelRaw isEqualToString:kABPhoneHomeFAXLabel]) { [phoneLabelRaw isEqualToString:kABPhoneHomeFAXLabel]) {
string16 homeFax = base::SysNSStringToUTF16( string16 homeFax = base::SysNSStringToUTF16(
[phoneNumbers valueAtIndex:reverseK]); [phoneNumbers valueAtIndex:reverseK]);
PhoneNumber::ParsePhoneNumber(homeFax, profile->SetInfo(PHONE_FAX_WHOLE_NUMBER, homeFax);
&number, &city_code, &country_code);
profile->SetInfo(PHONE_FAX_NUMBER, number);
profile->SetInfo(PHONE_FAX_CITY_CODE, city_code);
profile->SetInfo(PHONE_FAX_COUNTRY_CODE, country_code);
} else if ([addressLabelRaw isEqualToString:kABAddressWorkLabel] && } else if ([addressLabelRaw isEqualToString:kABAddressWorkLabel] &&
[phoneLabelRaw isEqualToString:kABPhoneWorkLabel]) { [phoneLabelRaw isEqualToString:kABPhoneWorkLabel]) {
string16 workPhone = base::SysNSStringToUTF16( string16 workPhone = base::SysNSStringToUTF16(
[phoneNumbers valueAtIndex:reverseK]); [phoneNumbers valueAtIndex:reverseK]);
PhoneNumber::ParsePhoneNumber(workPhone, profile->SetInfo(PHONE_HOME_WHOLE_NUMBER, workPhone);
&number, &city_code, &country_code);
profile->SetInfo(PHONE_HOME_NUMBER, number);
profile->SetInfo(PHONE_HOME_CITY_CODE, city_code);
profile->SetInfo(PHONE_HOME_COUNTRY_CODE, country_code);
} else if ([addressLabelRaw isEqualToString:kABAddressWorkLabel] && } else if ([addressLabelRaw isEqualToString:kABAddressWorkLabel] &&
[phoneLabelRaw isEqualToString:kABPhoneWorkFAXLabel]) { [phoneLabelRaw isEqualToString:kABPhoneWorkFAXLabel]) {
string16 workFax = base::SysNSStringToUTF16( string16 workFax = base::SysNSStringToUTF16(
[phoneNumbers valueAtIndex:reverseK]); [phoneNumbers valueAtIndex:reverseK]);
PhoneNumber::ParsePhoneNumber(workFax, profile->SetInfo(PHONE_FAX_WHOLE_NUMBER, workFax);
&number, &city_code, &country_code);
profile->SetInfo(PHONE_FAX_NUMBER, number);
profile->SetInfo(PHONE_FAX_CITY_CODE, city_code);
profile->SetInfo(PHONE_FAX_COUNTRY_CODE, country_code);
} }
} }
profile->NormalizePhones();
} }
} // namespace } // namespace
......
...@@ -889,7 +889,7 @@ TEST_F(PersonalDataManagerTest, AggregateSameProfileWithConflict) { ...@@ -889,7 +889,7 @@ TEST_F(PersonalDataManagerTest, AggregateSameProfileWithConflict) {
form1.fields.push_back(field); form1.fields.push_back(field);
// Phone gets updated. // Phone gets updated.
autofill_test::CreateTestFormField( autofill_test::CreateTestFormField(
"Phone:", "phone", "4445556666", "text", &field); "Phone:", "phone", "6505556666", "text", &field);
form1.fields.push_back(field); form1.fields.push_back(field);
FormStructure form_structure1(form1); FormStructure form_structure1(form1);
...@@ -907,7 +907,7 @@ TEST_F(PersonalDataManagerTest, AggregateSameProfileWithConflict) { ...@@ -907,7 +907,7 @@ TEST_F(PersonalDataManagerTest, AggregateSameProfileWithConflict) {
AutofillProfile expected; AutofillProfile expected;
autofill_test::SetProfileInfo(&expected, "George", NULL, autofill_test::SetProfileInfo(&expected, "George", NULL,
"Washington", "theprez@gmail.com", NULL, "1600 Pennsylvania Avenue", "Washington", "theprez@gmail.com", NULL, "1600 Pennsylvania Avenue",
"Suite A", "San Francisco", "California", "94102", NULL, "4445556666", "Suite A", "San Francisco", "California", "94102", NULL, "4085556666",
NULL); NULL);
const std::vector<AutofillProfile*>& results1 = personal_data_->profiles(); const std::vector<AutofillProfile*>& results1 = personal_data_->profiles();
ASSERT_EQ(1U, results1.size()); ASSERT_EQ(1U, results1.size());
...@@ -945,7 +945,7 @@ TEST_F(PersonalDataManagerTest, AggregateSameProfileWithConflict) { ...@@ -945,7 +945,7 @@ TEST_F(PersonalDataManagerTest, AggregateSameProfileWithConflict) {
form2.fields.push_back(field); form2.fields.push_back(field);
// Phone gets updated. // Phone gets updated.
autofill_test::CreateTestFormField( autofill_test::CreateTestFormField(
"Phone:", "phone", "1231231234", "text", &field); "Phone:", "phone", "6502231234", "text", &field);
form2.fields.push_back(field); form2.fields.push_back(field);
FormStructure form_structure2(form2); FormStructure form_structure2(form2);
...@@ -964,7 +964,7 @@ TEST_F(PersonalDataManagerTest, AggregateSameProfileWithConflict) { ...@@ -964,7 +964,7 @@ TEST_F(PersonalDataManagerTest, AggregateSameProfileWithConflict) {
// Add multi-valued phone number to expectation. Also, country gets added. // Add multi-valued phone number to expectation. Also, country gets added.
std::vector<string16> values; std::vector<string16> values;
expected.GetMultiInfo(PHONE_HOME_WHOLE_NUMBER, &values); expected.GetMultiInfo(PHONE_HOME_WHOLE_NUMBER, &values);
values.push_back(ASCIIToUTF16("1231231234")); values.push_back(ASCIIToUTF16("6502231234"));
expected.SetMultiInfo(PHONE_HOME_WHOLE_NUMBER, values); expected.SetMultiInfo(PHONE_HOME_WHOLE_NUMBER, values);
expected.SetInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("United States")); expected.SetInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("United States"));
ASSERT_EQ(1U, results2.size()); ASSERT_EQ(1U, results2.size());
...@@ -1632,7 +1632,7 @@ TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) { ...@@ -1632,7 +1632,7 @@ TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) {
autofill_test::SetProfileInfo(&profile0, autofill_test::SetProfileInfo(&profile0,
"Marion", NULL, "Morrison", "Marion", NULL, "Morrison",
"johnwayne@me.xyz", NULL, "123 Zoo St.", NULL, "Hollywood", "CA", "johnwayne@me.xyz", NULL, "123 Zoo St.", NULL, "Hollywood", "CA",
"91601", "US", "2345678910", NULL); "91601", "US", "14155678910", NULL);
personal_data_->AddProfile(profile0); personal_data_->AddProfile(profile0);
...@@ -1642,7 +1642,7 @@ TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) { ...@@ -1642,7 +1642,7 @@ TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) {
MessageLoop::current()->Run(); MessageLoop::current()->Run();
personal_data_->GetNonEmptyTypes(&non_empty_types); personal_data_->GetNonEmptyTypes(&non_empty_types);
EXPECT_EQ(13U, non_empty_types.size()); EXPECT_EQ(14U, non_empty_types.size());
EXPECT_TRUE(non_empty_types.count(NAME_FIRST)); EXPECT_TRUE(non_empty_types.count(NAME_FIRST));
EXPECT_TRUE(non_empty_types.count(NAME_LAST)); EXPECT_TRUE(non_empty_types.count(NAME_LAST));
EXPECT_TRUE(non_empty_types.count(NAME_FULL)); EXPECT_TRUE(non_empty_types.count(NAME_FULL));
...@@ -1653,6 +1653,7 @@ TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) { ...@@ -1653,6 +1653,7 @@ TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) {
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_ZIP)); EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_ZIP));
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_COUNTRY)); EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_COUNTRY));
EXPECT_TRUE(non_empty_types.count(PHONE_HOME_NUMBER)); EXPECT_TRUE(non_empty_types.count(PHONE_HOME_NUMBER));
EXPECT_TRUE(non_empty_types.count(PHONE_HOME_COUNTRY_CODE));
EXPECT_TRUE(non_empty_types.count(PHONE_HOME_CITY_CODE)); EXPECT_TRUE(non_empty_types.count(PHONE_HOME_CITY_CODE));
EXPECT_TRUE(non_empty_types.count(PHONE_HOME_CITY_AND_NUMBER)); EXPECT_TRUE(non_empty_types.count(PHONE_HOME_CITY_AND_NUMBER));
EXPECT_TRUE(non_empty_types.count(PHONE_HOME_WHOLE_NUMBER)); EXPECT_TRUE(non_empty_types.count(PHONE_HOME_WHOLE_NUMBER));
...@@ -1662,13 +1663,13 @@ TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) { ...@@ -1662,13 +1663,13 @@ TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) {
autofill_test::SetProfileInfo(&profile1, autofill_test::SetProfileInfo(&profile1,
"Josephine", "Alicia", "Saenz", "Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "903 Apple Ct.", NULL, "Orlando", "FL", "32801", "joewayne@me.xyz", "Fox", "903 Apple Ct.", NULL, "Orlando", "FL", "32801",
"US", "19482937549", "13502849239"); "US", "16502937549", "14082849239");
AutofillProfile profile2; AutofillProfile profile2;
autofill_test::SetProfileInfo(&profile2, autofill_test::SetProfileInfo(&profile2,
"Josephine", "Alicia", "Saenz", "Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL", "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL",
"32801", "US", "19482937549", "13502849239"); "32801", "US", "16502937549", "14152849239");
personal_data_->AddProfile(profile1); personal_data_->AddProfile(profile1);
personal_data_->AddProfile(profile2); personal_data_->AddProfile(profile2);
......
...@@ -330,9 +330,9 @@ void PhoneField::SetPhoneType(PhoneType phone_type) { ...@@ -330,9 +330,9 @@ void PhoneField::SetPhoneType(PhoneType phone_type) {
// Field types are different as well, so we create a temporary phone number, // Field types are different as well, so we create a temporary phone number,
// to get relevant field types. // to get relevant field types.
if (phone_type == HOME_PHONE) if (phone_type == HOME_PHONE)
number_.reset(new HomePhoneNumber); number_.reset(new PhoneNumber(AutofillType::PHONE_HOME));
else else
number_.reset(new FaxNumber); number_.reset(new PhoneNumber(AutofillType::PHONE_FAX));
phone_type_ = phone_type; phone_type_ = phone_type;
} }
This diff is collapsed.
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define CHROME_BROWSER_AUTOFILL_PHONE_NUMBER_H_ #define CHROME_BROWSER_AUTOFILL_PHONE_NUMBER_H_
#pragma once #pragma once
#include <string>
#include <vector> #include <vector>
#include "base/gtest_prod_util.h" #include "base/gtest_prod_util.h"
...@@ -17,7 +18,8 @@ ...@@ -17,7 +18,8 @@
class PhoneNumber : public FormGroup { class PhoneNumber : public FormGroup {
public: public:
PhoneNumber(); PhoneNumber();
explicit PhoneNumber(const PhoneNumber& number); explicit PhoneNumber(AutofillType::FieldTypeGroup phone_group);
PhoneNumber(const PhoneNumber& number);
virtual ~PhoneNumber(); virtual ~PhoneNumber();
PhoneNumber& operator=(const PhoneNumber& number); PhoneNumber& operator=(const PhoneNumber& number);
...@@ -29,15 +31,9 @@ class PhoneNumber : public FormGroup { ...@@ -29,15 +31,9 @@ class PhoneNumber : public FormGroup {
virtual string16 GetInfo(AutofillFieldType type) const; virtual string16 GetInfo(AutofillFieldType type) const;
virtual void SetInfo(AutofillFieldType type, const string16& value); virtual void SetInfo(AutofillFieldType type, const string16& value);
// Parses |value| to extract the components of a phone number. |number| // Validates |number_| and translates it into digits-only format.
// returns the trailing 7 digits, |city_code| returns the next 3 digits, and // Locale must be set.
// |country_code| returns any remaining digits. bool NormalizePhone();
// Separator characters are stripped before parsing the digits.
// Returns true if parsing was successful, false otherwise.
static bool ParsePhoneNumber(const string16& value,
string16* number,
string16* city_code,
string16* country_code);
// Size and offset of the prefix and suffix portions of phone numbers. // Size and offset of the prefix and suffix portions of phone numbers.
static const int kPrefixOffset = 0; static const int kPrefixOffset = 0;
...@@ -45,53 +41,55 @@ class PhoneNumber : public FormGroup { ...@@ -45,53 +41,55 @@ class PhoneNumber : public FormGroup {
static const int kSuffixOffset = 3; static const int kSuffixOffset = 3;
static const int kSuffixLength = 4; 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 // 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. // phone number. Currently, these are either fax or home phone number types.
virtual AutofillFieldType GetNumberType() const = 0; AutofillFieldType GetNumberType() const;
virtual AutofillFieldType GetCityCodeType() const = 0; AutofillFieldType GetCityCodeType() const;
virtual AutofillFieldType GetCountryCodeType() const = 0; AutofillFieldType GetCountryCodeType() const;
virtual AutofillFieldType GetCityAndNumberType() const = 0; AutofillFieldType GetCityAndNumberType() const;
virtual AutofillFieldType GetWholeNumberType() const = 0; AutofillFieldType GetWholeNumberType() const;
// The class used to combine home phone or fax parts into a whole number.
class PhoneCombineHelper {
public:
explicit PhoneCombineHelper(AutofillType::FieldTypeGroup phone_group)
: phone_group_(phone_group) { }
// Sets PHONE_HOME/FAX_CITY_CODE, PHONE_HOME/FAX_COUNTRY_CODE,
// PHONE_HOME/FAX_CITY_AND_NUMBER, PHONE_HOME/FAX_NUMBER and returns true.
// For all other field types returs false.
bool SetInfo(AutofillFieldType type, const string16& value);
// Returns true if parsing was successful, false otherwise.
bool ParseNumber(const std::string& locale, string16* value);
bool empty() const { return phone_.empty(); }
private:
string16 country_;
string16 city_;
string16 phone_;
AutofillType::FieldTypeGroup phone_group_;
};
private: private:
FRIEND_TEST_ALL_PREFIXES(PhoneNumberTest, Matcher); FRIEND_TEST_ALL_PREFIXES(PhoneNumberTest, Matcher);
const string16& country_code() const { return country_code_; }
const string16& city_code() const { return city_code_; }
const string16& number() const { return number_; }
const string16& extension() const { return extension_; }
string16 CityAndNumber() const { return city_code_ + number_; }
// Returns the entire phone number as a string, without punctuation.
virtual string16 WholeNumber() const;
void set_country_code(const string16& country_code) {
country_code_ = country_code;
}
void set_city_code(const string16& city_code) { city_code_ = city_code; }
void set_number(const string16& number);
void set_extension(const string16& extension) { extension_ = extension; }
void set_whole_number(const string16& whole_number);
// The numbers will be digits only (no punctuation), so any call to the IsX() // The numbers will be digits only (no punctuation), so any call to the IsX()
// functions should first call StripPunctuation on the text. // functions should first call StripPunctuation on the text.
bool IsNumber(const string16& text) const; bool IsNumber(const string16& text, const string16& number) const;
bool IsCityCode(const string16& text) const;
bool IsCountryCode(const string16& text) const;
bool IsCityAndNumber(const string16& text) const;
bool IsWholeNumber(const string16& text) const; bool IsWholeNumber(const string16& text) const;
// Verifies that |number| is a valid phone number.
bool Validate(const string16& number) const;
// Removes any punctuation characters from |number|.
static void StripPunctuation(string16* number); static void StripPunctuation(string16* number);
// Phone group - currently it is PHONE_HOME and PHONE_FAX.
AutofillType::FieldTypeGroup phone_group_;
// Locale for phone normalizing.
std::string locale_;
// The pieces of the phone number. // The pieces of the phone number.
string16 country_code_;
string16 city_code_; // city or area code.
string16 number_; string16 number_;
string16 extension_;
}; };
#endif // CHROME_BROWSER_AUTOFILL_PHONE_NUMBER_H_ #endif // CHROME_BROWSER_AUTOFILL_PHONE_NUMBER_H_
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/stringprintf.h" #include "base/stringprintf.h"
#include "base/string_number_conversions.h" #include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h" #include "base/utf_string_conversions.h"
#include "chrome/browser/autofill/autofill_country.h"
#include "third_party/libphonenumber/cpp/src/phonenumberutil.h" #include "third_party/libphonenumber/cpp/src/phonenumberutil.h"
namespace { namespace {
...@@ -16,8 +17,8 @@ namespace { ...@@ -16,8 +17,8 @@ namespace {
std::string SanitizeLocaleCode(const std::string& locale_code) { std::string SanitizeLocaleCode(const std::string& locale_code) {
if (locale_code.length() == 2) if (locale_code.length() == 2)
return locale_code; return locale_code;
// Use USA for incomplete locales. return AutofillCountry::CountryCodeForLocale(
return std::string("US"); AutofillCountry::ApplicationLocale());
} }
i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat UtilsTypeToPhoneLibType( i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat UtilsTypeToPhoneLibType(
...@@ -162,6 +163,12 @@ bool ConstructPhoneNumber(const string16& country_code, ...@@ -162,6 +163,12 @@ bool ConstructPhoneNumber(const string16& country_code,
if (validation != i18n::phonenumbers::PhoneNumberUtil::IS_POSSIBLE) if (validation != i18n::phonenumbers::PhoneNumberUtil::IS_POSSIBLE)
return false; return false;
// This verifies that number has a valid area code (that in some cases could
// be empty) for parsed country code. Also verifies that this is a valid
// number (in US 1234567 is not valid, because numbers do not start with 1).
if (!phone_util->IsValidNumber(i18n_number))
return false;
std::string formatted_number; std::string formatted_number;
phone_util->Format(i18n_number, UtilsTypeToPhoneLibType(phone_format), phone_util->Format(i18n_number, UtilsTypeToPhoneLibType(phone_format),
......
...@@ -283,20 +283,29 @@ TEST(PhoneNumberI18NTest, ConstructPhoneNumber) { ...@@ -283,20 +283,29 @@ TEST(PhoneNumberI18NTest, ConstructPhoneNumber) {
&number)); &number));
EXPECT_EQ(number, string16()); EXPECT_EQ(number, string16());
// Italian number // Italian number
EXPECT_TRUE(ConstructPhoneNumber(ASCIIToUTF16("39"), EXPECT_TRUE(ConstructPhoneNumber(ASCIIToUTF16(""),
ASCIIToUTF16(""), ASCIIToUTF16("347"),
ASCIIToUTF16("236618300"), ASCIIToUTF16("2345678"),
"US", "IT",
autofill_i18n::INTERNATIONAL, autofill_i18n::INTERNATIONAL,
&number)); &number));
EXPECT_EQ(number, ASCIIToUTF16("+39 236618300")); EXPECT_EQ(number, ASCIIToUTF16("+39 347 234 5678"));
EXPECT_TRUE(ConstructPhoneNumber(ASCIIToUTF16("39"), // German number.
ASCIIToUTF16(""), EXPECT_TRUE(ConstructPhoneNumber(ASCIIToUTF16("49"),
ASCIIToUTF16("236618300"), ASCIIToUTF16("024"),
"US", ASCIIToUTF16("2345678901"),
"DE",
autofill_i18n::NATIONAL, autofill_i18n::NATIONAL,
&number)); &number));
EXPECT_EQ(number, ASCIIToUTF16("236618300")); EXPECT_EQ(number, ASCIIToUTF16("02423/45678901"));
EXPECT_TRUE(ConstructPhoneNumber(ASCIIToUTF16("49"),
ASCIIToUTF16("024"),
ASCIIToUTF16("2345678901"),
"DE",
autofill_i18n::INTERNATIONAL,
&number));
EXPECT_EQ(number, ASCIIToUTF16("+49 2423/45678901"));
} }
TEST(PhoneNumberI18NTest, FormatPhone) { TEST(PhoneNumberI18NTest, FormatPhone) {
......
...@@ -10,8 +10,8 @@ ADDRESS_HOME_CITY: San Francisco ...@@ -10,8 +10,8 @@ ADDRESS_HOME_CITY: San Francisco
ADDRESS_HOME_STATE: CA ADDRESS_HOME_STATE: CA
ADDRESS_HOME_ZIP: 94102 ADDRESS_HOME_ZIP: 94102
ADDRESS_HOME_COUNTRY: United States ADDRESS_HOME_COUNTRY: United States
PHONE_HOME_WHOLE_NUMBER: 1110001111 PHONE_HOME_WHOLE_NUMBER: 16502101111
PHONE_FAX_WHOLE_NUMBER: 8880008888 PHONE_FAX_WHOLE_NUMBER: 7812008888
--- ---
NAME_FIRST: Billy NAME_FIRST: Billy
NAME_MIDDLE: Bob NAME_MIDDLE: Bob
...@@ -24,5 +24,5 @@ ADDRESS_HOME_CITY: San Francisco ...@@ -24,5 +24,5 @@ ADDRESS_HOME_CITY: San Francisco
ADDRESS_HOME_STATE: CA ADDRESS_HOME_STATE: CA
ADDRESS_HOME_ZIP: 94102 ADDRESS_HOME_ZIP: 94102
ADDRESS_HOME_COUNTRY: United States ADDRESS_HOME_COUNTRY: United States
PHONE_HOME_WHOLE_NUMBER: 2220003333 PHONE_HOME_WHOLE_NUMBER: 6502343333
PHONE_FAX_WHOLE_NUMBER: 8880008888 PHONE_FAX_WHOLE_NUMBER: 7812008888
...@@ -10,8 +10,8 @@ ADDRESS_HOME_CITY: SAN FRANCISCO ...@@ -10,8 +10,8 @@ ADDRESS_HOME_CITY: SAN FRANCISCO
ADDRESS_HOME_STATE: CA ADDRESS_HOME_STATE: CA
ADDRESS_HOME_ZIP: 94102 ADDRESS_HOME_ZIP: 94102
ADDRESS_HOME_COUNTRY: United States ADDRESS_HOME_COUNTRY: United States
PHONE_HOME_WHOLE_NUMBER: 1110001111 PHONE_HOME_WHOLE_NUMBER: 16502101111
PHONE_FAX_WHOLE_NUMBER: 8880008888 PHONE_FAX_WHOLE_NUMBER: 7812008888
--- ---
NAME_FIRST: Billy NAME_FIRST: Billy
NAME_MIDDLE: Bob NAME_MIDDLE: Bob
...@@ -24,5 +24,5 @@ ADDRESS_HOME_CITY: San Francisco ...@@ -24,5 +24,5 @@ ADDRESS_HOME_CITY: San Francisco
ADDRESS_HOME_STATE: CA ADDRESS_HOME_STATE: CA
ADDRESS_HOME_ZIP: 94102 ADDRESS_HOME_ZIP: 94102
ADDRESS_HOME_COUNTRY: United States ADDRESS_HOME_COUNTRY: United States
PHONE_HOME_WHOLE_NUMBER: 2220003333 PHONE_HOME_WHOLE_NUMBER: 6502343333
PHONE_FAX_WHOLE_NUMBER: 8880008888 PHONE_FAX_WHOLE_NUMBER: 7812008888
...@@ -10,8 +10,8 @@ ADDRESS_HOME_CITY: San Francisco ...@@ -10,8 +10,8 @@ ADDRESS_HOME_CITY: San Francisco
ADDRESS_HOME_STATE: CA ADDRESS_HOME_STATE: CA
ADDRESS_HOME_ZIP: 94102 ADDRESS_HOME_ZIP: 94102
ADDRESS_HOME_COUNTRY: United States ADDRESS_HOME_COUNTRY: United States
PHONE_HOME_WHOLE_NUMBER: 1110001111 PHONE_HOME_WHOLE_NUMBER: 16502101111
PHONE_FAX_WHOLE_NUMBER: 8880008888 PHONE_FAX_WHOLE_NUMBER: 7812008888
--- ---
NAME_FIRST: Alice NAME_FIRST: Alice
NAME_MIDDLE: Anne NAME_MIDDLE: Anne
...@@ -24,5 +24,5 @@ ADDRESS_HOME_CITY: San Francisco ...@@ -24,5 +24,5 @@ ADDRESS_HOME_CITY: San Francisco
ADDRESS_HOME_STATE: NY ADDRESS_HOME_STATE: NY
ADDRESS_HOME_ZIP: 11001 ADDRESS_HOME_ZIP: 11001
ADDRESS_HOME_COUNTRY: Canada ADDRESS_HOME_COUNTRY: Canada
PHONE_HOME_WHOLE_NUMBER: 1110001111 PHONE_HOME_WHOLE_NUMBER: 16502101111
PHONE_FAX_WHOLE_NUMBER: 8880008888 PHONE_FAX_WHOLE_NUMBER: 7812008888
...@@ -14,6 +14,6 @@ ADDRESS_HOME_CITY: San Francisco ...@@ -14,6 +14,6 @@ ADDRESS_HOME_CITY: San Francisco
ADDRESS_HOME_STATE: CA ADDRESS_HOME_STATE: CA
ADDRESS_HOME_ZIP: 94102 ADDRESS_HOME_ZIP: 94102
ADDRESS_HOME_COUNTRY: United States ADDRESS_HOME_COUNTRY: United States
PHONE_HOME_WHOLE_NUMBER: 1110001111 PHONE_HOME_WHOLE_NUMBER: 16502101111
PHONE_HOME_WHOLE_NUMBER: 2220003333 PHONE_HOME_WHOLE_NUMBER: 6502343333
PHONE_FAX_WHOLE_NUMBER: 8880008888 PHONE_FAX_WHOLE_NUMBER: 7812008888
...@@ -14,6 +14,6 @@ ADDRESS_HOME_CITY: San Francisco ...@@ -14,6 +14,6 @@ ADDRESS_HOME_CITY: San Francisco
ADDRESS_HOME_STATE: CA ADDRESS_HOME_STATE: CA
ADDRESS_HOME_ZIP: 94102 ADDRESS_HOME_ZIP: 94102
ADDRESS_HOME_COUNTRY: United States ADDRESS_HOME_COUNTRY: United States
PHONE_HOME_WHOLE_NUMBER: 1110001111 PHONE_HOME_WHOLE_NUMBER: 16502101111
PHONE_HOME_WHOLE_NUMBER: 2220003333 PHONE_HOME_WHOLE_NUMBER: 6502343333
PHONE_FAX_WHOLE_NUMBER: 8880008888 PHONE_FAX_WHOLE_NUMBER: 7812008888
...@@ -10,5 +10,5 @@ ADDRESS_HOME_CITY: San Francisco ...@@ -10,5 +10,5 @@ ADDRESS_HOME_CITY: San Francisco
ADDRESS_HOME_STATE: NY ADDRESS_HOME_STATE: NY
ADDRESS_HOME_ZIP: 11001 ADDRESS_HOME_ZIP: 11001
ADDRESS_HOME_COUNTRY: Canada ADDRESS_HOME_COUNTRY: Canada
PHONE_HOME_WHOLE_NUMBER: 1110001111 PHONE_HOME_WHOLE_NUMBER: 16502101111
PHONE_FAX_WHOLE_NUMBER: 8880008888 PHONE_FAX_WHOLE_NUMBER: 7812008888
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment