blob: 9ddff255d5d02a45fe313608f00bb692857541bf [file] [log] [blame]
Ben Murdocheb525c52013-07-10 11:40:50 +01001// 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/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/core/browser/autofill-inl.h"
18#include "components/autofill/core/browser/autofill_country.h"
19#include "components/autofill/core/browser/autofill_field.h"
20#include "components/autofill/core/browser/autofill_metrics.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/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
31using content::BrowserContext;
32
33namespace autofill {
34namespace {
35
36const base::string16::value_type kCreditCardPrefix[] = {'*', 0};
37
38template<typename T>
39class 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
57template<typename T, typename C>
58bool 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
65template<typename T>
66class DereferenceFunctor {
67 public:
68 template<typename T_Iterator>
69 const T& operator()(const T_Iterator& iterator) {
70 return *iterator;
71 }
72};
73
74template<typename T>
75T* 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.
84bool 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.
Ben Murdoch32409262013-08-07 11:04:47 +0100112bool IsValidFieldTypeAndValue(const std::set<ServerFieldType>& types_seen,
113 ServerFieldType field_type,
Ben Murdocheb525c52013-07-10 11:40:50 +0100114 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.
Ben Murdoch32409262013-08-07 11:04:47 +0100120 if (types_seen.count(field_type) &&
121 field_type != PHONE_HOME_NUMBER &&
Ben Murdocheb525c52013-07-10 11:40:50 +0100122 field_type != EMAIL_ADDRESS)
123 return false;
124
125 // Abandon the import if an email address value shows up in a field that is
126 // not an email address.
Ben Murdoch32409262013-08-07 11:04:47 +0100127 if (field_type != EMAIL_ADDRESS && IsValidEmailAddress(value))
Ben Murdocheb525c52013-07-10 11:40:50 +0100128 return false;
129
130 return true;
131}
132
133} // namespace
134
135PersonalDataManager::PersonalDataManager(const std::string& app_locale)
136 : browser_context_(NULL),
137 is_data_loaded_(false),
138 pending_profiles_query_(0),
139 pending_creditcards_query_(0),
140 app_locale_(app_locale),
141 metric_logger_(new AutofillMetrics),
142 has_logged_profile_count_(false) {}
143
144void PersonalDataManager::Init(BrowserContext* browser_context) {
145 browser_context_ = browser_context;
146
147 if (!browser_context_->IsOffTheRecord())
148 metric_logger_->LogIsAutofillEnabledAtStartup(IsAutofillEnabled());
149
150 scoped_refptr<AutofillWebDataService> autofill_data(
151 AutofillWebDataService::FromBrowserContext(browser_context_));
152
153 // WebDataService may not be available in tests.
154 if (!autofill_data.get())
155 return;
156
157 LoadProfiles();
158 LoadCreditCards();
159
160 autofill_data->AddObserver(this);
161}
162
163PersonalDataManager::~PersonalDataManager() {
164 CancelPendingQuery(&pending_profiles_query_);
165 CancelPendingQuery(&pending_creditcards_query_);
166
167 if (!browser_context_)
168 return;
169
170 scoped_refptr<AutofillWebDataService> autofill_data(
171 AutofillWebDataService::FromBrowserContext(browser_context_));
172 if (autofill_data.get())
173 autofill_data->RemoveObserver(this);
174}
175
176void PersonalDataManager::OnWebDataServiceRequestDone(
177 WebDataServiceBase::Handle h,
178 const WDTypedResult* result) {
179 DCHECK(pending_profiles_query_ || pending_creditcards_query_);
180
181 if (!result) {
182 // Error from the web database.
183 if (h == pending_creditcards_query_)
184 pending_creditcards_query_ = 0;
185 else if (h == pending_profiles_query_)
186 pending_profiles_query_ = 0;
187 return;
188 }
189
190 DCHECK(result->GetType() == AUTOFILL_PROFILES_RESULT ||
191 result->GetType() == AUTOFILL_CREDITCARDS_RESULT);
192
193 switch (result->GetType()) {
194 case AUTOFILL_PROFILES_RESULT:
195 ReceiveLoadedProfiles(h, result);
196 break;
197 case AUTOFILL_CREDITCARDS_RESULT:
198 ReceiveLoadedCreditCards(h, result);
199 break;
200 default:
201 NOTREACHED();
202 }
203
204 // If both requests have responded, then all personal data is loaded.
205 if (pending_profiles_query_ == 0 && pending_creditcards_query_ == 0) {
206 is_data_loaded_ = true;
207 std::vector<AutofillProfile*> profile_pointers(web_profiles_.size());
208 std::copy(web_profiles_.begin(), web_profiles_.end(),
209 profile_pointers.begin());
210 AutofillProfile::AdjustInferredLabels(&profile_pointers);
211 FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_,
212 OnPersonalDataChanged());
213 }
214}
215
216void PersonalDataManager::AutofillMultipleChanged() {
217 Refresh();
218}
219
220void PersonalDataManager::AddObserver(PersonalDataManagerObserver* observer) {
221 observers_.AddObserver(observer);
222}
223
224void PersonalDataManager::RemoveObserver(
225 PersonalDataManagerObserver* observer) {
226 observers_.RemoveObserver(observer);
227}
228
229bool PersonalDataManager::ImportFormData(
230 const FormStructure& form,
231 const CreditCard** imported_credit_card) {
232 scoped_ptr<AutofillProfile> imported_profile(new AutofillProfile);
233 scoped_ptr<CreditCard> local_imported_credit_card(new CreditCard);
234
235 const std::string origin = form.source_url().spec();
236 imported_profile->set_origin(origin);
237 local_imported_credit_card->set_origin(origin);
238
239 // Parse the form and construct a profile based on the information that is
240 // possible to import.
241 int importable_credit_card_fields = 0;
242
243 // Detect and discard forms with multiple fields of the same type.
Ben Murdoch32409262013-08-07 11:04:47 +0100244 // TODO(isherman): Some types are overlapping but not equal, e.g. phone number
245 // parts, address parts.
246 std::set<ServerFieldType> types_seen;
Ben Murdocheb525c52013-07-10 11:40:50 +0100247
248 // We only set complete phone, so aggregate phone parts in these vars and set
249 // complete at the end.
250 PhoneNumber::PhoneCombineHelper home;
251
252 for (size_t i = 0; i < form.field_count(); ++i) {
253 const AutofillField* field = form.field(i);
254 base::string16 value = CollapseWhitespace(field->value, false);
255
256 // If we don't know the type of the field, or the user hasn't entered any
257 // information into the field, then skip it.
258 if (!field->IsFieldFillable() || value.empty())
259 continue;
260
Ben Murdoch32409262013-08-07 11:04:47 +0100261 AutofillType field_type = field->Type();
Ben Murdochbb1529c2013-08-08 10:24:53 +0100262 ServerFieldType server_field_type = field_type.GetStorableType();
Ben Murdoch32409262013-08-07 11:04:47 +0100263 FieldTypeGroup group(field_type.group());
Ben Murdocheb525c52013-07-10 11:40:50 +0100264
265 // There can be multiple email fields (e.g. in the case of 'confirm email'
266 // fields) but they must all contain the same value, else the profile is
267 // invalid.
Ben Murdoch32409262013-08-07 11:04:47 +0100268 if (server_field_type == EMAIL_ADDRESS) {
269 if (types_seen.count(server_field_type) &&
270 imported_profile->GetRawInfo(EMAIL_ADDRESS) != value) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100271 imported_profile.reset();
272 break;
273 }
274 }
275
276 // If the |field_type| and |value| don't pass basic validity checks then
277 // abandon the import.
Ben Murdoch32409262013-08-07 11:04:47 +0100278 if (!IsValidFieldTypeAndValue(types_seen, server_field_type, value)) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100279 imported_profile.reset();
280 local_imported_credit_card.reset();
281 break;
282 }
283
Ben Murdoch32409262013-08-07 11:04:47 +0100284 types_seen.insert(server_field_type);
Ben Murdocheb525c52013-07-10 11:40:50 +0100285
Ben Murdoch2385ea32013-08-06 11:01:04 +0100286 if (group == CREDIT_CARD) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100287 if (LowerCaseEqualsASCII(field->form_control_type, "month")) {
Ben Murdoch32409262013-08-07 11:04:47 +0100288 DCHECK_EQ(CREDIT_CARD_EXP_MONTH, server_field_type);
Ben Murdocheb525c52013-07-10 11:40:50 +0100289 local_imported_credit_card->SetInfoForMonthInputType(value);
290 } else {
291 local_imported_credit_card->SetInfo(field_type, value, app_locale_);
292 }
293 ++importable_credit_card_fields;
294 } else {
295 // We need to store phone data in the variables, before building the whole
296 // number at the end. The rest of the fields are set "as is".
297 // If the fields are not the phone fields in question home.SetInfo() is
298 // going to return false.
299 if (!home.SetInfo(field_type, value))
300 imported_profile->SetInfo(field_type, value, app_locale_);
301
302 // Reject profiles with invalid country information.
Ben Murdoch32409262013-08-07 11:04:47 +0100303 if (server_field_type == ADDRESS_HOME_COUNTRY &&
Ben Murdocheb525c52013-07-10 11:40:50 +0100304 !value.empty() &&
305 imported_profile->GetRawInfo(ADDRESS_HOME_COUNTRY).empty()) {
306 imported_profile.reset();
307 break;
308 }
309 }
310 }
311
312 // Construct the phone number. Reject the profile if the number is invalid.
313 if (imported_profile.get() && !home.IsEmpty()) {
314 base::string16 constructed_number;
315 if (!home.ParseNumber(*imported_profile, app_locale_,
316 &constructed_number) ||
Ben Murdoch32409262013-08-07 11:04:47 +0100317 !imported_profile->SetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER),
318 constructed_number,
Ben Murdocheb525c52013-07-10 11:40:50 +0100319 app_locale_)) {
320 imported_profile.reset();
321 }
322 }
323
324 // Reject the profile if minimum address and validation requirements are not
325 // met.
326 if (imported_profile.get() &&
327 !IsValidLearnableProfile(*imported_profile, app_locale_))
328 imported_profile.reset();
329
330 // Reject the credit card if we did not detect enough filled credit card
331 // fields or if the credit card number does not seem to be valid.
332 if (local_imported_credit_card.get() &&
333 !local_imported_credit_card->IsComplete()) {
334 local_imported_credit_card.reset();
335 }
336
337 // Don't import if we already have this info.
338 // Don't present an infobar if we have already saved this card number.
339 bool merged_credit_card = false;
340 if (local_imported_credit_card.get()) {
341 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin();
342 iter != credit_cards_.end();
343 ++iter) {
344 // Make a local copy so that the data in |credit_cards_| isn't modified
345 // directly by the UpdateFromImportedCard() call.
346 CreditCard card = **iter;
347 if (card.UpdateFromImportedCard(*local_imported_credit_card.get(),
348 app_locale_)) {
349 merged_credit_card = true;
350 UpdateCreditCard(card);
351 local_imported_credit_card.reset();
352 break;
353 }
354 }
355 }
356
357 if (imported_profile.get()) {
358 // We always save imported profiles.
359 SaveImportedProfile(*imported_profile);
360 }
361 *imported_credit_card = local_imported_credit_card.release();
362
363 if (imported_profile.get() || *imported_credit_card || merged_credit_card) {
364 return true;
365 } else {
366 FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_,
367 OnInsufficientFormData());
368 return false;
369 }
370}
371
372void PersonalDataManager::AddProfile(const AutofillProfile& profile) {
373 if (browser_context_->IsOffTheRecord())
374 return;
375
376 if (profile.IsEmpty(app_locale_))
377 return;
378
379 // Don't add an existing profile.
380 if (FindByGUID<AutofillProfile>(web_profiles_, profile.guid()))
381 return;
382
383 scoped_refptr<AutofillWebDataService> autofill_data(
384 AutofillWebDataService::FromBrowserContext(browser_context_));
385 if (!autofill_data.get())
386 return;
387
388 // Don't add a duplicate.
389 if (FindByContents(web_profiles_, profile))
390 return;
391
392 // Add the new profile to the web database.
393 autofill_data->AddAutofillProfile(profile);
394
395 // Refresh our local cache and send notifications to observers.
396 Refresh();
397}
398
399void PersonalDataManager::UpdateProfile(const AutofillProfile& profile) {
400 if (browser_context_->IsOffTheRecord())
401 return;
402
403 AutofillProfile* existing_profile = GetProfileByGUID(profile.guid());
404 if (!existing_profile)
405 return;
406
407 // Don't overwrite the origin for a profile that is already stored.
408 if (existing_profile->Compare(profile) == 0)
409 return;
410
411 if (profile.IsEmpty(app_locale_)) {
412 RemoveByGUID(profile.guid());
413 return;
414 }
415
416 scoped_refptr<AutofillWebDataService> autofill_data(
417 AutofillWebDataService::FromBrowserContext(browser_context_));
418 if (!autofill_data.get())
419 return;
420
421 // Make the update.
422 autofill_data->UpdateAutofillProfile(profile);
423
424 // Refresh our local cache and send notifications to observers.
425 Refresh();
426}
427
428AutofillProfile* PersonalDataManager::GetProfileByGUID(
429 const std::string& guid) {
430 const std::vector<AutofillProfile*>& profiles = GetProfiles();
431 for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin();
432 iter != profiles.end(); ++iter) {
433 if ((*iter)->guid() == guid)
434 return *iter;
435 }
436 return NULL;
437}
438
439void PersonalDataManager::AddCreditCard(const CreditCard& credit_card) {
440 if (browser_context_->IsOffTheRecord())
441 return;
442
443 if (credit_card.IsEmpty(app_locale_))
444 return;
445
446 if (FindByGUID<CreditCard>(credit_cards_, credit_card.guid()))
447 return;
448
449 scoped_refptr<AutofillWebDataService> autofill_data(
450 AutofillWebDataService::FromBrowserContext(browser_context_));
451 if (!autofill_data.get())
452 return;
453
454 // Don't add a duplicate.
455 if (FindByContents(credit_cards_, credit_card))
456 return;
457
458 // Add the new credit card to the web database.
459 autofill_data->AddCreditCard(credit_card);
460
461 // Refresh our local cache and send notifications to observers.
462 Refresh();
463}
464
465void PersonalDataManager::UpdateCreditCard(const CreditCard& credit_card) {
466 if (browser_context_->IsOffTheRecord())
467 return;
468
469 CreditCard* existing_credit_card = GetCreditCardByGUID(credit_card.guid());
470 if (!existing_credit_card)
471 return;
472
473 // Don't overwrite the origin for a credit card that is already stored.
474 if (existing_credit_card->Compare(credit_card) == 0)
475 return;
476
477 if (credit_card.IsEmpty(app_locale_)) {
478 RemoveByGUID(credit_card.guid());
479 return;
480 }
481
482 scoped_refptr<AutofillWebDataService> autofill_data(
483 AutofillWebDataService::FromBrowserContext(browser_context_));
484 if (!autofill_data.get())
485 return;
486
487 // Make the update.
488 autofill_data->UpdateCreditCard(credit_card);
489
490 // Refresh our local cache and send notifications to observers.
491 Refresh();
492}
493
494void PersonalDataManager::RemoveByGUID(const std::string& guid) {
495 if (browser_context_->IsOffTheRecord())
496 return;
497
498 bool is_credit_card = FindByGUID<CreditCard>(credit_cards_, guid);
499 bool is_profile = !is_credit_card &&
500 FindByGUID<AutofillProfile>(web_profiles_, guid);
501 if (!is_credit_card && !is_profile)
502 return;
503
504 scoped_refptr<AutofillWebDataService> autofill_data(
505 AutofillWebDataService::FromBrowserContext(browser_context_));
506 if (!autofill_data.get())
507 return;
508
509 if (is_credit_card)
510 autofill_data->RemoveCreditCard(guid);
511 else
512 autofill_data->RemoveAutofillProfile(guid);
513
514 // Refresh our local cache and send notifications to observers.
515 Refresh();
516}
517
518CreditCard* PersonalDataManager::GetCreditCardByGUID(const std::string& guid) {
519 const std::vector<CreditCard*>& credit_cards = GetCreditCards();
520 for (std::vector<CreditCard*>::const_iterator iter = credit_cards.begin();
521 iter != credit_cards.end(); ++iter) {
522 if ((*iter)->guid() == guid)
523 return *iter;
524 }
525 return NULL;
526}
527
528void PersonalDataManager::GetNonEmptyTypes(
Ben Murdoch32409262013-08-07 11:04:47 +0100529 ServerFieldTypeSet* non_empty_types) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100530 const std::vector<AutofillProfile*>& profiles = GetProfiles();
531 for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin();
532 iter != profiles.end(); ++iter) {
533 (*iter)->GetNonEmptyTypes(app_locale_, non_empty_types);
534 }
535
536 for (ScopedVector<CreditCard>::const_iterator iter = credit_cards_.begin();
537 iter != credit_cards_.end(); ++iter) {
538 (*iter)->GetNonEmptyTypes(app_locale_, non_empty_types);
539 }
540}
541
542bool PersonalDataManager::IsDataLoaded() const {
543 return is_data_loaded_;
544}
545
546const std::vector<AutofillProfile*>& PersonalDataManager::GetProfiles() {
547 if (!user_prefs::UserPrefs::Get(browser_context_)->GetBoolean(
548 prefs::kAutofillAuxiliaryProfilesEnabled)) {
549 return web_profiles();
550 }
551
552 profiles_.clear();
553
554 // Populates |auxiliary_profiles_|.
555 LoadAuxiliaryProfiles();
556
557 profiles_.insert(profiles_.end(), web_profiles_.begin(), web_profiles_.end());
558 profiles_.insert(profiles_.end(),
559 auxiliary_profiles_.begin(), auxiliary_profiles_.end());
560 return profiles_;
561}
562
563const std::vector<AutofillProfile*>& PersonalDataManager::web_profiles() const {
564 return web_profiles_.get();
565}
566
567const std::vector<CreditCard*>& PersonalDataManager::GetCreditCards() const {
568 return credit_cards_.get();
569}
570
571void PersonalDataManager::Refresh() {
572 LoadProfiles();
573 LoadCreditCards();
574}
575
576void PersonalDataManager::GetProfileSuggestions(
Ben Murdoch32409262013-08-07 11:04:47 +0100577 const AutofillType& type,
Ben Murdocheb525c52013-07-10 11:40:50 +0100578 const base::string16& field_contents,
579 bool field_is_autofilled,
Ben Murdoch32409262013-08-07 11:04:47 +0100580 std::vector<ServerFieldType> other_field_types,
Ben Murdocheb525c52013-07-10 11:40:50 +0100581 std::vector<base::string16>* values,
582 std::vector<base::string16>* labels,
583 std::vector<base::string16>* icons,
584 std::vector<GUIDPair>* guid_pairs) {
585 values->clear();
586 labels->clear();
587 icons->clear();
588 guid_pairs->clear();
589
590 const std::vector<AutofillProfile*>& profiles = GetProfiles();
591 std::vector<AutofillProfile*> matched_profiles;
592 for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin();
593 iter != profiles.end(); ++iter) {
594 AutofillProfile* profile = *iter;
595
596 // The value of the stored data for this field type in the |profile|.
597 std::vector<base::string16> multi_values;
598 profile->GetMultiInfo(type, app_locale_, &multi_values);
599
600 for (size_t i = 0; i < multi_values.size(); ++i) {
601 if (!field_is_autofilled) {
602 // Suggest data that starts with what the user has typed.
603 if (!multi_values[i].empty() &&
604 StartsWith(multi_values[i], field_contents, false)) {
605 matched_profiles.push_back(profile);
606 values->push_back(multi_values[i]);
607 guid_pairs->push_back(GUIDPair(profile->guid(), i));
608 }
609 } else {
610 if (multi_values[i].empty())
611 continue;
612
613 base::string16 profile_value_lower_case(
614 StringToLowerASCII(multi_values[i]));
615 base::string16 field_value_lower_case(
616 StringToLowerASCII(field_contents));
617 // Phone numbers could be split in US forms, so field value could be
618 // either prefix or suffix of the phone.
619 bool matched_phones = false;
Ben Murdochbb1529c2013-08-08 10:24:53 +0100620 if (type.GetStorableType() == PHONE_HOME_NUMBER &&
Ben Murdoch32409262013-08-07 11:04:47 +0100621 !field_value_lower_case.empty() &&
622 profile_value_lower_case.find(field_value_lower_case) !=
623 base::string16::npos) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100624 matched_phones = true;
625 }
626
627 // Suggest variants of the profile that's already been filled in.
628 if (matched_phones ||
629 profile_value_lower_case == field_value_lower_case) {
630 for (size_t j = 0; j < multi_values.size(); ++j) {
631 if (!multi_values[j].empty()) {
632 values->push_back(multi_values[j]);
633 guid_pairs->push_back(GUIDPair(profile->guid(), j));
634 }
635 }
636
637 // We've added all the values for this profile so move on to the
638 // next.
639 break;
640 }
641 }
642 }
643 }
644
645 if (!field_is_autofilled) {
646 AutofillProfile::CreateInferredLabels(
647 &matched_profiles, &other_field_types,
Ben Murdochbb1529c2013-08-08 10:24:53 +0100648 type.GetStorableType(), 1, labels);
Ben Murdocheb525c52013-07-10 11:40:50 +0100649 } else {
650 // No sub-labels for previously filled fields.
651 labels->resize(values->size());
652 }
653
654 // No icons for profile suggestions.
655 icons->resize(values->size());
656}
657
658void PersonalDataManager::GetCreditCardSuggestions(
Ben Murdoch32409262013-08-07 11:04:47 +0100659 const AutofillType& type,
Ben Murdocheb525c52013-07-10 11:40:50 +0100660 const base::string16& field_contents,
661 std::vector<base::string16>* values,
662 std::vector<base::string16>* labels,
663 std::vector<base::string16>* icons,
664 std::vector<GUIDPair>* guid_pairs) {
665 values->clear();
666 labels->clear();
667 icons->clear();
668 guid_pairs->clear();
669
670 const std::vector<CreditCard*>& credit_cards = GetCreditCards();
671 for (std::vector<CreditCard*>::const_iterator iter = credit_cards.begin();
672 iter != credit_cards.end(); ++iter) {
673 CreditCard* credit_card = *iter;
674
675 // The value of the stored data for this field type in the |credit_card|.
676 base::string16 creditcard_field_value =
677 credit_card->GetInfo(type, app_locale_);
678 if (!creditcard_field_value.empty() &&
679 StartsWith(creditcard_field_value, field_contents, false)) {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100680 if (type.GetStorableType() == CREDIT_CARD_NUMBER)
Ben Murdocheb525c52013-07-10 11:40:50 +0100681 creditcard_field_value = credit_card->ObfuscatedNumber();
682
683 base::string16 label;
684 if (credit_card->number().empty()) {
685 // If there is no CC number, return name to show something.
Ben Murdoch32409262013-08-07 11:04:47 +0100686 label =
687 credit_card->GetInfo(AutofillType(CREDIT_CARD_NAME), app_locale_);
Ben Murdocheb525c52013-07-10 11:40:50 +0100688 } else {
689 label = kCreditCardPrefix;
690 label.append(credit_card->LastFourDigits());
691 }
692
693 values->push_back(creditcard_field_value);
694 labels->push_back(label);
695 icons->push_back(UTF8ToUTF16(credit_card->type()));
696 guid_pairs->push_back(GUIDPair(credit_card->guid(), 0));
697 }
698 }
699}
700
701bool PersonalDataManager::IsAutofillEnabled() const {
702 return user_prefs::UserPrefs::Get(browser_context_)->GetBoolean(
703 prefs::kAutofillEnabled);
704}
705
706// static
707bool PersonalDataManager::IsValidLearnableProfile(
708 const AutofillProfile& profile,
709 const std::string& app_locale) {
710 if (!IsMinimumAddress(profile, app_locale))
711 return false;
712
713 base::string16 email = profile.GetRawInfo(EMAIL_ADDRESS);
Ben Murdoch32409262013-08-07 11:04:47 +0100714 if (!email.empty() && !IsValidEmailAddress(email))
Ben Murdocheb525c52013-07-10 11:40:50 +0100715 return false;
716
717 // Reject profiles with invalid US state information.
718 if (profile.IsPresentButInvalid(ADDRESS_HOME_STATE))
719 return false;
720
721 // Reject profiles with invalid US zip information.
722 if (profile.IsPresentButInvalid(ADDRESS_HOME_ZIP))
723 return false;
724
725 return true;
726}
727
728// static
729bool PersonalDataManager::MergeProfile(
730 const AutofillProfile& new_profile,
731 const std::vector<AutofillProfile*>& existing_profiles,
732 const std::string& app_locale,
733 std::vector<AutofillProfile>* merged_profiles) {
734 merged_profiles->clear();
735
736 // Set to true if |existing_profiles| already contains an equivalent profile.
737 bool matching_profile_found = false;
738
739 // If we have already saved this address, merge in any missing values.
740 // Only merge with the first match.
741 for (std::vector<AutofillProfile*>::const_iterator iter =
742 existing_profiles.begin();
743 iter != existing_profiles.end(); ++iter) {
744 AutofillProfile* existing_profile = *iter;
745 if (!matching_profile_found &&
746 !new_profile.PrimaryValue().empty() &&
747 StringToLowerASCII(existing_profile->PrimaryValue()) ==
748 StringToLowerASCII(new_profile.PrimaryValue())) {
749 // Unverified profiles should always be updated with the newer data,
750 // whereas verified profiles should only ever be overwritten by verified
751 // data. If an automatically aggregated profile would overwrite a
752 // verified profile, just drop it.
753 matching_profile_found = true;
754 if (!existing_profile->IsVerified() || new_profile.IsVerified())
755 existing_profile->OverwriteWithOrAddTo(new_profile, app_locale);
756 }
757 merged_profiles->push_back(*existing_profile);
758 }
759
760 // If the new profile was not merged with an existing one, add it to the list.
761 if (!matching_profile_found)
762 merged_profiles->push_back(new_profile);
763
764 return matching_profile_found;
765}
766
767void PersonalDataManager::SetProfiles(std::vector<AutofillProfile>* profiles) {
768 if (browser_context_->IsOffTheRecord())
769 return;
770
771 // Remove empty profiles from input.
772 for (std::vector<AutofillProfile>::iterator it = profiles->begin();
773 it != profiles->end();) {
774 if (it->IsEmpty(app_locale_))
775 profiles->erase(it);
776 else
777 it++;
778 }
779
780 // Ensure that profile labels are up to date. Currently, sync relies on
781 // labels to identify a profile.
782 // TODO(dhollowa): We need to deprecate labels and update the way sync
783 // identifies profiles.
784 std::vector<AutofillProfile*> profile_pointers(profiles->size());
785 std::transform(profiles->begin(), profiles->end(), profile_pointers.begin(),
786 address_of<AutofillProfile>);
787 AutofillProfile::AdjustInferredLabels(&profile_pointers);
788
789 scoped_refptr<AutofillWebDataService> autofill_data(
790 AutofillWebDataService::FromBrowserContext(browser_context_));
791 if (!autofill_data.get())
792 return;
793
794 // Any profiles that are not in the new profile list should be removed from
795 // the web database.
796 for (std::vector<AutofillProfile*>::const_iterator iter =
797 web_profiles_.begin();
798 iter != web_profiles_.end(); ++iter) {
799 if (!FindByGUID<AutofillProfile>(*profiles, (*iter)->guid()))
800 autofill_data->RemoveAutofillProfile((*iter)->guid());
801 }
802
803 // Update the web database with the existing profiles.
804 for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
805 iter != profiles->end(); ++iter) {
806 if (FindByGUID<AutofillProfile>(web_profiles_, iter->guid()))
807 autofill_data->UpdateAutofillProfile(*iter);
808 }
809
810 // Add the new profiles to the web database. Don't add a duplicate.
811 for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
812 iter != profiles->end(); ++iter) {
813 if (!FindByGUID<AutofillProfile>(web_profiles_, iter->guid()) &&
814 !FindByContents(web_profiles_, *iter))
815 autofill_data->AddAutofillProfile(*iter);
816 }
817
818 // Copy in the new profiles.
819 web_profiles_.clear();
820 for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
821 iter != profiles->end(); ++iter) {
822 web_profiles_.push_back(new AutofillProfile(*iter));
823 }
824
825 // Refresh our local cache and send notifications to observers.
826 Refresh();
827}
828
829void PersonalDataManager::SetCreditCards(
830 std::vector<CreditCard>* credit_cards) {
831 if (browser_context_->IsOffTheRecord())
832 return;
833
834 // Remove empty credit cards from input.
835 for (std::vector<CreditCard>::iterator it = credit_cards->begin();
836 it != credit_cards->end();) {
837 if (it->IsEmpty(app_locale_))
838 credit_cards->erase(it);
839 else
840 it++;
841 }
842
843 scoped_refptr<AutofillWebDataService> autofill_data(
844 AutofillWebDataService::FromBrowserContext(browser_context_));
845 if (!autofill_data.get())
846 return;
847
848 // Any credit cards that are not in the new credit card list should be
849 // removed.
850 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin();
851 iter != credit_cards_.end(); ++iter) {
852 if (!FindByGUID<CreditCard>(*credit_cards, (*iter)->guid()))
853 autofill_data->RemoveCreditCard((*iter)->guid());
854 }
855
856 // Update the web database with the existing credit cards.
857 for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
858 iter != credit_cards->end(); ++iter) {
859 if (FindByGUID<CreditCard>(credit_cards_, iter->guid()))
860 autofill_data->UpdateCreditCard(*iter);
861 }
862
863 // Add the new credit cards to the web database. Don't add a duplicate.
864 for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
865 iter != credit_cards->end(); ++iter) {
866 if (!FindByGUID<CreditCard>(credit_cards_, iter->guid()) &&
867 !FindByContents(credit_cards_, *iter))
868 autofill_data->AddCreditCard(*iter);
869 }
870
871 // Copy in the new credit cards.
872 credit_cards_.clear();
873 for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
874 iter != credit_cards->end(); ++iter) {
875 credit_cards_.push_back(new CreditCard(*iter));
876 }
877
878 // Refresh our local cache and send notifications to observers.
879 Refresh();
880}
881
882void PersonalDataManager::LoadProfiles() {
883 scoped_refptr<AutofillWebDataService> autofill_data(
884 AutofillWebDataService::FromBrowserContext(browser_context_));
885 if (!autofill_data.get()) {
886 NOTREACHED();
887 return;
888 }
889
890 CancelPendingQuery(&pending_profiles_query_);
891
892 pending_profiles_query_ = autofill_data->GetAutofillProfiles(this);
893}
894
895// Win and Linux implementations do nothing. Mac and Android implementations
896// fill in the contents of |auxiliary_profiles_|.
897#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
898void PersonalDataManager::LoadAuxiliaryProfiles() {
899}
900#endif
901
902void PersonalDataManager::LoadCreditCards() {
903 scoped_refptr<AutofillWebDataService> autofill_data(
904 AutofillWebDataService::FromBrowserContext(browser_context_));
905 if (!autofill_data.get()) {
906 NOTREACHED();
907 return;
908 }
909
910 CancelPendingQuery(&pending_creditcards_query_);
911
912 pending_creditcards_query_ = autofill_data->GetCreditCards(this);
913}
914
915void PersonalDataManager::ReceiveLoadedProfiles(WebDataServiceBase::Handle h,
916 const WDTypedResult* result) {
917 DCHECK_EQ(pending_profiles_query_, h);
918
919 pending_profiles_query_ = 0;
920 web_profiles_.clear();
921
922 const WDResult<std::vector<AutofillProfile*> >* r =
923 static_cast<const WDResult<std::vector<AutofillProfile*> >*>(result);
924
925 std::vector<AutofillProfile*> profiles = r->GetValue();
926 for (std::vector<AutofillProfile*>::iterator iter = profiles.begin();
927 iter != profiles.end(); ++iter) {
928 web_profiles_.push_back(*iter);
929 }
930
931 LogProfileCount();
932}
933
934void PersonalDataManager::ReceiveLoadedCreditCards(
935 WebDataServiceBase::Handle h, const WDTypedResult* result) {
936 DCHECK_EQ(pending_creditcards_query_, h);
937
938 pending_creditcards_query_ = 0;
939 credit_cards_.clear();
940
941 const WDResult<std::vector<CreditCard*> >* r =
942 static_cast<const WDResult<std::vector<CreditCard*> >*>(result);
943
944 std::vector<CreditCard*> credit_cards = r->GetValue();
945 for (std::vector<CreditCard*>::iterator iter = credit_cards.begin();
946 iter != credit_cards.end(); ++iter) {
947 credit_cards_.push_back(*iter);
948 }
949}
950
951void PersonalDataManager::CancelPendingQuery(
952 WebDataServiceBase::Handle* handle) {
953 if (*handle) {
954 scoped_refptr<AutofillWebDataService> autofill_data(
955 AutofillWebDataService::FromBrowserContext(browser_context_));
956 if (!autofill_data.get()) {
957 NOTREACHED();
958 return;
959 }
960 autofill_data->CancelRequest(*handle);
961 }
962 *handle = 0;
963}
964
965void PersonalDataManager::SaveImportedProfile(
966 const AutofillProfile& imported_profile) {
967 if (browser_context_->IsOffTheRecord())
968 return;
969
970 // Don't save a web profile if the data in the profile is a subset of an
971 // auxiliary profile.
972 for (std::vector<AutofillProfile*>::const_iterator iter =
973 auxiliary_profiles_.begin();
974 iter != auxiliary_profiles_.end(); ++iter) {
975 if (imported_profile.IsSubsetOf(**iter, app_locale_))
976 return;
977 }
978
979 std::vector<AutofillProfile> profiles;
980 MergeProfile(imported_profile, web_profiles_.get(), app_locale_, &profiles);
981 SetProfiles(&profiles);
982}
983
984
985void PersonalDataManager::SaveImportedCreditCard(
986 const CreditCard& imported_card) {
987 DCHECK(!imported_card.number().empty());
988 if (browser_context_->IsOffTheRecord())
989 return;
990
991 // Set to true if |imported_card| is merged into the credit card list.
992 bool merged = false;
993
994 std::vector<CreditCard> credit_cards;
995 for (std::vector<CreditCard*>::const_iterator card = credit_cards_.begin();
996 card != credit_cards_.end();
997 ++card) {
998 // If |imported_card| has not yet been merged, check whether it should be
999 // with the current |card|.
1000 if (!merged && (*card)->UpdateFromImportedCard(imported_card, app_locale_))
1001 merged = true;
1002
1003 credit_cards.push_back(**card);
1004 }
1005
1006 if (!merged)
1007 credit_cards.push_back(imported_card);
1008
1009 SetCreditCards(&credit_cards);
1010}
1011
1012void PersonalDataManager::LogProfileCount() const {
1013 if (!has_logged_profile_count_) {
1014 metric_logger_->LogStoredProfileCount(web_profiles_.size());
1015 has_logged_profile_count_ = true;
1016 }
1017}
1018
1019const AutofillMetrics* PersonalDataManager::metric_logger() const {
1020 return metric_logger_.get();
1021}
1022
1023void PersonalDataManager::set_metric_logger(
1024 const AutofillMetrics* metric_logger) {
1025 metric_logger_.reset(metric_logger);
1026}
1027
1028void PersonalDataManager::set_browser_context(
1029 content::BrowserContext* context) {
1030 browser_context_ = context;
1031}
1032
1033} // namespace autofill