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 28 namespace autofill { 29 namespace { 30 31 const base::string16::value_type kCreditCardPrefix[] = {'*', 0}; 32 33 template<typename T> 34 class 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 52 template<typename T, typename C> 53 typename 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 60 template<typename T, typename C> 61 bool FindByGUID(const C& container, const std::string& guid) { 62 return FindElementByGUID<T>(container, guid) != container.end(); 63 } 64 65 template<typename T> 66 class 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. 85 bool 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. 113 bool 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. 135 static 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 142 PersonalDataManager::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 153 void 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 173 PersonalDataManager::~PersonalDataManager() { 174 CancelPendingQuery(&pending_profiles_query_); 175 CancelPendingQuery(&pending_creditcards_query_); 176 177 if (database_.get()) 178 database_->RemoveObserver(this); 179 } 180 181 void 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 213 void PersonalDataManager::AutofillMultipleChanged() { 214 Refresh(); 215 } 216 217 void PersonalDataManager::AddObserver(PersonalDataManagerObserver* observer) { 218 observers_.AddObserver(observer); 219 } 220 221 void PersonalDataManager::RemoveObserver( 222 PersonalDataManagerObserver* observer) { 223 observers_.RemoveObserver(observer); 224 } 225 226 bool 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 369 void 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 394 void 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 421 AutofillProfile* 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 429 void 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 453 void 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 480 void 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 502 CreditCard* 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 509 void 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 523 bool PersonalDataManager::IsDataLoaded() const { 524 return is_data_loaded_; 525 } 526 527 const std::vector<AutofillProfile*>& PersonalDataManager::GetProfiles() const { 528 #if defined(OS_MACOSX) && !defined(OS_IOS) 529 if (!pref_service_->GetBoolean(prefs::kAutofillUseMacAddressBook)) 530 return web_profiles(); 531 #else 532 if (!pref_service_->GetBoolean(prefs::kAutofillAuxiliaryProfilesEnabled)) 533 return web_profiles(); 534 #endif // defined(OS_MACOSX) && !defined(OS_IOS) 535 536 profiles_.clear(); 537 538 // Populates |auxiliary_profiles_|. 539 LoadAuxiliaryProfiles(); 540 541 profiles_.insert(profiles_.end(), web_profiles_.begin(), web_profiles_.end()); 542 profiles_.insert(profiles_.end(), 543 auxiliary_profiles_.begin(), auxiliary_profiles_.end()); 544 return profiles_; 545 } 546 547 const std::vector<AutofillProfile*>& PersonalDataManager::web_profiles() const { 548 return web_profiles_.get(); 549 } 550 551 const std::vector<CreditCard*>& PersonalDataManager::GetCreditCards() const { 552 return credit_cards_.get(); 553 } 554 555 void PersonalDataManager::Refresh() { 556 LoadProfiles(); 557 LoadCreditCards(); 558 } 559 560 void PersonalDataManager::GetProfileSuggestions( 561 const AutofillType& type, 562 const base::string16& field_contents, 563 bool field_is_autofilled, 564 const std::vector<ServerFieldType>& other_field_types, 565 const base::Callback<bool(const AutofillProfile&)>& filter, 566 std::vector<base::string16>* values, 567 std::vector<base::string16>* labels, 568 std::vector<base::string16>* icons, 569 std::vector<GUIDPair>* guid_pairs) { 570 values->clear(); 571 labels->clear(); 572 icons->clear(); 573 guid_pairs->clear(); 574 575 const std::vector<AutofillProfile*>& profiles = GetProfiles(); 576 std::vector<AutofillProfile*> matched_profiles; 577 for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin(); 578 iter != profiles.end(); ++iter) { 579 AutofillProfile* profile = *iter; 580 581 // The value of the stored data for this field type in the |profile|. 582 std::vector<base::string16> multi_values; 583 profile->GetMultiInfo(type, app_locale_, &multi_values); 584 585 for (size_t i = 0; i < multi_values.size(); ++i) { 586 if (!field_is_autofilled) { 587 // Suggest data that starts with what the user has typed. 588 if (!multi_values[i].empty() && 589 StartsWith(multi_values[i], field_contents, false) && 590 (filter.is_null() || filter.Run(*profile))) { 591 matched_profiles.push_back(profile); 592 values->push_back(multi_values[i]); 593 guid_pairs->push_back(GUIDPair(profile->guid(), i)); 594 } 595 } else { 596 if (multi_values[i].empty()) 597 continue; 598 599 base::string16 profile_value_lower_case( 600 StringToLowerASCII(multi_values[i])); 601 base::string16 field_value_lower_case( 602 StringToLowerASCII(field_contents)); 603 // Phone numbers could be split in US forms, so field value could be 604 // either prefix or suffix of the phone. 605 bool matched_phones = false; 606 if (type.GetStorableType() == PHONE_HOME_NUMBER && 607 !field_value_lower_case.empty() && 608 profile_value_lower_case.find(field_value_lower_case) != 609 base::string16::npos) { 610 matched_phones = true; 611 } 612 613 // Suggest variants of the profile that's already been filled in. 614 if (matched_phones || 615 profile_value_lower_case == field_value_lower_case) { 616 for (size_t j = 0; j < multi_values.size(); ++j) { 617 if (!multi_values[j].empty()) { 618 values->push_back(multi_values[j]); 619 guid_pairs->push_back(GUIDPair(profile->guid(), j)); 620 } 621 } 622 623 // We've added all the values for this profile so move on to the 624 // next. 625 break; 626 } 627 } 628 } 629 } 630 631 if (!field_is_autofilled) { 632 AutofillProfile::CreateInferredLabels( 633 matched_profiles, &other_field_types, 634 type.GetStorableType(), 1, labels); 635 } else { 636 // No sub-labels for previously filled fields. 637 labels->resize(values->size()); 638 } 639 640 // No icons for profile suggestions. 641 icons->resize(values->size()); 642 } 643 644 void PersonalDataManager::GetCreditCardSuggestions( 645 const AutofillType& type, 646 const base::string16& field_contents, 647 std::vector<base::string16>* values, 648 std::vector<base::string16>* labels, 649 std::vector<base::string16>* icons, 650 std::vector<GUIDPair>* guid_pairs) { 651 values->clear(); 652 labels->clear(); 653 icons->clear(); 654 guid_pairs->clear(); 655 656 const std::vector<CreditCard*>& credit_cards = GetCreditCards(); 657 for (std::vector<CreditCard*>::const_iterator iter = credit_cards.begin(); 658 iter != credit_cards.end(); ++iter) { 659 CreditCard* credit_card = *iter; 660 661 // The value of the stored data for this field type in the |credit_card|. 662 base::string16 creditcard_field_value = 663 credit_card->GetInfo(type, app_locale_); 664 if (!creditcard_field_value.empty() && 665 StartsWith(creditcard_field_value, field_contents, false)) { 666 if (type.GetStorableType() == CREDIT_CARD_NUMBER) 667 creditcard_field_value = credit_card->ObfuscatedNumber(); 668 669 base::string16 label; 670 if (credit_card->number().empty()) { 671 // If there is no CC number, return name to show something. 672 label = 673 credit_card->GetInfo(AutofillType(CREDIT_CARD_NAME), app_locale_); 674 } else { 675 label = kCreditCardPrefix; 676 label.append(credit_card->LastFourDigits()); 677 } 678 679 values->push_back(creditcard_field_value); 680 labels->push_back(label); 681 icons->push_back(base::UTF8ToUTF16(credit_card->type())); 682 guid_pairs->push_back(GUIDPair(credit_card->guid(), 0)); 683 } 684 } 685 } 686 687 bool PersonalDataManager::IsAutofillEnabled() const { 688 DCHECK(pref_service_); 689 return pref_service_->GetBoolean(prefs::kAutofillEnabled); 690 } 691 692 std::string PersonalDataManager::CountryCodeForCurrentTimezone() const { 693 return base::CountryCodeForCurrentTimezone(); 694 } 695 696 void PersonalDataManager::SetPrefService(PrefService* pref_service) { 697 enabled_pref_.reset(new BooleanPrefMember); 698 pref_service_ = pref_service; 699 // |pref_service_| can be NULL in tests. 700 if (pref_service_) { 701 enabled_pref_->Init(prefs::kAutofillEnabled, pref_service_, 702 base::Bind(&PersonalDataManager::EnabledPrefChanged, 703 base::Unretained(this))); 704 } 705 } 706 707 // static 708 bool PersonalDataManager::IsValidLearnableProfile( 709 const AutofillProfile& profile, 710 const std::string& app_locale) { 711 if (!IsMinimumAddress(profile, app_locale)) 712 return false; 713 714 base::string16 email = profile.GetRawInfo(EMAIL_ADDRESS); 715 if (!email.empty() && !IsValidEmailAddress(email)) 716 return false; 717 718 // Reject profiles with invalid US state information. 719 if (profile.IsPresentButInvalid(ADDRESS_HOME_STATE)) 720 return false; 721 722 // Reject profiles with invalid US zip information. 723 if (profile.IsPresentButInvalid(ADDRESS_HOME_ZIP)) 724 return false; 725 726 return true; 727 } 728 729 // static 730 std::string PersonalDataManager::MergeProfile( 731 const AutofillProfile& new_profile, 732 const std::vector<AutofillProfile*>& existing_profiles, 733 const std::string& app_locale, 734 std::vector<AutofillProfile>* merged_profiles) { 735 merged_profiles->clear(); 736 737 // Set to true if |existing_profiles| already contains an equivalent profile. 738 bool matching_profile_found = false; 739 std::string guid = new_profile.guid(); 740 741 // If we have already saved this address, merge in any missing values. 742 // Only merge with the first match. 743 for (std::vector<AutofillProfile*>::const_iterator iter = 744 existing_profiles.begin(); 745 iter != existing_profiles.end(); ++iter) { 746 AutofillProfile* existing_profile = *iter; 747 if (!matching_profile_found && 748 !new_profile.PrimaryValue().empty() && 749 StringToLowerASCII(existing_profile->PrimaryValue()) == 750 StringToLowerASCII(new_profile.PrimaryValue())) { 751 // Unverified profiles should always be updated with the newer data, 752 // whereas verified profiles should only ever be overwritten by verified 753 // data. If an automatically aggregated profile would overwrite a 754 // verified profile, just drop it. 755 matching_profile_found = true; 756 guid = existing_profile->guid(); 757 if (!existing_profile->IsVerified() || new_profile.IsVerified()) 758 existing_profile->OverwriteWithOrAddTo(new_profile, app_locale); 759 } 760 merged_profiles->push_back(*existing_profile); 761 } 762 763 // If the new profile was not merged with an existing one, add it to the list. 764 if (!matching_profile_found) 765 merged_profiles->push_back(new_profile); 766 767 return guid; 768 } 769 770 bool PersonalDataManager::IsCountryOfInterest(const std::string& country_code) 771 const { 772 DCHECK_EQ(2U, country_code.size()); 773 774 const std::vector<AutofillProfile*>& profiles = web_profiles(); 775 std::list<std::string> country_codes; 776 for (size_t i = 0; i < profiles.size(); ++i) { 777 country_codes.push_back(StringToLowerASCII(base::UTF16ToASCII( 778 profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY)))); 779 } 780 781 std::string timezone_country = CountryCodeForCurrentTimezone(); 782 if (!timezone_country.empty()) 783 country_codes.push_back(StringToLowerASCII(timezone_country)); 784 785 // Only take the locale into consideration if all else fails. 786 if (country_codes.empty()) { 787 country_codes.push_back(StringToLowerASCII( 788 AutofillCountry::CountryCodeForLocale(app_locale()))); 789 } 790 791 return std::find(country_codes.begin(), country_codes.end(), 792 StringToLowerASCII(country_code)) != country_codes.end(); 793 } 794 795 const std::string& PersonalDataManager::GetDefaultCountryCodeForNewAddress() 796 const { 797 if (default_country_code_.empty()) 798 default_country_code_ = MostCommonCountryCodeFromProfiles(); 799 800 // Failing that, guess based on system timezone. 801 if (default_country_code_.empty()) 802 default_country_code_ = CountryCodeForCurrentTimezone(); 803 804 // Failing that, guess based on locale. 805 if (default_country_code_.empty()) 806 default_country_code_ = AutofillCountry::CountryCodeForLocale(app_locale()); 807 808 return default_country_code_; 809 } 810 811 void PersonalDataManager::SetProfiles(std::vector<AutofillProfile>* profiles) { 812 if (is_off_the_record_) 813 return; 814 815 // Remove empty profiles from input. 816 profiles->erase(std::remove_if(profiles->begin(), profiles->end(), 817 IsEmptyFunctor<AutofillProfile>(app_locale_)), 818 profiles->end()); 819 820 if (!database_.get()) 821 return; 822 823 // Any profiles that are not in the new profile list should be removed from 824 // the web database. 825 for (std::vector<AutofillProfile*>::const_iterator iter = 826 web_profiles_.begin(); 827 iter != web_profiles_.end(); ++iter) { 828 if (!FindByGUID<AutofillProfile>(*profiles, (*iter)->guid())) 829 database_->RemoveAutofillProfile((*iter)->guid()); 830 } 831 832 // Update the web database with the existing profiles. 833 for (std::vector<AutofillProfile>::iterator iter = profiles->begin(); 834 iter != profiles->end(); ++iter) { 835 if (FindByGUID<AutofillProfile>(web_profiles_, iter->guid())) 836 database_->UpdateAutofillProfile(*iter); 837 } 838 839 // Add the new profiles to the web database. Don't add a duplicate. 840 for (std::vector<AutofillProfile>::iterator iter = profiles->begin(); 841 iter != profiles->end(); ++iter) { 842 if (!FindByGUID<AutofillProfile>(web_profiles_, iter->guid()) && 843 !FindByContents(web_profiles_, *iter)) 844 database_->AddAutofillProfile(*iter); 845 } 846 847 // Copy in the new profiles. 848 web_profiles_.clear(); 849 for (std::vector<AutofillProfile>::iterator iter = profiles->begin(); 850 iter != profiles->end(); ++iter) { 851 web_profiles_.push_back(new AutofillProfile(*iter)); 852 } 853 854 // Refresh our local cache and send notifications to observers. 855 Refresh(); 856 } 857 858 void PersonalDataManager::SetCreditCards( 859 std::vector<CreditCard>* credit_cards) { 860 if (is_off_the_record_) 861 return; 862 863 // Remove empty credit cards from input. 864 credit_cards->erase(std::remove_if(credit_cards->begin(), credit_cards->end(), 865 IsEmptyFunctor<CreditCard>(app_locale_)), 866 credit_cards->end()); 867 868 if (!database_.get()) 869 return; 870 871 // Any credit cards that are not in the new credit card list should be 872 // removed. 873 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin(); 874 iter != credit_cards_.end(); ++iter) { 875 if (!FindByGUID<CreditCard>(*credit_cards, (*iter)->guid())) 876 database_->RemoveCreditCard((*iter)->guid()); 877 } 878 879 // Update the web database with the existing credit cards. 880 for (std::vector<CreditCard>::iterator iter = credit_cards->begin(); 881 iter != credit_cards->end(); ++iter) { 882 if (FindByGUID<CreditCard>(credit_cards_, iter->guid())) 883 database_->UpdateCreditCard(*iter); 884 } 885 886 // Add the new credit cards to the web database. Don't add a duplicate. 887 for (std::vector<CreditCard>::iterator iter = credit_cards->begin(); 888 iter != credit_cards->end(); ++iter) { 889 if (!FindByGUID<CreditCard>(credit_cards_, iter->guid()) && 890 !FindByContents(credit_cards_, *iter)) 891 database_->AddCreditCard(*iter); 892 } 893 894 // Copy in the new credit cards. 895 credit_cards_.clear(); 896 for (std::vector<CreditCard>::iterator iter = credit_cards->begin(); 897 iter != credit_cards->end(); ++iter) { 898 credit_cards_.push_back(new CreditCard(*iter)); 899 } 900 901 // Refresh our local cache and send notifications to observers. 902 Refresh(); 903 } 904 905 void PersonalDataManager::LoadProfiles() { 906 if (!database_.get()) { 907 NOTREACHED(); 908 return; 909 } 910 911 CancelPendingQuery(&pending_profiles_query_); 912 913 pending_profiles_query_ = database_->GetAutofillProfiles(this); 914 } 915 916 // Win, Linux, and iOS implementations do nothing. Mac and Android 917 // implementations fill in the contents of |auxiliary_profiles_|. 918 #if defined(OS_IOS) || (!defined(OS_MACOSX) && !defined(OS_ANDROID)) 919 void PersonalDataManager::LoadAuxiliaryProfiles() const { 920 } 921 #endif 922 923 void PersonalDataManager::LoadCreditCards() { 924 if (!database_.get()) { 925 NOTREACHED(); 926 return; 927 } 928 929 CancelPendingQuery(&pending_creditcards_query_); 930 931 pending_creditcards_query_ = database_->GetCreditCards(this); 932 } 933 934 void PersonalDataManager::ReceiveLoadedProfiles(WebDataServiceBase::Handle h, 935 const WDTypedResult* result) { 936 DCHECK_EQ(pending_profiles_query_, h); 937 938 pending_profiles_query_ = 0; 939 web_profiles_.clear(); 940 941 const WDResult<std::vector<AutofillProfile*> >* r = 942 static_cast<const WDResult<std::vector<AutofillProfile*> >*>(result); 943 944 std::vector<AutofillProfile*> profiles = r->GetValue(); 945 for (std::vector<AutofillProfile*>::iterator iter = profiles.begin(); 946 iter != profiles.end(); ++iter) { 947 web_profiles_.push_back(*iter); 948 } 949 950 LogProfileCount(); 951 } 952 953 void PersonalDataManager::ReceiveLoadedCreditCards( 954 WebDataServiceBase::Handle h, const WDTypedResult* result) { 955 DCHECK_EQ(pending_creditcards_query_, h); 956 957 pending_creditcards_query_ = 0; 958 credit_cards_.clear(); 959 960 const WDResult<std::vector<CreditCard*> >* r = 961 static_cast<const WDResult<std::vector<CreditCard*> >*>(result); 962 963 std::vector<CreditCard*> credit_cards = r->GetValue(); 964 for (std::vector<CreditCard*>::iterator iter = credit_cards.begin(); 965 iter != credit_cards.end(); ++iter) { 966 credit_cards_.push_back(*iter); 967 } 968 } 969 970 void PersonalDataManager::CancelPendingQuery( 971 WebDataServiceBase::Handle* handle) { 972 if (*handle) { 973 if (!database_.get()) { 974 NOTREACHED(); 975 return; 976 } 977 database_->CancelRequest(*handle); 978 } 979 *handle = 0; 980 } 981 982 std::string PersonalDataManager::SaveImportedProfile( 983 const AutofillProfile& imported_profile) { 984 if (is_off_the_record_) 985 return std::string(); 986 987 // Don't save a web profile if the data in the profile is a subset of an 988 // auxiliary profile. 989 for (std::vector<AutofillProfile*>::const_iterator iter = 990 auxiliary_profiles_.begin(); 991 iter != auxiliary_profiles_.end(); ++iter) { 992 if (imported_profile.IsSubsetOf(**iter, app_locale_)) 993 return (*iter)->guid(); 994 } 995 996 std::vector<AutofillProfile> profiles; 997 std::string guid = 998 MergeProfile(imported_profile, web_profiles_.get(), app_locale_, 999 &profiles); 1000 SetProfiles(&profiles); 1001 return guid; 1002 } 1003 1004 void PersonalDataManager::NotifyPersonalDataChanged() { 1005 FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_, 1006 OnPersonalDataChanged()); 1007 } 1008 1009 std::string PersonalDataManager::SaveImportedCreditCard( 1010 const CreditCard& imported_card) { 1011 DCHECK(!imported_card.number().empty()); 1012 if (is_off_the_record_) 1013 return std::string(); 1014 1015 // Set to true if |imported_card| is merged into the credit card list. 1016 bool merged = false; 1017 1018 std::string guid = imported_card.guid(); 1019 std::vector<CreditCard> credit_cards; 1020 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin(); 1021 iter != credit_cards_.end(); 1022 ++iter) { 1023 CreditCard* card = *iter; 1024 // If |imported_card| has not yet been merged, check whether it should be 1025 // with the current |card|. 1026 if (!merged && card->UpdateFromImportedCard(imported_card, app_locale_)) { 1027 guid = card->guid(); 1028 merged = true; 1029 } 1030 1031 credit_cards.push_back(*card); 1032 } 1033 1034 if (!merged) 1035 credit_cards.push_back(imported_card); 1036 1037 SetCreditCards(&credit_cards); 1038 return guid; 1039 } 1040 1041 void PersonalDataManager::LogProfileCount() const { 1042 if (!has_logged_profile_count_) { 1043 metric_logger_->LogStoredProfileCount(web_profiles_.size()); 1044 has_logged_profile_count_ = true; 1045 } 1046 } 1047 1048 std::string PersonalDataManager::MostCommonCountryCodeFromProfiles() const { 1049 if (!IsAutofillEnabled()) 1050 return std::string(); 1051 1052 // Count up country codes from existing profiles. 1053 std::map<std::string, int> votes; 1054 // TODO(estade): can we make this GetProfiles() instead? It seems to cause 1055 // errors in tests on mac trybots. See http://crbug.com/57221 1056 const std::vector<AutofillProfile*>& profiles = web_profiles(); 1057 std::vector<std::string> country_codes; 1058 AutofillCountry::GetAvailableCountries(&country_codes); 1059 for (size_t i = 0; i < profiles.size(); ++i) { 1060 std::string country_code = StringToUpperASCII(base::UTF16ToASCII( 1061 profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY))); 1062 1063 if (std::find(country_codes.begin(), country_codes.end(), country_code) != 1064 country_codes.end()) { 1065 // Verified profiles count 100x more than unverified ones. 1066 votes[country_code] += profiles[i]->IsVerified() ? 100 : 1; 1067 } 1068 } 1069 1070 // Take the most common country code. 1071 if (!votes.empty()) { 1072 std::map<std::string, int>::iterator iter = 1073 std::max_element(votes.begin(), votes.end(), CompareVotes); 1074 return iter->first; 1075 } 1076 1077 return std::string(); 1078 } 1079 1080 void PersonalDataManager::EnabledPrefChanged() { 1081 default_country_code_.clear(); 1082 NotifyPersonalDataChanged(); 1083 } 1084 1085 } // namespace autofill 1086