OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |