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

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: Addressed comments 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 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
720 form_signature_field_names_; 721 form_signature_field_names_;
721 722
722 return Hash64Bit(form_string); 723 return Hash64Bit(form_string);
723 } 724 }
724 725
725 bool FormStructure::ShouldSkipField(const FormFieldData& field) const { 726 bool FormStructure::ShouldSkipField(const FormFieldData& field) const {
726 return field.is_checkable; 727 return field.is_checkable;
727 } 728 }
728 729
729 bool FormStructure::IsAutofillable() const { 730 bool FormStructure::IsAutofillable() const {
730 if (autofill_count() < kRequiredAutofillFields) 731 if (autofill_count() < kRequiredFieldsForPredictionRoutines)
731 return false; 732 return false;
732 733
733 return ShouldBeParsed(); 734 return ShouldBeParsed();
734 } 735 }
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() < kRequiredFieldsForPredictionRoutines &&
747 !has_author_specified_types_) {
746 return false; 748 return false;
749 }
747 750
748 // Rule out http(s)://*/search?... 751 // Rule out http(s)://*/search?...
749 // e.g. http://www.google.com/search?q=... 752 // e.g. http://www.google.com/search?q=...
750 // http://search.yahoo.com/search?p=... 753 // http://search.yahoo.com/search?p=...
751 if (target_url_.path() == "/search") 754 if (target_url_.path() == "/search")
752 return false; 755 return false;
753 756
754 bool has_text_field = false; 757 bool has_text_field = false;
755 for (const AutofillField* it : *this) { 758 for (const AutofillField* it : *this) {
756 has_text_field |= it->form_control_type != "select-one"; 759 has_text_field |= it->form_control_type != "select-one";
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
904 field_type); 907 field_type);
905 } else { 908 } else {
906 AutofillMetrics::LogOverallTypePrediction(AutofillMetrics::TYPE_MISMATCH, 909 AutofillMetrics::LogOverallTypePrediction(AutofillMetrics::TYPE_MISMATCH,
907 field_type); 910 field_type);
908 } 911 }
909 } 912 }
910 913
911 AutofillMetrics::LogNumberOfEditedAutofilledFieldsAtSubmission( 914 AutofillMetrics::LogNumberOfEditedAutofilledFieldsAtSubmission(
912 num_edited_autofilled_fields); 915 num_edited_autofilled_fields);
913 916
914 if (num_detected_field_types < kRequiredAutofillFields) { 917 if (num_detected_field_types < kRequiredFieldsForPredictionRoutines) {
915 AutofillMetrics::LogUserHappinessMetric( 918 AutofillMetrics::LogUserHappinessMetric(
916 AutofillMetrics::SUBMITTED_NON_FILLABLE_FORM); 919 AutofillMetrics::SUBMITTED_NON_FILLABLE_FORM);
917 } else { 920 } else {
918 if (did_autofill_all_possible_fields) { 921 if (did_autofill_all_possible_fields) {
919 AutofillMetrics::LogUserHappinessMetric( 922 AutofillMetrics::LogUserHappinessMetric(
920 AutofillMetrics::SUBMITTED_FILLABLE_FORM_AUTOFILLED_ALL); 923 AutofillMetrics::SUBMITTED_FILLABLE_FORM_AUTOFILLED_ALL);
921 } else if (did_autofill_some_possible_fields) { 924 } else if (did_autofill_some_possible_fields) {
922 AutofillMetrics::LogUserHappinessMetric( 925 AutofillMetrics::LogUserHappinessMetric(
923 AutofillMetrics::SUBMITTED_FILLABLE_FORM_AUTOFILLED_SOME); 926 AutofillMetrics::SUBMITTED_FILLABLE_FORM_AUTOFILLED_SOME);
924 } else { 927 } else {
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1065 EncodeFieldForQuery(*field, encompassing_xml_element); 1068 EncodeFieldForQuery(*field, encompassing_xml_element);
1066 break; 1069 break;
1067 case FormStructure::FIELD_ASSIGNMENTS: 1070 case FormStructure::FIELD_ASSIGNMENTS:
1068 EncodeFieldForFieldAssignments(*field, encompassing_xml_element); 1071 EncodeFieldForFieldAssignments(*field, encompassing_xml_element);
1069 break; 1072 break;
1070 } 1073 }
1071 } 1074 }
1072 return true; 1075 return true;
1073 } 1076 }
1074 1077
1075 void FormStructure::ParseFieldTypesFromAutocompleteAttributes( 1078 void FormStructure::ParseFieldTypesFromAutocompleteAttributes() {
1076 bool* found_types,
1077 bool* found_sections) {
1078 const std::string kDefaultSection = "-default"; 1079 const std::string kDefaultSection = "-default";
1079 1080
1080 *found_types = false; 1081 has_author_specified_types_ = false;
1081 *found_sections = false; 1082 has_author_specified_sections_ = false;
1082 for (AutofillField* field : fields_) { 1083 for (AutofillField* field : fields_) {
1083 // To prevent potential section name collisions, add a default suffix for 1084 // To prevent potential section name collisions, add a default suffix for
1084 // other fields. Without this, 'autocomplete' attribute values 1085 // other fields. Without this, 'autocomplete' attribute values
1085 // "section--shipping street-address" and "shipping street-address" would be 1086 // "section--shipping street-address" and "shipping street-address" would be
1086 // parsed identically, given the section handling code below. We do this 1087 // parsed identically, given the section handling code below. We do this
1087 // before any validation so that fields with invalid attributes still end up 1088 // before any validation so that fields with invalid attributes still end up
1088 // in the default section. These default section names will be overridden 1089 // in the default section. These default section names will be overridden
1089 // by subsequent heuristic parsing steps if there are no author-specified 1090 // by subsequent heuristic parsing steps if there are no author-specified
1090 // section names. 1091 // section names.
1091 field->set_section(kDefaultSection); 1092 field->set_section(kDefaultSection);
(...skipping 10 matching lines...) Expand all
1102 if (autocomplete_attribute.empty() || 1103 if (autocomplete_attribute.empty() ||
1103 autocomplete_attribute == "on" || 1104 autocomplete_attribute == "on" ||
1104 autocomplete_attribute == "off") { 1105 autocomplete_attribute == "off") {
1105 continue; 1106 continue;
1106 } 1107 }
1107 1108
1108 // Any other value, even it is invalid, is considered to be a type hint. 1109 // 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 1110 // This allows a website's author to specify an attribute like
1110 // autocomplete="other" on a field to disable all Autofill heuristics for 1111 // autocomplete="other" on a field to disable all Autofill heuristics for
1111 // the form. 1112 // the form.
1112 *found_types = true; 1113 has_author_specified_types_ = true;
1113 1114
1114 // Tokenize the attribute value. Per the spec, the tokens are parsed in 1115 // Tokenize the attribute value. Per the spec, the tokens are parsed in
1115 // reverse order. 1116 // reverse order.
1116 std::vector<std::string> tokens = base::SplitString( 1117 std::vector<std::string> tokens = base::SplitString(
1117 autocomplete_attribute, " ", base::KEEP_WHITESPACE, 1118 autocomplete_attribute, " ", base::KEEP_WHITESPACE,
1118 base::SPLIT_WANT_NONEMPTY); 1119 base::SPLIT_WANT_NONEMPTY);
1119 1120
1120 // The final token must be the field type. 1121 // The final token must be the field type.
1121 // If it is not one of the known types, abort. 1122 // If it is not one of the known types, abort.
1122 DCHECK(!tokens.empty()); 1123 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. 1166 // Prepend this section name to the suffix set in the preceding block.
1166 section = tokens.back().substr(kSectionPrefix.size()) + section; 1167 section = tokens.back().substr(kSectionPrefix.size()) + section;
1167 tokens.pop_back(); 1168 tokens.pop_back();
1168 } 1169 }
1169 1170
1170 // No other tokens are allowed. If there are any remaining, abort. 1171 // No other tokens are allowed. If there are any remaining, abort.
1171 if (!tokens.empty()) 1172 if (!tokens.empty())
1172 continue; 1173 continue;
1173 1174
1174 if (section != kDefaultSection) { 1175 if (section != kDefaultSection) {
1175 *found_sections = true; 1176 has_author_specified_sections_ = true;
1176 field->set_section(section); 1177 field->set_section(section);
1177 } 1178 }
1178 1179
1179 // No errors encountered while parsing! 1180 // No errors encountered while parsing!
1180 // Update the |field|'s type based on what was parsed from the attribute. 1181 // Update the |field|'s type based on what was parsed from the attribute.
1181 field->SetHtmlType(field_type, mode); 1182 field->SetHtmlType(field_type, mode);
1182 } 1183 }
1184
1185 was_parsed_for_autocomplete_attributes_ = true;
1183 } 1186 }
1184 1187
1185 bool FormStructure::FillFields( 1188 bool FormStructure::FillFields(
1186 const std::vector<ServerFieldType>& types, 1189 const std::vector<ServerFieldType>& types,
1187 const InputFieldComparator& matches, 1190 const InputFieldComparator& matches,
1188 const base::Callback<base::string16(const AutofillType&)>& get_info, 1191 const base::Callback<base::string16(const AutofillType&)>& get_info,
1189 const std::string& address_language_code, 1192 const std::string& address_language_code,
1190 const std::string& app_locale) { 1193 const std::string& app_locale) {
1191 bool filled_something = false; 1194 bool filled_something = false;
1192 for (size_t i = 0; i < field_count(); ++i) { 1195 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_) { 1324 for (AutofillField* field : fields_) {
1322 FieldTypeGroup field_type_group = field->Type().group(); 1325 FieldTypeGroup field_type_group = field->Type().group();
1323 if (field_type_group == CREDIT_CARD) 1326 if (field_type_group == CREDIT_CARD)
1324 field->set_section(field->section() + "-cc"); 1327 field->set_section(field->section() + "-cc");
1325 else 1328 else
1326 field->set_section(field->section() + "-default"); 1329 field->set_section(field->section() + "-default");
1327 } 1330 }
1328 } 1331 }
1329 1332
1330 } // namespace autofill 1333 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698