OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "chrome/browser/autofill/form_structure.h" | 5 #include "chrome/browser/autofill/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/logging.h" | 10 #include "base/logging.h" |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 method_ = GET; | 272 method_ = GET; |
273 } | 273 } |
274 } | 274 } |
275 | 275 |
276 FormStructure::~FormStructure() {} | 276 FormStructure::~FormStructure() {} |
277 | 277 |
278 void FormStructure::DetermineHeuristicTypes() { | 278 void FormStructure::DetermineHeuristicTypes() { |
279 // First, try to detect field types based on the fields' |autocompletetype| | 279 // First, try to detect field types based on the fields' |autocompletetype| |
280 // attributes. If there is at least one form field with this attribute, don't | 280 // attributes. If there is at least one form field with this attribute, don't |
281 // try to apply other heuristics to match fields in this form. | 281 // try to apply other heuristics to match fields in this form. |
282 bool found_sections; | 282 bool has_author_specified_sections; |
283 ParseAutocompletetypeAttributes(&has_author_specified_types_, | 283 ParseAutocompletetypeAttributes(&has_author_specified_types_, |
284 &found_sections); | 284 &has_author_specified_sections); |
285 | 285 |
286 if (!has_author_specified_types_) { | 286 if (!has_author_specified_types_) { |
287 FieldTypeMap field_type_map; | 287 FieldTypeMap field_type_map; |
288 FormField::ParseFormFields(fields_.get(), &field_type_map); | 288 FormField::ParseFormFields(fields_.get(), &field_type_map); |
289 for (size_t index = 0; index < field_count(); index++) { | 289 for (size_t index = 0; index < field_count(); index++) { |
290 AutofillField* field = fields_[index]; | 290 AutofillField* field = fields_[index]; |
291 FieldTypeMap::iterator iter = field_type_map.find(field->unique_name()); | 291 FieldTypeMap::iterator iter = field_type_map.find(field->unique_name()); |
292 if (iter != field_type_map.end()) | 292 if (iter != field_type_map.end()) |
293 field->set_heuristic_type(iter->second); | 293 field->set_heuristic_type(iter->second); |
294 } | 294 } |
295 } | 295 } |
296 | 296 |
297 UpdateAutofillCount(); | 297 UpdateAutofillCount(); |
298 | 298 IdentifySections(has_author_specified_sections); |
299 if (!found_sections) | |
300 IdentifySections(); | |
301 | |
302 // Ensure that credit card and address fields are in separate sections. | |
303 // This simplifies the section-aware logic in autofill_manager.cc. | |
304 for (std::vector<AutofillField*>::iterator field = fields_->begin(); | |
305 field != fields_->end(); ++field) { | |
306 AutofillType::FieldTypeGroup field_type_group = | |
307 AutofillType((*field)->type()).group(); | |
308 if (field_type_group == AutofillType::CREDIT_CARD) | |
309 (*field)->set_section((*field)->section() + ASCIIToUTF16("-cc")); | |
310 else | |
311 (*field)->set_section((*field)->section() + ASCIIToUTF16("-default")); | |
312 } | |
313 } | 299 } |
314 | 300 |
315 bool FormStructure::EncodeUploadRequest( | 301 bool FormStructure::EncodeUploadRequest( |
316 const FieldTypeSet& available_field_types, | 302 const FieldTypeSet& available_field_types, |
317 bool form_was_autofilled, | 303 bool form_was_autofilled, |
318 std::string* encoded_xml) const { | 304 std::string* encoded_xml) const { |
319 if (!ShouldBeCrowdsourced()) { | 305 if (!ShouldBeCrowdsourced()) { |
320 NOTREACHED(); | 306 NOTREACHED(); |
321 return false; | 307 return false; |
322 } | 308 } |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 AutofillFieldType heuristic_type = (*field)->type(); | 443 AutofillFieldType heuristic_type = (*field)->type(); |
458 if (heuristic_type != UNKNOWN_TYPE) | 444 if (heuristic_type != UNKNOWN_TYPE) |
459 heuristics_detected_fillable_field = true; | 445 heuristics_detected_fillable_field = true; |
460 | 446 |
461 (*field)->set_server_type(*current_type); | 447 (*field)->set_server_type(*current_type); |
462 if (heuristic_type != (*field)->type()) | 448 if (heuristic_type != (*field)->type()) |
463 query_response_overrode_heuristics = true; | 449 query_response_overrode_heuristics = true; |
464 } | 450 } |
465 | 451 |
466 form->UpdateAutofillCount(); | 452 form->UpdateAutofillCount(); |
| 453 form->IdentifySections(false); |
467 } | 454 } |
468 | 455 |
469 AutofillMetrics::ServerQueryMetric metric; | 456 AutofillMetrics::ServerQueryMetric metric; |
470 if (query_response_overrode_heuristics) { | 457 if (query_response_overrode_heuristics) { |
471 if (heuristics_detected_fillable_field) { | 458 if (heuristics_detected_fillable_field) { |
472 metric = AutofillMetrics::QUERY_RESPONSE_OVERRODE_LOCAL_HEURISTICS; | 459 metric = AutofillMetrics::QUERY_RESPONSE_OVERRODE_LOCAL_HEURISTICS; |
473 } else { | 460 } else { |
474 metric = AutofillMetrics::QUERY_RESPONSE_WITH_NO_LOCAL_HEURISTICS; | 461 metric = AutofillMetrics::QUERY_RESPONSE_WITH_NO_LOCAL_HEURISTICS; |
475 } | 462 } |
476 } else { | 463 } else { |
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
916 | 903 |
917 // Look for specified types. | 904 // Look for specified types. |
918 for (std::vector<string16>::const_iterator type = types.begin(); | 905 for (std::vector<string16>::const_iterator type = types.begin(); |
919 type != types.end(); ++type) { | 906 type != types.end(); ++type) { |
920 if (UpdateFromAutocompleteType(*type, *field)) | 907 if (UpdateFromAutocompleteType(*type, *field)) |
921 break; | 908 break; |
922 } | 909 } |
923 } | 910 } |
924 } | 911 } |
925 | 912 |
926 void FormStructure::IdentifySections() { | 913 void FormStructure::IdentifySections(bool has_author_specified_sections) { |
927 if (fields_.empty()) | 914 if (fields_.empty()) |
928 return; | 915 return; |
929 | 916 |
930 // Name sections after the first field in the section. | 917 if (!has_author_specified_sections) { |
931 string16 current_section = fields_->front()->unique_name(); | 918 // Name sections after the first field in the section. |
| 919 string16 current_section = fields_->front()->unique_name(); |
932 | 920 |
933 // Keep track of the types we've seen in this section. | 921 // Keep track of the types we've seen in this section. |
934 std::set<AutofillFieldType> seen_types; | 922 std::set<AutofillFieldType> seen_types; |
935 AutofillFieldType previous_type = UNKNOWN_TYPE; | 923 AutofillFieldType previous_type = UNKNOWN_TYPE; |
936 | 924 |
| 925 for (std::vector<AutofillField*>::iterator field = fields_->begin(); |
| 926 field != fields_->end(); ++field) { |
| 927 const AutofillFieldType current_type = |
| 928 AutofillType::GetEquivalentFieldType((*field)->type()); |
| 929 |
| 930 bool already_saw_current_type = seen_types.count(current_type) > 0; |
| 931 |
| 932 // Forms often ask for multiple phone numbers -- e.g. both a daytime and |
| 933 // evening phone number. Our phone number detection is also generally a |
| 934 // little off. Hence, ignore this field type as a signal here. |
| 935 if (AutofillType(current_type).group() == AutofillType::PHONE_HOME) |
| 936 already_saw_current_type = false; |
| 937 |
| 938 // Some forms have adjacent fields of the same type. Two common examples: |
| 939 // * Forms with two email fields, where the second is meant to "confirm" |
| 940 // the first. |
| 941 // * Forms with a <select> menu for states in some countries, and a |
| 942 // freeform <input> field for states in other countries. (Usually, |
| 943 // only one of these two will be visible for any given choice of |
| 944 // country.) |
| 945 // Generally, adjacent fields of the same type belong in the same logical |
| 946 // section. |
| 947 if (current_type == previous_type) |
| 948 already_saw_current_type = false; |
| 949 |
| 950 previous_type = current_type; |
| 951 |
| 952 if (current_type != UNKNOWN_TYPE && already_saw_current_type) { |
| 953 // We reached the end of a section, so start a new section. |
| 954 seen_types.clear(); |
| 955 current_section = (*field)->unique_name(); |
| 956 } |
| 957 |
| 958 seen_types.insert(current_type); |
| 959 (*field)->set_section(current_section); |
| 960 } |
| 961 } |
| 962 |
| 963 // Ensure that credit card and address fields are in separate sections. |
| 964 // This simplifies the section-aware logic in autofill_manager.cc. |
937 for (std::vector<AutofillField*>::iterator field = fields_->begin(); | 965 for (std::vector<AutofillField*>::iterator field = fields_->begin(); |
938 field != fields_->end(); ++field) { | 966 field != fields_->end(); ++field) { |
939 const AutofillFieldType current_type = | 967 AutofillType::FieldTypeGroup field_type_group = |
940 AutofillType::GetEquivalentFieldType((*field)->type()); | 968 AutofillType((*field)->type()).group(); |
941 | 969 if (field_type_group == AutofillType::CREDIT_CARD) |
942 bool already_saw_current_type = seen_types.count(current_type) > 0; | 970 (*field)->set_section((*field)->section() + ASCIIToUTF16("-cc")); |
943 | 971 else |
944 // Forms often ask for multiple phone numbers -- e.g. both a daytime and | 972 (*field)->set_section((*field)->section() + ASCIIToUTF16("-default")); |
945 // evening phone number. Our phone number detection is also generally a | |
946 // little off. Hence, ignore this field type as a signal here. | |
947 if (AutofillType(current_type).group() == AutofillType::PHONE_HOME) | |
948 already_saw_current_type = false; | |
949 | |
950 // Some forms have adjacent fields of the same type. Two common examples: | |
951 // * Forms with two email fields, where the second is meant to "confirm" | |
952 // the first. | |
953 // * Forms with a <select> menu for states in some countries, and a | |
954 // freeform <input> field for states in other countries. (Usually, only | |
955 // one of these two will be visible for any given choice of country.) | |
956 // Generally, adjacent fields of the same type belong in the same logical | |
957 // section. | |
958 if (current_type == previous_type) | |
959 already_saw_current_type = false; | |
960 | |
961 previous_type = current_type; | |
962 | |
963 if (current_type != UNKNOWN_TYPE && already_saw_current_type) { | |
964 // We reached the end of a section, so start a new section. | |
965 seen_types.clear(); | |
966 current_section = (*field)->unique_name(); | |
967 } | |
968 | |
969 seen_types.insert(current_type); | |
970 (*field)->set_section(current_section); | |
971 } | 973 } |
972 } | 974 } |
OLD | NEW |