rAc: change how enabling/disabling Autofill affects requestAutocomplete().
[chromium-blink-merge.git] / components / autofill / core / browser / personal_data_manager.cc
blobda70ce2c5581f333ce83302a5003c8a9bd0012d0
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"
7 #include <algorithm>
8 #include <functional>
9 #include <iterator>
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"
28 namespace autofill {
29 namespace {
31 const base::string16::value_type kCreditCardPrefix[] = {'*', 0};
33 template<typename T>
34 class FormGroupMatchesByGUIDFunctor {
35 public:
36 explicit FormGroupMatchesByGUIDFunctor(const std::string& guid)
37 : guid_(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_;
48 private:
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(),
56 container.end(),
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();
65 template<typename T>
66 class IsEmptyFunctor {
67 public:
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_);
76 private:
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())
89 return false;
91 std::string country_code =
92 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())
99 return false;
101 if (country.requires_state() &&
102 profile.GetRawInfo(ADDRESS_HOME_STATE).empty())
103 return false;
105 if (country.requires_zip() && profile.GetRawInfo(ADDRESS_HOME_ZIP).empty())
106 return false;
108 return true;
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)
124 return false;
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))
129 return false;
131 return true;
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;
140 } // namespace
142 PersonalDataManager::PersonalDataManager(const std::string& app_locale)
143 : database_(NULL),
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),
149 pref_service_(NULL),
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())
165 return;
167 LoadProfiles();
168 LoadCreditCards();
170 database_->AddObserver(this);
173 PersonalDataManager::~PersonalDataManager() {
174 CancelPendingQuery(&pending_profiles_query_);
175 CancelPendingQuery(&pending_creditcards_query_);
177 if (database_.get())
178 database_->RemoveObserver(this);
181 void PersonalDataManager::OnWebDataServiceRequestDone(
182 WebDataServiceBase::Handle h,
183 const WDTypedResult* result) {
184 DCHECK(pending_profiles_query_ || pending_creditcards_query_);
186 if (!result) {
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;
192 return;
195 switch (result->GetType()) {
196 case AUTOFILL_PROFILES_RESULT:
197 ReceiveLoadedProfiles(h, result);
198 break;
199 case AUTOFILL_CREDITCARDS_RESULT:
200 ReceiveLoadedCreditCards(h, result);
201 break;
202 default:
203 NOTREACHED();
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() {
214 Refresh();
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 TrimWhitespace(field->value, 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())
257 continue;
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
265 // invalid.
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();
270 break;
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();
279 break;
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);
288 } else {
289 local_imported_credit_card->SetInfo(field_type, value, app_locale_);
291 ++importable_credit_card_fields;
292 } else {
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 &&
302 !value.empty() &&
303 imported_profile->GetRawInfo(ADDRESS_HOME_COUNTRY).empty()) {
304 imported_profile.reset();
305 break;
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),
316 constructed_number,
317 app_locale_)) {
318 imported_profile.reset();
322 // Reject the profile if minimum address and validation requirements are not
323 // met.
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();
341 ++iter) {
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(),
346 app_locale_)) {
347 merged_credit_card = true;
348 UpdateCreditCard(card);
349 local_imported_credit_card.reset();
350 break;
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)
362 return true;
364 FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_,
365 OnInsufficientFormData());
366 return false;
369 void PersonalDataManager::AddProfile(const AutofillProfile& profile) {
370 if (is_off_the_record_)
371 return;
373 if (profile.IsEmpty(app_locale_))
374 return;
376 // Don't add an existing profile.
377 if (FindByGUID<AutofillProfile>(web_profiles_, profile.guid()))
378 return;
380 if (!database_.get())
381 return;
383 // Don't add a duplicate.
384 if (FindByContents(web_profiles_, profile))
385 return;
387 // Add the new profile to the web database.
388 database_->AddAutofillProfile(profile);
390 // Refresh our local cache and send notifications to observers.
391 Refresh();
394 void PersonalDataManager::UpdateProfile(const AutofillProfile& profile) {
395 if (is_off_the_record_)
396 return;
398 AutofillProfile* existing_profile = GetProfileByGUID(profile.guid());
399 if (!existing_profile)
400 return;
402 // Don't overwrite the origin for a profile that is already stored.
403 if (existing_profile->Compare(profile) == 0)
404 return;
406 if (profile.IsEmpty(app_locale_)) {
407 RemoveByGUID(profile.guid());
408 return;
411 if (!database_.get())
412 return;
414 // Make the update.
415 database_->UpdateAutofillProfile(profile);
417 // Refresh our local cache and send notifications to observers.
418 Refresh();
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_)
431 return;
433 if (credit_card.IsEmpty(app_locale_))
434 return;
436 if (FindByGUID<CreditCard>(credit_cards_, credit_card.guid()))
437 return;
439 if (!database_.get())
440 return;
442 // Don't add a duplicate.
443 if (FindByContents(credit_cards_, credit_card))
444 return;
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.
450 Refresh();
453 void PersonalDataManager::UpdateCreditCard(const CreditCard& credit_card) {
454 if (is_off_the_record_)
455 return;
457 CreditCard* existing_credit_card = GetCreditCardByGUID(credit_card.guid());
458 if (!existing_credit_card)
459 return;
461 // Don't overwrite the origin for a credit card that is already stored.
462 if (existing_credit_card->Compare(credit_card) == 0)
463 return;
465 if (credit_card.IsEmpty(app_locale_)) {
466 RemoveByGUID(credit_card.guid());
467 return;
470 if (!database_.get())
471 return;
473 // Make the update.
474 database_->UpdateCreditCard(credit_card);
476 // Refresh our local cache and send notifications to observers.
477 Refresh();
480 void PersonalDataManager::RemoveByGUID(const std::string& guid) {
481 if (is_off_the_record_)
482 return;
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)
488 return;
490 if (!database_.get())
491 return;
493 if (is_credit_card)
494 database_->RemoveCreditCard(guid);
495 else
496 database_->RemoveAutofillProfile(guid);
498 // Refresh our local cache and send notifications to observers.
499 Refresh();
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();
532 profiles_.clear();
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());
540 return profiles_;
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() {
552 LoadProfiles();
553 LoadCreditCards();
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 std::vector<base::string16>* values,
562 std::vector<base::string16>* labels,
563 std::vector<base::string16>* icons,
564 std::vector<GUIDPair>* guid_pairs) {
565 values->clear();
566 labels->clear();
567 icons->clear();
568 guid_pairs->clear();
570 const std::vector<AutofillProfile*>& profiles = GetProfiles();
571 std::vector<AutofillProfile*> matched_profiles;
572 for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin();
573 iter != profiles.end(); ++iter) {
574 AutofillProfile* profile = *iter;
576 // The value of the stored data for this field type in the |profile|.
577 std::vector<base::string16> multi_values;
578 profile->GetMultiInfo(type, app_locale_, &multi_values);
580 for (size_t i = 0; i < multi_values.size(); ++i) {
581 if (!field_is_autofilled) {
582 // Suggest data that starts with what the user has typed.
583 if (!multi_values[i].empty() &&
584 StartsWith(multi_values[i], field_contents, false)) {
585 matched_profiles.push_back(profile);
586 values->push_back(multi_values[i]);
587 guid_pairs->push_back(GUIDPair(profile->guid(), i));
589 } else {
590 if (multi_values[i].empty())
591 continue;
593 base::string16 profile_value_lower_case(
594 StringToLowerASCII(multi_values[i]));
595 base::string16 field_value_lower_case(
596 StringToLowerASCII(field_contents));
597 // Phone numbers could be split in US forms, so field value could be
598 // either prefix or suffix of the phone.
599 bool matched_phones = false;
600 if (type.GetStorableType() == PHONE_HOME_NUMBER &&
601 !field_value_lower_case.empty() &&
602 profile_value_lower_case.find(field_value_lower_case) !=
603 base::string16::npos) {
604 matched_phones = true;
607 // Suggest variants of the profile that's already been filled in.
608 if (matched_phones ||
609 profile_value_lower_case == field_value_lower_case) {
610 for (size_t j = 0; j < multi_values.size(); ++j) {
611 if (!multi_values[j].empty()) {
612 values->push_back(multi_values[j]);
613 guid_pairs->push_back(GUIDPair(profile->guid(), j));
617 // We've added all the values for this profile so move on to the
618 // next.
619 break;
625 if (!field_is_autofilled) {
626 AutofillProfile::CreateInferredLabels(
627 matched_profiles, &other_field_types,
628 type.GetStorableType(), 1, labels);
629 } else {
630 // No sub-labels for previously filled fields.
631 labels->resize(values->size());
634 // No icons for profile suggestions.
635 icons->resize(values->size());
638 void PersonalDataManager::GetCreditCardSuggestions(
639 const AutofillType& type,
640 const base::string16& field_contents,
641 std::vector<base::string16>* values,
642 std::vector<base::string16>* labels,
643 std::vector<base::string16>* icons,
644 std::vector<GUIDPair>* guid_pairs) {
645 values->clear();
646 labels->clear();
647 icons->clear();
648 guid_pairs->clear();
650 const std::vector<CreditCard*>& credit_cards = GetCreditCards();
651 for (std::vector<CreditCard*>::const_iterator iter = credit_cards.begin();
652 iter != credit_cards.end(); ++iter) {
653 CreditCard* credit_card = *iter;
655 // The value of the stored data for this field type in the |credit_card|.
656 base::string16 creditcard_field_value =
657 credit_card->GetInfo(type, app_locale_);
658 if (!creditcard_field_value.empty() &&
659 StartsWith(creditcard_field_value, field_contents, false)) {
660 if (type.GetStorableType() == CREDIT_CARD_NUMBER)
661 creditcard_field_value = credit_card->ObfuscatedNumber();
663 base::string16 label;
664 if (credit_card->number().empty()) {
665 // If there is no CC number, return name to show something.
666 label =
667 credit_card->GetInfo(AutofillType(CREDIT_CARD_NAME), app_locale_);
668 } else {
669 label = kCreditCardPrefix;
670 label.append(credit_card->LastFourDigits());
673 values->push_back(creditcard_field_value);
674 labels->push_back(label);
675 icons->push_back(base::UTF8ToUTF16(credit_card->type()));
676 guid_pairs->push_back(GUIDPair(credit_card->guid(), 0));
681 bool PersonalDataManager::IsAutofillEnabled() const {
682 DCHECK(pref_service_);
683 return pref_service_->GetBoolean(prefs::kAutofillEnabled);
686 std::string PersonalDataManager::CountryCodeForCurrentTimezone() const {
687 return base::CountryCodeForCurrentTimezone();
690 void PersonalDataManager::SetPrefService(PrefService* pref_service) {
691 enabled_pref_.reset(new BooleanPrefMember);
692 pref_service_ = pref_service;
693 // |pref_service_| can be NULL in tests.
694 if (pref_service_) {
695 enabled_pref_->Init(prefs::kAutofillEnabled, pref_service_,
696 base::Bind(&PersonalDataManager::EnabledPrefChanged,
697 base::Unretained(this)));
701 // static
702 bool PersonalDataManager::IsValidLearnableProfile(
703 const AutofillProfile& profile,
704 const std::string& app_locale) {
705 if (!IsMinimumAddress(profile, app_locale))
706 return false;
708 base::string16 email = profile.GetRawInfo(EMAIL_ADDRESS);
709 if (!email.empty() && !IsValidEmailAddress(email))
710 return false;
712 // Reject profiles with invalid US state information.
713 if (profile.IsPresentButInvalid(ADDRESS_HOME_STATE))
714 return false;
716 // Reject profiles with invalid US zip information.
717 if (profile.IsPresentButInvalid(ADDRESS_HOME_ZIP))
718 return false;
720 return true;
723 // static
724 std::string PersonalDataManager::MergeProfile(
725 const AutofillProfile& new_profile,
726 const std::vector<AutofillProfile*>& existing_profiles,
727 const std::string& app_locale,
728 std::vector<AutofillProfile>* merged_profiles) {
729 merged_profiles->clear();
731 // Set to true if |existing_profiles| already contains an equivalent profile.
732 bool matching_profile_found = false;
733 std::string guid = new_profile.guid();
735 // If we have already saved this address, merge in any missing values.
736 // Only merge with the first match.
737 for (std::vector<AutofillProfile*>::const_iterator iter =
738 existing_profiles.begin();
739 iter != existing_profiles.end(); ++iter) {
740 AutofillProfile* existing_profile = *iter;
741 if (!matching_profile_found &&
742 !new_profile.PrimaryValue().empty() &&
743 StringToLowerASCII(existing_profile->PrimaryValue()) ==
744 StringToLowerASCII(new_profile.PrimaryValue())) {
745 // Unverified profiles should always be updated with the newer data,
746 // whereas verified profiles should only ever be overwritten by verified
747 // data. If an automatically aggregated profile would overwrite a
748 // verified profile, just drop it.
749 matching_profile_found = true;
750 guid = existing_profile->guid();
751 if (!existing_profile->IsVerified() || new_profile.IsVerified())
752 existing_profile->OverwriteWithOrAddTo(new_profile, app_locale);
754 merged_profiles->push_back(*existing_profile);
757 // If the new profile was not merged with an existing one, add it to the list.
758 if (!matching_profile_found)
759 merged_profiles->push_back(new_profile);
761 return guid;
764 bool PersonalDataManager::IsCountryOfInterest(const std::string& country_code)
765 const {
766 DCHECK_EQ(2U, country_code.size());
768 const std::vector<AutofillProfile*>& profiles = web_profiles();
769 std::list<std::string> country_codes;
770 for (size_t i = 0; i < profiles.size(); ++i) {
771 country_codes.push_back(StringToLowerASCII(UTF16ToASCII(
772 profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY))));
775 std::string timezone_country = CountryCodeForCurrentTimezone();
776 if (!timezone_country.empty())
777 country_codes.push_back(StringToLowerASCII(timezone_country));
779 // Only take the locale into consideration if all else fails.
780 if (country_codes.empty()) {
781 country_codes.push_back(StringToLowerASCII(
782 AutofillCountry::CountryCodeForLocale(app_locale())));
785 return std::find(country_codes.begin(), country_codes.end(),
786 StringToLowerASCII(country_code)) != country_codes.end();
789 const std::string& PersonalDataManager::GetDefaultCountryCodeForNewAddress()
790 const {
791 if (default_country_code_.empty())
792 default_country_code_ = MostCommonCountryCodeFromProfiles();
794 // Failing that, guess based on system timezone.
795 if (default_country_code_.empty())
796 default_country_code_ = CountryCodeForCurrentTimezone();
798 // Failing that, guess based on locale.
799 if (default_country_code_.empty())
800 default_country_code_ = AutofillCountry::CountryCodeForLocale(app_locale());
802 return default_country_code_;
805 void PersonalDataManager::SetProfiles(std::vector<AutofillProfile>* profiles) {
806 if (is_off_the_record_)
807 return;
809 // Remove empty profiles from input.
810 profiles->erase(std::remove_if(profiles->begin(), profiles->end(),
811 IsEmptyFunctor<AutofillProfile>(app_locale_)),
812 profiles->end());
814 if (!database_.get())
815 return;
817 // Any profiles that are not in the new profile list should be removed from
818 // the web database.
819 for (std::vector<AutofillProfile*>::const_iterator iter =
820 web_profiles_.begin();
821 iter != web_profiles_.end(); ++iter) {
822 if (!FindByGUID<AutofillProfile>(*profiles, (*iter)->guid()))
823 database_->RemoveAutofillProfile((*iter)->guid());
826 // Update the web database with the existing profiles.
827 for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
828 iter != profiles->end(); ++iter) {
829 if (FindByGUID<AutofillProfile>(web_profiles_, iter->guid()))
830 database_->UpdateAutofillProfile(*iter);
833 // Add the new profiles to the web database. Don't add a duplicate.
834 for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
835 iter != profiles->end(); ++iter) {
836 if (!FindByGUID<AutofillProfile>(web_profiles_, iter->guid()) &&
837 !FindByContents(web_profiles_, *iter))
838 database_->AddAutofillProfile(*iter);
841 // Copy in the new profiles.
842 web_profiles_.clear();
843 for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
844 iter != profiles->end(); ++iter) {
845 web_profiles_.push_back(new AutofillProfile(*iter));
848 // Refresh our local cache and send notifications to observers.
849 Refresh();
852 void PersonalDataManager::SetCreditCards(
853 std::vector<CreditCard>* credit_cards) {
854 if (is_off_the_record_)
855 return;
857 // Remove empty credit cards from input.
858 credit_cards->erase(std::remove_if(credit_cards->begin(), credit_cards->end(),
859 IsEmptyFunctor<CreditCard>(app_locale_)),
860 credit_cards->end());
862 if (!database_.get())
863 return;
865 // Any credit cards that are not in the new credit card list should be
866 // removed.
867 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin();
868 iter != credit_cards_.end(); ++iter) {
869 if (!FindByGUID<CreditCard>(*credit_cards, (*iter)->guid()))
870 database_->RemoveCreditCard((*iter)->guid());
873 // Update the web database with the existing credit cards.
874 for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
875 iter != credit_cards->end(); ++iter) {
876 if (FindByGUID<CreditCard>(credit_cards_, iter->guid()))
877 database_->UpdateCreditCard(*iter);
880 // Add the new credit cards to the web database. Don't add a duplicate.
881 for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
882 iter != credit_cards->end(); ++iter) {
883 if (!FindByGUID<CreditCard>(credit_cards_, iter->guid()) &&
884 !FindByContents(credit_cards_, *iter))
885 database_->AddCreditCard(*iter);
888 // Copy in the new credit cards.
889 credit_cards_.clear();
890 for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
891 iter != credit_cards->end(); ++iter) {
892 credit_cards_.push_back(new CreditCard(*iter));
895 // Refresh our local cache and send notifications to observers.
896 Refresh();
899 void PersonalDataManager::LoadProfiles() {
900 if (!database_.get()) {
901 NOTREACHED();
902 return;
905 CancelPendingQuery(&pending_profiles_query_);
907 pending_profiles_query_ = database_->GetAutofillProfiles(this);
910 // Win, Linux, and iOS implementations do nothing. Mac and Android
911 // implementations fill in the contents of |auxiliary_profiles_|.
912 #if defined(OS_IOS) || (!defined(OS_MACOSX) && !defined(OS_ANDROID))
913 void PersonalDataManager::LoadAuxiliaryProfiles() const {
915 #endif
917 void PersonalDataManager::LoadCreditCards() {
918 if (!database_.get()) {
919 NOTREACHED();
920 return;
923 CancelPendingQuery(&pending_creditcards_query_);
925 pending_creditcards_query_ = database_->GetCreditCards(this);
928 void PersonalDataManager::ReceiveLoadedProfiles(WebDataServiceBase::Handle h,
929 const WDTypedResult* result) {
930 DCHECK_EQ(pending_profiles_query_, h);
932 pending_profiles_query_ = 0;
933 web_profiles_.clear();
935 const WDResult<std::vector<AutofillProfile*> >* r =
936 static_cast<const WDResult<std::vector<AutofillProfile*> >*>(result);
938 std::vector<AutofillProfile*> profiles = r->GetValue();
939 for (std::vector<AutofillProfile*>::iterator iter = profiles.begin();
940 iter != profiles.end(); ++iter) {
941 web_profiles_.push_back(*iter);
944 LogProfileCount();
947 void PersonalDataManager::ReceiveLoadedCreditCards(
948 WebDataServiceBase::Handle h, const WDTypedResult* result) {
949 DCHECK_EQ(pending_creditcards_query_, h);
951 pending_creditcards_query_ = 0;
952 credit_cards_.clear();
954 const WDResult<std::vector<CreditCard*> >* r =
955 static_cast<const WDResult<std::vector<CreditCard*> >*>(result);
957 std::vector<CreditCard*> credit_cards = r->GetValue();
958 for (std::vector<CreditCard*>::iterator iter = credit_cards.begin();
959 iter != credit_cards.end(); ++iter) {
960 credit_cards_.push_back(*iter);
964 void PersonalDataManager::CancelPendingQuery(
965 WebDataServiceBase::Handle* handle) {
966 if (*handle) {
967 if (!database_.get()) {
968 NOTREACHED();
969 return;
971 database_->CancelRequest(*handle);
973 *handle = 0;
976 std::string PersonalDataManager::SaveImportedProfile(
977 const AutofillProfile& imported_profile) {
978 if (is_off_the_record_)
979 return std::string();
981 // Don't save a web profile if the data in the profile is a subset of an
982 // auxiliary profile.
983 for (std::vector<AutofillProfile*>::const_iterator iter =
984 auxiliary_profiles_.begin();
985 iter != auxiliary_profiles_.end(); ++iter) {
986 if (imported_profile.IsSubsetOf(**iter, app_locale_))
987 return (*iter)->guid();
990 std::vector<AutofillProfile> profiles;
991 std::string guid =
992 MergeProfile(imported_profile, web_profiles_.get(), app_locale_,
993 &profiles);
994 SetProfiles(&profiles);
995 return guid;
998 void PersonalDataManager::NotifyPersonalDataChanged() {
999 FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_,
1000 OnPersonalDataChanged());
1003 std::string PersonalDataManager::SaveImportedCreditCard(
1004 const CreditCard& imported_card) {
1005 DCHECK(!imported_card.number().empty());
1006 if (is_off_the_record_)
1007 return std::string();
1009 // Set to true if |imported_card| is merged into the credit card list.
1010 bool merged = false;
1012 std::string guid = imported_card.guid();
1013 std::vector<CreditCard> credit_cards;
1014 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin();
1015 iter != credit_cards_.end();
1016 ++iter) {
1017 CreditCard* card = *iter;
1018 // If |imported_card| has not yet been merged, check whether it should be
1019 // with the current |card|.
1020 if (!merged && card->UpdateFromImportedCard(imported_card, app_locale_)) {
1021 guid = card->guid();
1022 merged = true;
1025 credit_cards.push_back(*card);
1028 if (!merged)
1029 credit_cards.push_back(imported_card);
1031 SetCreditCards(&credit_cards);
1032 return guid;
1035 void PersonalDataManager::LogProfileCount() const {
1036 if (!has_logged_profile_count_) {
1037 metric_logger_->LogStoredProfileCount(web_profiles_.size());
1038 has_logged_profile_count_ = true;
1042 std::string PersonalDataManager::MostCommonCountryCodeFromProfiles() const {
1043 if (!IsAutofillEnabled())
1044 return std::string();
1046 // Count up country codes from existing profiles.
1047 std::map<std::string, int> votes;
1048 // TODO(estade): can we make this GetProfiles() instead? It seems to cause
1049 // errors in tests on mac trybots. See http://crbug.com/57221
1050 const std::vector<AutofillProfile*>& profiles = web_profiles();
1051 std::vector<std::string> country_codes;
1052 AutofillCountry::GetAvailableCountries(&country_codes);
1053 for (size_t i = 0; i < profiles.size(); ++i) {
1054 std::string country_code = StringToUpperASCII(UTF16ToASCII(
1055 profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY)));
1057 if (std::find(country_codes.begin(), country_codes.end(), country_code) !=
1058 country_codes.end()) {
1059 // Verified profiles count 100x more than unverified ones.
1060 votes[country_code] += profiles[i]->IsVerified() ? 100 : 1;
1064 // Take the most common country code.
1065 if (!votes.empty()) {
1066 std::map<std::string, int>::iterator iter =
1067 std::max_element(votes.begin(), votes.end(), CompareVotes);
1068 return iter->first;
1071 return std::string();
1074 void PersonalDataManager::EnabledPrefChanged() {
1075 default_country_code_.clear();
1076 NotifyPersonalDataChanged();
1079 } // namespace autofill