• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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