diff options
author | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-09 23:42:34 +0000 |
---|---|---|
committer | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-09 23:42:34 +0000 |
commit | e2d8667b7a2bb47a25ddd9a74cbd627bf17b5c7e (patch) | |
tree | 776a15005671831ab776df8e0deb7d2a366aa23e /chrome | |
parent | 7d01a10bbf5887f4d095f53f5a7b376aa99f4635 (diff) | |
download | chromium_src-e2d8667b7a2bb47a25ddd9a74cbd627bf17b5c7e.zip chromium_src-e2d8667b7a2bb47a25ddd9a74cbd627bf17b5c7e.tar.gz chromium_src-e2d8667b7a2bb47a25ddd9a74cbd627bf17b5c7e.tar.bz2 |
autofill: Add the FormField interface. Classes that implement the FormField interface provide heuristics for determining the type of a form field. An initial implementation, EmailField, is provided.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/469013
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@34201 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/autofill/autofill_field.cc | 32 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_field.h | 35 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_manager.cc | 17 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_manager.h | 4 | ||||
-rw-r--r-- | chrome/browser/autofill/field_types.h | 6 | ||||
-rw-r--r-- | chrome/browser/autofill/form_field.cc | 191 | ||||
-rw-r--r-- | chrome/browser/autofill/form_field.h | 151 | ||||
-rw-r--r-- | chrome/browser/autofill/form_structure.cc | 67 | ||||
-rw-r--r-- | chrome/browser/autofill/form_structure.h | 34 | ||||
-rw-r--r-- | chrome/browser/autofill/personal_data_manager.cc | 4 | ||||
-rw-r--r-- | chrome/browser/autofill/personal_data_manager.h | 13 | ||||
-rwxr-xr-x | chrome/chrome_browser.gypi | 2 |
12 files changed, 541 insertions, 15 deletions
diff --git a/chrome/browser/autofill/autofill_field.cc b/chrome/browser/autofill/autofill_field.cc index fba28a0..0fcfdc6 100644 --- a/chrome/browser/autofill/autofill_field.cc +++ b/chrome/browser/autofill/autofill_field.cc @@ -25,8 +25,28 @@ static std::string Hash32Bit(const std::string& str) { } // namespace -AutoFillField::AutoFillField(const webkit_glue::FormField& field) - : webkit_glue::FormField(field) { +AutoFillField::AutoFillField() + : server_type_(NO_SERVER_DATA), + heuristic_type_(UNKNOWN_TYPE) { +} + +AutoFillField::AutoFillField(const webkit_glue::FormField& field, + const string16& unique_name) + : webkit_glue::FormField(field), + unique_name_(unique_name), + server_type_(NO_SERVER_DATA), + heuristic_type_(UNKNOWN_TYPE) { +} + +AutoFillFieldType AutoFillField::type() const { + if (server_type_ != NO_SERVER_DATA) + return server_type_; + + return heuristic_type_; +} + +bool AutoFillField::IsEmpty() const { + return value().empty(); } std::string AutoFillField::FieldSignature() const { @@ -35,3 +55,11 @@ std::string AutoFillField::FieldSignature() const { std::string field_string = field_name + "&" + type; return Hash32Bit(field_string); } + +void AutoFillField::set_heuristic_type(const AutoFillFieldType& type) { + DCHECK(type >= 0 && type < MAX_VALID_FIELD_TYPE); + if (type >= 0 && type < MAX_VALID_FIELD_TYPE) + heuristic_type_ = type; + else + heuristic_type_ = UNKNOWN_TYPE; +} diff --git a/chrome/browser/autofill/autofill_field.h b/chrome/browser/autofill/autofill_field.h index e8672d0..84a5fb2 100644 --- a/chrome/browser/autofill/autofill_field.h +++ b/chrome/browser/autofill/autofill_field.h @@ -5,21 +5,52 @@ #ifndef CHROME_BROWSER_AUTOFILL_AUTOFILL_FIELD_H_ #define CHROME_BROWSER_AUTOFILL_AUTOFILL_FIELD_H_ +#include <string> + +#include "base/string16.h" #include "chrome/browser/autofill/field_types.h" #include "webkit/glue/form_field.h" class AutoFillField : public webkit_glue::FormField { public: - explicit AutoFillField(const webkit_glue::FormField& field); + AutoFillField(); + AutoFillField(const webkit_glue::FormField& field, + const string16& unique_name); + + string16 unique_name() const { return unique_name_; } + AutoFillFieldType heuristic_type() const { return heuristic_type_; } const FieldTypeSet& possible_types() const { return possible_types_; } + void set_possible_types(const FieldTypeSet& possible_types) { + possible_types_ = possible_types; + } + + // This function automatically chooses between server and heuristic autofill + // type, depending on the data available. + AutoFillFieldType type() const; + + // Returns true if the value of this field is empty. + bool IsEmpty() const; // The unique signature of this field, composed of the field name and the html // input type in a 32-bit hash. std::string FieldSignature() const; + // Sets the heuristic type of this field, validating the input. + void set_heuristic_type(const AutoFillFieldType& type); + private: - FieldTypeSet possible_types_; + // The unique name of this field, generated by AutoFill. + string16 unique_name_; + + // The type of the field, as determined by the AutoFill server. + AutoFillFieldType server_type_; + + // The type of the field, as determined by the local heuristics. + AutoFillFieldType heuristic_type_; + + // The set of possible types for this field. + FieldTypeSet possible_types_; }; #endif // CHROME_BROWSER_AUTOFILL_AUTOFILL_FIELD_H_ diff --git a/chrome/browser/autofill/autofill_manager.cc b/chrome/browser/autofill/autofill_manager.cc index 15271f5..5632d63 100644 --- a/chrome/browser/autofill/autofill_manager.cc +++ b/chrome/browser/autofill/autofill_manager.cc @@ -37,7 +37,8 @@ void AutoFillManager::FormFieldValuesSubmitted( if (!upload_form_structure_->IsAutoFillable()) return; - // TODO(jhawkins): Determine possible field types. + // Determine the possible field types. + DeterminePossibleFieldTypes(upload_form_structure_.get()); if (!personal_data_->ImportFormData(form_structures_, this)) return; @@ -46,6 +47,20 @@ void AutoFillManager::FormFieldValuesSubmitted( infobar_.reset(new AutoFillInfoBarDelegate(tab_contents_, this)); } +void AutoFillManager::DeterminePossibleFieldTypes( + FormStructure* form_structure) { + // TODO(jhawkins): Update field text. + + form_structure->GetHeuristicAutoFillTypes(); + + for (size_t i = 0; i < form_structure->field_count(); i++) { + const AutoFillField* field = form_structure->field(i); + FieldTypeSet field_types; + personal_data_->GetPossibleFieldTypes(field->value(), &field_types); + form_structure->set_possible_types(i, field_types); + } +} + void AutoFillManager::SaveFormData() { UploadFormData(); diff --git a/chrome/browser/autofill/autofill_manager.h b/chrome/browser/autofill/autofill_manager.h index e5b3b58..dac7ffd 100644 --- a/chrome/browser/autofill/autofill_manager.h +++ b/chrome/browser/autofill/autofill_manager.h @@ -30,6 +30,10 @@ class AutoFillManager : public RenderViewHostDelegate::AutoFill { virtual void FormFieldValuesSubmitted( const webkit_glue::FormFieldValues& form); + // Uses heuristics and existing personal data to determine the possible field + // types. + void DeterminePossibleFieldTypes(FormStructure* form_structure); + // Saves the form data to the web database. void SaveFormData(); diff --git a/chrome/browser/autofill/field_types.h b/chrome/browser/autofill/field_types.h index 903af7e..d202a2e 100644 --- a/chrome/browser/autofill/field_types.h +++ b/chrome/browser/autofill/field_types.h @@ -7,6 +7,12 @@ #include <set> +typedef enum _AddressType { + kGenericAddress = 0, + kBillingAddress, + kShippingAddress +} AddressType; + // NOTE: This list MUST not be modified. The server aggregates and stores these // types over several versions, so we must remain fully compatible with the // autofill server, which is itself backward-compatible. The list must be kept diff --git a/chrome/browser/autofill/form_field.cc b/chrome/browser/autofill/form_field.cc new file mode 100644 index 0000000..dca943f --- /dev/null +++ b/chrome/browser/autofill/form_field.cc @@ -0,0 +1,191 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/autofill/form_field.h" + +#include "chrome/browser/autofill/autofill_field.h" +#include "third_party/WebKit/WebKit/chromium/public/WebRegularExpression.h" +#include "third_party/WebKit/WebKit/chromium/public/WebString.h" + +class EmailField : public FormField { + public: + virtual bool GetFieldInfo(FieldTypeMap* field_type_map) const { + bool ok = Add(field_type_map, field_, AutoFillType(EMAIL_ADDRESS)); + DCHECK(ok); + return true; + } + + static EmailField* Parse(std::vector<AutoFillField*>::const_iterator* iter, + bool is_ecml) { + string16 pattern; + if (is_ecml) { + pattern = GetEcmlPattern(kEcmlShipToEmail, kEcmlBillToEmail, '|'); + } else { + pattern = ASCIIToUTF16("email|e-mail"); + } + + AutoFillField* field; + if (ParseText(iter, pattern, &field)) + return new EmailField(field); + + return NULL; + } + + virtual int priority() const { return 1; } + + private: + explicit EmailField(AutoFillField *field) : field_(field) {} + + AutoFillField* field_; +}; + +// static +bool FormField::Match(AutoFillField* field, const string16& pattern) { + WebKit::WebRegularExpression re(WebKit::WebString(pattern), + WebKit::WebTextCaseInsensitive); + + // For now, we apply the same pattern to the field's label and the field's + // name. Matching the name is a bit of a long shot for many patterns, but + // it generally doesn't hurt to try. + if (re.match(WebKit::WebString(field->label())) || + re.match(WebKit::WebString(field->name()))) { + return true; + } + + return false; +} + +// static +FormField* FormField::ParseFormField( + std::vector<AutoFillField*>::const_iterator* iter, + bool is_ecml) { + FormField *field; + field = EmailField::Parse(iter, is_ecml); + if (field != NULL) + return field; + + // TODO(jhawkins): + // - AddressField + // - CreditCardField + // - NameField + // - PhoneField + + return NULL; +} + +// static +bool FormField::ParseText(std::vector<AutoFillField*>::const_iterator* iter, + const string16& pattern) { + AutoFillField* field; + return ParseText(iter, pattern, &field); +} + +// static +bool FormField::ParseText(std::vector<AutoFillField*>::const_iterator* iter, + const string16& pattern, + AutoFillField** dest) { + AutoFillField* field = **iter; + if (!field) + return false; + + if (Match(field, pattern)) { + *dest = field; + (*iter)++; + return true; + } + + return false; +} + +// static +bool FormField::ParseEmpty(std::vector<AutoFillField*>::const_iterator* iter) { + // TODO(jhawkins): Handle select fields. + return ParseText(iter, ASCIIToUTF16("")); +} + +// static +bool FormField::Add(FieldTypeMap* field_type_map, AutoFillField* field, + const AutoFillType& type) { + // Several fields are optional. + if (field) + field_type_map->insert(make_pair(field->unique_name(), type.field_type())); + + return true; +} + +string16 FormField::GetEcmlPattern(const string16& ecml_name) { + return ASCIIToUTF16("&") + ecml_name; +} + +string16 FormField::GetEcmlPattern(const string16& ecml_name1, + const string16& ecml_name2, + string16::value_type pattern_operator) { + string16 ampersand = ASCIIToUTF16("&"); + return ampersand + ecml_name1 + pattern_operator + ampersand + ecml_name2; +} + +FormFieldSet::FormFieldSet(FormStructure* fields) { + bool is_ecml = CheckECML(fields); + + // Parse fields. + std::vector<AutoFillField*>::const_iterator field = fields->begin(); + while (field != fields->end() && *field != NULL) { + FormField* form_field = FormField::ParseFormField(&field, is_ecml); + if (!form_field) { + field++; + continue; + } + + push_back(form_field); + } +} + +bool FormFieldSet::CheckECML(FormStructure* fields) { + size_t num_fields = fields->field_count(); + for (size_t index = 0; index < num_fields; ++index) { + string16 name(fields->field(index)->name()); + if (name.substr(0, 4) == ASCIIToUTF16("ecom") && + (StartsWith(name, kEcmlShipToTitle, false) || + StartsWith(name, kEcmlShipToFirstName, false) || + StartsWith(name, kEcmlShipToMiddleName, false) || + StartsWith(name, kEcmlShipToLastName, false) || + StartsWith(name, kEcmlShipToNameSuffix, false) || + StartsWith(name, kEcmlShipToCompanyName, false) || + StartsWith(name, kEcmlShipToAddress1, false) || + StartsWith(name, kEcmlShipToAddress2, false) || + StartsWith(name, kEcmlShipToAddress3, false) || + StartsWith(name, kEcmlShipToCity, false) || + StartsWith(name, kEcmlShipToStateProv, false) || + StartsWith(name, kEcmlShipToPostalCode, false) || + StartsWith(name, kEcmlShipToCountry, false) || + StartsWith(name, kEcmlShipToPhone, false) || + StartsWith(name, kEcmlShipToPhone, false) || + StartsWith(name, kEcmlShipToEmail, false) || + StartsWith(name, kEcmlBillToTitle, false) || + StartsWith(name, kEcmlBillToFirstName, false) || + StartsWith(name, kEcmlBillToMiddleName, false) || + StartsWith(name, kEcmlBillToLastName, false) || + StartsWith(name, kEcmlBillToNameSuffix, false) || + StartsWith(name, kEcmlBillToCompanyName, false) || + StartsWith(name, kEcmlBillToAddress1, false) || + StartsWith(name, kEcmlBillToAddress2, false) || + StartsWith(name, kEcmlBillToAddress3, false) || + StartsWith(name, kEcmlBillToCity, false) || + StartsWith(name, kEcmlBillToStateProv, false) || + StartsWith(name, kEcmlBillToPostalCode, false) || + StartsWith(name, kEcmlBillToCountry, false) || + StartsWith(name, kEcmlBillToPhone, false) || + StartsWith(name, kEcmlBillToPhone, false) || + StartsWith(name, kEcmlBillToEmail, false) || + StartsWith(name, kEcmlCardHolder, false) || + StartsWith(name, kEcmlCardType, false) || + StartsWith(name, kEcmlCardNumber, false) || + StartsWith(name, kEcmlCardVerification, false) || + StartsWith(name, kEcmlCardExpireMonth, false) || + StartsWith(name, kEcmlCardExpireYear, false))) { + return true; + } + } + return false; +} diff --git a/chrome/browser/autofill/form_field.h b/chrome/browser/autofill/form_field.h new file mode 100644 index 0000000..72fbb22 --- /dev/null +++ b/chrome/browser/autofill/form_field.h @@ -0,0 +1,151 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_AUTOFILL_FORM_FIELD_H_ +#define CHROME_BROWSER_AUTOFILL_FORM_FIELD_H_ + +#include <vector> + +#include "base/string16.h" +#include "base/string_util.h" +#include "chrome/browser/autofill/autofill_type.h" +#include "chrome/browser/autofill/form_structure.h" + +// Field names from the ECML specification; see RFC 3106. We've +// made these names lowercase since we convert labels and field names to +// lowercase before searching. + +// shipping name/address fields +static string16 kEcmlShipToTitle = ASCIIToUTF16("ecom_shipto_postal_name_prefix"); +static string16 kEcmlShipToFirstName = ASCIIToUTF16("ecom_shipto_postal_name_first"); +static string16 kEcmlShipToMiddleName = ASCIIToUTF16("ecom_shipto_postal_name_middle"); +static string16 kEcmlShipToLastName = ASCIIToUTF16("ecom_shipto_postal_name_last"); +static string16 kEcmlShipToNameSuffix = ASCIIToUTF16("ecom_shipto_postal_name_suffix"); +static string16 kEcmlShipToCompanyName = ASCIIToUTF16("ecom_shipto_postal_company"); +static string16 kEcmlShipToAddress1 = ASCIIToUTF16("ecom_shipto_postal_street_line1"); +static string16 kEcmlShipToAddress2 = ASCIIToUTF16("ecom_shipto_postal_street_line2"); +static string16 kEcmlShipToAddress3 = ASCIIToUTF16("ecom_shipto_postal_street_line3"); +static string16 kEcmlShipToCity = ASCIIToUTF16("ecom_shipto_postal_city"); +static string16 kEcmlShipToStateProv = ASCIIToUTF16("ecom_shipto_postal_stateprov"); +static string16 kEcmlShipToPostalCode = ASCIIToUTF16("ecom_shipto_postal_postalcode"); +static string16 kEcmlShipToCountry = ASCIIToUTF16("ecom_shipto_postal_countrycode"); +static string16 kEcmlShipToPhone = ASCIIToUTF16("ecom_shipto_telecom_phone_number"); +static string16 kEcmlShipToEmail = ASCIIToUTF16("ecom_shipto_online_email"); + + // billing name/address fields +static string16 kEcmlBillToTitle = ASCIIToUTF16("ecom_billto_postal_name_prefix"); +static string16 kEcmlBillToFirstName = ASCIIToUTF16("ecom_billto_postal_name_first"); +static string16 kEcmlBillToMiddleName = ASCIIToUTF16("ecom_billto_postal_name_middle"); +static string16 kEcmlBillToLastName = ASCIIToUTF16("ecom_billto_postal_name_last"); +static string16 kEcmlBillToNameSuffix = ASCIIToUTF16("ecom_billto_postal_name_suffix"); +static string16 kEcmlBillToCompanyName = ASCIIToUTF16("ecom_billto_postal_company"); +static string16 kEcmlBillToAddress1 = ASCIIToUTF16("ecom_billto_postal_street_line1"); +static string16 kEcmlBillToAddress2 = ASCIIToUTF16("ecom_billto_postal_street_line2"); +static string16 kEcmlBillToAddress3 = ASCIIToUTF16("ecom_billto_postal_street_line3"); +static string16 kEcmlBillToCity = ASCIIToUTF16("ecom_billto_postal_city"); +static string16 kEcmlBillToStateProv = ASCIIToUTF16("ecom_billto_postal_stateprov"); +static string16 kEcmlBillToPostalCode = ASCIIToUTF16("ecom_billto_postal_postalcode"); +static string16 kEcmlBillToCountry = ASCIIToUTF16("ecom_billto_postal_countrycode"); +static string16 kEcmlBillToPhone = ASCIIToUTF16("ecom_billto_telecom_phone_number"); +static string16 kEcmlBillToEmail = ASCIIToUTF16("ecom_billto_online_email"); + + // credit card fields +static string16 kEcmlCardHolder = ASCIIToUTF16("ecom_payment_card_name"); +static string16 kEcmlCardType = ASCIIToUTF16("ecom_payment_card_type"); +static string16 kEcmlCardNumber = ASCIIToUTF16("ecom_payment_card_number"); +static string16 kEcmlCardVerification = ASCIIToUTF16("ecom_payment_card_verification"); +static string16 kEcmlCardExpireDay = ASCIIToUTF16("ecom_payment_card_expdate_day"); +static string16 kEcmlCardExpireMonth = ASCIIToUTF16("ecom_payment_card_expdate_month"); +static string16 kEcmlCardExpireYear = ASCIIToUTF16("ecom_payment_card_expdate_year"); + +enum FormFieldType { + kAddressType, + kCreditCardType, + kOtherFieldType +}; + +class AutoFillField; + +// Represents a logical form field in a web form. Classes that implement this +// interface can identify themselves as a particular type of form field, e.g. +// name, phone number, or address field. +class FormField { + public: + virtual ~FormField() {} + + // Associates the available AutoFillTypes of a FormField into + // |field_type_map|. + virtual bool GetFieldInfo(FieldTypeMap* field_type_map) const = 0; + + // Returns the type of form field of the class implementing this interface. + virtual FormFieldType GetFormFieldType() const { return kOtherFieldType; } + + // TODO(jhawkins): I'm pretty sure this is not necessary in AutoFill++ because + // we use a static dialog setup. + virtual int priority() const = 0; + + // Returns true if |field| contains the regexp |pattern| in the name or label. + static bool Match(AutoFillField* field, const string16& pattern); + + // Parses a field using the different field views we know about. |is_ecml| + // should be true when the field conforms to the ECML specification. + static FormField* ParseFormField( + std::vector<AutoFillField*>::const_iterator* field, + bool is_ecml); + + // Attempts to parse a text field with the given pattern; returns true on + // success, but doesn't return the actual text field itself. + static bool ParseText(std::vector<AutoFillField*>::const_iterator* iter, + const string16& pattern); + + // Attempts to parse a text field with the given pattern. Returns true on + // success and fills |dest| with a pointer to the field. + static bool ParseText(std::vector<AutoFillField*>::const_iterator* iter, + const string16& pattern, + AutoFillField** dest); + + // Attempts to parse a control with an empty label. + static bool ParseEmpty(std::vector<AutoFillField*>::const_iterator* iter); + + // Adds an association between a field and a type to |field_type_map|. + static bool Add(FieldTypeMap* field_type_map, AutoFillField* field, + const AutoFillType& type); + + protected: + // Note: ECML compliance checking has been modified to accommodate Google + // Checkout field name limitation. All ECML compliant web forms will be + // recognized correctly as such however the restrictions on having exactly + // ECML compliant names have been loosened to only require that field names + // be prefixed with an ECML compiant name in order to accommodate checkout. + // Additionally we allow the use of '.' as a word delimiter in addition to the + // ECML standard '_' (see FormField::FormField for details). + static string16 GetEcmlPattern(const string16& ecml_name); + static string16 GetEcmlPattern(const string16& ecml_name1, + const string16& ecml_name2, + string16::value_type pattern_operator); +}; + +class FormFieldSet : public std::vector<FormField*> { + public: + explicit FormFieldSet(FormStructure* form); + + class FormFieldSorter { + public: + bool operator() (FormField *v1, FormField *v2) { + return v1->priority() < v2->priority(); + } + }; + + ~FormFieldSet() { + for (iterator i = begin(); i != end(); ++i) + delete *i; + } + + private: + // Checks if any of the labels are named according to the ECML standard. + // Returns true if at least one ECML named element is found. + bool CheckECML(FormStructure* fields); +}; + +#endif // CHROME_BROWSER_AUTOFILL_FORM_FIELD_H_ diff --git a/chrome/browser/autofill/form_structure.cc b/chrome/browser/autofill/form_structure.cc index 354a36c..ab4ac14 100644 --- a/chrome/browser/autofill/form_structure.cc +++ b/chrome/browser/autofill/form_structure.cc @@ -10,6 +10,7 @@ #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "chrome/browser/autofill/field_types.h" +#include "chrome/browser/autofill/form_field.h" #include "third_party/libjingle/files/talk/xmllite/xmlelement.h" #include "webkit/glue/form_field.h" #include "webkit/glue/form_field_values.h" @@ -56,9 +57,14 @@ FormStructure::FormStructure(const webkit_glue::FormFieldValues& values) std::vector<webkit_glue::FormField>::const_iterator field; for (field = values.elements.begin(); field != values.elements.end(); field++) { - fields_.push_back(AutoFillField(*field)); + // Generate a unique name for this field by appending a counter to the name. + string16 unique_name = field->name() + IntToString16(fields_.size() + 1); + fields_.push_back(new AutoFillField(*field, unique_name)); } + // Terminate the vector with a NULL item. + fields_.push_back(NULL); + std::string method = UTF16ToUTF8(values.method); if (method == kFormMethodPost) { method_ = POST; @@ -96,8 +102,8 @@ bool FormStructure::EncodeUploadRequest(bool auto_fill_used, autofill_upload.SetAttr(buzz::QName(kAttributeDataPresent), ""); // Add the child nodes for the form fields. - std::vector<AutoFillField>::const_iterator field; - for (field = fields_.begin(); field != fields_.end(); field++) { + for (size_t index = 0; index < field_count(); index++) { + const AutoFillField* field = fields_[index]; FieldTypeSet types = field->possible_types(); for (FieldTypeSet::const_iterator type = types.begin(); type != types.end(); type++) { @@ -121,6 +127,33 @@ bool FormStructure::EncodeUploadRequest(bool auto_fill_used, return true; } +void FormStructure::GetHeuristicAutoFillTypes() { + has_credit_card_field_ = false; + has_autofillable_field_ = false; + + FieldTypeMap field_type_map; + GetHeuristicFieldInfo(&field_type_map); + + for (size_t index = 0; index < field_count(); index++) { + AutoFillField* field = fields_[index]; + FieldTypeMap::iterator iter = field_type_map.find(field->unique_name()); + + AutoFillFieldType heuristic_auto_fill_type; + if (iter == field_type_map.end()) + heuristic_auto_fill_type = UNKNOWN_TYPE; + else + heuristic_auto_fill_type = iter->second; + + field->set_heuristic_type(heuristic_auto_fill_type); + + AutoFillType autofill_type(field->type()); + if (autofill_type.group() == AutoFillType::CREDIT_CARD) + has_credit_card_field_ = true; + if (autofill_type.field_type() != UNKNOWN_TYPE) + has_autofillable_field_ = true; + } +} + std::string FormStructure::FormSignature() const { std::string form_string = target_url_.host() + "&" + @@ -142,7 +175,7 @@ bool FormStructure::IsAutoFillable() const { // Disqualify all forms that are likely to be search boxes (like google.com). if (fields_.size() == 1) { - std::string name = UTF16ToUTF8(fields_[0].name()); + std::string name = UTF16ToUTF8(fields_[0]->name()); if (name == "q") return false; } @@ -152,3 +185,29 @@ bool FormStructure::IsAutoFillable() const { return true; } + +void FormStructure::set_possible_types(int index, const FieldTypeSet& types) { + int num_fields = static_cast<int>(fields_.size()); + DCHECK(index >= 0 && index < num_fields); + if (index >= 0 && index < num_fields) + fields_[index]->set_possible_types(types); +} + +AutoFillField* FormStructure::field(int index) { + return fields_[index]; +} + +size_t FormStructure::field_count() const { + // Don't count the NULL terminator. + return fields_.size() - 1; +} + +void FormStructure::GetHeuristicFieldInfo(FieldTypeMap* field_type_map) { + FormFieldSet fields = FormFieldSet(this); + + FormFieldSet::const_iterator field; + for (field = fields.begin(); field != fields.end(); field++) { + bool ok = (*field)->GetFieldInfo(field_type_map); + DCHECK(ok); + } +} diff --git a/chrome/browser/autofill/form_structure.h b/chrome/browser/autofill/form_structure.h index c0d178d9..5892941 100644 --- a/chrome/browser/autofill/form_structure.h +++ b/chrome/browser/autofill/form_structure.h @@ -8,8 +8,10 @@ #include <string> #include <vector> -#include "base/scoped_ptr.h" +#include "base/scoped_vector.h" #include "chrome/browser/autofill/autofill_field.h" +#include "chrome/browser/autofill/autofill_type.h" +#include "chrome/browser/autofill/field_types.h" #include "googleurl/src/gurl.h" namespace webkit_glue { @@ -30,6 +32,10 @@ class FormStructure { // Encodes the XML upload request from this FormStructure. bool EncodeUploadRequest(bool auto_fill_used, std::string* encoded_xml) const; + // Runs several heuristics against the form fields to determine their possible + // types. + void GetHeuristicAutoFillTypes(); + // The unique signature for this form, composed of the target url domain, // the form name, and the form field names in a 64-bit hash. std::string FormSignature() const; @@ -38,7 +44,24 @@ class FormStructure { // like google/yahoo/msn search, etc. bool IsAutoFillable() const; + // Sets the possible types for the field at |index|. + void set_possible_types(int index, const FieldTypeSet& types); + + AutoFillField* field(int index); + size_t field_count() const; + + // Used for iterating over the fields. + std::vector<AutoFillField*>::const_iterator begin() const { + return fields_.begin(); + } + std::vector<AutoFillField*>::const_iterator end() const { + return fields_.end(); + } + private: + // Associates the field with the heuristic type for each of the field views. + void GetHeuristicFieldInfo(FieldTypeMap* field_types_map); + // The name of the form. std::string form_name_; @@ -48,8 +71,13 @@ class FormStructure { // The target URL. GURL target_url_; - // A vector of all the input fields in the form. - std::vector<AutoFillField> fields_; + bool has_credit_card_field_; + bool has_autofillable_field_; + bool has_password_fields_; + + // A vector of all the input fields in the form. The vector is terminated by + // a NULL entry. + ScopedVector<AutoFillField> fields_; // The names of the form input elements, that are part of the form signature. // The string starts with "&" and the names are also separated by the "&" diff --git a/chrome/browser/autofill/personal_data_manager.cc b/chrome/browser/autofill/personal_data_manager.cc index 8333c699..ca204636 100644 --- a/chrome/browser/autofill/personal_data_manager.cc +++ b/chrome/browser/autofill/personal_data_manager.cc @@ -16,5 +16,9 @@ bool PersonalDataManager::ImportFormData( return true; } +void PersonalDataManager::GetPossibleFieldTypes(const string16& text, + FieldTypeSet* possible_types) { +} + PersonalDataManager::PersonalDataManager() { } diff --git a/chrome/browser/autofill/personal_data_manager.h b/chrome/browser/autofill/personal_data_manager.h index f8a7b01..1d27f16 100644 --- a/chrome/browser/autofill/personal_data_manager.h +++ b/chrome/browser/autofill/personal_data_manager.h @@ -7,6 +7,9 @@ #include <vector> +#include "base/string16.h" +#include "chrome/browser/autofill/field_types.h" + class AutoFillManager; class FormStructure; @@ -22,9 +25,13 @@ class PersonalDataManager { // has not previously been prompted, the user will be asked if he would like // to import the data. If the user selects yes, a profile will be created // with all of the information from recognized fields. - virtual bool ImportFormData( - const std::vector<FormStructure*>& form_structures, - AutoFillManager* autofill_manager); + bool ImportFormData(const std::vector<FormStructure*>& form_structures, + AutoFillManager* autofill_manager); + + // Gets the possible field types for the given text, determined by matching + // the text with all known personal information and returning matching types. + void GetPossibleFieldTypes(const string16& text, + FieldTypeSet* possible_types); private: // Make sure that only Profile can create an instance of PersonalDataManager. diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 805bbfe..240574d 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -87,6 +87,8 @@ 'browser/autofill/autofill_type.cc', 'browser/autofill/autofill_type.h', 'browser/autofill/field_types.h', + 'browser/autofill/form_field.cc', + 'browser/autofill/form_field.h', 'browser/autofill/form_structure.cc', 'browser/autofill/form_structure.h', 'browser/autofill/personal_data_manager.cc', |