| 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 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 } // namespace | 366 } // namespace |
| 367 | 367 |
| 368 FormStructure::FormStructure(const FormData& form) | 368 FormStructure::FormStructure(const FormData& form) |
| 369 : form_name_(form.name), | 369 : form_name_(form.name), |
| 370 source_url_(form.origin), | 370 source_url_(form.origin), |
| 371 target_url_(form.action), | 371 target_url_(form.action), |
| 372 autofill_count_(0), | 372 autofill_count_(0), |
| 373 active_field_count_(0), | 373 active_field_count_(0), |
| 374 upload_required_(USE_UPLOAD_RATES), | 374 upload_required_(USE_UPLOAD_RATES), |
| 375 has_author_specified_types_(false), | 375 has_author_specified_types_(false), |
| 376 has_author_specified_sections_(false), |
| 377 was_parsed_for_autocomplete_attributes_(false), |
| 376 has_password_field_(false), | 378 has_password_field_(false), |
| 377 is_form_tag_(form.is_form_tag) { | 379 is_form_tag_(form.is_form_tag) { |
| 378 // Copy the form fields. | 380 // Copy the form fields. |
| 379 std::map<base::string16, size_t> unique_names; | 381 std::map<base::string16, size_t> unique_names; |
| 380 for (const FormFieldData& field : form.fields) { | 382 for (const FormFieldData& field : form.fields) { |
| 381 if (!ShouldSkipField(field)) { | 383 if (!ShouldSkipField(field)) { |
| 382 // Add all supported form fields (including with empty names) to the | 384 // Add all supported form fields (including with empty names) to the |
| 383 // signature. This is a requirement for Autofill servers. | 385 // signature. This is a requirement for Autofill servers. |
| 384 form_signature_field_names_.append("&"); | 386 form_signature_field_names_.append("&"); |
| 385 form_signature_field_names_.append(StripDigitsIfRequired(field.name)); | 387 form_signature_field_names_.append(StripDigitsIfRequired(field.name)); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 400 } | 402 } |
| 401 } | 403 } |
| 402 | 404 |
| 403 FormStructure::~FormStructure() {} | 405 FormStructure::~FormStructure() {} |
| 404 | 406 |
| 405 void FormStructure::DetermineHeuristicTypes() { | 407 void FormStructure::DetermineHeuristicTypes() { |
| 406 // First, try to detect field types based on each field's |autocomplete| | 408 // First, try to detect field types based on each field's |autocomplete| |
| 407 // attribute value. If there is at least one form field that specifies an | 409 // attribute value. If there is at least one form field that specifies an |
| 408 // autocomplete type hint, don't try to apply other heuristics to match fields | 410 // autocomplete type hint, don't try to apply other heuristics to match fields |
| 409 // in this form. | 411 // in this form. |
| 410 bool has_author_specified_sections; | 412 if (!was_parsed_for_autocomplete_attributes_) |
| 411 ParseFieldTypesFromAutocompleteAttributes(&has_author_specified_types_, | 413 ParseFieldTypesFromAutocompleteAttributes(); |
| 412 &has_author_specified_sections); | |
| 413 | 414 |
| 414 if (!has_author_specified_types_) { | 415 if (!has_author_specified_types_) { |
| 415 ServerFieldTypeMap field_type_map; | 416 ServerFieldTypeMap field_type_map; |
| 416 FormField::ParseFormFields(fields_.get(), is_form_tag_, &field_type_map); | 417 FormField::ParseFormFields(fields_.get(), is_form_tag_, &field_type_map); |
| 417 for (size_t i = 0; i < field_count(); ++i) { | 418 for (size_t i = 0; i < field_count(); ++i) { |
| 418 AutofillField* field = fields_[i]; | 419 AutofillField* field = fields_[i]; |
| 419 ServerFieldTypeMap::iterator iter = | 420 ServerFieldTypeMap::iterator iter = |
| 420 field_type_map.find(field->unique_name()); | 421 field_type_map.find(field->unique_name()); |
| 421 if (iter != field_type_map.end()) | 422 if (iter != field_type_map.end()) |
| 422 field->set_heuristic_type(iter->second); | 423 field->set_heuristic_type(iter->second); |
| 423 } | 424 } |
| 424 } | 425 } |
| 425 | 426 |
| 426 UpdateAutofillCount(); | 427 UpdateAutofillCount(); |
| 427 IdentifySections(has_author_specified_sections); | 428 IdentifySections(has_author_specified_sections_); |
| 428 | 429 |
| 429 if (IsAutofillable()) { | 430 if (IsAutofillable()) { |
| 430 AutofillMetrics::LogDeveloperEngagementMetric( | 431 AutofillMetrics::LogDeveloperEngagementMetric( |
| 431 AutofillMetrics::FILLABLE_FORM_PARSED); | 432 AutofillMetrics::FILLABLE_FORM_PARSED); |
| 432 if (has_author_specified_types_) { | 433 if (has_author_specified_types_) { |
| 433 AutofillMetrics::LogDeveloperEngagementMetric( | 434 AutofillMetrics::LogDeveloperEngagementMetric( |
| 434 AutofillMetrics::FILLABLE_FORM_CONTAINS_TYPE_HINTS); | 435 AutofillMetrics::FILLABLE_FORM_CONTAINS_TYPE_HINTS); |
| 435 } | 436 } |
| 436 } | 437 } |
| 437 } | 438 } |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 form_signature_field_names_; | 703 form_signature_field_names_; |
| 703 | 704 |
| 704 return Hash64Bit(form_string); | 705 return Hash64Bit(form_string); |
| 705 } | 706 } |
| 706 | 707 |
| 707 bool FormStructure::ShouldSkipField(const FormFieldData& field) const { | 708 bool FormStructure::ShouldSkipField(const FormFieldData& field) const { |
| 708 return field.is_checkable; | 709 return field.is_checkable; |
| 709 } | 710 } |
| 710 | 711 |
| 711 bool FormStructure::IsAutofillable() const { | 712 bool FormStructure::IsAutofillable() const { |
| 712 if (autofill_count() < kRequiredAutofillFields) | 713 if (autofill_count() < kRequiredFieldsForPredictionRoutines) |
| 713 return false; | 714 return false; |
| 714 | 715 |
| 715 return ShouldBeParsed(); | 716 return ShouldBeParsed(); |
| 716 } | 717 } |
| 717 | 718 |
| 718 void FormStructure::UpdateAutofillCount() { | 719 void FormStructure::UpdateAutofillCount() { |
| 719 autofill_count_ = 0; | 720 autofill_count_ = 0; |
| 720 for (const AutofillField* field : *this) { | 721 for (const AutofillField* field : *this) { |
| 721 if (field && field->IsFieldFillable()) | 722 if (field && field->IsFieldFillable()) |
| 722 ++autofill_count_; | 723 ++autofill_count_; |
| 723 } | 724 } |
| 724 } | 725 } |
| 725 | 726 |
| 726 bool FormStructure::ShouldBeParsed() const { | 727 bool FormStructure::ShouldBeParsed() const { |
| 727 if (active_field_count() < kRequiredAutofillFields) | 728 if (active_field_count() < kRequiredFieldsForPredictionRoutines && |
| 729 !has_author_specified_types_) { |
| 728 return false; | 730 return false; |
| 731 } |
| 729 | 732 |
| 730 // Rule out http(s)://*/search?... | 733 // Rule out http(s)://*/search?... |
| 731 // e.g. http://www.google.com/search?q=... | 734 // e.g. http://www.google.com/search?q=... |
| 732 // http://search.yahoo.com/search?p=... | 735 // http://search.yahoo.com/search?p=... |
| 733 if (target_url_.path() == "/search") | 736 if (target_url_.path() == "/search") |
| 734 return false; | 737 return false; |
| 735 | 738 |
| 736 bool has_text_field = false; | 739 bool has_text_field = false; |
| 737 for (const AutofillField* it : *this) { | 740 for (const AutofillField* it : *this) { |
| 738 has_text_field |= it->form_control_type != "select-one"; | 741 has_text_field |= it->form_control_type != "select-one"; |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 886 field_type); | 889 field_type); |
| 887 } else { | 890 } else { |
| 888 AutofillMetrics::LogOverallTypePrediction(AutofillMetrics::TYPE_MISMATCH, | 891 AutofillMetrics::LogOverallTypePrediction(AutofillMetrics::TYPE_MISMATCH, |
| 889 field_type); | 892 field_type); |
| 890 } | 893 } |
| 891 } | 894 } |
| 892 | 895 |
| 893 AutofillMetrics::LogNumberOfEditedAutofilledFieldsAtSubmission( | 896 AutofillMetrics::LogNumberOfEditedAutofilledFieldsAtSubmission( |
| 894 num_edited_autofilled_fields); | 897 num_edited_autofilled_fields); |
| 895 | 898 |
| 896 if (num_detected_field_types < kRequiredAutofillFields) { | 899 if (num_detected_field_types < kRequiredFieldsForPredictionRoutines) { |
| 897 AutofillMetrics::LogAutofillFormSubmittedState( | 900 AutofillMetrics::LogAutofillFormSubmittedState( |
| 898 AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA); | 901 AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA); |
| 899 } else { | 902 } else { |
| 900 if (did_autofill_all_possible_fields) { | 903 if (did_autofill_all_possible_fields) { |
| 901 AutofillMetrics::LogAutofillFormSubmittedState( | 904 AutofillMetrics::LogAutofillFormSubmittedState( |
| 902 AutofillMetrics::FILLABLE_FORM_AUTOFILLED_ALL); | 905 AutofillMetrics::FILLABLE_FORM_AUTOFILLED_ALL); |
| 903 } else if (did_autofill_some_possible_fields) { | 906 } else if (did_autofill_some_possible_fields) { |
| 904 AutofillMetrics::LogAutofillFormSubmittedState( | 907 AutofillMetrics::LogAutofillFormSubmittedState( |
| 905 AutofillMetrics::FILLABLE_FORM_AUTOFILLED_SOME); | 908 AutofillMetrics::FILLABLE_FORM_AUTOFILLED_SOME); |
| 906 } else if (!did_show_suggestions) { | 909 } else if (!did_show_suggestions) { |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1051 EncodeFieldForQuery(*field, encompassing_xml_element); | 1054 EncodeFieldForQuery(*field, encompassing_xml_element); |
| 1052 break; | 1055 break; |
| 1053 case FormStructure::FIELD_ASSIGNMENTS: | 1056 case FormStructure::FIELD_ASSIGNMENTS: |
| 1054 EncodeFieldForFieldAssignments(*field, encompassing_xml_element); | 1057 EncodeFieldForFieldAssignments(*field, encompassing_xml_element); |
| 1055 break; | 1058 break; |
| 1056 } | 1059 } |
| 1057 } | 1060 } |
| 1058 return true; | 1061 return true; |
| 1059 } | 1062 } |
| 1060 | 1063 |
| 1061 void FormStructure::ParseFieldTypesFromAutocompleteAttributes( | 1064 void FormStructure::ParseFieldTypesFromAutocompleteAttributes() { |
| 1062 bool* found_types, | |
| 1063 bool* found_sections) { | |
| 1064 const std::string kDefaultSection = "-default"; | 1065 const std::string kDefaultSection = "-default"; |
| 1065 | 1066 |
| 1066 *found_types = false; | 1067 has_author_specified_types_ = false; |
| 1067 *found_sections = false; | 1068 has_author_specified_sections_ = false; |
| 1068 for (AutofillField* field : fields_) { | 1069 for (AutofillField* field : fields_) { |
| 1069 // To prevent potential section name collisions, add a default suffix for | 1070 // To prevent potential section name collisions, add a default suffix for |
| 1070 // other fields. Without this, 'autocomplete' attribute values | 1071 // other fields. Without this, 'autocomplete' attribute values |
| 1071 // "section--shipping street-address" and "shipping street-address" would be | 1072 // "section--shipping street-address" and "shipping street-address" would be |
| 1072 // parsed identically, given the section handling code below. We do this | 1073 // parsed identically, given the section handling code below. We do this |
| 1073 // before any validation so that fields with invalid attributes still end up | 1074 // before any validation so that fields with invalid attributes still end up |
| 1074 // in the default section. These default section names will be overridden | 1075 // in the default section. These default section names will be overridden |
| 1075 // by subsequent heuristic parsing steps if there are no author-specified | 1076 // by subsequent heuristic parsing steps if there are no author-specified |
| 1076 // section names. | 1077 // section names. |
| 1077 field->set_section(kDefaultSection); | 1078 field->set_section(kDefaultSection); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1088 if (autocomplete_attribute.empty() || | 1089 if (autocomplete_attribute.empty() || |
| 1089 autocomplete_attribute == "on" || | 1090 autocomplete_attribute == "on" || |
| 1090 autocomplete_attribute == "off") { | 1091 autocomplete_attribute == "off") { |
| 1091 continue; | 1092 continue; |
| 1092 } | 1093 } |
| 1093 | 1094 |
| 1094 // Any other value, even it is invalid, is considered to be a type hint. | 1095 // Any other value, even it is invalid, is considered to be a type hint. |
| 1095 // This allows a website's author to specify an attribute like | 1096 // This allows a website's author to specify an attribute like |
| 1096 // autocomplete="other" on a field to disable all Autofill heuristics for | 1097 // autocomplete="other" on a field to disable all Autofill heuristics for |
| 1097 // the form. | 1098 // the form. |
| 1098 *found_types = true; | 1099 has_author_specified_types_ = true; |
| 1099 | 1100 |
| 1100 // Tokenize the attribute value. Per the spec, the tokens are parsed in | 1101 // Tokenize the attribute value. Per the spec, the tokens are parsed in |
| 1101 // reverse order. | 1102 // reverse order. |
| 1102 std::vector<std::string> tokens = base::SplitString( | 1103 std::vector<std::string> tokens = base::SplitString( |
| 1103 autocomplete_attribute, " ", base::KEEP_WHITESPACE, | 1104 autocomplete_attribute, " ", base::KEEP_WHITESPACE, |
| 1104 base::SPLIT_WANT_NONEMPTY); | 1105 base::SPLIT_WANT_NONEMPTY); |
| 1105 | 1106 |
| 1106 // The final token must be the field type. | 1107 // The final token must be the field type. |
| 1107 // If it is not one of the known types, abort. | 1108 // If it is not one of the known types, abort. |
| 1108 DCHECK(!tokens.empty()); | 1109 DCHECK(!tokens.empty()); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1151 // Prepend this section name to the suffix set in the preceding block. | 1152 // Prepend this section name to the suffix set in the preceding block. |
| 1152 section = tokens.back().substr(kSectionPrefix.size()) + section; | 1153 section = tokens.back().substr(kSectionPrefix.size()) + section; |
| 1153 tokens.pop_back(); | 1154 tokens.pop_back(); |
| 1154 } | 1155 } |
| 1155 | 1156 |
| 1156 // No other tokens are allowed. If there are any remaining, abort. | 1157 // No other tokens are allowed. If there are any remaining, abort. |
| 1157 if (!tokens.empty()) | 1158 if (!tokens.empty()) |
| 1158 continue; | 1159 continue; |
| 1159 | 1160 |
| 1160 if (section != kDefaultSection) { | 1161 if (section != kDefaultSection) { |
| 1161 *found_sections = true; | 1162 has_author_specified_sections_ = true; |
| 1162 field->set_section(section); | 1163 field->set_section(section); |
| 1163 } | 1164 } |
| 1164 | 1165 |
| 1165 // No errors encountered while parsing! | 1166 // No errors encountered while parsing! |
| 1166 // Update the |field|'s type based on what was parsed from the attribute. | 1167 // Update the |field|'s type based on what was parsed from the attribute. |
| 1167 field->SetHtmlType(field_type, mode); | 1168 field->SetHtmlType(field_type, mode); |
| 1168 } | 1169 } |
| 1170 |
| 1171 was_parsed_for_autocomplete_attributes_ = true; |
| 1169 } | 1172 } |
| 1170 | 1173 |
| 1171 bool FormStructure::FillFields( | 1174 bool FormStructure::FillFields( |
| 1172 const std::vector<ServerFieldType>& types, | 1175 const std::vector<ServerFieldType>& types, |
| 1173 const InputFieldComparator& matches, | 1176 const InputFieldComparator& matches, |
| 1174 const base::Callback<base::string16(const AutofillType&)>& get_info, | 1177 const base::Callback<base::string16(const AutofillType&)>& get_info, |
| 1175 const std::string& address_language_code, | 1178 const std::string& address_language_code, |
| 1176 const std::string& app_locale) { | 1179 const std::string& app_locale) { |
| 1177 bool filled_something = false; | 1180 bool filled_something = false; |
| 1178 for (size_t i = 0; i < field_count(); ++i) { | 1181 for (size_t i = 0; i < field_count(); ++i) { |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1307 for (AutofillField* field : fields_) { | 1310 for (AutofillField* field : fields_) { |
| 1308 FieldTypeGroup field_type_group = field->Type().group(); | 1311 FieldTypeGroup field_type_group = field->Type().group(); |
| 1309 if (field_type_group == CREDIT_CARD) | 1312 if (field_type_group == CREDIT_CARD) |
| 1310 field->set_section(field->section() + "-cc"); | 1313 field->set_section(field->section() + "-cc"); |
| 1311 else | 1314 else |
| 1312 field->set_section(field->section() + "-default"); | 1315 field->set_section(field->section() + "-default"); |
| 1313 } | 1316 } |
| 1314 } | 1317 } |
| 1315 | 1318 |
| 1316 } // namespace autofill | 1319 } // namespace autofill |
| OLD | NEW |