1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "components/autofill/core/browser/autofill_profile.h" 6 7 #include <algorithm> 8 #include <functional> 9 #include <map> 10 #include <ostream> 11 #include <set> 12 13 #include "base/basictypes.h" 14 #include "base/guid.h" 15 #include "base/logging.h" 16 #include "base/strings/string_util.h" 17 #include "base/strings/utf_string_conversions.h" 18 #include "components/autofill/core/browser/address.h" 19 #include "components/autofill/core/browser/address_i18n.h" 20 #include "components/autofill/core/browser/autofill_country.h" 21 #include "components/autofill/core/browser/autofill_field.h" 22 #include "components/autofill/core/browser/autofill_type.h" 23 #include "components/autofill/core/browser/contact_info.h" 24 #include "components/autofill/core/browser/phone_number.h" 25 #include "components/autofill/core/browser/phone_number_i18n.h" 26 #include "components/autofill/core/browser/validation.h" 27 #include "components/autofill/core/common/form_field_data.h" 28 #include "grit/components_strings.h" 29 #include "third_party/libaddressinput/chromium/addressinput_util.h" 30 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h" 31 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_formatter.h" 32 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_metadata.h" 33 #include "ui/base/l10n/l10n_util.h" 34 35 using base::ASCIIToUTF16; 36 using base::UTF16ToUTF8; 37 using i18n::addressinput::AddressData; 38 using i18n::addressinput::AddressField; 39 40 namespace autofill { 41 namespace { 42 43 // Like |AutofillType::GetStorableType()|, but also returns |NAME_FULL| for 44 // first, middle, and last name field types. 45 ServerFieldType GetStorableTypeCollapsingNames(ServerFieldType type) { 46 ServerFieldType storable_type = AutofillType(type).GetStorableType(); 47 if (AutofillType(storable_type).group() == NAME) 48 return NAME_FULL; 49 50 return storable_type; 51 } 52 53 // Fills |distinguishing_fields| with a list of fields to use when creating 54 // labels that can help to distinguish between two profiles. Draws fields from 55 // |suggested_fields| if it is non-NULL; otherwise returns a default list. 56 // If |suggested_fields| is non-NULL, does not include |excluded_field| in the 57 // list. Otherwise, |excluded_field| is ignored, and should be set to 58 // |UNKNOWN_TYPE| by convention. The resulting list of fields is sorted in 59 // decreasing order of importance. 60 void GetFieldsForDistinguishingProfiles( 61 const std::vector<ServerFieldType>* suggested_fields, 62 ServerFieldType excluded_field, 63 std::vector<ServerFieldType>* distinguishing_fields) { 64 static const ServerFieldType kDefaultDistinguishingFields[] = { 65 NAME_FULL, 66 ADDRESS_HOME_LINE1, 67 ADDRESS_HOME_LINE2, 68 ADDRESS_HOME_DEPENDENT_LOCALITY, 69 ADDRESS_HOME_CITY, 70 ADDRESS_HOME_STATE, 71 ADDRESS_HOME_ZIP, 72 ADDRESS_HOME_SORTING_CODE, 73 ADDRESS_HOME_COUNTRY, 74 EMAIL_ADDRESS, 75 PHONE_HOME_WHOLE_NUMBER, 76 COMPANY_NAME, 77 }; 78 79 std::vector<ServerFieldType> default_fields; 80 if (!suggested_fields) { 81 default_fields.assign( 82 kDefaultDistinguishingFields, 83 kDefaultDistinguishingFields + arraysize(kDefaultDistinguishingFields)); 84 if (excluded_field == UNKNOWN_TYPE) { 85 distinguishing_fields->swap(default_fields); 86 return; 87 } 88 suggested_fields = &default_fields; 89 } 90 91 // Keep track of which fields we've seen so that we avoid duplicate entries. 92 // Always ignore fields of unknown type and the excluded field. 93 std::set<ServerFieldType> seen_fields; 94 seen_fields.insert(UNKNOWN_TYPE); 95 seen_fields.insert(GetStorableTypeCollapsingNames(excluded_field)); 96 97 distinguishing_fields->clear(); 98 for (std::vector<ServerFieldType>::const_iterator it = 99 suggested_fields->begin(); 100 it != suggested_fields->end(); ++it) { 101 ServerFieldType suggested_type = GetStorableTypeCollapsingNames(*it); 102 if (seen_fields.insert(suggested_type).second) 103 distinguishing_fields->push_back(suggested_type); 104 } 105 106 // Special case: If the excluded field is a partial name (e.g. first name) and 107 // the suggested fields include other name fields, include |NAME_FULL| in the 108 // list of distinguishing fields as a last-ditch fallback. This allows us to 109 // distinguish between profiles that are identical except for the name. 110 if (excluded_field != NAME_FULL && 111 GetStorableTypeCollapsingNames(excluded_field) == NAME_FULL) { 112 for (std::vector<ServerFieldType>::const_iterator it = 113 suggested_fields->begin(); 114 it != suggested_fields->end(); ++it) { 115 if (*it != excluded_field && 116 GetStorableTypeCollapsingNames(*it) == NAME_FULL) { 117 distinguishing_fields->push_back(NAME_FULL); 118 break; 119 } 120 } 121 } 122 } 123 124 // A helper function for string streaming. Concatenates multi-valued entries 125 // stored for a given |type| into a single string. This string is returned. 126 const base::string16 MultiString(const AutofillProfile& p, 127 ServerFieldType type) { 128 std::vector<base::string16> values; 129 p.GetRawMultiInfo(type, &values); 130 base::string16 accumulate; 131 for (size_t i = 0; i < values.size(); ++i) { 132 if (i > 0) 133 accumulate += ASCIIToUTF16(" "); 134 accumulate += values[i]; 135 } 136 return accumulate; 137 } 138 139 base::string16 GetFormGroupInfo(const FormGroup& form_group, 140 const AutofillType& type, 141 const std::string& app_locale) { 142 return app_locale.empty() ? 143 form_group.GetRawInfo(type.GetStorableType()) : 144 form_group.GetInfo(type, app_locale); 145 } 146 147 template <class T> 148 void CopyRawValuesToItems(ServerFieldType type, 149 const std::vector<base::string16>& values, 150 const T& prototype, 151 std::vector<T>* form_group_items) { 152 form_group_items->resize(values.size(), prototype); 153 for (size_t i = 0; i < form_group_items->size(); ++i) { 154 (*form_group_items)[i].SetRawInfo(type, values[i]); 155 } 156 // Must have at least one (possibly empty) element. 157 form_group_items->resize(std::max<size_t>(1UL, values.size()), prototype); 158 } 159 160 template <class T> 161 void CopyValuesToItems(AutofillType type, 162 const std::vector<base::string16>& values, 163 const T& prototype, 164 const std::string& app_locale, 165 std::vector<T>* form_group_items) { 166 form_group_items->resize(values.size(), prototype); 167 for (size_t i = 0; i < form_group_items->size(); ++i) { 168 (*form_group_items)[i].SetInfo(type, values[i], app_locale); 169 } 170 // Must have at least one (possibly empty) element. 171 form_group_items->resize(std::max<size_t>(1UL, values.size()), prototype); 172 } 173 174 template <class T> 175 void CopyItemsToValues(const AutofillType& type, 176 const std::vector<T>& form_group_items, 177 const std::string& app_locale, 178 std::vector<base::string16>* values) { 179 values->resize(form_group_items.size()); 180 for (size_t i = 0; i < values->size(); ++i) { 181 (*values)[i] = GetFormGroupInfo(form_group_items[i], type, app_locale); 182 } 183 } 184 185 // Collapse compound field types to their "full" type. I.e. First name 186 // collapses to full name, area code collapses to full phone, etc. 187 void CollapseCompoundFieldTypes(ServerFieldTypeSet* type_set) { 188 ServerFieldTypeSet collapsed_set; 189 for (ServerFieldTypeSet::iterator it = type_set->begin(); 190 it != type_set->end(); ++it) { 191 switch (*it) { 192 case NAME_FIRST: 193 case NAME_MIDDLE: 194 case NAME_LAST: 195 case NAME_MIDDLE_INITIAL: 196 case NAME_FULL: 197 case NAME_SUFFIX: 198 collapsed_set.insert(NAME_FULL); 199 break; 200 201 case PHONE_HOME_NUMBER: 202 case PHONE_HOME_CITY_CODE: 203 case PHONE_HOME_COUNTRY_CODE: 204 case PHONE_HOME_CITY_AND_NUMBER: 205 case PHONE_HOME_WHOLE_NUMBER: 206 collapsed_set.insert(PHONE_HOME_WHOLE_NUMBER); 207 break; 208 209 default: 210 collapsed_set.insert(*it); 211 } 212 } 213 std::swap(*type_set, collapsed_set); 214 } 215 216 class FindByPhone { 217 public: 218 FindByPhone(const base::string16& phone, 219 const std::string& country_code, 220 const std::string& app_locale) 221 : phone_(phone), 222 country_code_(country_code), 223 app_locale_(app_locale) {} 224 225 bool operator()(const base::string16& phone) { 226 return i18n::PhoneNumbersMatch(phone, phone_, country_code_, app_locale_); 227 } 228 229 private: 230 base::string16 phone_; 231 std::string country_code_; 232 std::string app_locale_; 233 }; 234 235 // Functor used to check for case-insensitive equality of two strings. 236 struct CaseInsensitiveStringEquals { 237 public: 238 CaseInsensitiveStringEquals(const base::string16& other) 239 : other_(other) {} 240 241 bool operator()(const base::string16& x) const { 242 return x.size() == other_.size() && 243 base::StringToLowerASCII(x) == base::StringToLowerASCII(other_); 244 } 245 246 private: 247 const base::string16& other_; 248 }; 249 250 } // namespace 251 252 AutofillProfile::AutofillProfile(const std::string& guid, 253 const std::string& origin) 254 : AutofillDataModel(guid, origin), 255 name_(1), 256 email_(1), 257 phone_number_(1, PhoneNumber(this)) { 258 } 259 260 AutofillProfile::AutofillProfile() 261 : AutofillDataModel(base::GenerateGUID(), std::string()), 262 name_(1), 263 email_(1), 264 phone_number_(1, PhoneNumber(this)) { 265 } 266 267 AutofillProfile::AutofillProfile(const AutofillProfile& profile) 268 : AutofillDataModel(std::string(), std::string()) { 269 operator=(profile); 270 } 271 272 AutofillProfile::~AutofillProfile() { 273 } 274 275 AutofillProfile& AutofillProfile::operator=(const AutofillProfile& profile) { 276 if (this == &profile) 277 return *this; 278 279 set_guid(profile.guid()); 280 set_origin(profile.origin()); 281 282 name_ = profile.name_; 283 email_ = profile.email_; 284 company_ = profile.company_; 285 phone_number_ = profile.phone_number_; 286 287 for (size_t i = 0; i < phone_number_.size(); ++i) 288 phone_number_[i].set_profile(this); 289 290 address_ = profile.address_; 291 set_language_code(profile.language_code()); 292 293 return *this; 294 } 295 296 void AutofillProfile::GetMatchingTypes( 297 const base::string16& text, 298 const std::string& app_locale, 299 ServerFieldTypeSet* matching_types) const { 300 FormGroupList info = FormGroups(); 301 for (FormGroupList::const_iterator it = info.begin(); it != info.end(); ++it) 302 (*it)->GetMatchingTypes(text, app_locale, matching_types); 303 } 304 305 base::string16 AutofillProfile::GetRawInfo(ServerFieldType type) const { 306 const FormGroup* form_group = FormGroupForType(AutofillType(type)); 307 if (!form_group) 308 return base::string16(); 309 310 return form_group->GetRawInfo(type); 311 } 312 313 void AutofillProfile::SetRawInfo(ServerFieldType type, 314 const base::string16& value) { 315 FormGroup* form_group = MutableFormGroupForType(AutofillType(type)); 316 if (form_group) 317 form_group->SetRawInfo(type, value); 318 } 319 320 base::string16 AutofillProfile::GetInfo(const AutofillType& type, 321 const std::string& app_locale) const { 322 if (type.html_type() == HTML_TYPE_FULL_ADDRESS) { 323 scoped_ptr<AddressData> address_data = 324 i18n::CreateAddressDataFromAutofillProfile(*this, app_locale); 325 if (!addressinput::HasAllRequiredFields(*address_data)) 326 return base::string16(); 327 328 std::vector<std::string> lines; 329 ::i18n::addressinput::GetFormattedNationalAddress(*address_data, &lines); 330 return base::UTF8ToUTF16(JoinString(lines, '\n')); 331 } 332 333 const FormGroup* form_group = FormGroupForType(type); 334 if (!form_group) 335 return base::string16(); 336 337 return form_group->GetInfo(type, app_locale); 338 } 339 340 bool AutofillProfile::SetInfo(const AutofillType& type, 341 const base::string16& value, 342 const std::string& app_locale) { 343 FormGroup* form_group = MutableFormGroupForType(type); 344 if (!form_group) 345 return false; 346 347 base::string16 trimmed_value; 348 base::TrimWhitespace(value, base::TRIM_ALL, &trimmed_value); 349 return form_group->SetInfo(type, trimmed_value, app_locale); 350 } 351 352 base::string16 AutofillProfile::GetInfoForVariant( 353 const AutofillType& type, 354 size_t variant, 355 const std::string& app_locale) const { 356 std::vector<base::string16> values; 357 GetMultiInfo(type, app_locale, &values); 358 359 if (variant >= values.size()) { 360 // If the variant is unavailable, bail. This case is reachable, for 361 // example if Sync updates a profile during the filling process. 362 return base::string16(); 363 } 364 365 return values[variant]; 366 } 367 368 void AutofillProfile::SetRawMultiInfo( 369 ServerFieldType type, 370 const std::vector<base::string16>& values) { 371 switch (AutofillType(type).group()) { 372 case NAME: 373 case NAME_BILLING: 374 CopyRawValuesToItems(type, values, NameInfo(), &name_); 375 break; 376 377 case EMAIL: 378 CopyRawValuesToItems(type, values, EmailInfo(), &email_); 379 break; 380 381 case PHONE_HOME: 382 case PHONE_BILLING: 383 CopyRawValuesToItems(type, values, PhoneNumber(this), &phone_number_); 384 break; 385 386 default: 387 if (values.size() == 1U) { 388 SetRawInfo(type, values[0]); 389 } else if (values.empty()) { 390 SetRawInfo(type, base::string16()); 391 } else { 392 // Shouldn't attempt to set multiple values on single-valued field. 393 NOTREACHED(); 394 } 395 break; 396 } 397 } 398 399 void AutofillProfile::GetRawMultiInfo( 400 ServerFieldType type, 401 std::vector<base::string16>* values) const { 402 GetMultiInfoImpl(AutofillType(type), std::string(), values); 403 } 404 405 void AutofillProfile::SetMultiInfo(const AutofillType& type, 406 const std::vector<base::string16>& values, 407 const std::string& app_locale) { 408 switch (AutofillType(type).group()) { 409 case NAME: 410 case NAME_BILLING: 411 CopyValuesToItems(type, values, NameInfo(), app_locale, &name_); 412 break; 413 414 case EMAIL: 415 CopyValuesToItems(type, values, EmailInfo(), app_locale, &email_); 416 break; 417 418 case PHONE_HOME: 419 case PHONE_BILLING: 420 CopyValuesToItems( 421 type, values, PhoneNumber(this), app_locale, &phone_number_); 422 break; 423 424 default: 425 if (values.size() == 1U) { 426 SetInfo(type, values[0], app_locale); 427 } else if (values.empty()) { 428 SetInfo(type, base::string16(), app_locale); 429 } else { 430 // Shouldn't attempt to set multiple values on single-valued field. 431 NOTREACHED(); 432 } 433 break; 434 } 435 } 436 437 void AutofillProfile::GetMultiInfo(const AutofillType& type, 438 const std::string& app_locale, 439 std::vector<base::string16>* values) const { 440 GetMultiInfoImpl(type, app_locale, values); 441 } 442 443 bool AutofillProfile::IsEmpty(const std::string& app_locale) const { 444 ServerFieldTypeSet types; 445 GetNonEmptyTypes(app_locale, &types); 446 return types.empty(); 447 } 448 449 bool AutofillProfile::IsPresentButInvalid(ServerFieldType type) const { 450 std::string country = UTF16ToUTF8(GetRawInfo(ADDRESS_HOME_COUNTRY)); 451 base::string16 data = GetRawInfo(type); 452 if (data.empty()) 453 return false; 454 455 switch (type) { 456 case ADDRESS_HOME_STATE: 457 return country == "US" && !autofill::IsValidState(data); 458 459 case ADDRESS_HOME_ZIP: 460 return country == "US" && !autofill::IsValidZip(data); 461 462 case PHONE_HOME_WHOLE_NUMBER: 463 return !i18n::PhoneObject(data, country).IsValidNumber(); 464 465 case EMAIL_ADDRESS: 466 return !autofill::IsValidEmailAddress(data); 467 468 default: 469 NOTREACHED(); 470 return false; 471 } 472 } 473 474 int AutofillProfile::Compare(const AutofillProfile& profile) const { 475 const ServerFieldType single_value_types[] = { 476 COMPANY_NAME, 477 ADDRESS_HOME_STREET_ADDRESS, 478 ADDRESS_HOME_DEPENDENT_LOCALITY, 479 ADDRESS_HOME_CITY, 480 ADDRESS_HOME_STATE, 481 ADDRESS_HOME_ZIP, 482 ADDRESS_HOME_SORTING_CODE, 483 ADDRESS_HOME_COUNTRY, 484 }; 485 486 for (size_t i = 0; i < arraysize(single_value_types); ++i) { 487 int comparison = GetRawInfo(single_value_types[i]).compare( 488 profile.GetRawInfo(single_value_types[i])); 489 if (comparison != 0) 490 return comparison; 491 } 492 493 const ServerFieldType multi_value_types[] = { NAME_FULL, 494 NAME_FIRST, 495 NAME_MIDDLE, 496 NAME_LAST, 497 EMAIL_ADDRESS, 498 PHONE_HOME_WHOLE_NUMBER }; 499 500 for (size_t i = 0; i < arraysize(multi_value_types); ++i) { 501 std::vector<base::string16> values_a; 502 std::vector<base::string16> values_b; 503 GetRawMultiInfo(multi_value_types[i], &values_a); 504 profile.GetRawMultiInfo(multi_value_types[i], &values_b); 505 if (values_a.size() < values_b.size()) 506 return -1; 507 if (values_a.size() > values_b.size()) 508 return 1; 509 for (size_t j = 0; j < values_a.size(); ++j) { 510 int comparison = values_a[j].compare(values_b[j]); 511 if (comparison != 0) 512 return comparison; 513 } 514 } 515 516 return 0; 517 } 518 519 bool AutofillProfile::EqualsSansOrigin(const AutofillProfile& profile) const { 520 return guid() == profile.guid() && 521 language_code() == profile.language_code() && 522 Compare(profile) == 0; 523 } 524 525 bool AutofillProfile::EqualsSansGuid(const AutofillProfile& profile) const { 526 return origin() == profile.origin() && 527 language_code() == profile.language_code() && 528 Compare(profile) == 0; 529 } 530 531 bool AutofillProfile::operator==(const AutofillProfile& profile) const { 532 return guid() == profile.guid() && EqualsSansGuid(profile); 533 } 534 535 bool AutofillProfile::operator!=(const AutofillProfile& profile) const { 536 return !operator==(profile); 537 } 538 539 const base::string16 AutofillProfile::PrimaryValue() const { 540 return GetRawInfo(ADDRESS_HOME_LINE1) + GetRawInfo(ADDRESS_HOME_CITY); 541 } 542 543 bool AutofillProfile::IsSubsetOf(const AutofillProfile& profile, 544 const std::string& app_locale) const { 545 ServerFieldTypeSet types; 546 GetNonEmptyTypes(app_locale, &types); 547 548 for (ServerFieldTypeSet::const_iterator it = types.begin(); it != types.end(); 549 ++it) { 550 if (*it == NAME_FULL || *it == ADDRESS_HOME_STREET_ADDRESS) { 551 // Ignore the compound "full name" field type. We are only interested in 552 // comparing the constituent parts. For example, if |this| has a middle 553 // name saved, but |profile| lacks one, |profile| could still be a subset 554 // of |this|. Likewise, ignore the compound "street address" type, as we 555 // are only interested in matching line-by-line. 556 continue; 557 } else if (AutofillType(*it).group() == PHONE_HOME) { 558 // Phone numbers should be canonicalized prior to being compared. 559 if (*it != PHONE_HOME_WHOLE_NUMBER) { 560 continue; 561 } else if (!i18n::PhoneNumbersMatch( 562 GetRawInfo(*it), 563 profile.GetRawInfo(*it), 564 base::UTF16ToASCII(GetRawInfo(ADDRESS_HOME_COUNTRY)), 565 app_locale)) { 566 return false; 567 } 568 } else if (base::StringToLowerASCII(GetRawInfo(*it)) != 569 base::StringToLowerASCII(profile.GetRawInfo(*it))) { 570 return false; 571 } 572 } 573 574 return true; 575 } 576 577 void AutofillProfile::OverwriteOrAppendNames( 578 const std::vector<NameInfo>& names, 579 const std::string& app_locale) { 580 std::vector<NameInfo> results(name_); 581 for (std::vector<NameInfo>::const_iterator it = names.begin(); 582 it != names.end(); 583 ++it) { 584 NameInfo imported_name = *it; 585 bool should_append_imported_name = true; 586 587 for (size_t index = 0; index < name_.size(); ++index) { 588 NameInfo current_name = name_[index]; 589 if (current_name.ParsedNamesAreEqual(imported_name)) { 590 if (current_name.GetRawInfo(NAME_FULL).empty()) { 591 current_name.SetRawInfo(NAME_FULL, 592 imported_name.GetRawInfo(NAME_FULL)); 593 } 594 595 should_append_imported_name = false; 596 break; 597 } 598 599 AutofillType type = AutofillType(NAME_FULL); 600 base::string16 full_name = current_name.GetInfo(type, app_locale); 601 if (base::StringToLowerASCII(full_name) == 602 base::StringToLowerASCII(imported_name.GetInfo(type, app_locale))) { 603 // The imported name has the same full name string as one of the 604 // existing names for this profile. Because full names are 605 // _heuristically_ parsed into {first, middle, last} name components, 606 // it's possible that either the existing name or the imported name 607 // was misparsed. Prefer to keep the name whose {first, middle, 608 // last} components do not match those computed by the heuristic 609 // parse, as this more likely represents the correct, user-input parse 610 // of the name. 611 NameInfo heuristically_parsed_name; 612 heuristically_parsed_name.SetInfo(type, full_name, app_locale); 613 if (imported_name.ParsedNamesAreEqual(heuristically_parsed_name)) { 614 should_append_imported_name = false; 615 break; 616 } 617 618 if (current_name.ParsedNamesAreEqual(heuristically_parsed_name)) { 619 results[index] = imported_name; 620 should_append_imported_name = false; 621 break; 622 } 623 } 624 } 625 626 // Append unique names to the list. 627 if (should_append_imported_name) 628 results.push_back(imported_name); 629 } 630 631 name_.swap(results); 632 } 633 634 void AutofillProfile::OverwriteWithOrAddTo(const AutofillProfile& profile, 635 const std::string& app_locale) { 636 // Verified profiles should never be overwritten with unverified data. 637 DCHECK(!IsVerified() || profile.IsVerified()); 638 set_origin(profile.origin()); 639 set_language_code(profile.language_code()); 640 641 ServerFieldTypeSet field_types; 642 profile.GetNonEmptyTypes(app_locale, &field_types); 643 644 // Only transfer "full" types (e.g. full name) and not fragments (e.g. 645 // first name, last name). 646 CollapseCompoundFieldTypes(&field_types); 647 648 // TODO(isherman): Revisit this decision in the context of i18n and storing 649 // full addresses rather than storing 1-to-2 lines of an address. 650 // For addresses, do the opposite: transfer individual address lines, rather 651 // than full addresses. 652 field_types.erase(ADDRESS_HOME_STREET_ADDRESS); 653 654 for (ServerFieldTypeSet::const_iterator iter = field_types.begin(); 655 iter != field_types.end(); ++iter) { 656 FieldTypeGroup group = AutofillType(*iter).group(); 657 // Special case names. 658 if (group == NAME) { 659 OverwriteOrAppendNames(profile.name_, app_locale); 660 continue; 661 } 662 663 // Single value field --- overwrite. 664 if (!AutofillProfile::SupportsMultiValue(*iter)) { 665 base::string16 new_value = profile.GetRawInfo(*iter); 666 if (base::StringToLowerASCII(GetRawInfo(*iter)) != 667 base::StringToLowerASCII(new_value)) { 668 SetRawInfo(*iter, new_value); 669 } 670 continue; 671 } 672 673 // Multi value field --- overwrite/append. 674 std::vector<base::string16> new_values; 675 profile.GetRawMultiInfo(*iter, &new_values); 676 std::vector<base::string16> existing_values; 677 GetRawMultiInfo(*iter, &existing_values); 678 679 // GetMultiInfo always returns at least one element, even if the profile 680 // has no data stored for this field type. 681 if (existing_values.size() == 1 && existing_values.front().empty()) 682 existing_values.clear(); 683 684 for (std::vector<base::string16>::iterator value_iter = 685 new_values.begin(); 686 value_iter != new_values.end(); ++value_iter) { 687 // Don't add duplicates. Most types get case insensitive matching. 688 std::vector<base::string16>::const_iterator existing_iter; 689 690 if (group == PHONE_HOME) { 691 // Phones allow "fuzzy" matching, so "1-800-FLOWERS", "18003569377", 692 // "(800)356-9377" and "356-9377" are considered the same. 693 std::string country_code = 694 base::UTF16ToASCII(GetRawInfo(ADDRESS_HOME_COUNTRY)); 695 existing_iter = 696 std::find_if(existing_values.begin(), existing_values.end(), 697 FindByPhone(*value_iter, country_code, app_locale)); 698 } else { 699 existing_iter = 700 std::find_if(existing_values.begin(), existing_values.end(), 701 CaseInsensitiveStringEquals(*value_iter)); 702 } 703 704 if (existing_iter == existing_values.end()) 705 existing_values.insert(existing_values.end(), *value_iter); 706 } 707 708 SetRawMultiInfo(*iter, existing_values); 709 } 710 } 711 712 // static 713 bool AutofillProfile::SupportsMultiValue(ServerFieldType type) { 714 FieldTypeGroup group = AutofillType(type).group(); 715 return group == NAME || 716 group == NAME_BILLING || 717 group == EMAIL || 718 group == PHONE_HOME || 719 group == PHONE_BILLING; 720 } 721 722 // static 723 void AutofillProfile::CreateDifferentiatingLabels( 724 const std::vector<AutofillProfile*>& profiles, 725 const std::string& app_locale, 726 std::vector<base::string16>* labels) { 727 const size_t kMinimalFieldsShown = 2; 728 CreateInferredLabels(profiles, NULL, UNKNOWN_TYPE, kMinimalFieldsShown, 729 app_locale, labels); 730 DCHECK_EQ(profiles.size(), labels->size()); 731 } 732 733 // static 734 void AutofillProfile::CreateInferredLabels( 735 const std::vector<AutofillProfile*>& profiles, 736 const std::vector<ServerFieldType>* suggested_fields, 737 ServerFieldType excluded_field, 738 size_t minimal_fields_shown, 739 const std::string& app_locale, 740 std::vector<base::string16>* labels) { 741 std::vector<ServerFieldType> fields_to_use; 742 GetFieldsForDistinguishingProfiles(suggested_fields, excluded_field, 743 &fields_to_use); 744 745 // Construct the default label for each profile. Also construct a map that 746 // associates each label with the profiles that have this label. This map is 747 // then used to detect which labels need further differentiating fields. 748 std::map<base::string16, std::list<size_t> > labels_to_profiles; 749 for (size_t i = 0; i < profiles.size(); ++i) { 750 base::string16 label = 751 profiles[i]->ConstructInferredLabel(fields_to_use, 752 minimal_fields_shown, 753 app_locale); 754 labels_to_profiles[label].push_back(i); 755 } 756 757 labels->resize(profiles.size()); 758 for (std::map<base::string16, std::list<size_t> >::const_iterator it = 759 labels_to_profiles.begin(); 760 it != labels_to_profiles.end(); ++it) { 761 if (it->second.size() == 1) { 762 // This label is unique, so use it without any further ado. 763 base::string16 label = it->first; 764 size_t profile_index = it->second.front(); 765 (*labels)[profile_index] = label; 766 } else { 767 // We have more than one profile with the same label, so add 768 // differentiating fields. 769 CreateInferredLabelsHelper(profiles, it->second, fields_to_use, 770 minimal_fields_shown, app_locale, labels); 771 } 772 } 773 } 774 775 void AutofillProfile::GetSupportedTypes( 776 ServerFieldTypeSet* supported_types) const { 777 FormGroupList info = FormGroups(); 778 for (FormGroupList::const_iterator it = info.begin(); it != info.end(); ++it) 779 (*it)->GetSupportedTypes(supported_types); 780 } 781 782 void AutofillProfile::GetMultiInfoImpl( 783 const AutofillType& type, 784 const std::string& app_locale, 785 std::vector<base::string16>* values) const { 786 switch (type.group()) { 787 case NAME: 788 case NAME_BILLING: 789 CopyItemsToValues(type, name_, app_locale, values); 790 break; 791 case EMAIL: 792 CopyItemsToValues(type, email_, app_locale, values); 793 break; 794 case PHONE_HOME: 795 case PHONE_BILLING: 796 CopyItemsToValues(type, phone_number_, app_locale, values); 797 break; 798 default: 799 values->resize(1); 800 (*values)[0] = GetFormGroupInfo(*this, type, app_locale); 801 } 802 } 803 804 base::string16 AutofillProfile::ConstructInferredLabel( 805 const std::vector<ServerFieldType>& included_fields, 806 size_t num_fields_to_use, 807 const std::string& app_locale) const { 808 base::string16 separator = 809 l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_SUMMARY_SEPARATOR); 810 811 AutofillType region_code_type(HTML_TYPE_COUNTRY_CODE, HTML_MODE_NONE); 812 const base::string16& profile_region_code = 813 GetInfo(region_code_type, app_locale); 814 std::string address_region_code = UTF16ToUTF8(profile_region_code); 815 816 // A copy of |this| pruned down to contain only data for the address fields in 817 // |included_fields|. 818 AutofillProfile trimmed_profile(guid(), origin()); 819 trimmed_profile.SetInfo(region_code_type, profile_region_code, app_locale); 820 trimmed_profile.set_language_code(language_code()); 821 822 std::vector<ServerFieldType> remaining_fields; 823 for (std::vector<ServerFieldType>::const_iterator it = 824 included_fields.begin(); 825 it != included_fields.end() && num_fields_to_use > 0; 826 ++it) { 827 AddressField address_field; 828 if (!i18n::FieldForType(*it, &address_field) || 829 !::i18n::addressinput::IsFieldUsed( 830 address_field, address_region_code) || 831 address_field == ::i18n::addressinput::COUNTRY) { 832 remaining_fields.push_back(*it); 833 continue; 834 } 835 836 AutofillType autofill_type(*it); 837 const base::string16& field_value = GetInfo(autofill_type, app_locale); 838 if (field_value.empty()) 839 continue; 840 841 trimmed_profile.SetInfo(autofill_type, field_value, app_locale); 842 --num_fields_to_use; 843 } 844 845 scoped_ptr<AddressData> address_data = 846 i18n::CreateAddressDataFromAutofillProfile(trimmed_profile, app_locale); 847 std::string address_line; 848 ::i18n::addressinput::GetFormattedNationalAddressLine( 849 *address_data, &address_line); 850 base::string16 label = base::UTF8ToUTF16(address_line); 851 852 for (std::vector<ServerFieldType>::const_iterator it = 853 remaining_fields.begin(); 854 it != remaining_fields.end() && num_fields_to_use > 0; 855 ++it) { 856 const base::string16& field_value = GetInfo(AutofillType(*it), app_locale); 857 if (field_value.empty()) 858 continue; 859 860 if (!label.empty()) 861 label.append(separator); 862 863 label.append(field_value); 864 --num_fields_to_use; 865 } 866 867 // If country code is missing, libaddressinput won't be used to format the 868 // address. In this case the suggestion might include a multi-line street 869 // address which needs to be flattened. 870 base::ReplaceChars(label, base::ASCIIToUTF16("\n"), separator, &label); 871 872 return label; 873 } 874 875 // static 876 void AutofillProfile::CreateInferredLabelsHelper( 877 const std::vector<AutofillProfile*>& profiles, 878 const std::list<size_t>& indices, 879 const std::vector<ServerFieldType>& fields, 880 size_t num_fields_to_include, 881 const std::string& app_locale, 882 std::vector<base::string16>* labels) { 883 // For efficiency, we first construct a map of fields to their text values and 884 // each value's frequency. 885 std::map<ServerFieldType, 886 std::map<base::string16, size_t> > field_text_frequencies_by_field; 887 for (std::vector<ServerFieldType>::const_iterator field = fields.begin(); 888 field != fields.end(); ++field) { 889 std::map<base::string16, size_t>& field_text_frequencies = 890 field_text_frequencies_by_field[*field]; 891 892 for (std::list<size_t>::const_iterator it = indices.begin(); 893 it != indices.end(); ++it) { 894 const AutofillProfile* profile = profiles[*it]; 895 base::string16 field_text = 896 profile->GetInfo(AutofillType(*field), app_locale); 897 898 // If this label is not already in the map, add it with frequency 0. 899 if (!field_text_frequencies.count(field_text)) 900 field_text_frequencies[field_text] = 0; 901 902 // Now, increment the frequency for this label. 903 ++field_text_frequencies[field_text]; 904 } 905 } 906 907 // Now comes the meat of the algorithm. For each profile, we scan the list of 908 // fields to use, looking for two things: 909 // 1. A (non-empty) field that differentiates the profile from all others 910 // 2. At least |num_fields_to_include| non-empty fields 911 // Before we've satisfied condition (2), we include all fields, even ones that 912 // are identical across all the profiles. Once we've satisfied condition (2), 913 // we only include fields that that have at last two distinct values. 914 for (std::list<size_t>::const_iterator it = indices.begin(); 915 it != indices.end(); ++it) { 916 const AutofillProfile* profile = profiles[*it]; 917 918 std::vector<ServerFieldType> label_fields; 919 bool found_differentiating_field = false; 920 for (std::vector<ServerFieldType>::const_iterator field = fields.begin(); 921 field != fields.end(); ++field) { 922 // Skip over empty fields. 923 base::string16 field_text = 924 profile->GetInfo(AutofillType(*field), app_locale); 925 if (field_text.empty()) 926 continue; 927 928 std::map<base::string16, size_t>& field_text_frequencies = 929 field_text_frequencies_by_field[*field]; 930 found_differentiating_field |= 931 !field_text_frequencies.count(base::string16()) && 932 (field_text_frequencies[field_text] == 1); 933 934 // Once we've found enough non-empty fields, skip over any remaining 935 // fields that are identical across all the profiles. 936 if (label_fields.size() >= num_fields_to_include && 937 (field_text_frequencies.size() == 1)) 938 continue; 939 940 label_fields.push_back(*field); 941 942 // If we've (1) found a differentiating field and (2) found at least 943 // |num_fields_to_include| non-empty fields, we're done! 944 if (found_differentiating_field && 945 label_fields.size() >= num_fields_to_include) 946 break; 947 } 948 949 (*labels)[*it] = profile->ConstructInferredLabel( 950 label_fields, label_fields.size(), app_locale); 951 } 952 } 953 954 AutofillProfile::FormGroupList AutofillProfile::FormGroups() const { 955 FormGroupList v(5); 956 v[0] = &name_[0]; 957 v[1] = &email_[0]; 958 v[2] = &company_; 959 v[3] = &phone_number_[0]; 960 v[4] = &address_; 961 return v; 962 } 963 964 const FormGroup* AutofillProfile::FormGroupForType( 965 const AutofillType& type) const { 966 return const_cast<AutofillProfile*>(this)->MutableFormGroupForType(type); 967 } 968 969 FormGroup* AutofillProfile::MutableFormGroupForType(const AutofillType& type) { 970 switch (type.group()) { 971 case NAME: 972 case NAME_BILLING: 973 return &name_[0]; 974 975 case EMAIL: 976 return &email_[0]; 977 978 case COMPANY: 979 return &company_; 980 981 case PHONE_HOME: 982 case PHONE_BILLING: 983 return &phone_number_[0]; 984 985 case ADDRESS_HOME: 986 case ADDRESS_BILLING: 987 return &address_; 988 989 case NO_GROUP: 990 case CREDIT_CARD: 991 case PASSWORD_FIELD: 992 case TRANSACTION: 993 return NULL; 994 } 995 996 NOTREACHED(); 997 return NULL; 998 } 999 1000 // So we can compare AutofillProfiles with EXPECT_EQ(). 1001 std::ostream& operator<<(std::ostream& os, const AutofillProfile& profile) { 1002 return os 1003 << profile.guid() 1004 << " " 1005 << profile.origin() 1006 << " " 1007 << UTF16ToUTF8(MultiString(profile, NAME_FIRST)) 1008 << " " 1009 << UTF16ToUTF8(MultiString(profile, NAME_MIDDLE)) 1010 << " " 1011 << UTF16ToUTF8(MultiString(profile, NAME_LAST)) 1012 << " " 1013 << UTF16ToUTF8(MultiString(profile, EMAIL_ADDRESS)) 1014 << " " 1015 << UTF16ToUTF8(profile.GetRawInfo(COMPANY_NAME)) 1016 << " " 1017 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE1)) 1018 << " " 1019 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE2)) 1020 << " " 1021 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY)) 1022 << " " 1023 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_CITY)) 1024 << " " 1025 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_STATE)) 1026 << " " 1027 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_ZIP)) 1028 << " " 1029 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE)) 1030 << " " 1031 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY)) 1032 << " " 1033 << profile.language_code() 1034 << " " 1035 << UTF16ToUTF8(MultiString(profile, PHONE_HOME_WHOLE_NUMBER)); 1036 } 1037 1038 } // namespace autofill 1039