diff options
author | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-08 19:12:58 +0000 |
---|---|---|
committer | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-08 19:12:58 +0000 |
commit | 2bf3d70f1426733e2535016128e2464305740b29 (patch) | |
tree | 2e45419ebe7b5d82287955f475a3638755b23ca1 /chrome/browser/autofill | |
parent | c4ff495718e7b190229e863e3387c4e5f99475a9 (diff) | |
download | chromium_src-2bf3d70f1426733e2535016128e2464305740b29.zip chromium_src-2bf3d70f1426733e2535016128e2464305740b29.tar.gz chromium_src-2bf3d70f1426733e2535016128e2464305740b29.tar.bz2 |
Implement ImportFormData and GetPossibleFieldTypes for PersonalDataManager, used by the AutoFillManager.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/521067
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35808 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/autofill')
-rw-r--r-- | chrome/browser/autofill/autofill_field.cc | 6 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_field.h | 4 | ||||
-rw-r--r-- | chrome/browser/autofill/form_structure.cc | 4 | ||||
-rw-r--r-- | chrome/browser/autofill/form_structure.h | 2 | ||||
-rw-r--r-- | chrome/browser/autofill/personal_data_manager.cc | 170 | ||||
-rw-r--r-- | chrome/browser/autofill/personal_data_manager.h | 48 |
6 files changed, 229 insertions, 5 deletions
diff --git a/chrome/browser/autofill/autofill_field.cc b/chrome/browser/autofill/autofill_field.cc index 0fcfdc6..e48d0a4 100644 --- a/chrome/browser/autofill/autofill_field.cc +++ b/chrome/browser/autofill/autofill_field.cc @@ -13,7 +13,7 @@ namespace { static std::string Hash32Bit(const std::string& str) { std::string hash_bin = base::SHA1HashString(str); - DCHECK(hash_bin.length() == 20); + DCHECK_EQ(20U, hash_bin.length()); uint32 hash32 = ((hash_bin[0] & 0xFF) << 24) | ((hash_bin[1] & 0xFF) << 16) | @@ -63,3 +63,7 @@ void AutoFillField::set_heuristic_type(const AutoFillFieldType& type) { else heuristic_type_ = UNKNOWN_TYPE; } + +bool AutoFillField::IsFieldFillable() const { + return type() != UNKNOWN_TYPE; +} diff --git a/chrome/browser/autofill/autofill_field.h b/chrome/browser/autofill/autofill_field.h index 84a5fb2..9ed87e2 100644 --- a/chrome/browser/autofill/autofill_field.h +++ b/chrome/browser/autofill/autofill_field.h @@ -39,6 +39,10 @@ class AutoFillField : public webkit_glue::FormField { // Sets the heuristic type of this field, validating the input. void set_heuristic_type(const AutoFillFieldType& type); + // Returns true if the field type has been determined (without the text in the + // field). + bool IsFieldFillable() const; + private: // The unique name of this field, generated by AutoFill. string16 unique_name_; diff --git a/chrome/browser/autofill/form_structure.cc b/chrome/browser/autofill/form_structure.cc index ab4ac14..ca3acc5 100644 --- a/chrome/browser/autofill/form_structure.cc +++ b/chrome/browser/autofill/form_structure.cc @@ -33,7 +33,7 @@ namespace { static std::string Hash64Bit(const std::string& str) { std::string hash_bin = base::SHA1HashString(str); - DCHECK(hash_bin.length() == 20); + DCHECK_EQ(20U, hash_bin.length()); uint64 hash64 = (((static_cast<uint64>(hash_bin[0])) & 0xFF) << 56) | (((static_cast<uint64>(hash_bin[1])) & 0xFF) << 48) | @@ -193,7 +193,7 @@ void FormStructure::set_possible_types(int index, const FieldTypeSet& types) { fields_[index]->set_possible_types(types); } -AutoFillField* FormStructure::field(int index) { +const AutoFillField* FormStructure::field(int index) const { return fields_[index]; } diff --git a/chrome/browser/autofill/form_structure.h b/chrome/browser/autofill/form_structure.h index 5892941..80e67b9 100644 --- a/chrome/browser/autofill/form_structure.h +++ b/chrome/browser/autofill/form_structure.h @@ -47,7 +47,7 @@ class FormStructure { // Sets the possible types for the field at |index|. void set_possible_types(int index, const FieldTypeSet& types); - AutoFillField* field(int index); + const AutoFillField* field(int index) const; size_t field_count() const; // Used for iterating over the fields. diff --git a/chrome/browser/autofill/personal_data_manager.cc b/chrome/browser/autofill/personal_data_manager.cc index ca204636..c60aa6e 100644 --- a/chrome/browser/autofill/personal_data_manager.cc +++ b/chrome/browser/autofill/personal_data_manager.cc @@ -5,20 +5,188 @@ #include "chrome/browser/autofill/personal_data_manager.h" #include "chrome/browser/autofill/autofill_manager.h" +#include "chrome/browser/autofill/autofill_field.h" #include "chrome/browser/autofill/form_structure.h" +// The minimum number of fields that must contain user data and have known types +// before autofill will attempt to import the data into a profile. +static const int kMinImportSize = 5; + +// The number of digits in a phone number. +static const int kPhoneNumberLength = 7; + +// The number of digits in an area code. +static const int kPhoneCityCodeLength = 3; + PersonalDataManager::~PersonalDataManager() { } bool PersonalDataManager::ImportFormData( const std::vector<FormStructure*>& form_structures, AutoFillManager* autofill_manager) { + InitializeIfNeeded(); + + // Parse the form and construct a profile based on the information that is + // possible to import. + int importable_fields = 0; + int importable_credit_card_fields = 0; + imported_profile_.reset(new AutoFillProfile(string16(), + CreateNextUniqueId())); + imported_credit_card_.reset(new CreditCard(string16())); + + bool billing_address_info = false; + std::vector<FormStructure*>::const_iterator iter; + for (iter = form_structures.begin(); iter != form_structures.end(); ++iter) { + const FormStructure* form = *iter; + for (size_t i = 0; i < form->field_count(); ++i) { + const AutoFillField* field = form->field(i); + string16 value = CollapseWhitespace(field->value(), false); + + // If we don't know the type of the field, or the user hasn't entered any + // information into the field, then skip it. + if (!field->IsFieldFillable() || value.empty()) + continue; + + AutoFillType field_type(field->type()); + FieldTypeGroup group(field_type.group()); + + if (group == AutoFillType::CREDIT_CARD) { + // If the user has a password set, we have no way of setting credit + // card numbers. + if (!HasPassword()) { + imported_credit_card_->SetInfo(AutoFillType(field_type.field_type()), + value); + ++importable_credit_card_fields; + } + } else { + // In the case of a phone number, if the whole phone number was entered + // into a single field, then parse it and set the sub components. + if (field_type.subgroup() == AutoFillType::PHONE_WHOLE_NUMBER) { + if (group == AutoFillType::PHONE_HOME) { + ParsePhoneNumber(imported_profile_.get(), &value, PHONE_HOME_NUMBER, + PHONE_HOME_CITY_CODE, PHONE_HOME_COUNTRY_CODE); + } else if (group == AutoFillType::PHONE_FAX) { + ParsePhoneNumber(imported_profile_.get(), &value, PHONE_FAX_NUMBER, + PHONE_FAX_CITY_CODE, PHONE_FAX_COUNTRY_CODE); + } + continue; + } + + imported_profile_->SetInfo(AutoFillType(field_type.field_type()), + value); + + // If we found any billing address information, then set the profile to + // use a separate billing address. + if (group == AutoFillType::ADDRESS_BILLING) + billing_address_info = true; + + ++importable_fields; + } + } + } + + // If the user did not enter enough information on the page then don't bother + // importing the data. + if (importable_fields + importable_credit_card_fields < kMinImportSize) + return false; + + if (!billing_address_info) + imported_profile_->set_use_billing_address(false); + + if (importable_fields == 0) + imported_profile_.reset(); + + if (importable_credit_card_fields == 0) + imported_credit_card_.reset(); + + // TODO(jhawkins): Alert the AutoFillManager that we have data. + return true; } void PersonalDataManager::GetPossibleFieldTypes(const string16& text, FieldTypeSet* possible_types) { + InitializeIfNeeded(); + + string16 clean_info = StringToLowerASCII(CollapseWhitespace(text, false)); + + if (clean_info.empty()) { + possible_types->insert(EMPTY_TYPE); + return; + } + + ScopedVector<FormGroup>::const_iterator iter; + for (iter = profiles_.begin(); iter != profiles_.end(); ++iter) { + const FormGroup* profile = *iter; + if (!profile) { + DLOG(ERROR) << "NULL information in profiles list"; + continue; + } + profile->GetPossibleFieldTypes(clean_info, possible_types); + } + + for (iter = credit_cards_.begin(); iter != credit_cards_.end(); ++iter) { + const FormGroup* credit_card = *iter; + if (!credit_card) { + DLOG(ERROR) << "NULL information in credit cards list"; + continue; + } + credit_card->GetPossibleFieldTypes(clean_info, possible_types); + } + + if (possible_types->size() == 0) + possible_types->insert(UNKNOWN_TYPE); +} + +bool PersonalDataManager::HasPassword() { + InitializeIfNeeded(); + return !password_hash_.empty(); +} + +PersonalDataManager::PersonalDataManager() + : is_initialized_(false) { +} + +void PersonalDataManager::InitializeIfNeeded() { + if (is_initialized_) + return; + + is_initialized_ = true; + // TODO(jhawkins): Load data. } -PersonalDataManager::PersonalDataManager() { +int PersonalDataManager::CreateNextUniqueId() { + // Profile IDs MUST start at 1 to allow 0 as an error value when reading + // the ID from the WebDB (see LoadData()). + int id = 1; + while (unique_ids_.count(id) != 0) + ++id; + unique_ids_.insert(id); + return id; +} + +void PersonalDataManager::ParsePhoneNumber( + AutoFillProfile* profile, + string16* value, + AutoFillFieldType number, + AutoFillFieldType city_code, + AutoFillFieldType country_code) const { + // Treat the last 7 digits as the number. + string16 number_str = value->substr(kPhoneNumberLength, + value->size() - kPhoneNumberLength); + profile->SetInfo(AutoFillType(number), number_str); + value->resize(value->size() - kPhoneNumberLength); + if (value->empty()) + return; + + // Treat the next three digits as the city code. + string16 city_code_str = value->substr(kPhoneCityCodeLength, + value->size() - kPhoneCityCodeLength); + profile->SetInfo(AutoFillType(city_code), city_code_str); + value->resize(value->size() - kPhoneCityCodeLength); + if (value->empty()) + return; + + // Treat any remaining digits as the country code. + profile->SetInfo(AutoFillType(country_code), *value); } diff --git a/chrome/browser/autofill/personal_data_manager.h b/chrome/browser/autofill/personal_data_manager.h index 1d27f16..c28c24b 100644 --- a/chrome/browser/autofill/personal_data_manager.h +++ b/chrome/browser/autofill/personal_data_manager.h @@ -5,9 +5,14 @@ #ifndef CHROME_BROWSER_AUTOFILL_PERSONAL_DATA_MANAGER_H_ #define CHROME_BROWSER_AUTOFILL_PERSONAL_DATA_MANAGER_H_ +#include <set> #include <vector> +#include "base/scoped_ptr.h" +#include "base/scoped_vector.h" #include "base/string16.h" +#include "chrome/browser/autofill/autofill_profile.h" +#include "chrome/browser/autofill/credit_card.h" #include "chrome/browser/autofill/field_types.h" class AutoFillManager; @@ -33,11 +38,54 @@ class PersonalDataManager { void GetPossibleFieldTypes(const string16& text, FieldTypeSet* possible_types); + // Returns true if the credit card information is stored with a password. + bool HasPassword(); + private: // Make sure that only Profile can create an instance of PersonalDataManager. friend class ProfileImpl; PersonalDataManager(); + + // Initializes the object if needed. This should be called at the beginning + // of all the public functions to make sure that the object has been properly + // initialized before use. + void InitializeIfNeeded(); + + // This will create and reserve a new unique id for a profile. + int CreateNextUniqueId(); + + // Parses value to extract the components of a phone number and adds them to + // profile. + // + // TODO(jhawkins): Investigate if this can be moved to PhoneField. + void ParsePhoneNumber(AutoFillProfile* profile, + string16* value, + AutoFillFieldType number, + AutoFillFieldType city_code, + AutoFillFieldType country_code) const; + + // True if PersonalDataManager is initialized. + bool is_initialized_; + + // The set of already created unique IDs, used to create a new unique ID. + std::set<int> unique_ids_; + + // The loaded profiles. + ScopedVector<FormGroup> profiles_; + + // The loaded credit cards. + ScopedVector<FormGroup> credit_cards_; + + // The profile that is imported from a web form by ImportFormData. + scoped_ptr<AutoFillProfile> imported_profile_; + + // The credit card that is imported from a web form by ImportFormData. + scoped_ptr<CreditCard> imported_credit_card_; + + // The hash of the password used to store the credit card. This is empty if + // no password exists. + string16 password_hash_; }; #endif // CHROME_BROWSER_AUTOFILL_PERSONAL_DATA_MANAGER_H_ |