Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(270)

Side by Side Diff: components/autofill/core/browser/form_structure.cc

Issue 22009003: [Autofill] Distinguish between native field types and potentially HTML field types. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « components/autofill/core/browser/form_structure.h ('k') | components/autofill/core/browser/form_structure_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698