| Index: chrome/browser/autofill/form_structure.cc
|
| diff --git a/chrome/browser/autofill/form_structure.cc b/chrome/browser/autofill/form_structure.cc
|
| index 3f2eb001b12d06efcc9ea019efd8dad94cb42455..b9e0a2eb23036dfb385429681362bb3c786c7ada 100644
|
| --- a/chrome/browser/autofill/form_structure.cc
|
| +++ b/chrome/browser/autofill/form_structure.cc
|
| @@ -4,6 +4,8 @@
|
|
|
| #include "chrome/browser/autofill/form_structure.h"
|
|
|
| +#include <utility>
|
| +
|
| #include "base/basictypes.h"
|
| #include "base/logging.h"
|
| #include "base/sha1.h"
|
| @@ -85,6 +87,177 @@ std::string EncodeFieldTypes(const FieldTypeSet& available_field_types) {
|
| return data_presence;
|
| }
|
|
|
| +bool ConvertToAutofillFieldType(const AutofillField& field,
|
| + const string16& autocomplete_type,
|
| + AutofillFieldType* autofill_type) {
|
| + if (autocomplete_type == ASCIIToUTF16("given-name")) {
|
| + *autofill_type = NAME_FIRST;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("middle-name")) {
|
| + *autofill_type = NAME_MIDDLE;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("middle-initial")) {
|
| + *autofill_type = NAME_MIDDLE_INITIAL;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("surname")) {
|
| + *autofill_type = NAME_LAST;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("full-name")) {
|
| + *autofill_type = NAME_FULL;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("street-address") ||
|
| + autocomplete_type == ASCIIToUTF16("address-line1")) {
|
| + *autofill_type = ADDRESS_HOME_LINE1;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("address-line2")) {
|
| + *autofill_type = ADDRESS_HOME_LINE2;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("locality")) {
|
| + *autofill_type = ADDRESS_HOME_CITY;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("administrative-area")) {
|
| + *autofill_type = ADDRESS_HOME_STATE;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("postal-code")) {
|
| + *autofill_type = ADDRESS_HOME_ZIP;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("country")) {
|
| + *autofill_type = ADDRESS_HOME_COUNTRY;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("organization")) {
|
| + *autofill_type = COMPANY_NAME;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("email")) {
|
| + *autofill_type = EMAIL_ADDRESS;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("phone-full")) {
|
| + *autofill_type = PHONE_HOME_WHOLE_NUMBER;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("phone-country-code")) {
|
| + *autofill_type = PHONE_HOME_COUNTRY_CODE;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("phone-city-code")) {
|
| + *autofill_type = PHONE_HOME_CITY_CODE;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("phone-number")) {
|
| + *autofill_type = PHONE_HOME_NUMBER;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("fax-full")) {
|
| + *autofill_type = PHONE_FAX_WHOLE_NUMBER;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("fax-country-code")) {
|
| + *autofill_type = PHONE_FAX_COUNTRY_CODE;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("fax-city-code")) {
|
| + *autofill_type = PHONE_FAX_CITY_CODE;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("fax-number")) {
|
| + *autofill_type = PHONE_FAX_NUMBER;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("cc-full-name")) {
|
| + *autofill_type = CREDIT_CARD_NAME;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("cc-number")) {
|
| + *autofill_type = CREDIT_CARD_NUMBER;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("cc-exp-month")) {
|
| + *autofill_type = CREDIT_CARD_EXP_MONTH;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("cc-exp-year")) {
|
| + if (field.max_length == 2)
|
| + *autofill_type = CREDIT_CARD_EXP_2_DIGIT_YEAR;
|
| + else
|
| + *autofill_type = CREDIT_CARD_EXP_4_DIGIT_YEAR;
|
| + return true;
|
| + }
|
| +
|
| + if (autocomplete_type == ASCIIToUTF16("cc-exp")) {
|
| + // TODO(isherman): Choose variant based on HTML5 validation regex.
|
| + *autofill_type = CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR;
|
| + return true;
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| +// Classifies each field in |fields| based upon its |autocompletetype|
|
| +// attribute, if the attribute is available. The association is stored into
|
| +// |map|. Returns |true| if the attribute is available (and non-empty) for at
|
| +// least one field.
|
| +bool ParseAutocompletetypeAttributes(const std::vector<AutofillField*>& fields,
|
| + FieldTypeMap* map) {
|
| + bool found_attribute = false;
|
| + for (std::vector<AutofillField*>::const_iterator field = fields.begin();
|
| + field != fields.end(); ++field) {
|
| + if ((*field)->autocomplete_type.empty())
|
| + continue;
|
| +
|
| + found_attribute = true;
|
| + std::vector<string16> types;
|
| + Tokenize((*field)->autocomplete_type, ASCIIToUTF16(" "), &types);
|
| +
|
| + // TODO(isherman): Handle sections: http://crbug.com/92121
|
| + for (std::vector<string16>::const_iterator type = types.begin();
|
| + type != types.end(); ++type) {
|
| + AutofillFieldType autofill_type = UNKNOWN_TYPE;
|
| + if (ConvertToAutofillFieldType(**field, *type, &autofill_type)) {
|
| + map->insert(make_pair((*field)->unique_name(), autofill_type));
|
| + break;
|
| + }
|
| + }
|
| + }
|
| +
|
| + return found_attribute;
|
| +}
|
| +
|
| } // namespace
|
|
|
| FormStructure::FormStructure(const FormData& form)
|
| @@ -93,7 +266,8 @@ FormStructure::FormStructure(const FormData& form)
|
| target_url_(form.action),
|
| autofill_count_(0),
|
| upload_required_(USE_UPLOAD_RATES),
|
| - server_experiment_id_("no server response") {
|
| + server_experiment_id_("no server response"),
|
| + has_author_specified_types_(false) {
|
| // Copy the form fields.
|
| std::vector<webkit_glue::FormField>::const_iterator field;
|
| for (field = form.fields.begin();
|
| @@ -125,7 +299,14 @@ void FormStructure::DetermineHeuristicTypes() {
|
| autofill_count_ = 0;
|
|
|
| FieldTypeMap field_type_map;
|
| - FormField::ParseFormFields(fields_.get(), &field_type_map);
|
| +
|
| + // First, try to detect field types based on the fields' |autocompletetype|
|
| + // attributes. If there is at least one form field with this attribute, don't
|
| + // try to apply other heuristics to match fields in this form.
|
| + has_author_specified_types_ =
|
| + ParseAutocompletetypeAttributes(fields_.get(), &field_type_map);
|
| + if (!has_author_specified_types_)
|
| + FormField::ParseFormFields(fields_.get(), &field_type_map);
|
|
|
| for (size_t index = 0; index < field_count(); index++) {
|
| AutofillField* field = fields_[index];
|
| @@ -140,8 +321,6 @@ void FormStructure::DetermineHeuristicTypes() {
|
| }
|
|
|
| field->set_heuristic_type(heuristic_autofill_type);
|
| -
|
| - AutofillType autofill_type(field->type());
|
| }
|
| }
|
|
|
| @@ -149,8 +328,8 @@ bool FormStructure::EncodeUploadRequest(
|
| const FieldTypeSet& available_field_types,
|
| bool form_was_autofilled,
|
| std::string* encoded_xml) const {
|
| - if (!ShouldBeParsed(true)) {
|
| - NOTREACHED(); // Caller should've checked for search pages.
|
| + if (!ShouldBeCrowdsourced()) {
|
| + NOTREACHED();
|
| return false;
|
| }
|
|
|
| @@ -403,6 +582,10 @@ bool FormStructure::ShouldBeParsed(bool require_method_post) const {
|
| return !require_method_post || (method_ == POST);
|
| }
|
|
|
| +bool FormStructure::ShouldBeCrowdsourced() const {
|
| + return !has_author_specified_types_ && ShouldBeParsed(true);
|
| +}
|
| +
|
| void FormStructure::UpdateFromCache(const FormStructure& cached_form) {
|
| // Map from field signatures to cached fields.
|
| std::map<std::string, const AutofillField*> cached_fields;
|
|
|