Chromium Code Reviews| 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 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 382 } // namespace | 382 } // namespace |
| 383 | 383 |
| 384 FormStructure::FormStructure(const FormData& form) | 384 FormStructure::FormStructure(const FormData& form) |
| 385 : form_name_(form.name), | 385 : form_name_(form.name), |
| 386 source_url_(form.origin), | 386 source_url_(form.origin), |
| 387 target_url_(form.action), | 387 target_url_(form.action), |
| 388 autofill_count_(0), | 388 autofill_count_(0), |
| 389 active_field_count_(0), | 389 active_field_count_(0), |
| 390 upload_required_(USE_UPLOAD_RATES), | 390 upload_required_(USE_UPLOAD_RATES), |
| 391 has_author_specified_types_(false), | 391 has_author_specified_types_(false), |
| 392 has_author_specified_sections_(false), | |
| 393 was_parsed_for_autocomplete_attributes_(false), | |
| 392 has_password_field_(false), | 394 has_password_field_(false), |
| 393 is_form_tag_(form.is_form_tag) { | 395 is_form_tag_(form.is_form_tag) { |
| 394 // Copy the form fields. | 396 // Copy the form fields. |
| 395 std::map<base::string16, size_t> unique_names; | 397 std::map<base::string16, size_t> unique_names; |
| 396 for (const FormFieldData& field : form.fields) { | 398 for (const FormFieldData& field : form.fields) { |
| 397 if (!ShouldSkipField(field)) { | 399 if (!ShouldSkipField(field)) { |
| 398 // Add all supported form fields (including with empty names) to the | 400 // Add all supported form fields (including with empty names) to the |
| 399 // signature. This is a requirement for Autofill servers. | 401 // signature. This is a requirement for Autofill servers. |
| 400 form_signature_field_names_.append("&"); | 402 form_signature_field_names_.append("&"); |
| 401 form_signature_field_names_.append(StripDigitsIfRequired(field.name)); | 403 form_signature_field_names_.append(StripDigitsIfRequired(field.name)); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 416 } | 418 } |
| 417 } | 419 } |
| 418 | 420 |
| 419 FormStructure::~FormStructure() {} | 421 FormStructure::~FormStructure() {} |
| 420 | 422 |
| 421 void FormStructure::DetermineHeuristicTypes() { | 423 void FormStructure::DetermineHeuristicTypes() { |
| 422 // First, try to detect field types based on each field's |autocomplete| | 424 // First, try to detect field types based on each field's |autocomplete| |
| 423 // attribute value. If there is at least one form field that specifies an | 425 // attribute value. If there is at least one form field that specifies an |
| 424 // autocomplete type hint, don't try to apply other heuristics to match fields | 426 // autocomplete type hint, don't try to apply other heuristics to match fields |
| 425 // in this form. | 427 // in this form. |
| 426 bool has_author_specified_sections; | 428 if (!was_parsed_for_autocomplete_attributes_) |
| 427 ParseFieldTypesFromAutocompleteAttributes(&has_author_specified_types_, | 429 ParseFieldTypesFromAutocompleteAttributes(); |
| 428 &has_author_specified_sections); | |
| 429 | 430 |
| 430 if (!has_author_specified_types_) { | 431 if (!has_author_specified_types_) { |
| 431 ServerFieldTypeMap field_type_map; | 432 ServerFieldTypeMap field_type_map; |
| 432 FormField::ParseFormFields(fields_.get(), is_form_tag_, &field_type_map); | 433 FormField::ParseFormFields(fields_.get(), is_form_tag_, &field_type_map); |
| 433 for (size_t i = 0; i < field_count(); ++i) { | 434 for (size_t i = 0; i < field_count(); ++i) { |
| 434 AutofillField* field = fields_[i]; | 435 AutofillField* field = fields_[i]; |
| 435 ServerFieldTypeMap::iterator iter = | 436 ServerFieldTypeMap::iterator iter = |
| 436 field_type_map.find(field->unique_name()); | 437 field_type_map.find(field->unique_name()); |
| 437 if (iter != field_type_map.end()) | 438 if (iter != field_type_map.end()) |
| 438 field->set_heuristic_type(iter->second); | 439 field->set_heuristic_type(iter->second); |
| 439 } | 440 } |
| 440 } | 441 } |
| 441 | 442 |
| 442 UpdateAutofillCount(); | 443 UpdateAutofillCount(); |
| 443 IdentifySections(has_author_specified_sections); | 444 IdentifySections(has_author_specified_sections_); |
| 444 | 445 |
| 445 if (IsAutofillable()) { | 446 if (IsAutofillable()) { |
| 446 AutofillMetrics::LogDeveloperEngagementMetric( | 447 AutofillMetrics::LogDeveloperEngagementMetric( |
| 447 AutofillMetrics::FILLABLE_FORM_PARSED); | 448 AutofillMetrics::FILLABLE_FORM_PARSED); |
| 448 if (has_author_specified_types_) { | 449 if (has_author_specified_types_) { |
| 449 AutofillMetrics::LogDeveloperEngagementMetric( | 450 AutofillMetrics::LogDeveloperEngagementMetric( |
| 450 AutofillMetrics::FILLABLE_FORM_CONTAINS_TYPE_HINTS); | 451 AutofillMetrics::FILLABLE_FORM_CONTAINS_TYPE_HINTS); |
| 451 } | 452 } |
| 452 } | 453 } |
| 453 } | 454 } |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 739 autofill_count_ = 0; | 740 autofill_count_ = 0; |
| 740 for (std::vector<AutofillField*>::const_iterator iter = begin(); | 741 for (std::vector<AutofillField*>::const_iterator iter = begin(); |
| 741 iter != end(); ++iter) { | 742 iter != end(); ++iter) { |
| 742 AutofillField* field = *iter; | 743 AutofillField* field = *iter; |
| 743 if (field && field->IsFieldFillable()) | 744 if (field && field->IsFieldFillable()) |
| 744 ++autofill_count_; | 745 ++autofill_count_; |
| 745 } | 746 } |
| 746 } | 747 } |
| 747 | 748 |
| 748 bool FormStructure::ShouldBeParsed() const { | 749 bool FormStructure::ShouldBeParsed() const { |
| 749 if (active_field_count() < kRequiredAutofillFields) | 750 if (active_field_count() < kRequiredAutofillFields && |
| 751 !has_author_specified_types_) | |
| 750 return false; | 752 return false; |
| 751 | 753 |
| 752 // Rule out http(s)://*/search?... | 754 // Rule out http(s)://*/search?... |
| 753 // e.g. http://www.google.com/search?q=... | 755 // e.g. http://www.google.com/search?q=... |
| 754 // http://search.yahoo.com/search?p=... | 756 // http://search.yahoo.com/search?p=... |
| 755 if (target_url_.path() == "/search") | 757 if (target_url_.path() == "/search") |
| 756 return false; | 758 return false; |
| 757 | 759 |
| 758 bool has_text_field = false; | 760 bool has_text_field = false; |
| 759 for (std::vector<AutofillField*>::const_iterator it = begin(); | 761 for (std::vector<AutofillField*>::const_iterator it = begin(); |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1075 EncodeFieldForQuery(*field, encompassing_xml_element); | 1077 EncodeFieldForQuery(*field, encompassing_xml_element); |
| 1076 break; | 1078 break; |
| 1077 case FormStructure::FIELD_ASSIGNMENTS: | 1079 case FormStructure::FIELD_ASSIGNMENTS: |
| 1078 EncodeFieldForFieldAssignments(*field, encompassing_xml_element); | 1080 EncodeFieldForFieldAssignments(*field, encompassing_xml_element); |
| 1079 break; | 1081 break; |
| 1080 } | 1082 } |
| 1081 } | 1083 } |
| 1082 return true; | 1084 return true; |
| 1083 } | 1085 } |
| 1084 | 1086 |
| 1085 void FormStructure::ParseFieldTypesFromAutocompleteAttributes( | 1087 void FormStructure::ParseFieldTypesFromAutocompleteAttributes() { |
| 1086 bool* found_types, | |
| 1087 bool* found_sections) { | |
| 1088 const std::string kDefaultSection = "-default"; | 1088 const std::string kDefaultSection = "-default"; |
| 1089 | 1089 |
| 1090 *found_types = false; | 1090 has_author_specified_types_ = false; |
| 1091 *found_sections = false; | 1091 has_author_specified_sections_ = false; |
| 1092 for (std::vector<AutofillField*>::iterator it = fields_.begin(); | 1092 for (std::vector<AutofillField*>::iterator it = fields_.begin(); |
| 1093 it != fields_.end(); ++it) { | 1093 it != fields_.end(); ++it) { |
| 1094 AutofillField* field = *it; | 1094 AutofillField* field = *it; |
| 1095 | 1095 |
| 1096 // To prevent potential section name collisions, add a default suffix for | 1096 // To prevent potential section name collisions, add a default suffix for |
| 1097 // other fields. Without this, 'autocomplete' attribute values | 1097 // other fields. Without this, 'autocomplete' attribute values |
| 1098 // "section--shipping street-address" and "shipping street-address" would be | 1098 // "section--shipping street-address" and "shipping street-address" would be |
| 1099 // parsed identically, given the section handling code below. We do this | 1099 // parsed identically, given the section handling code below. We do this |
| 1100 // before any validation so that fields with invalid attributes still end up | 1100 // before any validation so that fields with invalid attributes still end up |
| 1101 // in the default section. These default section names will be overridden | 1101 // in the default section. These default section names will be overridden |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1115 if (autocomplete_attribute.empty() || | 1115 if (autocomplete_attribute.empty() || |
| 1116 autocomplete_attribute == "on" || | 1116 autocomplete_attribute == "on" || |
| 1117 autocomplete_attribute == "off") { | 1117 autocomplete_attribute == "off") { |
| 1118 continue; | 1118 continue; |
| 1119 } | 1119 } |
| 1120 | 1120 |
| 1121 // Any other value, even it is invalid, is considered to be a type hint. | 1121 // Any other value, even it is invalid, is considered to be a type hint. |
| 1122 // This allows a website's author to specify an attribute like | 1122 // This allows a website's author to specify an attribute like |
| 1123 // autocomplete="other" on a field to disable all Autofill heuristics for | 1123 // autocomplete="other" on a field to disable all Autofill heuristics for |
| 1124 // the form. | 1124 // the form. |
| 1125 *found_types = true; | 1125 has_author_specified_types_ = true; |
| 1126 | 1126 |
| 1127 // Tokenize the attribute value. Per the spec, the tokens are parsed in | 1127 // Tokenize the attribute value. Per the spec, the tokens are parsed in |
| 1128 // reverse order. | 1128 // reverse order. |
| 1129 std::vector<std::string> tokens = base::SplitString( | 1129 std::vector<std::string> tokens = base::SplitString( |
| 1130 autocomplete_attribute, " ", base::KEEP_WHITESPACE, | 1130 autocomplete_attribute, " ", base::KEEP_WHITESPACE, |
| 1131 base::SPLIT_WANT_NONEMPTY); | 1131 base::SPLIT_WANT_NONEMPTY); |
| 1132 | 1132 |
| 1133 // The final token must be the field type. | 1133 // The final token must be the field type. |
| 1134 // If it is not one of the known types, abort. | 1134 // If it is not one of the known types, abort. |
| 1135 DCHECK(!tokens.empty()); | 1135 DCHECK(!tokens.empty()); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1178 // Prepend this section name to the suffix set in the preceding block. | 1178 // Prepend this section name to the suffix set in the preceding block. |
| 1179 section = tokens.back().substr(kSectionPrefix.size()) + section; | 1179 section = tokens.back().substr(kSectionPrefix.size()) + section; |
| 1180 tokens.pop_back(); | 1180 tokens.pop_back(); |
| 1181 } | 1181 } |
| 1182 | 1182 |
| 1183 // No other tokens are allowed. If there are any remaining, abort. | 1183 // No other tokens are allowed. If there are any remaining, abort. |
| 1184 if (!tokens.empty()) | 1184 if (!tokens.empty()) |
| 1185 continue; | 1185 continue; |
| 1186 | 1186 |
| 1187 if (section != kDefaultSection) { | 1187 if (section != kDefaultSection) { |
| 1188 *found_sections = true; | 1188 has_author_specified_sections_ = true; |
| 1189 field->set_section(section); | 1189 field->set_section(section); |
| 1190 } | 1190 } |
| 1191 | 1191 |
| 1192 // No errors encountered while parsing! | 1192 // No errors encountered while parsing! |
| 1193 // Update the |field|'s type based on what was parsed from the attribute. | 1193 // Update the |field|'s type based on what was parsed from the attribute. |
| 1194 field->SetHtmlType(field_type, mode); | 1194 field->SetHtmlType(field_type, mode); |
| 1195 | |
| 1196 was_parsed_for_autocomplete_attributes_ = true; | |
|
Mathieu
2015/10/20 21:03:11
should this go one line down, outside the loop?
sebsg
2015/10/21 18:20:50
Done.
| |
| 1195 } | 1197 } |
| 1196 } | 1198 } |
| 1197 | 1199 |
| 1198 bool FormStructure::FillFields( | 1200 bool FormStructure::FillFields( |
| 1199 const std::vector<ServerFieldType>& types, | 1201 const std::vector<ServerFieldType>& types, |
| 1200 const InputFieldComparator& matches, | 1202 const InputFieldComparator& matches, |
| 1201 const base::Callback<base::string16(const AutofillType&)>& get_info, | 1203 const base::Callback<base::string16(const AutofillType&)>& get_info, |
| 1202 const std::string& address_language_code, | 1204 const std::string& address_language_code, |
| 1203 const std::string& app_locale) { | 1205 const std::string& app_locale) { |
| 1204 bool filled_something = false; | 1206 bool filled_something = false; |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1334 for (AutofillField* field : fields_) { | 1336 for (AutofillField* field : fields_) { |
| 1335 FieldTypeGroup field_type_group = field->Type().group(); | 1337 FieldTypeGroup field_type_group = field->Type().group(); |
| 1336 if (field_type_group == CREDIT_CARD) | 1338 if (field_type_group == CREDIT_CARD) |
| 1337 field->set_section(field->section() + "-cc"); | 1339 field->set_section(field->section() + "-cc"); |
| 1338 else | 1340 else |
| 1339 field->set_section(field->section() + "-default"); | 1341 field->set_section(field->section() + "-default"); |
| 1340 } | 1342 } |
| 1341 } | 1343 } |
| 1342 | 1344 |
| 1343 } // namespace autofill | 1345 } // namespace autofill |
| OLD | NEW |