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 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 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())
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
->Compare(profile
) == 0)
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 std::vector
<base::string16
>* values
,
562 std::vector
<base::string16
>* labels
,
563 std::vector
<base::string16
>* icons
,
564 std::vector
<GUIDPair
>* guid_pairs
) {
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
));
590 if (multi_values
[i
].empty())
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
625 if (!field_is_autofilled
) {
626 AutofillProfile::CreateInferredLabels(
627 matched_profiles
, &other_field_types
,
628 type
.GetStorableType(), 1, labels
);
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
) {
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.
667 credit_card
->GetInfo(AutofillType(CREDIT_CARD_NAME
), app_locale_
);
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.
695 enabled_pref_
->Init(prefs::kAutofillEnabled
, pref_service_
,
696 base::Bind(&PersonalDataManager::EnabledPrefChanged
,
697 base::Unretained(this)));
702 bool PersonalDataManager::IsValidLearnableProfile(
703 const AutofillProfile
& profile
,
704 const std::string
& app_locale
) {
705 if (!IsMinimumAddress(profile
, app_locale
))
708 base::string16 email
= profile
.GetRawInfo(EMAIL_ADDRESS
);
709 if (!email
.empty() && !IsValidEmailAddress(email
))
712 // Reject profiles with invalid US state information.
713 if (profile
.IsPresentButInvalid(ADDRESS_HOME_STATE
))
716 // Reject profiles with invalid US zip information.
717 if (profile
.IsPresentButInvalid(ADDRESS_HOME_ZIP
))
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
);
764 bool PersonalDataManager::IsCountryOfInterest(const std::string
& country_code
)
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()
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_
)
809 // Remove empty profiles from input.
810 profiles
->erase(std::remove_if(profiles
->begin(), profiles
->end(),
811 IsEmptyFunctor
<AutofillProfile
>(app_locale_
)),
814 if (!database_
.get())
817 // Any profiles that are not in the new profile list should be removed from
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.
852 void PersonalDataManager::SetCreditCards(
853 std::vector
<CreditCard
>* credit_cards
) {
854 if (is_off_the_record_
)
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())
865 // Any credit cards that are not in the new credit card list should be
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.
899 void PersonalDataManager::LoadProfiles() {
900 if (!database_
.get()) {
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 {
917 void PersonalDataManager::LoadCreditCards() {
918 if (!database_
.get()) {
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
);
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
) {
967 if (!database_
.get()) {
971 database_
->CancelRequest(*handle
);
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
;
992 MergeProfile(imported_profile
, web_profiles_
.get(), app_locale_
,
994 SetProfiles(&profiles
);
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();
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();
1025 credit_cards
.push_back(*card
);
1029 credit_cards
.push_back(imported_card
);
1031 SetCreditCards(&credit_cards
);
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
);
1071 return std::string();
1074 void PersonalDataManager::EnabledPrefChanged() {
1075 default_country_code_
.clear();
1076 NotifyPersonalDataChanged();
1079 } // namespace autofill