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