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.
4
5 #include "components/autofill/core/browser/personal_data_manager.h"
6
7 #include <algorithm>
8 #include <functional>
9 #include <iterator>
10
11 #include "base/i18n/timezone.h"
12 #include "base/logging.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/prefs/pref_service.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "components/autofill/core/browser/address_i18n.h"
19 #include "components/autofill/core/browser/autofill-inl.h"
20 #include "components/autofill/core/browser/autofill_country.h"
21 #include "components/autofill/core/browser/autofill_field.h"
22 #include "components/autofill/core/browser/form_structure.h"
23 #include "components/autofill/core/browser/personal_data_manager_observer.h"
24 #include "components/autofill/core/browser/phone_number.h"
25 #include "components/autofill/core/browser/phone_number_i18n.h"
26 #include "components/autofill/core/browser/validation.h"
27 #include "components/autofill/core/common/autofill_pref_names.h"
28 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
29 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_formatter.h"
30
31 namespace autofill {
32 namespace {
33
34 using ::i18n::addressinput::AddressField;
35 using ::i18n::addressinput::GetStreetAddressLinesAsSingleLine;
36 using ::i18n::addressinput::STREET_ADDRESS;
37
38 const base::string16::value_type kCreditCardPrefix[] = {'*', 0};
39
40 template<typename T>
41 class FormGroupMatchesByGUIDFunctor {
42 public:
FormGroupMatchesByGUIDFunctor(const std::string & guid)43 explicit FormGroupMatchesByGUIDFunctor(const std::string& guid)
44 : guid_(guid) {
45 }
46
operator ()(const T & form_group)47 bool operator()(const T& form_group) {
48 return form_group.guid() == guid_;
49 }
50
operator ()(const T * form_group)51 bool operator()(const T* form_group) {
52 return form_group->guid() == guid_;
53 }
54
55 private:
56 const std::string guid_;
57 };
58
59 template<typename T, typename C>
FindElementByGUID(const C & container,const std::string & guid)60 typename C::const_iterator FindElementByGUID(const C& container,
61 const std::string& guid) {
62 return std::find_if(container.begin(),
63 container.end(),
64 FormGroupMatchesByGUIDFunctor<T>(guid));
65 }
66
67 template<typename T, typename C>
FindByGUID(const C & container,const std::string & guid)68 bool FindByGUID(const C& container, const std::string& guid) {
69 return FindElementByGUID<T>(container, guid) != container.end();
70 }
71
72 template<typename T>
73 class IsEmptyFunctor {
74 public:
IsEmptyFunctor(const std::string & app_locale)75 explicit IsEmptyFunctor(const std::string& app_locale)
76 : app_locale_(app_locale) {
77 }
78
operator ()(const T & form_group)79 bool operator()(const T& form_group) {
80 return form_group.IsEmpty(app_locale_);
81 }
82
83 private:
84 const std::string app_locale_;
85 };
86
87 // Returns true if minimum requirements for import of a given |profile| have
88 // been met. An address submitted via a form must have at least the fields
89 // required as determined by its country code.
90 // No verification of validity of the contents is preformed. This is an
91 // existence check only.
IsMinimumAddress(const AutofillProfile & profile,const std::string & app_locale)92 bool IsMinimumAddress(const AutofillProfile& profile,
93 const std::string& app_locale) {
94 // All countries require at least one address line.
95 if (profile.GetRawInfo(ADDRESS_HOME_LINE1).empty())
96 return false;
97
98 std::string country_code =
99 base::UTF16ToASCII(profile.GetRawInfo(ADDRESS_HOME_COUNTRY));
100 if (country_code.empty())
101 country_code = AutofillCountry::CountryCodeForLocale(app_locale);
102
103 AutofillCountry country(country_code, app_locale);
104
105 if (country.requires_city() && profile.GetRawInfo(ADDRESS_HOME_CITY).empty())
106 return false;
107
108 if (country.requires_state() &&
109 profile.GetRawInfo(ADDRESS_HOME_STATE).empty())
110 return false;
111
112 if (country.requires_zip() && profile.GetRawInfo(ADDRESS_HOME_ZIP).empty())
113 return false;
114
115 return true;
116 }
117
118 // Return true if the |field_type| and |value| are valid within the context
119 // of importing a form.
IsValidFieldTypeAndValue(const std::set<ServerFieldType> & types_seen,ServerFieldType field_type,const base::string16 & value)120 bool IsValidFieldTypeAndValue(const std::set<ServerFieldType>& types_seen,
121 ServerFieldType field_type,
122 const base::string16& value) {
123 // Abandon the import if two fields of the same type are encountered.
124 // This indicates ambiguous data or miscategorization of types.
125 // Make an exception for PHONE_HOME_NUMBER however as both prefix and
126 // suffix are stored against this type, and for EMAIL_ADDRESS because it is
127 // common to see second 'confirm email address' fields on forms.
128 if (types_seen.count(field_type) &&
129 field_type != PHONE_HOME_NUMBER &&
130 field_type != EMAIL_ADDRESS)
131 return false;
132
133 // Abandon the import if an email address value shows up in a field that is
134 // not an email address.
135 if (field_type != EMAIL_ADDRESS && IsValidEmailAddress(value))
136 return false;
137
138 return true;
139 }
140
141 // A helper function for finding the maximum value in a string->int map.
CompareVotes(const std::pair<std::string,int> & a,const std::pair<std::string,int> & b)142 static bool CompareVotes(const std::pair<std::string, int>& a,
143 const std::pair<std::string, int>& b) {
144 return a.second < b.second;
145 }
146
147 } // namespace
148
PersonalDataManager(const std::string & app_locale)149 PersonalDataManager::PersonalDataManager(const std::string& app_locale)
150 : database_(NULL),
151 is_data_loaded_(false),
152 pending_profiles_query_(0),
153 pending_creditcards_query_(0),
154 app_locale_(app_locale),
155 metric_logger_(new AutofillMetrics),
156 pref_service_(NULL),
157 is_off_the_record_(false),
158 has_logged_profile_count_(false) {}
159
Init(scoped_refptr<AutofillWebDataService> database,PrefService * pref_service,bool is_off_the_record)160 void PersonalDataManager::Init(scoped_refptr<AutofillWebDataService> database,
161 PrefService* pref_service,
162 bool is_off_the_record) {
163 database_ = database;
164 SetPrefService(pref_service);
165 is_off_the_record_ = is_off_the_record;
166
167 if (!is_off_the_record_)
168 metric_logger_->LogIsAutofillEnabledAtStartup(IsAutofillEnabled());
169
170 // WebDataService may not be available in tests.
171 if (!database_.get())
172 return;
173
174 LoadProfiles();
175 LoadCreditCards();
176
177 database_->AddObserver(this);
178 }
179
~PersonalDataManager()180 PersonalDataManager::~PersonalDataManager() {
181 CancelPendingQuery(&pending_profiles_query_);
182 CancelPendingQuery(&pending_creditcards_query_);
183
184 if (database_.get())
185 database_->RemoveObserver(this);
186 }
187
OnWebDataServiceRequestDone(WebDataServiceBase::Handle h,const WDTypedResult * result)188 void PersonalDataManager::OnWebDataServiceRequestDone(
189 WebDataServiceBase::Handle h,
190 const WDTypedResult* result) {
191 DCHECK(pending_profiles_query_ || pending_creditcards_query_);
192
193 if (!result) {
194 // Error from the web database.
195 if (h == pending_creditcards_query_)
196 pending_creditcards_query_ = 0;
197 else if (h == pending_profiles_query_)
198 pending_profiles_query_ = 0;
199 return;
200 }
201
202 switch (result->GetType()) {
203 case AUTOFILL_PROFILES_RESULT:
204 ReceiveLoadedProfiles(h, result);
205 break;
206 case AUTOFILL_CREDITCARDS_RESULT:
207 ReceiveLoadedCreditCards(h, result);
208 break;
209 default:
210 NOTREACHED();
211 }
212
213 // If both requests have responded, then all personal data is loaded.
214 if (pending_profiles_query_ == 0 && pending_creditcards_query_ == 0) {
215 is_data_loaded_ = true;
216 NotifyPersonalDataChanged();
217 }
218 }
219
AutofillMultipleChanged()220 void PersonalDataManager::AutofillMultipleChanged() {
221 Refresh();
222 }
223
AddObserver(PersonalDataManagerObserver * observer)224 void PersonalDataManager::AddObserver(PersonalDataManagerObserver* observer) {
225 observers_.AddObserver(observer);
226 }
227
RemoveObserver(PersonalDataManagerObserver * observer)228 void PersonalDataManager::RemoveObserver(
229 PersonalDataManagerObserver* observer) {
230 observers_.RemoveObserver(observer);
231 }
232
ImportFormData(const FormStructure & form,scoped_ptr<CreditCard> * imported_credit_card)233 bool PersonalDataManager::ImportFormData(
234 const FormStructure& form,
235 scoped_ptr<CreditCard>* imported_credit_card) {
236 scoped_ptr<AutofillProfile> imported_profile(new AutofillProfile);
237 scoped_ptr<CreditCard> local_imported_credit_card(new CreditCard);
238
239 const std::string origin = form.source_url().spec();
240 imported_profile->set_origin(origin);
241 local_imported_credit_card->set_origin(origin);
242
243 // Parse the form and construct a profile based on the information that is
244 // possible to import.
245 int importable_credit_card_fields = 0;
246
247 // Detect and discard forms with multiple fields of the same type.
248 // TODO(isherman): Some types are overlapping but not equal, e.g. phone number
249 // parts, address parts.
250 std::set<ServerFieldType> types_seen;
251
252 // We only set complete phone, so aggregate phone parts in these vars and set
253 // complete at the end.
254 PhoneNumber::PhoneCombineHelper home;
255
256 for (size_t i = 0; i < form.field_count(); ++i) {
257 const AutofillField* field = form.field(i);
258 base::string16 value;
259 base::TrimWhitespace(field->value, base::TRIM_ALL, &value);
260
261 // If we don't know the type of the field, or the user hasn't entered any
262 // information into the field, then skip it.
263 if (!field->IsFieldFillable() || value.empty())
264 continue;
265
266 AutofillType field_type = field->Type();
267 ServerFieldType server_field_type = field_type.GetStorableType();
268 FieldTypeGroup group(field_type.group());
269
270 // There can be multiple email fields (e.g. in the case of 'confirm email'
271 // fields) but they must all contain the same value, else the profile is
272 // invalid.
273 if (server_field_type == EMAIL_ADDRESS) {
274 if (types_seen.count(server_field_type) &&
275 imported_profile->GetRawInfo(EMAIL_ADDRESS) != value) {
276 imported_profile.reset();
277 break;
278 }
279 }
280
281 // If the |field_type| and |value| don't pass basic validity checks then
282 // abandon the import.
283 if (!IsValidFieldTypeAndValue(types_seen, server_field_type, value)) {
284 imported_profile.reset();
285 local_imported_credit_card.reset();
286 break;
287 }
288
289 types_seen.insert(server_field_type);
290
291 if (group == CREDIT_CARD) {
292 if (LowerCaseEqualsASCII(field->form_control_type, "month")) {
293 DCHECK_EQ(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, server_field_type);
294 local_imported_credit_card->SetInfoForMonthInputType(value);
295 } else {
296 local_imported_credit_card->SetInfo(field_type, value, app_locale_);
297 }
298 ++importable_credit_card_fields;
299 } else {
300 // We need to store phone data in the variables, before building the whole
301 // number at the end. The rest of the fields are set "as is".
302 // If the fields are not the phone fields in question home.SetInfo() is
303 // going to return false.
304 if (!home.SetInfo(field_type, value))
305 imported_profile->SetInfo(field_type, value, app_locale_);
306
307 // Reject profiles with invalid country information.
308 if (server_field_type == ADDRESS_HOME_COUNTRY &&
309 !value.empty() &&
310 imported_profile->GetRawInfo(ADDRESS_HOME_COUNTRY).empty()) {
311 imported_profile.reset();
312 break;
313 }
314 }
315 }
316
317 // Construct the phone number. Reject the profile if the number is invalid.
318 if (imported_profile.get() && !home.IsEmpty()) {
319 base::string16 constructed_number;
320 if (!home.ParseNumber(*imported_profile, app_locale_,
321 &constructed_number) ||
322 !imported_profile->SetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER),
323 constructed_number,
324 app_locale_)) {
325 imported_profile.reset();
326 }
327 }
328
329 // Reject the profile if minimum address and validation requirements are not
330 // met.
331 if (imported_profile.get() &&
332 !IsValidLearnableProfile(*imported_profile, app_locale_))
333 imported_profile.reset();
334
335 // Reject the credit card if we did not detect enough filled credit card
336 // fields or if the credit card number does not seem to be valid.
337 if (local_imported_credit_card.get() &&
338 !local_imported_credit_card->IsComplete()) {
339 local_imported_credit_card.reset();
340 }
341
342 // Don't import if we already have this info.
343 // Don't present an infobar if we have already saved this card number.
344 bool merged_credit_card = false;
345 if (local_imported_credit_card.get()) {
346 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin();
347 iter != credit_cards_.end();
348 ++iter) {
349 // Make a local copy so that the data in |credit_cards_| isn't modified
350 // directly by the UpdateFromImportedCard() call.
351 CreditCard card = **iter;
352 if (card.UpdateFromImportedCard(*local_imported_credit_card.get(),
353 app_locale_)) {
354 merged_credit_card = true;
355 UpdateCreditCard(card);
356 local_imported_credit_card.reset();
357 break;
358 }
359 }
360 }
361
362 if (imported_profile.get()) {
363 // We always save imported profiles.
364 SaveImportedProfile(*imported_profile);
365 }
366 *imported_credit_card = local_imported_credit_card.Pass();
367
368 if (imported_profile.get() || *imported_credit_card || merged_credit_card)
369 return true;
370
371 FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_,
372 OnInsufficientFormData());
373 return false;
374 }
375
AddProfile(const AutofillProfile & profile)376 void PersonalDataManager::AddProfile(const AutofillProfile& profile) {
377 if (is_off_the_record_)
378 return;
379
380 if (profile.IsEmpty(app_locale_))
381 return;
382
383 // Don't add an existing profile.
384 if (FindByGUID<AutofillProfile>(web_profiles_, profile.guid()))
385 return;
386
387 if (!database_.get())
388 return;
389
390 // Don't add a duplicate.
391 if (FindByContents(web_profiles_, profile))
392 return;
393
394 // Add the new profile to the web database.
395 database_->AddAutofillProfile(profile);
396
397 // Refresh our local cache and send notifications to observers.
398 Refresh();
399 }
400
UpdateProfile(const AutofillProfile & profile)401 void PersonalDataManager::UpdateProfile(const AutofillProfile& profile) {
402 if (is_off_the_record_)
403 return;
404
405 AutofillProfile* existing_profile = GetProfileByGUID(profile.guid());
406 if (!existing_profile)
407 return;
408
409 // Don't overwrite the origin for a profile that is already stored.
410 if (existing_profile->EqualsSansOrigin(profile))
411 return;
412
413 if (profile.IsEmpty(app_locale_)) {
414 RemoveByGUID(profile.guid());
415 return;
416 }
417
418 if (!database_.get())
419 return;
420
421 // Make the update.
422 database_->UpdateAutofillProfile(profile);
423
424 // Refresh our local cache and send notifications to observers.
425 Refresh();
426 }
427
GetProfileByGUID(const std::string & guid)428 AutofillProfile* PersonalDataManager::GetProfileByGUID(
429 const std::string& guid) {
430 const std::vector<AutofillProfile*>& profiles = GetProfiles();
431 std::vector<AutofillProfile*>::const_iterator iter =
432 FindElementByGUID<AutofillProfile>(profiles, guid);
433 return (iter != profiles.end()) ? *iter : NULL;
434 }
435
AddCreditCard(const CreditCard & credit_card)436 void PersonalDataManager::AddCreditCard(const CreditCard& credit_card) {
437 if (is_off_the_record_)
438 return;
439
440 if (credit_card.IsEmpty(app_locale_))
441 return;
442
443 if (FindByGUID<CreditCard>(credit_cards_, credit_card.guid()))
444 return;
445
446 if (!database_.get())
447 return;
448
449 // Don't add a duplicate.
450 if (FindByContents(credit_cards_, credit_card))
451 return;
452
453 // Add the new credit card to the web database.
454 database_->AddCreditCard(credit_card);
455
456 // Refresh our local cache and send notifications to observers.
457 Refresh();
458 }
459
UpdateCreditCard(const CreditCard & credit_card)460 void PersonalDataManager::UpdateCreditCard(const CreditCard& credit_card) {
461 if (is_off_the_record_)
462 return;
463
464 CreditCard* existing_credit_card = GetCreditCardByGUID(credit_card.guid());
465 if (!existing_credit_card)
466 return;
467
468 // Don't overwrite the origin for a credit card that is already stored.
469 if (existing_credit_card->Compare(credit_card) == 0)
470 return;
471
472 if (credit_card.IsEmpty(app_locale_)) {
473 RemoveByGUID(credit_card.guid());
474 return;
475 }
476
477 if (!database_.get())
478 return;
479
480 // Make the update.
481 database_->UpdateCreditCard(credit_card);
482
483 // Refresh our local cache and send notifications to observers.
484 Refresh();
485 }
486
RemoveByGUID(const std::string & guid)487 void PersonalDataManager::RemoveByGUID(const std::string& guid) {
488 if (is_off_the_record_)
489 return;
490
491 bool is_credit_card = FindByGUID<CreditCard>(credit_cards_, guid);
492 bool is_profile = !is_credit_card &&
493 FindByGUID<AutofillProfile>(web_profiles_, guid);
494 if (!is_credit_card && !is_profile)
495 return;
496
497 if (!database_.get())
498 return;
499
500 if (is_credit_card)
501 database_->RemoveCreditCard(guid);
502 else
503 database_->RemoveAutofillProfile(guid);
504
505 // Refresh our local cache and send notifications to observers.
506 Refresh();
507 }
508
GetCreditCardByGUID(const std::string & guid)509 CreditCard* PersonalDataManager::GetCreditCardByGUID(const std::string& guid) {
510 const std::vector<CreditCard*>& credit_cards = GetCreditCards();
511 std::vector<CreditCard*>::const_iterator iter =
512 FindElementByGUID<CreditCard>(credit_cards, guid);
513 return (iter != credit_cards.end()) ? *iter : NULL;
514 }
515
GetNonEmptyTypes(ServerFieldTypeSet * non_empty_types)516 void PersonalDataManager::GetNonEmptyTypes(
517 ServerFieldTypeSet* non_empty_types) {
518 const std::vector<AutofillProfile*>& profiles = GetProfiles();
519 for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin();
520 iter != profiles.end(); ++iter) {
521 (*iter)->GetNonEmptyTypes(app_locale_, non_empty_types);
522 }
523
524 for (ScopedVector<CreditCard>::const_iterator iter = credit_cards_.begin();
525 iter != credit_cards_.end(); ++iter) {
526 (*iter)->GetNonEmptyTypes(app_locale_, non_empty_types);
527 }
528 }
529
IsDataLoaded() const530 bool PersonalDataManager::IsDataLoaded() const {
531 return is_data_loaded_;
532 }
533
GetProfiles() const534 const std::vector<AutofillProfile*>& PersonalDataManager::GetProfiles() const {
535 return GetProfiles(false);
536 }
537
web_profiles() const538 const std::vector<AutofillProfile*>& PersonalDataManager::web_profiles() const {
539 return web_profiles_.get();
540 }
541
GetCreditCards() const542 const std::vector<CreditCard*>& PersonalDataManager::GetCreditCards() const {
543 return credit_cards_.get();
544 }
545
Refresh()546 void PersonalDataManager::Refresh() {
547 LoadProfiles();
548 LoadCreditCards();
549 }
550
GetProfileSuggestions(const AutofillType & type,const base::string16 & field_contents,bool field_is_autofilled,const std::vector<ServerFieldType> & other_field_types,const base::Callback<bool (const AutofillProfile &)> & filter,std::vector<base::string16> * values,std::vector<base::string16> * labels,std::vector<base::string16> * icons,std::vector<GUIDPair> * guid_pairs)551 void PersonalDataManager::GetProfileSuggestions(
552 const AutofillType& type,
553 const base::string16& field_contents,
554 bool field_is_autofilled,
555 const std::vector<ServerFieldType>& other_field_types,
556 const base::Callback<bool(const AutofillProfile&)>& filter,
557 std::vector<base::string16>* values,
558 std::vector<base::string16>* labels,
559 std::vector<base::string16>* icons,
560 std::vector<GUIDPair>* guid_pairs) {
561 values->clear();
562 labels->clear();
563 icons->clear();
564 guid_pairs->clear();
565
566 const std::vector<AutofillProfile*>& profiles = GetProfiles(true);
567 std::vector<AutofillProfile*> matched_profiles;
568 for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin();
569 iter != profiles.end(); ++iter) {
570 AutofillProfile* profile = *iter;
571
572 // The value of the stored data for this field type in the |profile|.
573 std::vector<base::string16> multi_values;
574 AddressField address_field;
575 if (i18n::FieldForType(type.GetStorableType(), &address_field) &&
576 address_field == STREET_ADDRESS) {
577 std::string street_address_line;
578 GetStreetAddressLinesAsSingleLine(
579 *i18n::CreateAddressDataFromAutofillProfile(*profile, app_locale_),
580 &street_address_line);
581 multi_values.push_back(base::UTF8ToUTF16(street_address_line));
582 } else {
583 profile->GetMultiInfo(type, app_locale_, &multi_values);
584 }
585
586 for (size_t i = 0; i < multi_values.size(); ++i) {
587 // Newlines can be found only in a street address, which was collapsed
588 // into a single line above.
589 DCHECK(multi_values[i].find('\n') == std::string::npos);
590
591 if (!field_is_autofilled) {
592 // Suggest data that starts with what the user has typed.
593 if (!multi_values[i].empty() &&
594 StartsWith(multi_values[i], field_contents, false) &&
595 (filter.is_null() || filter.Run(*profile))) {
596 matched_profiles.push_back(profile);
597 values->push_back(multi_values[i]);
598 guid_pairs->push_back(GUIDPair(profile->guid(), i));
599 }
600 } else {
601 if (multi_values[i].empty())
602 continue;
603
604 base::string16 profile_value_lower_case(
605 base::StringToLowerASCII(multi_values[i]));
606 base::string16 field_value_lower_case(
607 base::StringToLowerASCII(field_contents));
608 // Phone numbers could be split in US forms, so field value could be
609 // either prefix or suffix of the phone.
610 bool matched_phones = false;
611 if (type.GetStorableType() == PHONE_HOME_NUMBER &&
612 !field_value_lower_case.empty() &&
613 profile_value_lower_case.find(field_value_lower_case) !=
614 base::string16::npos) {
615 matched_phones = true;
616 }
617
618 // Suggest variants of the profile that's already been filled in.
619 if (matched_phones ||
620 profile_value_lower_case == field_value_lower_case) {
621 for (size_t j = 0; j < multi_values.size(); ++j) {
622 if (!multi_values[j].empty()) {
623 values->push_back(multi_values[j]);
624 guid_pairs->push_back(GUIDPair(profile->guid(), j));
625 }
626 }
627
628 // We've added all the values for this profile so move on to the
629 // next.
630 break;
631 }
632 }
633 }
634 }
635
636 if (!field_is_autofilled) {
637 AutofillProfile::CreateInferredLabels(
638 matched_profiles, &other_field_types,
639 type.GetStorableType(), 1, app_locale_, labels);
640 } else {
641 // No sub-labels for previously filled fields.
642 labels->resize(values->size());
643 }
644
645 // No icons for profile suggestions.
646 icons->resize(values->size());
647 }
648
GetCreditCardSuggestions(const AutofillType & type,const base::string16 & field_contents,std::vector<base::string16> * values,std::vector<base::string16> * labels,std::vector<base::string16> * icons,std::vector<GUIDPair> * guid_pairs)649 void PersonalDataManager::GetCreditCardSuggestions(
650 const AutofillType& type,
651 const base::string16& field_contents,
652 std::vector<base::string16>* values,
653 std::vector<base::string16>* labels,
654 std::vector<base::string16>* icons,
655 std::vector<GUIDPair>* guid_pairs) {
656 values->clear();
657 labels->clear();
658 icons->clear();
659 guid_pairs->clear();
660
661 const std::vector<CreditCard*>& credit_cards = GetCreditCards();
662 for (std::vector<CreditCard*>::const_iterator iter = credit_cards.begin();
663 iter != credit_cards.end(); ++iter) {
664 CreditCard* credit_card = *iter;
665
666 // The value of the stored data for this field type in the |credit_card|.
667 base::string16 creditcard_field_value =
668 credit_card->GetInfo(type, app_locale_);
669 if (!creditcard_field_value.empty() &&
670 StartsWith(creditcard_field_value, field_contents, false)) {
671 if (type.GetStorableType() == CREDIT_CARD_NUMBER)
672 creditcard_field_value = credit_card->ObfuscatedNumber();
673
674 // If the value is the card number, the label is the expiration date.
675 // Otherwise the label is the card number, or if that is empty the
676 // cardholder name. The label should never repeat the value.
677 base::string16 label;
678 if (type.GetStorableType() == CREDIT_CARD_NUMBER) {
679 label = credit_card->GetInfo(
680 AutofillType(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR), app_locale_);
681 } else if (credit_card->number().empty()) {
682 if (type.GetStorableType() != CREDIT_CARD_NAME) {
683 label =
684 credit_card->GetInfo(AutofillType(CREDIT_CARD_NAME), app_locale_);
685 }
686 } else {
687 label = kCreditCardPrefix;
688 label.append(credit_card->LastFourDigits());
689 }
690
691 values->push_back(creditcard_field_value);
692 labels->push_back(label);
693 icons->push_back(base::UTF8ToUTF16(credit_card->type()));
694 guid_pairs->push_back(GUIDPair(credit_card->guid(), 0));
695 }
696 }
697 }
698
IsAutofillEnabled() const699 bool PersonalDataManager::IsAutofillEnabled() const {
700 DCHECK(pref_service_);
701 return pref_service_->GetBoolean(prefs::kAutofillEnabled);
702 }
703
CountryCodeForCurrentTimezone() const704 std::string PersonalDataManager::CountryCodeForCurrentTimezone() const {
705 return base::CountryCodeForCurrentTimezone();
706 }
707
SetPrefService(PrefService * pref_service)708 void PersonalDataManager::SetPrefService(PrefService* pref_service) {
709 enabled_pref_.reset(new BooleanPrefMember);
710 pref_service_ = pref_service;
711 // |pref_service_| can be NULL in tests.
712 if (pref_service_) {
713 enabled_pref_->Init(prefs::kAutofillEnabled, pref_service_,
714 base::Bind(&PersonalDataManager::EnabledPrefChanged,
715 base::Unretained(this)));
716 }
717 }
718
719 // static
IsValidLearnableProfile(const AutofillProfile & profile,const std::string & app_locale)720 bool PersonalDataManager::IsValidLearnableProfile(
721 const AutofillProfile& profile,
722 const std::string& app_locale) {
723 if (!IsMinimumAddress(profile, app_locale))
724 return false;
725
726 base::string16 email = profile.GetRawInfo(EMAIL_ADDRESS);
727 if (!email.empty() && !IsValidEmailAddress(email))
728 return false;
729
730 // Reject profiles with invalid US state information.
731 if (profile.IsPresentButInvalid(ADDRESS_HOME_STATE))
732 return false;
733
734 // Reject profiles with invalid US zip information.
735 if (profile.IsPresentButInvalid(ADDRESS_HOME_ZIP))
736 return false;
737
738 return true;
739 }
740
741 // static
MergeProfile(const AutofillProfile & new_profile,const std::vector<AutofillProfile * > & existing_profiles,const std::string & app_locale,std::vector<AutofillProfile> * merged_profiles)742 std::string PersonalDataManager::MergeProfile(
743 const AutofillProfile& new_profile,
744 const std::vector<AutofillProfile*>& existing_profiles,
745 const std::string& app_locale,
746 std::vector<AutofillProfile>* merged_profiles) {
747 merged_profiles->clear();
748
749 // Set to true if |existing_profiles| already contains an equivalent profile.
750 bool matching_profile_found = false;
751 std::string guid = new_profile.guid();
752
753 // If we have already saved this address, merge in any missing values.
754 // Only merge with the first match.
755 for (std::vector<AutofillProfile*>::const_iterator iter =
756 existing_profiles.begin();
757 iter != existing_profiles.end(); ++iter) {
758 AutofillProfile* existing_profile = *iter;
759 if (!matching_profile_found &&
760 !new_profile.PrimaryValue().empty() &&
761 base::StringToLowerASCII(existing_profile->PrimaryValue()) ==
762 base::StringToLowerASCII(new_profile.PrimaryValue())) {
763 // Unverified profiles should always be updated with the newer data,
764 // whereas verified profiles should only ever be overwritten by verified
765 // data. If an automatically aggregated profile would overwrite a
766 // verified profile, just drop it.
767 matching_profile_found = true;
768 guid = existing_profile->guid();
769 if (!existing_profile->IsVerified() || new_profile.IsVerified())
770 existing_profile->OverwriteWithOrAddTo(new_profile, app_locale);
771 }
772 merged_profiles->push_back(*existing_profile);
773 }
774
775 // If the new profile was not merged with an existing one, add it to the list.
776 if (!matching_profile_found)
777 merged_profiles->push_back(new_profile);
778
779 return guid;
780 }
781
IsCountryOfInterest(const std::string & country_code) const782 bool PersonalDataManager::IsCountryOfInterest(const std::string& country_code)
783 const {
784 DCHECK_EQ(2U, country_code.size());
785
786 const std::vector<AutofillProfile*>& profiles = web_profiles();
787 std::list<std::string> country_codes;
788 for (size_t i = 0; i < profiles.size(); ++i) {
789 country_codes.push_back(base::StringToLowerASCII(base::UTF16ToASCII(
790 profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY))));
791 }
792
793 std::string timezone_country = CountryCodeForCurrentTimezone();
794 if (!timezone_country.empty())
795 country_codes.push_back(base::StringToLowerASCII(timezone_country));
796
797 // Only take the locale into consideration if all else fails.
798 if (country_codes.empty()) {
799 country_codes.push_back(base::StringToLowerASCII(
800 AutofillCountry::CountryCodeForLocale(app_locale())));
801 }
802
803 return std::find(country_codes.begin(), country_codes.end(),
804 base::StringToLowerASCII(country_code)) !=
805 country_codes.end();
806 }
807
GetDefaultCountryCodeForNewAddress() const808 const std::string& PersonalDataManager::GetDefaultCountryCodeForNewAddress()
809 const {
810 if (default_country_code_.empty())
811 default_country_code_ = MostCommonCountryCodeFromProfiles();
812
813 // Failing that, guess based on system timezone.
814 if (default_country_code_.empty())
815 default_country_code_ = CountryCodeForCurrentTimezone();
816
817 // Failing that, guess based on locale.
818 if (default_country_code_.empty())
819 default_country_code_ = AutofillCountry::CountryCodeForLocale(app_locale());
820
821 return default_country_code_;
822 }
823
SetProfiles(std::vector<AutofillProfile> * profiles)824 void PersonalDataManager::SetProfiles(std::vector<AutofillProfile>* profiles) {
825 if (is_off_the_record_)
826 return;
827
828 // Remove empty profiles from input.
829 profiles->erase(std::remove_if(profiles->begin(), profiles->end(),
830 IsEmptyFunctor<AutofillProfile>(app_locale_)),
831 profiles->end());
832
833 if (!database_.get())
834 return;
835
836 // Any profiles that are not in the new profile list should be removed from
837 // the web database.
838 for (std::vector<AutofillProfile*>::const_iterator iter =
839 web_profiles_.begin();
840 iter != web_profiles_.end(); ++iter) {
841 if (!FindByGUID<AutofillProfile>(*profiles, (*iter)->guid()))
842 database_->RemoveAutofillProfile((*iter)->guid());
843 }
844
845 // Update the web database with the existing profiles.
846 for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
847 iter != profiles->end(); ++iter) {
848 if (FindByGUID<AutofillProfile>(web_profiles_, iter->guid()))
849 database_->UpdateAutofillProfile(*iter);
850 }
851
852 // Add the new profiles to the web database. Don't add a duplicate.
853 for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
854 iter != profiles->end(); ++iter) {
855 if (!FindByGUID<AutofillProfile>(web_profiles_, iter->guid()) &&
856 !FindByContents(web_profiles_, *iter))
857 database_->AddAutofillProfile(*iter);
858 }
859
860 // Copy in the new profiles.
861 web_profiles_.clear();
862 for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
863 iter != profiles->end(); ++iter) {
864 web_profiles_.push_back(new AutofillProfile(*iter));
865 }
866
867 // Refresh our local cache and send notifications to observers.
868 Refresh();
869 }
870
SetCreditCards(std::vector<CreditCard> * credit_cards)871 void PersonalDataManager::SetCreditCards(
872 std::vector<CreditCard>* credit_cards) {
873 if (is_off_the_record_)
874 return;
875
876 // Remove empty credit cards from input.
877 credit_cards->erase(std::remove_if(credit_cards->begin(), credit_cards->end(),
878 IsEmptyFunctor<CreditCard>(app_locale_)),
879 credit_cards->end());
880
881 if (!database_.get())
882 return;
883
884 // Any credit cards that are not in the new credit card list should be
885 // removed.
886 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin();
887 iter != credit_cards_.end(); ++iter) {
888 if (!FindByGUID<CreditCard>(*credit_cards, (*iter)->guid()))
889 database_->RemoveCreditCard((*iter)->guid());
890 }
891
892 // Update the web database with the existing credit cards.
893 for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
894 iter != credit_cards->end(); ++iter) {
895 if (FindByGUID<CreditCard>(credit_cards_, iter->guid()))
896 database_->UpdateCreditCard(*iter);
897 }
898
899 // Add the new credit cards to the web database. Don't add a duplicate.
900 for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
901 iter != credit_cards->end(); ++iter) {
902 if (!FindByGUID<CreditCard>(credit_cards_, iter->guid()) &&
903 !FindByContents(credit_cards_, *iter))
904 database_->AddCreditCard(*iter);
905 }
906
907 // Copy in the new credit cards.
908 credit_cards_.clear();
909 for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
910 iter != credit_cards->end(); ++iter) {
911 credit_cards_.push_back(new CreditCard(*iter));
912 }
913
914 // Refresh our local cache and send notifications to observers.
915 Refresh();
916 }
917
LoadProfiles()918 void PersonalDataManager::LoadProfiles() {
919 if (!database_.get()) {
920 NOTREACHED();
921 return;
922 }
923
924 CancelPendingQuery(&pending_profiles_query_);
925
926 pending_profiles_query_ = database_->GetAutofillProfiles(this);
927 }
928
929 // Win, Linux, Android and iOS implementations do nothing. Mac implementation
930 // fills in the contents of |auxiliary_profiles_|.
931 #if defined(OS_IOS) || !defined(OS_MACOSX)
LoadAuxiliaryProfiles(bool record_metrics) const932 void PersonalDataManager::LoadAuxiliaryProfiles(bool record_metrics) const {
933 }
934 #endif
935
LoadCreditCards()936 void PersonalDataManager::LoadCreditCards() {
937 if (!database_.get()) {
938 NOTREACHED();
939 return;
940 }
941
942 CancelPendingQuery(&pending_creditcards_query_);
943
944 pending_creditcards_query_ = database_->GetCreditCards(this);
945 }
946
ReceiveLoadedProfiles(WebDataServiceBase::Handle h,const WDTypedResult * result)947 void PersonalDataManager::ReceiveLoadedProfiles(WebDataServiceBase::Handle h,
948 const WDTypedResult* result) {
949 DCHECK_EQ(pending_profiles_query_, h);
950
951 pending_profiles_query_ = 0;
952 web_profiles_.clear();
953
954 const WDResult<std::vector<AutofillProfile*> >* r =
955 static_cast<const WDResult<std::vector<AutofillProfile*> >*>(result);
956
957 std::vector<AutofillProfile*> profiles = r->GetValue();
958 for (std::vector<AutofillProfile*>::iterator iter = profiles.begin();
959 iter != profiles.end(); ++iter) {
960 web_profiles_.push_back(*iter);
961 }
962
963 LogProfileCount();
964 }
965
ReceiveLoadedCreditCards(WebDataServiceBase::Handle h,const WDTypedResult * result)966 void PersonalDataManager::ReceiveLoadedCreditCards(
967 WebDataServiceBase::Handle h, const WDTypedResult* result) {
968 DCHECK_EQ(pending_creditcards_query_, h);
969
970 pending_creditcards_query_ = 0;
971 credit_cards_.clear();
972
973 const WDResult<std::vector<CreditCard*> >* r =
974 static_cast<const WDResult<std::vector<CreditCard*> >*>(result);
975
976 std::vector<CreditCard*> credit_cards = r->GetValue();
977 for (std::vector<CreditCard*>::iterator iter = credit_cards.begin();
978 iter != credit_cards.end(); ++iter) {
979 credit_cards_.push_back(*iter);
980 }
981 }
982
CancelPendingQuery(WebDataServiceBase::Handle * handle)983 void PersonalDataManager::CancelPendingQuery(
984 WebDataServiceBase::Handle* handle) {
985 if (*handle) {
986 if (!database_.get()) {
987 NOTREACHED();
988 return;
989 }
990 database_->CancelRequest(*handle);
991 }
992 *handle = 0;
993 }
994
SaveImportedProfile(const AutofillProfile & imported_profile)995 std::string PersonalDataManager::SaveImportedProfile(
996 const AutofillProfile& imported_profile) {
997 if (is_off_the_record_)
998 return std::string();
999
1000 // Don't save a web profile if the data in the profile is a subset of an
1001 // auxiliary profile.
1002 for (std::vector<AutofillProfile*>::const_iterator iter =
1003 auxiliary_profiles_.begin();
1004 iter != auxiliary_profiles_.end(); ++iter) {
1005 if (imported_profile.IsSubsetOf(**iter, app_locale_))
1006 return (*iter)->guid();
1007 }
1008
1009 std::vector<AutofillProfile> profiles;
1010 std::string guid =
1011 MergeProfile(imported_profile, web_profiles_.get(), app_locale_,
1012 &profiles);
1013 SetProfiles(&profiles);
1014 return guid;
1015 }
1016
NotifyPersonalDataChanged()1017 void PersonalDataManager::NotifyPersonalDataChanged() {
1018 FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_,
1019 OnPersonalDataChanged());
1020 }
1021
SaveImportedCreditCard(const CreditCard & imported_card)1022 std::string PersonalDataManager::SaveImportedCreditCard(
1023 const CreditCard& imported_card) {
1024 DCHECK(!imported_card.number().empty());
1025 if (is_off_the_record_)
1026 return std::string();
1027
1028 // Set to true if |imported_card| is merged into the credit card list.
1029 bool merged = false;
1030
1031 std::string guid = imported_card.guid();
1032 std::vector<CreditCard> credit_cards;
1033 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin();
1034 iter != credit_cards_.end();
1035 ++iter) {
1036 CreditCard* card = *iter;
1037 // If |imported_card| has not yet been merged, check whether it should be
1038 // with the current |card|.
1039 if (!merged && card->UpdateFromImportedCard(imported_card, app_locale_)) {
1040 guid = card->guid();
1041 merged = true;
1042 }
1043
1044 credit_cards.push_back(*card);
1045 }
1046
1047 if (!merged)
1048 credit_cards.push_back(imported_card);
1049
1050 SetCreditCards(&credit_cards);
1051 return guid;
1052 }
1053
LogProfileCount() const1054 void PersonalDataManager::LogProfileCount() const {
1055 if (!has_logged_profile_count_) {
1056 metric_logger_->LogStoredProfileCount(web_profiles_.size());
1057 has_logged_profile_count_ = true;
1058 }
1059 }
1060
MostCommonCountryCodeFromProfiles() const1061 std::string PersonalDataManager::MostCommonCountryCodeFromProfiles() const {
1062 if (!IsAutofillEnabled())
1063 return std::string();
1064
1065 // Count up country codes from existing profiles.
1066 std::map<std::string, int> votes;
1067 // TODO(estade): can we make this GetProfiles() instead? It seems to cause
1068 // errors in tests on mac trybots. See http://crbug.com/57221
1069 const std::vector<AutofillProfile*>& profiles = web_profiles();
1070 std::vector<std::string> country_codes;
1071 AutofillCountry::GetAvailableCountries(&country_codes);
1072 for (size_t i = 0; i < profiles.size(); ++i) {
1073 std::string country_code = StringToUpperASCII(base::UTF16ToASCII(
1074 profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY)));
1075
1076 if (std::find(country_codes.begin(), country_codes.end(), country_code) !=
1077 country_codes.end()) {
1078 // Verified profiles count 100x more than unverified ones.
1079 votes[country_code] += profiles[i]->IsVerified() ? 100 : 1;
1080 }
1081 }
1082
1083 // Take the most common country code.
1084 if (!votes.empty()) {
1085 std::map<std::string, int>::iterator iter =
1086 std::max_element(votes.begin(), votes.end(), CompareVotes);
1087 return iter->first;
1088 }
1089
1090 return std::string();
1091 }
1092
EnabledPrefChanged()1093 void PersonalDataManager::EnabledPrefChanged() {
1094 default_country_code_.clear();
1095 NotifyPersonalDataChanged();
1096 }
1097
GetProfiles(bool record_metrics) const1098 const std::vector<AutofillProfile*>& PersonalDataManager::GetProfiles(
1099 bool record_metrics) const {
1100 #if defined(OS_MACOSX) && !defined(OS_IOS)
1101 if (!pref_service_->GetBoolean(prefs::kAutofillUseMacAddressBook))
1102 return web_profiles();
1103 #else
1104 if (!pref_service_->GetBoolean(prefs::kAutofillAuxiliaryProfilesEnabled))
1105 return web_profiles();
1106 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
1107
1108 profiles_.clear();
1109
1110 // Populates |auxiliary_profiles_|.
1111 LoadAuxiliaryProfiles(record_metrics);
1112
1113 profiles_.insert(profiles_.end(), web_profiles_.begin(), web_profiles_.end());
1114 profiles_.insert(
1115 profiles_.end(), auxiliary_profiles_.begin(), auxiliary_profiles_.end());
1116 return profiles_;
1117 }
1118
1119 } // namespace autofill
1120