Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4728)

Unified Diff: chrome/browser/autofill/form_structure.cc

Issue 7613015: Add preliminary Autofill support for 'autocompletetype' sections. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Precompute credit card vs. address sections Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/autofill/form_structure.cc
diff --git a/chrome/browser/autofill/form_structure.cc b/chrome/browser/autofill/form_structure.cc
index b9e0a2eb23036dfb385429681362bb3c786c7ada..076e3c415a1eed0c567199075e91b3cd201c95bf 100644
--- a/chrome/browser/autofill/form_structure.cc
+++ b/chrome/browser/autofill/form_structure.cc
@@ -221,43 +221,13 @@ bool ConvertToAutofillFieldType(const AutofillField& field,
if (autocomplete_type == ASCIIToUTF16("cc-exp")) {
// TODO(isherman): Choose variant based on HTML5 validation regex.
- *autofill_type = CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR;
+ *autofill_type = CREDIT_CARD_EXP_DATE_4_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)
@@ -296,31 +266,39 @@ FormStructure::FormStructure(const FormData& form)
FormStructure::~FormStructure() {}
void FormStructure::DetermineHeuristicTypes() {
- autofill_count_ = 0;
-
- FieldTypeMap 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);
+ bool found_sections;
+ ParseAutocompletetypeAttributes(&has_author_specified_types_,
+ &found_sections);
- 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_autofill_type;
- if (iter == field_type_map.end()) {
- heuristic_autofill_type = UNKNOWN_TYPE;
- } else {
- heuristic_autofill_type = iter->second;
- ++autofill_count_;
+ if (!has_author_specified_types_) {
+ FieldTypeMap field_type_map;
+ FormField::ParseFormFields(fields_.get(), &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());
+ if (iter != field_type_map.end())
+ field->set_heuristic_type(iter->second);
}
+ }
+
+ UpdateAutofillCount();
- field->set_heuristic_type(heuristic_autofill_type);
+ if (!found_sections)
+ IdentifySections();
+
+ // Ensure that credit card and address fields are in separate sections.
+ // This simplifies the section-aware logic in autofill_manager.cc.
+ for (std::vector<AutofillField*>::iterator field = fields_->begin();
+ field != fields_->end(); ++field) {
+ AutofillType::FieldTypeGroup field_type_group =
+ AutofillType((*field)->type()).group();
+ if (field_type_group == AutofillType::CREDIT_CARD)
+ (*field)->set_section((*field)->section() + ASCIIToUTF16("-cc"));
+ else
+ (*field)->set_section((*field)->section() + ASCIIToUTF16("-default"));
}
}
@@ -852,3 +830,86 @@ bool FormStructure::EncodeFormRequest(
}
return true;
}
+
+void FormStructure::ParseAutocompletetypeAttributes(bool* found_attribute,
+ bool* found_sections) {
+ *found_attribute = false;
+ *found_sections = false;
+ for (std::vector<AutofillField*>::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);
+
+ // Look for a named section.
+ const string16 kSectionPrefix = ASCIIToUTF16("section-");
+ if (!types.empty() && StartsWith(types.front(), kSectionPrefix, true)) {
+ *found_sections = true;
+ (*field)->set_section(types.front().substr(kSectionPrefix.size()));
+ }
+
+ // Look for specified types.
+ for (std::vector<string16>::const_iterator type = types.begin();
+ type != types.end(); ++type) {
+ AutofillFieldType autofill_type = UNKNOWN_TYPE;
+ if (ConvertToAutofillFieldType(**field, *type, &autofill_type)) {
+ (*field)->set_heuristic_type(autofill_type);
+ break;
+ }
+ }
+ }
+}
+
+void FormStructure::IdentifySections() {
+ if (fields_.empty())
+ return;
+
+ // Name sections after the first field in the section.
+ string16 current_section = fields_->front()->unique_name();
+
+ // Keep track of the types we've seen in this section.
+ std::set<AutofillFieldType> seen_types;
+ AutofillFieldType previous_type = UNKNOWN_TYPE;
+
+ for (std::vector<AutofillField*>::iterator field = fields_->begin();
+ field != fields_->end(); ++field) {
+ const AutofillFieldType current_type =
+ AutofillType::GetEquivalentFieldType((*field)->type());
+
+ bool already_saw_current_type = seen_types.count(current_type) > 0;
+
+ // Forms often ask for multiple phone numbers -- e.g. both a daytime and
+ // evening phone number. Our phone and fax number detection is also
+ // generally a little off. Hence, ignore both field types as a signal here.
+ AutofillType::FieldTypeGroup current_type_group =
+ AutofillType(current_type).group();
+ if (current_type_group == AutofillType::PHONE_HOME ||
+ current_type_group == AutofillType::PHONE_FAX)
+ already_saw_current_type = false;
+
+ // Some forms have adjacent fields of the same type. Two common examples:
+ // * Forms with two email fields, where the second is meant to "confirm"
+ // the first.
+ // * Forms with a <select> menu for states in some countries, and a
+ // freeform <input> field for states in other countries. (Usually, only
+ // one of these two will be visible for any given choice of country.)
+ // Generally, adjacent fields of the same type belong in the same logical
+ // section.
+ if (current_type == previous_type)
+ already_saw_current_type = false;
+
+ previous_type = current_type;
+
+ if (current_type != UNKNOWN_TYPE && already_saw_current_type) {
+ // We reached the end of a section, so start a new section.
+ seen_types.clear();
+ current_section = (*field)->unique_name();
+ }
+
+ seen_types.insert(current_type);
+ (*field)->set_section(current_section);
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698