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/command_line.h"
12 #include "base/i18n/timezone.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/prefs/pref_service.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/autofill_metrics.h"
24 #include "components/autofill/core/browser/form_structure.h"
25 #include "components/autofill/core/browser/personal_data_manager_observer.h"
26 #include "components/autofill/core/browser/phone_number.h"
27 #include "components/autofill/core/browser/phone_number_i18n.h"
28 #include "components/autofill/core/browser/validation.h"
29 #include "components/autofill/core/common/autofill_pref_names.h"
30 #include "components/autofill/core/common/autofill_switches.h"
31 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
32 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_formatter.h"
37 using ::i18n::addressinput::AddressField
;
38 using ::i18n::addressinput::GetStreetAddressLinesAsSingleLine
;
39 using ::i18n::addressinput::STREET_ADDRESS
;
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 // Returns the list of values for the given type in the profile. There may be
143 // more than one (for example, the user can have more than one phone number per
146 // In addition to just getting the values out of the autocomplete profile, this
147 // function handles formatting of the street address into a single string.
148 std::vector
<base::string16
> GetMultiInfoInOneLine(
149 const AutofillProfile
* profile
,
150 const AutofillType
& type
,
151 const std::string app_locale
) {
152 std::vector
<base::string16
> results
;
154 AddressField address_field
;
155 if (i18n::FieldForType(type
.GetStorableType(), &address_field
) &&
156 address_field
== STREET_ADDRESS
) {
157 std::string street_address_line
;
158 GetStreetAddressLinesAsSingleLine(
159 *i18n::CreateAddressDataFromAutofillProfile(*profile
, app_locale
),
160 &street_address_line
);
161 results
.push_back(base::UTF8ToUTF16(street_address_line
));
163 profile
->GetMultiInfo(type
, app_locale
, &results
);
168 // Returns true if the current field contents match what's currently in the
169 // form field. The current field contents must be already canonicalized. In
170 // addition to doing a case-insensitive match, this will do special handling
171 // for phone numbers.
172 bool MatchesInput(const base::string16
& profile_value
,
173 const base::string16
& field_contents_canon
,
174 const AutofillType
& type
) {
175 base::string16 profile_value_canon
=
176 AutofillProfile::CanonicalizeProfileString(profile_value
);
178 if (profile_value_canon
== field_contents_canon
)
181 // Phone numbers could be split in US forms, so field value could be
182 // either prefix or suffix of the phone.
183 if (type
.GetStorableType() == PHONE_HOME_NUMBER
) {
184 return !field_contents_canon
.empty() &&
185 profile_value_canon
.find(field_contents_canon
) !=
186 base::string16::npos
;
192 // Receives the loaded profiles from the web data service and stores them in
193 // |*dest|. The pending handle is the address of the pending handle
194 // corresponding to this request type. This function is used to save both
195 // server and local profiles and credit cards.
196 template<typename ValueType
>
197 void ReceiveLoadedDBvalues(WebDataServiceBase::Handle h
,
198 const WDTypedResult
* result
,
199 WebDataServiceBase::Handle
* pending_handle
,
200 ScopedVector
<ValueType
>* dest
) {
201 DCHECK_EQ(*pending_handle
, h
);
204 const WDResult
<std::vector
<ValueType
*>>* r
=
205 static_cast<const WDResult
<std::vector
<ValueType
*>>*>(result
);
208 for (ValueType
* value
: r
->GetValue())
209 dest
->push_back(value
);
212 // A helper function for finding the maximum value in a string->int map.
213 static bool CompareVotes(const std::pair
<std::string
, int>& a
,
214 const std::pair
<std::string
, int>& b
) {
215 return a
.second
< b
.second
;
218 // Ranks two data models according to their recency of use. Currently this will
219 // place all server (Wallet) cards and addresses below all locally saved ones,
220 // which is probably not what we want. TODO(estade): figure out relative ranking
222 bool RankByMfu(const AutofillDataModel
* a
, const AutofillDataModel
* b
) {
223 if (a
->use_count() != b
->use_count())
224 return a
->use_count() > b
->use_count();
226 // Ties are broken by MRU.
227 return a
->use_date() > b
->use_date();
232 PersonalDataManager::PersonalDataManager(const std::string
& app_locale
)
234 is_data_loaded_(false),
235 pending_profiles_query_(0),
236 pending_server_profiles_query_(0),
237 pending_creditcards_query_(0),
238 pending_server_creditcards_query_(0),
239 app_locale_(app_locale
),
241 is_off_the_record_(false),
242 has_logged_profile_count_(false) {}
244 void PersonalDataManager::Init(scoped_refptr
<AutofillWebDataService
> database
,
245 PrefService
* pref_service
,
246 bool is_off_the_record
) {
247 database_
= database
;
248 SetPrefService(pref_service
);
249 is_off_the_record_
= is_off_the_record
;
251 if (!is_off_the_record_
)
252 AutofillMetrics::LogIsAutofillEnabledAtStartup(IsAutofillEnabled());
254 // WebDataService may not be available in tests.
255 if (!database_
.get())
261 database_
->AddObserver(this);
264 PersonalDataManager::~PersonalDataManager() {
265 CancelPendingQuery(&pending_profiles_query_
);
266 CancelPendingQuery(&pending_server_profiles_query_
);
267 CancelPendingQuery(&pending_creditcards_query_
);
268 CancelPendingQuery(&pending_server_creditcards_query_
);
271 database_
->RemoveObserver(this);
274 void PersonalDataManager::OnWebDataServiceRequestDone(
275 WebDataServiceBase::Handle h
,
276 const WDTypedResult
* result
) {
277 DCHECK(pending_profiles_query_
|| pending_server_profiles_query_
||
278 pending_creditcards_query_
|| pending_server_creditcards_query_
);
281 // Error from the web database.
282 if (h
== pending_creditcards_query_
)
283 pending_creditcards_query_
= 0;
284 else if (h
== pending_profiles_query_
)
285 pending_profiles_query_
= 0;
289 switch (result
->GetType()) {
290 case AUTOFILL_PROFILES_RESULT
:
291 if (h
== pending_profiles_query_
) {
292 ReceiveLoadedDBvalues(h
, result
, &pending_profiles_query_
,
294 LogProfileCount(); // This only logs local profiles.
296 ReceiveLoadedDBvalues(h
, result
, &pending_server_profiles_query_
,
300 case AUTOFILL_CREDITCARDS_RESULT
:
301 if (h
== pending_creditcards_query_
) {
302 ReceiveLoadedDBvalues(h
, result
, &pending_creditcards_query_
,
303 &local_credit_cards_
);
305 ReceiveLoadedDBvalues(h
, result
, &pending_server_creditcards_query_
,
306 &server_credit_cards_
);
313 // If all requests have responded, then all personal data is loaded.
314 if (pending_profiles_query_
== 0 &&
315 pending_creditcards_query_
== 0 &&
316 pending_server_profiles_query_
== 0 &&
317 pending_server_creditcards_query_
== 0) {
318 is_data_loaded_
= true;
319 NotifyPersonalDataChanged();
323 void PersonalDataManager::AutofillMultipleChanged() {
327 void PersonalDataManager::AddObserver(PersonalDataManagerObserver
* observer
) {
328 observers_
.AddObserver(observer
);
331 void PersonalDataManager::RemoveObserver(
332 PersonalDataManagerObserver
* observer
) {
333 observers_
.RemoveObserver(observer
);
336 bool PersonalDataManager::ImportFormData(
337 const FormStructure
& form
,
338 scoped_ptr
<CreditCard
>* imported_credit_card
) {
339 scoped_ptr
<AutofillProfile
> imported_profile(new AutofillProfile
);
340 scoped_ptr
<CreditCard
> local_imported_credit_card(new CreditCard
);
342 const std::string origin
= form
.source_url().spec();
343 imported_profile
->set_origin(origin
);
344 local_imported_credit_card
->set_origin(origin
);
346 // Parse the form and construct a profile based on the information that is
347 // possible to import.
348 int importable_credit_card_fields
= 0;
350 // Detect and discard forms with multiple fields of the same type.
351 // TODO(isherman): Some types are overlapping but not equal, e.g. phone number
352 // parts, address parts.
353 std::set
<ServerFieldType
> types_seen
;
355 // We only set complete phone, so aggregate phone parts in these vars and set
356 // complete at the end.
357 PhoneNumber::PhoneCombineHelper home
;
359 for (size_t i
= 0; i
< form
.field_count(); ++i
) {
360 const AutofillField
* field
= form
.field(i
);
361 base::string16 value
;
362 base::TrimWhitespace(field
->value
, base::TRIM_ALL
, &value
);
364 // If we don't know the type of the field, or the user hasn't entered any
365 // information into the field, then skip it.
366 if (!field
->IsFieldFillable() || value
.empty())
369 AutofillType field_type
= field
->Type();
370 ServerFieldType server_field_type
= field_type
.GetStorableType();
371 FieldTypeGroup
group(field_type
.group());
373 // There can be multiple email fields (e.g. in the case of 'confirm email'
374 // fields) but they must all contain the same value, else the profile is
376 if (server_field_type
== EMAIL_ADDRESS
) {
377 if (types_seen
.count(server_field_type
) &&
378 imported_profile
->GetRawInfo(EMAIL_ADDRESS
) != value
) {
379 imported_profile
.reset();
384 // If the |field_type| and |value| don't pass basic validity checks then
385 // abandon the import.
386 if (!IsValidFieldTypeAndValue(types_seen
, server_field_type
, value
)) {
387 imported_profile
.reset();
388 local_imported_credit_card
.reset();
392 types_seen
.insert(server_field_type
);
394 if (group
== CREDIT_CARD
) {
395 if (LowerCaseEqualsASCII(field
->form_control_type
, "month")) {
396 DCHECK_EQ(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR
, server_field_type
);
397 local_imported_credit_card
->SetInfoForMonthInputType(value
);
399 local_imported_credit_card
->SetInfo(field_type
, value
, app_locale_
);
401 ++importable_credit_card_fields
;
403 // We need to store phone data in the variables, before building the whole
404 // number at the end. The rest of the fields are set "as is".
405 // If the fields are not the phone fields in question home.SetInfo() is
406 // going to return false.
407 if (!home
.SetInfo(field_type
, value
))
408 imported_profile
->SetInfo(field_type
, value
, app_locale_
);
410 // Reject profiles with invalid country information.
411 if (server_field_type
== ADDRESS_HOME_COUNTRY
&&
413 imported_profile
->GetRawInfo(ADDRESS_HOME_COUNTRY
).empty()) {
414 imported_profile
.reset();
420 // Construct the phone number. Reject the profile if the number is invalid.
421 if (imported_profile
.get() && !home
.IsEmpty()) {
422 base::string16 constructed_number
;
423 if (!home
.ParseNumber(*imported_profile
, app_locale_
,
424 &constructed_number
) ||
425 !imported_profile
->SetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER
),
428 imported_profile
.reset();
432 // Reject the profile if minimum address and validation requirements are not
434 if (imported_profile
.get() &&
435 !IsValidLearnableProfile(*imported_profile
, app_locale_
))
436 imported_profile
.reset();
438 // Reject the credit card if we did not detect enough filled credit card
439 // fields or if the credit card number does not seem to be valid.
440 if (local_imported_credit_card
.get() &&
441 !local_imported_credit_card
->IsComplete()) {
442 local_imported_credit_card
.reset();
445 // Don't import if we already have this info.
446 // Don't present an infobar if we have already saved this card number.
447 bool merged_credit_card
= false;
448 if (local_imported_credit_card
) {
449 for (CreditCard
* card
: local_credit_cards_
) {
450 // Make a local copy so that the data in |local_credit_cards_| isn't
451 // modified directly by the UpdateFromImportedCard() call.
452 CreditCard
card_copy(*card
);
453 if (card_copy
.UpdateFromImportedCard(*local_imported_credit_card
.get(),
455 merged_credit_card
= true;
456 UpdateCreditCard(card_copy
);
457 local_imported_credit_card
.reset();
463 // Also don't offer to save if we already have this stored as a full wallet
464 // card. (In particular this comes up just after filling and submitting a
466 if (local_imported_credit_card
) {
467 for (CreditCard
* card
: server_credit_cards_
) {
468 if (card
->record_type() == CreditCard::FULL_SERVER_CARD
&&
469 local_imported_credit_card
->IsLocalDuplicateOfServerCard(*card
)) {
470 local_imported_credit_card
.reset();
476 if (imported_profile
.get()) {
477 // We always save imported profiles.
478 SaveImportedProfile(*imported_profile
);
480 *imported_credit_card
= local_imported_credit_card
.Pass();
482 if (imported_profile
.get() || *imported_credit_card
|| merged_credit_card
)
485 FOR_EACH_OBSERVER(PersonalDataManagerObserver
, observers_
,
486 OnInsufficientFormData());
490 void PersonalDataManager::RecordUseOf(const AutofillDataModel
& data_model
) {
491 if (!database_
.get())
494 CreditCard
* credit_card
= GetCreditCardByGUID(data_model
.guid());
496 credit_card
->RecordUse();
498 if (credit_card
->record_type() == CreditCard::LOCAL_CARD
)
499 database_
->UpdateCreditCard(*credit_card
);
500 else if (credit_card
->record_type() == CreditCard::FULL_SERVER_CARD
)
501 database_
->UpdateUnmaskedCardUsageStats(*credit_card
);
503 NOTREACHED() << " A MASKED_SERVER_CARD can't be used.";
509 AutofillProfile
* profile
= GetProfileByGUID(data_model
.guid());
511 profile
->RecordUse();
512 database_
->UpdateAutofillProfile(*profile
);
517 void PersonalDataManager::AddProfile(const AutofillProfile
& profile
) {
518 if (is_off_the_record_
)
521 if (profile
.IsEmpty(app_locale_
))
524 // Don't add an existing profile.
525 if (FindByGUID
<AutofillProfile
>(web_profiles_
, profile
.guid()))
528 if (!database_
.get())
531 // Don't add a duplicate.
532 if (FindByContents(web_profiles_
, profile
))
535 // Add the new profile to the web database.
536 database_
->AddAutofillProfile(profile
);
538 // Refresh our local cache and send notifications to observers.
542 void PersonalDataManager::UpdateProfile(const AutofillProfile
& profile
) {
543 if (is_off_the_record_
)
546 AutofillProfile
* existing_profile
= GetProfileByGUID(profile
.guid());
547 if (!existing_profile
)
550 // Don't overwrite the origin for a profile that is already stored.
551 if (existing_profile
->EqualsSansOrigin(profile
))
554 if (profile
.IsEmpty(app_locale_
)) {
555 RemoveByGUID(profile
.guid());
559 if (!database_
.get())
563 database_
->UpdateAutofillProfile(profile
);
565 // Refresh our local cache and send notifications to observers.
569 AutofillProfile
* PersonalDataManager::GetProfileByGUID(
570 const std::string
& guid
) {
571 const std::vector
<AutofillProfile
*>& profiles
= GetProfiles();
572 std::vector
<AutofillProfile
*>::const_iterator iter
=
573 FindElementByGUID
<AutofillProfile
>(profiles
, guid
);
574 return (iter
!= profiles
.end()) ? *iter
: NULL
;
577 void PersonalDataManager::AddCreditCard(const CreditCard
& credit_card
) {
578 if (is_off_the_record_
)
581 if (credit_card
.IsEmpty(app_locale_
))
584 if (FindByGUID
<CreditCard
>(local_credit_cards_
, credit_card
.guid()))
587 if (!database_
.get())
590 // Don't add a duplicate.
591 if (FindByContents(local_credit_cards_
, credit_card
))
594 // Add the new credit card to the web database.
595 database_
->AddCreditCard(credit_card
);
597 // Refresh our local cache and send notifications to observers.
601 void PersonalDataManager::UpdateCreditCard(const CreditCard
& credit_card
) {
602 DCHECK_EQ(CreditCard::LOCAL_CARD
, credit_card
.record_type());
603 if (is_off_the_record_
)
606 CreditCard
* existing_credit_card
= GetCreditCardByGUID(credit_card
.guid());
607 if (!existing_credit_card
)
610 // Don't overwrite the origin for a credit card that is already stored.
611 if (existing_credit_card
->Compare(credit_card
) == 0)
614 if (credit_card
.IsEmpty(app_locale_
)) {
615 RemoveByGUID(credit_card
.guid());
619 if (!database_
.get())
623 database_
->UpdateCreditCard(credit_card
);
625 // Refresh our local cache and send notifications to observers.
629 void PersonalDataManager::UpdateServerCreditCard(
630 const CreditCard
& credit_card
) {
631 DCHECK_NE(CreditCard::LOCAL_CARD
, credit_card
.record_type());
633 if (is_off_the_record_
|| !database_
.get())
636 // Look up by server id, not GUID.
637 CreditCard
* existing_credit_card
= nullptr;
638 for (auto it
: server_credit_cards_
) {
639 if (credit_card
.server_id() == it
->server_id()) {
640 existing_credit_card
= it
;
644 if (!existing_credit_card
)
647 DCHECK_NE(existing_credit_card
->record_type(), credit_card
.record_type());
648 DCHECK_EQ(existing_credit_card
->Label(), credit_card
.Label());
649 if (existing_credit_card
->record_type() == CreditCard::MASKED_SERVER_CARD
) {
650 database_
->UnmaskServerCreditCard(credit_card
.server_id(),
651 credit_card
.number());
653 database_
->MaskServerCreditCard(credit_card
.server_id());
659 void PersonalDataManager::ResetFullServerCards() {
660 for (const CreditCard
* card
: server_credit_cards_
) {
661 CreditCard card_copy
= *card
;
662 if (card_copy
.record_type() == CreditCard::FULL_SERVER_CARD
) {
663 card_copy
.set_record_type(CreditCard::MASKED_SERVER_CARD
);
664 card_copy
.SetNumber(card
->LastFourDigits());
665 UpdateServerCreditCard(card_copy
);
670 void PersonalDataManager::RemoveByGUID(const std::string
& guid
) {
671 if (is_off_the_record_
)
674 bool is_credit_card
= FindByGUID
<CreditCard
>(local_credit_cards_
, guid
);
675 bool is_profile
= !is_credit_card
&&
676 FindByGUID
<AutofillProfile
>(web_profiles_
, guid
);
677 if (!is_credit_card
&& !is_profile
)
680 if (!database_
.get())
684 database_
->RemoveCreditCard(guid
);
686 database_
->RemoveAutofillProfile(guid
);
688 // Refresh our local cache and send notifications to observers.
692 CreditCard
* PersonalDataManager::GetCreditCardByGUID(const std::string
& guid
) {
693 const std::vector
<CreditCard
*>& credit_cards
= GetCreditCards();
694 std::vector
<CreditCard
*>::const_iterator iter
=
695 FindElementByGUID
<CreditCard
>(credit_cards
, guid
);
696 return (iter
!= credit_cards
.end()) ? *iter
: NULL
;
699 void PersonalDataManager::GetNonEmptyTypes(
700 ServerFieldTypeSet
* non_empty_types
) {
701 for (AutofillProfile
* profile
: GetProfiles())
702 profile
->GetNonEmptyTypes(app_locale_
, non_empty_types
);
703 for (CreditCard
* card
: GetCreditCards())
704 card
->GetNonEmptyTypes(app_locale_
, non_empty_types
);
707 bool PersonalDataManager::IsDataLoaded() const {
708 return is_data_loaded_
;
711 const std::vector
<AutofillProfile
*>& PersonalDataManager::GetProfiles() const {
712 return GetProfiles(false);
715 const std::vector
<AutofillProfile
*>& PersonalDataManager::web_profiles() const {
716 return web_profiles_
.get();
719 const std::vector
<CreditCard
*>& PersonalDataManager::GetLocalCreditCards()
721 return local_credit_cards_
.get();
724 const std::vector
<CreditCard
*>& PersonalDataManager::GetCreditCards() const {
725 credit_cards_
.clear();
726 credit_cards_
.insert(credit_cards_
.end(), local_credit_cards_
.begin(),
727 local_credit_cards_
.end());
728 if (IsExperimentalWalletIntegrationEnabled() &&
729 pref_service_
->GetBoolean(prefs::kAutofillWalletImportEnabled
)) {
730 credit_cards_
.insert(credit_cards_
.end(), server_credit_cards_
.begin(),
731 server_credit_cards_
.end());
733 return credit_cards_
;
736 void PersonalDataManager::Refresh() {
741 std::vector
<Suggestion
> PersonalDataManager::GetProfileSuggestions(
742 const AutofillType
& type
,
743 const base::string16
& field_contents
,
744 bool field_is_autofilled
,
745 const std::vector
<ServerFieldType
>& other_field_types
) {
746 std::vector
<Suggestion
> suggestions
;
747 base::string16 field_contents_canon
=
748 AutofillProfile::CanonicalizeProfileString(field_contents
);
750 std::vector
<AutofillProfile
*> profiles
= GetProfiles(true);
751 std::sort(profiles
.begin(), profiles
.end(), RankByMfu
);
753 if (field_is_autofilled
) {
754 // This field was previously autofilled. In this case, suggesting results
755 // based on prefix is useless since it will be the same thing. Instead,
756 // check for a field that may have multiple possible values (for example,
757 // multiple names for the same address) and suggest the alternates. This
758 // allows for easy correction of the data.
759 for (AutofillProfile
* profile
: profiles
) {
760 std::vector
<base::string16
> values
=
761 GetMultiInfoInOneLine(profile
, type
, app_locale_
);
763 // Check if the contents of this field match any of the inputs.
764 bool matches_field
= false;
765 for (const base::string16
& value
: values
) {
766 if (MatchesInput(value
, field_contents_canon
, type
)) {
767 matches_field
= true;
773 // Field unmodified, make alternate suggestions.
774 for (size_t i
= 0; i
< values
.size(); i
++) {
775 if (values
[i
].empty())
777 suggestions
.push_back(Suggestion(values
[i
]));
778 suggestions
.back().backend_id
.guid
= profile
->guid();
779 suggestions
.back().backend_id
.variant
= i
;
784 // Match based on a prefix search.
785 std::vector
<AutofillProfile
*> matched_profiles
;
786 for (AutofillProfile
* profile
: profiles
) {
787 std::vector
<base::string16
> values
=
788 GetMultiInfoInOneLine(profile
, type
, app_locale_
);
789 for (size_t i
= 0; i
< values
.size(); i
++) {
790 if (values
[i
].empty())
793 base::string16 value_canon
=
794 AutofillProfile::CanonicalizeProfileString(values
[i
]);
795 if (StartsWith(value_canon
, field_contents_canon
, true)) {
796 // Prefix match, add suggestion.
797 matched_profiles
.push_back(profile
);
798 suggestions
.push_back(Suggestion(values
[i
]));
799 suggestions
.back().backend_id
.guid
= profile
->guid();
800 suggestions
.back().backend_id
.variant
= i
;
805 // Generate disambiguating labels based on the list of matches.
806 std::vector
<base::string16
> labels
;
807 AutofillProfile::CreateInferredLabels(
808 matched_profiles
, &other_field_types
,
809 type
.GetStorableType(), 1, app_locale_
, &labels
);
810 DCHECK_EQ(suggestions
.size(), labels
.size());
811 for (size_t i
= 0; i
< labels
.size(); i
++)
812 suggestions
[i
].label
= labels
[i
];
818 std::vector
<Suggestion
> PersonalDataManager::GetCreditCardSuggestions(
819 const AutofillType
& type
,
820 const base::string16
& field_contents
) {
821 std::list
<const CreditCard
*> cards_to_suggest
;
822 for (const CreditCard
* credit_card
: GetCreditCards()) {
823 // The value of the stored data for this field type in the |credit_card|.
824 base::string16 creditcard_field_value
=
825 credit_card
->GetInfo(type
, app_locale_
);
826 if (creditcard_field_value
.empty())
829 // For card number fields, suggest the card if:
830 // - the number matches any part of the card, or
831 // - it's a masked card and there are 6 or fewers typed so far.
832 // For other fields, require that the field contents match the beginning of
834 if (type
.GetStorableType() == CREDIT_CARD_NUMBER
) {
835 if (creditcard_field_value
.find(field_contents
) == base::string16::npos
&&
836 (credit_card
->record_type() != CreditCard::MASKED_SERVER_CARD
||
837 field_contents
.size() >= 6)) {
840 } else if (!StartsWith(creditcard_field_value
, field_contents
, false)) {
844 cards_to_suggest
.push_back(credit_card
);
847 // Server cards shadow identical local cards.
848 for (auto outer_it
= cards_to_suggest
.begin();
849 outer_it
!= cards_to_suggest
.end();
851 if ((*outer_it
)->record_type() == CreditCard::LOCAL_CARD
)
854 for (auto inner_it
= cards_to_suggest
.begin();
855 inner_it
!= cards_to_suggest
.end();) {
856 auto inner_it_copy
= inner_it
++;
857 if ((*inner_it_copy
)->IsLocalDuplicateOfServerCard(**outer_it
))
858 cards_to_suggest
.erase(inner_it_copy
);
862 cards_to_suggest
.sort(RankByMfu
);
864 std::vector
<Suggestion
> suggestions
;
865 for (const CreditCard
* credit_card
: cards_to_suggest
) {
866 // Make a new suggestion.
867 suggestions
.push_back(Suggestion());
868 Suggestion
* suggestion
= &suggestions
.back();
870 suggestion
->value
= credit_card
->GetInfo(type
, app_locale_
);
871 suggestion
->icon
= base::UTF8ToUTF16(credit_card
->type());
872 suggestion
->backend_id
.guid
= credit_card
->guid();
874 // If the value is the card number, the label is the expiration date.
875 // Otherwise the label is the card number, or if that is empty the
876 // cardholder name. The label should never repeat the value.
877 if (type
.GetStorableType() == CREDIT_CARD_NUMBER
) {
878 suggestion
->value
= credit_card
->TypeAndLastFourDigits();
879 suggestion
->label
= credit_card
->GetInfo(
880 AutofillType(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR
), app_locale_
);
881 } else if (credit_card
->number().empty()) {
882 if (type
.GetStorableType() != CREDIT_CARD_NAME
) {
884 credit_card
->GetInfo(AutofillType(CREDIT_CARD_NAME
), app_locale_
);
887 #if defined(OS_ANDROID)
888 // Since Android places the label on its own row, there's more horizontal
889 // space to work with. Show "Amex - 1234" rather than desktop's "*1234".
890 suggestion
->label
= credit_card
->TypeAndLastFourDigits();
892 suggestion
->label
= base::ASCIIToUTF16("*");
893 suggestion
->label
.append(credit_card
->LastFourDigits());
900 bool PersonalDataManager::IsAutofillEnabled() const {
901 DCHECK(pref_service_
);
902 return pref_service_
->GetBoolean(prefs::kAutofillEnabled
);
905 std::string
PersonalDataManager::CountryCodeForCurrentTimezone() const {
906 return base::CountryCodeForCurrentTimezone();
909 void PersonalDataManager::SetPrefService(PrefService
* pref_service
) {
910 enabled_pref_
.reset(new BooleanPrefMember
);
911 pref_service_
= pref_service
;
912 // |pref_service_| can be NULL in tests.
914 enabled_pref_
->Init(prefs::kAutofillEnabled
, pref_service_
,
915 base::Bind(&PersonalDataManager::EnabledPrefChanged
,
916 base::Unretained(this)));
921 bool PersonalDataManager::IsValidLearnableProfile(
922 const AutofillProfile
& profile
,
923 const std::string
& app_locale
) {
924 if (!IsMinimumAddress(profile
, app_locale
))
927 base::string16 email
= profile
.GetRawInfo(EMAIL_ADDRESS
);
928 if (!email
.empty() && !IsValidEmailAddress(email
))
931 // Reject profiles with invalid US state information.
932 if (profile
.IsPresentButInvalid(ADDRESS_HOME_STATE
))
935 // Reject profiles with invalid US zip information.
936 if (profile
.IsPresentButInvalid(ADDRESS_HOME_ZIP
))
943 std::string
PersonalDataManager::MergeProfile(
944 const AutofillProfile
& new_profile
,
945 const std::vector
<AutofillProfile
*>& existing_profiles
,
946 const std::string
& app_locale
,
947 std::vector
<AutofillProfile
>* merged_profiles
) {
948 merged_profiles
->clear();
950 // Set to true if |existing_profiles| already contains an equivalent profile.
951 bool matching_profile_found
= false;
952 std::string guid
= new_profile
.guid();
954 // If we have already saved this address, merge in any missing values.
955 // Only merge with the first match.
956 for (AutofillProfile
* existing_profile
: existing_profiles
) {
957 if (!matching_profile_found
&&
958 !new_profile
.PrimaryValue().empty() &&
959 AutofillProfile::AreProfileStringsSimilar(
960 existing_profile
->PrimaryValue(),
961 new_profile
.PrimaryValue())) {
962 // Unverified profiles should always be updated with the newer data,
963 // whereas verified profiles should only ever be overwritten by verified
964 // data. If an automatically aggregated profile would overwrite a
965 // verified profile, just drop it.
966 matching_profile_found
= true;
967 guid
= existing_profile
->guid();
968 if (!existing_profile
->IsVerified() || new_profile
.IsVerified())
969 existing_profile
->OverwriteWithOrAddTo(new_profile
, app_locale
);
971 merged_profiles
->push_back(*existing_profile
);
974 // If the new profile was not merged with an existing one, add it to the list.
975 if (!matching_profile_found
)
976 merged_profiles
->push_back(new_profile
);
981 bool PersonalDataManager::IsCountryOfInterest(const std::string
& country_code
)
983 DCHECK_EQ(2U, country_code
.size());
985 const std::vector
<AutofillProfile
*>& profiles
= web_profiles();
986 std::list
<std::string
> country_codes
;
987 for (size_t i
= 0; i
< profiles
.size(); ++i
) {
988 country_codes
.push_back(base::StringToLowerASCII(base::UTF16ToASCII(
989 profiles
[i
]->GetRawInfo(ADDRESS_HOME_COUNTRY
))));
992 std::string timezone_country
= CountryCodeForCurrentTimezone();
993 if (!timezone_country
.empty())
994 country_codes
.push_back(base::StringToLowerASCII(timezone_country
));
996 // Only take the locale into consideration if all else fails.
997 if (country_codes
.empty()) {
998 country_codes
.push_back(base::StringToLowerASCII(
999 AutofillCountry::CountryCodeForLocale(app_locale())));
1002 return std::find(country_codes
.begin(), country_codes
.end(),
1003 base::StringToLowerASCII(country_code
)) !=
1004 country_codes
.end();
1007 const std::string
& PersonalDataManager::GetDefaultCountryCodeForNewAddress()
1009 if (default_country_code_
.empty())
1010 default_country_code_
= MostCommonCountryCodeFromProfiles();
1012 // Failing that, guess based on system timezone.
1013 if (default_country_code_
.empty())
1014 default_country_code_
= CountryCodeForCurrentTimezone();
1016 // Failing that, guess based on locale.
1017 if (default_country_code_
.empty())
1018 default_country_code_
= AutofillCountry::CountryCodeForLocale(app_locale());
1020 return default_country_code_
;
1023 bool PersonalDataManager::IsExperimentalWalletIntegrationEnabled() const {
1024 return pref_service_
->GetBoolean(prefs::kAutofillWalletSyncExperimentEnabled
);
1027 void PersonalDataManager::SetProfiles(std::vector
<AutofillProfile
>* profiles
) {
1028 if (is_off_the_record_
)
1031 // Remove empty profiles from input.
1032 profiles
->erase(std::remove_if(profiles
->begin(), profiles
->end(),
1033 IsEmptyFunctor
<AutofillProfile
>(app_locale_
)),
1036 if (!database_
.get())
1039 // Any profiles that are not in the new profile list should be removed from
1040 // the web database.
1041 for (std::vector
<AutofillProfile
*>::const_iterator iter
=
1042 web_profiles_
.begin();
1043 iter
!= web_profiles_
.end(); ++iter
) {
1044 if (!FindByGUID
<AutofillProfile
>(*profiles
, (*iter
)->guid()))
1045 database_
->RemoveAutofillProfile((*iter
)->guid());
1048 // Update the web database with the existing profiles.
1049 for (std::vector
<AutofillProfile
>::iterator iter
= profiles
->begin();
1050 iter
!= profiles
->end(); ++iter
) {
1051 if (FindByGUID
<AutofillProfile
>(web_profiles_
, iter
->guid()))
1052 database_
->UpdateAutofillProfile(*iter
);
1055 // Add the new profiles to the web database. Don't add a duplicate.
1056 for (std::vector
<AutofillProfile
>::iterator iter
= profiles
->begin();
1057 iter
!= profiles
->end(); ++iter
) {
1058 if (!FindByGUID
<AutofillProfile
>(web_profiles_
, iter
->guid()) &&
1059 !FindByContents(web_profiles_
, *iter
))
1060 database_
->AddAutofillProfile(*iter
);
1063 // Copy in the new profiles.
1064 web_profiles_
.clear();
1065 for (std::vector
<AutofillProfile
>::iterator iter
= profiles
->begin();
1066 iter
!= profiles
->end(); ++iter
) {
1067 web_profiles_
.push_back(new AutofillProfile(*iter
));
1070 // Refresh our local cache and send notifications to observers.
1074 void PersonalDataManager::SetCreditCards(
1075 std::vector
<CreditCard
>* credit_cards
) {
1076 if (is_off_the_record_
)
1079 // Remove empty credit cards from input.
1080 credit_cards
->erase(std::remove_if(credit_cards
->begin(), credit_cards
->end(),
1081 IsEmptyFunctor
<CreditCard
>(app_locale_
)),
1082 credit_cards
->end());
1084 if (!database_
.get())
1087 // Any credit cards that are not in the new credit card list should be
1089 for (const CreditCard
* card
: local_credit_cards_
) {
1090 if (!FindByGUID
<CreditCard
>(*credit_cards
, card
->guid()))
1091 database_
->RemoveCreditCard(card
->guid());
1094 // Update the web database with the existing credit cards.
1095 for (const CreditCard
& card
: *credit_cards
) {
1096 if (FindByGUID
<CreditCard
>(local_credit_cards_
, card
.guid()))
1097 database_
->UpdateCreditCard(card
);
1100 // Add the new credit cards to the web database. Don't add a duplicate.
1101 for (const CreditCard
& card
: *credit_cards
) {
1102 if (!FindByGUID
<CreditCard
>(local_credit_cards_
, card
.guid()) &&
1103 !FindByContents(local_credit_cards_
, card
))
1104 database_
->AddCreditCard(card
);
1107 // Copy in the new credit cards.
1108 local_credit_cards_
.clear();
1109 for (const CreditCard
& card
: *credit_cards
)
1110 local_credit_cards_
.push_back(new CreditCard(card
));
1112 // Refresh our local cache and send notifications to observers.
1116 void PersonalDataManager::LoadProfiles() {
1117 if (!database_
.get()) {
1122 CancelPendingQuery(&pending_profiles_query_
);
1123 CancelPendingQuery(&pending_server_profiles_query_
);
1125 pending_profiles_query_
= database_
->GetAutofillProfiles(this);
1126 pending_server_profiles_query_
= database_
->GetAutofillServerProfiles(this);
1129 // Win, Linux, Android and iOS implementations do nothing. Mac implementation
1130 // fills in the contents of |auxiliary_profiles_|.
1131 #if defined(OS_IOS) || !defined(OS_MACOSX)
1132 void PersonalDataManager::LoadAuxiliaryProfiles(bool record_metrics
) const {
1136 void PersonalDataManager::LoadCreditCards() {
1137 if (!database_
.get()) {
1142 CancelPendingQuery(&pending_creditcards_query_
);
1143 CancelPendingQuery(&pending_server_creditcards_query_
);
1145 pending_creditcards_query_
= database_
->GetCreditCards(this);
1146 pending_server_creditcards_query_
= database_
->GetServerCreditCards(this);
1149 void PersonalDataManager::CancelPendingQuery(
1150 WebDataServiceBase::Handle
* handle
) {
1152 if (!database_
.get()) {
1156 database_
->CancelRequest(*handle
);
1161 std::string
PersonalDataManager::SaveImportedProfile(
1162 const AutofillProfile
& imported_profile
) {
1163 if (is_off_the_record_
)
1164 return std::string();
1166 // Don't save a web profile if the data in the profile is a subset of an
1167 // auxiliary profile.
1168 for (std::vector
<AutofillProfile
*>::const_iterator iter
=
1169 auxiliary_profiles_
.begin();
1170 iter
!= auxiliary_profiles_
.end(); ++iter
) {
1171 if (imported_profile
.IsSubsetOf(**iter
, app_locale_
))
1172 return (*iter
)->guid();
1175 std::vector
<AutofillProfile
> profiles
;
1177 MergeProfile(imported_profile
, web_profiles_
.get(), app_locale_
,
1179 SetProfiles(&profiles
);
1183 void PersonalDataManager::NotifyPersonalDataChanged() {
1184 FOR_EACH_OBSERVER(PersonalDataManagerObserver
, observers_
,
1185 OnPersonalDataChanged());
1188 std::string
PersonalDataManager::SaveImportedCreditCard(
1189 const CreditCard
& imported_card
) {
1190 DCHECK(!imported_card
.number().empty());
1191 if (is_off_the_record_
)
1192 return std::string();
1194 // Set to true if |imported_card| is merged into the credit card list.
1195 bool merged
= false;
1197 std::string guid
= imported_card
.guid();
1198 std::vector
<CreditCard
> credit_cards
;
1199 for (CreditCard
* card
: local_credit_cards_
) {
1200 // If |imported_card| has not yet been merged, check whether it should be
1201 // with the current |card|.
1202 if (!merged
&& card
->UpdateFromImportedCard(imported_card
, app_locale_
)) {
1203 guid
= card
->guid();
1207 credit_cards
.push_back(*card
);
1211 credit_cards
.push_back(imported_card
);
1213 SetCreditCards(&credit_cards
);
1217 void PersonalDataManager::LogProfileCount() const {
1218 if (!has_logged_profile_count_
) {
1219 AutofillMetrics::LogStoredProfileCount(web_profiles_
.size());
1220 has_logged_profile_count_
= true;
1224 std::string
PersonalDataManager::MostCommonCountryCodeFromProfiles() const {
1225 if (!IsAutofillEnabled())
1226 return std::string();
1228 // Count up country codes from existing profiles.
1229 std::map
<std::string
, int> votes
;
1230 // TODO(estade): can we make this GetProfiles() instead? It seems to cause
1231 // errors in tests on mac trybots. See http://crbug.com/57221
1232 const std::vector
<AutofillProfile
*>& profiles
= web_profiles();
1233 std::vector
<std::string
> country_codes
;
1234 AutofillCountry::GetAvailableCountries(&country_codes
);
1235 for (size_t i
= 0; i
< profiles
.size(); ++i
) {
1236 std::string country_code
= StringToUpperASCII(base::UTF16ToASCII(
1237 profiles
[i
]->GetRawInfo(ADDRESS_HOME_COUNTRY
)));
1239 if (std::find(country_codes
.begin(), country_codes
.end(), country_code
) !=
1240 country_codes
.end()) {
1241 // Verified profiles count 100x more than unverified ones.
1242 votes
[country_code
] += profiles
[i
]->IsVerified() ? 100 : 1;
1246 // Take the most common country code.
1247 if (!votes
.empty()) {
1248 std::map
<std::string
, int>::iterator iter
=
1249 std::max_element(votes
.begin(), votes
.end(), CompareVotes
);
1253 return std::string();
1256 void PersonalDataManager::EnabledPrefChanged() {
1257 default_country_code_
.clear();
1258 NotifyPersonalDataChanged();
1261 const std::vector
<AutofillProfile
*>& PersonalDataManager::GetProfiles(
1262 bool record_metrics
) const {
1263 #if defined(OS_MACOSX) && !defined(OS_IOS)
1264 bool use_auxiliary_profiles
=
1265 pref_service_
->GetBoolean(prefs::kAutofillUseMacAddressBook
);
1267 bool use_auxiliary_profiles
=
1268 pref_service_
->GetBoolean(prefs::kAutofillAuxiliaryProfilesEnabled
);
1269 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
1272 profiles_
.insert(profiles_
.end(), web_profiles().begin(),
1273 web_profiles().end());
1274 if (use_auxiliary_profiles
) {
1275 LoadAuxiliaryProfiles(record_metrics
);
1277 profiles_
.end(), auxiliary_profiles_
.begin(),
1278 auxiliary_profiles_
.end());
1280 if (IsExperimentalWalletIntegrationEnabled() &&
1281 pref_service_
->GetBoolean(prefs::kAutofillWalletImportEnabled
)) {
1283 profiles_
.end(), server_profiles_
.begin(), server_profiles_
.end());
1288 } // namespace autofill