| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/autofill/browser/personal_data_manager.h" | 5 #include "components/autofill/browser/personal_data_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <functional> | 8 #include <functional> |
| 9 #include <iterator> | 9 #include <iterator> |
| 10 | 10 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 #include "components/autofill/browser/validation.h" | 25 #include "components/autofill/browser/validation.h" |
| 26 #include "components/autofill/common/autofill_pref_names.h" | 26 #include "components/autofill/common/autofill_pref_names.h" |
| 27 #include "components/user_prefs/user_prefs.h" | 27 #include "components/user_prefs/user_prefs.h" |
| 28 #include "components/webdata/autofill/autofill_webdata_service.h" | 28 #include "components/webdata/autofill/autofill_webdata_service.h" |
| 29 #include "content/public/browser/browser_context.h" | 29 #include "content/public/browser/browser_context.h" |
| 30 | 30 |
| 31 using content::BrowserContext; | 31 using content::BrowserContext; |
| 32 | 32 |
| 33 namespace { | 33 namespace { |
| 34 | 34 |
| 35 const string16::value_type kCreditCardPrefix[] = {'*', 0}; | 35 const base::string16::value_type kCreditCardPrefix[] = {'*', 0}; |
| 36 | 36 |
| 37 template<typename T> | 37 template<typename T> |
| 38 class FormGroupMatchesByGUIDFunctor { | 38 class FormGroupMatchesByGUIDFunctor { |
| 39 public: | 39 public: |
| 40 explicit FormGroupMatchesByGUIDFunctor(const std::string& guid) | 40 explicit FormGroupMatchesByGUIDFunctor(const std::string& guid) |
| 41 : guid_(guid) { | 41 : guid_(guid) { |
| 42 } | 42 } |
| 43 | 43 |
| 44 bool operator()(const T& form_group) { | 44 bool operator()(const T& form_group) { |
| 45 return form_group.guid() == guid_; | 45 return form_group.guid() == guid_; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 if (country.requires_zip() && profile.GetRawInfo(ADDRESS_HOME_ZIP).empty()) | 103 if (country.requires_zip() && profile.GetRawInfo(ADDRESS_HOME_ZIP).empty()) |
| 104 return false; | 104 return false; |
| 105 | 105 |
| 106 return true; | 106 return true; |
| 107 } | 107 } |
| 108 | 108 |
| 109 // Return true if the |field_type| and |value| are valid within the context | 109 // Return true if the |field_type| and |value| are valid within the context |
| 110 // of importing a form. | 110 // of importing a form. |
| 111 bool IsValidFieldTypeAndValue(const std::set<AutofillFieldType>& types_seen, | 111 bool IsValidFieldTypeAndValue(const std::set<AutofillFieldType>& types_seen, |
| 112 AutofillFieldType field_type, | 112 AutofillFieldType field_type, |
| 113 const string16& value) { | 113 const base::string16& value) { |
| 114 // Abandon the import if two fields of the same type are encountered. | 114 // Abandon the import if two fields of the same type are encountered. |
| 115 // This indicates ambiguous data or miscategorization of types. | 115 // This indicates ambiguous data or miscategorization of types. |
| 116 // Make an exception for PHONE_HOME_NUMBER however as both prefix and | 116 // Make an exception for PHONE_HOME_NUMBER however as both prefix and |
| 117 // suffix are stored against this type, and for EMAIL_ADDRESS because it is | 117 // suffix are stored against this type, and for EMAIL_ADDRESS because it is |
| 118 // common to see second 'confirm email address' fields on forms. | 118 // common to see second 'confirm email address' fields on forms. |
| 119 if (types_seen.count(field_type) && field_type != PHONE_HOME_NUMBER && | 119 if (types_seen.count(field_type) && field_type != PHONE_HOME_NUMBER && |
| 120 field_type != EMAIL_ADDRESS) | 120 field_type != EMAIL_ADDRESS) |
| 121 return false; | 121 return false; |
| 122 | 122 |
| 123 // Abandon the import if an email address value shows up in a field that is | 123 // Abandon the import if an email address value shows up in a field that is |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 | 234 |
| 235 // Detect and discard forms with multiple fields of the same type. | 235 // Detect and discard forms with multiple fields of the same type. |
| 236 std::set<AutofillFieldType> types_seen; | 236 std::set<AutofillFieldType> types_seen; |
| 237 | 237 |
| 238 // We only set complete phone, so aggregate phone parts in these vars and set | 238 // We only set complete phone, so aggregate phone parts in these vars and set |
| 239 // complete at the end. | 239 // complete at the end. |
| 240 PhoneNumber::PhoneCombineHelper home; | 240 PhoneNumber::PhoneCombineHelper home; |
| 241 | 241 |
| 242 for (size_t i = 0; i < form.field_count(); ++i) { | 242 for (size_t i = 0; i < form.field_count(); ++i) { |
| 243 const AutofillField* field = form.field(i); | 243 const AutofillField* field = form.field(i); |
| 244 string16 value = CollapseWhitespace(field->value, false); | 244 base::string16 value = CollapseWhitespace(field->value, false); |
| 245 | 245 |
| 246 // If we don't know the type of the field, or the user hasn't entered any | 246 // If we don't know the type of the field, or the user hasn't entered any |
| 247 // information into the field, then skip it. | 247 // information into the field, then skip it. |
| 248 if (!field->IsFieldFillable() || value.empty()) | 248 if (!field->IsFieldFillable() || value.empty()) |
| 249 continue; | 249 continue; |
| 250 | 250 |
| 251 AutofillFieldType field_type = field->type(); | 251 AutofillFieldType field_type = field->type(); |
| 252 FieldTypeGroup group(AutofillType(field_type).group()); | 252 FieldTypeGroup group(AutofillType(field_type).group()); |
| 253 | 253 |
| 254 // There can be multiple email fields (e.g. in the case of 'confirm email' | 254 // There can be multiple email fields (e.g. in the case of 'confirm email' |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 !value.empty() && | 293 !value.empty() && |
| 294 imported_profile->GetRawInfo(ADDRESS_HOME_COUNTRY).empty()) { | 294 imported_profile->GetRawInfo(ADDRESS_HOME_COUNTRY).empty()) { |
| 295 imported_profile.reset(); | 295 imported_profile.reset(); |
| 296 break; | 296 break; |
| 297 } | 297 } |
| 298 } | 298 } |
| 299 } | 299 } |
| 300 | 300 |
| 301 // Construct the phone number. Reject the profile if the number is invalid. | 301 // Construct the phone number. Reject the profile if the number is invalid. |
| 302 if (imported_profile.get() && !home.IsEmpty()) { | 302 if (imported_profile.get() && !home.IsEmpty()) { |
| 303 string16 constructed_number; | 303 base::string16 constructed_number; |
| 304 if (!home.ParseNumber(*imported_profile, app_locale_, | 304 if (!home.ParseNumber(*imported_profile, app_locale_, |
| 305 &constructed_number) || | 305 &constructed_number) || |
| 306 !imported_profile->SetInfo(PHONE_HOME_WHOLE_NUMBER, constructed_number, | 306 !imported_profile->SetInfo(PHONE_HOME_WHOLE_NUMBER, constructed_number, |
| 307 app_locale_)) { | 307 app_locale_)) { |
| 308 imported_profile.reset(); | 308 imported_profile.reset(); |
| 309 } | 309 } |
| 310 } | 310 } |
| 311 | 311 |
| 312 // Reject the profile if minimum address and validation requirements are not | 312 // Reject the profile if minimum address and validation requirements are not |
| 313 // met. | 313 // met. |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 return credit_cards_.get(); | 542 return credit_cards_.get(); |
| 543 } | 543 } |
| 544 | 544 |
| 545 void PersonalDataManager::Refresh() { | 545 void PersonalDataManager::Refresh() { |
| 546 LoadProfiles(); | 546 LoadProfiles(); |
| 547 LoadCreditCards(); | 547 LoadCreditCards(); |
| 548 } | 548 } |
| 549 | 549 |
| 550 void PersonalDataManager::GetProfileSuggestions( | 550 void PersonalDataManager::GetProfileSuggestions( |
| 551 AutofillFieldType type, | 551 AutofillFieldType type, |
| 552 const string16& field_contents, | 552 const base::string16& field_contents, |
| 553 bool field_is_autofilled, | 553 bool field_is_autofilled, |
| 554 std::vector<AutofillFieldType> other_field_types, | 554 std::vector<AutofillFieldType> other_field_types, |
| 555 std::vector<string16>* values, | 555 std::vector<base::string16>* values, |
| 556 std::vector<string16>* labels, | 556 std::vector<base::string16>* labels, |
| 557 std::vector<string16>* icons, | 557 std::vector<base::string16>* icons, |
| 558 std::vector<GUIDPair>* guid_pairs) { | 558 std::vector<GUIDPair>* guid_pairs) { |
| 559 values->clear(); | 559 values->clear(); |
| 560 labels->clear(); | 560 labels->clear(); |
| 561 icons->clear(); | 561 icons->clear(); |
| 562 guid_pairs->clear(); | 562 guid_pairs->clear(); |
| 563 | 563 |
| 564 const std::vector<AutofillProfile*>& profiles = GetProfiles(); | 564 const std::vector<AutofillProfile*>& profiles = GetProfiles(); |
| 565 std::vector<AutofillProfile*> matched_profiles; | 565 std::vector<AutofillProfile*> matched_profiles; |
| 566 for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin(); | 566 for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin(); |
| 567 iter != profiles.end(); ++iter) { | 567 iter != profiles.end(); ++iter) { |
| 568 AutofillProfile* profile = *iter; | 568 AutofillProfile* profile = *iter; |
| 569 | 569 |
| 570 // The value of the stored data for this field type in the |profile|. | 570 // The value of the stored data for this field type in the |profile|. |
| 571 std::vector<string16> multi_values; | 571 std::vector<base::string16> multi_values; |
| 572 profile->GetMultiInfo(type, app_locale_, &multi_values); | 572 profile->GetMultiInfo(type, app_locale_, &multi_values); |
| 573 | 573 |
| 574 for (size_t i = 0; i < multi_values.size(); ++i) { | 574 for (size_t i = 0; i < multi_values.size(); ++i) { |
| 575 if (!field_is_autofilled) { | 575 if (!field_is_autofilled) { |
| 576 // Suggest data that starts with what the user has typed. | 576 // Suggest data that starts with what the user has typed. |
| 577 if (!multi_values[i].empty() && | 577 if (!multi_values[i].empty() && |
| 578 StartsWith(multi_values[i], field_contents, false)) { | 578 StartsWith(multi_values[i], field_contents, false)) { |
| 579 matched_profiles.push_back(profile); | 579 matched_profiles.push_back(profile); |
| 580 values->push_back(multi_values[i]); | 580 values->push_back(multi_values[i]); |
| 581 guid_pairs->push_back(GUIDPair(profile->guid(), i)); | 581 guid_pairs->push_back(GUIDPair(profile->guid(), i)); |
| 582 } | 582 } |
| 583 } else { | 583 } else { |
| 584 if (multi_values[i].empty()) | 584 if (multi_values[i].empty()) |
| 585 continue; | 585 continue; |
| 586 | 586 |
| 587 string16 profile_value_lower_case( | 587 base::string16 profile_value_lower_case( |
| 588 StringToLowerASCII(multi_values[i])); | 588 StringToLowerASCII(multi_values[i])); |
| 589 string16 field_value_lower_case(StringToLowerASCII(field_contents)); | 589 base::string16 field_value_lower_case( |
| 590 StringToLowerASCII(field_contents)); |
| 590 // Phone numbers could be split in US forms, so field value could be | 591 // Phone numbers could be split in US forms, so field value could be |
| 591 // either prefix or suffix of the phone. | 592 // either prefix or suffix of the phone. |
| 592 bool matched_phones = false; | 593 bool matched_phones = false; |
| 593 if (type == PHONE_HOME_NUMBER && !field_value_lower_case.empty() && | 594 if (type == PHONE_HOME_NUMBER && !field_value_lower_case.empty() && |
| 594 (profile_value_lower_case.find(field_value_lower_case) != | 595 (profile_value_lower_case.find(field_value_lower_case) != |
| 595 string16::npos)) { | 596 base::string16::npos)) { |
| 596 matched_phones = true; | 597 matched_phones = true; |
| 597 } | 598 } |
| 598 | 599 |
| 599 // Suggest variants of the profile that's already been filled in. | 600 // Suggest variants of the profile that's already been filled in. |
| 600 if (matched_phones || | 601 if (matched_phones || |
| 601 profile_value_lower_case == field_value_lower_case) { | 602 profile_value_lower_case == field_value_lower_case) { |
| 602 for (size_t j = 0; j < multi_values.size(); ++j) { | 603 for (size_t j = 0; j < multi_values.size(); ++j) { |
| 603 if (!multi_values[j].empty()) { | 604 if (!multi_values[j].empty()) { |
| 604 values->push_back(multi_values[j]); | 605 values->push_back(multi_values[j]); |
| 605 guid_pairs->push_back(GUIDPair(profile->guid(), j)); | 606 guid_pairs->push_back(GUIDPair(profile->guid(), j)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 622 // No sub-labels for previously filled fields. | 623 // No sub-labels for previously filled fields. |
| 623 labels->resize(values->size()); | 624 labels->resize(values->size()); |
| 624 } | 625 } |
| 625 | 626 |
| 626 // No icons for profile suggestions. | 627 // No icons for profile suggestions. |
| 627 icons->resize(values->size()); | 628 icons->resize(values->size()); |
| 628 } | 629 } |
| 629 | 630 |
| 630 void PersonalDataManager::GetCreditCardSuggestions( | 631 void PersonalDataManager::GetCreditCardSuggestions( |
| 631 AutofillFieldType type, | 632 AutofillFieldType type, |
| 632 const string16& field_contents, | 633 const base::string16& field_contents, |
| 633 std::vector<string16>* values, | 634 std::vector<base::string16>* values, |
| 634 std::vector<string16>* labels, | 635 std::vector<base::string16>* labels, |
| 635 std::vector<string16>* icons, | 636 std::vector<base::string16>* icons, |
| 636 std::vector<GUIDPair>* guid_pairs) { | 637 std::vector<GUIDPair>* guid_pairs) { |
| 637 values->clear(); | 638 values->clear(); |
| 638 labels->clear(); | 639 labels->clear(); |
| 639 icons->clear(); | 640 icons->clear(); |
| 640 guid_pairs->clear(); | 641 guid_pairs->clear(); |
| 641 | 642 |
| 642 for (std::vector<CreditCard*>::const_iterator iter = credit_cards().begin(); | 643 for (std::vector<CreditCard*>::const_iterator iter = credit_cards().begin(); |
| 643 iter != credit_cards().end(); ++iter) { | 644 iter != credit_cards().end(); ++iter) { |
| 644 CreditCard* credit_card = *iter; | 645 CreditCard* credit_card = *iter; |
| 645 | 646 |
| 646 // The value of the stored data for this field type in the |credit_card|. | 647 // The value of the stored data for this field type in the |credit_card|. |
| 647 string16 creditcard_field_value = credit_card->GetInfo(type, app_locale_); | 648 base::string16 creditcard_field_value = |
| 649 credit_card->GetInfo(type, app_locale_); |
| 648 if (!creditcard_field_value.empty() && | 650 if (!creditcard_field_value.empty() && |
| 649 StartsWith(creditcard_field_value, field_contents, false)) { | 651 StartsWith(creditcard_field_value, field_contents, false)) { |
| 650 if (type == CREDIT_CARD_NUMBER) | 652 if (type == CREDIT_CARD_NUMBER) |
| 651 creditcard_field_value = credit_card->ObfuscatedNumber(); | 653 creditcard_field_value = credit_card->ObfuscatedNumber(); |
| 652 | 654 |
| 653 string16 label; | 655 base::string16 label; |
| 654 if (credit_card->number().empty()) { | 656 if (credit_card->number().empty()) { |
| 655 // If there is no CC number, return name to show something. | 657 // If there is no CC number, return name to show something. |
| 656 label = credit_card->GetInfo(CREDIT_CARD_NAME, app_locale_); | 658 label = credit_card->GetInfo(CREDIT_CARD_NAME, app_locale_); |
| 657 } else { | 659 } else { |
| 658 label = kCreditCardPrefix; | 660 label = kCreditCardPrefix; |
| 659 label.append(credit_card->LastFourDigits()); | 661 label.append(credit_card->LastFourDigits()); |
| 660 } | 662 } |
| 661 | 663 |
| 662 values->push_back(creditcard_field_value); | 664 values->push_back(creditcard_field_value); |
| 663 labels->push_back(label); | 665 labels->push_back(label); |
| 664 icons->push_back(UTF8ToUTF16(credit_card->type())); | 666 icons->push_back(UTF8ToUTF16(credit_card->type())); |
| 665 guid_pairs->push_back(GUIDPair(credit_card->guid(), 0)); | 667 guid_pairs->push_back(GUIDPair(credit_card->guid(), 0)); |
| 666 } | 668 } |
| 667 } | 669 } |
| 668 } | 670 } |
| 669 | 671 |
| 670 bool PersonalDataManager::IsAutofillEnabled() const { | 672 bool PersonalDataManager::IsAutofillEnabled() const { |
| 671 return components::UserPrefs::Get(browser_context_)->GetBoolean( | 673 return components::UserPrefs::Get(browser_context_)->GetBoolean( |
| 672 prefs::kAutofillEnabled); | 674 prefs::kAutofillEnabled); |
| 673 } | 675 } |
| 674 | 676 |
| 675 // static | 677 // static |
| 676 bool PersonalDataManager::IsValidLearnableProfile( | 678 bool PersonalDataManager::IsValidLearnableProfile( |
| 677 const AutofillProfile& profile, | 679 const AutofillProfile& profile, |
| 678 const std::string& app_locale) { | 680 const std::string& app_locale) { |
| 679 if (!IsMinimumAddress(profile, app_locale)) | 681 if (!IsMinimumAddress(profile, app_locale)) |
| 680 return false; | 682 return false; |
| 681 | 683 |
| 682 string16 email = profile.GetRawInfo(EMAIL_ADDRESS); | 684 base::string16 email = profile.GetRawInfo(EMAIL_ADDRESS); |
| 683 if (!email.empty() && !autofill::IsValidEmailAddress(email)) | 685 if (!email.empty() && !autofill::IsValidEmailAddress(email)) |
| 684 return false; | 686 return false; |
| 685 | 687 |
| 686 // Reject profiles with invalid US state information. | 688 // Reject profiles with invalid US state information. |
| 687 string16 state = profile.GetRawInfo(ADDRESS_HOME_STATE); | 689 base::string16 state = profile.GetRawInfo(ADDRESS_HOME_STATE); |
| 688 if (profile.GetRawInfo(ADDRESS_HOME_COUNTRY) == ASCIIToUTF16("US") && | 690 if (profile.GetRawInfo(ADDRESS_HOME_COUNTRY) == ASCIIToUTF16("US") && |
| 689 !state.empty() && !FormGroup::IsValidState(state)) { | 691 !state.empty() && !FormGroup::IsValidState(state)) { |
| 690 return false; | 692 return false; |
| 691 } | 693 } |
| 692 | 694 |
| 693 // Reject profiles with invalid US zip information. | 695 // Reject profiles with invalid US zip information. |
| 694 string16 zip = profile.GetRawInfo(ADDRESS_HOME_ZIP); | 696 base::string16 zip = profile.GetRawInfo(ADDRESS_HOME_ZIP); |
| 695 if (profile.GetRawInfo(ADDRESS_HOME_COUNTRY) == ASCIIToUTF16("US") && | 697 if (profile.GetRawInfo(ADDRESS_HOME_COUNTRY) == ASCIIToUTF16("US") && |
| 696 !zip.empty() && !autofill::IsValidZip(zip)) | 698 !zip.empty() && !autofill::IsValidZip(zip)) |
| 697 return false; | 699 return false; |
| 698 | 700 |
| 699 return true; | 701 return true; |
| 700 } | 702 } |
| 701 | 703 |
| 702 // static | 704 // static |
| 703 bool PersonalDataManager::MergeProfile( | 705 bool PersonalDataManager::MergeProfile( |
| 704 const AutofillProfile& profile, | 706 const AutofillProfile& profile, |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 999 | 1001 |
| 1000 void PersonalDataManager::set_metric_logger( | 1002 void PersonalDataManager::set_metric_logger( |
| 1001 const AutofillMetrics* metric_logger) { | 1003 const AutofillMetrics* metric_logger) { |
| 1002 metric_logger_.reset(metric_logger); | 1004 metric_logger_.reset(metric_logger); |
| 1003 } | 1005 } |
| 1004 | 1006 |
| 1005 void PersonalDataManager::set_browser_context( | 1007 void PersonalDataManager::set_browser_context( |
| 1006 content::BrowserContext* context) { | 1008 content::BrowserContext* context) { |
| 1007 browser_context_ = context; | 1009 browser_context_ = context; |
| 1008 } | 1010 } |
| OLD | NEW |