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