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