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