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