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.
5 #include "components/autofill/core/browser/personal_data_manager.h"
11 #include "base/i18n/timezone.h"
12 #include "base/logging.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/prefs/pref_service.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "components/autofill/core/browser/autofill-inl.h"
19 #include "components/autofill/core/browser/autofill_country.h"
20 #include "components/autofill/core/browser/autofill_field.h"
21 #include "components/autofill/core/browser/form_structure.h"
22 #include "components/autofill/core/browser/personal_data_manager_observer.h"
23 #include "components/autofill/core/browser/phone_number.h"
24 #include "components/autofill/core/browser/phone_number_i18n.h"
25 #include "components/autofill/core/browser/validation.h"
26 #include "components/autofill/core/common/autofill_pref_names.h"
31 const base::string16::value_type kCreditCardPrefix[] = {'*', 0};
34 class FormGroupMatchesByGUIDFunctor {
36 explicit FormGroupMatchesByGUIDFunctor(const std::string& guid)
40 bool operator()(const T& form_group) {
41 return form_group.guid() == guid_;
44 bool operator()(const T* form_group) {
45 return form_group->guid() == guid_;
49 const std::string guid_;
52 template<typename T, typename C>
53 typename C::const_iterator FindElementByGUID(const C& container,
54 const std::string& guid) {
55 return std::find_if(container.begin(),
57 FormGroupMatchesByGUIDFunctor<T>(guid));
60 template<typename T, typename C>
61 bool FindByGUID(const C& container, const std::string& guid) {
62 return FindElementByGUID<T>(container, guid) != container.end();
66 class IsEmptyFunctor {
68 explicit IsEmptyFunctor(const std::string& app_locale)
69 : app_locale_(app_locale) {
72 bool operator()(const T& form_group) {
73 return form_group.IsEmpty(app_locale_);
77 const std::string app_locale_;
80 // Returns true if minimum requirements for import of a given |profile| have
81 // been met. An address submitted via a form must have at least the fields
82 // required as determined by its country code.
83 // No verification of validity of the contents is preformed. This is an
84 // existence check only.
85 bool IsMinimumAddress(const AutofillProfile& profile,
86 const std::string& app_locale) {
87 // All countries require at least one address line.
88 if (profile.GetRawInfo(ADDRESS_HOME_LINE1).empty())
91 std::string country_code =
92 base::UTF16ToASCII(profile.GetRawInfo(ADDRESS_HOME_COUNTRY));
93 if (country_code.empty())
94 country_code = AutofillCountry::CountryCodeForLocale(app_locale);
96 AutofillCountry country(country_code, app_locale);
98 if (country.requires_city() && profile.GetRawInfo(ADDRESS_HOME_CITY).empty())
101 if (country.requires_state() &&
102 profile.GetRawInfo(ADDRESS_HOME_STATE).empty())
105 if (country.requires_zip() && profile.GetRawInfo(ADDRESS_HOME_ZIP).empty())
111 // Return true if the |field_type| and |value| are valid within the context
112 // of importing a form.
113 bool IsValidFieldTypeAndValue(const std::set<ServerFieldType>& types_seen,
114 ServerFieldType field_type,
115 const base::string16& value) {
116 // Abandon the import if two fields of the same type are encountered.
117 // This indicates ambiguous data or miscategorization of types.
118 // Make an exception for PHONE_HOME_NUMBER however as both prefix and
119 // suffix are stored against this type, and for EMAIL_ADDRESS because it is
120 // common to see second 'confirm email address' fields on forms.
121 if (types_seen.count(field_type) &&
122 field_type != PHONE_HOME_NUMBER &&
123 field_type != EMAIL_ADDRESS)
126 // Abandon the import if an email address value shows up in a field that is
127 // not an email address.
128 if (field_type != EMAIL_ADDRESS && IsValidEmailAddress(value))
134 // A helper function for finding the maximum value in a string->int map.
135 static bool CompareVotes(const std::pair<std::string, int>& a,
136 const std::pair<std::string, int>& b) {
137 return a.second < b.second;
142 PersonalDataManager::PersonalDataManager(const std::string& app_locale)
144 is_data_loaded_(false),
145 pending_profiles_query_(0),
146 pending_creditcards_query_(0),
147 app_locale_(app_locale),
148 metric_logger_(new AutofillMetrics),
150 is_off_the_record_(false),
151 has_logged_profile_count_(false) {}
153 void PersonalDataManager::Init(scoped_refptr<AutofillWebDataService> database,
154 PrefService* pref_service,
155 bool is_off_the_record) {
156 database_ = database;
157 SetPrefService(pref_service);
158 is_off_the_record_ = is_off_the_record;
160 if (!is_off_the_record_)
161 metric_logger_->LogIsAutofillEnabledAtStartup(IsAutofillEnabled());
163 // WebDataService may not be available in tests.
164 if (!database_.get())
170 database_->AddObserver(this);
173 PersonalDataManager::~PersonalDataManager() {
174 CancelPendingQuery(&pending_profiles_query_);
175 CancelPendingQuery(&pending_creditcards_query_);
178 database_->RemoveObserver(this);
181 void PersonalDataManager::OnWebDataServiceRequestDone(
182 WebDataServiceBase::Handle h,
183 const WDTypedResult* result) {
184 DCHECK(pending_profiles_query_ || pending_creditcards_query_);
187 // Error from the web database.
188 if (h == pending_creditcards_query_)
189 pending_creditcards_query_ = 0;
190 else if (h == pending_profiles_query_)
191 pending_profiles_query_ = 0;
195 switch (result->GetType()) {
196 case AUTOFILL_PROFILES_RESULT:
197 ReceiveLoadedProfiles(h, result);
199 case AUTOFILL_CREDITCARDS_RESULT:
200 ReceiveLoadedCreditCards(h, result);
206 // If both requests have responded, then all personal data is loaded.
207 if (pending_profiles_query_ == 0 && pending_creditcards_query_ == 0) {
208 is_data_loaded_ = true;
209 NotifyPersonalDataChanged();
213 void PersonalDataManager::AutofillMultipleChanged() {
217 void PersonalDataManager::AddObserver(PersonalDataManagerObserver* observer) {
218 observers_.AddObserver(observer);
221 void PersonalDataManager::RemoveObserver(
222 PersonalDataManagerObserver* observer) {
223 observers_.RemoveObserver(observer);
226 bool PersonalDataManager::ImportFormData(
227 const FormStructure& form,
228 scoped_ptr<CreditCard>* imported_credit_card) {
229 scoped_ptr<AutofillProfile> imported_profile(new AutofillProfile);
230 scoped_ptr<CreditCard> local_imported_credit_card(new CreditCard);
232 const std::string origin = form.source_url().spec();
233 imported_profile->set_origin(origin);
234 local_imported_credit_card->set_origin(origin);
236 // Parse the form and construct a profile based on the information that is
237 // possible to import.
238 int importable_credit_card_fields = 0;
240 // Detect and discard forms with multiple fields of the same type.
241 // TODO(isherman): Some types are overlapping but not equal, e.g. phone number
242 // parts, address parts.
243 std::set<ServerFieldType> types_seen;
245 // We only set complete phone, so aggregate phone parts in these vars and set
246 // complete at the end.
247 PhoneNumber::PhoneCombineHelper home;
249 for (size_t i = 0; i < form.field_count(); ++i) {
250 const AutofillField* field = form.field(i);
251 base::string16 value;
252 base::TrimWhitespace(field->value, base::TRIM_ALL, &value);
254 // If we don't know the type of the field, or the user hasn't entered any
255 // information into the field, then skip it.
256 if (!field->IsFieldFillable() || value.empty())
259 AutofillType field_type = field->Type();
260 ServerFieldType server_field_type = field_type.GetStorableType();
261 FieldTypeGroup group(field_type.group());
263 // There can be multiple email fields (e.g. in the case of 'confirm email'
264 // fields) but they must all contain the same value, else the profile is
266 if (server_field_type == EMAIL_ADDRESS) {
267 if (types_seen.count(server_field_type) &&
268 imported_profile->GetRawInfo(EMAIL_ADDRESS) != value) {
269 imported_profile.reset();
274 // If the |field_type| and |value| don't pass basic validity checks then
275 // abandon the import.
276 if (!IsValidFieldTypeAndValue(types_seen, server_field_type, value)) {
277 imported_profile.reset();
278 local_imported_credit_card.reset();
282 types_seen.insert(server_field_type);
284 if (group == CREDIT_CARD) {
285 if (LowerCaseEqualsASCII(field->form_control_type, "month")) {
286 DCHECK_EQ(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, server_field_type);
287 local_imported_credit_card->SetInfoForMonthInputType(value);
289 local_imported_credit_card->SetInfo(field_type, value, app_locale_);
291 ++importable_credit_card_fields;
293 // We need to store phone data in the variables, before building the whole
294 // number at the end. The rest of the fields are set "as is".
295 // If the fields are not the phone fields in question home.SetInfo() is
296 // going to return false.
297 if (!home.SetInfo(field_type, value))
298 imported_profile->SetInfo(field_type, value, app_locale_);
300 // Reject profiles with invalid country information.
301 if (server_field_type == ADDRESS_HOME_COUNTRY &&
303 imported_profile->GetRawInfo(ADDRESS_HOME_COUNTRY).empty()) {
304 imported_profile.reset();
310 // Construct the phone number. Reject the profile if the number is invalid.
311 if (imported_profile.get() && !home.IsEmpty()) {
312 base::string16 constructed_number;
313 if (!home.ParseNumber(*imported_profile, app_locale_,
314 &constructed_number) ||
315 !imported_profile->SetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER),
318 imported_profile.reset();
322 // Reject the profile if minimum address and validation requirements are not
324 if (imported_profile.get() &&
325 !IsValidLearnableProfile(*imported_profile, app_locale_))
326 imported_profile.reset();
328 // Reject the credit card if we did not detect enough filled credit card
329 // fields or if the credit card number does not seem to be valid.
330 if (local_imported_credit_card.get() &&
331 !local_imported_credit_card->IsComplete()) {
332 local_imported_credit_card.reset();
335 // Don't import if we already have this info.
336 // Don't present an infobar if we have already saved this card number.
337 bool merged_credit_card = false;
338 if (local_imported_credit_card.get()) {
339 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin();
340 iter != credit_cards_.end();
342 // Make a local copy so that the data in |credit_cards_| isn't modified
343 // directly by the UpdateFromImportedCard() call.
344 CreditCard card = **iter;
345 if (card.UpdateFromImportedCard(*local_imported_credit_card.get(),
347 merged_credit_card = true;
348 UpdateCreditCard(card);
349 local_imported_credit_card.reset();
355 if (imported_profile.get()) {
356 // We always save imported profiles.
357 SaveImportedProfile(*imported_profile);
359 *imported_credit_card = local_imported_credit_card.Pass();
361 if (imported_profile.get() || *imported_credit_card || merged_credit_card)
364 FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_,
365 OnInsufficientFormData());
369 void PersonalDataManager::AddProfile(const AutofillProfile& profile) {
370 if (is_off_the_record_)
373 if (profile.IsEmpty(app_locale_))
376 // Don't add an existing profile.
377 if (FindByGUID<AutofillProfile>(web_profiles_, profile.guid()))
380 if (!database_.get())
383 // Don't add a duplicate.
384 if (FindByContents(web_profiles_, profile))
387 // Add the new profile to the web database.
388 database_->AddAutofillProfile(profile);
390 // Refresh our local cache and send notifications to observers.
394 void PersonalDataManager::UpdateProfile(const AutofillProfile& profile) {
395 if (is_off_the_record_)
398 AutofillProfile* existing_profile = GetProfileByGUID(profile.guid());
399 if (!existing_profile)
402 // Don't overwrite the origin for a profile that is already stored.
403 if (existing_profile->EqualsSansOrigin(profile))
406 if (profile.IsEmpty(app_locale_)) {
407 RemoveByGUID(profile.guid());
411 if (!database_.get())
415 database_->UpdateAutofillProfile(profile);
417 // Refresh our local cache and send notifications to observers.
421 AutofillProfile* PersonalDataManager::GetProfileByGUID(
422 const std::string& guid) {
423 const std::vector<AutofillProfile*>& profiles = GetProfiles();
424 std::vector<AutofillProfile*>::const_iterator iter =
425 FindElementByGUID<AutofillProfile>(profiles, guid);
426 return (iter != profiles.end()) ? *iter : NULL;
429 void PersonalDataManager::AddCreditCard(const CreditCard& credit_card) {
430 if (is_off_the_record_)
433 if (credit_card.IsEmpty(app_locale_))
436 if (FindByGUID<CreditCard>(credit_cards_, credit_card.guid()))
439 if (!database_.get())
442 // Don't add a duplicate.
443 if (FindByContents(credit_cards_, credit_card))
446 // Add the new credit card to the web database.
447 database_->AddCreditCard(credit_card);
449 // Refresh our local cache and send notifications to observers.
453 void PersonalDataManager::UpdateCreditCard(const CreditCard& credit_card) {
454 if (is_off_the_record_)
457 CreditCard* existing_credit_card = GetCreditCardByGUID(credit_card.guid());
458 if (!existing_credit_card)
461 // Don't overwrite the origin for a credit card that is already stored.
462 if (existing_credit_card->Compare(credit_card) == 0)
465 if (credit_card.IsEmpty(app_locale_)) {
466 RemoveByGUID(credit_card.guid());
470 if (!database_.get())
474 database_->UpdateCreditCard(credit_card);
476 // Refresh our local cache and send notifications to observers.
480 void PersonalDataManager::RemoveByGUID(const std::string& guid) {
481 if (is_off_the_record_)
484 bool is_credit_card = FindByGUID<CreditCard>(credit_cards_, guid);
485 bool is_profile = !is_credit_card &&
486 FindByGUID<AutofillProfile>(web_profiles_, guid);
487 if (!is_credit_card && !is_profile)
490 if (!database_.get())
494 database_->RemoveCreditCard(guid);
496 database_->RemoveAutofillProfile(guid);
498 // Refresh our local cache and send notifications to observers.
502 CreditCard* PersonalDataManager::GetCreditCardByGUID(const std::string& guid) {
503 const std::vector<CreditCard*>& credit_cards = GetCreditCards();
504 std::vector<CreditCard*>::const_iterator iter =
505 FindElementByGUID<CreditCard>(credit_cards, guid);
506 return (iter != credit_cards.end()) ? *iter : NULL;
509 void PersonalDataManager::GetNonEmptyTypes(
510 ServerFieldTypeSet* non_empty_types) {
511 const std::vector<AutofillProfile*>& profiles = GetProfiles();
512 for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin();
513 iter != profiles.end(); ++iter) {
514 (*iter)->GetNonEmptyTypes(app_locale_, non_empty_types);
517 for (ScopedVector<CreditCard>::const_iterator iter = credit_cards_.begin();
518 iter != credit_cards_.end(); ++iter) {
519 (*iter)->GetNonEmptyTypes(app_locale_, non_empty_types);
523 bool PersonalDataManager::IsDataLoaded() const {
524 return is_data_loaded_;
527 const std::vector<AutofillProfile*>& PersonalDataManager::GetProfiles() const {
528 if (!pref_service_->GetBoolean(prefs::kAutofillAuxiliaryProfilesEnabled)) {
529 return web_profiles();
534 // Populates |auxiliary_profiles_|.
535 LoadAuxiliaryProfiles();
537 profiles_.insert(profiles_.end(), web_profiles_.begin(), web_profiles_.end());
538 profiles_.insert(profiles_.end(),
539 auxiliary_profiles_.begin(), auxiliary_profiles_.end());
543 const std::vector<AutofillProfile*>& PersonalDataManager::web_profiles() const {
544 return web_profiles_.get();
547 const std::vector<CreditCard*>& PersonalDataManager::GetCreditCards() const {
548 return credit_cards_.get();
551 void PersonalDataManager::Refresh() {
556 void PersonalDataManager::GetProfileSuggestions(
557 const AutofillType& type,
558 const base::string16& field_contents,
559 bool field_is_autofilled,
560 const std::vector<ServerFieldType>& other_field_types,
561 const base::Callback<bool(const AutofillProfile&)>& filter,
562 std::vector<base::string16>* values,
563 std::vector<base::string16>* labels,
564 std::vector<base::string16>* icons,
565 std::vector<GUIDPair>* guid_pairs) {
571 const std::vector<AutofillProfile*>& profiles = GetProfiles();
572 std::vector<AutofillProfile*> matched_profiles;
573 for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin();
574 iter != profiles.end(); ++iter) {
575 AutofillProfile* profile = *iter;
577 // The value of the stored data for this field type in the |profile|.
578 std::vector<base::string16> multi_values;
579 profile->GetMultiInfo(type, app_locale_, &multi_values);
581 for (size_t i = 0; i < multi_values.size(); ++i) {
582 if (!field_is_autofilled) {
583 // Suggest data that starts with what the user has typed.
584 if (!multi_values[i].empty() &&
585 StartsWith(multi_values[i], field_contents, false) &&
586 (filter.is_null() || filter.Run(*profile))) {
587 matched_profiles.push_back(profile);
588 values->push_back(multi_values[i]);
589 guid_pairs->push_back(GUIDPair(profile->guid(), i));
592 if (multi_values[i].empty())
595 base::string16 profile_value_lower_case(
596 StringToLowerASCII(multi_values[i]));
597 base::string16 field_value_lower_case(
598 StringToLowerASCII(field_contents));
599 // Phone numbers could be split in US forms, so field value could be
600 // either prefix or suffix of the phone.
601 bool matched_phones = false;
602 if (type.GetStorableType() == PHONE_HOME_NUMBER &&
603 !field_value_lower_case.empty() &&
604 profile_value_lower_case.find(field_value_lower_case) !=
605 base::string16::npos) {
606 matched_phones = true;
609 // Suggest variants of the profile that's already been filled in.
610 if (matched_phones ||
611 profile_value_lower_case == field_value_lower_case) {
612 for (size_t j = 0; j < multi_values.size(); ++j) {
613 if (!multi_values[j].empty()) {
614 values->push_back(multi_values[j]);
615 guid_pairs->push_back(GUIDPair(profile->guid(), j));
619 // We've added all the values for this profile so move on to the
627 if (!field_is_autofilled) {
628 AutofillProfile::CreateInferredLabels(
629 matched_profiles, &other_field_types,
630 type.GetStorableType(), 1, labels);
632 // No sub-labels for previously filled fields.
633 labels->resize(values->size());
636 // No icons for profile suggestions.
637 icons->resize(values->size());
640 void PersonalDataManager::GetCreditCardSuggestions(
641 const AutofillType& type,
642 const base::string16& field_contents,
643 std::vector<base::string16>* values,
644 std::vector<base::string16>* labels,
645 std::vector<base::string16>* icons,
646 std::vector<GUIDPair>* guid_pairs) {
652 const std::vector<CreditCard*>& credit_cards = GetCreditCards();
653 for (std::vector<CreditCard*>::const_iterator iter = credit_cards.begin();
654 iter != credit_cards.end(); ++iter) {
655 CreditCard* credit_card = *iter;
657 // The value of the stored data for this field type in the |credit_card|.
658 base::string16 creditcard_field_value =
659 credit_card->GetInfo(type, app_locale_);
660 if (!creditcard_field_value.empty() &&
661 StartsWith(creditcard_field_value, field_contents, false)) {
662 if (type.GetStorableType() == CREDIT_CARD_NUMBER)
663 creditcard_field_value = credit_card->ObfuscatedNumber();
665 base::string16 label;
666 if (credit_card->number().empty()) {
667 // If there is no CC number, return name to show something.
669 credit_card->GetInfo(AutofillType(CREDIT_CARD_NAME), app_locale_);
671 label = kCreditCardPrefix;
672 label.append(credit_card->LastFourDigits());
675 values->push_back(creditcard_field_value);
676 labels->push_back(label);
677 icons->push_back(base::UTF8ToUTF16(credit_card->type()));
678 guid_pairs->push_back(GUIDPair(credit_card->guid(), 0));
683 bool PersonalDataManager::IsAutofillEnabled() const {
684 DCHECK(pref_service_);
685 return pref_service_->GetBoolean(prefs::kAutofillEnabled);
688 std::string PersonalDataManager::CountryCodeForCurrentTimezone() const {
689 return base::CountryCodeForCurrentTimezone();
692 void PersonalDataManager::SetPrefService(PrefService* pref_service) {
693 enabled_pref_.reset(new BooleanPrefMember);
694 pref_service_ = pref_service;
695 // |pref_service_| can be NULL in tests.
697 enabled_pref_->Init(prefs::kAutofillEnabled, pref_service_,
698 base::Bind(&PersonalDataManager::EnabledPrefChanged,
699 base::Unretained(this)));
704 bool PersonalDataManager::IsValidLearnableProfile(
705 const AutofillProfile& profile,
706 const std::string& app_locale) {
707 if (!IsMinimumAddress(profile, app_locale))
710 base::string16 email = profile.GetRawInfo(EMAIL_ADDRESS);
711 if (!email.empty() && !IsValidEmailAddress(email))
714 // Reject profiles with invalid US state information.
715 if (profile.IsPresentButInvalid(ADDRESS_HOME_STATE))
718 // Reject profiles with invalid US zip information.
719 if (profile.IsPresentButInvalid(ADDRESS_HOME_ZIP))
726 std::string PersonalDataManager::MergeProfile(
727 const AutofillProfile& new_profile,
728 const std::vector<AutofillProfile*>& existing_profiles,
729 const std::string& app_locale,
730 std::vector<AutofillProfile>* merged_profiles) {
731 merged_profiles->clear();
733 // Set to true if |existing_profiles| already contains an equivalent profile.
734 bool matching_profile_found = false;
735 std::string guid = new_profile.guid();
737 // If we have already saved this address, merge in any missing values.
738 // Only merge with the first match.
739 for (std::vector<AutofillProfile*>::const_iterator iter =
740 existing_profiles.begin();
741 iter != existing_profiles.end(); ++iter) {
742 AutofillProfile* existing_profile = *iter;
743 if (!matching_profile_found &&
744 !new_profile.PrimaryValue().empty() &&
745 StringToLowerASCII(existing_profile->PrimaryValue()) ==
746 StringToLowerASCII(new_profile.PrimaryValue())) {
747 // Unverified profiles should always be updated with the newer data,
748 // whereas verified profiles should only ever be overwritten by verified
749 // data. If an automatically aggregated profile would overwrite a
750 // verified profile, just drop it.
751 matching_profile_found = true;
752 guid = existing_profile->guid();
753 if (!existing_profile->IsVerified() || new_profile.IsVerified())
754 existing_profile->OverwriteWithOrAddTo(new_profile, app_locale);
756 merged_profiles->push_back(*existing_profile);
759 // If the new profile was not merged with an existing one, add it to the list.
760 if (!matching_profile_found)
761 merged_profiles->push_back(new_profile);
766 bool PersonalDataManager::IsCountryOfInterest(const std::string& country_code)
768 DCHECK_EQ(2U, country_code.size());
770 const std::vector<AutofillProfile*>& profiles = web_profiles();
771 std::list<std::string> country_codes;
772 for (size_t i = 0; i < profiles.size(); ++i) {
773 country_codes.push_back(StringToLowerASCII(base::UTF16ToASCII(
774 profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY))));
777 std::string timezone_country = CountryCodeForCurrentTimezone();
778 if (!timezone_country.empty())
779 country_codes.push_back(StringToLowerASCII(timezone_country));
781 // Only take the locale into consideration if all else fails.
782 if (country_codes.empty()) {
783 country_codes.push_back(StringToLowerASCII(
784 AutofillCountry::CountryCodeForLocale(app_locale())));
787 return std::find(country_codes.begin(), country_codes.end(),
788 StringToLowerASCII(country_code)) != country_codes.end();
791 const std::string& PersonalDataManager::GetDefaultCountryCodeForNewAddress()
793 if (default_country_code_.empty())
794 default_country_code_ = MostCommonCountryCodeFromProfiles();
796 // Failing that, guess based on system timezone.
797 if (default_country_code_.empty())
798 default_country_code_ = CountryCodeForCurrentTimezone();
800 // Failing that, guess based on locale.
801 if (default_country_code_.empty())
802 default_country_code_ = AutofillCountry::CountryCodeForLocale(app_locale());
804 return default_country_code_;
807 void PersonalDataManager::SetProfiles(std::vector<AutofillProfile>* profiles) {
808 if (is_off_the_record_)
811 // Remove empty profiles from input.
812 profiles->erase(std::remove_if(profiles->begin(), profiles->end(),
813 IsEmptyFunctor<AutofillProfile>(app_locale_)),
816 if (!database_.get())
819 // Any profiles that are not in the new profile list should be removed from
821 for (std::vector<AutofillProfile*>::const_iterator iter =
822 web_profiles_.begin();
823 iter != web_profiles_.end(); ++iter) {
824 if (!FindByGUID<AutofillProfile>(*profiles, (*iter)->guid()))
825 database_->RemoveAutofillProfile((*iter)->guid());
828 // Update the web database with the existing profiles.
829 for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
830 iter != profiles->end(); ++iter) {
831 if (FindByGUID<AutofillProfile>(web_profiles_, iter->guid()))
832 database_->UpdateAutofillProfile(*iter);
835 // Add the new profiles to the web database. Don't add a duplicate.
836 for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
837 iter != profiles->end(); ++iter) {
838 if (!FindByGUID<AutofillProfile>(web_profiles_, iter->guid()) &&
839 !FindByContents(web_profiles_, *iter))
840 database_->AddAutofillProfile(*iter);
843 // Copy in the new profiles.
844 web_profiles_.clear();
845 for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
846 iter != profiles->end(); ++iter) {
847 web_profiles_.push_back(new AutofillProfile(*iter));
850 // Refresh our local cache and send notifications to observers.
854 void PersonalDataManager::SetCreditCards(
855 std::vector<CreditCard>* credit_cards) {
856 if (is_off_the_record_)
859 // Remove empty credit cards from input.
860 credit_cards->erase(std::remove_if(credit_cards->begin(), credit_cards->end(),
861 IsEmptyFunctor<CreditCard>(app_locale_)),
862 credit_cards->end());
864 if (!database_.get())
867 // Any credit cards that are not in the new credit card list should be
869 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin();
870 iter != credit_cards_.end(); ++iter) {
871 if (!FindByGUID<CreditCard>(*credit_cards, (*iter)->guid()))
872 database_->RemoveCreditCard((*iter)->guid());
875 // Update the web database with the existing credit cards.
876 for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
877 iter != credit_cards->end(); ++iter) {
878 if (FindByGUID<CreditCard>(credit_cards_, iter->guid()))
879 database_->UpdateCreditCard(*iter);
882 // Add the new credit cards to the web database. Don't add a duplicate.
883 for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
884 iter != credit_cards->end(); ++iter) {
885 if (!FindByGUID<CreditCard>(credit_cards_, iter->guid()) &&
886 !FindByContents(credit_cards_, *iter))
887 database_->AddCreditCard(*iter);
890 // Copy in the new credit cards.
891 credit_cards_.clear();
892 for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
893 iter != credit_cards->end(); ++iter) {
894 credit_cards_.push_back(new CreditCard(*iter));
897 // Refresh our local cache and send notifications to observers.
901 void PersonalDataManager::LoadProfiles() {
902 if (!database_.get()) {
907 CancelPendingQuery(&pending_profiles_query_);
909 pending_profiles_query_ = database_->GetAutofillProfiles(this);
912 // Win, Linux, and iOS implementations do nothing. Mac and Android
913 // implementations fill in the contents of |auxiliary_profiles_|.
914 #if defined(OS_IOS) || (!defined(OS_MACOSX) && !defined(OS_ANDROID))
915 void PersonalDataManager::LoadAuxiliaryProfiles() const {
919 void PersonalDataManager::LoadCreditCards() {
920 if (!database_.get()) {
925 CancelPendingQuery(&pending_creditcards_query_);
927 pending_creditcards_query_ = database_->GetCreditCards(this);
930 void PersonalDataManager::ReceiveLoadedProfiles(WebDataServiceBase::Handle h,
931 const WDTypedResult* result) {
932 DCHECK_EQ(pending_profiles_query_, h);
934 pending_profiles_query_ = 0;
935 web_profiles_.clear();
937 const WDResult<std::vector<AutofillProfile*> >* r =
938 static_cast<const WDResult<std::vector<AutofillProfile*> >*>(result);
940 std::vector<AutofillProfile*> profiles = r->GetValue();
941 for (std::vector<AutofillProfile*>::iterator iter = profiles.begin();
942 iter != profiles.end(); ++iter) {
943 web_profiles_.push_back(*iter);
949 void PersonalDataManager::ReceiveLoadedCreditCards(
950 WebDataServiceBase::Handle h, const WDTypedResult* result) {
951 DCHECK_EQ(pending_creditcards_query_, h);
953 pending_creditcards_query_ = 0;
954 credit_cards_.clear();
956 const WDResult<std::vector<CreditCard*> >* r =
957 static_cast<const WDResult<std::vector<CreditCard*> >*>(result);
959 std::vector<CreditCard*> credit_cards = r->GetValue();
960 for (std::vector<CreditCard*>::iterator iter = credit_cards.begin();
961 iter != credit_cards.end(); ++iter) {
962 credit_cards_.push_back(*iter);
966 void PersonalDataManager::CancelPendingQuery(
967 WebDataServiceBase::Handle* handle) {
969 if (!database_.get()) {
973 database_->CancelRequest(*handle);
978 std::string PersonalDataManager::SaveImportedProfile(
979 const AutofillProfile& imported_profile) {
980 if (is_off_the_record_)
981 return std::string();
983 // Don't save a web profile if the data in the profile is a subset of an
984 // auxiliary profile.
985 for (std::vector<AutofillProfile*>::const_iterator iter =
986 auxiliary_profiles_.begin();
987 iter != auxiliary_profiles_.end(); ++iter) {
988 if (imported_profile.IsSubsetOf(**iter, app_locale_))
989 return (*iter)->guid();
992 std::vector<AutofillProfile> profiles;
994 MergeProfile(imported_profile, web_profiles_.get(), app_locale_,
996 SetProfiles(&profiles);
1000 void PersonalDataManager::NotifyPersonalDataChanged() {
1001 FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_,
1002 OnPersonalDataChanged());
1005 std::string PersonalDataManager::SaveImportedCreditCard(
1006 const CreditCard& imported_card) {
1007 DCHECK(!imported_card.number().empty());
1008 if (is_off_the_record_)
1009 return std::string();
1011 // Set to true if |imported_card| is merged into the credit card list.
1012 bool merged = false;
1014 std::string guid = imported_card.guid();
1015 std::vector<CreditCard> credit_cards;
1016 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin();
1017 iter != credit_cards_.end();
1019 CreditCard* card = *iter;
1020 // If |imported_card| has not yet been merged, check whether it should be
1021 // with the current |card|.
1022 if (!merged && card->UpdateFromImportedCard(imported_card, app_locale_)) {
1023 guid = card->guid();
1027 credit_cards.push_back(*card);
1031 credit_cards.push_back(imported_card);
1033 SetCreditCards(&credit_cards);
1037 void PersonalDataManager::LogProfileCount() const {
1038 if (!has_logged_profile_count_) {
1039 metric_logger_->LogStoredProfileCount(web_profiles_.size());
1040 has_logged_profile_count_ = true;
1044 std::string PersonalDataManager::MostCommonCountryCodeFromProfiles() const {
1045 if (!IsAutofillEnabled())
1046 return std::string();
1048 // Count up country codes from existing profiles.
1049 std::map<std::string, int> votes;
1050 // TODO(estade): can we make this GetProfiles() instead? It seems to cause
1051 // errors in tests on mac trybots. See http://crbug.com/57221
1052 const std::vector<AutofillProfile*>& profiles = web_profiles();
1053 std::vector<std::string> country_codes;
1054 AutofillCountry::GetAvailableCountries(&country_codes);
1055 for (size_t i = 0; i < profiles.size(); ++i) {
1056 std::string country_code = StringToUpperASCII(base::UTF16ToASCII(
1057 profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY)));
1059 if (std::find(country_codes.begin(), country_codes.end(), country_code) !=
1060 country_codes.end()) {
1061 // Verified profiles count 100x more than unverified ones.
1062 votes[country_code] += profiles[i]->IsVerified() ? 100 : 1;
1066 // Take the most common country code.
1067 if (!votes.empty()) {
1068 std::map<std::string, int>::iterator iter =
1069 std::max_element(votes.begin(), votes.end(), CompareVotes);
1073 return std::string();
1076 void PersonalDataManager::EnabledPrefChanged() {
1077 default_country_code_.clear();
1078 NotifyPersonalDataChanged();
1081 } // namespace autofill