Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(368)

Side by Side Diff: components/autofill/browser/personal_data_manager.cc

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

Powered by Google App Engine
This is Rietveld 408576698