Rename GetIconID to GetIconId
[chromium-blink-merge.git] / components / autofill / core / browser / personal_data_manager.cc
blob6c62dbc56c73e44bf57be4f84b7e33a4eea84e66
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/command_line.h"
12 #include "base/i18n/case_conversion.h"
13 #include "base/i18n/timezone.h"
14 #include "base/logging.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/prefs/pref_service.h"
17 #include "base/profiler/scoped_tracker.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "components/autofill/core/browser/address_i18n.h"
22 #include "components/autofill/core/browser/autofill-inl.h"
23 #include "components/autofill/core/browser/autofill_country.h"
24 #include "components/autofill/core/browser/autofill_experiments.h"
25 #include "components/autofill/core/browser/autofill_field.h"
26 #include "components/autofill/core/browser/autofill_metrics.h"
27 #include "components/autofill/core/browser/form_structure.h"
28 #include "components/autofill/core/browser/personal_data_manager_observer.h"
29 #include "components/autofill/core/browser/phone_number.h"
30 #include "components/autofill/core/browser/phone_number_i18n.h"
31 #include "components/autofill/core/browser/validation.h"
32 #include "components/autofill/core/common/autofill_pref_names.h"
33 #include "components/autofill/core/common/autofill_switches.h"
34 #include "components/autofill/core/common/autofill_util.h"
35 #include "components/signin/core/browser/account_tracker_service.h"
36 #include "components/signin/core/common/signin_pref_names.h"
37 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
38 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_formatter.h"
40 namespace autofill {
41 namespace {
43 using ::i18n::addressinput::AddressField;
44 using ::i18n::addressinput::GetStreetAddressLinesAsSingleLine;
45 using ::i18n::addressinput::STREET_ADDRESS;
47 template<typename T>
48 class FormGroupMatchesByGUIDFunctor {
49 public:
50 explicit FormGroupMatchesByGUIDFunctor(const std::string& guid)
51 : guid_(guid) {
54 bool operator()(const T& form_group) {
55 return form_group.guid() == guid_;
58 bool operator()(const T* form_group) {
59 return form_group->guid() == guid_;
62 private:
63 const std::string guid_;
66 template<typename T, typename C>
67 typename C::const_iterator FindElementByGUID(const C& container,
68 const std::string& guid) {
69 return std::find_if(container.begin(),
70 container.end(),
71 FormGroupMatchesByGUIDFunctor<T>(guid));
74 template<typename T, typename C>
75 bool FindByGUID(const C& container, const std::string& guid) {
76 return FindElementByGUID<T>(container, guid) != container.end();
79 template<typename T>
80 class IsEmptyFunctor {
81 public:
82 explicit IsEmptyFunctor(const std::string& app_locale)
83 : app_locale_(app_locale) {
86 bool operator()(const T& form_group) {
87 return form_group.IsEmpty(app_locale_);
90 private:
91 const std::string app_locale_;
94 // Returns true if minimum requirements for import of a given |profile| have
95 // been met. An address submitted via a form must have at least the fields
96 // required as determined by its country code.
97 // No verification of validity of the contents is preformed. This is an
98 // existence check only.
99 bool IsMinimumAddress(const AutofillProfile& profile,
100 const std::string& app_locale) {
101 // All countries require at least one address line.
102 if (profile.GetRawInfo(ADDRESS_HOME_LINE1).empty())
103 return false;
105 std::string country_code =
106 base::UTF16ToASCII(profile.GetRawInfo(ADDRESS_HOME_COUNTRY));
107 if (country_code.empty())
108 country_code = AutofillCountry::CountryCodeForLocale(app_locale);
110 AutofillCountry country(country_code, app_locale);
112 if (country.requires_city() && profile.GetRawInfo(ADDRESS_HOME_CITY).empty())
113 return false;
115 if (country.requires_state() &&
116 profile.GetRawInfo(ADDRESS_HOME_STATE).empty())
117 return false;
119 if (country.requires_zip() && profile.GetRawInfo(ADDRESS_HOME_ZIP).empty())
120 return false;
122 return true;
125 // Return true if the |field_type| and |value| are valid within the context
126 // of importing a form.
127 bool IsValidFieldTypeAndValue(const std::set<ServerFieldType>& types_seen,
128 ServerFieldType field_type,
129 const base::string16& value) {
130 // Abandon the import if two fields of the same type are encountered.
131 // This indicates ambiguous data or miscategorization of types.
132 // Make an exception for PHONE_HOME_NUMBER however as both prefix and
133 // suffix are stored against this type, and for EMAIL_ADDRESS because it is
134 // common to see second 'confirm email address' fields on forms.
135 if (types_seen.count(field_type) &&
136 field_type != PHONE_HOME_NUMBER &&
137 field_type != EMAIL_ADDRESS)
138 return false;
140 // Abandon the import if an email address value shows up in a field that is
141 // not an email address.
142 if (field_type != EMAIL_ADDRESS && IsValidEmailAddress(value))
143 return false;
145 return true;
148 // In addition to just getting the values out of the autocomplete profile, this
149 // function handles formatting of the street address into a single string.
150 base::string16 GetInfoInOneLine(const AutofillProfile* profile,
151 const AutofillType& type,
152 const std::string app_locale) {
153 std::vector<base::string16> results;
155 AddressField address_field;
156 if (i18n::FieldForType(type.GetStorableType(), &address_field) &&
157 address_field == STREET_ADDRESS) {
158 std::string street_address_line;
159 GetStreetAddressLinesAsSingleLine(
160 *i18n::CreateAddressDataFromAutofillProfile(*profile, app_locale),
161 &street_address_line);
162 return base::UTF8ToUTF16(street_address_line);
165 return profile->GetInfo(type, app_locale);
168 // Receives the loaded profiles from the web data service and stores them in
169 // |*dest|. The pending handle is the address of the pending handle
170 // corresponding to this request type. This function is used to save both
171 // server and local profiles and credit cards.
172 template <typename ValueType>
173 void ReceiveLoadedDbValues(WebDataServiceBase::Handle h,
174 const WDTypedResult* result,
175 WebDataServiceBase::Handle* pending_handle,
176 ScopedVector<ValueType>* dest) {
177 DCHECK_EQ(*pending_handle, h);
178 *pending_handle = 0;
180 const WDResult<std::vector<ValueType*>>* r =
181 static_cast<const WDResult<std::vector<ValueType*>>*>(result);
183 dest->clear();
184 for (ValueType* value : r->GetValue())
185 dest->push_back(value);
188 // A helper function for finding the maximum value in a string->int map.
189 static bool CompareVotes(const std::pair<std::string, int>& a,
190 const std::pair<std::string, int>& b) {
191 return a.second < b.second;
194 // Ranks two data models according to their recency of use. Currently this will
195 // place all server (Wallet) cards and addresses below all locally saved ones,
196 // which is probably not what we want. TODO(estade): figure out relative ranking
197 // of server data.
198 bool RankByMfu(const AutofillDataModel* a, const AutofillDataModel* b) {
199 if (a->use_count() != b->use_count())
200 return a->use_count() > b->use_count();
202 // Ties are broken by MRU.
203 return a->use_date() > b->use_date();
206 } // namespace
208 PersonalDataManager::PersonalDataManager(const std::string& app_locale)
209 : database_(NULL),
210 is_data_loaded_(false),
211 pending_profiles_query_(0),
212 pending_server_profiles_query_(0),
213 pending_creditcards_query_(0),
214 pending_server_creditcards_query_(0),
215 app_locale_(app_locale),
216 pref_service_(NULL),
217 account_tracker_(NULL),
218 is_off_the_record_(false),
219 has_logged_profile_count_(false) {}
221 void PersonalDataManager::Init(scoped_refptr<AutofillWebDataService> database,
222 PrefService* pref_service,
223 AccountTrackerService* account_tracker,
224 bool is_off_the_record) {
225 database_ = database;
226 SetPrefService(pref_service);
227 account_tracker_ = account_tracker;
228 is_off_the_record_ = is_off_the_record;
230 if (!is_off_the_record_)
231 AutofillMetrics::LogIsAutofillEnabledAtStartup(IsAutofillEnabled());
233 // WebDataService may not be available in tests.
234 if (!database_.get())
235 return;
237 LoadProfiles();
238 LoadCreditCards();
240 database_->AddObserver(this);
243 PersonalDataManager::~PersonalDataManager() {
244 CancelPendingQuery(&pending_profiles_query_);
245 CancelPendingQuery(&pending_server_profiles_query_);
246 CancelPendingQuery(&pending_creditcards_query_);
247 CancelPendingQuery(&pending_server_creditcards_query_);
249 if (database_.get())
250 database_->RemoveObserver(this);
253 void PersonalDataManager::OnWebDataServiceRequestDone(
254 WebDataServiceBase::Handle h,
255 const WDTypedResult* result) {
256 DCHECK(pending_profiles_query_ || pending_server_profiles_query_ ||
257 pending_creditcards_query_ || pending_server_creditcards_query_);
259 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
260 // fixed.
261 tracked_objects::ScopedTracker tracking_profile(
262 FROM_HERE_WITH_EXPLICIT_FUNCTION(
263 "422460 PersonalDataManager::OnWebDataServiceRequestDone"));
265 if (!result) {
266 // Error from the web database.
267 if (h == pending_creditcards_query_)
268 pending_creditcards_query_ = 0;
269 else if (h == pending_profiles_query_)
270 pending_profiles_query_ = 0;
271 return;
274 switch (result->GetType()) {
275 case AUTOFILL_PROFILES_RESULT:
276 if (h == pending_profiles_query_) {
277 ReceiveLoadedDbValues(h, result, &pending_profiles_query_,
278 &web_profiles_);
279 LogProfileCount(); // This only logs local profiles.
280 } else {
281 ReceiveLoadedDbValues(h, result, &pending_server_profiles_query_,
282 &server_profiles_);
284 if (!server_profiles_.empty()) {
285 std::string account_id =
286 pref_service_->GetString(::prefs::kGoogleServicesAccountId);
287 base::string16 email =
288 base::UTF8ToUTF16(
289 account_tracker_->GetAccountInfo(account_id).email);
290 DCHECK(!email.empty());
291 for (AutofillProfile* profile : server_profiles_)
292 profile->SetRawInfo(EMAIL_ADDRESS, email);
295 break;
296 case AUTOFILL_CREDITCARDS_RESULT:
297 if (h == pending_creditcards_query_) {
298 ReceiveLoadedDbValues(h, result, &pending_creditcards_query_,
299 &local_credit_cards_);
300 } else {
301 ReceiveLoadedDbValues(h, result, &pending_server_creditcards_query_,
302 &server_credit_cards_);
304 // If the user has a saved unmasked server card and the experiment is
305 // disabled, force mask all cards back to the unsaved state.
306 if (!OfferStoreUnmaskedCards())
307 ResetFullServerCards();
309 break;
310 default:
311 NOTREACHED();
314 // If all requests have responded, then all personal data is loaded.
315 if (pending_profiles_query_ == 0 &&
316 pending_creditcards_query_ == 0 &&
317 pending_server_profiles_query_ == 0 &&
318 pending_server_creditcards_query_ == 0) {
319 is_data_loaded_ = true;
320 NotifyPersonalDataChanged();
324 void PersonalDataManager::AutofillMultipleChanged() {
325 Refresh();
328 void PersonalDataManager::AddObserver(PersonalDataManagerObserver* observer) {
329 observers_.AddObserver(observer);
332 void PersonalDataManager::RemoveObserver(
333 PersonalDataManagerObserver* observer) {
334 observers_.RemoveObserver(observer);
337 bool PersonalDataManager::ImportFormData(
338 const FormStructure& form,
339 scoped_ptr<CreditCard>* imported_credit_card) {
340 scoped_ptr<AutofillProfile> imported_profile(new AutofillProfile);
341 scoped_ptr<CreditCard> local_imported_credit_card(new CreditCard);
343 const std::string origin = form.source_url().spec();
344 imported_profile->set_origin(origin);
345 local_imported_credit_card->set_origin(origin);
347 // Parse the form and construct a profile based on the information that is
348 // possible to import.
349 int importable_credit_card_fields = 0;
351 // Detect and discard forms with multiple fields of the same type.
352 // TODO(isherman): Some types are overlapping but not equal, e.g. phone number
353 // parts, address parts.
354 std::set<ServerFieldType> types_seen;
356 // We only set complete phone, so aggregate phone parts in these vars and set
357 // complete at the end.
358 PhoneNumber::PhoneCombineHelper home;
360 for (size_t i = 0; i < form.field_count(); ++i) {
361 const AutofillField* field = form.field(i);
362 base::string16 value;
363 base::TrimWhitespace(field->value, base::TRIM_ALL, &value);
365 // If we don't know the type of the field, or the user hasn't entered any
366 // information into the field, then skip it.
367 if (!field->IsFieldFillable() || value.empty())
368 continue;
370 AutofillType field_type = field->Type();
371 ServerFieldType server_field_type = field_type.GetStorableType();
372 FieldTypeGroup group(field_type.group());
374 // There can be multiple email fields (e.g. in the case of 'confirm email'
375 // fields) but they must all contain the same value, else the profile is
376 // invalid.
377 if (server_field_type == EMAIL_ADDRESS) {
378 if (types_seen.count(server_field_type) &&
379 imported_profile->GetRawInfo(EMAIL_ADDRESS) != value) {
380 imported_profile.reset();
381 break;
385 // If the |field_type| and |value| don't pass basic validity checks then
386 // abandon the import.
387 if (!IsValidFieldTypeAndValue(types_seen, server_field_type, value)) {
388 imported_profile.reset();
389 local_imported_credit_card.reset();
390 break;
393 types_seen.insert(server_field_type);
395 if (group == CREDIT_CARD) {
396 if (base::LowerCaseEqualsASCII(field->form_control_type, "month")) {
397 DCHECK_EQ(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, server_field_type);
398 local_imported_credit_card->SetInfoForMonthInputType(value);
399 } else {
400 local_imported_credit_card->SetInfo(field_type, value, app_locale_);
402 ++importable_credit_card_fields;
403 } else {
404 // We need to store phone data in the variables, before building the whole
405 // number at the end. The rest of the fields are set "as is".
406 // If the fields are not the phone fields in question home.SetInfo() is
407 // going to return false.
408 if (!home.SetInfo(field_type, value))
409 imported_profile->SetInfo(field_type, value, app_locale_);
411 // Reject profiles with invalid country information.
412 if (server_field_type == ADDRESS_HOME_COUNTRY &&
413 !value.empty() &&
414 imported_profile->GetRawInfo(ADDRESS_HOME_COUNTRY).empty()) {
415 imported_profile.reset();
416 break;
421 // Construct the phone number. Reject the profile if the number is invalid.
422 if (imported_profile.get() && !home.IsEmpty()) {
423 base::string16 constructed_number;
424 if (!home.ParseNumber(*imported_profile, app_locale_,
425 &constructed_number) ||
426 !imported_profile->SetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER),
427 constructed_number,
428 app_locale_)) {
429 imported_profile.reset();
433 // Reject the profile if minimum address and validation requirements are not
434 // met.
435 if (imported_profile.get() &&
436 !IsValidLearnableProfile(*imported_profile, app_locale_))
437 imported_profile.reset();
439 // Reject the credit card if we did not detect enough filled credit card
440 // fields or if the credit card number does not seem to be valid.
441 if (local_imported_credit_card.get() &&
442 !local_imported_credit_card->IsComplete()) {
443 local_imported_credit_card.reset();
446 // Don't import if we already have this info.
447 // Don't present an infobar if we have already saved this card number.
448 bool merged_credit_card = false;
449 if (local_imported_credit_card) {
450 for (CreditCard* card : local_credit_cards_) {
451 // Make a local copy so that the data in |local_credit_cards_| isn't
452 // modified directly by the UpdateFromImportedCard() call.
453 CreditCard card_copy(*card);
454 if (card_copy.UpdateFromImportedCard(*local_imported_credit_card.get(),
455 app_locale_)) {
456 merged_credit_card = true;
457 UpdateCreditCard(card_copy);
458 local_imported_credit_card.reset();
459 break;
464 // Also don't offer to save if we already have this stored as a full wallet
465 // card. Note that we will offer to save masked server cards, as long as
466 // the user re-typed the info by hand. See AutofillManager's
467 // |recently_unmasked_cards_|.
468 if (local_imported_credit_card) {
469 for (CreditCard* card : server_credit_cards_) {
470 if (card->record_type() == CreditCard::FULL_SERVER_CARD &&
471 local_imported_credit_card->IsLocalDuplicateOfServerCard(*card)) {
472 local_imported_credit_card.reset();
473 break;
478 if (imported_profile.get()) {
479 // We always save imported profiles.
480 SaveImportedProfile(*imported_profile);
482 *imported_credit_card = local_imported_credit_card.Pass();
484 if (imported_profile.get() || *imported_credit_card || merged_credit_card)
485 return true;
487 FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_,
488 OnInsufficientFormData());
489 return false;
492 void PersonalDataManager::RecordUseOf(const AutofillDataModel& data_model) {
493 if (is_off_the_record_ || !database_.get())
494 return;
496 CreditCard* credit_card = GetCreditCardByGUID(data_model.guid());
497 if (credit_card) {
498 credit_card->RecordUse();
500 if (credit_card->record_type() == CreditCard::LOCAL_CARD)
501 database_->UpdateCreditCard(*credit_card);
502 else
503 database_->UpdateServerCardUsageStats(*credit_card);
505 Refresh();
506 return;
509 AutofillProfile* profile = GetProfileByGUID(data_model.guid());
510 if (profile) {
511 profile->RecordUse();
513 if (profile->record_type() == AutofillProfile::LOCAL_PROFILE)
514 database_->UpdateAutofillProfile(*profile);
515 else if (profile->record_type() == AutofillProfile::SERVER_PROFILE)
516 database_->UpdateServerAddressUsageStats(*profile);
518 Refresh();
522 void PersonalDataManager::AddProfile(const AutofillProfile& profile) {
523 if (is_off_the_record_)
524 return;
526 if (profile.IsEmpty(app_locale_))
527 return;
529 // Don't add an existing profile.
530 if (FindByGUID<AutofillProfile>(web_profiles_, profile.guid()))
531 return;
533 if (!database_.get())
534 return;
536 // Don't add a duplicate.
537 if (FindByContents(web_profiles_, profile))
538 return;
540 // Add the new profile to the web database.
541 database_->AddAutofillProfile(profile);
543 // Refresh our local cache and send notifications to observers.
544 Refresh();
547 void PersonalDataManager::UpdateProfile(const AutofillProfile& profile) {
548 if (is_off_the_record_)
549 return;
551 AutofillProfile* existing_profile = GetProfileByGUID(profile.guid());
552 if (!existing_profile)
553 return;
555 // Don't overwrite the origin for a profile that is already stored.
556 if (existing_profile->EqualsSansOrigin(profile))
557 return;
559 if (profile.IsEmpty(app_locale_)) {
560 RemoveByGUID(profile.guid());
561 return;
564 if (!database_.get())
565 return;
567 // Make the update.
568 database_->UpdateAutofillProfile(profile);
570 // Refresh our local cache and send notifications to observers.
571 Refresh();
574 AutofillProfile* PersonalDataManager::GetProfileByGUID(
575 const std::string& guid) {
576 const std::vector<AutofillProfile*>& profiles = GetProfiles();
577 std::vector<AutofillProfile*>::const_iterator iter =
578 FindElementByGUID<AutofillProfile>(profiles, guid);
579 return (iter != profiles.end()) ? *iter : NULL;
582 void PersonalDataManager::AddCreditCard(const CreditCard& credit_card) {
583 if (is_off_the_record_)
584 return;
586 if (credit_card.IsEmpty(app_locale_))
587 return;
589 if (FindByGUID<CreditCard>(local_credit_cards_, credit_card.guid()))
590 return;
592 if (!database_.get())
593 return;
595 // Don't add a duplicate.
596 if (FindByContents(local_credit_cards_, credit_card))
597 return;
599 // Add the new credit card to the web database.
600 database_->AddCreditCard(credit_card);
602 // Refresh our local cache and send notifications to observers.
603 Refresh();
606 void PersonalDataManager::UpdateCreditCard(const CreditCard& credit_card) {
607 DCHECK_EQ(CreditCard::LOCAL_CARD, credit_card.record_type());
608 if (is_off_the_record_)
609 return;
611 CreditCard* existing_credit_card = GetCreditCardByGUID(credit_card.guid());
612 if (!existing_credit_card)
613 return;
615 // Don't overwrite the origin for a credit card that is already stored.
616 if (existing_credit_card->Compare(credit_card) == 0)
617 return;
619 if (credit_card.IsEmpty(app_locale_)) {
620 RemoveByGUID(credit_card.guid());
621 return;
624 if (!database_.get())
625 return;
627 // Make the update.
628 database_->UpdateCreditCard(credit_card);
630 // Refresh our local cache and send notifications to observers.
631 Refresh();
634 void PersonalDataManager::UpdateServerCreditCard(
635 const CreditCard& credit_card) {
636 DCHECK_NE(CreditCard::LOCAL_CARD, credit_card.record_type());
638 if (is_off_the_record_ || !database_.get())
639 return;
641 // Look up by server id, not GUID.
642 CreditCard* existing_credit_card = nullptr;
643 for (auto it : server_credit_cards_) {
644 if (credit_card.server_id() == it->server_id()) {
645 existing_credit_card = it;
646 break;
649 if (!existing_credit_card)
650 return;
652 DCHECK_NE(existing_credit_card->record_type(), credit_card.record_type());
653 DCHECK_EQ(existing_credit_card->Label(), credit_card.Label());
654 if (existing_credit_card->record_type() == CreditCard::MASKED_SERVER_CARD) {
655 database_->UnmaskServerCreditCard(credit_card,
656 credit_card.number());
657 } else {
658 database_->MaskServerCreditCard(credit_card.server_id());
661 Refresh();
664 void PersonalDataManager::ResetFullServerCard(const std::string& guid) {
665 for (const CreditCard* card : server_credit_cards_) {
666 if (card->guid() == guid) {
667 DCHECK_EQ(card->record_type(), CreditCard::FULL_SERVER_CARD);
668 CreditCard card_copy = *card;
669 card_copy.set_record_type(CreditCard::MASKED_SERVER_CARD);
670 card_copy.SetNumber(card->LastFourDigits());
671 UpdateServerCreditCard(card_copy);
672 break;
677 void PersonalDataManager::ResetFullServerCards() {
678 for (const CreditCard* card : server_credit_cards_) {
679 if (card->record_type() == CreditCard::FULL_SERVER_CARD) {
680 CreditCard card_copy = *card;
681 card_copy.set_record_type(CreditCard::MASKED_SERVER_CARD);
682 card_copy.SetNumber(card->LastFourDigits());
683 UpdateServerCreditCard(card_copy);
688 void PersonalDataManager::ClearAllServerData() {
689 // This could theoretically be called before we get the data back from the
690 // database on startup, and it could get called when the wallet pref is
691 // off (meaning this class won't even query for the server data) so don't
692 // check the server_credit_cards_/profiles_ before posting to the DB.
693 database_->ClearAllServerData();
695 // The above call will eventually clear our server data by notifying us
696 // that the data changed and then this class will re-fetch. Preemptively
697 // clear so that tests can synchronously verify that this data was cleared.
698 server_credit_cards_.clear();
699 server_profiles_.clear();
702 void PersonalDataManager::RemoveByGUID(const std::string& guid) {
703 if (is_off_the_record_)
704 return;
706 bool is_credit_card = FindByGUID<CreditCard>(local_credit_cards_, guid);
707 bool is_profile = !is_credit_card &&
708 FindByGUID<AutofillProfile>(web_profiles_, guid);
709 if (!is_credit_card && !is_profile)
710 return;
712 if (!database_.get())
713 return;
715 if (is_credit_card)
716 database_->RemoveCreditCard(guid);
717 else
718 database_->RemoveAutofillProfile(guid);
720 // Refresh our local cache and send notifications to observers.
721 Refresh();
724 CreditCard* PersonalDataManager::GetCreditCardByGUID(const std::string& guid) {
725 const std::vector<CreditCard*>& credit_cards = GetCreditCards();
726 std::vector<CreditCard*>::const_iterator iter =
727 FindElementByGUID<CreditCard>(credit_cards, guid);
728 return (iter != credit_cards.end()) ? *iter : NULL;
731 void PersonalDataManager::GetNonEmptyTypes(
732 ServerFieldTypeSet* non_empty_types) {
733 for (AutofillProfile* profile : GetProfiles())
734 profile->GetNonEmptyTypes(app_locale_, non_empty_types);
735 for (CreditCard* card : GetCreditCards())
736 card->GetNonEmptyTypes(app_locale_, non_empty_types);
739 bool PersonalDataManager::IsDataLoaded() const {
740 return is_data_loaded_;
743 const std::vector<AutofillProfile*>& PersonalDataManager::GetProfiles() const {
744 return GetProfiles(false);
747 const std::vector<AutofillProfile*>& PersonalDataManager::web_profiles() const {
748 return web_profiles_.get();
751 const std::vector<CreditCard*>& PersonalDataManager::GetLocalCreditCards()
752 const {
753 return local_credit_cards_.get();
756 const std::vector<CreditCard*>& PersonalDataManager::GetCreditCards() const {
757 credit_cards_.clear();
758 credit_cards_.insert(credit_cards_.end(), local_credit_cards_.begin(),
759 local_credit_cards_.end());
760 if (IsExperimentalWalletIntegrationEnabled() &&
761 pref_service_->GetBoolean(prefs::kAutofillWalletImportEnabled)) {
762 credit_cards_.insert(credit_cards_.end(), server_credit_cards_.begin(),
763 server_credit_cards_.end());
765 return credit_cards_;
768 bool PersonalDataManager::HasServerData() const {
769 return !server_credit_cards_.empty() || !server_profiles_.empty();
772 void PersonalDataManager::Refresh() {
773 LoadProfiles();
774 LoadCreditCards();
777 std::vector<Suggestion> PersonalDataManager::GetProfileSuggestions(
778 const AutofillType& type,
779 const base::string16& field_contents,
780 bool field_is_autofilled,
781 const std::vector<ServerFieldType>& other_field_types) {
782 if (IsInAutofillSuggestionsDisabledExperiment())
783 return std::vector<Suggestion>();
785 base::string16 field_contents_canon =
786 AutofillProfile::CanonicalizeProfileString(field_contents);
788 std::vector<AutofillProfile*> profiles = GetProfiles(true);
789 std::sort(profiles.begin(), profiles.end(), RankByMfu);
791 std::vector<Suggestion> suggestions;
792 // Match based on a prefix search.
793 std::vector<AutofillProfile*> matched_profiles;
794 for (AutofillProfile* profile : profiles) {
795 base::string16 value = GetInfoInOneLine(profile, type, app_locale_);
796 if (value.empty())
797 continue;
798 base::string16 value_canon =
799 AutofillProfile::CanonicalizeProfileString(value);
800 bool prefix_matched_suggestion = base::StartsWith(
801 value_canon, field_contents_canon, base::CompareCase::SENSITIVE);
802 if (prefix_matched_suggestion ||
803 FieldIsSuggestionSubstringStartingOnTokenBoundary(value, field_contents,
804 false)) {
805 matched_profiles.push_back(profile);
806 suggestions.push_back(Suggestion(value));
807 suggestions.back().backend_id = profile->guid();
808 suggestions.back().match = prefix_matched_suggestion
809 ? Suggestion::PREFIX_MATCH
810 : Suggestion::SUBSTRING_MATCH;
814 // Prefix matches should precede other token matches.
815 if (IsFeatureSubstringMatchEnabled()) {
816 std::stable_sort(suggestions.begin(), suggestions.end(),
817 [](const Suggestion& a, const Suggestion& b) {
818 return a.match < b.match;
822 // Don't show two suggestions if one is a subset of the other.
823 std::vector<AutofillProfile*> unique_matched_profiles;
824 std::vector<Suggestion> unique_suggestions;
825 ServerFieldTypeSet types(other_field_types.begin(), other_field_types.end());
826 for (size_t i = 0; i < matched_profiles.size(); ++i) {
827 bool include = true;
828 AutofillProfile* profile_a = matched_profiles[i];
829 for (size_t j = 0; j < matched_profiles.size(); ++j) {
830 AutofillProfile* profile_b = matched_profiles[j];
831 // Check if profile A is a subset of profile B. If not, continue.
832 if (i == j || suggestions[i].value != suggestions[j].value ||
833 !profile_a->IsSubsetOfForFieldSet(*profile_b, app_locale_, types)) {
834 continue;
837 // Check if profile B is also a subset of profile A. If so, the
838 // profiles are identical. Include the first one but not the second.
839 if (i < j &&
840 profile_b->IsSubsetOfForFieldSet(*profile_a, app_locale_, types)) {
841 continue;
844 // One-way subset. Don't include profile A.
845 include = false;
846 break;
848 if (include) {
849 unique_matched_profiles.push_back(matched_profiles[i]);
850 unique_suggestions.push_back(suggestions[i]);
854 // Generate disambiguating labels based on the list of matches.
855 std::vector<base::string16> labels;
856 AutofillProfile::CreateInferredLabels(
857 unique_matched_profiles, &other_field_types, type.GetStorableType(), 1,
858 app_locale_, &labels);
859 DCHECK_EQ(unique_suggestions.size(), labels.size());
860 for (size_t i = 0; i < labels.size(); i++)
861 unique_suggestions[i].label = labels[i];
863 return unique_suggestions;
866 std::vector<Suggestion> PersonalDataManager::GetCreditCardSuggestions(
867 const AutofillType& type,
868 const base::string16& field_contents) {
869 if (IsInAutofillSuggestionsDisabledExperiment())
870 return std::vector<Suggestion>();
872 std::list<const CreditCard*> cards_to_suggest;
873 std::list<const CreditCard*> substring_matched_cards;
874 base::string16 field_contents_lower = base::i18n::ToLower(field_contents);
875 for (const CreditCard* credit_card : GetCreditCards()) {
876 // The value of the stored data for this field type in the |credit_card|.
877 base::string16 creditcard_field_value =
878 credit_card->GetInfo(type, app_locale_);
879 if (creditcard_field_value.empty())
880 continue;
881 base::string16 creditcard_field_lower =
882 base::i18n::ToLower(creditcard_field_value);
884 // For card number fields, suggest the card if:
885 // - the number matches any part of the card, or
886 // - it's a masked card and there are 6 or fewers typed so far.
887 // For other fields, require that the field contents match the beginning of
888 // the stored data.
889 if (type.GetStorableType() == CREDIT_CARD_NUMBER) {
890 if (creditcard_field_lower.find(field_contents_lower) ==
891 base::string16::npos &&
892 (credit_card->record_type() != CreditCard::MASKED_SERVER_CARD ||
893 field_contents.size() >= 6)) {
894 continue;
896 cards_to_suggest.push_back(credit_card);
897 } else if (base::StartsWith(creditcard_field_lower, field_contents_lower,
898 base::CompareCase::SENSITIVE)) {
899 cards_to_suggest.push_back(credit_card);
900 } else if (FieldIsSuggestionSubstringStartingOnTokenBoundary(
901 creditcard_field_lower, field_contents_lower, true)) {
902 substring_matched_cards.push_back(credit_card);
906 cards_to_suggest.sort(RankByMfu);
908 // Prefix matches should precede other token matches.
909 if (IsFeatureSubstringMatchEnabled()) {
910 substring_matched_cards.sort(RankByMfu);
911 cards_to_suggest.insert(cards_to_suggest.end(),
912 substring_matched_cards.begin(),
913 substring_matched_cards.end());
916 // De-dupe card suggestions. Full server cards shadow local cards, and
917 // local cards shadow masked server cards.
918 for (auto outer_it = cards_to_suggest.begin();
919 outer_it != cards_to_suggest.end();
920 ++outer_it) {
922 if ((*outer_it)->record_type() == CreditCard::FULL_SERVER_CARD) {
923 for (auto inner_it = cards_to_suggest.begin();
924 inner_it != cards_to_suggest.end();) {
925 auto inner_it_copy = inner_it++;
926 if ((*inner_it_copy)->IsLocalDuplicateOfServerCard(**outer_it))
927 cards_to_suggest.erase(inner_it_copy);
929 } else if ((*outer_it)->record_type() == CreditCard::LOCAL_CARD) {
930 for (auto inner_it = cards_to_suggest.begin();
931 inner_it != cards_to_suggest.end();) {
932 auto inner_it_copy = inner_it++;
933 if ((*inner_it_copy)->record_type() == CreditCard::MASKED_SERVER_CARD &&
934 (*outer_it)->IsLocalDuplicateOfServerCard(**inner_it_copy)) {
935 cards_to_suggest.erase(inner_it_copy);
941 std::vector<Suggestion> suggestions;
942 for (const CreditCard* credit_card : cards_to_suggest) {
943 // Make a new suggestion.
944 suggestions.push_back(Suggestion());
945 Suggestion* suggestion = &suggestions.back();
947 suggestion->value = credit_card->GetInfo(type, app_locale_);
948 suggestion->icon = base::UTF8ToUTF16(credit_card->type());
949 suggestion->backend_id = credit_card->guid();
951 // If the value is the card number, the label is the expiration date.
952 // Otherwise the label is the card number, or if that is empty the
953 // cardholder name. The label should never repeat the value.
954 if (type.GetStorableType() == CREDIT_CARD_NUMBER) {
955 suggestion->value = credit_card->TypeAndLastFourDigits();
956 suggestion->label = credit_card->GetInfo(
957 AutofillType(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR), app_locale_);
958 } else if (credit_card->number().empty()) {
959 if (type.GetStorableType() != CREDIT_CARD_NAME) {
960 suggestion->label =
961 credit_card->GetInfo(AutofillType(CREDIT_CARD_NAME), app_locale_);
963 } else {
964 #if defined(OS_ANDROID)
965 // Since Android places the label on its own row, there's more horizontal
966 // space to work with. Show "Amex - 1234" rather than desktop's "*1234".
967 suggestion->label = credit_card->TypeAndLastFourDigits();
968 #else
969 suggestion->label = base::ASCIIToUTF16("*");
970 suggestion->label.append(credit_card->LastFourDigits());
971 #endif
974 return suggestions;
977 bool PersonalDataManager::IsAutofillEnabled() const {
978 return ::autofill::IsAutofillEnabled(pref_service_);
981 std::string PersonalDataManager::CountryCodeForCurrentTimezone() const {
982 return base::CountryCodeForCurrentTimezone();
985 void PersonalDataManager::SetPrefService(PrefService* pref_service) {
986 enabled_pref_.reset(new BooleanPrefMember);
987 wallet_enabled_pref_.reset(new BooleanPrefMember);
988 pref_service_ = pref_service;
989 // |pref_service_| can be NULL in tests.
990 if (pref_service_) {
991 enabled_pref_->Init(prefs::kAutofillEnabled, pref_service_,
992 base::Bind(&PersonalDataManager::EnabledPrefChanged,
993 base::Unretained(this)));
994 wallet_enabled_pref_->Init(prefs::kAutofillWalletImportEnabled,
995 pref_service_,
996 base::Bind(&PersonalDataManager::EnabledPrefChanged,
997 base::Unretained(this)));
1001 // static
1002 bool PersonalDataManager::IsValidLearnableProfile(
1003 const AutofillProfile& profile,
1004 const std::string& app_locale) {
1005 if (!IsMinimumAddress(profile, app_locale))
1006 return false;
1008 base::string16 email = profile.GetRawInfo(EMAIL_ADDRESS);
1009 if (!email.empty() && !IsValidEmailAddress(email))
1010 return false;
1012 // Reject profiles with invalid US state information.
1013 if (profile.IsPresentButInvalid(ADDRESS_HOME_STATE))
1014 return false;
1016 // Reject profiles with invalid US zip information.
1017 if (profile.IsPresentButInvalid(ADDRESS_HOME_ZIP))
1018 return false;
1020 return true;
1023 // static
1024 std::string PersonalDataManager::MergeProfile(
1025 const AutofillProfile& new_profile,
1026 const std::vector<AutofillProfile*>& existing_profiles,
1027 const std::string& app_locale,
1028 std::vector<AutofillProfile>* merged_profiles) {
1029 merged_profiles->clear();
1031 // Set to true if |existing_profiles| already contains an equivalent profile.
1032 bool matching_profile_found = false;
1033 std::string guid = new_profile.guid();
1035 // If we have already saved this address, merge in any missing values.
1036 // Only merge with the first match.
1037 for (AutofillProfile* existing_profile : existing_profiles) {
1038 if (!matching_profile_found && !new_profile.PrimaryValue().empty() &&
1039 existing_profile->SaveAdditionalInfo(new_profile, app_locale)) {
1040 // Unverified profiles should always be updated with the newer data,
1041 // whereas verified profiles should only ever be overwritten by verified
1042 // data. If an automatically aggregated profile would overwrite a
1043 // verified profile, just drop it.
1044 matching_profile_found = true;
1045 guid = existing_profile->guid();
1047 merged_profiles->push_back(*existing_profile);
1050 // If the new profile was not merged with an existing one, add it to the list.
1051 if (!matching_profile_found)
1052 merged_profiles->push_back(new_profile);
1054 return guid;
1057 bool PersonalDataManager::IsCountryOfInterest(const std::string& country_code)
1058 const {
1059 DCHECK_EQ(2U, country_code.size());
1061 const std::vector<AutofillProfile*>& profiles = web_profiles();
1062 std::list<std::string> country_codes;
1063 for (size_t i = 0; i < profiles.size(); ++i) {
1064 country_codes.push_back(base::ToLowerASCII(base::UTF16ToASCII(
1065 profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY))));
1068 std::string timezone_country = CountryCodeForCurrentTimezone();
1069 if (!timezone_country.empty())
1070 country_codes.push_back(base::ToLowerASCII(timezone_country));
1072 // Only take the locale into consideration if all else fails.
1073 if (country_codes.empty()) {
1074 country_codes.push_back(base::ToLowerASCII(
1075 AutofillCountry::CountryCodeForLocale(app_locale())));
1078 return std::find(country_codes.begin(), country_codes.end(),
1079 base::ToLowerASCII(country_code)) != country_codes.end();
1082 const std::string& PersonalDataManager::GetDefaultCountryCodeForNewAddress()
1083 const {
1084 if (default_country_code_.empty())
1085 default_country_code_ = MostCommonCountryCodeFromProfiles();
1087 // Failing that, guess based on system timezone.
1088 if (default_country_code_.empty())
1089 default_country_code_ = CountryCodeForCurrentTimezone();
1091 // Failing that, guess based on locale.
1092 if (default_country_code_.empty())
1093 default_country_code_ = AutofillCountry::CountryCodeForLocale(app_locale());
1095 return default_country_code_;
1098 bool PersonalDataManager::IsExperimentalWalletIntegrationEnabled() const {
1099 return pref_service_->GetBoolean(prefs::kAutofillWalletSyncExperimentEnabled);
1102 void PersonalDataManager::SetProfiles(std::vector<AutofillProfile>* profiles) {
1103 if (is_off_the_record_)
1104 return;
1106 // Remove empty profiles from input.
1107 profiles->erase(std::remove_if(profiles->begin(), profiles->end(),
1108 IsEmptyFunctor<AutofillProfile>(app_locale_)),
1109 profiles->end());
1111 if (!database_.get())
1112 return;
1114 // Any profiles that are not in the new profile list should be removed from
1115 // the web database.
1116 for (std::vector<AutofillProfile*>::const_iterator iter =
1117 web_profiles_.begin();
1118 iter != web_profiles_.end(); ++iter) {
1119 if (!FindByGUID<AutofillProfile>(*profiles, (*iter)->guid()))
1120 database_->RemoveAutofillProfile((*iter)->guid());
1123 // Update the web database with the existing profiles.
1124 for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
1125 iter != profiles->end(); ++iter) {
1126 if (FindByGUID<AutofillProfile>(web_profiles_, iter->guid()))
1127 database_->UpdateAutofillProfile(*iter);
1130 // Add the new profiles to the web database. Don't add a duplicate.
1131 for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
1132 iter != profiles->end(); ++iter) {
1133 if (!FindByGUID<AutofillProfile>(web_profiles_, iter->guid()) &&
1134 !FindByContents(web_profiles_, *iter))
1135 database_->AddAutofillProfile(*iter);
1138 // Copy in the new profiles.
1139 web_profiles_.clear();
1140 for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
1141 iter != profiles->end(); ++iter) {
1142 web_profiles_.push_back(new AutofillProfile(*iter));
1145 // Refresh our local cache and send notifications to observers.
1146 Refresh();
1149 void PersonalDataManager::SetCreditCards(
1150 std::vector<CreditCard>* credit_cards) {
1151 if (is_off_the_record_)
1152 return;
1154 // Remove empty credit cards from input.
1155 credit_cards->erase(std::remove_if(credit_cards->begin(), credit_cards->end(),
1156 IsEmptyFunctor<CreditCard>(app_locale_)),
1157 credit_cards->end());
1159 if (!database_.get())
1160 return;
1162 // Any credit cards that are not in the new credit card list should be
1163 // removed.
1164 for (const CreditCard* card : local_credit_cards_) {
1165 if (!FindByGUID<CreditCard>(*credit_cards, card->guid()))
1166 database_->RemoveCreditCard(card->guid());
1169 // Update the web database with the existing credit cards.
1170 for (const CreditCard& card : *credit_cards) {
1171 if (FindByGUID<CreditCard>(local_credit_cards_, card.guid()))
1172 database_->UpdateCreditCard(card);
1175 // Add the new credit cards to the web database. Don't add a duplicate.
1176 for (const CreditCard& card : *credit_cards) {
1177 if (!FindByGUID<CreditCard>(local_credit_cards_, card.guid()) &&
1178 !FindByContents(local_credit_cards_, card))
1179 database_->AddCreditCard(card);
1182 // Copy in the new credit cards.
1183 local_credit_cards_.clear();
1184 for (const CreditCard& card : *credit_cards)
1185 local_credit_cards_.push_back(new CreditCard(card));
1187 // Refresh our local cache and send notifications to observers.
1188 Refresh();
1191 void PersonalDataManager::LoadProfiles() {
1192 if (!database_.get()) {
1193 NOTREACHED();
1194 return;
1197 CancelPendingQuery(&pending_profiles_query_);
1198 CancelPendingQuery(&pending_server_profiles_query_);
1200 pending_profiles_query_ = database_->GetAutofillProfiles(this);
1201 pending_server_profiles_query_ = database_->GetServerProfiles(this);
1204 void PersonalDataManager::LoadCreditCards() {
1205 if (!database_.get()) {
1206 NOTREACHED();
1207 return;
1210 CancelPendingQuery(&pending_creditcards_query_);
1211 CancelPendingQuery(&pending_server_creditcards_query_);
1213 pending_creditcards_query_ = database_->GetCreditCards(this);
1214 pending_server_creditcards_query_ = database_->GetServerCreditCards(this);
1217 void PersonalDataManager::CancelPendingQuery(
1218 WebDataServiceBase::Handle* handle) {
1219 if (*handle) {
1220 if (!database_.get()) {
1221 NOTREACHED();
1222 return;
1224 database_->CancelRequest(*handle);
1226 *handle = 0;
1229 std::string PersonalDataManager::SaveImportedProfile(
1230 const AutofillProfile& imported_profile) {
1231 if (is_off_the_record_)
1232 return std::string();
1234 // ...or server profile.
1235 for (AutofillProfile* profile : server_profiles_) {
1236 if (imported_profile.IsSubsetOf(*profile, app_locale_))
1237 return profile->guid();
1240 std::vector<AutofillProfile> profiles;
1241 std::string guid =
1242 MergeProfile(imported_profile, web_profiles_.get(), app_locale_,
1243 &profiles);
1244 SetProfiles(&profiles);
1245 return guid;
1248 void PersonalDataManager::NotifyPersonalDataChanged() {
1249 FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_,
1250 OnPersonalDataChanged());
1253 std::string PersonalDataManager::SaveImportedCreditCard(
1254 const CreditCard& imported_card) {
1255 DCHECK(!imported_card.number().empty());
1256 if (is_off_the_record_)
1257 return std::string();
1259 // Set to true if |imported_card| is merged into the credit card list.
1260 bool merged = false;
1262 std::string guid = imported_card.guid();
1263 std::vector<CreditCard> credit_cards;
1264 for (CreditCard* card : local_credit_cards_) {
1265 // If |imported_card| has not yet been merged, check whether it should be
1266 // with the current |card|.
1267 if (!merged && card->UpdateFromImportedCard(imported_card, app_locale_)) {
1268 guid = card->guid();
1269 merged = true;
1272 credit_cards.push_back(*card);
1275 if (!merged)
1276 credit_cards.push_back(imported_card);
1278 SetCreditCards(&credit_cards);
1279 return guid;
1282 void PersonalDataManager::LogProfileCount() const {
1283 if (!has_logged_profile_count_) {
1284 AutofillMetrics::LogStoredProfileCount(web_profiles_.size());
1285 has_logged_profile_count_ = true;
1289 std::string PersonalDataManager::MostCommonCountryCodeFromProfiles() const {
1290 if (!IsAutofillEnabled())
1291 return std::string();
1293 // Count up country codes from existing profiles.
1294 std::map<std::string, int> votes;
1295 // TODO(estade): can we make this GetProfiles() instead? It seems to cause
1296 // errors in tests on mac trybots. See http://crbug.com/57221
1297 const std::vector<AutofillProfile*>& profiles = web_profiles();
1298 std::vector<std::string> country_codes;
1299 AutofillCountry::GetAvailableCountries(&country_codes);
1300 for (size_t i = 0; i < profiles.size(); ++i) {
1301 std::string country_code = base::ToUpperASCII(base::UTF16ToASCII(
1302 profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY)));
1304 if (std::find(country_codes.begin(), country_codes.end(), country_code) !=
1305 country_codes.end()) {
1306 // Verified profiles count 100x more than unverified ones.
1307 votes[country_code] += profiles[i]->IsVerified() ? 100 : 1;
1311 // Take the most common country code.
1312 if (!votes.empty()) {
1313 std::map<std::string, int>::iterator iter =
1314 std::max_element(votes.begin(), votes.end(), CompareVotes);
1315 return iter->first;
1318 return std::string();
1321 void PersonalDataManager::EnabledPrefChanged() {
1322 default_country_code_.clear();
1323 if (!pref_service_->GetBoolean(prefs::kAutofillWalletImportEnabled)) {
1324 // Re-mask all server cards when the user turns off wallet card
1325 // integration.
1326 ResetFullServerCards();
1328 NotifyPersonalDataChanged();
1331 const std::vector<AutofillProfile*>& PersonalDataManager::GetProfiles(
1332 bool record_metrics) const {
1333 profiles_.clear();
1334 profiles_.insert(profiles_.end(), web_profiles().begin(),
1335 web_profiles().end());
1336 if (IsExperimentalWalletIntegrationEnabled() &&
1337 pref_service_->GetBoolean(prefs::kAutofillWalletImportEnabled)) {
1338 profiles_.insert(
1339 profiles_.end(), server_profiles_.begin(), server_profiles_.end());
1341 return profiles_;
1344 } // namespace autofill