| 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 |