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/profiler/scoped_tracker.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/string_util.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "components/autofill/core/browser/address_i18n.h"
20 #include "components/autofill/core/browser/autofill-inl.h"
21 #include "components/autofill/core/browser/autofill_country.h"
22 #include "components/autofill/core/browser/autofill_field.h"
23 #include "components/autofill/core/browser/form_structure.h"
24 #include "components/autofill/core/browser/personal_data_manager_observer.h"
25 #include "components/autofill/core/browser/phone_number.h"
26 #include "components/autofill/core/browser/phone_number_i18n.h"
27 #include "components/autofill/core/browser/validation.h"
28 #include "components/autofill/core/common/autofill_pref_names.h"
29 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
30 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_formatter.h"
35 using ::i18n::addressinput::AddressField;
36 using ::i18n::addressinput::GetStreetAddressLinesAsSingleLine;
37 using ::i18n::addressinput::STREET_ADDRESS;
39 const base::string16::value_type kCreditCardPrefix[] = {'*', 0};
42 class FormGroupMatchesByGUIDFunctor {
44 explicit FormGroupMatchesByGUIDFunctor(const std::string& guid)
48 bool operator()(const T& form_group) {
49 return form_group.guid() == guid_;
52 bool operator()(const T* form_group) {
53 return form_group->guid() == guid_;
57 const std::string guid_;
60 template<typename T, typename C>
61 typename C::const_iterator FindElementByGUID(const C& container,
62 const std::string& guid) {
63 return std::find_if(container.begin(),
65 FormGroupMatchesByGUIDFunctor<T>(guid));
68 template<typename T, typename C>
69 bool FindByGUID(const C& container, const std::string& guid) {
70 return FindElementByGUID<T>(container, guid) != container.end();
74 class IsEmptyFunctor {
76 explicit IsEmptyFunctor(const std::string& app_locale)
77 : app_locale_(app_locale) {
80 bool operator()(const T& form_group) {
81 return form_group.IsEmpty(app_locale_);
85 const std::string app_locale_;
88 // Returns true if minimum requirements for import of a given |profile| have
89 // been met. An address submitted via a form must have at least the fields
90 // required as determined by its country code.
91 // No verification of validity of the contents is preformed. This is an
92 // existence check only.
93 bool IsMinimumAddress(const AutofillProfile& profile,
94 const std::string& app_locale) {
95 // All countries require at least one address line.
96 if (profile.GetRawInfo(ADDRESS_HOME_LINE1).empty())
99 std::string country_code =
100 base::UTF16ToASCII(profile.GetRawInfo(ADDRESS_HOME_COUNTRY));
101 if (country_code.empty())
102 country_code = AutofillCountry::CountryCodeForLocale(app_locale);
104 AutofillCountry country(country_code, app_locale);
106 if (country.requires_city() && profile.GetRawInfo(ADDRESS_HOME_CITY).empty())
109 if (country.requires_state() &&
110 profile.GetRawInfo(ADDRESS_HOME_STATE).empty())
113 if (country.requires_zip() && profile.GetRawInfo(ADDRESS_HOME_ZIP).empty())
119 // Return true if the |field_type| and |value| are valid within the context
120 // of importing a form.
121 bool IsValidFieldTypeAndValue(const std::set<ServerFieldType>& types_seen,
122 ServerFieldType field_type,
123 const base::string16& value) {
124 // Abandon the import if two fields of the same type are encountered.
125 // This indicates ambiguous data or miscategorization of types.
126 // Make an exception for PHONE_HOME_NUMBER however as both prefix and
127 // suffix are stored against this type, and for EMAIL_ADDRESS because it is
128 // common to see second 'confirm email address' fields on forms.
129 if (types_seen.count(field_type) &&
130 field_type != PHONE_HOME_NUMBER &&
131 field_type != EMAIL_ADDRESS)
134 // Abandon the import if an email address value shows up in a field that is
135 // not an email address.
136 if (field_type != EMAIL_ADDRESS && IsValidEmailAddress(value))
142 // A helper function for finding the maximum value in a string->int map.
143 static bool CompareVotes(const std::pair<std::string, int>& a,
144 const std::pair<std::string, int>& b) {
145 return a.second < b.second;
150 PersonalDataManager::PersonalDataManager(const std::string& app_locale)
152 is_data_loaded_(false),
153 pending_profiles_query_(0),
154 pending_creditcards_query_(0),
155 app_locale_(app_locale),
156 metric_logger_(new AutofillMetrics),
158 is_off_the_record_(false),
159 has_logged_profile_count_(false) {}
161 void PersonalDataManager::Init(scoped_refptr<AutofillWebDataService> database,
162 PrefService* pref_service,
163 bool is_off_the_record) {
164 database_ = database;
165 SetPrefService(pref_service);
166 is_off_the_record_ = is_off_the_record;
168 if (!is_off_the_record_)
169 metric_logger_->LogIsAutofillEnabledAtStartup(IsAutofillEnabled());
171 // WebDataService may not be available in tests.
172 if (!database_.get())
178 database_->AddObserver(this);
181 PersonalDataManager::~PersonalDataManager() {
182 CancelPendingQuery(&pending_profiles_query_);
183 CancelPendingQuery(&pending_creditcards_query_);
186 database_->RemoveObserver(this);
189 void PersonalDataManager::OnWebDataServiceRequestDone(
190 WebDataServiceBase::Handle h,
191 const WDTypedResult* result) {
192 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422460 is fixed.
193 tracked_objects::ScopedTracker tracking_profile(
194 FROM_HERE_WITH_EXPLICIT_FUNCTION(
195 "422460 PersonalDataManager::OnWebDataServiceRequestDone"));
197 DCHECK(pending_profiles_query_ || pending_creditcards_query_);
200 // Error from the web database.
201 if (h == pending_creditcards_query_)
202 pending_creditcards_query_ = 0;
203 else if (h == pending_profiles_query_)
204 pending_profiles_query_ = 0;
208 switch (result->GetType()) {
209 case AUTOFILL_PROFILES_RESULT:
210 ReceiveLoadedProfiles(h, result);
212 case AUTOFILL_CREDITCARDS_RESULT:
213 ReceiveLoadedCreditCards(h, result);
219 // If both requests have responded, then all personal data is loaded.
220 if (pending_profiles_query_ == 0 && pending_creditcards_query_ == 0) {
221 is_data_loaded_ = true;
222 NotifyPersonalDataChanged();
226 void PersonalDataManager::AutofillMultipleChanged() {
230 void PersonalDataManager::AddObserver(PersonalDataManagerObserver* observer) {
231 observers_.AddObserver(observer);
234 void PersonalDataManager::RemoveObserver(
235 PersonalDataManagerObserver* observer) {
236 observers_.RemoveObserver(observer);
239 bool PersonalDataManager::ImportFormData(
240 const FormStructure& form,
241 scoped_ptr<CreditCard>* imported_credit_card) {
242 scoped_ptr<AutofillProfile> imported_profile(new AutofillProfile);
243 scoped_ptr<CreditCard> local_imported_credit_card(new CreditCard);
245 const std::string origin = form.source_url().spec();
246 imported_profile->set_origin(origin);
247 local_imported_credit_card->set_origin(origin);
249 // Parse the form and construct a profile based on the information that is
250 // possible to import.
251 int importable_credit_card_fields = 0;
253 // Detect and discard forms with multiple fields of the same type.
254 // TODO(isherman): Some types are overlapping but not equal, e.g. phone number
255 // parts, address parts.
256 std::set<ServerFieldType> types_seen;
258 // We only set complete phone, so aggregate phone parts in these vars and set
259 // complete at the end.
260 PhoneNumber::PhoneCombineHelper home;
262 for (size_t i = 0; i < form.field_count(); ++i) {
263 const AutofillField* field = form.field(i);
264 base::string16 value;
265 base::TrimWhitespace(field->value, base::TRIM_ALL, &value);
267 // If we don't know the type of the field, or the user hasn't entered any
268 // information into the field, then skip it.
269 if (!field->IsFieldFillable() || value.empty())
272 AutofillType field_type = field->Type();
273 ServerFieldType server_field_type = field_type.GetStorableType();
274 FieldTypeGroup group(field_type.group());
276 // There can be multiple email fields (e.g. in the case of 'confirm email'
277 // fields) but they must all contain the same value, else the profile is
279 if (server_field_type == EMAIL_ADDRESS) {
280 if (types_seen.count(server_field_type) &&
281 imported_profile->GetRawInfo(EMAIL_ADDRESS) != value) {
282 imported_profile.reset();
287 // If the |field_type| and |value| don't pass basic validity checks then
288 // abandon the import.
289 if (!IsValidFieldTypeAndValue(types_seen, server_field_type, value)) {
290 imported_profile.reset();
291 local_imported_credit_card.reset();
295 types_seen.insert(server_field_type);
297 if (group == CREDIT_CARD) {
298 if (LowerCaseEqualsASCII(field->form_control_type, "month")) {
299 DCHECK_EQ(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, server_field_type);
300 local_imported_credit_card->SetInfoForMonthInputType(value);
302 local_imported_credit_card->SetInfo(field_type, value, app_locale_);
304 ++importable_credit_card_fields;
306 // We need to store phone data in the variables, before building the whole
307 // number at the end. The rest of the fields are set "as is".
308 // If the fields are not the phone fields in question home.SetInfo() is
309 // going to return false.
310 if (!home.SetInfo(field_type, value))
311 imported_profile->SetInfo(field_type, value, app_locale_);
313 // Reject profiles with invalid country information.
314 if (server_field_type == ADDRESS_HOME_COUNTRY &&
316 imported_profile->GetRawInfo(ADDRESS_HOME_COUNTRY).empty()) {
317 imported_profile.reset();
323 // Construct the phone number. Reject the profile if the number is invalid.
324 if (imported_profile.get() && !home.IsEmpty()) {
325 base::string16 constructed_number;
326 if (!home.ParseNumber(*imported_profile, app_locale_,
327 &constructed_number) ||
328 !imported_profile->SetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER),
331 imported_profile.reset();
335 // Reject the profile if minimum address and validation requirements are not
337 if (imported_profile.get() &&
338 !IsValidLearnableProfile(*imported_profile, app_locale_))
339 imported_profile.reset();
341 // Reject the credit card if we did not detect enough filled credit card
342 // fields or if the credit card number does not seem to be valid.
343 if (local_imported_credit_card.get() &&
344 !local_imported_credit_card->IsComplete()) {
345 local_imported_credit_card.reset();
348 // Don't import if we already have this info.
349 // Don't present an infobar if we have already saved this card number.
350 bool merged_credit_card = false;
351 if (local_imported_credit_card.get()) {
352 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin();
353 iter != credit_cards_.end();
355 // Make a local copy so that the data in |credit_cards_| isn't modified
356 // directly by the UpdateFromImportedCard() call.
357 CreditCard card = **iter;
358 if (card.UpdateFromImportedCard(*local_imported_credit_card.get(),
360 merged_credit_card = true;
361 UpdateCreditCard(card);
362 local_imported_credit_card.reset();
368 if (imported_profile.get()) {
369 // We always save imported profiles.
370 SaveImportedProfile(*imported_profile);
372 *imported_credit_card = local_imported_credit_card.Pass();
374 if (imported_profile.get() || *imported_credit_card || merged_credit_card)
377 FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_,
378 OnInsufficientFormData());
382 void PersonalDataManager::AddProfile(const AutofillProfile& profile) {
383 if (is_off_the_record_)
386 if (profile.IsEmpty(app_locale_))
389 // Don't add an existing profile.
390 if (FindByGUID<AutofillProfile>(web_profiles_, profile.guid()))
393 if (!database_.get())
396 // Don't add a duplicate.
397 if (FindByContents(web_profiles_, profile))
400 // Add the new profile to the web database.
401 database_->AddAutofillProfile(profile);
403 // Refresh our local cache and send notifications to observers.
407 void PersonalDataManager::UpdateProfile(const AutofillProfile& profile) {
408 if (is_off_the_record_)
411 AutofillProfile* existing_profile = GetProfileByGUID(profile.guid());
412 if (!existing_profile)
415 // Don't overwrite the origin for a profile that is already stored.
416 if (existing_profile->EqualsSansOrigin(profile))
419 if (profile.IsEmpty(app_locale_)) {
420 RemoveByGUID(profile.guid());
424 if (!database_.get())
428 database_->UpdateAutofillProfile(profile);
430 // Refresh our local cache and send notifications to observers.
434 AutofillProfile* PersonalDataManager::GetProfileByGUID(
435 const std::string& guid) {
436 const std::vector<AutofillProfile*>& profiles = GetProfiles();
437 std::vector<AutofillProfile*>::const_iterator iter =
438 FindElementByGUID<AutofillProfile>(profiles, guid);
439 return (iter != profiles.end()) ? *iter : NULL;
442 void PersonalDataManager::AddCreditCard(const CreditCard& credit_card) {
443 if (is_off_the_record_)
446 if (credit_card.IsEmpty(app_locale_))
449 if (FindByGUID<CreditCard>(credit_cards_, credit_card.guid()))
452 if (!database_.get())
455 // Don't add a duplicate.
456 if (FindByContents(credit_cards_, credit_card))
459 // Add the new credit card to the web database.
460 database_->AddCreditCard(credit_card);
462 // Refresh our local cache and send notifications to observers.
466 void PersonalDataManager::UpdateCreditCard(const CreditCard& credit_card) {
467 if (is_off_the_record_)
470 CreditCard* existing_credit_card = GetCreditCardByGUID(credit_card.guid());
471 if (!existing_credit_card)
474 // Don't overwrite the origin for a credit card that is already stored.
475 if (existing_credit_card->Compare(credit_card) == 0)
478 if (credit_card.IsEmpty(app_locale_)) {
479 RemoveByGUID(credit_card.guid());
483 if (!database_.get())
487 database_->UpdateCreditCard(credit_card);
489 // Refresh our local cache and send notifications to observers.
493 void PersonalDataManager::RemoveByGUID(const std::string& guid) {
494 if (is_off_the_record_)
497 bool is_credit_card = FindByGUID<CreditCard>(credit_cards_, guid);
498 bool is_profile = !is_credit_card &&
499 FindByGUID<AutofillProfile>(web_profiles_, guid);
500 if (!is_credit_card && !is_profile)
503 if (!database_.get())
507 database_->RemoveCreditCard(guid);
509 database_->RemoveAutofillProfile(guid);
511 // Refresh our local cache and send notifications to observers.
515 CreditCard* PersonalDataManager::GetCreditCardByGUID(const std::string& guid) {
516 const std::vector<CreditCard*>& credit_cards = GetCreditCards();
517 std::vector<CreditCard*>::const_iterator iter =
518 FindElementByGUID<CreditCard>(credit_cards, guid);
519 return (iter != credit_cards.end()) ? *iter : NULL;
522 void PersonalDataManager::GetNonEmptyTypes(
523 ServerFieldTypeSet* non_empty_types) {
524 const std::vector<AutofillProfile*>& profiles = GetProfiles();
525 for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin();
526 iter != profiles.end(); ++iter) {
527 (*iter)->GetNonEmptyTypes(app_locale_, non_empty_types);
530 for (ScopedVector<CreditCard>::const_iterator iter = credit_cards_.begin();
531 iter != credit_cards_.end(); ++iter) {
532 (*iter)->GetNonEmptyTypes(app_locale_, non_empty_types);
536 bool PersonalDataManager::IsDataLoaded() const {
537 return is_data_loaded_;
540 const std::vector<AutofillProfile*>& PersonalDataManager::GetProfiles() const {
541 return GetProfiles(false);
544 const std::vector<AutofillProfile*>& PersonalDataManager::web_profiles() const {
545 return web_profiles_.get();
548 const std::vector<CreditCard*>& PersonalDataManager::GetCreditCards() const {
549 return credit_cards_.get();
552 void PersonalDataManager::Refresh() {
557 void PersonalDataManager::GetProfileSuggestions(
558 const AutofillType& type,
559 const base::string16& field_contents,
560 bool field_is_autofilled,
561 const std::vector<ServerFieldType>& other_field_types,
562 const base::Callback<bool(const AutofillProfile&)>& filter,
563 std::vector<base::string16>* values,
564 std::vector<base::string16>* labels,
565 std::vector<base::string16>* icons,
566 std::vector<GUIDPair>* guid_pairs) {
572 const std::vector<AutofillProfile*>& profiles = GetProfiles(true);
573 std::vector<AutofillProfile*> matched_profiles;
574 for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin();
575 iter != profiles.end(); ++iter) {
576 AutofillProfile* profile = *iter;
578 // The value of the stored data for this field type in the |profile|.
579 std::vector<base::string16> multi_values;
580 AddressField address_field;
581 if (i18n::FieldForType(type.GetStorableType(), &address_field) &&
582 address_field == STREET_ADDRESS) {
583 std::string street_address_line;
584 GetStreetAddressLinesAsSingleLine(
585 *i18n::CreateAddressDataFromAutofillProfile(*profile, app_locale_),
586 &street_address_line);
587 multi_values.push_back(base::UTF8ToUTF16(street_address_line));
589 profile->GetMultiInfo(type, app_locale_, &multi_values);
592 for (size_t i = 0; i < multi_values.size(); ++i) {
593 // Newlines can be found only in a street address, which was collapsed
594 // into a single line above.
595 DCHECK(multi_values[i].find('\n') == std::string::npos);
597 if (!field_is_autofilled) {
598 // Suggest data that starts with what the user has typed.
599 if (!multi_values[i].empty() &&
600 StartsWith(multi_values[i], field_contents, false) &&
601 (filter.is_null() || filter.Run(*profile))) {
602 matched_profiles.push_back(profile);
603 values->push_back(multi_values[i]);
604 guid_pairs->push_back(GUIDPair(profile->guid(), i));
607 if (multi_values[i].empty())
610 base::string16 profile_value_lower_case(
611 base::StringToLowerASCII(multi_values[i]));
612 base::string16 field_value_lower_case(
613 base::StringToLowerASCII(field_contents));
614 // Phone numbers could be split in US forms, so field value could be
615 // either prefix or suffix of the phone.
616 bool matched_phones = false;
617 if (type.GetStorableType() == PHONE_HOME_NUMBER &&
618 !field_value_lower_case.empty() &&
619 profile_value_lower_case.find(field_value_lower_case) !=
620 base::string16::npos) {
621 matched_phones = true;
624 // Suggest variants of the profile that's already been filled in.
625 if (matched_phones ||
626 profile_value_lower_case == field_value_lower_case) {
627 for (size_t j = 0; j < multi_values.size(); ++j) {
628 if (!multi_values[j].empty()) {
629 values->push_back(multi_values[j]);
630 guid_pairs->push_back(GUIDPair(profile->guid(), j));
634 // We've added all the values for this profile so move on to the
642 if (!field_is_autofilled) {
643 AutofillProfile::CreateInferredLabels(
644 matched_profiles, &other_field_types,
645 type.GetStorableType(), 1, app_locale_, labels);
647 // No sub-labels for previously filled fields.
648 labels->resize(values->size());
651 // No icons for profile suggestions.
652 icons->resize(values->size());
655 void PersonalDataManager::GetCreditCardSuggestions(
656 const AutofillType& type,
657 const base::string16& field_contents,
658 std::vector<base::string16>* values,
659 std::vector<base::string16>* labels,
660 std::vector<base::string16>* icons,
661 std::vector<GUIDPair>* guid_pairs) {
667 const std::vector<CreditCard*>& credit_cards = GetCreditCards();
668 for (std::vector<CreditCard*>::const_iterator iter = credit_cards.begin();
669 iter != credit_cards.end(); ++iter) {
670 CreditCard* credit_card = *iter;
672 // The value of the stored data for this field type in the |credit_card|.
673 base::string16 creditcard_field_value =
674 credit_card->GetInfo(type, app_locale_);
675 if (!creditcard_field_value.empty() &&
676 (StartsWith(creditcard_field_value, field_contents, false) ||
677 (type.GetStorableType() == CREDIT_CARD_NUMBER &&
678 base::string16::npos !=
679 creditcard_field_value.find(field_contents)))) {
680 // If the value is the card number, the label is the expiration date.
681 // Otherwise the label is the card number, or if that is empty the
682 // cardholder name. The label should never repeat the value.
683 base::string16 label;
684 if (type.GetStorableType() == CREDIT_CARD_NUMBER) {
685 creditcard_field_value = credit_card->ObfuscatedNumber();
686 label = credit_card->GetInfo(
687 AutofillType(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR), app_locale_);
688 } else if (credit_card->number().empty()) {
689 if (type.GetStorableType() != CREDIT_CARD_NAME) {
691 credit_card->GetInfo(AutofillType(CREDIT_CARD_NAME), app_locale_);
694 label = kCreditCardPrefix;
695 label.append(credit_card->LastFourDigits());
698 values->push_back(creditcard_field_value);
699 labels->push_back(label);
700 icons->push_back(base::UTF8ToUTF16(credit_card->type()));
701 guid_pairs->push_back(GUIDPair(credit_card->guid(), 0));
706 bool PersonalDataManager::IsAutofillEnabled() const {
707 DCHECK(pref_service_);
708 return pref_service_->GetBoolean(prefs::kAutofillEnabled);
711 std::string PersonalDataManager::CountryCodeForCurrentTimezone() const {
712 return base::CountryCodeForCurrentTimezone();
715 void PersonalDataManager::SetPrefService(PrefService* pref_service) {
716 enabled_pref_.reset(new BooleanPrefMember);
717 pref_service_ = pref_service;
718 // |pref_service_| can be NULL in tests.
720 enabled_pref_->Init(prefs::kAutofillEnabled, pref_service_,
721 base::Bind(&PersonalDataManager::EnabledPrefChanged,
722 base::Unretained(this)));
727 bool PersonalDataManager::IsValidLearnableProfile(
728 const AutofillProfile& profile,
729 const std::string& app_locale) {
730 if (!IsMinimumAddress(profile, app_locale))
733 base::string16 email = profile.GetRawInfo(EMAIL_ADDRESS);
734 if (!email.empty() && !IsValidEmailAddress(email))
737 // Reject profiles with invalid US state information.
738 if (profile.IsPresentButInvalid(ADDRESS_HOME_STATE))
741 // Reject profiles with invalid US zip information.
742 if (profile.IsPresentButInvalid(ADDRESS_HOME_ZIP))
749 std::string PersonalDataManager::MergeProfile(
750 const AutofillProfile& new_profile,
751 const std::vector<AutofillProfile*>& existing_profiles,
752 const std::string& app_locale,
753 std::vector<AutofillProfile>* merged_profiles) {
754 merged_profiles->clear();
756 // Set to true if |existing_profiles| already contains an equivalent profile.
757 bool matching_profile_found = false;
758 std::string guid = new_profile.guid();
760 // If we have already saved this address, merge in any missing values.
761 // Only merge with the first match.
762 for (std::vector<AutofillProfile*>::const_iterator iter =
763 existing_profiles.begin();
764 iter != existing_profiles.end(); ++iter) {
765 AutofillProfile* existing_profile = *iter;
766 if (!matching_profile_found &&
767 !new_profile.PrimaryValue().empty() &&
768 base::StringToLowerASCII(existing_profile->PrimaryValue()) ==
769 base::StringToLowerASCII(new_profile.PrimaryValue())) {
770 // Unverified profiles should always be updated with the newer data,
771 // whereas verified profiles should only ever be overwritten by verified
772 // data. If an automatically aggregated profile would overwrite a
773 // verified profile, just drop it.
774 matching_profile_found = true;
775 guid = existing_profile->guid();
776 if (!existing_profile->IsVerified() || new_profile.IsVerified())
777 existing_profile->OverwriteWithOrAddTo(new_profile, app_locale);
779 merged_profiles->push_back(*existing_profile);
782 // If the new profile was not merged with an existing one, add it to the list.
783 if (!matching_profile_found)
784 merged_profiles->push_back(new_profile);
789 bool PersonalDataManager::IsCountryOfInterest(const std::string& country_code)
791 DCHECK_EQ(2U, country_code.size());
793 const std::vector<AutofillProfile*>& profiles = web_profiles();
794 std::list<std::string> country_codes;
795 for (size_t i = 0; i < profiles.size(); ++i) {
796 country_codes.push_back(base::StringToLowerASCII(base::UTF16ToASCII(
797 profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY))));
800 std::string timezone_country = CountryCodeForCurrentTimezone();
801 if (!timezone_country.empty())
802 country_codes.push_back(base::StringToLowerASCII(timezone_country));
804 // Only take the locale into consideration if all else fails.
805 if (country_codes.empty()) {
806 country_codes.push_back(base::StringToLowerASCII(
807 AutofillCountry::CountryCodeForLocale(app_locale())));
810 return std::find(country_codes.begin(), country_codes.end(),
811 base::StringToLowerASCII(country_code)) !=
815 const std::string& PersonalDataManager::GetDefaultCountryCodeForNewAddress()
817 if (default_country_code_.empty())
818 default_country_code_ = MostCommonCountryCodeFromProfiles();
820 // Failing that, guess based on system timezone.
821 if (default_country_code_.empty())
822 default_country_code_ = CountryCodeForCurrentTimezone();
824 // Failing that, guess based on locale.
825 if (default_country_code_.empty())
826 default_country_code_ = AutofillCountry::CountryCodeForLocale(app_locale());
828 return default_country_code_;
831 void PersonalDataManager::SetProfiles(std::vector<AutofillProfile>* profiles) {
832 if (is_off_the_record_)
835 // Remove empty profiles from input.
836 profiles->erase(std::remove_if(profiles->begin(), profiles->end(),
837 IsEmptyFunctor<AutofillProfile>(app_locale_)),
840 if (!database_.get())
843 // Any profiles that are not in the new profile list should be removed from
845 for (std::vector<AutofillProfile*>::const_iterator iter =
846 web_profiles_.begin();
847 iter != web_profiles_.end(); ++iter) {
848 if (!FindByGUID<AutofillProfile>(*profiles, (*iter)->guid()))
849 database_->RemoveAutofillProfile((*iter)->guid());
852 // Update the web database with the existing profiles.
853 for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
854 iter != profiles->end(); ++iter) {
855 if (FindByGUID<AutofillProfile>(web_profiles_, iter->guid()))
856 database_->UpdateAutofillProfile(*iter);
859 // Add the new profiles to the web database. Don't add a duplicate.
860 for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
861 iter != profiles->end(); ++iter) {
862 if (!FindByGUID<AutofillProfile>(web_profiles_, iter->guid()) &&
863 !FindByContents(web_profiles_, *iter))
864 database_->AddAutofillProfile(*iter);
867 // Copy in the new profiles.
868 web_profiles_.clear();
869 for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
870 iter != profiles->end(); ++iter) {
871 web_profiles_.push_back(new AutofillProfile(*iter));
874 // Refresh our local cache and send notifications to observers.
878 void PersonalDataManager::SetCreditCards(
879 std::vector<CreditCard>* credit_cards) {
880 if (is_off_the_record_)
883 // Remove empty credit cards from input.
884 credit_cards->erase(std::remove_if(credit_cards->begin(), credit_cards->end(),
885 IsEmptyFunctor<CreditCard>(app_locale_)),
886 credit_cards->end());
888 if (!database_.get())
891 // Any credit cards that are not in the new credit card list should be
893 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin();
894 iter != credit_cards_.end(); ++iter) {
895 if (!FindByGUID<CreditCard>(*credit_cards, (*iter)->guid()))
896 database_->RemoveCreditCard((*iter)->guid());
899 // Update the web database with the existing credit cards.
900 for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
901 iter != credit_cards->end(); ++iter) {
902 if (FindByGUID<CreditCard>(credit_cards_, iter->guid()))
903 database_->UpdateCreditCard(*iter);
906 // Add the new credit cards to the web database. Don't add a duplicate.
907 for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
908 iter != credit_cards->end(); ++iter) {
909 if (!FindByGUID<CreditCard>(credit_cards_, iter->guid()) &&
910 !FindByContents(credit_cards_, *iter))
911 database_->AddCreditCard(*iter);
914 // Copy in the new credit cards.
915 credit_cards_.clear();
916 for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
917 iter != credit_cards->end(); ++iter) {
918 credit_cards_.push_back(new CreditCard(*iter));
921 // Refresh our local cache and send notifications to observers.
925 void PersonalDataManager::LoadProfiles() {
926 if (!database_.get()) {
931 CancelPendingQuery(&pending_profiles_query_);
933 pending_profiles_query_ = database_->GetAutofillProfiles(this);
936 // Win, Linux, Android and iOS implementations do nothing. Mac implementation
937 // fills in the contents of |auxiliary_profiles_|.
938 #if defined(OS_IOS) || !defined(OS_MACOSX)
939 void PersonalDataManager::LoadAuxiliaryProfiles(bool record_metrics) const {
943 void PersonalDataManager::LoadCreditCards() {
944 if (!database_.get()) {
949 CancelPendingQuery(&pending_creditcards_query_);
951 pending_creditcards_query_ = database_->GetCreditCards(this);
954 void PersonalDataManager::ReceiveLoadedProfiles(WebDataServiceBase::Handle h,
955 const WDTypedResult* result) {
956 DCHECK_EQ(pending_profiles_query_, h);
958 pending_profiles_query_ = 0;
959 web_profiles_.clear();
961 const WDResult<std::vector<AutofillProfile*> >* r =
962 static_cast<const WDResult<std::vector<AutofillProfile*> >*>(result);
964 std::vector<AutofillProfile*> profiles = r->GetValue();
965 for (std::vector<AutofillProfile*>::iterator iter = profiles.begin();
966 iter != profiles.end(); ++iter) {
967 web_profiles_.push_back(*iter);
973 void PersonalDataManager::ReceiveLoadedCreditCards(
974 WebDataServiceBase::Handle h, const WDTypedResult* result) {
975 DCHECK_EQ(pending_creditcards_query_, h);
977 pending_creditcards_query_ = 0;
978 credit_cards_.clear();
980 const WDResult<std::vector<CreditCard*> >* r =
981 static_cast<const WDResult<std::vector<CreditCard*> >*>(result);
983 std::vector<CreditCard*> credit_cards = r->GetValue();
984 for (std::vector<CreditCard*>::iterator iter = credit_cards.begin();
985 iter != credit_cards.end(); ++iter) {
986 credit_cards_.push_back(*iter);
990 void PersonalDataManager::CancelPendingQuery(
991 WebDataServiceBase::Handle* handle) {
993 if (!database_.get()) {
997 database_->CancelRequest(*handle);
1002 std::string PersonalDataManager::SaveImportedProfile(
1003 const AutofillProfile& imported_profile) {
1004 if (is_off_the_record_)
1005 return std::string();
1007 // Don't save a web profile if the data in the profile is a subset of an
1008 // auxiliary profile.
1009 for (std::vector<AutofillProfile*>::const_iterator iter =
1010 auxiliary_profiles_.begin();
1011 iter != auxiliary_profiles_.end(); ++iter) {
1012 if (imported_profile.IsSubsetOf(**iter, app_locale_))
1013 return (*iter)->guid();
1016 std::vector<AutofillProfile> profiles;
1018 MergeProfile(imported_profile, web_profiles_.get(), app_locale_,
1020 SetProfiles(&profiles);
1024 void PersonalDataManager::NotifyPersonalDataChanged() {
1025 FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_,
1026 OnPersonalDataChanged());
1029 std::string PersonalDataManager::SaveImportedCreditCard(
1030 const CreditCard& imported_card) {
1031 DCHECK(!imported_card.number().empty());
1032 if (is_off_the_record_)
1033 return std::string();
1035 // Set to true if |imported_card| is merged into the credit card list.
1036 bool merged = false;
1038 std::string guid = imported_card.guid();
1039 std::vector<CreditCard> credit_cards;
1040 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin();
1041 iter != credit_cards_.end();
1043 CreditCard* card = *iter;
1044 // If |imported_card| has not yet been merged, check whether it should be
1045 // with the current |card|.
1046 if (!merged && card->UpdateFromImportedCard(imported_card, app_locale_)) {
1047 guid = card->guid();
1051 credit_cards.push_back(*card);
1055 credit_cards.push_back(imported_card);
1057 SetCreditCards(&credit_cards);
1061 void PersonalDataManager::LogProfileCount() const {
1062 if (!has_logged_profile_count_) {
1063 metric_logger_->LogStoredProfileCount(web_profiles_.size());
1064 has_logged_profile_count_ = true;
1068 std::string PersonalDataManager::MostCommonCountryCodeFromProfiles() const {
1069 if (!IsAutofillEnabled())
1070 return std::string();
1072 // Count up country codes from existing profiles.
1073 std::map<std::string, int> votes;
1074 // TODO(estade): can we make this GetProfiles() instead? It seems to cause
1075 // errors in tests on mac trybots. See http://crbug.com/57221
1076 const std::vector<AutofillProfile*>& profiles = web_profiles();
1077 std::vector<std::string> country_codes;
1078 AutofillCountry::GetAvailableCountries(&country_codes);
1079 for (size_t i = 0; i < profiles.size(); ++i) {
1080 std::string country_code = StringToUpperASCII(base::UTF16ToASCII(
1081 profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY)));
1083 if (std::find(country_codes.begin(), country_codes.end(), country_code) !=
1084 country_codes.end()) {
1085 // Verified profiles count 100x more than unverified ones.
1086 votes[country_code] += profiles[i]->IsVerified() ? 100 : 1;
1090 // Take the most common country code.
1091 if (!votes.empty()) {
1092 std::map<std::string, int>::iterator iter =
1093 std::max_element(votes.begin(), votes.end(), CompareVotes);
1097 return std::string();
1100 void PersonalDataManager::EnabledPrefChanged() {
1101 default_country_code_.clear();
1102 NotifyPersonalDataChanged();
1105 const std::vector<AutofillProfile*>& PersonalDataManager::GetProfiles(
1106 bool record_metrics) const {
1107 #if defined(OS_MACOSX) && !defined(OS_IOS)
1108 if (!pref_service_->GetBoolean(prefs::kAutofillUseMacAddressBook))
1109 return web_profiles();
1111 if (!pref_service_->GetBoolean(prefs::kAutofillAuxiliaryProfilesEnabled))
1112 return web_profiles();
1113 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
1117 // Populates |auxiliary_profiles_|.
1118 LoadAuxiliaryProfiles(record_metrics);
1120 profiles_.insert(profiles_.end(), web_profiles_.begin(), web_profiles_.end());
1122 profiles_.end(), auxiliary_profiles_.begin(), auxiliary_profiles_.end());
1126 } // namespace autofill