summaryrefslogtreecommitdiffstats
path: root/chrome/browser/autofill
diff options
context:
space:
mode:
authorjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-08 19:12:58 +0000
committerjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-08 19:12:58 +0000
commit2bf3d70f1426733e2535016128e2464305740b29 (patch)
tree2e45419ebe7b5d82287955f475a3638755b23ca1 /chrome/browser/autofill
parentc4ff495718e7b190229e863e3387c4e5f99475a9 (diff)
downloadchromium_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.cc6
-rw-r--r--chrome/browser/autofill/autofill_field.h4
-rw-r--r--chrome/browser/autofill/form_structure.cc4
-rw-r--r--chrome/browser/autofill/form_structure.h2
-rw-r--r--chrome/browser/autofill/personal_data_manager.cc170
-rw-r--r--chrome/browser/autofill/personal_data_manager.h48
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_