OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/autofill/autofill_profile.h" | 5 #include "chrome/browser/autofill/autofill_profile.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <map> | 8 #include <map> |
9 #include <set> | 9 #include <set> |
10 | 10 |
11 #include "base/basictypes.h" | 11 #include "base/basictypes.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/string_util.h" | 13 #include "base/string_util.h" |
14 #include "base/utf_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
15 #include "chrome/browser/autofill/address.h" | 15 #include "chrome/browser/autofill/address.h" |
16 #include "chrome/browser/autofill/autofill_type.h" | 16 #include "chrome/browser/autofill/autofill_type.h" |
17 #include "chrome/browser/autofill/contact_info.h" | 17 #include "chrome/browser/autofill/contact_info.h" |
18 #include "chrome/browser/autofill/fax_number.h" | 18 #include "chrome/browser/autofill/phone_number.h" |
19 #include "chrome/browser/autofill/home_phone_number.h" | 19 #include "chrome/browser/autofill/phone_number_i18n.h" |
20 #include "chrome/common/guid.h" | 20 #include "chrome/common/guid.h" |
21 #include "grit/generated_resources.h" | 21 #include "grit/generated_resources.h" |
22 #include "ui/base/l10n/l10n_util.h" | 22 #include "ui/base/l10n/l10n_util.h" |
23 | 23 |
24 namespace { | 24 namespace { |
25 | 25 |
26 // Like |AutofillType::GetEquivalentFieldType()|, but also returns |NAME_FULL| | 26 // Like |AutofillType::GetEquivalentFieldType()|, but also returns |NAME_FULL| |
27 // for first, middle, and last name field types. | 27 // for first, middle, and last name field types. |
28 AutofillFieldType GetEquivalentFieldTypeCollapsingNames( | 28 AutofillFieldType GetEquivalentFieldTypeCollapsingNames( |
29 AutofillFieldType field_type) { | 29 AutofillFieldType field_type) { |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 if (i > 0) | 110 if (i > 0) |
111 accumulate += ASCIIToUTF16(" "); | 111 accumulate += ASCIIToUTF16(" "); |
112 accumulate += values[i]; | 112 accumulate += values[i]; |
113 } | 113 } |
114 return accumulate; | 114 return accumulate; |
115 } | 115 } |
116 | 116 |
117 template <class T> | 117 template <class T> |
118 void CopyValuesToItems(AutofillFieldType type, | 118 void CopyValuesToItems(AutofillFieldType type, |
119 const std::vector<string16>& values, | 119 const std::vector<string16>& values, |
120 std::vector<T>* form_group_items) { | 120 std::vector<T>* form_group_items, |
| 121 const T& prototype) { |
121 form_group_items->resize(values.size()); | 122 form_group_items->resize(values.size()); |
122 for (size_t i = 0; i < form_group_items->size(); ++i) | 123 for (size_t i = 0; i < form_group_items->size(); ++i) |
123 (*form_group_items)[i].SetInfo(type, CollapseWhitespace(values[i], false)); | 124 (*form_group_items)[i].SetInfo(type, CollapseWhitespace(values[i], false)); |
124 // Must have at least one (possibly empty) element. | 125 // Must have at least one (possibly empty) element. |
125 if (form_group_items->empty()) | 126 if (form_group_items->empty()) |
126 form_group_items->resize(1); | 127 form_group_items->resize(1, prototype); |
127 } | 128 } |
128 | 129 |
129 template <class T> | 130 template <class T> |
130 void CopyItemsToValues(AutofillFieldType type, | 131 void CopyItemsToValues(AutofillFieldType type, |
131 const std::vector<T>& form_group_items, | 132 const std::vector<T>& form_group_items, |
132 std::vector<string16>* values) { | 133 std::vector<string16>* values) { |
133 values->resize(form_group_items.size()); | 134 values->resize(form_group_items.size()); |
134 for (size_t i = 0; i < values->size(); ++i) | 135 for (size_t i = 0; i < values->size(); ++i) |
135 (*values)[i] = form_group_items[i].GetInfo(type); | 136 (*values)[i] = form_group_items[i].GetInfo(type); |
136 } | 137 } |
(...skipping 30 matching lines...) Expand all Loading... |
167 collapsed_set.insert(PHONE_FAX_WHOLE_NUMBER); | 168 collapsed_set.insert(PHONE_FAX_WHOLE_NUMBER); |
168 break; | 169 break; |
169 | 170 |
170 default: | 171 default: |
171 collapsed_set.insert(*iter); | 172 collapsed_set.insert(*iter); |
172 } | 173 } |
173 } | 174 } |
174 std::swap(*type_set, collapsed_set); | 175 std::swap(*type_set, collapsed_set); |
175 } | 176 } |
176 | 177 |
| 178 class FindByPhone { |
| 179 public: |
| 180 FindByPhone(const string16& phone, const std::string& country_code) |
| 181 : phone_(phone), |
| 182 country_code_(country_code) { |
| 183 } |
| 184 |
| 185 bool operator()(const string16& phone) { |
| 186 return autofill_i18n::PhoneNumbersMatch(phone, phone_, country_code_); |
| 187 } |
| 188 |
| 189 bool operator()(const string16* phone) { |
| 190 return autofill_i18n::PhoneNumbersMatch(*phone, phone_, country_code_); |
| 191 } |
| 192 |
| 193 private: |
| 194 string16 phone_; |
| 195 std::string country_code_; |
| 196 }; |
| 197 |
177 } // namespace | 198 } // namespace |
178 | 199 |
179 AutofillProfile::AutofillProfile(const std::string& guid) | 200 AutofillProfile::AutofillProfile(const std::string& guid) |
180 : guid_(guid), name_(1), email_(1), home_number_(1), fax_number_(1) { | 201 : guid_(guid), |
| 202 name_(1), |
| 203 email_(1), |
| 204 home_number_(1, PhoneNumber(AutofillType::PHONE_HOME)), |
| 205 fax_number_(1, PhoneNumber(AutofillType::PHONE_FAX)) { |
181 } | 206 } |
182 | 207 |
183 AutofillProfile::AutofillProfile() | 208 AutofillProfile::AutofillProfile() |
184 : guid_(guid::GenerateGUID()), | 209 : guid_(guid::GenerateGUID()), |
185 name_(1), | 210 name_(1), |
186 email_(1), | 211 email_(1), |
187 home_number_(1), | 212 home_number_(1, PhoneNumber(AutofillType::PHONE_HOME)), |
188 fax_number_(1) { | 213 fax_number_(1, PhoneNumber(AutofillType::PHONE_FAX)) { |
189 } | 214 } |
190 | 215 |
191 AutofillProfile::AutofillProfile(const AutofillProfile& profile) | 216 AutofillProfile::AutofillProfile(const AutofillProfile& profile) |
192 : FormGroup() { | 217 : FormGroup() { |
193 operator=(profile); | 218 operator=(profile); |
194 } | 219 } |
195 | 220 |
196 AutofillProfile::~AutofillProfile() { | 221 AutofillProfile::~AutofillProfile() { |
197 } | 222 } |
198 | 223 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 void AutofillProfile::SetInfo(AutofillFieldType type, const string16& value) { | 264 void AutofillProfile::SetInfo(AutofillFieldType type, const string16& value) { |
240 FormGroup* form_group = MutableFormGroupForType(type); | 265 FormGroup* form_group = MutableFormGroupForType(type); |
241 if (form_group) | 266 if (form_group) |
242 form_group->SetInfo(type, CollapseWhitespace(value, false)); | 267 form_group->SetInfo(type, CollapseWhitespace(value, false)); |
243 } | 268 } |
244 | 269 |
245 void AutofillProfile::SetMultiInfo(AutofillFieldType type, | 270 void AutofillProfile::SetMultiInfo(AutofillFieldType type, |
246 const std::vector<string16>& values) { | 271 const std::vector<string16>& values) { |
247 switch (AutofillType(type).group()) { | 272 switch (AutofillType(type).group()) { |
248 case AutofillType::NAME: | 273 case AutofillType::NAME: |
249 CopyValuesToItems(type, values, &name_); | 274 CopyValuesToItems(type, values, &name_, NameInfo()); |
250 break; | 275 break; |
251 case AutofillType::EMAIL: | 276 case AutofillType::EMAIL: |
252 CopyValuesToItems(type, values, &email_); | 277 CopyValuesToItems(type, values, &email_, EmailInfo()); |
253 break; | 278 break; |
254 case AutofillType::PHONE_HOME: | 279 case AutofillType::PHONE_HOME: |
255 CopyValuesToItems(type, values, &home_number_); | 280 CopyValuesToItems(type, |
| 281 values, |
| 282 &home_number_, |
| 283 PhoneNumber(AutofillType::PHONE_HOME)); |
256 break; | 284 break; |
257 case AutofillType::PHONE_FAX: | 285 case AutofillType::PHONE_FAX: |
258 CopyValuesToItems(type, values, &fax_number_); | 286 CopyValuesToItems(type, |
| 287 values, |
| 288 &fax_number_, |
| 289 PhoneNumber(AutofillType::PHONE_FAX)); |
259 break; | 290 break; |
260 default: | 291 default: |
261 if (values.size() == 1) { | 292 if (values.size() == 1) { |
262 SetInfo(type, values[0]); | 293 SetInfo(type, values[0]); |
263 } else if (values.size() == 0) { | 294 } else if (values.size() == 0) { |
264 SetInfo(type, string16()); | 295 SetInfo(type, string16()); |
265 } else { | 296 } else { |
266 NOTREACHED() | 297 NOTREACHED() |
267 << "Attempt to set multiple values on single-valued field."; | 298 << "Attempt to set multiple values on single-valued field."; |
268 } | 299 } |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
456 | 487 |
457 bool AutofillProfile::operator!=(const AutofillProfile& profile) const { | 488 bool AutofillProfile::operator!=(const AutofillProfile& profile) const { |
458 return !operator==(profile); | 489 return !operator==(profile); |
459 } | 490 } |
460 | 491 |
461 const string16 AutofillProfile::PrimaryValue() const { | 492 const string16 AutofillProfile::PrimaryValue() const { |
462 return GetInfo(ADDRESS_HOME_LINE1) + | 493 return GetInfo(ADDRESS_HOME_LINE1) + |
463 GetInfo(ADDRESS_HOME_CITY); | 494 GetInfo(ADDRESS_HOME_CITY); |
464 } | 495 } |
465 | 496 |
| 497 bool AutofillProfile::NormalizePhones() { |
| 498 // Successful either if nothing to parse, or everything is parsed correctly. |
| 499 bool success = true; |
| 500 for (size_t i = 0; i < home_number_.size(); ++i) { |
| 501 home_number_[i].set_locale(CountryCode()); |
| 502 if (!home_number_[i].NormalizePhone()) |
| 503 success = false; |
| 504 } |
| 505 for (size_t i = 0; i < fax_number_.size(); ++i) { |
| 506 fax_number_[i].set_locale(CountryCode()); |
| 507 if (!fax_number_[i].NormalizePhone()) |
| 508 success = false; |
| 509 } |
| 510 return success; |
| 511 } |
| 512 |
466 void AutofillProfile::OverwriteWithOrAddTo(const AutofillProfile& profile) { | 513 void AutofillProfile::OverwriteWithOrAddTo(const AutofillProfile& profile) { |
467 FieldTypeSet field_types; | 514 FieldTypeSet field_types; |
468 profile.GetNonEmptyTypes(&field_types); | 515 profile.GetNonEmptyTypes(&field_types); |
469 | 516 |
470 // Only transfer "full" types (e.g. full name) and not fragments (e.g. | 517 // Only transfer "full" types (e.g. full name) and not fragments (e.g. |
471 // first name, last name). | 518 // first name, last name). |
472 CollapseCompoundFieldTypes(&field_types); | 519 CollapseCompoundFieldTypes(&field_types); |
473 | 520 |
474 for (FieldTypeSet::const_iterator iter = field_types.begin(); | 521 for (FieldTypeSet::const_iterator iter = field_types.begin(); |
475 iter != field_types.end(); ++iter) { | 522 iter != field_types.end(); ++iter) { |
476 if (AutofillProfile::SupportsMultiValue(*iter)) { | 523 if (AutofillProfile::SupportsMultiValue(*iter)) { |
477 std::vector<string16> new_values; | 524 std::vector<string16> new_values; |
478 profile.GetMultiInfo(*iter, &new_values); | 525 profile.GetMultiInfo(*iter, &new_values); |
479 std::vector<string16> existing_values; | 526 std::vector<string16> existing_values; |
480 GetMultiInfo(*iter, &existing_values); | 527 GetMultiInfo(*iter, &existing_values); |
| 528 FieldTypeGroup group = AutofillType(*iter).group(); |
481 for (std::vector<string16>::iterator value_iter = new_values.begin(); | 529 for (std::vector<string16>::iterator value_iter = new_values.begin(); |
482 value_iter != new_values.end(); ++value_iter) { | 530 value_iter != new_values.end(); ++value_iter) { |
483 // Don't add duplicates. | 531 // Don't add duplicates. |
484 if (std::find(existing_values.begin(), existing_values.end(), | 532 if (group == AutofillType::PHONE_HOME || |
485 *value_iter) == existing_values.end()) { | 533 group == AutofillType::PHONE_FAX) { |
486 existing_values.insert(existing_values.end(), *value_iter); | 534 AddPhoneIfUnique(*value_iter, &existing_values); |
| 535 } else { |
| 536 if (std::find(existing_values.begin(), existing_values.end(), |
| 537 *value_iter) == existing_values.end()) { |
| 538 existing_values.insert(existing_values.end(), *value_iter); |
| 539 } |
487 } | 540 } |
488 } | 541 } |
489 SetMultiInfo(*iter, existing_values); | 542 SetMultiInfo(*iter, existing_values); |
490 } else { | 543 } else { |
491 SetInfo(*iter, profile.GetInfo(*iter)); | 544 SetInfo(*iter, profile.GetInfo(*iter)); |
492 } | 545 } |
493 } | 546 } |
494 } | 547 } |
495 | 548 |
| 549 void AutofillProfile::AddPhoneIfUnique(const string16& phone, |
| 550 std::vector<string16>* existing_phones) { |
| 551 DCHECK(existing_phones); |
| 552 // Phones allow "fuzzy" matching, so "1-800-FLOWERS", "18003569377", |
| 553 // "(800)356-9377" and "356-9377" are considered the same. |
| 554 std::vector<string16>::const_iterator phone_iter; |
| 555 if (std::find_if(existing_phones->begin(), existing_phones->end(), |
| 556 FindByPhone(phone, CountryCode())) == |
| 557 existing_phones->end()) { |
| 558 existing_phones->push_back(phone); |
| 559 } |
| 560 } |
| 561 |
496 string16 AutofillProfile::ConstructInferredLabel( | 562 string16 AutofillProfile::ConstructInferredLabel( |
497 const std::vector<AutofillFieldType>& included_fields, | 563 const std::vector<AutofillFieldType>& included_fields, |
498 size_t num_fields_to_use) const { | 564 size_t num_fields_to_use) const { |
499 const string16 separator = | 565 const string16 separator = |
500 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_SEPARATOR); | 566 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_SEPARATOR); |
501 | 567 |
502 string16 label; | 568 string16 label; |
503 size_t num_fields_used = 0; | 569 size_t num_fields_used = 0; |
504 for (std::vector<AutofillFieldType>::const_iterator it = | 570 for (std::vector<AutofillFieldType>::const_iterator it = |
505 included_fields.begin(); | 571 included_fields.begin(); |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
669 << UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_STATE)) | 735 << UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_STATE)) |
670 << " " | 736 << " " |
671 << UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_ZIP)) | 737 << UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_ZIP)) |
672 << " " | 738 << " " |
673 << UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_COUNTRY)) | 739 << UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_COUNTRY)) |
674 << " " | 740 << " " |
675 << UTF16ToUTF8(MultiString(profile, PHONE_HOME_WHOLE_NUMBER)) | 741 << UTF16ToUTF8(MultiString(profile, PHONE_HOME_WHOLE_NUMBER)) |
676 << " " | 742 << " " |
677 << UTF16ToUTF8(MultiString(profile, PHONE_FAX_WHOLE_NUMBER)); | 743 << UTF16ToUTF8(MultiString(profile, PHONE_FAX_WHOLE_NUMBER)); |
678 } | 744 } |
OLD | NEW |