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