personal_data_manager.cc revision f2477e01787aa58f445919b809d89e252beef54f
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/personal_data_manager.h" 6 7#include <algorithm> 8#include <functional> 9#include <iterator> 10 11#include "base/i18n/timezone.h" 12#include "base/logging.h" 13#include "base/memory/ref_counted.h" 14#include "base/prefs/pref_service.h" 15#include "base/strings/string_number_conversions.h" 16#include "base/strings/string_util.h" 17#include "base/strings/utf_string_conversions.h" 18#include "components/autofill/core/browser/autofill-inl.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/form_structure.h" 22#include "components/autofill/core/browser/personal_data_manager_observer.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/autofill_pref_names.h" 27 28namespace autofill { 29namespace { 30 31const base::string16::value_type kCreditCardPrefix[] = {'*', 0}; 32 33template<typename T> 34class FormGroupMatchesByGUIDFunctor { 35 public: 36 explicit FormGroupMatchesByGUIDFunctor(const std::string& guid) 37 : guid_(guid) { 38 } 39 40 bool operator()(const T& form_group) { 41 return form_group.guid() == guid_; 42 } 43 44 bool operator()(const T* form_group) { 45 return form_group->guid() == guid_; 46 } 47 48 private: 49 const std::string guid_; 50}; 51 52template<typename T, typename C> 53typename C::const_iterator FindElementByGUID(const C& container, 54 const std::string& guid) { 55 return std::find_if(container.begin(), 56 container.end(), 57 FormGroupMatchesByGUIDFunctor<T>(guid)); 58} 59 60template<typename T, typename C> 61bool FindByGUID(const C& container, const std::string& guid) { 62 return FindElementByGUID<T>(container, guid) != container.end(); 63} 64 65template<typename T> 66class IsEmptyFunctor { 67 public: 68 explicit IsEmptyFunctor(const std::string& app_locale) 69 : app_locale_(app_locale) { 70 } 71 72 bool operator()(const T& form_group) { 73 return form_group.IsEmpty(app_locale_); 74 } 75 76 private: 77 const std::string app_locale_; 78}; 79 80// Returns true if minimum requirements for import of a given |profile| have 81// been met. An address submitted via a form must have at least the fields 82// required as determined by its country code. 83// No verification of validity of the contents is preformed. This is an 84// existence check only. 85bool IsMinimumAddress(const AutofillProfile& profile, 86 const std::string& app_locale) { 87 // All countries require at least one address line. 88 if (profile.GetRawInfo(ADDRESS_HOME_LINE1).empty()) 89 return false; 90 91 std::string country_code = 92 UTF16ToASCII(profile.GetRawInfo(ADDRESS_HOME_COUNTRY)); 93 if (country_code.empty()) 94 country_code = AutofillCountry::CountryCodeForLocale(app_locale); 95 96 AutofillCountry country(country_code, app_locale); 97 98 if (country.requires_city() && profile.GetRawInfo(ADDRESS_HOME_CITY).empty()) 99 return false; 100 101 if (country.requires_state() && 102 profile.GetRawInfo(ADDRESS_HOME_STATE).empty()) 103 return false; 104 105 if (country.requires_zip() && profile.GetRawInfo(ADDRESS_HOME_ZIP).empty()) 106 return false; 107 108 return true; 109} 110 111// Return true if the |field_type| and |value| are valid within the context 112// of importing a form. 113bool IsValidFieldTypeAndValue(const std::set<ServerFieldType>& types_seen, 114 ServerFieldType field_type, 115 const base::string16& value) { 116 // Abandon the import if two fields of the same type are encountered. 117 // This indicates ambiguous data or miscategorization of types. 118 // Make an exception for PHONE_HOME_NUMBER however as both prefix and 119 // suffix are stored against this type, and for EMAIL_ADDRESS because it is 120 // common to see second 'confirm email address' fields on forms. 121 if (types_seen.count(field_type) && 122 field_type != PHONE_HOME_NUMBER && 123 field_type != EMAIL_ADDRESS) 124 return false; 125 126 // Abandon the import if an email address value shows up in a field that is 127 // not an email address. 128 if (field_type != EMAIL_ADDRESS && IsValidEmailAddress(value)) 129 return false; 130 131 return true; 132} 133 134// A helper function for finding the maximum value in a string->int map. 135static bool CompareVotes(const std::pair<std::string, int>& a, 136 const std::pair<std::string, int>& b) { 137 return a.second < b.second; 138} 139 140} // namespace 141 142PersonalDataManager::PersonalDataManager(const std::string& app_locale) 143 : database_(NULL), 144 is_data_loaded_(false), 145 pending_profiles_query_(0), 146 pending_creditcards_query_(0), 147 app_locale_(app_locale), 148 metric_logger_(new AutofillMetrics), 149 is_off_the_record_(false), 150 has_logged_profile_count_(false) {} 151 152void PersonalDataManager::Init(scoped_refptr<AutofillWebDataService> database, 153 PrefService* pref_service, 154 bool is_off_the_record) { 155 database_ = database; 156 pref_service_ = pref_service; 157 is_off_the_record_ = is_off_the_record; 158 159 if (!is_off_the_record_) 160 metric_logger_->LogIsAutofillEnabledAtStartup(IsAutofillEnabled()); 161 162 // WebDataService may not be available in tests. 163 if (!database_.get()) 164 return; 165 166 LoadProfiles(); 167 LoadCreditCards(); 168 169 database_->AddObserver(this); 170} 171 172PersonalDataManager::~PersonalDataManager() { 173 CancelPendingQuery(&pending_profiles_query_); 174 CancelPendingQuery(&pending_creditcards_query_); 175 176 if (database_.get()) 177 database_->RemoveObserver(this); 178} 179 180void PersonalDataManager::OnWebDataServiceRequestDone( 181 WebDataServiceBase::Handle h, 182 const WDTypedResult* result) { 183 DCHECK(pending_profiles_query_ || pending_creditcards_query_); 184 185 if (!result) { 186 // Error from the web database. 187 if (h == pending_creditcards_query_) 188 pending_creditcards_query_ = 0; 189 else if (h == pending_profiles_query_) 190 pending_profiles_query_ = 0; 191 return; 192 } 193 194 switch (result->GetType()) { 195 case AUTOFILL_PROFILES_RESULT: 196 ReceiveLoadedProfiles(h, result); 197 break; 198 case AUTOFILL_CREDITCARDS_RESULT: 199 ReceiveLoadedCreditCards(h, result); 200 break; 201 default: 202 NOTREACHED(); 203 } 204 205 // If both requests have responded, then all personal data is loaded. 206 if (pending_profiles_query_ == 0 && pending_creditcards_query_ == 0) { 207 is_data_loaded_ = true; 208 FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_, 209 OnPersonalDataChanged()); 210 } 211} 212 213void PersonalDataManager::AutofillMultipleChanged() { 214 Refresh(); 215} 216 217void PersonalDataManager::AddObserver(PersonalDataManagerObserver* observer) { 218 observers_.AddObserver(observer); 219} 220 221void PersonalDataManager::RemoveObserver( 222 PersonalDataManagerObserver* observer) { 223 observers_.RemoveObserver(observer); 224} 225 226bool PersonalDataManager::ImportFormData( 227 const FormStructure& form, 228 scoped_ptr<CreditCard>* imported_credit_card) { 229 scoped_ptr<AutofillProfile> imported_profile(new AutofillProfile); 230 scoped_ptr<CreditCard> local_imported_credit_card(new CreditCard); 231 232 const std::string origin = form.source_url().spec(); 233 imported_profile->set_origin(origin); 234 local_imported_credit_card->set_origin(origin); 235 236 // Parse the form and construct a profile based on the information that is 237 // possible to import. 238 int importable_credit_card_fields = 0; 239 240 // Detect and discard forms with multiple fields of the same type. 241 // TODO(isherman): Some types are overlapping but not equal, e.g. phone number 242 // parts, address parts. 243 std::set<ServerFieldType> types_seen; 244 245 // We only set complete phone, so aggregate phone parts in these vars and set 246 // complete at the end. 247 PhoneNumber::PhoneCombineHelper home; 248 249 for (size_t i = 0; i < form.field_count(); ++i) { 250 const AutofillField* field = form.field(i); 251 base::string16 value = CollapseWhitespace(field->value, false); 252 253 // If we don't know the type of the field, or the user hasn't entered any 254 // information into the field, then skip it. 255 if (!field->IsFieldFillable() || value.empty()) 256 continue; 257 258 AutofillType field_type = field->Type(); 259 ServerFieldType server_field_type = field_type.GetStorableType(); 260 FieldTypeGroup group(field_type.group()); 261 262 // There can be multiple email fields (e.g. in the case of 'confirm email' 263 // fields) but they must all contain the same value, else the profile is 264 // invalid. 265 if (server_field_type == EMAIL_ADDRESS) { 266 if (types_seen.count(server_field_type) && 267 imported_profile->GetRawInfo(EMAIL_ADDRESS) != value) { 268 imported_profile.reset(); 269 break; 270 } 271 } 272 273 // If the |field_type| and |value| don't pass basic validity checks then 274 // abandon the import. 275 if (!IsValidFieldTypeAndValue(types_seen, server_field_type, value)) { 276 imported_profile.reset(); 277 local_imported_credit_card.reset(); 278 break; 279 } 280 281 types_seen.insert(server_field_type); 282 283 if (group == CREDIT_CARD) { 284 if (LowerCaseEqualsASCII(field->form_control_type, "month")) { 285 DCHECK_EQ(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, server_field_type); 286 local_imported_credit_card->SetInfoForMonthInputType(value); 287 } else { 288 local_imported_credit_card->SetInfo(field_type, value, app_locale_); 289 } 290 ++importable_credit_card_fields; 291 } else { 292 // We need to store phone data in the variables, before building the whole 293 // number at the end. The rest of the fields are set "as is". 294 // If the fields are not the phone fields in question home.SetInfo() is 295 // going to return false. 296 if (!home.SetInfo(field_type, value)) 297 imported_profile->SetInfo(field_type, value, app_locale_); 298 299 // Reject profiles with invalid country information. 300 if (server_field_type == ADDRESS_HOME_COUNTRY && 301 !value.empty() && 302 imported_profile->GetRawInfo(ADDRESS_HOME_COUNTRY).empty()) { 303 imported_profile.reset(); 304 break; 305 } 306 } 307 } 308 309 // Construct the phone number. Reject the profile if the number is invalid. 310 if (imported_profile.get() && !home.IsEmpty()) { 311 base::string16 constructed_number; 312 if (!home.ParseNumber(*imported_profile, app_locale_, 313 &constructed_number) || 314 !imported_profile->SetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER), 315 constructed_number, 316 app_locale_)) { 317 imported_profile.reset(); 318 } 319 } 320 321 // Reject the profile if minimum address and validation requirements are not 322 // met. 323 if (imported_profile.get() && 324 !IsValidLearnableProfile(*imported_profile, app_locale_)) 325 imported_profile.reset(); 326 327 // Reject the credit card if we did not detect enough filled credit card 328 // fields or if the credit card number does not seem to be valid. 329 if (local_imported_credit_card.get() && 330 !local_imported_credit_card->IsComplete()) { 331 local_imported_credit_card.reset(); 332 } 333 334 // Don't import if we already have this info. 335 // Don't present an infobar if we have already saved this card number. 336 bool merged_credit_card = false; 337 if (local_imported_credit_card.get()) { 338 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin(); 339 iter != credit_cards_.end(); 340 ++iter) { 341 // Make a local copy so that the data in |credit_cards_| isn't modified 342 // directly by the UpdateFromImportedCard() call. 343 CreditCard card = **iter; 344 if (card.UpdateFromImportedCard(*local_imported_credit_card.get(), 345 app_locale_)) { 346 merged_credit_card = true; 347 UpdateCreditCard(card); 348 local_imported_credit_card.reset(); 349 break; 350 } 351 } 352 } 353 354 if (imported_profile.get()) { 355 // We always save imported profiles. 356 SaveImportedProfile(*imported_profile); 357 } 358 *imported_credit_card = local_imported_credit_card.Pass(); 359 360 if (imported_profile.get() || *imported_credit_card || merged_credit_card) 361 return true; 362 363 FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_, 364 OnInsufficientFormData()); 365 return false; 366} 367 368void PersonalDataManager::AddProfile(const AutofillProfile& profile) { 369 if (is_off_the_record_) 370 return; 371 372 if (profile.IsEmpty(app_locale_)) 373 return; 374 375 // Don't add an existing profile. 376 if (FindByGUID<AutofillProfile>(web_profiles_, profile.guid())) 377 return; 378 379 if (!database_.get()) 380 return; 381 382 // Don't add a duplicate. 383 if (FindByContents(web_profiles_, profile)) 384 return; 385 386 // Add the new profile to the web database. 387 database_->AddAutofillProfile(profile); 388 389 // Refresh our local cache and send notifications to observers. 390 Refresh(); 391} 392 393void PersonalDataManager::UpdateProfile(const AutofillProfile& profile) { 394 if (is_off_the_record_) 395 return; 396 397 AutofillProfile* existing_profile = GetProfileByGUID(profile.guid()); 398 if (!existing_profile) 399 return; 400 401 // Don't overwrite the origin for a profile that is already stored. 402 if (existing_profile->Compare(profile) == 0) 403 return; 404 405 if (profile.IsEmpty(app_locale_)) { 406 RemoveByGUID(profile.guid()); 407 return; 408 } 409 410 if (!database_.get()) 411 return; 412 413 // Make the update. 414 database_->UpdateAutofillProfile(profile); 415 416 // Refresh our local cache and send notifications to observers. 417 Refresh(); 418} 419 420AutofillProfile* PersonalDataManager::GetProfileByGUID( 421 const std::string& guid) { 422 const std::vector<AutofillProfile*>& profiles = GetProfiles(); 423 std::vector<AutofillProfile*>::const_iterator iter = 424 FindElementByGUID<AutofillProfile>(profiles, guid); 425 return (iter != profiles.end()) ? *iter : NULL; 426} 427 428void PersonalDataManager::AddCreditCard(const CreditCard& credit_card) { 429 if (is_off_the_record_) 430 return; 431 432 if (credit_card.IsEmpty(app_locale_)) 433 return; 434 435 if (FindByGUID<CreditCard>(credit_cards_, credit_card.guid())) 436 return; 437 438 if (!database_.get()) 439 return; 440 441 // Don't add a duplicate. 442 if (FindByContents(credit_cards_, credit_card)) 443 return; 444 445 // Add the new credit card to the web database. 446 database_->AddCreditCard(credit_card); 447 448 // Refresh our local cache and send notifications to observers. 449 Refresh(); 450} 451 452void PersonalDataManager::UpdateCreditCard(const CreditCard& credit_card) { 453 if (is_off_the_record_) 454 return; 455 456 CreditCard* existing_credit_card = GetCreditCardByGUID(credit_card.guid()); 457 if (!existing_credit_card) 458 return; 459 460 // Don't overwrite the origin for a credit card that is already stored. 461 if (existing_credit_card->Compare(credit_card) == 0) 462 return; 463 464 if (credit_card.IsEmpty(app_locale_)) { 465 RemoveByGUID(credit_card.guid()); 466 return; 467 } 468 469 if (!database_.get()) 470 return; 471 472 // Make the update. 473 database_->UpdateCreditCard(credit_card); 474 475 // Refresh our local cache and send notifications to observers. 476 Refresh(); 477} 478 479void PersonalDataManager::RemoveByGUID(const std::string& guid) { 480 if (is_off_the_record_) 481 return; 482 483 bool is_credit_card = FindByGUID<CreditCard>(credit_cards_, guid); 484 bool is_profile = !is_credit_card && 485 FindByGUID<AutofillProfile>(web_profiles_, guid); 486 if (!is_credit_card && !is_profile) 487 return; 488 489 if (!database_.get()) 490 return; 491 492 if (is_credit_card) 493 database_->RemoveCreditCard(guid); 494 else 495 database_->RemoveAutofillProfile(guid); 496 497 // Refresh our local cache and send notifications to observers. 498 Refresh(); 499} 500 501CreditCard* PersonalDataManager::GetCreditCardByGUID(const std::string& guid) { 502 const std::vector<CreditCard*>& credit_cards = GetCreditCards(); 503 std::vector<CreditCard*>::const_iterator iter = 504 FindElementByGUID<CreditCard>(credit_cards, guid); 505 return (iter != credit_cards.end()) ? *iter : NULL; 506} 507 508void PersonalDataManager::GetNonEmptyTypes( 509 ServerFieldTypeSet* non_empty_types) { 510 const std::vector<AutofillProfile*>& profiles = GetProfiles(); 511 for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin(); 512 iter != profiles.end(); ++iter) { 513 (*iter)->GetNonEmptyTypes(app_locale_, non_empty_types); 514 } 515 516 for (ScopedVector<CreditCard>::const_iterator iter = credit_cards_.begin(); 517 iter != credit_cards_.end(); ++iter) { 518 (*iter)->GetNonEmptyTypes(app_locale_, non_empty_types); 519 } 520} 521 522bool PersonalDataManager::IsDataLoaded() const { 523 return is_data_loaded_; 524} 525 526const std::vector<AutofillProfile*>& PersonalDataManager::GetProfiles() const { 527 if (!pref_service_->GetBoolean(prefs::kAutofillAuxiliaryProfilesEnabled)) { 528 return web_profiles(); 529 } 530 531 profiles_.clear(); 532 533 // Populates |auxiliary_profiles_|. 534 LoadAuxiliaryProfiles(); 535 536 profiles_.insert(profiles_.end(), web_profiles_.begin(), web_profiles_.end()); 537 profiles_.insert(profiles_.end(), 538 auxiliary_profiles_.begin(), auxiliary_profiles_.end()); 539 return profiles_; 540} 541 542const std::vector<AutofillProfile*>& PersonalDataManager::web_profiles() const { 543 return web_profiles_.get(); 544} 545 546const std::vector<CreditCard*>& PersonalDataManager::GetCreditCards() const { 547 return credit_cards_.get(); 548} 549 550void PersonalDataManager::Refresh() { 551 LoadProfiles(); 552 LoadCreditCards(); 553} 554 555void PersonalDataManager::GetProfileSuggestions( 556 const AutofillType& type, 557 const base::string16& field_contents, 558 bool field_is_autofilled, 559 const std::vector<ServerFieldType>& other_field_types, 560 std::vector<base::string16>* values, 561 std::vector<base::string16>* labels, 562 std::vector<base::string16>* icons, 563 std::vector<GUIDPair>* guid_pairs) { 564 values->clear(); 565 labels->clear(); 566 icons->clear(); 567 guid_pairs->clear(); 568 569 const std::vector<AutofillProfile*>& profiles = GetProfiles(); 570 std::vector<AutofillProfile*> matched_profiles; 571 for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin(); 572 iter != profiles.end(); ++iter) { 573 AutofillProfile* profile = *iter; 574 575 // The value of the stored data for this field type in the |profile|. 576 std::vector<base::string16> multi_values; 577 profile->GetMultiInfo(type, app_locale_, &multi_values); 578 579 for (size_t i = 0; i < multi_values.size(); ++i) { 580 if (!field_is_autofilled) { 581 // Suggest data that starts with what the user has typed. 582 if (!multi_values[i].empty() && 583 StartsWith(multi_values[i], field_contents, false)) { 584 matched_profiles.push_back(profile); 585 values->push_back(multi_values[i]); 586 guid_pairs->push_back(GUIDPair(profile->guid(), i)); 587 } 588 } else { 589 if (multi_values[i].empty()) 590 continue; 591 592 base::string16 profile_value_lower_case( 593 StringToLowerASCII(multi_values[i])); 594 base::string16 field_value_lower_case( 595 StringToLowerASCII(field_contents)); 596 // Phone numbers could be split in US forms, so field value could be 597 // either prefix or suffix of the phone. 598 bool matched_phones = false; 599 if (type.GetStorableType() == PHONE_HOME_NUMBER && 600 !field_value_lower_case.empty() && 601 profile_value_lower_case.find(field_value_lower_case) != 602 base::string16::npos) { 603 matched_phones = true; 604 } 605 606 // Suggest variants of the profile that's already been filled in. 607 if (matched_phones || 608 profile_value_lower_case == field_value_lower_case) { 609 for (size_t j = 0; j < multi_values.size(); ++j) { 610 if (!multi_values[j].empty()) { 611 values->push_back(multi_values[j]); 612 guid_pairs->push_back(GUIDPair(profile->guid(), j)); 613 } 614 } 615 616 // We've added all the values for this profile so move on to the 617 // next. 618 break; 619 } 620 } 621 } 622 } 623 624 if (!field_is_autofilled) { 625 AutofillProfile::CreateInferredLabels( 626 matched_profiles, &other_field_types, 627 type.GetStorableType(), 1, labels); 628 } else { 629 // No sub-labels for previously filled fields. 630 labels->resize(values->size()); 631 } 632 633 // No icons for profile suggestions. 634 icons->resize(values->size()); 635} 636 637void PersonalDataManager::GetCreditCardSuggestions( 638 const AutofillType& type, 639 const base::string16& field_contents, 640 std::vector<base::string16>* values, 641 std::vector<base::string16>* labels, 642 std::vector<base::string16>* icons, 643 std::vector<GUIDPair>* guid_pairs) { 644 values->clear(); 645 labels->clear(); 646 icons->clear(); 647 guid_pairs->clear(); 648 649 const std::vector<CreditCard*>& credit_cards = GetCreditCards(); 650 for (std::vector<CreditCard*>::const_iterator iter = credit_cards.begin(); 651 iter != credit_cards.end(); ++iter) { 652 CreditCard* credit_card = *iter; 653 654 // The value of the stored data for this field type in the |credit_card|. 655 base::string16 creditcard_field_value = 656 credit_card->GetInfo(type, app_locale_); 657 if (!creditcard_field_value.empty() && 658 StartsWith(creditcard_field_value, field_contents, false)) { 659 if (type.GetStorableType() == CREDIT_CARD_NUMBER) 660 creditcard_field_value = credit_card->ObfuscatedNumber(); 661 662 base::string16 label; 663 if (credit_card->number().empty()) { 664 // If there is no CC number, return name to show something. 665 label = 666 credit_card->GetInfo(AutofillType(CREDIT_CARD_NAME), app_locale_); 667 } else { 668 label = kCreditCardPrefix; 669 label.append(credit_card->LastFourDigits()); 670 } 671 672 values->push_back(creditcard_field_value); 673 labels->push_back(label); 674 icons->push_back(UTF8ToUTF16(credit_card->type())); 675 guid_pairs->push_back(GUIDPair(credit_card->guid(), 0)); 676 } 677 } 678} 679 680bool PersonalDataManager::IsAutofillEnabled() const { 681 return pref_service_->GetBoolean(prefs::kAutofillEnabled); 682} 683 684// static 685bool PersonalDataManager::IsValidLearnableProfile( 686 const AutofillProfile& profile, 687 const std::string& app_locale) { 688 if (!IsMinimumAddress(profile, app_locale)) 689 return false; 690 691 base::string16 email = profile.GetRawInfo(EMAIL_ADDRESS); 692 if (!email.empty() && !IsValidEmailAddress(email)) 693 return false; 694 695 // Reject profiles with invalid US state information. 696 if (profile.IsPresentButInvalid(ADDRESS_HOME_STATE)) 697 return false; 698 699 // Reject profiles with invalid US zip information. 700 if (profile.IsPresentButInvalid(ADDRESS_HOME_ZIP)) 701 return false; 702 703 return true; 704} 705 706// static 707std::string PersonalDataManager::MergeProfile( 708 const AutofillProfile& new_profile, 709 const std::vector<AutofillProfile*>& existing_profiles, 710 const std::string& app_locale, 711 std::vector<AutofillProfile>* merged_profiles) { 712 merged_profiles->clear(); 713 714 // Set to true if |existing_profiles| already contains an equivalent profile. 715 bool matching_profile_found = false; 716 std::string guid = new_profile.guid(); 717 718 // If we have already saved this address, merge in any missing values. 719 // Only merge with the first match. 720 for (std::vector<AutofillProfile*>::const_iterator iter = 721 existing_profiles.begin(); 722 iter != existing_profiles.end(); ++iter) { 723 AutofillProfile* existing_profile = *iter; 724 if (!matching_profile_found && 725 !new_profile.PrimaryValue().empty() && 726 StringToLowerASCII(existing_profile->PrimaryValue()) == 727 StringToLowerASCII(new_profile.PrimaryValue())) { 728 // Unverified profiles should always be updated with the newer data, 729 // whereas verified profiles should only ever be overwritten by verified 730 // data. If an automatically aggregated profile would overwrite a 731 // verified profile, just drop it. 732 matching_profile_found = true; 733 guid = existing_profile->guid(); 734 if (!existing_profile->IsVerified() || new_profile.IsVerified()) 735 existing_profile->OverwriteWithOrAddTo(new_profile, app_locale); 736 } 737 merged_profiles->push_back(*existing_profile); 738 } 739 740 // If the new profile was not merged with an existing one, add it to the list. 741 if (!matching_profile_found) 742 merged_profiles->push_back(new_profile); 743 744 return guid; 745} 746 747const std::string& PersonalDataManager::GetDefaultCountryCodeForNewAddress() 748 const { 749 if (default_country_code_.empty()) 750 default_country_code_ = MostCommonCountryCodeFromProfiles(); 751 752 // Failing that, guess based on system timezone. 753 if (default_country_code_.empty()) 754 default_country_code_ = base::CountryCodeForCurrentTimezone(); 755 756 // Failing that, guess based on locale. 757 if (default_country_code_.empty()) 758 default_country_code_ = AutofillCountry::CountryCodeForLocale(app_locale()); 759 760 return default_country_code_; 761} 762 763void PersonalDataManager::SetProfiles(std::vector<AutofillProfile>* profiles) { 764 if (is_off_the_record_) 765 return; 766 767 // Remove empty profiles from input. 768 profiles->erase(std::remove_if(profiles->begin(), profiles->end(), 769 IsEmptyFunctor<AutofillProfile>(app_locale_)), 770 profiles->end()); 771 772 if (!database_.get()) 773 return; 774 775 // Any profiles that are not in the new profile list should be removed from 776 // the web database. 777 for (std::vector<AutofillProfile*>::const_iterator iter = 778 web_profiles_.begin(); 779 iter != web_profiles_.end(); ++iter) { 780 if (!FindByGUID<AutofillProfile>(*profiles, (*iter)->guid())) 781 database_->RemoveAutofillProfile((*iter)->guid()); 782 } 783 784 // Update the web database with the existing profiles. 785 for (std::vector<AutofillProfile>::iterator iter = profiles->begin(); 786 iter != profiles->end(); ++iter) { 787 if (FindByGUID<AutofillProfile>(web_profiles_, iter->guid())) 788 database_->UpdateAutofillProfile(*iter); 789 } 790 791 // Add the new profiles to the web database. Don't add a duplicate. 792 for (std::vector<AutofillProfile>::iterator iter = profiles->begin(); 793 iter != profiles->end(); ++iter) { 794 if (!FindByGUID<AutofillProfile>(web_profiles_, iter->guid()) && 795 !FindByContents(web_profiles_, *iter)) 796 database_->AddAutofillProfile(*iter); 797 } 798 799 // Copy in the new profiles. 800 web_profiles_.clear(); 801 for (std::vector<AutofillProfile>::iterator iter = profiles->begin(); 802 iter != profiles->end(); ++iter) { 803 web_profiles_.push_back(new AutofillProfile(*iter)); 804 } 805 806 // Refresh our local cache and send notifications to observers. 807 Refresh(); 808} 809 810void PersonalDataManager::SetCreditCards( 811 std::vector<CreditCard>* credit_cards) { 812 if (is_off_the_record_) 813 return; 814 815 // Remove empty credit cards from input. 816 credit_cards->erase(std::remove_if(credit_cards->begin(), credit_cards->end(), 817 IsEmptyFunctor<CreditCard>(app_locale_)), 818 credit_cards->end()); 819 820 if (!database_.get()) 821 return; 822 823 // Any credit cards that are not in the new credit card list should be 824 // removed. 825 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin(); 826 iter != credit_cards_.end(); ++iter) { 827 if (!FindByGUID<CreditCard>(*credit_cards, (*iter)->guid())) 828 database_->RemoveCreditCard((*iter)->guid()); 829 } 830 831 // Update the web database with the existing credit cards. 832 for (std::vector<CreditCard>::iterator iter = credit_cards->begin(); 833 iter != credit_cards->end(); ++iter) { 834 if (FindByGUID<CreditCard>(credit_cards_, iter->guid())) 835 database_->UpdateCreditCard(*iter); 836 } 837 838 // Add the new credit cards to the web database. Don't add a duplicate. 839 for (std::vector<CreditCard>::iterator iter = credit_cards->begin(); 840 iter != credit_cards->end(); ++iter) { 841 if (!FindByGUID<CreditCard>(credit_cards_, iter->guid()) && 842 !FindByContents(credit_cards_, *iter)) 843 database_->AddCreditCard(*iter); 844 } 845 846 // Copy in the new credit cards. 847 credit_cards_.clear(); 848 for (std::vector<CreditCard>::iterator iter = credit_cards->begin(); 849 iter != credit_cards->end(); ++iter) { 850 credit_cards_.push_back(new CreditCard(*iter)); 851 } 852 853 // Refresh our local cache and send notifications to observers. 854 Refresh(); 855} 856 857void PersonalDataManager::LoadProfiles() { 858 if (!database_.get()) { 859 NOTREACHED(); 860 return; 861 } 862 863 CancelPendingQuery(&pending_profiles_query_); 864 865 pending_profiles_query_ = database_->GetAutofillProfiles(this); 866} 867 868// Win and Linux implementations do nothing. Mac and Android implementations 869// fill in the contents of |auxiliary_profiles_|. 870#if !defined(OS_MACOSX) && !defined(OS_ANDROID) 871void PersonalDataManager::LoadAuxiliaryProfiles() const { 872} 873#endif 874 875void PersonalDataManager::LoadCreditCards() { 876 if (!database_.get()) { 877 NOTREACHED(); 878 return; 879 } 880 881 CancelPendingQuery(&pending_creditcards_query_); 882 883 pending_creditcards_query_ = database_->GetCreditCards(this); 884} 885 886void PersonalDataManager::ReceiveLoadedProfiles(WebDataServiceBase::Handle h, 887 const WDTypedResult* result) { 888 DCHECK_EQ(pending_profiles_query_, h); 889 890 pending_profiles_query_ = 0; 891 web_profiles_.clear(); 892 893 const WDResult<std::vector<AutofillProfile*> >* r = 894 static_cast<const WDResult<std::vector<AutofillProfile*> >*>(result); 895 896 std::vector<AutofillProfile*> profiles = r->GetValue(); 897 for (std::vector<AutofillProfile*>::iterator iter = profiles.begin(); 898 iter != profiles.end(); ++iter) { 899 web_profiles_.push_back(*iter); 900 } 901 902 LogProfileCount(); 903} 904 905void PersonalDataManager::ReceiveLoadedCreditCards( 906 WebDataServiceBase::Handle h, const WDTypedResult* result) { 907 DCHECK_EQ(pending_creditcards_query_, h); 908 909 pending_creditcards_query_ = 0; 910 credit_cards_.clear(); 911 912 const WDResult<std::vector<CreditCard*> >* r = 913 static_cast<const WDResult<std::vector<CreditCard*> >*>(result); 914 915 std::vector<CreditCard*> credit_cards = r->GetValue(); 916 for (std::vector<CreditCard*>::iterator iter = credit_cards.begin(); 917 iter != credit_cards.end(); ++iter) { 918 credit_cards_.push_back(*iter); 919 } 920} 921 922void PersonalDataManager::CancelPendingQuery( 923 WebDataServiceBase::Handle* handle) { 924 if (*handle) { 925 if (!database_.get()) { 926 NOTREACHED(); 927 return; 928 } 929 database_->CancelRequest(*handle); 930 } 931 *handle = 0; 932} 933 934std::string PersonalDataManager::SaveImportedProfile( 935 const AutofillProfile& imported_profile) { 936 if (is_off_the_record_) 937 return std::string(); 938 939 // Don't save a web profile if the data in the profile is a subset of an 940 // auxiliary profile. 941 for (std::vector<AutofillProfile*>::const_iterator iter = 942 auxiliary_profiles_.begin(); 943 iter != auxiliary_profiles_.end(); ++iter) { 944 if (imported_profile.IsSubsetOf(**iter, app_locale_)) 945 return (*iter)->guid(); 946 } 947 948 std::vector<AutofillProfile> profiles; 949 std::string guid = 950 MergeProfile(imported_profile, web_profiles_.get(), app_locale_, 951 &profiles); 952 SetProfiles(&profiles); 953 return guid; 954} 955 956 957std::string PersonalDataManager::SaveImportedCreditCard( 958 const CreditCard& imported_card) { 959 DCHECK(!imported_card.number().empty()); 960 if (is_off_the_record_) 961 return std::string(); 962 963 // Set to true if |imported_card| is merged into the credit card list. 964 bool merged = false; 965 966 std::string guid = imported_card.guid(); 967 std::vector<CreditCard> credit_cards; 968 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin(); 969 iter != credit_cards_.end(); 970 ++iter) { 971 CreditCard* card = *iter; 972 // If |imported_card| has not yet been merged, check whether it should be 973 // with the current |card|. 974 if (!merged && card->UpdateFromImportedCard(imported_card, app_locale_)) { 975 guid = card->guid(); 976 merged = true; 977 } 978 979 credit_cards.push_back(*card); 980 } 981 982 if (!merged) 983 credit_cards.push_back(imported_card); 984 985 SetCreditCards(&credit_cards); 986 return guid; 987} 988 989void PersonalDataManager::LogProfileCount() const { 990 if (!has_logged_profile_count_) { 991 metric_logger_->LogStoredProfileCount(web_profiles_.size()); 992 has_logged_profile_count_ = true; 993 } 994} 995 996std::string PersonalDataManager::MostCommonCountryCodeFromProfiles() const { 997 // Count up country codes from existing profiles. 998 std::map<std::string, int> votes; 999 // TODO(estade): can we make this GetProfiles() instead? It seems to cause 1000 // errors in tests on mac trybots. See http://crbug.com/57221 1001 const std::vector<AutofillProfile*>& profiles = web_profiles(); 1002 std::vector<std::string> country_codes; 1003 AutofillCountry::GetAvailableCountries(&country_codes); 1004 for (size_t i = 0; i < profiles.size(); ++i) { 1005 std::string country_code = StringToUpperASCII(UTF16ToASCII( 1006 profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY))); 1007 1008 if (std::find(country_codes.begin(), country_codes.end(), country_code) != 1009 country_codes.end()) { 1010 // Verified profiles count 100x more than unverified ones. 1011 votes[country_code] += profiles[i]->IsVerified() ? 100 : 1; 1012 } 1013 } 1014 1015 // Take the most common country code. 1016 if (!votes.empty()) { 1017 std::map<std::string, int>::iterator iter = 1018 std::max_element(votes.begin(), votes.end(), CompareVotes); 1019 return iter->first; 1020 } 1021 1022 return std::string(); 1023} 1024 1025} // namespace autofill 1026