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/autofill_country.h" 20 #include "components/autofill/core/browser/autofill_field.h" 21 #include "components/autofill/core/browser/autofill_type.h" 22 #include "components/autofill/core/browser/contact_info.h" 23 #include "components/autofill/core/browser/phone_number.h" 24 #include "components/autofill/core/browser/phone_number_i18n.h" 25 #include "components/autofill/core/browser/validation.h" 26 #include "components/autofill/core/common/form_field_data.h" 27 #include "grit/component_strings.h" 28 #include "ui/base/l10n/l10n_util.h" 29 30 namespace autofill { 31 namespace { 32 33 // Like |AutofillType::GetStorableType()|, but also returns |NAME_FULL| for 34 // first, middle, and last name field types. 35 ServerFieldType GetStorableTypeCollapsingNames(ServerFieldType type) { 36 ServerFieldType storable_type = AutofillType(type).GetStorableType(); 37 if (AutofillType(storable_type).group() == NAME) 38 return NAME_FULL; 39 40 return storable_type; 41 } 42 43 // Fills |distinguishing_fields| with a list of fields to use when creating 44 // labels that can help to distinguish between two profiles. Draws fields from 45 // |suggested_fields| if it is non-NULL; otherwise returns a default list. 46 // If |suggested_fields| is non-NULL, does not include |excluded_field| in the 47 // list. Otherwise, |excluded_field| is ignored, and should be set to 48 // |UNKNOWN_TYPE| by convention. The resulting list of fields is sorted in 49 // decreasing order of importance. 50 void GetFieldsForDistinguishingProfiles( 51 const std::vector<ServerFieldType>* suggested_fields, 52 ServerFieldType excluded_field, 53 std::vector<ServerFieldType>* distinguishing_fields) { 54 static const ServerFieldType kDefaultDistinguishingFields[] = { 55 NAME_FULL, 56 ADDRESS_HOME_LINE1, 57 ADDRESS_HOME_LINE2, 58 ADDRESS_HOME_CITY, 59 ADDRESS_HOME_STATE, 60 ADDRESS_HOME_ZIP, 61 ADDRESS_HOME_COUNTRY, 62 EMAIL_ADDRESS, 63 PHONE_HOME_WHOLE_NUMBER, 64 COMPANY_NAME, 65 }; 66 67 if (!suggested_fields) { 68 DCHECK_EQ(excluded_field, UNKNOWN_TYPE); 69 distinguishing_fields->assign( 70 kDefaultDistinguishingFields, 71 kDefaultDistinguishingFields + arraysize(kDefaultDistinguishingFields)); 72 return; 73 } 74 75 // Keep track of which fields we've seen so that we avoid duplicate entries. 76 // Always ignore fields of unknown type and the excluded field. 77 std::set<ServerFieldType> seen_fields; 78 seen_fields.insert(UNKNOWN_TYPE); 79 seen_fields.insert(GetStorableTypeCollapsingNames(excluded_field)); 80 81 distinguishing_fields->clear(); 82 for (std::vector<ServerFieldType>::const_iterator it = 83 suggested_fields->begin(); 84 it != suggested_fields->end(); ++it) { 85 ServerFieldType suggested_type = GetStorableTypeCollapsingNames(*it); 86 if (seen_fields.insert(suggested_type).second) 87 distinguishing_fields->push_back(suggested_type); 88 } 89 90 // Special case: If the excluded field is a partial name (e.g. first name) and 91 // the suggested fields include other name fields, include |NAME_FULL| in the 92 // list of distinguishing fields as a last-ditch fallback. This allows us to 93 // distinguish between profiles that are identical except for the name. 94 if (excluded_field != NAME_FULL && 95 GetStorableTypeCollapsingNames(excluded_field) == NAME_FULL) { 96 for (std::vector<ServerFieldType>::const_iterator it = 97 suggested_fields->begin(); 98 it != suggested_fields->end(); ++it) { 99 if (*it != excluded_field && 100 GetStorableTypeCollapsingNames(*it) == NAME_FULL) { 101 distinguishing_fields->push_back(NAME_FULL); 102 break; 103 } 104 } 105 } 106 } 107 108 // A helper function for string streaming. Concatenates multi-valued entries 109 // stored for a given |type| into a single string. This string is returned. 110 const base::string16 MultiString(const AutofillProfile& p, 111 ServerFieldType type) { 112 std::vector<base::string16> values; 113 p.GetRawMultiInfo(type, &values); 114 base::string16 accumulate; 115 for (size_t i = 0; i < values.size(); ++i) { 116 if (i > 0) 117 accumulate += ASCIIToUTF16(" "); 118 accumulate += values[i]; 119 } 120 return accumulate; 121 } 122 123 base::string16 GetFormGroupInfo(const FormGroup& form_group, 124 const AutofillType& type, 125 const std::string& app_locale) { 126 return app_locale.empty() ? 127 form_group.GetRawInfo(type.GetStorableType()) : 128 form_group.GetInfo(type, app_locale); 129 } 130 131 template <class T> 132 void CopyValuesToItems(ServerFieldType type, 133 const std::vector<base::string16>& values, 134 std::vector<T>* form_group_items, 135 const T& prototype) { 136 form_group_items->resize(values.size(), prototype); 137 for (size_t i = 0; i < form_group_items->size(); ++i) { 138 (*form_group_items)[i].SetRawInfo(type, 139 CollapseWhitespace(values[i], false)); 140 } 141 // Must have at least one (possibly empty) element. 142 if (form_group_items->empty()) 143 form_group_items->resize(1, prototype); 144 } 145 146 template <class T> 147 void CopyItemsToValues(const AutofillType& type, 148 const std::vector<T>& form_group_items, 149 const std::string& app_locale, 150 std::vector<base::string16>* values) { 151 values->resize(form_group_items.size()); 152 for (size_t i = 0; i < values->size(); ++i) { 153 (*values)[i] = GetFormGroupInfo(form_group_items[i], type, app_locale); 154 } 155 } 156 157 // Collapse compound field types to their "full" type. I.e. First name 158 // collapses to full name, area code collapses to full phone, etc. 159 void CollapseCompoundFieldTypes(ServerFieldTypeSet* type_set) { 160 ServerFieldTypeSet collapsed_set; 161 for (ServerFieldTypeSet::iterator it = type_set->begin(); 162 it != type_set->end(); ++it) { 163 switch (*it) { 164 case NAME_FIRST: 165 case NAME_MIDDLE: 166 case NAME_LAST: 167 case NAME_MIDDLE_INITIAL: 168 case NAME_FULL: 169 case NAME_SUFFIX: 170 collapsed_set.insert(NAME_FULL); 171 break; 172 173 case PHONE_HOME_NUMBER: 174 case PHONE_HOME_CITY_CODE: 175 case PHONE_HOME_COUNTRY_CODE: 176 case PHONE_HOME_CITY_AND_NUMBER: 177 case PHONE_HOME_WHOLE_NUMBER: 178 collapsed_set.insert(PHONE_HOME_WHOLE_NUMBER); 179 break; 180 181 default: 182 collapsed_set.insert(*it); 183 } 184 } 185 std::swap(*type_set, collapsed_set); 186 } 187 188 class FindByPhone { 189 public: 190 FindByPhone(const base::string16& phone, 191 const std::string& country_code, 192 const std::string& app_locale) 193 : phone_(phone), 194 country_code_(country_code), 195 app_locale_(app_locale) { 196 } 197 198 bool operator()(const base::string16& phone) { 199 return i18n::PhoneNumbersMatch(phone, phone_, country_code_, app_locale_); 200 } 201 202 bool operator()(const base::string16* phone) { 203 return i18n::PhoneNumbersMatch(*phone, phone_, country_code_, app_locale_); 204 } 205 206 private: 207 base::string16 phone_; 208 std::string country_code_; 209 std::string app_locale_; 210 }; 211 212 // Functor used to check for case-insensitive equality of two strings. 213 struct CaseInsensitiveStringEquals 214 : public std::binary_function<base::string16, base::string16, bool> 215 { 216 bool operator()(const base::string16& x, const base::string16& y) const { 217 return 218 x.size() == y.size() && StringToLowerASCII(x) == StringToLowerASCII(y); 219 } 220 }; 221 222 } // namespace 223 224 AutofillProfile::AutofillProfile(const std::string& guid, 225 const std::string& origin) 226 : AutofillDataModel(guid, origin), 227 name_(1), 228 email_(1), 229 phone_number_(1, PhoneNumber(this)) { 230 } 231 232 AutofillProfile::AutofillProfile() 233 : AutofillDataModel(base::GenerateGUID(), std::string()), 234 name_(1), 235 email_(1), 236 phone_number_(1, PhoneNumber(this)) { 237 } 238 239 AutofillProfile::AutofillProfile(const AutofillProfile& profile) 240 : AutofillDataModel(std::string(), std::string()) { 241 operator=(profile); 242 } 243 244 AutofillProfile::~AutofillProfile() { 245 } 246 247 AutofillProfile& AutofillProfile::operator=(const AutofillProfile& profile) { 248 if (this == &profile) 249 return *this; 250 251 set_guid(profile.guid()); 252 set_origin(profile.origin()); 253 254 label_ = profile.label_; 255 name_ = profile.name_; 256 email_ = profile.email_; 257 company_ = profile.company_; 258 phone_number_ = profile.phone_number_; 259 260 for (size_t i = 0; i < phone_number_.size(); ++i) 261 phone_number_[i].set_profile(this); 262 263 address_ = profile.address_; 264 265 return *this; 266 } 267 268 void AutofillProfile::GetMatchingTypes( 269 const base::string16& text, 270 const std::string& app_locale, 271 ServerFieldTypeSet* matching_types) const { 272 FormGroupList info = FormGroups(); 273 for (FormGroupList::const_iterator it = info.begin(); it != info.end(); ++it) 274 (*it)->GetMatchingTypes(text, app_locale, matching_types); 275 } 276 277 base::string16 AutofillProfile::GetRawInfo(ServerFieldType type) const { 278 const FormGroup* form_group = FormGroupForType(AutofillType(type)); 279 if (!form_group) 280 return base::string16(); 281 282 return form_group->GetRawInfo(type); 283 } 284 285 void AutofillProfile::SetRawInfo(ServerFieldType type, 286 const base::string16& value) { 287 FormGroup* form_group = MutableFormGroupForType(AutofillType(type)); 288 if (form_group) 289 form_group->SetRawInfo(type, CollapseWhitespace(value, false)); 290 } 291 292 base::string16 AutofillProfile::GetInfo(const AutofillType& type, 293 const std::string& app_locale) const { 294 const FormGroup* form_group = FormGroupForType(type); 295 if (!form_group) 296 return base::string16(); 297 298 return form_group->GetInfo(type, app_locale); 299 } 300 301 bool AutofillProfile::SetInfo(const AutofillType& type, 302 const base::string16& value, 303 const std::string& app_locale) { 304 FormGroup* form_group = MutableFormGroupForType(type); 305 if (!form_group) 306 return false; 307 308 return 309 form_group->SetInfo(type, CollapseWhitespace(value, false), app_locale); 310 } 311 312 void AutofillProfile::SetRawMultiInfo( 313 ServerFieldType type, 314 const std::vector<base::string16>& values) { 315 switch (AutofillType(type).group()) { 316 case NAME: 317 case NAME_BILLING: 318 CopyValuesToItems(type, values, &name_, NameInfo()); 319 break; 320 case EMAIL: 321 CopyValuesToItems(type, values, &email_, EmailInfo()); 322 break; 323 case PHONE_HOME: 324 case PHONE_BILLING: 325 CopyValuesToItems(type, 326 values, 327 &phone_number_, 328 PhoneNumber(this)); 329 break; 330 default: 331 if (values.size() == 1) { 332 SetRawInfo(type, values[0]); 333 } else if (values.size() == 0) { 334 SetRawInfo(type, base::string16()); 335 } else { 336 // Shouldn't attempt to set multiple values on single-valued field. 337 NOTREACHED(); 338 } 339 break; 340 } 341 } 342 343 void AutofillProfile::GetRawMultiInfo( 344 ServerFieldType type, 345 std::vector<base::string16>* values) const { 346 GetMultiInfoImpl(AutofillType(type), std::string(), values); 347 } 348 349 void AutofillProfile::GetMultiInfo(const AutofillType& type, 350 const std::string& app_locale, 351 std::vector<base::string16>* values) const { 352 GetMultiInfoImpl(type, app_locale, values); 353 } 354 355 void AutofillProfile::FillFormField(const AutofillField& field, 356 size_t variant, 357 const std::string& app_locale, 358 FormFieldData* field_data) const { 359 AutofillType type = field.Type(); 360 DCHECK_NE(CREDIT_CARD, type.group()); 361 DCHECK(field_data); 362 363 if (type.GetStorableType() == PHONE_HOME_NUMBER) { 364 FillPhoneNumberField(field, variant, app_locale, field_data); 365 } else if (field_data->form_control_type == "select-one") { 366 FillSelectControl(type, app_locale, field_data); 367 } else { 368 std::vector<base::string16> values; 369 GetMultiInfo(type, app_locale, &values); 370 if (variant >= values.size()) { 371 // If the variant is unavailable, bail. This case is reachable, for 372 // example if Sync updates a profile during the filling process. 373 return; 374 } 375 376 field_data->value = values[variant]; 377 } 378 } 379 380 void AutofillProfile::FillPhoneNumberField(const AutofillField& field, 381 size_t variant, 382 const std::string& app_locale, 383 FormFieldData* field_data) const { 384 std::vector<base::string16> values; 385 GetMultiInfo(field.Type(), app_locale, &values); 386 DCHECK(variant < values.size()); 387 388 // If we are filling a phone number, check to see if the size field 389 // matches the "prefix" or "suffix" sizes and fill accordingly. 390 base::string16 number = values[variant]; 391 if (number.length() == 392 PhoneNumber::kPrefixLength + PhoneNumber::kSuffixLength) { 393 if (field.phone_part() == AutofillField::PHONE_PREFIX || 394 field_data->max_length == PhoneNumber::kPrefixLength) { 395 number = number.substr(PhoneNumber::kPrefixOffset, 396 PhoneNumber::kPrefixLength); 397 } else if (field.phone_part() == AutofillField::PHONE_SUFFIX || 398 field_data->max_length == PhoneNumber::kSuffixLength) { 399 number = number.substr(PhoneNumber::kSuffixOffset, 400 PhoneNumber::kSuffixLength); 401 } 402 } 403 404 field_data->value = number; 405 } 406 407 const base::string16 AutofillProfile::Label() const { 408 return label_; 409 } 410 411 bool AutofillProfile::IsEmpty(const std::string& app_locale) const { 412 ServerFieldTypeSet types; 413 GetNonEmptyTypes(app_locale, &types); 414 return types.empty(); 415 } 416 417 bool AutofillProfile::IsPresentButInvalid(ServerFieldType type) const { 418 std::string country = UTF16ToUTF8(GetRawInfo(ADDRESS_HOME_COUNTRY)); 419 base::string16 data = GetRawInfo(type); 420 switch (type) { 421 case ADDRESS_HOME_STATE: 422 if (!data.empty() && country == "US" && !autofill::IsValidState(data)) 423 return true; 424 break; 425 426 case ADDRESS_HOME_ZIP: 427 if (!data.empty() && country == "US" && !autofill::IsValidZip(data)) 428 return true; 429 break; 430 431 case PHONE_HOME_WHOLE_NUMBER: { 432 if (!data.empty() && !i18n::PhoneObject(data, country).IsValidNumber()) 433 return true; 434 break; 435 } 436 437 default: 438 NOTREACHED(); 439 break; 440 } 441 442 return false; 443 } 444 445 446 int AutofillProfile::Compare(const AutofillProfile& profile) const { 447 const ServerFieldType single_value_types[] = { COMPANY_NAME, 448 ADDRESS_HOME_LINE1, 449 ADDRESS_HOME_LINE2, 450 ADDRESS_HOME_CITY, 451 ADDRESS_HOME_STATE, 452 ADDRESS_HOME_ZIP, 453 ADDRESS_HOME_COUNTRY }; 454 455 for (size_t i = 0; i < arraysize(single_value_types); ++i) { 456 int comparison = GetRawInfo(single_value_types[i]).compare( 457 profile.GetRawInfo(single_value_types[i])); 458 if (comparison != 0) 459 return comparison; 460 } 461 462 const ServerFieldType multi_value_types[] = { NAME_FIRST, 463 NAME_MIDDLE, 464 NAME_LAST, 465 EMAIL_ADDRESS, 466 PHONE_HOME_WHOLE_NUMBER }; 467 468 for (size_t i = 0; i < arraysize(multi_value_types); ++i) { 469 std::vector<base::string16> values_a; 470 std::vector<base::string16> values_b; 471 GetRawMultiInfo(multi_value_types[i], &values_a); 472 profile.GetRawMultiInfo(multi_value_types[i], &values_b); 473 if (values_a.size() < values_b.size()) 474 return -1; 475 if (values_a.size() > values_b.size()) 476 return 1; 477 for (size_t j = 0; j < values_a.size(); ++j) { 478 int comparison = values_a[j].compare(values_b[j]); 479 if (comparison != 0) 480 return comparison; 481 } 482 } 483 484 return 0; 485 } 486 487 bool AutofillProfile::operator==(const AutofillProfile& profile) const { 488 return guid() == profile.guid() && 489 origin() == profile.origin() && 490 Compare(profile) == 0; 491 } 492 493 bool AutofillProfile::operator!=(const AutofillProfile& profile) const { 494 return !operator==(profile); 495 } 496 497 const base::string16 AutofillProfile::PrimaryValue() const { 498 return GetRawInfo(ADDRESS_HOME_LINE1) + GetRawInfo(ADDRESS_HOME_CITY); 499 } 500 501 bool AutofillProfile::IsSubsetOf(const AutofillProfile& profile, 502 const std::string& app_locale) const { 503 ServerFieldTypeSet types; 504 GetNonEmptyTypes(app_locale, &types); 505 506 for (ServerFieldTypeSet::const_iterator it = types.begin(); it != types.end(); 507 ++it) { 508 if (*it == NAME_FULL) { 509 // Ignore the compound "full name" field type. We are only interested in 510 // comparing the constituent parts. For example, if |this| has a middle 511 // name saved, but |profile| lacks one, |profile| could still be a subset 512 // of |this|. 513 continue; 514 } else if (AutofillType(*it).group() == PHONE_HOME) { 515 // Phone numbers should be canonicalized prior to being compared. 516 if (*it != PHONE_HOME_WHOLE_NUMBER) { 517 continue; 518 } else if (!i18n::PhoneNumbersMatch( 519 GetRawInfo(*it), 520 profile.GetRawInfo(*it), 521 UTF16ToASCII(GetRawInfo(ADDRESS_HOME_COUNTRY)), 522 app_locale)) { 523 return false; 524 } 525 } else if (StringToLowerASCII(GetRawInfo(*it)) != 526 StringToLowerASCII(profile.GetRawInfo(*it))) { 527 return false; 528 } 529 } 530 531 return true; 532 } 533 534 void AutofillProfile::OverwriteWithOrAddTo(const AutofillProfile& profile, 535 const std::string& app_locale) { 536 // Verified profiles should never be overwritten with unverified data. 537 DCHECK(!IsVerified() || profile.IsVerified()); 538 set_origin(profile.origin()); 539 540 ServerFieldTypeSet field_types; 541 profile.GetNonEmptyTypes(app_locale, &field_types); 542 543 // Only transfer "full" types (e.g. full name) and not fragments (e.g. 544 // first name, last name). 545 CollapseCompoundFieldTypes(&field_types); 546 547 for (ServerFieldTypeSet::const_iterator iter = field_types.begin(); 548 iter != field_types.end(); ++iter) { 549 if (AutofillProfile::SupportsMultiValue(*iter)) { 550 std::vector<base::string16> new_values; 551 profile.GetRawMultiInfo(*iter, &new_values); 552 std::vector<base::string16> existing_values; 553 GetRawMultiInfo(*iter, &existing_values); 554 555 // GetMultiInfo always returns at least one element, even if the profile 556 // has no data stored for this field type. 557 if (existing_values.size() == 1 && existing_values.front().empty()) 558 existing_values.clear(); 559 560 FieldTypeGroup group = AutofillType(*iter).group(); 561 for (std::vector<base::string16>::iterator value_iter = 562 new_values.begin(); 563 value_iter != new_values.end(); ++value_iter) { 564 // Don't add duplicates. 565 if (group == PHONE_HOME) { 566 AddPhoneIfUnique(*value_iter, app_locale, &existing_values); 567 } else { 568 std::vector<base::string16>::const_iterator existing_iter = 569 std::find_if( 570 existing_values.begin(), existing_values.end(), 571 std::bind1st(CaseInsensitiveStringEquals(), *value_iter)); 572 if (existing_iter == existing_values.end()) 573 existing_values.insert(existing_values.end(), *value_iter); 574 } 575 } 576 SetRawMultiInfo(*iter, existing_values); 577 } else { 578 base::string16 new_value = profile.GetRawInfo(*iter); 579 if (StringToLowerASCII(GetRawInfo(*iter)) != 580 StringToLowerASCII(new_value)) { 581 SetRawInfo(*iter, new_value); 582 } 583 } 584 } 585 } 586 587 // static 588 bool AutofillProfile::SupportsMultiValue(ServerFieldType type) { 589 FieldTypeGroup group = AutofillType(type).group(); 590 return group == NAME || 591 group == NAME_BILLING || 592 group == EMAIL || 593 group == PHONE_HOME || 594 group == PHONE_BILLING; 595 } 596 597 // static 598 bool AutofillProfile::AdjustInferredLabels( 599 std::vector<AutofillProfile*>* profiles) { 600 const size_t kMinimalFieldsShown = 2; 601 602 std::vector<base::string16> created_labels; 603 CreateInferredLabels(profiles, NULL, UNKNOWN_TYPE, kMinimalFieldsShown, 604 &created_labels); 605 DCHECK_EQ(profiles->size(), created_labels.size()); 606 607 bool updated_labels = false; 608 for (size_t i = 0; i < profiles->size(); ++i) { 609 if ((*profiles)[i]->Label() != created_labels[i]) { 610 updated_labels = true; 611 (*profiles)[i]->label_ = created_labels[i]; 612 } 613 } 614 return updated_labels; 615 } 616 617 // static 618 void AutofillProfile::CreateInferredLabels( 619 const std::vector<AutofillProfile*>* profiles, 620 const std::vector<ServerFieldType>* suggested_fields, 621 ServerFieldType excluded_field, 622 size_t minimal_fields_shown, 623 std::vector<base::string16>* created_labels) { 624 DCHECK(profiles); 625 DCHECK(created_labels); 626 627 std::vector<ServerFieldType> fields_to_use; 628 GetFieldsForDistinguishingProfiles(suggested_fields, excluded_field, 629 &fields_to_use); 630 631 // Construct the default label for each profile. Also construct a map that 632 // associates each label with the profiles that have this label. This map is 633 // then used to detect which labels need further differentiating fields. 634 std::map<base::string16, std::list<size_t> > labels; 635 for (size_t i = 0; i < profiles->size(); ++i) { 636 base::string16 label = 637 (*profiles)[i]->ConstructInferredLabel(fields_to_use, 638 minimal_fields_shown); 639 labels[label].push_back(i); 640 } 641 642 created_labels->resize(profiles->size()); 643 for (std::map<base::string16, std::list<size_t> >::const_iterator it = 644 labels.begin(); 645 it != labels.end(); ++it) { 646 if (it->second.size() == 1) { 647 // This label is unique, so use it without any further ado. 648 base::string16 label = it->first; 649 size_t profile_index = it->second.front(); 650 (*created_labels)[profile_index] = label; 651 } else { 652 // We have more than one profile with the same label, so add 653 // differentiating fields. 654 CreateDifferentiatingLabels(*profiles, it->second, fields_to_use, 655 minimal_fields_shown, created_labels); 656 } 657 } 658 } 659 660 void AutofillProfile::GetSupportedTypes( 661 ServerFieldTypeSet* supported_types) const { 662 FormGroupList info = FormGroups(); 663 for (FormGroupList::const_iterator it = info.begin(); it != info.end(); ++it) 664 (*it)->GetSupportedTypes(supported_types); 665 } 666 667 bool AutofillProfile::FillCountrySelectControl( 668 const std::string& app_locale, 669 FormFieldData* field_data) const { 670 std::string country_code = UTF16ToASCII(GetRawInfo(ADDRESS_HOME_COUNTRY)); 671 672 DCHECK_EQ(field_data->option_values.size(), 673 field_data->option_contents.size()); 674 for (size_t i = 0; i < field_data->option_values.size(); ++i) { 675 // Canonicalize each <option> value to a country code, and compare to the 676 // target country code. 677 base::string16 value = field_data->option_values[i]; 678 base::string16 contents = field_data->option_contents[i]; 679 if (country_code == AutofillCountry::GetCountryCode(value, app_locale) || 680 country_code == AutofillCountry::GetCountryCode(contents, app_locale)) { 681 field_data->value = value; 682 return true; 683 } 684 } 685 686 return false; 687 } 688 689 void AutofillProfile::GetMultiInfoImpl( 690 const AutofillType& type, 691 const std::string& app_locale, 692 std::vector<base::string16>* values) const { 693 switch (type.group()) { 694 case NAME: 695 case NAME_BILLING: 696 CopyItemsToValues(type, name_, app_locale, values); 697 break; 698 case EMAIL: 699 CopyItemsToValues(type, email_, app_locale, values); 700 break; 701 case PHONE_HOME: 702 case PHONE_BILLING: 703 CopyItemsToValues(type, phone_number_, app_locale, values); 704 break; 705 default: 706 values->resize(1); 707 (*values)[0] = GetFormGroupInfo(*this, type, app_locale); 708 } 709 } 710 711 void AutofillProfile::AddPhoneIfUnique( 712 const base::string16& phone, 713 const std::string& app_locale, 714 std::vector<base::string16>* existing_phones) { 715 DCHECK(existing_phones); 716 // Phones allow "fuzzy" matching, so "1-800-FLOWERS", "18003569377", 717 // "(800)356-9377" and "356-9377" are considered the same. 718 std::string country_code = UTF16ToASCII(GetRawInfo(ADDRESS_HOME_COUNTRY)); 719 if (std::find_if(existing_phones->begin(), existing_phones->end(), 720 FindByPhone(phone, country_code, app_locale)) == 721 existing_phones->end()) { 722 existing_phones->push_back(phone); 723 } 724 } 725 726 base::string16 AutofillProfile::ConstructInferredLabel( 727 const std::vector<ServerFieldType>& included_fields, 728 size_t num_fields_to_use) const { 729 const base::string16 separator = 730 l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_SUMMARY_SEPARATOR); 731 732 base::string16 label; 733 size_t num_fields_used = 0; 734 for (std::vector<ServerFieldType>::const_iterator it = 735 included_fields.begin(); 736 it != included_fields.end() && num_fields_used < num_fields_to_use; 737 ++it) { 738 base::string16 field = GetRawInfo(*it); 739 if (field.empty()) 740 continue; 741 742 if (!label.empty()) 743 label.append(separator); 744 745 label.append(field); 746 ++num_fields_used; 747 } 748 return label; 749 } 750 751 // static 752 void AutofillProfile::CreateDifferentiatingLabels( 753 const std::vector<AutofillProfile*>& profiles, 754 const std::list<size_t>& indices, 755 const std::vector<ServerFieldType>& fields, 756 size_t num_fields_to_include, 757 std::vector<base::string16>* created_labels) { 758 // For efficiency, we first construct a map of fields to their text values and 759 // each value's frequency. 760 std::map<ServerFieldType, 761 std::map<base::string16, size_t> > field_text_frequencies_by_field; 762 for (std::vector<ServerFieldType>::const_iterator field = fields.begin(); 763 field != fields.end(); ++field) { 764 std::map<base::string16, size_t>& field_text_frequencies = 765 field_text_frequencies_by_field[*field]; 766 767 for (std::list<size_t>::const_iterator it = indices.begin(); 768 it != indices.end(); ++it) { 769 const AutofillProfile* profile = profiles[*it]; 770 base::string16 field_text = profile->GetRawInfo(*field); 771 772 // If this label is not already in the map, add it with frequency 0. 773 if (!field_text_frequencies.count(field_text)) 774 field_text_frequencies[field_text] = 0; 775 776 // Now, increment the frequency for this label. 777 ++field_text_frequencies[field_text]; 778 } 779 } 780 781 // Now comes the meat of the algorithm. For each profile, we scan the list of 782 // fields to use, looking for two things: 783 // 1. A (non-empty) field that differentiates the profile from all others 784 // 2. At least |num_fields_to_include| non-empty fields 785 // Before we've satisfied condition (2), we include all fields, even ones that 786 // are identical across all the profiles. Once we've satisfied condition (2), 787 // we only include fields that that have at last two distinct values. 788 for (std::list<size_t>::const_iterator it = indices.begin(); 789 it != indices.end(); ++it) { 790 const AutofillProfile* profile = profiles[*it]; 791 792 std::vector<ServerFieldType> label_fields; 793 bool found_differentiating_field = false; 794 for (std::vector<ServerFieldType>::const_iterator field = fields.begin(); 795 field != fields.end(); ++field) { 796 // Skip over empty fields. 797 base::string16 field_text = profile->GetRawInfo(*field); 798 if (field_text.empty()) 799 continue; 800 801 std::map<base::string16, size_t>& field_text_frequencies = 802 field_text_frequencies_by_field[*field]; 803 found_differentiating_field |= 804 !field_text_frequencies.count(base::string16()) && 805 (field_text_frequencies[field_text] == 1); 806 807 // Once we've found enough non-empty fields, skip over any remaining 808 // fields that are identical across all the profiles. 809 if (label_fields.size() >= num_fields_to_include && 810 (field_text_frequencies.size() == 1)) 811 continue; 812 813 label_fields.push_back(*field); 814 815 // If we've (1) found a differentiating field and (2) found at least 816 // |num_fields_to_include| non-empty fields, we're done! 817 if (found_differentiating_field && 818 label_fields.size() >= num_fields_to_include) 819 break; 820 } 821 822 (*created_labels)[*it] = 823 profile->ConstructInferredLabel(label_fields, 824 label_fields.size()); 825 } 826 } 827 828 AutofillProfile::FormGroupList AutofillProfile::FormGroups() const { 829 FormGroupList v(5); 830 v[0] = &name_[0]; 831 v[1] = &email_[0]; 832 v[2] = &company_; 833 v[3] = &phone_number_[0]; 834 v[4] = &address_; 835 return v; 836 } 837 838 const FormGroup* AutofillProfile::FormGroupForType( 839 const AutofillType& type) const { 840 return const_cast<AutofillProfile*>(this)->MutableFormGroupForType(type); 841 } 842 843 FormGroup* AutofillProfile::MutableFormGroupForType(const AutofillType& type) { 844 switch (type.group()) { 845 case NAME: 846 case NAME_BILLING: 847 return &name_[0]; 848 849 case EMAIL: 850 return &email_[0]; 851 852 case COMPANY: 853 return &company_; 854 855 case PHONE_HOME: 856 case PHONE_BILLING: 857 return &phone_number_[0]; 858 859 case ADDRESS_HOME: 860 case ADDRESS_BILLING: 861 return &address_; 862 863 case NO_GROUP: 864 case CREDIT_CARD: 865 return NULL; 866 } 867 868 NOTREACHED(); 869 return NULL; 870 } 871 872 // So we can compare AutofillProfiles with EXPECT_EQ(). 873 std::ostream& operator<<(std::ostream& os, const AutofillProfile& profile) { 874 return os 875 << UTF16ToUTF8(profile.Label()) 876 << " " 877 << profile.guid() 878 << " " 879 << profile.origin() 880 << " " 881 << UTF16ToUTF8(MultiString(profile, NAME_FIRST)) 882 << " " 883 << UTF16ToUTF8(MultiString(profile, NAME_MIDDLE)) 884 << " " 885 << UTF16ToUTF8(MultiString(profile, NAME_LAST)) 886 << " " 887 << UTF16ToUTF8(MultiString(profile, EMAIL_ADDRESS)) 888 << " " 889 << UTF16ToUTF8(profile.GetRawInfo(COMPANY_NAME)) 890 << " " 891 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE1)) 892 << " " 893 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE2)) 894 << " " 895 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_CITY)) 896 << " " 897 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_STATE)) 898 << " " 899 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_ZIP)) 900 << " " 901 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY)) 902 << " " 903 << UTF16ToUTF8(MultiString(profile, PHONE_HOME_WHOLE_NUMBER)); 904 } 905 906 } // namespace autofill 907