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

Side by Side Diff: components/autofill/core/browser/form_structure.cc

Issue 1411363003: [Autofill] Always show available data when encountering autocomplete attributes (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 5 years, 1 month 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 unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/autofill/core/browser/form_structure.h" 5 #include "components/autofill/core/browser/form_structure.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 } // namespace 384 } // namespace
385 385
386 FormStructure::FormStructure(const FormData& form) 386 FormStructure::FormStructure(const FormData& form)
387 : form_name_(form.name), 387 : form_name_(form.name),
388 source_url_(form.origin), 388 source_url_(form.origin),
389 target_url_(form.action), 389 target_url_(form.action),
390 autofill_count_(0), 390 autofill_count_(0),
391 active_field_count_(0), 391 active_field_count_(0),
392 upload_required_(USE_UPLOAD_RATES), 392 upload_required_(USE_UPLOAD_RATES),
393 has_author_specified_types_(false), 393 has_author_specified_types_(false),
394 has_author_specified_sections_(false),
395 was_parsed_for_autocomplete_attributes_(false),
394 has_password_field_(false), 396 has_password_field_(false),
395 is_form_tag_(form.is_form_tag) { 397 is_form_tag_(form.is_form_tag) {
396 // Copy the form fields. 398 // Copy the form fields.
397 std::map<base::string16, size_t> unique_names; 399 std::map<base::string16, size_t> unique_names;
398 for (const FormFieldData& field : form.fields) { 400 for (const FormFieldData& field : form.fields) {
399 if (!ShouldSkipField(field)) { 401 if (!ShouldSkipField(field)) {
400 // Add all supported form fields (including with empty names) to the 402 // Add all supported form fields (including with empty names) to the
401 // signature. This is a requirement for Autofill servers. 403 // signature. This is a requirement for Autofill servers.
402 form_signature_field_names_.append("&"); 404 form_signature_field_names_.append("&");
403 form_signature_field_names_.append(StripDigitsIfRequired(field.name)); 405 form_signature_field_names_.append(StripDigitsIfRequired(field.name));
(...skipping 14 matching lines...) Expand all
418 } 420 }
419 } 421 }
420 422
421 FormStructure::~FormStructure() {} 423 FormStructure::~FormStructure() {}
422 424
423 void FormStructure::DetermineHeuristicTypes() { 425 void FormStructure::DetermineHeuristicTypes() {
424 // First, try to detect field types based on each field's |autocomplete| 426 // First, try to detect field types based on each field's |autocomplete|
425 // attribute value. If there is at least one form field that specifies an 427 // attribute value. If there is at least one form field that specifies an
426 // autocomplete type hint, don't try to apply other heuristics to match fields 428 // autocomplete type hint, don't try to apply other heuristics to match fields
427 // in this form. 429 // in this form.
428 bool has_author_specified_sections; 430 if (!was_parsed_for_autocomplete_attributes_)
429 ParseFieldTypesFromAutocompleteAttributes(&has_author_specified_types_, 431 ParseFieldTypesFromAutocompleteAttributes();
430 &has_author_specified_sections);
431 432
432 if (!has_author_specified_types_) { 433 if (!has_author_specified_types_) {
433 ServerFieldTypeMap field_type_map; 434 ServerFieldTypeMap field_type_map;
434 FormField::ParseFormFields(fields_.get(), is_form_tag_, &field_type_map); 435 FormField::ParseFormFields(fields_.get(), is_form_tag_, &field_type_map);
435 for (size_t i = 0; i < field_count(); ++i) { 436 for (size_t i = 0; i < field_count(); ++i) {
436 AutofillField* field = fields_[i]; 437 AutofillField* field = fields_[i];
437 ServerFieldTypeMap::iterator iter = 438 ServerFieldTypeMap::iterator iter =
438 field_type_map.find(field->unique_name()); 439 field_type_map.find(field->unique_name());
439 if (iter != field_type_map.end()) 440 if (iter != field_type_map.end())
440 field->set_heuristic_type(iter->second); 441 field->set_heuristic_type(iter->second);
441 } 442 }
442 } 443 }
443 444
444 UpdateAutofillCount(); 445 UpdateAutofillCount();
445 IdentifySections(has_author_specified_sections); 446 IdentifySections(has_author_specified_sections_);
446 447
447 if (IsAutofillable()) { 448 if (IsAutofillable()) {
448 AutofillMetrics::LogDeveloperEngagementMetric( 449 AutofillMetrics::LogDeveloperEngagementMetric(
449 AutofillMetrics::FILLABLE_FORM_PARSED); 450 AutofillMetrics::FILLABLE_FORM_PARSED);
450 if (has_author_specified_types_) { 451 if (has_author_specified_types_) {
451 AutofillMetrics::LogDeveloperEngagementMetric( 452 AutofillMetrics::LogDeveloperEngagementMetric(
452 AutofillMetrics::FILLABLE_FORM_CONTAINS_TYPE_HINTS); 453 AutofillMetrics::FILLABLE_FORM_CONTAINS_TYPE_HINTS);
453 } 454 }
454 } 455 }
455 } 456 }
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 736
736 void FormStructure::UpdateAutofillCount() { 737 void FormStructure::UpdateAutofillCount() {
737 autofill_count_ = 0; 738 autofill_count_ = 0;
738 for (const AutofillField* field : *this) { 739 for (const AutofillField* field : *this) {
739 if (field && field->IsFieldFillable()) 740 if (field && field->IsFieldFillable())
740 ++autofill_count_; 741 ++autofill_count_;
741 } 742 }
742 } 743 }
743 744
744 bool FormStructure::ShouldBeParsed() const { 745 bool FormStructure::ShouldBeParsed() const {
745 if (active_field_count() < kRequiredAutofillFields) 746 if (active_field_count() < kRequiredAutofillFields &&
747 !has_author_specified_types_)
Evan Stade 2015/11/04 17:15:19 curlies
sebsg 2015/11/10 19:04:51 Done.
746 return false; 748 return false;
747 749
748 // Rule out http(s)://*/search?... 750 // Rule out http(s)://*/search?...
749 // e.g. http://www.google.com/search?q=... 751 // e.g. http://www.google.com/search?q=...
750 // http://search.yahoo.com/search?p=... 752 // http://search.yahoo.com/search?p=...
751 if (target_url_.path() == "/search") 753 if (target_url_.path() == "/search")
752 return false; 754 return false;
753 755
754 bool has_text_field = false; 756 bool has_text_field = false;
755 for (const AutofillField* it : *this) { 757 for (const AutofillField* it : *this) {
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after
1065 EncodeFieldForQuery(*field, encompassing_xml_element); 1067 EncodeFieldForQuery(*field, encompassing_xml_element);
1066 break; 1068 break;
1067 case FormStructure::FIELD_ASSIGNMENTS: 1069 case FormStructure::FIELD_ASSIGNMENTS:
1068 EncodeFieldForFieldAssignments(*field, encompassing_xml_element); 1070 EncodeFieldForFieldAssignments(*field, encompassing_xml_element);
1069 break; 1071 break;
1070 } 1072 }
1071 } 1073 }
1072 return true; 1074 return true;
1073 } 1075 }
1074 1076
1075 void FormStructure::ParseFieldTypesFromAutocompleteAttributes( 1077 void FormStructure::ParseFieldTypesFromAutocompleteAttributes() {
1076 bool* found_types,
1077 bool* found_sections) {
1078 const std::string kDefaultSection = "-default"; 1078 const std::string kDefaultSection = "-default";
1079 1079
1080 *found_types = false; 1080 has_author_specified_types_ = false;
1081 *found_sections = false; 1081 has_author_specified_sections_ = false;
1082 for (AutofillField* field : fields_) { 1082 for (std::vector<AutofillField*>::iterator it = fields_.begin();
1083 it != fields_.end(); ++it) {
Evan Stade 2015/11/04 17:15:19 why did you change teh format of this loop
sebsg 2015/11/10 19:04:51 Bad merge on PS#4, good catch!
1084 AutofillField* field = *it;
1085
1083 // To prevent potential section name collisions, add a default suffix for 1086 // To prevent potential section name collisions, add a default suffix for
1084 // other fields. Without this, 'autocomplete' attribute values 1087 // other fields. Without this, 'autocomplete' attribute values
1085 // "section--shipping street-address" and "shipping street-address" would be 1088 // "section--shipping street-address" and "shipping street-address" would be
1086 // parsed identically, given the section handling code below. We do this 1089 // parsed identically, given the section handling code below. We do this
1087 // before any validation so that fields with invalid attributes still end up 1090 // before any validation so that fields with invalid attributes still end up
1088 // in the default section. These default section names will be overridden 1091 // in the default section. These default section names will be overridden
1089 // by subsequent heuristic parsing steps if there are no author-specified 1092 // by subsequent heuristic parsing steps if there are no author-specified
1090 // section names. 1093 // section names.
1091 field->set_section(kDefaultSection); 1094 field->set_section(kDefaultSection);
1092 1095
1093 // Canonicalize the attribute value by trimming whitespace, collapsing 1096 // Canonicalize the attribute value by trimming whitespace, collapsing
1094 // non-space characters (e.g. tab) to spaces, and converting to lowercase. 1097 // non-space characters (e.g. tab) to spaces, and converting to lowercase.
1095 std::string autocomplete_attribute = 1098 std::string autocomplete_attribute =
1096 base::CollapseWhitespaceASCII(field->autocomplete_attribute, false); 1099 base::CollapseWhitespaceASCII(field->autocomplete_attribute, false);
1097 autocomplete_attribute = base::ToLowerASCII(autocomplete_attribute); 1100 autocomplete_attribute = base::ToLowerASCII(autocomplete_attribute);
1098 1101
1099 // The autocomplete attribute is overloaded: it can specify either a field 1102 // The autocomplete attribute is overloaded: it can specify either a field
1100 // type hint or whether autocomplete should be enabled at all. Ignore the 1103 // type hint or whether autocomplete should be enabled at all. Ignore the
1101 // latter type of attribute value. 1104 // latter type of attribute value.
1102 if (autocomplete_attribute.empty() || 1105 if (autocomplete_attribute.empty() ||
1103 autocomplete_attribute == "on" || 1106 autocomplete_attribute == "on" ||
1104 autocomplete_attribute == "off") { 1107 autocomplete_attribute == "off") {
1105 continue; 1108 continue;
1106 } 1109 }
1107 1110
1108 // Any other value, even it is invalid, is considered to be a type hint. 1111 // Any other value, even it is invalid, is considered to be a type hint.
1109 // This allows a website's author to specify an attribute like 1112 // This allows a website's author to specify an attribute like
1110 // autocomplete="other" on a field to disable all Autofill heuristics for 1113 // autocomplete="other" on a field to disable all Autofill heuristics for
1111 // the form. 1114 // the form.
1112 *found_types = true; 1115 has_author_specified_types_ = true;
1113 1116
1114 // Tokenize the attribute value. Per the spec, the tokens are parsed in 1117 // Tokenize the attribute value. Per the spec, the tokens are parsed in
1115 // reverse order. 1118 // reverse order.
1116 std::vector<std::string> tokens = base::SplitString( 1119 std::vector<std::string> tokens = base::SplitString(
1117 autocomplete_attribute, " ", base::KEEP_WHITESPACE, 1120 autocomplete_attribute, " ", base::KEEP_WHITESPACE,
1118 base::SPLIT_WANT_NONEMPTY); 1121 base::SPLIT_WANT_NONEMPTY);
1119 1122
1120 // The final token must be the field type. 1123 // The final token must be the field type.
1121 // If it is not one of the known types, abort. 1124 // If it is not one of the known types, abort.
1122 DCHECK(!tokens.empty()); 1125 DCHECK(!tokens.empty());
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1165 // Prepend this section name to the suffix set in the preceding block. 1168 // Prepend this section name to the suffix set in the preceding block.
1166 section = tokens.back().substr(kSectionPrefix.size()) + section; 1169 section = tokens.back().substr(kSectionPrefix.size()) + section;
1167 tokens.pop_back(); 1170 tokens.pop_back();
1168 } 1171 }
1169 1172
1170 // No other tokens are allowed. If there are any remaining, abort. 1173 // No other tokens are allowed. If there are any remaining, abort.
1171 if (!tokens.empty()) 1174 if (!tokens.empty())
1172 continue; 1175 continue;
1173 1176
1174 if (section != kDefaultSection) { 1177 if (section != kDefaultSection) {
1175 *found_sections = true; 1178 has_author_specified_sections_ = true;
1176 field->set_section(section); 1179 field->set_section(section);
1177 } 1180 }
1178 1181
1179 // No errors encountered while parsing! 1182 // No errors encountered while parsing!
1180 // Update the |field|'s type based on what was parsed from the attribute. 1183 // Update the |field|'s type based on what was parsed from the attribute.
1181 field->SetHtmlType(field_type, mode); 1184 field->SetHtmlType(field_type, mode);
1182 } 1185 }
1186
1187 was_parsed_for_autocomplete_attributes_ = true;
1183 } 1188 }
1184 1189
1185 bool FormStructure::FillFields( 1190 bool FormStructure::FillFields(
1186 const std::vector<ServerFieldType>& types, 1191 const std::vector<ServerFieldType>& types,
1187 const InputFieldComparator& matches, 1192 const InputFieldComparator& matches,
1188 const base::Callback<base::string16(const AutofillType&)>& get_info, 1193 const base::Callback<base::string16(const AutofillType&)>& get_info,
1189 const std::string& address_language_code, 1194 const std::string& address_language_code,
1190 const std::string& app_locale) { 1195 const std::string& app_locale) {
1191 bool filled_something = false; 1196 bool filled_something = false;
1192 for (size_t i = 0; i < field_count(); ++i) { 1197 for (size_t i = 0; i < field_count(); ++i) {
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
1321 for (AutofillField* field : fields_) { 1326 for (AutofillField* field : fields_) {
1322 FieldTypeGroup field_type_group = field->Type().group(); 1327 FieldTypeGroup field_type_group = field->Type().group();
1323 if (field_type_group == CREDIT_CARD) 1328 if (field_type_group == CREDIT_CARD)
1324 field->set_section(field->section() + "-cc"); 1329 field->set_section(field->section() + "-cc");
1325 else 1330 else
1326 field->set_section(field->section() + "-default"); 1331 field->set_section(field->section() + "-default");
1327 } 1332 }
1328 } 1333 }
1329 1334
1330 } // namespace autofill 1335 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698