personal_data_manager.cc revision a02191e04bc25c4935f804f2c080ae28663d096d
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 base::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 pref_service_(NULL), 150 is_off_the_record_(false), 151 has_logged_profile_count_(false) {} 152 153void PersonalDataManager::Init(scoped_refptr<AutofillWebDataService> database, 154 PrefService* pref_service, 155 bool is_off_the_record) { 156 database_ = database; 157 SetPrefService(pref_service); 158 is_off_the_record_ = is_off_the_record; 159 160 if (!is_off_the_record_) 161 metric_logger_->LogIsAutofillEnabledAtStartup(IsAutofillEnabled()); 162 163 // WebDataService may not be available in tests. 164 if (!database_.get()) 165 return; 166 167 LoadProfiles(); 168 LoadCreditCards(); 169 170 database_->AddObserver(this); 171} 172 173PersonalDataManager::~PersonalDataManager() { 174 CancelPendingQuery(&pending_profiles_query_); 175 CancelPendingQuery(&pending_creditcards_query_); 176 177 if (database_.get()) 178 database_->RemoveObserver(this); 179} 180 181void PersonalDataManager::OnWebDataServiceRequestDone( 182 WebDataServiceBase::Handle h, 183 const WDTypedResult* result) { 184 DCHECK(pending_profiles_query_ || pending_creditcards_query_); 185 186 if (!result) { 187 // Error from the web database. 188 if (h == pending_creditcards_query_) 189 pending_creditcards_query_ = 0; 190 else if (h == pending_profiles_query_) 191 pending_profiles_query_ = 0; 192 return; 193 } 194 195 switch (result->GetType()) { 196 case AUTOFILL_PROFILES_RESULT: 197 ReceiveLoadedProfiles(h, result); 198 break; 199 case AUTOFILL_CREDITCARDS_RESULT: 200 ReceiveLoadedCreditCards(h, result); 201 break; 202 default: 203 NOTREACHED(); 204 } 205 206 // If both requests have responded, then all personal data is loaded. 207 if (pending_profiles_query_ == 0 && pending_creditcards_query_ == 0) { 208 is_data_loaded_ = true; 209 NotifyPersonalDataChanged(); 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; 252 base::TrimWhitespace(field->value, base::TRIM_ALL, &value); 253 254 // If we don't know the type of the field, or the user hasn't entered any 255 // information into the field, then skip it. 256 if (!field->IsFieldFillable() || value.empty()) 257 continue; 258 259 AutofillType field_type = field->Type(); 260 ServerFieldType server_field_type = field_type.GetStorableType(); 261 FieldTypeGroup group(field_type.group()); 262 263 // There can be multiple email fields (e.g. in the case of 'confirm email' 264 // fields) but they must all contain the same value, else the profile is 265 // invalid. 266 if (server_field_type == EMAIL_ADDRESS) { 267 if (types_seen.count(server_field_type) && 268 imported_profile->GetRawInfo(EMAIL_ADDRESS) != value) { 269 imported_profile.reset(); 270 break; 271 } 272 } 273 274 // If the |field_type| and |value| don't pass basic validity checks then 275 // abandon the import. 276 if (!IsValidFieldTypeAndValue(types_seen, server_field_type, value)) { 277 imported_profile.reset(); 278 local_imported_credit_card.reset(); 279 break; 280 } 281 282 types_seen.insert(server_field_type); 283 284 if (group == CREDIT_CARD) { 285 if (LowerCaseEqualsASCII(field->form_control_type, "month")) { 286 DCHECK_EQ(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, server_field_type); 287 local_imported_credit_card->SetInfoForMonthInputType(value); 288 } else { 289 local_imported_credit_card->SetInfo(field_type, value, app_locale_); 290 } 291 ++importable_credit_card_fields; 292 } else { 293 // We need to store phone data in the variables, before building the whole 294 // number at the end. The rest of the fields are set "as is". 295 // If the fields are not the phone fields in question home.SetInfo() is 296 // going to return false. 297 if (!home.SetInfo(field_type, value)) 298 imported_profile->SetInfo(field_type, value, app_locale_); 299 300 // Reject profiles with invalid country information. 301 if (server_field_type == ADDRESS_HOME_COUNTRY && 302 !value.empty() && 303 imported_profile->GetRawInfo(ADDRESS_HOME_COUNTRY).empty()) { 304 imported_profile.reset(); 305 break; 306 } 307 } 308 } 309 310 // Construct the phone number. Reject the profile if the number is invalid. 311 if (imported_profile.get() && !home.IsEmpty()) { 312 base::string16 constructed_number; 313 if (!home.ParseNumber(*imported_profile, app_locale_, 314 &constructed_number) || 315 !imported_profile->SetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER), 316 constructed_number, 317 app_locale_)) { 318 imported_profile.reset(); 319 } 320 } 321 322 // Reject the profile if minimum address and validation requirements are not 323 // met. 324 if (imported_profile.get() && 325 !IsValidLearnableProfile(*imported_profile, app_locale_)) 326 imported_profile.reset(); 327 328 // Reject the credit card if we did not detect enough filled credit card 329 // fields or if the credit card number does not seem to be valid. 330 if (local_imported_credit_card.get() && 331 !local_imported_credit_card->IsComplete()) { 332 local_imported_credit_card.reset(); 333 } 334 335 // Don't import if we already have this info. 336 // Don't present an infobar if we have already saved this card number. 337 bool merged_credit_card = false; 338 if (local_imported_credit_card.get()) { 339 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin(); 340 iter != credit_cards_.end(); 341 ++iter) { 342 // Make a local copy so that the data in |credit_cards_| isn't modified 343 // directly by the UpdateFromImportedCard() call. 344 CreditCard card = **iter; 345 if (card.UpdateFromImportedCard(*local_imported_credit_card.get(), 346 app_locale_)) { 347 merged_credit_card = true; 348 UpdateCreditCard(card); 349 local_imported_credit_card.reset(); 350 break; 351 } 352 } 353 } 354 355 if (imported_profile.get()) { 356 // We always save imported profiles. 357 SaveImportedProfile(*imported_profile); 358 } 359 *imported_credit_card = local_imported_credit_card.Pass(); 360 361 if (imported_profile.get() || *imported_credit_card || merged_credit_card) 362 return true; 363 364 FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_, 365 OnInsufficientFormData()); 366 return false; 367} 368 369void PersonalDataManager::AddProfile(const AutofillProfile& profile) { 370 if (is_off_the_record_) 371 return; 372 373 if (profile.IsEmpty(app_locale_)) 374 return; 375 376 // Don't add an existing profile. 377 if (FindByGUID<AutofillProfile>(web_profiles_, profile.guid())) 378 return; 379 380 if (!database_.get()) 381 return; 382 383 // Don't add a duplicate. 384 if (FindByContents(web_profiles_, profile)) 385 return; 386 387 // Add the new profile to the web database. 388 database_->AddAutofillProfile(profile); 389 390 // Refresh our local cache and send notifications to observers. 391 Refresh(); 392} 393 394void PersonalDataManager::UpdateProfile(const AutofillProfile& profile) { 395 if (is_off_the_record_) 396 return; 397 398 AutofillProfile* existing_profile = GetProfileByGUID(profile.guid()); 399 if (!existing_profile) 400 return; 401 402 // Don't overwrite the origin for a profile that is already stored. 403 if (existing_profile->EqualsSansOrigin(profile)) 404 return; 405 406 if (profile.IsEmpty(app_locale_)) { 407 RemoveByGUID(profile.guid()); 408 return; 409 } 410 411 if (!database_.get()) 412 return; 413 414 // Make the update. 415 database_->UpdateAutofillProfile(profile); 416 417 // Refresh our local cache and send notifications to observers. 418 Refresh(); 419} 420 421AutofillProfile* PersonalDataManager::GetProfileByGUID( 422 const std::string& guid) { 423 const std::vector<AutofillProfile*>& profiles = GetProfiles(); 424 std::vector<AutofillProfile*>::const_iterator iter = 425 FindElementByGUID<AutofillProfile>(profiles, guid); 426 return (iter != profiles.end()) ? *iter : NULL; 427} 428 429void PersonalDataManager::AddCreditCard(const CreditCard& credit_card) { 430 if (is_off_the_record_) 431 return; 432 433 if (credit_card.IsEmpty(app_locale_)) 434 return; 435 436 if (FindByGUID<CreditCard>(credit_cards_, credit_card.guid())) 437 return; 438 439 if (!database_.get()) 440 return; 441 442 // Don't add a duplicate. 443 if (FindByContents(credit_cards_, credit_card)) 444 return; 445 446 // Add the new credit card to the web database. 447 database_->AddCreditCard(credit_card); 448 449 // Refresh our local cache and send notifications to observers. 450 Refresh(); 451} 452 453void PersonalDataManager::UpdateCreditCard(const CreditCard& credit_card) { 454 if (is_off_the_record_) 455 return; 456 457 CreditCard* existing_credit_card = GetCreditCardByGUID(credit_card.guid()); 458 if (!existing_credit_card) 459 return; 460 461 // Don't overwrite the origin for a credit card that is already stored. 462 if (existing_credit_card->Compare(credit_card) == 0) 463 return; 464 465 if (credit_card.IsEmpty(app_locale_)) { 466 RemoveByGUID(credit_card.guid()); 467 return; 468 } 469 470 if (!database_.get()) 471 return; 472 473 // Make the update. 474 database_->UpdateCreditCard(credit_card); 475 476 // Refresh our local cache and send notifications to observers. 477 Refresh(); 478} 479 480void PersonalDataManager::RemoveByGUID(const std::string& guid) { 481 if (is_off_the_record_) 482 return; 483 484 bool is_credit_card = FindByGUID<CreditCard>(credit_cards_, guid); 485 bool is_profile = !is_credit_card && 486 FindByGUID<AutofillProfile>(web_profiles_, guid); 487 if (!is_credit_card && !is_profile) 488 return; 489 490 if (!database_.get()) 491 return; 492 493 if (is_credit_card) 494 database_->RemoveCreditCard(guid); 495 else 496 database_->RemoveAutofillProfile(guid); 497 498 // Refresh our local cache and send notifications to observers. 499 Refresh(); 500} 501 502CreditCard* PersonalDataManager::GetCreditCardByGUID(const std::string& guid) { 503 const std::vector<CreditCard*>& credit_cards = GetCreditCards(); 504 std::vector<CreditCard*>::const_iterator iter = 505 FindElementByGUID<CreditCard>(credit_cards, guid); 506 return (iter != credit_cards.end()) ? *iter : NULL; 507} 508 509void PersonalDataManager::GetNonEmptyTypes( 510 ServerFieldTypeSet* non_empty_types) { 511 const std::vector<AutofillProfile*>& profiles = GetProfiles(); 512 for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin(); 513 iter != profiles.end(); ++iter) { 514 (*iter)->GetNonEmptyTypes(app_locale_, non_empty_types); 515 } 516 517 for (ScopedVector<CreditCard>::const_iterator iter = credit_cards_.begin(); 518 iter != credit_cards_.end(); ++iter) { 519 (*iter)->GetNonEmptyTypes(app_locale_, non_empty_types); 520 } 521} 522 523bool PersonalDataManager::IsDataLoaded() const { 524 return is_data_loaded_; 525} 526 527const std::vector<AutofillProfile*>& PersonalDataManager::GetProfiles() const { 528 if (!pref_service_->GetBoolean(prefs::kAutofillAuxiliaryProfilesEnabled)) { 529 return web_profiles(); 530 } 531 532 profiles_.clear(); 533 534 // Populates |auxiliary_profiles_|. 535 LoadAuxiliaryProfiles(); 536 537 profiles_.insert(profiles_.end(), web_profiles_.begin(), web_profiles_.end()); 538 profiles_.insert(profiles_.end(), 539 auxiliary_profiles_.begin(), auxiliary_profiles_.end()); 540 return profiles_; 541} 542 543const std::vector<AutofillProfile*>& PersonalDataManager::web_profiles() const { 544 return web_profiles_.get(); 545} 546 547const std::vector<CreditCard*>& PersonalDataManager::GetCreditCards() const { 548 return credit_cards_.get(); 549} 550 551void PersonalDataManager::Refresh() { 552 LoadProfiles(); 553 LoadCreditCards(); 554} 555 556void PersonalDataManager::GetProfileSuggestions( 557 const AutofillType& type, 558 const base::string16& field_contents, 559 bool field_is_autofilled, 560 const std::vector<ServerFieldType>& other_field_types, 561 const base::Callback<bool(const AutofillProfile&)>& filter, 562 std::vector<base::string16>* values, 563 std::vector<base::string16>* labels, 564 std::vector<base::string16>* icons, 565 std::vector<GUIDPair>* guid_pairs) { 566 values->clear(); 567 labels->clear(); 568 icons->clear(); 569 guid_pairs->clear(); 570 571 const std::vector<AutofillProfile*>& profiles = GetProfiles(); 572 std::vector<AutofillProfile*> matched_profiles; 573 for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin(); 574 iter != profiles.end(); ++iter) { 575 AutofillProfile* profile = *iter; 576 577 // The value of the stored data for this field type in the |profile|. 578 std::vector<base::string16> multi_values; 579 profile->GetMultiInfo(type, app_locale_, &multi_values); 580 581 for (size_t i = 0; i < multi_values.size(); ++i) { 582 if (!field_is_autofilled) { 583 // Suggest data that starts with what the user has typed. 584 if (!multi_values[i].empty() && 585 StartsWith(multi_values[i], field_contents, false) && 586 (filter.is_null() || filter.Run(*profile))) { 587 matched_profiles.push_back(profile); 588 values->push_back(multi_values[i]); 589 guid_pairs->push_back(GUIDPair(profile->guid(), i)); 590 } 591 } else { 592 if (multi_values[i].empty()) 593 continue; 594 595 base::string16 profile_value_lower_case( 596 StringToLowerASCII(multi_values[i])); 597 base::string16 field_value_lower_case( 598 StringToLowerASCII(field_contents)); 599 // Phone numbers could be split in US forms, so field value could be 600 // either prefix or suffix of the phone. 601 bool matched_phones = false; 602 if (type.GetStorableType() == PHONE_HOME_NUMBER && 603 !field_value_lower_case.empty() && 604 profile_value_lower_case.find(field_value_lower_case) != 605 base::string16::npos) { 606 matched_phones = true; 607 } 608 609 // Suggest variants of the profile that's already been filled in. 610 if (matched_phones || 611 profile_value_lower_case == field_value_lower_case) { 612 for (size_t j = 0; j < multi_values.size(); ++j) { 613 if (!multi_values[j].empty()) { 614 values->push_back(multi_values[j]); 615 guid_pairs->push_back(GUIDPair(profile->guid(), j)); 616 } 617 } 618 619 // We've added all the values for this profile so move on to the 620 // next. 621 break; 622 } 623 } 624 } 625 } 626 627 if (!field_is_autofilled) { 628 AutofillProfile::CreateInferredLabels( 629 matched_profiles, &other_field_types, 630 type.GetStorableType(), 1, labels); 631 } else { 632 // No sub-labels for previously filled fields. 633 labels->resize(values->size()); 634 } 635 636 // No icons for profile suggestions. 637 icons->resize(values->size()); 638} 639 640void PersonalDataManager::GetCreditCardSuggestions( 641 const AutofillType& type, 642 const base::string16& field_contents, 643 std::vector<base::string16>* values, 644 std::vector<base::string16>* labels, 645 std::vector<base::string16>* icons, 646 std::vector<GUIDPair>* guid_pairs) { 647 values->clear(); 648 labels->clear(); 649 icons->clear(); 650 guid_pairs->clear(); 651 652 const std::vector<CreditCard*>& credit_cards = GetCreditCards(); 653 for (std::vector<CreditCard*>::const_iterator iter = credit_cards.begin(); 654 iter != credit_cards.end(); ++iter) { 655 CreditCard* credit_card = *iter; 656 657 // The value of the stored data for this field type in the |credit_card|. 658 base::string16 creditcard_field_value = 659 credit_card->GetInfo(type, app_locale_); 660 if (!creditcard_field_value.empty() && 661 StartsWith(creditcard_field_value, field_contents, false)) { 662 if (type.GetStorableType() == CREDIT_CARD_NUMBER) 663 creditcard_field_value = credit_card->ObfuscatedNumber(); 664 665 base::string16 label; 666 if (credit_card->number().empty()) { 667 // If there is no CC number, return name to show something. 668 label = 669 credit_card->GetInfo(AutofillType(CREDIT_CARD_NAME), app_locale_); 670 } else { 671 label = kCreditCardPrefix; 672 label.append(credit_card->LastFourDigits()); 673 } 674 675 values->push_back(creditcard_field_value); 676 labels->push_back(label); 677 icons->push_back(base::UTF8ToUTF16(credit_card->type())); 678 guid_pairs->push_back(GUIDPair(credit_card->guid(), 0)); 679 } 680 } 681} 682 683bool PersonalDataManager::IsAutofillEnabled() const { 684 DCHECK(pref_service_); 685 return pref_service_->GetBoolean(prefs::kAutofillEnabled); 686} 687 688std::string PersonalDataManager::CountryCodeForCurrentTimezone() const { 689 return base::CountryCodeForCurrentTimezone(); 690} 691 692void PersonalDataManager::SetPrefService(PrefService* pref_service) { 693 enabled_pref_.reset(new BooleanPrefMember); 694 pref_service_ = pref_service; 695 // |pref_service_| can be NULL in tests. 696 if (pref_service_) { 697 enabled_pref_->Init(prefs::kAutofillEnabled, pref_service_, 698 base::Bind(&PersonalDataManager::EnabledPrefChanged, 699 base::Unretained(this))); 700 } 701} 702 703// static 704bool PersonalDataManager::IsValidLearnableProfile( 705 const AutofillProfile& profile, 706 const std::string& app_locale) { 707 if (!IsMinimumAddress(profile, app_locale)) 708 return false; 709 710 base::string16 email = profile.GetRawInfo(EMAIL_ADDRESS); 711 if (!email.empty() && !IsValidEmailAddress(email)) 712 return false; 713 714 // Reject profiles with invalid US state information. 715 if (profile.IsPresentButInvalid(ADDRESS_HOME_STATE)) 716 return false; 717 718 // Reject profiles with invalid US zip information. 719 if (profile.IsPresentButInvalid(ADDRESS_HOME_ZIP)) 720 return false; 721 722 return true; 723} 724 725// static 726std::string PersonalDataManager::MergeProfile( 727 const AutofillProfile& new_profile, 728 const std::vector<AutofillProfile*>& existing_profiles, 729 const std::string& app_locale, 730 std::vector<AutofillProfile>* merged_profiles) { 731 merged_profiles->clear(); 732 733 // Set to true if |existing_profiles| already contains an equivalent profile. 734 bool matching_profile_found = false; 735 std::string guid = new_profile.guid(); 736 737 // If we have already saved this address, merge in any missing values. 738 // Only merge with the first match. 739 for (std::vector<AutofillProfile*>::const_iterator iter = 740 existing_profiles.begin(); 741 iter != existing_profiles.end(); ++iter) { 742 AutofillProfile* existing_profile = *iter; 743 if (!matching_profile_found && 744 !new_profile.PrimaryValue().empty() && 745 StringToLowerASCII(existing_profile->PrimaryValue()) == 746 StringToLowerASCII(new_profile.PrimaryValue())) { 747 // Unverified profiles should always be updated with the newer data, 748 // whereas verified profiles should only ever be overwritten by verified 749 // data. If an automatically aggregated profile would overwrite a 750 // verified profile, just drop it. 751 matching_profile_found = true; 752 guid = existing_profile->guid(); 753 if (!existing_profile->IsVerified() || new_profile.IsVerified()) 754 existing_profile->OverwriteWithOrAddTo(new_profile, app_locale); 755 } 756 merged_profiles->push_back(*existing_profile); 757 } 758 759 // If the new profile was not merged with an existing one, add it to the list. 760 if (!matching_profile_found) 761 merged_profiles->push_back(new_profile); 762 763 return guid; 764} 765 766bool PersonalDataManager::IsCountryOfInterest(const std::string& country_code) 767 const { 768 DCHECK_EQ(2U, country_code.size()); 769 770 const std::vector<AutofillProfile*>& profiles = web_profiles(); 771 std::list<std::string> country_codes; 772 for (size_t i = 0; i < profiles.size(); ++i) { 773 country_codes.push_back(StringToLowerASCII(base::UTF16ToASCII( 774 profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY)))); 775 } 776 777 std::string timezone_country = CountryCodeForCurrentTimezone(); 778 if (!timezone_country.empty()) 779 country_codes.push_back(StringToLowerASCII(timezone_country)); 780 781 // Only take the locale into consideration if all else fails. 782 if (country_codes.empty()) { 783 country_codes.push_back(StringToLowerASCII( 784 AutofillCountry::CountryCodeForLocale(app_locale()))); 785 } 786 787 return std::find(country_codes.begin(), country_codes.end(), 788 StringToLowerASCII(country_code)) != country_codes.end(); 789} 790 791const std::string& PersonalDataManager::GetDefaultCountryCodeForNewAddress() 792 const { 793 if (default_country_code_.empty()) 794 default_country_code_ = MostCommonCountryCodeFromProfiles(); 795 796 // Failing that, guess based on system timezone. 797 if (default_country_code_.empty()) 798 default_country_code_ = CountryCodeForCurrentTimezone(); 799 800 // Failing that, guess based on locale. 801 if (default_country_code_.empty()) 802 default_country_code_ = AutofillCountry::CountryCodeForLocale(app_locale()); 803 804 return default_country_code_; 805} 806 807void PersonalDataManager::SetProfiles(std::vector<AutofillProfile>* profiles) { 808 if (is_off_the_record_) 809 return; 810 811 // Remove empty profiles from input. 812 profiles->erase(std::remove_if(profiles->begin(), profiles->end(), 813 IsEmptyFunctor<AutofillProfile>(app_locale_)), 814 profiles->end()); 815 816 if (!database_.get()) 817 return; 818 819 // Any profiles that are not in the new profile list should be removed from 820 // the web database. 821 for (std::vector<AutofillProfile*>::const_iterator iter = 822 web_profiles_.begin(); 823 iter != web_profiles_.end(); ++iter) { 824 if (!FindByGUID<AutofillProfile>(*profiles, (*iter)->guid())) 825 database_->RemoveAutofillProfile((*iter)->guid()); 826 } 827 828 // Update the web database with the existing profiles. 829 for (std::vector<AutofillProfile>::iterator iter = profiles->begin(); 830 iter != profiles->end(); ++iter) { 831 if (FindByGUID<AutofillProfile>(web_profiles_, iter->guid())) 832 database_->UpdateAutofillProfile(*iter); 833 } 834 835 // Add the new profiles to the web database. Don't add a duplicate. 836 for (std::vector<AutofillProfile>::iterator iter = profiles->begin(); 837 iter != profiles->end(); ++iter) { 838 if (!FindByGUID<AutofillProfile>(web_profiles_, iter->guid()) && 839 !FindByContents(web_profiles_, *iter)) 840 database_->AddAutofillProfile(*iter); 841 } 842 843 // Copy in the new profiles. 844 web_profiles_.clear(); 845 for (std::vector<AutofillProfile>::iterator iter = profiles->begin(); 846 iter != profiles->end(); ++iter) { 847 web_profiles_.push_back(new AutofillProfile(*iter)); 848 } 849 850 // Refresh our local cache and send notifications to observers. 851 Refresh(); 852} 853 854void PersonalDataManager::SetCreditCards( 855 std::vector<CreditCard>* credit_cards) { 856 if (is_off_the_record_) 857 return; 858 859 // Remove empty credit cards from input. 860 credit_cards->erase(std::remove_if(credit_cards->begin(), credit_cards->end(), 861 IsEmptyFunctor<CreditCard>(app_locale_)), 862 credit_cards->end()); 863 864 if (!database_.get()) 865 return; 866 867 // Any credit cards that are not in the new credit card list should be 868 // removed. 869 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin(); 870 iter != credit_cards_.end(); ++iter) { 871 if (!FindByGUID<CreditCard>(*credit_cards, (*iter)->guid())) 872 database_->RemoveCreditCard((*iter)->guid()); 873 } 874 875 // Update the web database with the existing credit cards. 876 for (std::vector<CreditCard>::iterator iter = credit_cards->begin(); 877 iter != credit_cards->end(); ++iter) { 878 if (FindByGUID<CreditCard>(credit_cards_, iter->guid())) 879 database_->UpdateCreditCard(*iter); 880 } 881 882 // Add the new credit cards to the web database. Don't add a duplicate. 883 for (std::vector<CreditCard>::iterator iter = credit_cards->begin(); 884 iter != credit_cards->end(); ++iter) { 885 if (!FindByGUID<CreditCard>(credit_cards_, iter->guid()) && 886 !FindByContents(credit_cards_, *iter)) 887 database_->AddCreditCard(*iter); 888 } 889 890 // Copy in the new credit cards. 891 credit_cards_.clear(); 892 for (std::vector<CreditCard>::iterator iter = credit_cards->begin(); 893 iter != credit_cards->end(); ++iter) { 894 credit_cards_.push_back(new CreditCard(*iter)); 895 } 896 897 // Refresh our local cache and send notifications to observers. 898 Refresh(); 899} 900 901void PersonalDataManager::LoadProfiles() { 902 if (!database_.get()) { 903 NOTREACHED(); 904 return; 905 } 906 907 CancelPendingQuery(&pending_profiles_query_); 908 909 pending_profiles_query_ = database_->GetAutofillProfiles(this); 910} 911 912// Win, Linux, and iOS implementations do nothing. Mac and Android 913// implementations fill in the contents of |auxiliary_profiles_|. 914#if defined(OS_IOS) || (!defined(OS_MACOSX) && !defined(OS_ANDROID)) 915void PersonalDataManager::LoadAuxiliaryProfiles() const { 916} 917#endif 918 919void PersonalDataManager::LoadCreditCards() { 920 if (!database_.get()) { 921 NOTREACHED(); 922 return; 923 } 924 925 CancelPendingQuery(&pending_creditcards_query_); 926 927 pending_creditcards_query_ = database_->GetCreditCards(this); 928} 929 930void PersonalDataManager::ReceiveLoadedProfiles(WebDataServiceBase::Handle h, 931 const WDTypedResult* result) { 932 DCHECK_EQ(pending_profiles_query_, h); 933 934 pending_profiles_query_ = 0; 935 web_profiles_.clear(); 936 937 const WDResult<std::vector<AutofillProfile*> >* r = 938 static_cast<const WDResult<std::vector<AutofillProfile*> >*>(result); 939 940 std::vector<AutofillProfile*> profiles = r->GetValue(); 941 for (std::vector<AutofillProfile*>::iterator iter = profiles.begin(); 942 iter != profiles.end(); ++iter) { 943 web_profiles_.push_back(*iter); 944 } 945 946 LogProfileCount(); 947} 948 949void PersonalDataManager::ReceiveLoadedCreditCards( 950 WebDataServiceBase::Handle h, const WDTypedResult* result) { 951 DCHECK_EQ(pending_creditcards_query_, h); 952 953 pending_creditcards_query_ = 0; 954 credit_cards_.clear(); 955 956 const WDResult<std::vector<CreditCard*> >* r = 957 static_cast<const WDResult<std::vector<CreditCard*> >*>(result); 958 959 std::vector<CreditCard*> credit_cards = r->GetValue(); 960 for (std::vector<CreditCard*>::iterator iter = credit_cards.begin(); 961 iter != credit_cards.end(); ++iter) { 962 credit_cards_.push_back(*iter); 963 } 964} 965 966void PersonalDataManager::CancelPendingQuery( 967 WebDataServiceBase::Handle* handle) { 968 if (*handle) { 969 if (!database_.get()) { 970 NOTREACHED(); 971 return; 972 } 973 database_->CancelRequest(*handle); 974 } 975 *handle = 0; 976} 977 978std::string PersonalDataManager::SaveImportedProfile( 979 const AutofillProfile& imported_profile) { 980 if (is_off_the_record_) 981 return std::string(); 982 983 // Don't save a web profile if the data in the profile is a subset of an 984 // auxiliary profile. 985 for (std::vector<AutofillProfile*>::const_iterator iter = 986 auxiliary_profiles_.begin(); 987 iter != auxiliary_profiles_.end(); ++iter) { 988 if (imported_profile.IsSubsetOf(**iter, app_locale_)) 989 return (*iter)->guid(); 990 } 991 992 std::vector<AutofillProfile> profiles; 993 std::string guid = 994 MergeProfile(imported_profile, web_profiles_.get(), app_locale_, 995 &profiles); 996 SetProfiles(&profiles); 997 return guid; 998} 999 1000void PersonalDataManager::NotifyPersonalDataChanged() { 1001 FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_, 1002 OnPersonalDataChanged()); 1003} 1004 1005std::string PersonalDataManager::SaveImportedCreditCard( 1006 const CreditCard& imported_card) { 1007 DCHECK(!imported_card.number().empty()); 1008 if (is_off_the_record_) 1009 return std::string(); 1010 1011 // Set to true if |imported_card| is merged into the credit card list. 1012 bool merged = false; 1013 1014 std::string guid = imported_card.guid(); 1015 std::vector<CreditCard> credit_cards; 1016 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin(); 1017 iter != credit_cards_.end(); 1018 ++iter) { 1019 CreditCard* card = *iter; 1020 // If |imported_card| has not yet been merged, check whether it should be 1021 // with the current |card|. 1022 if (!merged && card->UpdateFromImportedCard(imported_card, app_locale_)) { 1023 guid = card->guid(); 1024 merged = true; 1025 } 1026 1027 credit_cards.push_back(*card); 1028 } 1029 1030 if (!merged) 1031 credit_cards.push_back(imported_card); 1032 1033 SetCreditCards(&credit_cards); 1034 return guid; 1035} 1036 1037void PersonalDataManager::LogProfileCount() const { 1038 if (!has_logged_profile_count_) { 1039 metric_logger_->LogStoredProfileCount(web_profiles_.size()); 1040 has_logged_profile_count_ = true; 1041 } 1042} 1043 1044std::string PersonalDataManager::MostCommonCountryCodeFromProfiles() const { 1045 if (!IsAutofillEnabled()) 1046 return std::string(); 1047 1048 // Count up country codes from existing profiles. 1049 std::map<std::string, int> votes; 1050 // TODO(estade): can we make this GetProfiles() instead? It seems to cause 1051 // errors in tests on mac trybots. See http://crbug.com/57221 1052 const std::vector<AutofillProfile*>& profiles = web_profiles(); 1053 std::vector<std::string> country_codes; 1054 AutofillCountry::GetAvailableCountries(&country_codes); 1055 for (size_t i = 0; i < profiles.size(); ++i) { 1056 std::string country_code = StringToUpperASCII(base::UTF16ToASCII( 1057 profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY))); 1058 1059 if (std::find(country_codes.begin(), country_codes.end(), country_code) != 1060 country_codes.end()) { 1061 // Verified profiles count 100x more than unverified ones. 1062 votes[country_code] += profiles[i]->IsVerified() ? 100 : 1; 1063 } 1064 } 1065 1066 // Take the most common country code. 1067 if (!votes.empty()) { 1068 std::map<std::string, int>::iterator iter = 1069 std::max_element(votes.begin(), votes.end(), CompareVotes); 1070 return iter->first; 1071 } 1072 1073 return std::string(); 1074} 1075 1076void PersonalDataManager::EnabledPrefChanged() { 1077 default_country_code_.clear(); 1078 NotifyPersonalDataChanged(); 1079} 1080 1081} // namespace autofill 1082