Move StringToUpperASCII to base namespace
[chromium-blink-merge.git] / components / autofill / core / browser / personal_data_manager.cc
blobb451b6826f342d834c25d76e822c185d500db609
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/timezone.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/prefs/pref_service.h"
16 #include "base/profiler/scoped_tracker.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "components/autofill/core/browser/address_i18n.h"
21 #include "components/autofill/core/browser/autofill-inl.h"
22 #include "components/autofill/core/browser/autofill_country.h"
23 #include "components/autofill/core/browser/autofill_experiments.h"
24 #include "components/autofill/core/browser/autofill_field.h"
25 #include "components/autofill/core/browser/autofill_metrics.h"
26 #include "components/autofill/core/browser/form_structure.h"
27 #include "components/autofill/core/browser/personal_data_manager_observer.h"
28 #include "components/autofill/core/browser/phone_number.h"
29 #include "components/autofill/core/browser/phone_number_i18n.h"
30 #include "components/autofill/core/browser/validation.h"
31 #include "components/autofill/core/common/autofill_pref_names.h"
32 #include "components/autofill/core/common/autofill_switches.h"
33 #include "components/signin/core/browser/account_tracker_service.h"
34 #include "components/signin/core/common/signin_pref_names.h"
35 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
36 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_formatter.h"
38 namespace autofill {
39 namespace {
41 using ::i18n::addressinput::AddressField;
42 using ::i18n::addressinput::GetStreetAddressLinesAsSingleLine;
43 using ::i18n::addressinput::STREET_ADDRESS;
45 template<typename T>
46 class FormGroupMatchesByGUIDFunctor {
47 public:
48 explicit FormGroupMatchesByGUIDFunctor(const std::string& guid)
49 : guid_(guid) {
52 bool operator()(const T& form_group) {
53 return form_group.guid() == guid_;
56 bool operator()(const T* form_group) {
57 return form_group->guid() == guid_;
60 private:
61 const std::string guid_;
64 template<typename T, typename C>
65 typename C::const_iterator FindElementByGUID(const C& container,
66 const std::string& guid) {
67 return std::find_if(container.begin(),
68 container.end(),
69 FormGroupMatchesByGUIDFunctor<T>(guid));
72 template<typename T, typename C>
73 bool FindByGUID(const C& container, const std::string& guid) {
74 return FindElementByGUID<T>(container, guid) != container.end();
77 template<typename T>
78 class IsEmptyFunctor {
79 public:
80 explicit IsEmptyFunctor(const std::string& app_locale)
81 : app_locale_(app_locale) {
84 bool operator()(const T& form_group) {
85 return form_group.IsEmpty(app_locale_);
88 private:
89 const std::string app_locale_;
92 // Returns true if minimum requirements for import of a given |profile| have
93 // been met. An address submitted via a form must have at least the fields
94 // required as determined by its country code.
95 // No verification of validity of the contents is preformed. This is an
96 // existence check only.
97 bool IsMinimumAddress(const AutofillProfile& profile,
98 const std::string& app_locale) {
99 // All countries require at least one address line.
100 if (profile.GetRawInfo(ADDRESS_HOME_LINE1).empty())
101 return false;
103 std::string country_code =
104 base::UTF16ToASCII(profile.GetRawInfo(ADDRESS_HOME_COUNTRY));
105 if (country_code.empty())
106 country_code = AutofillCountry::CountryCodeForLocale(app_locale);
108 AutofillCountry country(country_code, app_locale);
110 if (country.requires_city() && profile.GetRawInfo(ADDRESS_HOME_CITY).empty())
111 return false;
113 if (country.requires_state() &&
114 profile.GetRawInfo(ADDRESS_HOME_STATE).empty())
115 return false;
117 if (country.requires_zip() && profile.GetRawInfo(ADDRESS_HOME_ZIP).empty())
118 return false;
120 return true;
123 // Return true if the |field_type| and |value| are valid within the context
124 // of importing a form.
125 bool IsValidFieldTypeAndValue(const std::set<ServerFieldType>& types_seen,
126 ServerFieldType field_type,
127 const base::string16& value) {
128 // Abandon the import if two fields of the same type are encountered.
129 // This indicates ambiguous data or miscategorization of types.
130 // Make an exception for PHONE_HOME_NUMBER however as both prefix and
131 // suffix are stored against this type, and for EMAIL_ADDRESS because it is
132 // common to see second 'confirm email address' fields on forms.
133 if (types_seen.count(field_type) &&
134 field_type != PHONE_HOME_NUMBER &&
135 field_type != EMAIL_ADDRESS)
136 return false;
138 // Abandon the import if an email address value shows up in a field that is
139 // not an email address.
140 if (field_type != EMAIL_ADDRESS && IsValidEmailAddress(value))
141 return false;
143 return true;
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 base::string16 GetInfoInOneLine(const AutofillProfile* profile,
149 const AutofillType& type,
150 const std::string app_locale) {
151 std::vector<base::string16> results;
153 AddressField address_field;
154 if (i18n::FieldForType(type.GetStorableType(), &address_field) &&
155 address_field == STREET_ADDRESS) {
156 std::string street_address_line;
157 GetStreetAddressLinesAsSingleLine(
158 *i18n::CreateAddressDataFromAutofillProfile(*profile, app_locale),
159 &street_address_line);
160 return base::UTF8ToUTF16(street_address_line);
163 return profile->GetInfo(type, app_locale);
166 // Receives the loaded profiles from the web data service and stores them in
167 // |*dest|. The pending handle is the address of the pending handle
168 // corresponding to this request type. This function is used to save both
169 // server and local profiles and credit cards.
170 template <typename ValueType>
171 void ReceiveLoadedDbValues(WebDataServiceBase::Handle h,
172 const WDTypedResult* result,
173 WebDataServiceBase::Handle* pending_handle,
174 ScopedVector<ValueType>* dest) {
175 DCHECK_EQ(*pending_handle, h);
176 *pending_handle = 0;
178 const WDResult<std::vector<ValueType*>>* r =
179 static_cast<const WDResult<std::vector<ValueType*>>*>(result);
181 dest->clear();
182 for (ValueType* value : r->GetValue())
183 dest->push_back(value);
186 // A helper function for finding the maximum value in a string->int map.
187 static bool CompareVotes(const std::pair<std::string, int>& a,
188 const std::pair<std::string, int>& b) {
189 return a.second < b.second;
192 // Ranks two data models according to their recency of use. Currently this will
193 // place all server (Wallet) cards and addresses below all locally saved ones,
194 // which is probably not what we want. TODO(estade): figure out relative ranking
195 // of server data.
196 bool RankByMfu(const AutofillDataModel* a, const AutofillDataModel* b) {
197 if (a->use_count() != b->use_count())
198 return a->use_count() > b->use_count();
200 // Ties are broken by MRU.
201 return a->use_date() > b->use_date();
204 } // namespace
206 PersonalDataManager::PersonalDataManager(const std::string& app_locale)
207 : database_(NULL),
208 is_data_loaded_(false),
209 pending_profiles_query_(0),
210 pending_server_profiles_query_(0),
211 pending_creditcards_query_(0),
212 pending_server_creditcards_query_(0),
213 app_locale_(app_locale),
214 pref_service_(NULL),
215 account_tracker_(NULL),
216 is_off_the_record_(false),
217 has_logged_profile_count_(false) {}
219 void PersonalDataManager::Init(scoped_refptr<AutofillWebDataService> database,
220 PrefService* pref_service,
221 AccountTrackerService* account_tracker,
222 bool is_off_the_record) {
223 database_ = database;
224 SetPrefService(pref_service);
225 account_tracker_ = account_tracker;
226 is_off_the_record_ = is_off_the_record;
228 if (!is_off_the_record_)
229 AutofillMetrics::LogIsAutofillEnabledAtStartup(IsAutofillEnabled());
231 // WebDataService may not be available in tests.
232 if (!database_.get())
233 return;
235 LoadProfiles();
236 LoadCreditCards();
238 database_->AddObserver(this);
241 PersonalDataManager::~PersonalDataManager() {
242 CancelPendingQuery(&pending_profiles_query_);
243 CancelPendingQuery(&pending_server_profiles_query_);
244 CancelPendingQuery(&pending_creditcards_query_);
245 CancelPendingQuery(&pending_server_creditcards_query_);
247 if (database_.get())
248 database_->RemoveObserver(this);
251 void PersonalDataManager::OnWebDataServiceRequestDone(
252 WebDataServiceBase::Handle h,
253 const WDTypedResult* result) {
254 DCHECK(pending_profiles_query_ || pending_server_profiles_query_ ||
255 pending_creditcards_query_ || pending_server_creditcards_query_);
257 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
258 // fixed.
259 tracked_objects::ScopedTracker tracking_profile(
260 FROM_HERE_WITH_EXPLICIT_FUNCTION(
261 "422460 PersonalDataManager::OnWebDataServiceRequestDone"));
263 if (!result) {
264 // Error from the web database.
265 if (h == pending_creditcards_query_)
266 pending_creditcards_query_ = 0;
267 else if (h == pending_profiles_query_)
268 pending_profiles_query_ = 0;
269 return;
272 switch (result->GetType()) {
273 case AUTOFILL_PROFILES_RESULT:
274 if (h == pending_profiles_query_) {
275 ReceiveLoadedDbValues(h, result, &pending_profiles_query_,
276 &web_profiles_);
277 LogProfileCount(); // This only logs local profiles.
278 } else {
279 ReceiveLoadedDbValues(h, result, &pending_server_profiles_query_,
280 &server_profiles_);
282 if (!server_profiles_.empty()) {
283 std::string account_id =
284 pref_service_->GetString(::prefs::kGoogleServicesAccountId);
285 base::string16 email =
286 base::UTF8ToUTF16(
287 account_tracker_->GetAccountInfo(account_id).email);
288 DCHECK(!email.empty());
289 for (AutofillProfile* profile : server_profiles_)
290 profile->SetRawInfo(EMAIL_ADDRESS, email);
293 break;
294 case AUTOFILL_CREDITCARDS_RESULT:
295 if (h == pending_creditcards_query_) {
296 ReceiveLoadedDbValues(h, result, &pending_creditcards_query_,
297 &local_credit_cards_);
298 } else {
299 ReceiveLoadedDbValues(h, result, &pending_server_creditcards_query_,
300 &server_credit_cards_);
302 // If the user has a saved unmasked server card and the experiment is
303 // disabled, force mask all cards back to the unsaved state.
304 if (!OfferStoreUnmaskedCards())
305 ResetFullServerCards();
307 break;
308 default:
309 NOTREACHED();
312 // If all requests have responded, then all personal data is loaded.
313 if (pending_profiles_query_ == 0 &&
314 pending_creditcards_query_ == 0 &&
315 pending_server_profiles_query_ == 0 &&
316 pending_server_creditcards_query_ == 0) {
317 is_data_loaded_ = true;
318 NotifyPersonalDataChanged();
322 void PersonalDataManager::AutofillMultipleChanged() {
323 Refresh();
326 void PersonalDataManager::AddObserver(PersonalDataManagerObserver* observer) {
327 observers_.AddObserver(observer);
330 void PersonalDataManager::RemoveObserver(
331 PersonalDataManagerObserver* observer) {
332 observers_.RemoveObserver(observer);
335 bool PersonalDataManager::ImportFormData(
336 const FormStructure& form,
337 scoped_ptr<CreditCard>* imported_credit_card) {
338 scoped_ptr<AutofillProfile> imported_profile(new AutofillProfile);
339 scoped_ptr<CreditCard> local_imported_credit_card(new CreditCard);
341 const std::string origin = form.source_url().spec();
342 imported_profile->set_origin(origin);
343 local_imported_credit_card->set_origin(origin);
345 // Parse the form and construct a profile based on the information that is
346 // possible to import.
347 int importable_credit_card_fields = 0;
349 // Detect and discard forms with multiple fields of the same type.
350 // TODO(isherman): Some types are overlapping but not equal, e.g. phone number
351 // parts, address parts.
352 std::set<ServerFieldType> types_seen;
354 // We only set complete phone, so aggregate phone parts in these vars and set
355 // complete at the end.
356 PhoneNumber::PhoneCombineHelper home;
358 for (size_t i = 0; i < form.field_count(); ++i) {
359 const AutofillField* field = form.field(i);
360 base::string16 value;
361 base::TrimWhitespace(field->value, base::TRIM_ALL, &value);
363 // If we don't know the type of the field, or the user hasn't entered any
364 // information into the field, then skip it.
365 if (!field->IsFieldFillable() || value.empty())
366 continue;
368 AutofillType field_type = field->Type();
369 ServerFieldType server_field_type = field_type.GetStorableType();
370 FieldTypeGroup group(field_type.group());
372 // There can be multiple email fields (e.g. in the case of 'confirm email'
373 // fields) but they must all contain the same value, else the profile is
374 // invalid.
375 if (server_field_type == EMAIL_ADDRESS) {
376 if (types_seen.count(server_field_type) &&
377 imported_profile->GetRawInfo(EMAIL_ADDRESS) != value) {
378 imported_profile.reset();
379 break;
383 // If the |field_type| and |value| don't pass basic validity checks then
384 // abandon the import.
385 if (!IsValidFieldTypeAndValue(types_seen, server_field_type, value)) {
386 imported_profile.reset();
387 local_imported_credit_card.reset();
388 break;
391 types_seen.insert(server_field_type);
393 if (group == CREDIT_CARD) {
394 if (LowerCaseEqualsASCII(field->form_control_type, "month")) {
395 DCHECK_EQ(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, server_field_type);
396 local_imported_credit_card->SetInfoForMonthInputType(value);
397 } else {
398 local_imported_credit_card->SetInfo(field_type, value, app_locale_);
400 ++importable_credit_card_fields;
401 } else {
402 // We need to store phone data in the variables, before building the whole
403 // number at the end. The rest of the fields are set "as is".
404 // If the fields are not the phone fields in question home.SetInfo() is
405 // going to return false.
406 if (!home.SetInfo(field_type, value))
407 imported_profile->SetInfo(field_type, value, app_locale_);
409 // Reject profiles with invalid country information.
410 if (server_field_type == ADDRESS_HOME_COUNTRY &&
411 !value.empty() &&
412 imported_profile->GetRawInfo(ADDRESS_HOME_COUNTRY).empty()) {
413 imported_profile.reset();
414 break;
419 // Construct the phone number. Reject the profile if the number is invalid.
420 if (imported_profile.get() && !home.IsEmpty()) {
421 base::string16 constructed_number;
422 if (!home.ParseNumber(*imported_profile, app_locale_,
423 &constructed_number) ||
424 !imported_profile->SetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER),
425 constructed_number,
426 app_locale_)) {
427 imported_profile.reset();
431 // Reject the profile if minimum address and validation requirements are not
432 // met.
433 if (imported_profile.get() &&
434 !IsValidLearnableProfile(*imported_profile, app_locale_))
435 imported_profile.reset();
437 // Reject the credit card if we did not detect enough filled credit card
438 // fields or if the credit card number does not seem to be valid.
439 if (local_imported_credit_card.get() &&
440 !local_imported_credit_card->IsComplete()) {
441 local_imported_credit_card.reset();
444 // Don't import if we already have this info.
445 // Don't present an infobar if we have already saved this card number.
446 bool merged_credit_card = false;
447 if (local_imported_credit_card) {
448 for (CreditCard* card : local_credit_cards_) {
449 // Make a local copy so that the data in |local_credit_cards_| isn't
450 // modified directly by the UpdateFromImportedCard() call.
451 CreditCard card_copy(*card);
452 if (card_copy.UpdateFromImportedCard(*local_imported_credit_card.get(),
453 app_locale_)) {
454 merged_credit_card = true;
455 UpdateCreditCard(card_copy);
456 local_imported_credit_card.reset();
457 break;
462 // Also don't offer to save if we already have this stored as a full wallet
463 // card. Note that we will offer to save masked server cards, as long as
464 // the user re-typed the info by hand. See AutofillManager's
465 // |recently_unmasked_cards_|.
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();
471 break;
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)
483 return true;
485 FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_,
486 OnInsufficientFormData());
487 return false;
490 void PersonalDataManager::RecordUseOf(const AutofillDataModel& data_model) {
491 if (is_off_the_record_ || !database_.get())
492 return;
494 CreditCard* credit_card = GetCreditCardByGUID(data_model.guid());
495 if (credit_card) {
496 credit_card->RecordUse();
498 if (credit_card->record_type() == CreditCard::LOCAL_CARD)
499 database_->UpdateCreditCard(*credit_card);
500 else
501 database_->UpdateServerCardUsageStats(*credit_card);
503 Refresh();
504 return;
507 AutofillProfile* profile = GetProfileByGUID(data_model.guid());
508 if (profile) {
509 profile->RecordUse();
511 if (profile->record_type() == AutofillProfile::LOCAL_PROFILE)
512 database_->UpdateAutofillProfile(*profile);
513 else if (profile->record_type() == AutofillProfile::SERVER_PROFILE)
514 database_->UpdateServerAddressUsageStats(*profile);
516 Refresh();
520 void PersonalDataManager::AddProfile(const AutofillProfile& profile) {
521 if (is_off_the_record_)
522 return;
524 if (profile.IsEmpty(app_locale_))
525 return;
527 // Don't add an existing profile.
528 if (FindByGUID<AutofillProfile>(web_profiles_, profile.guid()))
529 return;
531 if (!database_.get())
532 return;
534 // Don't add a duplicate.
535 if (FindByContents(web_profiles_, profile))
536 return;
538 // Add the new profile to the web database.
539 database_->AddAutofillProfile(profile);
541 // Refresh our local cache and send notifications to observers.
542 Refresh();
545 void PersonalDataManager::UpdateProfile(const AutofillProfile& profile) {
546 if (is_off_the_record_)
547 return;
549 AutofillProfile* existing_profile = GetProfileByGUID(profile.guid());
550 if (!existing_profile)
551 return;
553 // Don't overwrite the origin for a profile that is already stored.
554 if (existing_profile->EqualsSansOrigin(profile))
555 return;
557 if (profile.IsEmpty(app_locale_)) {
558 RemoveByGUID(profile.guid());
559 return;
562 if (!database_.get())
563 return;
565 // Make the update.
566 database_->UpdateAutofillProfile(profile);
568 // Refresh our local cache and send notifications to observers.
569 Refresh();
572 AutofillProfile* PersonalDataManager::GetProfileByGUID(
573 const std::string& guid) {
574 const std::vector<AutofillProfile*>& profiles = GetProfiles();
575 std::vector<AutofillProfile*>::const_iterator iter =
576 FindElementByGUID<AutofillProfile>(profiles, guid);
577 return (iter != profiles.end()) ? *iter : NULL;
580 void PersonalDataManager::AddCreditCard(const CreditCard& credit_card) {
581 if (is_off_the_record_)
582 return;
584 if (credit_card.IsEmpty(app_locale_))
585 return;
587 if (FindByGUID<CreditCard>(local_credit_cards_, credit_card.guid()))
588 return;
590 if (!database_.get())
591 return;
593 // Don't add a duplicate.
594 if (FindByContents(local_credit_cards_, credit_card))
595 return;
597 // Add the new credit card to the web database.
598 database_->AddCreditCard(credit_card);
600 // Refresh our local cache and send notifications to observers.
601 Refresh();
604 void PersonalDataManager::UpdateCreditCard(const CreditCard& credit_card) {
605 DCHECK_EQ(CreditCard::LOCAL_CARD, credit_card.record_type());
606 if (is_off_the_record_)
607 return;
609 CreditCard* existing_credit_card = GetCreditCardByGUID(credit_card.guid());
610 if (!existing_credit_card)
611 return;
613 // Don't overwrite the origin for a credit card that is already stored.
614 if (existing_credit_card->Compare(credit_card) == 0)
615 return;
617 if (credit_card.IsEmpty(app_locale_)) {
618 RemoveByGUID(credit_card.guid());
619 return;
622 if (!database_.get())
623 return;
625 // Make the update.
626 database_->UpdateCreditCard(credit_card);
628 // Refresh our local cache and send notifications to observers.
629 Refresh();
632 void PersonalDataManager::UpdateServerCreditCard(
633 const CreditCard& credit_card) {
634 DCHECK_NE(CreditCard::LOCAL_CARD, credit_card.record_type());
636 if (is_off_the_record_ || !database_.get())
637 return;
639 // Look up by server id, not GUID.
640 CreditCard* existing_credit_card = nullptr;
641 for (auto it : server_credit_cards_) {
642 if (credit_card.server_id() == it->server_id()) {
643 existing_credit_card = it;
644 break;
647 if (!existing_credit_card)
648 return;
650 DCHECK_NE(existing_credit_card->record_type(), credit_card.record_type());
651 DCHECK_EQ(existing_credit_card->Label(), credit_card.Label());
652 if (existing_credit_card->record_type() == CreditCard::MASKED_SERVER_CARD) {
653 database_->UnmaskServerCreditCard(credit_card,
654 credit_card.number());
655 } else {
656 database_->MaskServerCreditCard(credit_card.server_id());
659 Refresh();
662 void PersonalDataManager::ResetFullServerCard(const std::string& guid) {
663 for (const CreditCard* card : server_credit_cards_) {
664 if (card->guid() == guid) {
665 DCHECK_EQ(card->record_type(), CreditCard::FULL_SERVER_CARD);
666 CreditCard card_copy = *card;
667 card_copy.set_record_type(CreditCard::MASKED_SERVER_CARD);
668 card_copy.SetNumber(card->LastFourDigits());
669 UpdateServerCreditCard(card_copy);
670 break;
675 void PersonalDataManager::ResetFullServerCards() {
676 for (const CreditCard* card : server_credit_cards_) {
677 if (card->record_type() == CreditCard::FULL_SERVER_CARD) {
678 CreditCard card_copy = *card;
679 card_copy.set_record_type(CreditCard::MASKED_SERVER_CARD);
680 card_copy.SetNumber(card->LastFourDigits());
681 UpdateServerCreditCard(card_copy);
686 void PersonalDataManager::ClearAllServerData() {
687 // This could theoretically be called before we get the data back from the
688 // database on startup, and it could get called when the wallet pref is
689 // off (meaning this class won't even query for the server data) so don't
690 // check the server_credit_cards_/profiles_ before posting to the DB.
691 database_->ClearAllServerData();
693 // The above call will eventually clear our server data by notifying us
694 // that the data changed and then this class will re-fetch. Preemptively
695 // clear so that tests can synchronously verify that this data was cleared.
696 server_credit_cards_.clear();
697 server_profiles_.clear();
700 void PersonalDataManager::RemoveByGUID(const std::string& guid) {
701 if (is_off_the_record_)
702 return;
704 bool is_credit_card = FindByGUID<CreditCard>(local_credit_cards_, guid);
705 bool is_profile = !is_credit_card &&
706 FindByGUID<AutofillProfile>(web_profiles_, guid);
707 if (!is_credit_card && !is_profile)
708 return;
710 if (!database_.get())
711 return;
713 if (is_credit_card)
714 database_->RemoveCreditCard(guid);
715 else
716 database_->RemoveAutofillProfile(guid);
718 // Refresh our local cache and send notifications to observers.
719 Refresh();
722 CreditCard* PersonalDataManager::GetCreditCardByGUID(const std::string& guid) {
723 const std::vector<CreditCard*>& credit_cards = GetCreditCards();
724 std::vector<CreditCard*>::const_iterator iter =
725 FindElementByGUID<CreditCard>(credit_cards, guid);
726 return (iter != credit_cards.end()) ? *iter : NULL;
729 void PersonalDataManager::GetNonEmptyTypes(
730 ServerFieldTypeSet* non_empty_types) {
731 for (AutofillProfile* profile : GetProfiles())
732 profile->GetNonEmptyTypes(app_locale_, non_empty_types);
733 for (CreditCard* card : GetCreditCards())
734 card->GetNonEmptyTypes(app_locale_, non_empty_types);
737 bool PersonalDataManager::IsDataLoaded() const {
738 return is_data_loaded_;
741 const std::vector<AutofillProfile*>& PersonalDataManager::GetProfiles() const {
742 return GetProfiles(false);
745 const std::vector<AutofillProfile*>& PersonalDataManager::web_profiles() const {
746 return web_profiles_.get();
749 const std::vector<CreditCard*>& PersonalDataManager::GetLocalCreditCards()
750 const {
751 return local_credit_cards_.get();
754 const std::vector<CreditCard*>& PersonalDataManager::GetCreditCards() const {
755 credit_cards_.clear();
756 credit_cards_.insert(credit_cards_.end(), local_credit_cards_.begin(),
757 local_credit_cards_.end());
758 if (IsExperimentalWalletIntegrationEnabled() &&
759 pref_service_->GetBoolean(prefs::kAutofillWalletImportEnabled)) {
760 credit_cards_.insert(credit_cards_.end(), server_credit_cards_.begin(),
761 server_credit_cards_.end());
763 return credit_cards_;
766 bool PersonalDataManager::HasServerData() const {
767 return !server_credit_cards_.empty() || !server_profiles_.empty();
770 void PersonalDataManager::Refresh() {
771 LoadProfiles();
772 LoadCreditCards();
775 std::vector<Suggestion> PersonalDataManager::GetProfileSuggestions(
776 const AutofillType& type,
777 const base::string16& field_contents,
778 bool field_is_autofilled,
779 const std::vector<ServerFieldType>& other_field_types) {
780 base::string16 field_contents_canon =
781 AutofillProfile::CanonicalizeProfileString(field_contents);
783 std::vector<AutofillProfile*> profiles = GetProfiles(true);
784 std::sort(profiles.begin(), profiles.end(), RankByMfu);
786 std::vector<Suggestion> suggestions;
787 // Match based on a prefix search.
788 std::vector<AutofillProfile*> matched_profiles;
789 for (AutofillProfile* profile : profiles) {
790 base::string16 value = GetInfoInOneLine(profile, type, app_locale_);
791 if (value.empty())
792 continue;
793 base::string16 value_canon =
794 AutofillProfile::CanonicalizeProfileString(value);
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(value));
799 suggestions.back().backend_id = profile->guid();
803 // Don't show two suggestions if one is a subset of the other.
804 std::vector<AutofillProfile*> unique_matched_profiles;
805 std::vector<Suggestion> unique_suggestions;
806 ServerFieldTypeSet types(other_field_types.begin(), other_field_types.end());
807 for (size_t i = 0; i < matched_profiles.size(); ++i) {
808 bool include = true;
809 AutofillProfile* profile_a = matched_profiles[i];
810 for (size_t j = 0; j < matched_profiles.size(); ++j) {
811 AutofillProfile* profile_b = matched_profiles[j];
812 // Check if profile A is a subset of profile B. If not, continue.
813 if (i == j || suggestions[i].value != suggestions[j].value ||
814 !profile_a->IsSubsetOfForFieldSet(*profile_b, app_locale_, types)) {
815 continue;
818 // Check if profile B is also a subset of profile A. If so, the
819 // profiles are identical. Include the first one but not the second.
820 if (i < j &&
821 profile_b->IsSubsetOfForFieldSet(*profile_a, app_locale_, types)) {
822 continue;
825 // One-way subset. Don't include profile A.
826 include = false;
827 break;
829 if (include) {
830 unique_matched_profiles.push_back(matched_profiles[i]);
831 unique_suggestions.push_back(suggestions[i]);
835 // Generate disambiguating labels based on the list of matches.
836 std::vector<base::string16> labels;
837 AutofillProfile::CreateInferredLabels(
838 unique_matched_profiles, &other_field_types, type.GetStorableType(), 1,
839 app_locale_, &labels);
840 DCHECK_EQ(unique_suggestions.size(), labels.size());
841 for (size_t i = 0; i < labels.size(); i++)
842 unique_suggestions[i].label = labels[i];
844 return unique_suggestions;
847 std::vector<Suggestion> PersonalDataManager::GetCreditCardSuggestions(
848 const AutofillType& type,
849 const base::string16& field_contents) {
850 std::list<const CreditCard*> cards_to_suggest;
851 for (const CreditCard* credit_card : GetCreditCards()) {
852 // The value of the stored data for this field type in the |credit_card|.
853 base::string16 creditcard_field_value =
854 credit_card->GetInfo(type, app_locale_);
855 if (creditcard_field_value.empty())
856 continue;
858 // For card number fields, suggest the card if:
859 // - the number matches any part of the card, or
860 // - it's a masked card and there are 6 or fewers typed so far.
861 // For other fields, require that the field contents match the beginning of
862 // the stored data.
863 if (type.GetStorableType() == CREDIT_CARD_NUMBER) {
864 if (creditcard_field_value.find(field_contents) == base::string16::npos &&
865 (credit_card->record_type() != CreditCard::MASKED_SERVER_CARD ||
866 field_contents.size() >= 6)) {
867 continue;
869 } else if (!StartsWith(creditcard_field_value, field_contents, false)) {
870 continue;
873 cards_to_suggest.push_back(credit_card);
876 // De-dupe card suggestions. Full server cards shadow local cards, and
877 // local cards shadow masked server cards.
878 for (auto outer_it = cards_to_suggest.begin();
879 outer_it != cards_to_suggest.end();
880 ++outer_it) {
882 if ((*outer_it)->record_type() == CreditCard::FULL_SERVER_CARD) {
883 for (auto inner_it = cards_to_suggest.begin();
884 inner_it != cards_to_suggest.end();) {
885 auto inner_it_copy = inner_it++;
886 if ((*inner_it_copy)->IsLocalDuplicateOfServerCard(**outer_it))
887 cards_to_suggest.erase(inner_it_copy);
889 } else if ((*outer_it)->record_type() == CreditCard::LOCAL_CARD) {
890 for (auto inner_it = cards_to_suggest.begin();
891 inner_it != cards_to_suggest.end();) {
892 auto inner_it_copy = inner_it++;
893 if ((*inner_it_copy)->record_type() == CreditCard::MASKED_SERVER_CARD &&
894 (*outer_it)->IsLocalDuplicateOfServerCard(**inner_it_copy)) {
895 cards_to_suggest.erase(inner_it_copy);
901 cards_to_suggest.sort(RankByMfu);
903 std::vector<Suggestion> suggestions;
904 for (const CreditCard* credit_card : cards_to_suggest) {
905 // Make a new suggestion.
906 suggestions.push_back(Suggestion());
907 Suggestion* suggestion = &suggestions.back();
909 suggestion->value = credit_card->GetInfo(type, app_locale_);
910 suggestion->icon = base::UTF8ToUTF16(credit_card->type());
911 suggestion->backend_id = credit_card->guid();
913 // If the value is the card number, the label is the expiration date.
914 // Otherwise the label is the card number, or if that is empty the
915 // cardholder name. The label should never repeat the value.
916 if (type.GetStorableType() == CREDIT_CARD_NUMBER) {
917 suggestion->value = credit_card->TypeAndLastFourDigits();
918 suggestion->label = credit_card->GetInfo(
919 AutofillType(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR), app_locale_);
920 } else if (credit_card->number().empty()) {
921 if (type.GetStorableType() != CREDIT_CARD_NAME) {
922 suggestion->label =
923 credit_card->GetInfo(AutofillType(CREDIT_CARD_NAME), app_locale_);
925 } else {
926 #if defined(OS_ANDROID)
927 // Since Android places the label on its own row, there's more horizontal
928 // space to work with. Show "Amex - 1234" rather than desktop's "*1234".
929 suggestion->label = credit_card->TypeAndLastFourDigits();
930 #else
931 suggestion->label = base::ASCIIToUTF16("*");
932 suggestion->label.append(credit_card->LastFourDigits());
933 #endif
936 return suggestions;
939 bool PersonalDataManager::IsAutofillEnabled() const {
940 return ::autofill::IsAutofillEnabled(pref_service_);
943 std::string PersonalDataManager::CountryCodeForCurrentTimezone() const {
944 return base::CountryCodeForCurrentTimezone();
947 void PersonalDataManager::SetPrefService(PrefService* pref_service) {
948 enabled_pref_.reset(new BooleanPrefMember);
949 wallet_enabled_pref_.reset(new BooleanPrefMember);
950 pref_service_ = pref_service;
951 // |pref_service_| can be NULL in tests.
952 if (pref_service_) {
953 enabled_pref_->Init(prefs::kAutofillEnabled, pref_service_,
954 base::Bind(&PersonalDataManager::EnabledPrefChanged,
955 base::Unretained(this)));
956 wallet_enabled_pref_->Init(prefs::kAutofillWalletImportEnabled,
957 pref_service_,
958 base::Bind(&PersonalDataManager::EnabledPrefChanged,
959 base::Unretained(this)));
963 // static
964 bool PersonalDataManager::IsValidLearnableProfile(
965 const AutofillProfile& profile,
966 const std::string& app_locale) {
967 if (!IsMinimumAddress(profile, app_locale))
968 return false;
970 base::string16 email = profile.GetRawInfo(EMAIL_ADDRESS);
971 if (!email.empty() && !IsValidEmailAddress(email))
972 return false;
974 // Reject profiles with invalid US state information.
975 if (profile.IsPresentButInvalid(ADDRESS_HOME_STATE))
976 return false;
978 // Reject profiles with invalid US zip information.
979 if (profile.IsPresentButInvalid(ADDRESS_HOME_ZIP))
980 return false;
982 return true;
985 // static
986 std::string PersonalDataManager::MergeProfile(
987 const AutofillProfile& new_profile,
988 const std::vector<AutofillProfile*>& existing_profiles,
989 const std::string& app_locale,
990 std::vector<AutofillProfile>* merged_profiles) {
991 merged_profiles->clear();
993 // Set to true if |existing_profiles| already contains an equivalent profile.
994 bool matching_profile_found = false;
995 std::string guid = new_profile.guid();
997 // If we have already saved this address, merge in any missing values.
998 // Only merge with the first match.
999 for (AutofillProfile* existing_profile : existing_profiles) {
1000 if (!matching_profile_found && !new_profile.PrimaryValue().empty() &&
1001 existing_profile->SaveAdditionalInfo(new_profile, app_locale)) {
1002 // Unverified profiles should always be updated with the newer data,
1003 // whereas verified profiles should only ever be overwritten by verified
1004 // data. If an automatically aggregated profile would overwrite a
1005 // verified profile, just drop it.
1006 matching_profile_found = true;
1007 guid = existing_profile->guid();
1009 merged_profiles->push_back(*existing_profile);
1012 // If the new profile was not merged with an existing one, add it to the list.
1013 if (!matching_profile_found)
1014 merged_profiles->push_back(new_profile);
1016 return guid;
1019 bool PersonalDataManager::IsCountryOfInterest(const std::string& country_code)
1020 const {
1021 DCHECK_EQ(2U, country_code.size());
1023 const std::vector<AutofillProfile*>& profiles = web_profiles();
1024 std::list<std::string> country_codes;
1025 for (size_t i = 0; i < profiles.size(); ++i) {
1026 country_codes.push_back(base::StringToLowerASCII(base::UTF16ToASCII(
1027 profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY))));
1030 std::string timezone_country = CountryCodeForCurrentTimezone();
1031 if (!timezone_country.empty())
1032 country_codes.push_back(base::StringToLowerASCII(timezone_country));
1034 // Only take the locale into consideration if all else fails.
1035 if (country_codes.empty()) {
1036 country_codes.push_back(base::StringToLowerASCII(
1037 AutofillCountry::CountryCodeForLocale(app_locale())));
1040 return std::find(country_codes.begin(), country_codes.end(),
1041 base::StringToLowerASCII(country_code)) !=
1042 country_codes.end();
1045 const std::string& PersonalDataManager::GetDefaultCountryCodeForNewAddress()
1046 const {
1047 if (default_country_code_.empty())
1048 default_country_code_ = MostCommonCountryCodeFromProfiles();
1050 // Failing that, guess based on system timezone.
1051 if (default_country_code_.empty())
1052 default_country_code_ = CountryCodeForCurrentTimezone();
1054 // Failing that, guess based on locale.
1055 if (default_country_code_.empty())
1056 default_country_code_ = AutofillCountry::CountryCodeForLocale(app_locale());
1058 return default_country_code_;
1061 bool PersonalDataManager::IsExperimentalWalletIntegrationEnabled() const {
1062 return pref_service_->GetBoolean(prefs::kAutofillWalletSyncExperimentEnabled);
1065 void PersonalDataManager::SetProfiles(std::vector<AutofillProfile>* profiles) {
1066 if (is_off_the_record_)
1067 return;
1069 // Remove empty profiles from input.
1070 profiles->erase(std::remove_if(profiles->begin(), profiles->end(),
1071 IsEmptyFunctor<AutofillProfile>(app_locale_)),
1072 profiles->end());
1074 if (!database_.get())
1075 return;
1077 // Any profiles that are not in the new profile list should be removed from
1078 // the web database.
1079 for (std::vector<AutofillProfile*>::const_iterator iter =
1080 web_profiles_.begin();
1081 iter != web_profiles_.end(); ++iter) {
1082 if (!FindByGUID<AutofillProfile>(*profiles, (*iter)->guid()))
1083 database_->RemoveAutofillProfile((*iter)->guid());
1086 // Update the web database with the existing profiles.
1087 for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
1088 iter != profiles->end(); ++iter) {
1089 if (FindByGUID<AutofillProfile>(web_profiles_, iter->guid()))
1090 database_->UpdateAutofillProfile(*iter);
1093 // Add the new profiles to the web database. Don't add a duplicate.
1094 for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
1095 iter != profiles->end(); ++iter) {
1096 if (!FindByGUID<AutofillProfile>(web_profiles_, iter->guid()) &&
1097 !FindByContents(web_profiles_, *iter))
1098 database_->AddAutofillProfile(*iter);
1101 // Copy in the new profiles.
1102 web_profiles_.clear();
1103 for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
1104 iter != profiles->end(); ++iter) {
1105 web_profiles_.push_back(new AutofillProfile(*iter));
1108 // Refresh our local cache and send notifications to observers.
1109 Refresh();
1112 void PersonalDataManager::SetCreditCards(
1113 std::vector<CreditCard>* credit_cards) {
1114 if (is_off_the_record_)
1115 return;
1117 // Remove empty credit cards from input.
1118 credit_cards->erase(std::remove_if(credit_cards->begin(), credit_cards->end(),
1119 IsEmptyFunctor<CreditCard>(app_locale_)),
1120 credit_cards->end());
1122 if (!database_.get())
1123 return;
1125 // Any credit cards that are not in the new credit card list should be
1126 // removed.
1127 for (const CreditCard* card : local_credit_cards_) {
1128 if (!FindByGUID<CreditCard>(*credit_cards, card->guid()))
1129 database_->RemoveCreditCard(card->guid());
1132 // Update the web database with the existing credit cards.
1133 for (const CreditCard& card : *credit_cards) {
1134 if (FindByGUID<CreditCard>(local_credit_cards_, card.guid()))
1135 database_->UpdateCreditCard(card);
1138 // Add the new credit cards to the web database. Don't add a duplicate.
1139 for (const CreditCard& card : *credit_cards) {
1140 if (!FindByGUID<CreditCard>(local_credit_cards_, card.guid()) &&
1141 !FindByContents(local_credit_cards_, card))
1142 database_->AddCreditCard(card);
1145 // Copy in the new credit cards.
1146 local_credit_cards_.clear();
1147 for (const CreditCard& card : *credit_cards)
1148 local_credit_cards_.push_back(new CreditCard(card));
1150 // Refresh our local cache and send notifications to observers.
1151 Refresh();
1154 void PersonalDataManager::LoadProfiles() {
1155 if (!database_.get()) {
1156 NOTREACHED();
1157 return;
1160 CancelPendingQuery(&pending_profiles_query_);
1161 CancelPendingQuery(&pending_server_profiles_query_);
1163 pending_profiles_query_ = database_->GetAutofillProfiles(this);
1164 pending_server_profiles_query_ = database_->GetServerProfiles(this);
1167 // Win, Linux, Android and iOS implementations do nothing. Mac implementation
1168 // fills in the contents of |auxiliary_profiles_|.
1169 #if defined(OS_IOS) || !defined(OS_MACOSX)
1170 void PersonalDataManager::LoadAuxiliaryProfiles(bool record_metrics) const {
1172 #endif
1174 void PersonalDataManager::LoadCreditCards() {
1175 if (!database_.get()) {
1176 NOTREACHED();
1177 return;
1180 CancelPendingQuery(&pending_creditcards_query_);
1181 CancelPendingQuery(&pending_server_creditcards_query_);
1183 pending_creditcards_query_ = database_->GetCreditCards(this);
1184 pending_server_creditcards_query_ = database_->GetServerCreditCards(this);
1187 void PersonalDataManager::CancelPendingQuery(
1188 WebDataServiceBase::Handle* handle) {
1189 if (*handle) {
1190 if (!database_.get()) {
1191 NOTREACHED();
1192 return;
1194 database_->CancelRequest(*handle);
1196 *handle = 0;
1199 std::string PersonalDataManager::SaveImportedProfile(
1200 const AutofillProfile& imported_profile) {
1201 if (is_off_the_record_)
1202 return std::string();
1204 // Don't save a web profile if the data in the profile is a subset of an
1205 // auxiliary profile...
1206 for (AutofillProfile* profile : auxiliary_profiles_) {
1207 if (imported_profile.IsSubsetOf(*profile, app_locale_))
1208 return profile->guid();
1211 // ...or server profile.
1212 for (AutofillProfile* profile : server_profiles_) {
1213 if (imported_profile.IsSubsetOf(*profile, app_locale_))
1214 return profile->guid();
1217 std::vector<AutofillProfile> profiles;
1218 std::string guid =
1219 MergeProfile(imported_profile, web_profiles_.get(), app_locale_,
1220 &profiles);
1221 SetProfiles(&profiles);
1222 return guid;
1225 void PersonalDataManager::NotifyPersonalDataChanged() {
1226 FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_,
1227 OnPersonalDataChanged());
1230 std::string PersonalDataManager::SaveImportedCreditCard(
1231 const CreditCard& imported_card) {
1232 DCHECK(!imported_card.number().empty());
1233 if (is_off_the_record_)
1234 return std::string();
1236 // Set to true if |imported_card| is merged into the credit card list.
1237 bool merged = false;
1239 std::string guid = imported_card.guid();
1240 std::vector<CreditCard> credit_cards;
1241 for (CreditCard* card : local_credit_cards_) {
1242 // If |imported_card| has not yet been merged, check whether it should be
1243 // with the current |card|.
1244 if (!merged && card->UpdateFromImportedCard(imported_card, app_locale_)) {
1245 guid = card->guid();
1246 merged = true;
1249 credit_cards.push_back(*card);
1252 if (!merged)
1253 credit_cards.push_back(imported_card);
1255 SetCreditCards(&credit_cards);
1256 return guid;
1259 void PersonalDataManager::LogProfileCount() const {
1260 if (!has_logged_profile_count_) {
1261 AutofillMetrics::LogStoredProfileCount(web_profiles_.size());
1262 has_logged_profile_count_ = true;
1266 std::string PersonalDataManager::MostCommonCountryCodeFromProfiles() const {
1267 if (!IsAutofillEnabled())
1268 return std::string();
1270 // Count up country codes from existing profiles.
1271 std::map<std::string, int> votes;
1272 // TODO(estade): can we make this GetProfiles() instead? It seems to cause
1273 // errors in tests on mac trybots. See http://crbug.com/57221
1274 const std::vector<AutofillProfile*>& profiles = web_profiles();
1275 std::vector<std::string> country_codes;
1276 AutofillCountry::GetAvailableCountries(&country_codes);
1277 for (size_t i = 0; i < profiles.size(); ++i) {
1278 std::string country_code = base::StringToUpperASCII(base::UTF16ToASCII(
1279 profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY)));
1281 if (std::find(country_codes.begin(), country_codes.end(), country_code) !=
1282 country_codes.end()) {
1283 // Verified profiles count 100x more than unverified ones.
1284 votes[country_code] += profiles[i]->IsVerified() ? 100 : 1;
1288 // Take the most common country code.
1289 if (!votes.empty()) {
1290 std::map<std::string, int>::iterator iter =
1291 std::max_element(votes.begin(), votes.end(), CompareVotes);
1292 return iter->first;
1295 return std::string();
1298 void PersonalDataManager::EnabledPrefChanged() {
1299 default_country_code_.clear();
1300 if (!pref_service_->GetBoolean(prefs::kAutofillWalletImportEnabled)) {
1301 // Re-mask all server cards when the user turns off wallet card
1302 // integration.
1303 ResetFullServerCards();
1305 NotifyPersonalDataChanged();
1308 const std::vector<AutofillProfile*>& PersonalDataManager::GetProfiles(
1309 bool record_metrics) const {
1310 #if defined(OS_MACOSX) && !defined(OS_IOS)
1311 bool use_auxiliary_profiles =
1312 pref_service_->GetBoolean(prefs::kAutofillUseMacAddressBook);
1313 #else
1314 bool use_auxiliary_profiles =
1315 pref_service_->GetBoolean(prefs::kAutofillAuxiliaryProfilesEnabled);
1316 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
1318 profiles_.clear();
1319 profiles_.insert(profiles_.end(), web_profiles().begin(),
1320 web_profiles().end());
1321 if (use_auxiliary_profiles) {
1322 LoadAuxiliaryProfiles(record_metrics);
1323 profiles_.insert(
1324 profiles_.end(), auxiliary_profiles_.begin(),
1325 auxiliary_profiles_.end());
1327 if (IsExperimentalWalletIntegrationEnabled() &&
1328 pref_service_->GetBoolean(prefs::kAutofillWalletImportEnabled)) {
1329 profiles_.insert(
1330 profiles_.end(), server_profiles_.begin(), server_profiles_.end());
1332 return profiles_;
1335 } // namespace autofill