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

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

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

Powered by Google App Engine
This is Rietveld 408576698