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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 const char kXMLElementFields[] = "fields"; | 58 const char kXMLElementFields[] = "fields"; |
59 const char kXMLElementForm[] = "form"; | 59 const char kXMLElementForm[] = "form"; |
60 const char kBillingSection[] = "billing"; | 60 const char kBillingSection[] = "billing"; |
61 const char kShippingSection[] = "shipping"; | 61 const char kShippingSection[] = "shipping"; |
62 | 62 |
63 // Stip away >= 5 consecutive digits. | 63 // Stip away >= 5 consecutive digits. |
64 const char kIgnorePatternInFieldName[] = "\\d{5,}+"; | 64 const char kIgnorePatternInFieldName[] = "\\d{5,}+"; |
65 | 65 |
66 // Helper for |EncodeUploadRequest()| that creates a bit field corresponding to | 66 // Helper for |EncodeUploadRequest()| that creates a bit field corresponding to |
67 // |available_field_types| and returns the hex representation as a string. | 67 // |available_field_types| and returns the hex representation as a string. |
68 std::string EncodeFieldTypes(const FieldTypeSet& available_field_types) { | 68 std::string EncodeFieldTypes(const ServerFieldTypeSet& available_field_types) { |
69 // There are |MAX_VALID_FIELD_TYPE| different field types and 8 bits per byte, | 69 // There are |MAX_VALID_FIELD_TYPE| different field types and 8 bits per byte, |
70 // so we need ceil(MAX_VALID_FIELD_TYPE / 8) bytes to encode the bit field. | 70 // so we need ceil(MAX_VALID_FIELD_TYPE / 8) bytes to encode the bit field. |
71 const size_t kNumBytes = (MAX_VALID_FIELD_TYPE + 0x7) / 8; | 71 const size_t kNumBytes = (MAX_VALID_FIELD_TYPE + 0x7) / 8; |
72 | 72 |
73 // Pack the types in |available_field_types| into |bit_field|. | 73 // Pack the types in |available_field_types| into |bit_field|. |
74 std::vector<uint8> bit_field(kNumBytes, 0); | 74 std::vector<uint8> bit_field(kNumBytes, 0); |
75 for (FieldTypeSet::const_iterator field_type = available_field_types.begin(); | 75 for (ServerFieldTypeSet::const_iterator field_type = |
| 76 available_field_types.begin(); |
76 field_type != available_field_types.end(); | 77 field_type != available_field_types.end(); |
77 ++field_type) { | 78 ++field_type) { |
78 // Set the appropriate bit in the field. The bit we set is the one | 79 // Set the appropriate bit in the field. The bit we set is the one |
79 // |field_type| % 8 from the left of the byte. | 80 // |field_type| % 8 from the left of the byte. |
80 const size_t byte = *field_type / 8; | 81 const size_t byte = *field_type / 8; |
81 const size_t bit = 0x80 >> (*field_type % 8); | 82 const size_t bit = 0x80 >> (*field_type % 8); |
82 DCHECK(byte < bit_field.size()); | 83 DCHECK(byte < bit_field.size()); |
83 bit_field[byte] |= bit; | 84 bit_field[byte] |= bit; |
84 } | 85 } |
85 | 86 |
(...skipping 14 matching lines...) Expand all Loading... |
100 } | 101 } |
101 | 102 |
102 // Helper for |EncodeFormRequest()| that creates XmlElements for the given field | 103 // Helper for |EncodeFormRequest()| that creates XmlElements for the given field |
103 // in upload xml, and also add them to the parent XmlElement. | 104 // in upload xml, and also add them to the parent XmlElement. |
104 void EncodeFieldForUpload(const AutofillField& field, | 105 void EncodeFieldForUpload(const AutofillField& field, |
105 buzz::XmlElement* parent) { | 106 buzz::XmlElement* parent) { |
106 // Don't upload checkable fields. | 107 // Don't upload checkable fields. |
107 if (field.is_checkable) | 108 if (field.is_checkable) |
108 return; | 109 return; |
109 | 110 |
110 FieldTypeSet types = field.possible_types(); | 111 ServerFieldTypeSet types = field.possible_types(); |
111 // |types| could be empty in unit-tests only. | 112 // |types| could be empty in unit-tests only. |
112 for (FieldTypeSet::iterator field_type = types.begin(); | 113 for (ServerFieldTypeSet::iterator field_type = types.begin(); |
113 field_type != types.end(); ++field_type) { | 114 field_type != types.end(); ++field_type) { |
114 buzz::XmlElement *field_element = new buzz::XmlElement( | 115 buzz::XmlElement *field_element = new buzz::XmlElement( |
115 buzz::QName(kXMLElementField)); | 116 buzz::QName(kXMLElementField)); |
116 | 117 |
117 field_element->SetAttr(buzz::QName(kAttributeSignature), | 118 field_element->SetAttr(buzz::QName(kAttributeSignature), |
118 field.FieldSignature()); | 119 field.FieldSignature()); |
119 field_element->SetAttr(buzz::QName(kAttributeAutofillType), | 120 field_element->SetAttr(buzz::QName(kAttributeAutofillType), |
120 base::IntToString(*field_type)); | 121 base::IntToString(*field_type)); |
121 parent->AddElement(field_element); | 122 parent->AddElement(field_element); |
122 } | 123 } |
123 } | 124 } |
124 | 125 |
125 // Helper for |EncodeFormRequest()| that creates XmlElement for the given field | 126 // Helper for |EncodeFormRequest()| that creates XmlElement for the given field |
126 // in query xml, and also add it to the parent XmlElement. | 127 // in query xml, and also add it to the parent XmlElement. |
127 void EncodeFieldForQuery(const AutofillField& field, | 128 void EncodeFieldForQuery(const AutofillField& field, |
128 buzz::XmlElement* parent) { | 129 buzz::XmlElement* parent) { |
129 buzz::XmlElement *field_element = new buzz::XmlElement( | 130 buzz::XmlElement *field_element = new buzz::XmlElement( |
130 buzz::QName(kXMLElementField)); | 131 buzz::QName(kXMLElementField)); |
131 field_element->SetAttr(buzz::QName(kAttributeSignature), | 132 field_element->SetAttr(buzz::QName(kAttributeSignature), |
132 field.FieldSignature()); | 133 field.FieldSignature()); |
133 parent->AddElement(field_element); | 134 parent->AddElement(field_element); |
134 } | 135 } |
135 | 136 |
136 // Helper for |EncodeFormRequest()| that creates XmlElements for the given field | 137 // Helper for |EncodeFormRequest()| that creates XmlElements for the given field |
137 // in field assignments xml, and also add them to the parent XmlElement. | 138 // in field assignments xml, and also add them to the parent XmlElement. |
138 void EncodeFieldForFieldAssignments(const AutofillField& field, | 139 void EncodeFieldForFieldAssignments(const AutofillField& field, |
139 buzz::XmlElement* parent) { | 140 buzz::XmlElement* parent) { |
140 FieldTypeSet types = field.possible_types(); | 141 ServerFieldTypeSet types = field.possible_types(); |
141 for (FieldTypeSet::iterator field_type = types.begin(); | 142 for (ServerFieldTypeSet::iterator field_type = types.begin(); |
142 field_type != types.end(); ++field_type) { | 143 field_type != types.end(); ++field_type) { |
143 buzz::XmlElement *field_element = new buzz::XmlElement( | 144 buzz::XmlElement *field_element = new buzz::XmlElement( |
144 buzz::QName(kXMLElementFields)); | 145 buzz::QName(kXMLElementFields)); |
145 | 146 |
146 field_element->SetAttr(buzz::QName(kAttributeFieldID), | 147 field_element->SetAttr(buzz::QName(kAttributeFieldID), |
147 field.FieldSignature()); | 148 field.FieldSignature()); |
148 field_element->SetAttr(buzz::QName(kAttributeFieldType), | 149 field_element->SetAttr(buzz::QName(kAttributeFieldType), |
149 base::IntToString(*field_type)); | 150 base::IntToString(*field_type)); |
150 field_element->SetAttr(buzz::QName(kAttributeName), | 151 field_element->SetAttr(buzz::QName(kAttributeName), |
151 UTF16ToUTF8(field.name)); | 152 UTF16ToUTF8(field.name)); |
152 parent->AddElement(field_element); | 153 parent->AddElement(field_element); |
153 } | 154 } |
154 } | 155 } |
155 | 156 |
156 // Returns |true| iff the |token| is a type hint for a contact field, as | 157 // Returns |true| iff the |token| is a type hint for a contact field, as |
157 // specified in the implementation section of http://is.gd/whatwg_autocomplete | 158 // specified in the implementation section of http://is.gd/whatwg_autocomplete |
158 // Note that "fax" and "pager" are intentionally ignored, as Chrome does not | 159 // Note that "fax" and "pager" are intentionally ignored, as Chrome does not |
159 // support filling either type of information. | 160 // support filling either type of information. |
160 bool IsContactTypeHint(const std::string& token) { | 161 bool IsContactTypeHint(const std::string& token) { |
161 return token == "home" || token == "work" || token == "mobile"; | 162 return token == "home" || token == "work" || token == "mobile"; |
162 } | 163 } |
163 | 164 |
164 // Returns |true| iff the |token| is a type hint appropriate for a field of the | 165 // Returns |true| iff the |token| is a type hint appropriate for a field of the |
165 // given |field_type|, as specified in the implementation section of | 166 // given |field_type|, as specified in the implementation section of |
166 // http://is.gd/whatwg_autocomplete | 167 // http://is.gd/whatwg_autocomplete |
| 168 // TODO(isherman): This should use HTML field types, not native ones. |
167 bool ContactTypeHintMatchesFieldType(const std::string& token, | 169 bool ContactTypeHintMatchesFieldType(const std::string& token, |
168 AutofillFieldType field_type) { | 170 ServerFieldType field_type) { |
169 // The "home" and "work" type hints are only appropriate for email and phone | 171 // The "home" and "work" type hints are only appropriate for email and phone |
170 // number field types. | 172 // number field types. |
171 if (token == "home" || token == "work") { | 173 if (token == "home" || token == "work") { |
172 return field_type == EMAIL_ADDRESS || | 174 return field_type == EMAIL_ADDRESS || |
173 (field_type >= PHONE_HOME_NUMBER && | 175 (field_type >= PHONE_HOME_NUMBER && |
174 field_type <= PHONE_HOME_WHOLE_NUMBER); | 176 field_type <= PHONE_HOME_WHOLE_NUMBER); |
175 } | 177 } |
176 | 178 |
177 // The "mobile" type hint is only appropriate for phone number field types. | 179 // The "mobile" type hint is only appropriate for phone number field types. |
178 // Note that "fax" and "pager" are intentionally ignored, as Chrome does not | 180 // Note that "fax" and "pager" are intentionally ignored, as Chrome does not |
179 // support filling either type of information. | 181 // support filling either type of information. |
180 if (token == "mobile") { | 182 if (token == "mobile") { |
181 return field_type >= PHONE_HOME_NUMBER && | 183 return field_type >= PHONE_HOME_NUMBER && |
182 field_type <= PHONE_HOME_WHOLE_NUMBER; | 184 field_type <= PHONE_HOME_WHOLE_NUMBER; |
183 } | 185 } |
184 | 186 |
185 return false; | 187 return false; |
186 } | 188 } |
187 | 189 |
188 // Returns the Chrome Autofill-supported field type corresponding to the given | 190 // Returns the Chrome Autofill-supported field type corresponding to the given |
189 // |autocomplete_type|, if there is one, in the context of the given |field|. | 191 // |autocomplete_type|, if there is one, in the context of the given |field|. |
190 // Chrome Autofill supports a subset of the field types listed at | 192 // Chrome Autofill supports a subset of the field types listed at |
191 // http://is.gd/whatwg_autocomplete | 193 // http://is.gd/whatwg_autocomplete |
192 AutofillFieldType FieldTypeFromAutocompleteType( | 194 // TODO(isherman): This should use HTML field types, not native ones. |
| 195 ServerFieldType FieldTypeFromAutocompleteType( |
193 const std::string& autocomplete_type, | 196 const std::string& autocomplete_type, |
194 const AutofillField& field) { | 197 const AutofillField& field) { |
195 if (autocomplete_type == "name") | 198 if (autocomplete_type == "name") |
196 return NAME_FULL; | 199 return NAME_FULL; |
197 | 200 |
198 if (autocomplete_type == "given-name") | 201 if (autocomplete_type == "given-name") |
199 return NAME_FIRST; | 202 return NAME_FIRST; |
200 | 203 |
201 if (autocomplete_type == "additional-name") { | 204 if (autocomplete_type == "additional-name") { |
202 if (field.max_length == 1) | 205 if (field.max_length == 1) |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 // First, try to detect field types based on each field's |autocomplete| | 375 // First, try to detect field types based on each field's |autocomplete| |
373 // attribute value. If there is at least one form field that specifies an | 376 // attribute value. If there is at least one form field that specifies an |
374 // autocomplete type hint, don't try to apply other heuristics to match fields | 377 // autocomplete type hint, don't try to apply other heuristics to match fields |
375 // in this form. | 378 // in this form. |
376 bool has_author_specified_sections; | 379 bool has_author_specified_sections; |
377 ParseFieldTypesFromAutocompleteAttributes(PARSE_FOR_AUTOFILL, | 380 ParseFieldTypesFromAutocompleteAttributes(PARSE_FOR_AUTOFILL, |
378 &has_author_specified_types_, | 381 &has_author_specified_types_, |
379 &has_author_specified_sections); | 382 &has_author_specified_sections); |
380 | 383 |
381 if (!has_author_specified_types_) { | 384 if (!has_author_specified_types_) { |
382 FieldTypeMap field_type_map; | 385 ServerFieldTypeMap field_type_map; |
383 FormField::ParseFormFields(fields_.get(), &field_type_map); | 386 FormField::ParseFormFields(fields_.get(), &field_type_map); |
384 for (size_t index = 0; index < field_count(); index++) { | 387 for (size_t i = 0; i < field_count(); ++i) { |
385 AutofillField* field = fields_[index]; | 388 AutofillField* field = fields_[i]; |
386 FieldTypeMap::iterator iter = field_type_map.find(field->unique_name()); | 389 ServerFieldTypeMap::iterator iter = |
| 390 field_type_map.find(field->unique_name()); |
387 if (iter != field_type_map.end()) | 391 if (iter != field_type_map.end()) |
388 field->set_heuristic_type(iter->second); | 392 field->set_heuristic_type(iter->second); |
389 } | 393 } |
390 } | 394 } |
391 | 395 |
392 UpdateAutofillCount(); | 396 UpdateAutofillCount(); |
393 IdentifySections(has_author_specified_sections); | 397 IdentifySections(has_author_specified_sections); |
394 | 398 |
395 if (IsAutofillable(true)) { | 399 if (IsAutofillable(true)) { |
396 metric_logger.LogDeveloperEngagementMetric( | 400 metric_logger.LogDeveloperEngagementMetric( |
397 AutofillMetrics::FILLABLE_FORM_PARSED); | 401 AutofillMetrics::FILLABLE_FORM_PARSED); |
398 if (has_author_specified_types_) { | 402 if (has_author_specified_types_) { |
399 metric_logger.LogDeveloperEngagementMetric( | 403 metric_logger.LogDeveloperEngagementMetric( |
400 AutofillMetrics::FILLABLE_FORM_CONTAINS_TYPE_HINTS); | 404 AutofillMetrics::FILLABLE_FORM_CONTAINS_TYPE_HINTS); |
401 } | 405 } |
402 } | 406 } |
403 } | 407 } |
404 | 408 |
405 bool FormStructure::EncodeUploadRequest( | 409 bool FormStructure::EncodeUploadRequest( |
406 const FieldTypeSet& available_field_types, | 410 const ServerFieldTypeSet& available_field_types, |
407 bool form_was_autofilled, | 411 bool form_was_autofilled, |
408 std::string* encoded_xml) const { | 412 std::string* encoded_xml) const { |
409 DCHECK(ShouldBeCrowdsourced()); | 413 DCHECK(ShouldBeCrowdsourced()); |
410 | 414 |
411 // Verify that |available_field_types| agrees with the possible field types we | 415 // Verify that |available_field_types| agrees with the possible field types we |
412 // are uploading. | 416 // are uploading. |
413 for (std::vector<AutofillField*>::const_iterator field = begin(); | 417 for (std::vector<AutofillField*>::const_iterator field = begin(); |
414 field != end(); | 418 field != end(); |
415 ++field) { | 419 ++field) { |
416 for (FieldTypeSet::const_iterator type = (*field)->possible_types().begin(); | 420 for (ServerFieldTypeSet::const_iterator type = |
| 421 (*field)->possible_types().begin(); |
417 type != (*field)->possible_types().end(); | 422 type != (*field)->possible_types().end(); |
418 ++type) { | 423 ++type) { |
419 DCHECK(*type == UNKNOWN_TYPE || | 424 DCHECK(*type == UNKNOWN_TYPE || |
420 *type == EMPTY_TYPE || | 425 *type == EMPTY_TYPE || |
421 available_field_types.count(*type)); | 426 available_field_types.count(*type)); |
422 } | 427 } |
423 } | 428 } |
424 | 429 |
425 // Set up the <autofillupload> element and its attributes. | 430 // Set up the <autofillupload> element and its attributes. |
426 buzz::XmlElement autofill_request_xml( | 431 buzz::XmlElement autofill_request_xml( |
(...skipping 14 matching lines...) Expand all Loading... |
441 *encoded_xml = kXMLDeclaration; | 446 *encoded_xml = kXMLDeclaration; |
442 *encoded_xml += autofill_request_xml.Str().c_str(); | 447 *encoded_xml += autofill_request_xml.Str().c_str(); |
443 | 448 |
444 // To enable this logging, run with the flag --vmodule="form_structure=2". | 449 // To enable this logging, run with the flag --vmodule="form_structure=2". |
445 VLOG(2) << "\n" << *encoded_xml; | 450 VLOG(2) << "\n" << *encoded_xml; |
446 | 451 |
447 return true; | 452 return true; |
448 } | 453 } |
449 | 454 |
450 bool FormStructure::EncodeFieldAssignments( | 455 bool FormStructure::EncodeFieldAssignments( |
451 const FieldTypeSet& available_field_types, | 456 const ServerFieldTypeSet& available_field_types, |
452 std::string* encoded_xml) const { | 457 std::string* encoded_xml) const { |
453 DCHECK(ShouldBeCrowdsourced()); | 458 DCHECK(ShouldBeCrowdsourced()); |
454 | 459 |
455 // Set up the <fieldassignments> element and its attributes. | 460 // Set up the <fieldassignments> element and its attributes. |
456 buzz::XmlElement autofill_request_xml( | 461 buzz::XmlElement autofill_request_xml( |
457 (buzz::QName(kXMLElementFieldAssignments))); | 462 (buzz::QName(kXMLElementFieldAssignments))); |
458 autofill_request_xml.SetAttr(buzz::QName(kAttributeFormSignature), | 463 autofill_request_xml.SetAttr(buzz::QName(kAttributeFormSignature), |
459 FormSignature()); | 464 FormSignature()); |
460 | 465 |
461 if (!EncodeFormRequest(FormStructure::FIELD_ASSIGNMENTS, | 466 if (!EncodeFormRequest(FormStructure::FIELD_ASSIGNMENTS, |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
590 continue; | 595 continue; |
591 | 596 |
592 // In some cases *successful* response does not return all the fields. | 597 // In some cases *successful* response does not return all the fields. |
593 // Quit the update of the types then. | 598 // Quit the update of the types then. |
594 if (current_info == field_infos.end()) | 599 if (current_info == field_infos.end()) |
595 break; | 600 break; |
596 | 601 |
597 // UNKNOWN_TYPE is reserved for use by the client. | 602 // UNKNOWN_TYPE is reserved for use by the client. |
598 DCHECK_NE(current_info->field_type, UNKNOWN_TYPE); | 603 DCHECK_NE(current_info->field_type, UNKNOWN_TYPE); |
599 | 604 |
600 AutofillFieldType heuristic_type = (*field)->type(); | 605 ServerFieldType heuristic_type = (*field)->heuristic_type(); |
601 if (heuristic_type != UNKNOWN_TYPE) | 606 if (heuristic_type != UNKNOWN_TYPE) |
602 heuristics_detected_fillable_field = true; | 607 heuristics_detected_fillable_field = true; |
603 | 608 |
604 (*field)->set_server_type(current_info->field_type); | 609 (*field)->set_server_type(current_info->field_type); |
605 if (heuristic_type != (*field)->type()) | 610 if (heuristic_type != (*field)->Type().server_type()) |
606 query_response_overrode_heuristics = true; | 611 query_response_overrode_heuristics = true; |
607 | 612 |
608 // Copy default value into the field if available. | 613 // Copy default value into the field if available. |
609 if (!current_info->default_value.empty()) | 614 if (!current_info->default_value.empty()) |
610 (*field)->set_default_value(current_info->default_value); | 615 (*field)->set_default_value(current_info->default_value); |
611 | 616 |
612 ++current_info; | 617 ++current_info; |
613 } | 618 } |
614 | 619 |
615 form->UpdateAutofillCount(); | 620 form->UpdateAutofillCount(); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 field != form_structure->fields_.end(); ++field) { | 656 field != form_structure->fields_.end(); ++field) { |
652 form.data.fields.push_back(FormFieldData(**field)); | 657 form.data.fields.push_back(FormFieldData(**field)); |
653 | 658 |
654 FormFieldDataPredictions annotated_field; | 659 FormFieldDataPredictions annotated_field; |
655 annotated_field.signature = (*field)->FieldSignature(); | 660 annotated_field.signature = (*field)->FieldSignature(); |
656 annotated_field.heuristic_type = | 661 annotated_field.heuristic_type = |
657 AutofillType::FieldTypeToString((*field)->heuristic_type()); | 662 AutofillType::FieldTypeToString((*field)->heuristic_type()); |
658 annotated_field.server_type = | 663 annotated_field.server_type = |
659 AutofillType::FieldTypeToString((*field)->server_type()); | 664 AutofillType::FieldTypeToString((*field)->server_type()); |
660 annotated_field.overall_type = | 665 annotated_field.overall_type = |
661 AutofillType::FieldTypeToString((*field)->type()); | 666 AutofillType::FieldTypeToString((*field)->Type().server_type()); |
662 form.fields.push_back(annotated_field); | 667 form.fields.push_back(annotated_field); |
663 } | 668 } |
664 | 669 |
665 forms->push_back(form); | 670 forms->push_back(form); |
666 } | 671 } |
667 } | 672 } |
668 | 673 |
669 std::string FormStructure::FormSignature() const { | 674 std::string FormStructure::FormSignature() const { |
670 std::string scheme(target_url_.scheme()); | 675 std::string scheme(target_url_.scheme()); |
671 std::string host(target_url_.host()); | 676 std::string host(target_url_.host()); |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
799 size_t num_detected_field_types = 0; | 804 size_t num_detected_field_types = 0; |
800 bool did_autofill_all_possible_fields = true; | 805 bool did_autofill_all_possible_fields = true; |
801 bool did_autofill_some_possible_fields = false; | 806 bool did_autofill_some_possible_fields = false; |
802 for (size_t i = 0; i < field_count(); ++i) { | 807 for (size_t i = 0; i < field_count(); ++i) { |
803 const AutofillField* field = this->field(i); | 808 const AutofillField* field = this->field(i); |
804 metric_logger.LogQualityMetric(AutofillMetrics::FIELD_SUBMITTED, | 809 metric_logger.LogQualityMetric(AutofillMetrics::FIELD_SUBMITTED, |
805 experiment_id); | 810 experiment_id); |
806 | 811 |
807 // No further logging for empty fields nor for fields where the entered data | 812 // No further logging for empty fields nor for fields where the entered data |
808 // does not appear to already exist in the user's stored Autofill data. | 813 // does not appear to already exist in the user's stored Autofill data. |
809 const FieldTypeSet& field_types = field->possible_types(); | 814 const ServerFieldTypeSet& field_types = field->possible_types(); |
810 DCHECK(!field_types.empty()); | 815 DCHECK(!field_types.empty()); |
811 if (field_types.count(EMPTY_TYPE) || field_types.count(UNKNOWN_TYPE)) | 816 if (field_types.count(EMPTY_TYPE) || field_types.count(UNKNOWN_TYPE)) |
812 continue; | 817 continue; |
813 | 818 |
814 ++num_detected_field_types; | 819 ++num_detected_field_types; |
815 if (field->is_autofilled) | 820 if (field->is_autofilled) |
816 did_autofill_some_possible_fields = true; | 821 did_autofill_some_possible_fields = true; |
817 else | 822 else |
818 did_autofill_all_possible_fields = false; | 823 did_autofill_all_possible_fields = false; |
819 | 824 |
820 // Collapse field types that Chrome treats as identical, e.g. home and | 825 // Collapse field types that Chrome treats as identical, e.g. home and |
821 // billing address fields. | 826 // billing address fields. |
822 FieldTypeSet collapsed_field_types; | 827 ServerFieldTypeSet collapsed_field_types; |
823 for (FieldTypeSet::const_iterator it = field_types.begin(); | 828 for (ServerFieldTypeSet::const_iterator it = field_types.begin(); |
824 it != field_types.end(); | 829 it != field_types.end(); |
825 ++it) { | 830 ++it) { |
826 // Since we currently only support US phone numbers, the (city code + main | 831 // Since we currently only support US phone numbers, the (city code + main |
827 // digits) number is almost always identical to the whole phone number. | 832 // digits) number is almost always identical to the whole phone number. |
828 // TODO(isherman): Improve this logic once we add support for | 833 // TODO(isherman): Improve this logic once we add support for |
829 // international numbers. | 834 // international numbers. |
830 if (*it == PHONE_HOME_CITY_AND_NUMBER) | 835 if (*it == PHONE_HOME_CITY_AND_NUMBER) |
831 collapsed_field_types.insert(PHONE_HOME_WHOLE_NUMBER); | 836 collapsed_field_types.insert(PHONE_HOME_WHOLE_NUMBER); |
832 else | 837 else |
833 collapsed_field_types.insert(AutofillType::GetEquivalentFieldType(*it)); | 838 collapsed_field_types.insert(AutofillType::GetEquivalentFieldType(*it)); |
834 } | 839 } |
835 | 840 |
836 // Capture the field's type, if it is unambiguous. | 841 // Capture the field's type, if it is unambiguous. |
837 AutofillFieldType field_type = UNKNOWN_TYPE; | 842 ServerFieldType field_type = UNKNOWN_TYPE; |
838 if (collapsed_field_types.size() == 1) | 843 if (collapsed_field_types.size() == 1) |
839 field_type = *collapsed_field_types.begin(); | 844 field_type = *collapsed_field_types.begin(); |
840 | 845 |
841 AutofillFieldType heuristic_type = field->heuristic_type(); | 846 ServerFieldType heuristic_type = field->heuristic_type(); |
842 AutofillFieldType server_type = field->server_type(); | 847 ServerFieldType server_type = field->server_type(); |
843 AutofillFieldType predicted_type = field->type(); | 848 ServerFieldType predicted_type = field->Type().server_type(); |
844 | 849 |
845 // Log heuristic, server, and overall type quality metrics, independently of | 850 // Log heuristic, server, and overall type quality metrics, independently of |
846 // whether the field was autofilled. | 851 // whether the field was autofilled. |
847 if (heuristic_type == UNKNOWN_TYPE) { | 852 if (heuristic_type == UNKNOWN_TYPE) { |
848 metric_logger.LogHeuristicTypePrediction(AutofillMetrics::TYPE_UNKNOWN, | 853 metric_logger.LogHeuristicTypePrediction(AutofillMetrics::TYPE_UNKNOWN, |
849 field_type, experiment_id); | 854 field_type, experiment_id); |
850 } else if (field_types.count(heuristic_type)) { | 855 } else if (field_types.count(heuristic_type)) { |
851 metric_logger.LogHeuristicTypePrediction(AutofillMetrics::TYPE_MATCH, | 856 metric_logger.LogHeuristicTypePrediction(AutofillMetrics::TYPE_MATCH, |
852 field_type, experiment_id); | 857 field_type, experiment_id); |
853 } else { | 858 } else { |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1120 // Tokenize the attribute value. Per the spec, the tokens are parsed in | 1125 // Tokenize the attribute value. Per the spec, the tokens are parsed in |
1121 // reverse order. | 1126 // reverse order. |
1122 std::vector<std::string> tokens; | 1127 std::vector<std::string> tokens; |
1123 Tokenize(autocomplete_attribute, " ", &tokens); | 1128 Tokenize(autocomplete_attribute, " ", &tokens); |
1124 | 1129 |
1125 // The final token must be the field type. | 1130 // The final token must be the field type. |
1126 // If it is not one of the known types, abort. | 1131 // If it is not one of the known types, abort. |
1127 DCHECK(!tokens.empty()); | 1132 DCHECK(!tokens.empty()); |
1128 std::string field_type_token = tokens.back(); | 1133 std::string field_type_token = tokens.back(); |
1129 tokens.pop_back(); | 1134 tokens.pop_back(); |
1130 AutofillFieldType field_type = | 1135 ServerFieldType field_type = |
1131 FieldTypeFromAutocompleteType(field_type_token, *field); | 1136 FieldTypeFromAutocompleteType(field_type_token, *field); |
1132 if (field_type == UNKNOWN_TYPE) | 1137 if (field_type == UNKNOWN_TYPE) |
1133 continue; | 1138 continue; |
1134 | 1139 |
1135 // The preceding token, if any, may be a type hint. | 1140 // The preceding token, if any, may be a type hint. |
1136 if (!tokens.empty() && IsContactTypeHint(tokens.back())) { | 1141 if (!tokens.empty() && IsContactTypeHint(tokens.back())) { |
1137 // If it is, it must match the field type; otherwise, abort. | 1142 // If it is, it must match the field type; otherwise, abort. |
1138 // Note that an invalid token invalidates the entire attribute value, even | 1143 // Note that an invalid token invalidates the entire attribute value, even |
1139 // if the other tokens are valid. | 1144 // if the other tokens are valid. |
1140 if (!ContactTypeHintMatchesFieldType(tokens.back(), field_type)) | 1145 if (!ContactTypeHintMatchesFieldType(tokens.back(), field_type)) |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1198 | 1203 |
1199 void FormStructure::IdentifySections(bool has_author_specified_sections) { | 1204 void FormStructure::IdentifySections(bool has_author_specified_sections) { |
1200 if (fields_.empty()) | 1205 if (fields_.empty()) |
1201 return; | 1206 return; |
1202 | 1207 |
1203 if (!has_author_specified_sections) { | 1208 if (!has_author_specified_sections) { |
1204 // Name sections after the first field in the section. | 1209 // Name sections after the first field in the section. |
1205 base::string16 current_section = fields_.front()->unique_name(); | 1210 base::string16 current_section = fields_.front()->unique_name(); |
1206 | 1211 |
1207 // Keep track of the types we've seen in this section. | 1212 // Keep track of the types we've seen in this section. |
1208 std::set<AutofillFieldType> seen_types; | 1213 std::set<ServerFieldType> seen_types; |
1209 AutofillFieldType previous_type = UNKNOWN_TYPE; | 1214 ServerFieldType previous_type = UNKNOWN_TYPE; |
1210 | 1215 |
1211 for (std::vector<AutofillField*>::iterator field = fields_.begin(); | 1216 for (std::vector<AutofillField*>::iterator field = fields_.begin(); |
1212 field != fields_.end(); ++field) { | 1217 field != fields_.end(); ++field) { |
1213 const AutofillFieldType current_type = | 1218 const ServerFieldType current_type = |
1214 AutofillType::GetEquivalentFieldType((*field)->type()); | 1219 AutofillType::GetEquivalentFieldType((*field)->Type().server_type()); |
1215 | 1220 |
1216 bool already_saw_current_type = seen_types.count(current_type) > 0; | 1221 bool already_saw_current_type = seen_types.count(current_type) > 0; |
1217 | 1222 |
1218 // Forms often ask for multiple phone numbers -- e.g. both a daytime and | 1223 // Forms often ask for multiple phone numbers -- e.g. both a daytime and |
1219 // evening phone number. Our phone number detection is also generally a | 1224 // evening phone number. Our phone number detection is also generally a |
1220 // little off. Hence, ignore this field type as a signal here. | 1225 // little off. Hence, ignore this field type as a signal here. |
1221 if (AutofillType(current_type).group() == PHONE_HOME) | 1226 if (AutofillType(current_type).group() == PHONE_HOME) |
1222 already_saw_current_type = false; | 1227 already_saw_current_type = false; |
1223 | 1228 |
1224 // Some forms have adjacent fields of the same type. Two common examples: | 1229 // Some forms have adjacent fields of the same type. Two common examples: |
(...skipping 18 matching lines...) Expand all Loading... |
1243 | 1248 |
1244 seen_types.insert(current_type); | 1249 seen_types.insert(current_type); |
1245 (*field)->set_section(UTF16ToUTF8(current_section)); | 1250 (*field)->set_section(UTF16ToUTF8(current_section)); |
1246 } | 1251 } |
1247 } | 1252 } |
1248 | 1253 |
1249 // Ensure that credit card and address fields are in separate sections. | 1254 // Ensure that credit card and address fields are in separate sections. |
1250 // This simplifies the section-aware logic in autofill_manager.cc. | 1255 // This simplifies the section-aware logic in autofill_manager.cc. |
1251 for (std::vector<AutofillField*>::iterator field = fields_.begin(); | 1256 for (std::vector<AutofillField*>::iterator field = fields_.begin(); |
1252 field != fields_.end(); ++field) { | 1257 field != fields_.end(); ++field) { |
1253 FieldTypeGroup field_type_group = AutofillType((*field)->type()).group(); | 1258 FieldTypeGroup field_type_group = (*field)->Type().group(); |
1254 if (field_type_group == CREDIT_CARD) | 1259 if (field_type_group == CREDIT_CARD) |
1255 (*field)->set_section((*field)->section() + "-cc"); | 1260 (*field)->set_section((*field)->section() + "-cc"); |
1256 else | 1261 else |
1257 (*field)->set_section((*field)->section() + "-default"); | 1262 (*field)->set_section((*field)->section() + "-default"); |
1258 } | 1263 } |
1259 } | 1264 } |
1260 | 1265 |
1261 } // namespace autofill | 1266 } // namespace autofill |
OLD | NEW |