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

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

Issue 22040002: [Autofill] Add a separate enumeration for HTML field type hints. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add docs 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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 const char kAcceptedFeaturesExperiment[] = "e"; // e=experiments 50 const char kAcceptedFeaturesExperiment[] = "e"; // e=experiments
51 const char kAcceptedFeaturesAutocheckoutExperiment[] = "a,e"; // a=autocheckout 51 const char kAcceptedFeaturesAutocheckoutExperiment[] = "a,e"; // a=autocheckout
52 const char kClientVersion[] = "6.1.1715.1442/en (GGLL)"; 52 const char kClientVersion[] = "6.1.1715.1442/en (GGLL)";
53 const char kXMLDeclaration[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; 53 const char kXMLDeclaration[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
54 const char kXMLElementAutofillQuery[] = "autofillquery"; 54 const char kXMLElementAutofillQuery[] = "autofillquery";
55 const char kXMLElementAutofillUpload[] = "autofillupload"; 55 const char kXMLElementAutofillUpload[] = "autofillupload";
56 const char kXMLElementFieldAssignments[] = "fieldassignments"; 56 const char kXMLElementFieldAssignments[] = "fieldassignments";
57 const char kXMLElementField[] = "field"; 57 const char kXMLElementField[] = "field";
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 kBillingMode[] = "billing";
61 const char kShippingSection[] = "shipping"; 61 const char kShippingMode[] = "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 NativeFieldTypeSet& available_field_types) { 68 std::string EncodeFieldTypes(const NativeFieldTypeSet& 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;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 // specified in the implementation section of http://is.gd/whatwg_autocomplete 158 // specified in the implementation section of http://is.gd/whatwg_autocomplete
159 // 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
160 // support filling either type of information. 160 // support filling either type of information.
161 bool IsContactTypeHint(const std::string& token) { 161 bool IsContactTypeHint(const std::string& token) {
162 return token == "home" || token == "work" || token == "mobile"; 162 return token == "home" || token == "work" || token == "mobile";
163 } 163 }
164 164
165 // 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
166 // given |field_type|, as specified in the implementation section of 166 // given |field_type|, as specified in the implementation section of
167 // http://is.gd/whatwg_autocomplete 167 // http://is.gd/whatwg_autocomplete
168 // TODO(isherman): This should use HTML field types, not native ones.
169 bool ContactTypeHintMatchesFieldType(const std::string& token, 168 bool ContactTypeHintMatchesFieldType(const std::string& token,
170 NativeFieldType field_type) { 169 HtmlFieldType field_type) {
171 // The "home" and "work" type hints are only appropriate for email and phone 170 // The "home" and "work" type hints are only appropriate for email and phone
172 // number field types. 171 // number field types.
173 if (token == "home" || token == "work") { 172 if (token == "home" || token == "work") {
174 return field_type == EMAIL_ADDRESS || 173 return field_type == HTML_TYPE_EMAIL ||
175 (field_type >= PHONE_HOME_NUMBER && 174 (field_type >= HTML_TYPE_TEL &&
176 field_type <= PHONE_HOME_WHOLE_NUMBER); 175 field_type <= HTML_TYPE_TEL_LOCAL_SUFFIX);
177 } 176 }
178 177
179 // The "mobile" type hint is only appropriate for phone number field types. 178 // The "mobile" type hint is only appropriate for phone number field types.
180 // Note that "fax" and "pager" are intentionally ignored, as Chrome does not 179 // Note that "fax" and "pager" are intentionally ignored, as Chrome does not
181 // support filling either type of information. 180 // support filling either type of information.
182 if (token == "mobile") { 181 if (token == "mobile") {
183 return field_type >= PHONE_HOME_NUMBER && 182 return field_type >= HTML_TYPE_TEL &&
184 field_type <= PHONE_HOME_WHOLE_NUMBER; 183 field_type <= HTML_TYPE_TEL_LOCAL_SUFFIX;
185 } 184 }
186 185
187 return false; 186 return false;
188 } 187 }
189 188
190 // Returns the Chrome Autofill-supported field type corresponding to the given 189 // Returns the Chrome Autofill-supported field type corresponding to the given
191 // |autocomplete_type|, if there is one, in the context of the given |field|. 190 // |autocomplete_type|, if there is one, in the context of the given |field|.
192 // Chrome Autofill supports a subset of the field types listed at 191 // Chrome Autofill supports a subset of the field types listed at
193 // http://is.gd/whatwg_autocomplete 192 // http://is.gd/whatwg_autocomplete
194 // TODO(isherman): This should use HTML field types, not native ones. 193 HtmlFieldType FieldTypeFromAutocompleteType(
Evan Stade 2013/08/05 18:47:24 maybe you should rename this to FieldTypeFromAutoc
Ilya Sherman 2013/08/06 05:05:39 Done.
195 NativeFieldType FieldTypeFromAutocompleteType(
196 const std::string& autocomplete_type, 194 const std::string& autocomplete_type,
197 const AutofillField& field) { 195 const AutofillField& field) {
198 if (autocomplete_type == "name") 196 if (autocomplete_type == "name")
199 return NAME_FULL; 197 return HTML_TYPE_NAME;
200 198
201 if (autocomplete_type == "given-name") 199 if (autocomplete_type == "given-name")
202 return NAME_FIRST; 200 return HTML_TYPE_GIVEN_NAME;
203 201
204 if (autocomplete_type == "additional-name") { 202 if (autocomplete_type == "additional-name") {
205 if (field.max_length == 1) 203 if (field.max_length == 1)
206 return NAME_MIDDLE_INITIAL; 204 return HTML_TYPE_ADDITIONAL_NAME_INITIAL;
207 else 205 else
208 return NAME_MIDDLE; 206 return HTML_TYPE_ADDITIONAL_NAME;
209 } 207 }
210 208
211 if (autocomplete_type == "family-name") 209 if (autocomplete_type == "family-name")
212 return NAME_LAST; 210 return HTML_TYPE_FAMILY_NAME;
213
214 if (autocomplete_type == "honorific-suffix")
215 return NAME_SUFFIX;
216 211
217 if (autocomplete_type == "organization") 212 if (autocomplete_type == "organization")
218 return COMPANY_NAME; 213 return HTML_TYPE_ORGANIZATION;
214
215 if (autocomplete_type == "street-address")
216 return HTML_TYPE_STREET_ADDRESS;
219 217
220 if (autocomplete_type == "address-line1") 218 if (autocomplete_type == "address-line1")
221 return ADDRESS_HOME_LINE1; 219 return HTML_TYPE_ADDRESS_LINE1;
222 220
223 if (autocomplete_type == "address-line2") 221 if (autocomplete_type == "address-line2")
224 return ADDRESS_HOME_LINE2; 222 return HTML_TYPE_ADDRESS_LINE2;
225 223
226 if (autocomplete_type == "locality") 224 if (autocomplete_type == "locality")
227 return ADDRESS_HOME_CITY; 225 return HTML_TYPE_LOCALITY;
228 226
229 if (autocomplete_type == "region") 227 if (autocomplete_type == "region")
230 return ADDRESS_HOME_STATE; 228 return HTML_TYPE_REGION;
231 229
232 if (autocomplete_type == "country") 230 if (autocomplete_type == "country")
233 return ADDRESS_HOME_COUNTRY; 231 return HTML_TYPE_COUNTRY_CODE;
232
233 if (autocomplete_type == "country-name")
234 return HTML_TYPE_COUNTRY_NAME;
234 235
235 if (autocomplete_type == "postal-code") 236 if (autocomplete_type == "postal-code")
236 return ADDRESS_HOME_ZIP; 237 return HTML_TYPE_POSTAL_CODE;
237 238
238 if (autocomplete_type == "cc-name") 239 if (autocomplete_type == "cc-name")
239 return CREDIT_CARD_NAME; 240 return HTML_TYPE_CREDIT_CARD_NAME;
240 241
241 if (autocomplete_type == "cc-number") 242 if (autocomplete_type == "cc-number")
242 return CREDIT_CARD_NUMBER; 243 return HTML_TYPE_CREDIT_CARD_NUMBER;
243 244
244 if (autocomplete_type == "cc-exp") { 245 if (autocomplete_type == "cc-exp") {
245 if (field.max_length == 5) 246 if (field.max_length == 5)
246 return CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR; 247 return HTML_TYPE_CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR;
247 else 248 else
248 return CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR; 249 return HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR;
249 } 250 }
250 251
251 if (autocomplete_type == "cc-exp-month") 252 if (autocomplete_type == "cc-exp-month")
252 return CREDIT_CARD_EXP_MONTH; 253 return HTML_TYPE_CREDIT_CARD_EXP_MONTH;
253 254
254 if (autocomplete_type == "cc-exp-year") { 255 if (autocomplete_type == "cc-exp-year") {
255 if (field.max_length == 2) 256 if (field.max_length == 2)
256 return CREDIT_CARD_EXP_2_DIGIT_YEAR; 257 return HTML_TYPE_CREDIT_CARD_EXP_2_DIGIT_YEAR;
257 else 258 else
258 return CREDIT_CARD_EXP_4_DIGIT_YEAR; 259 return HTML_TYPE_CREDIT_CARD_EXP_4_DIGIT_YEAR;
259 } 260 }
260 261
261 if (autocomplete_type == "cc-csc") 262 if (autocomplete_type == "cc-csc")
262 return CREDIT_CARD_VERIFICATION_CODE; 263 return HTML_TYPE_CREDIT_CARD_VERIFICATION_CODE;
263 264
264 if (autocomplete_type == "cc-type") 265 if (autocomplete_type == "cc-type")
265 return CREDIT_CARD_TYPE; 266 return HTML_TYPE_CREDIT_CARD_TYPE;
266 267
267 if (autocomplete_type == "tel") 268 if (autocomplete_type == "tel")
268 return PHONE_HOME_WHOLE_NUMBER; 269 return HTML_TYPE_TEL;
269 270
270 if (autocomplete_type == "tel-country-code") 271 if (autocomplete_type == "tel-country-code")
271 return PHONE_HOME_COUNTRY_CODE; 272 return HTML_TYPE_TEL_COUNTRY_CODE;
272 273
273 if (autocomplete_type == "tel-national") 274 if (autocomplete_type == "tel-national")
274 return PHONE_HOME_CITY_AND_NUMBER; 275 return HTML_TYPE_TEL_NATIONAL;
275 276
276 if (autocomplete_type == "tel-area-code") 277 if (autocomplete_type == "tel-area-code")
277 return PHONE_HOME_CITY_CODE; 278 return HTML_TYPE_TEL_AREA_CODE;
278 279
279 if (autocomplete_type == "tel-local") 280 if (autocomplete_type == "tel-local")
280 return PHONE_HOME_NUMBER; 281 return HTML_TYPE_TEL_LOCAL;
281 282
282 if (autocomplete_type == "tel-local-prefix") 283 if (autocomplete_type == "tel-local-prefix")
283 return PHONE_HOME_NUMBER; 284 return HTML_TYPE_TEL_LOCAL_PREFIX;
284 285
285 if (autocomplete_type == "tel-local-suffix") 286 if (autocomplete_type == "tel-local-suffix")
286 return PHONE_HOME_NUMBER; 287 return HTML_TYPE_TEL_LOCAL_SUFFIX;
287 288
288 if (autocomplete_type == "email") 289 if (autocomplete_type == "email")
289 return EMAIL_ADDRESS; 290 return HTML_TYPE_EMAIL;
290 291
291 return UNKNOWN_TYPE; 292 return HTML_TYPE_UNKNOWN;
292 } 293 }
293 294
294 std::string StripDigitsIfRequired(const base::string16& input) { 295 std::string StripDigitsIfRequired(const base::string16& input) {
295 UErrorCode status = U_ZERO_ERROR; 296 UErrorCode status = U_ZERO_ERROR;
296 CR_DEFINE_STATIC_LOCAL(icu::UnicodeString, icu_pattern, 297 CR_DEFINE_STATIC_LOCAL(icu::UnicodeString, icu_pattern,
297 (kIgnorePatternInFieldName)); 298 (kIgnorePatternInFieldName));
298 CR_DEFINE_STATIC_LOCAL(icu::RegexMatcher, matcher, 299 CR_DEFINE_STATIC_LOCAL(icu::RegexMatcher, matcher,
299 (icu_pattern, UREGEX_CASE_INSENSITIVE, status)); 300 (icu_pattern, UREGEX_CASE_INSENSITIVE, status));
300 DCHECK_EQ(status, U_ZERO_ERROR); 301 DCHECK_EQ(status, U_ZERO_ERROR);
301 302
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 371
371 FormStructure::~FormStructure() {} 372 FormStructure::~FormStructure() {}
372 373
373 void FormStructure::DetermineHeuristicTypes( 374 void FormStructure::DetermineHeuristicTypes(
374 const AutofillMetrics& metric_logger) { 375 const AutofillMetrics& metric_logger) {
375 // First, try to detect field types based on each field's |autocomplete| 376 // First, try to detect field types based on each field's |autocomplete|
376 // attribute value. If there is at least one form field that specifies an 377 // attribute value. If there is at least one form field that specifies an
377 // autocomplete type hint, don't try to apply other heuristics to match fields 378 // autocomplete type hint, don't try to apply other heuristics to match fields
378 // in this form. 379 // in this form.
379 bool has_author_specified_sections; 380 bool has_author_specified_sections;
380 ParseFieldTypesFromAutocompleteAttributes(PARSE_FOR_AUTOFILL, 381 ParseFieldTypesFromAutocompleteAttributes(&has_author_specified_types_,
381 &has_author_specified_types_,
382 &has_author_specified_sections); 382 &has_author_specified_sections);
383 383
384 if (!has_author_specified_types_) { 384 if (!has_author_specified_types_) {
385 NativeFieldTypeMap field_type_map; 385 NativeFieldTypeMap field_type_map;
386 FormField::ParseFormFields(fields_.get(), &field_type_map); 386 FormField::ParseFormFields(fields_.get(), &field_type_map);
387 for (size_t i = 0; i < field_count(); ++i) { 387 for (size_t i = 0; i < field_count(); ++i) {
388 AutofillField* field = fields_[i]; 388 AutofillField* field = fields_[i];
389 NativeFieldTypeMap::iterator iter = 389 NativeFieldTypeMap::iterator iter =
390 field_type_map.find(field->unique_name()); 390 field_type_map.find(field->unique_name());
391 if (iter != field_type_map.end()) 391 if (iter != field_type_map.end())
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 break; 600 break;
601 601
602 // UNKNOWN_TYPE is reserved for use by the client. 602 // UNKNOWN_TYPE is reserved for use by the client.
603 DCHECK_NE(current_info->field_type, UNKNOWN_TYPE); 603 DCHECK_NE(current_info->field_type, UNKNOWN_TYPE);
604 604
605 NativeFieldType heuristic_type = (*field)->heuristic_type(); 605 NativeFieldType heuristic_type = (*field)->heuristic_type();
606 if (heuristic_type != UNKNOWN_TYPE) 606 if (heuristic_type != UNKNOWN_TYPE)
607 heuristics_detected_fillable_field = true; 607 heuristics_detected_fillable_field = true;
608 608
609 (*field)->set_server_type(current_info->field_type); 609 (*field)->set_server_type(current_info->field_type);
610 if (heuristic_type != (*field)->Type().native_type()) 610 if (heuristic_type != (*field)->Type().GetEquivalentNativeType())
611 query_response_overrode_heuristics = true; 611 query_response_overrode_heuristics = true;
612 612
613 // Copy default value into the field if available. 613 // Copy default value into the field if available.
614 if (!current_info->default_value.empty()) 614 if (!current_info->default_value.empty())
615 (*field)->set_default_value(current_info->default_value); 615 (*field)->set_default_value(current_info->default_value);
616 616
617 ++current_info; 617 ++current_info;
618 } 618 }
619 619
620 form->UpdateAutofillCount(); 620 form->UpdateAutofillCount();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 form.experiment_id = form_structure->server_experiment_id_; 652 form.experiment_id = form_structure->server_experiment_id_;
653 653
654 for (std::vector<AutofillField*>::const_iterator field = 654 for (std::vector<AutofillField*>::const_iterator field =
655 form_structure->fields_.begin(); 655 form_structure->fields_.begin();
656 field != form_structure->fields_.end(); ++field) { 656 field != form_structure->fields_.end(); ++field) {
657 form.data.fields.push_back(FormFieldData(**field)); 657 form.data.fields.push_back(FormFieldData(**field));
658 658
659 FormFieldDataPredictions annotated_field; 659 FormFieldDataPredictions annotated_field;
660 annotated_field.signature = (*field)->FieldSignature(); 660 annotated_field.signature = (*field)->FieldSignature();
661 annotated_field.heuristic_type = 661 annotated_field.heuristic_type =
662 AutofillType::FieldTypeToString((*field)->heuristic_type()); 662 AutofillType((*field)->heuristic_type()).ToString();
663 annotated_field.server_type = 663 annotated_field.server_type =
664 AutofillType::FieldTypeToString((*field)->server_type()); 664 AutofillType((*field)->server_type()).ToString();
665 annotated_field.overall_type = 665 annotated_field.overall_type = (*field)->Type().ToString();
666 AutofillType::FieldTypeToString((*field)->Type().native_type());
667 form.fields.push_back(annotated_field); 666 form.fields.push_back(annotated_field);
668 } 667 }
669 668
670 forms->push_back(form); 669 forms->push_back(form);
671 } 670 }
672 } 671 }
673 672
674 std::string FormStructure::FormSignature() const { 673 std::string FormStructure::FormSignature() const {
675 std::string scheme(target_url_.scheme()); 674 std::string scheme(target_url_.scheme());
676 std::string host(target_url_.host()); 675 std::string host(target_url_.host());
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
825 // Collapse field types that Chrome treats as identical, e.g. home and 824 // Collapse field types that Chrome treats as identical, e.g. home and
826 // billing address fields. 825 // billing address fields.
827 NativeFieldTypeSet collapsed_field_types; 826 NativeFieldTypeSet collapsed_field_types;
828 for (NativeFieldTypeSet::const_iterator it = field_types.begin(); 827 for (NativeFieldTypeSet::const_iterator it = field_types.begin();
829 it != field_types.end(); 828 it != field_types.end();
830 ++it) { 829 ++it) {
831 // Since we currently only support US phone numbers, the (city code + main 830 // Since we currently only support US phone numbers, the (city code + main
832 // digits) number is almost always identical to the whole phone number. 831 // digits) number is almost always identical to the whole phone number.
833 // TODO(isherman): Improve this logic once we add support for 832 // TODO(isherman): Improve this logic once we add support for
834 // international numbers. 833 // international numbers.
835 if (*it == PHONE_HOME_CITY_AND_NUMBER) 834 if (*it == PHONE_HOME_CITY_AND_NUMBER) {
836 collapsed_field_types.insert(PHONE_HOME_WHOLE_NUMBER); 835 collapsed_field_types.insert(PHONE_HOME_WHOLE_NUMBER);
837 else 836 } else {
838 collapsed_field_types.insert(AutofillType::GetEquivalentFieldType(*it)); 837 collapsed_field_types.insert(
838 AutofillType(*it).GetEquivalentNativeType());
839 }
839 } 840 }
840 841
841 // Capture the field's type, if it is unambiguous. 842 // Capture the field's type, if it is unambiguous.
842 NativeFieldType field_type = UNKNOWN_TYPE; 843 NativeFieldType field_type = UNKNOWN_TYPE;
843 if (collapsed_field_types.size() == 1) 844 if (collapsed_field_types.size() == 1)
844 field_type = *collapsed_field_types.begin(); 845 field_type = *collapsed_field_types.begin();
845 846
846 NativeFieldType heuristic_type = field->heuristic_type(); 847 NativeFieldType heuristic_type =
847 NativeFieldType server_type = field->server_type(); 848 AutofillType(field->heuristic_type()).GetEquivalentNativeType();
848 NativeFieldType predicted_type = field->Type().native_type(); 849 NativeFieldType server_type =
850 AutofillType(field->server_type()).GetEquivalentNativeType();
851 NativeFieldType predicted_type = field->Type().GetEquivalentNativeType();
849 852
850 // Log heuristic, server, and overall type quality metrics, independently of 853 // Log heuristic, server, and overall type quality metrics, independently of
851 // whether the field was autofilled. 854 // whether the field was autofilled.
852 if (heuristic_type == UNKNOWN_TYPE) { 855 if (heuristic_type == UNKNOWN_TYPE) {
853 metric_logger.LogHeuristicTypePrediction(AutofillMetrics::TYPE_UNKNOWN, 856 metric_logger.LogHeuristicTypePrediction(AutofillMetrics::TYPE_UNKNOWN,
854 field_type, experiment_id); 857 field_type, experiment_id);
855 } else if (field_types.count(heuristic_type)) { 858 } else if (field_types.count(heuristic_type)) {
856 metric_logger.LogHeuristicTypePrediction(AutofillMetrics::TYPE_MATCH, 859 metric_logger.LogHeuristicTypePrediction(AutofillMetrics::TYPE_MATCH,
857 field_type, experiment_id); 860 field_type, experiment_id);
858 } else { 861 } else {
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
1073 break; 1076 break;
1074 case FormStructure::FIELD_ASSIGNMENTS: 1077 case FormStructure::FIELD_ASSIGNMENTS:
1075 EncodeFieldForFieldAssignments(*field, encompassing_xml_element); 1078 EncodeFieldForFieldAssignments(*field, encompassing_xml_element);
1076 break; 1079 break;
1077 } 1080 }
1078 } 1081 }
1079 return true; 1082 return true;
1080 } 1083 }
1081 1084
1082 void FormStructure::ParseFieldTypesFromAutocompleteAttributes( 1085 void FormStructure::ParseFieldTypesFromAutocompleteAttributes(
1083 ParseTarget parse_target,
1084 bool* found_types, 1086 bool* found_types,
1085 bool* found_sections) { 1087 bool* found_sections) {
1086 const std::string kDefaultSection = "-default"; 1088 const std::string kDefaultSection = "-default";
1087 1089
1088 *found_types = false; 1090 *found_types = false;
1089 *found_sections = false; 1091 *found_sections = false;
1090 for (std::vector<AutofillField*>::iterator it = fields_.begin(); 1092 for (std::vector<AutofillField*>::iterator it = fields_.begin();
1091 it != fields_.end(); ++it) { 1093 it != fields_.end(); ++it) {
1092 AutofillField* field = *it; 1094 AutofillField* field = *it;
1093 1095
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1125 // Tokenize the attribute value. Per the spec, the tokens are parsed in 1127 // Tokenize the attribute value. Per the spec, the tokens are parsed in
1126 // reverse order. 1128 // reverse order.
1127 std::vector<std::string> tokens; 1129 std::vector<std::string> tokens;
1128 Tokenize(autocomplete_attribute, " ", &tokens); 1130 Tokenize(autocomplete_attribute, " ", &tokens);
1129 1131
1130 // The final token must be the field type. 1132 // The final token must be the field type.
1131 // If it is not one of the known types, abort. 1133 // If it is not one of the known types, abort.
1132 DCHECK(!tokens.empty()); 1134 DCHECK(!tokens.empty());
1133 std::string field_type_token = tokens.back(); 1135 std::string field_type_token = tokens.back();
1134 tokens.pop_back(); 1136 tokens.pop_back();
1135 NativeFieldType field_type = 1137 HtmlFieldType field_type =
1136 FieldTypeFromAutocompleteType(field_type_token, *field); 1138 FieldTypeFromAutocompleteType(field_type_token, *field);
1137 if (field_type == UNKNOWN_TYPE) 1139 if (field_type == HTML_TYPE_UNKNOWN)
1138 continue; 1140 continue;
1139 1141
1140 // The preceding token, if any, may be a type hint. 1142 // The preceding token, if any, may be a type hint.
1141 if (!tokens.empty() && IsContactTypeHint(tokens.back())) { 1143 if (!tokens.empty() && IsContactTypeHint(tokens.back())) {
1142 // If it is, it must match the field type; otherwise, abort. 1144 // If it is, it must match the field type; otherwise, abort.
1143 // Note that an invalid token invalidates the entire attribute value, even 1145 // Note that an invalid token invalidates the entire attribute value, even
1144 // if the other tokens are valid. 1146 // if the other tokens are valid.
1145 if (!ContactTypeHintMatchesFieldType(tokens.back(), field_type)) 1147 if (!ContactTypeHintMatchesFieldType(tokens.back(), field_type))
1146 continue; 1148 continue;
1147 1149
1148 // Chrome Autofill ignores these type hints. 1150 // Chrome Autofill ignores these type hints.
1149 tokens.pop_back(); 1151 tokens.pop_back();
1150 } 1152 }
1151 1153
1152 // The preceding token, if any, may be a fixed string that is either 1154 // The preceding token, if any, may be a fixed string that is either
1153 // "shipping" or "billing". Chrome Autofill treats these as implicit 1155 // "shipping" or "billing". Chrome Autofill treats these as implicit
1154 // section name suffixes. 1156 // section name suffixes.
1155 DCHECK_EQ(kDefaultSection, field->section()); 1157 DCHECK_EQ(kDefaultSection, field->section());
1156 std::string section = field->section(); 1158 std::string section = field->section();
1157 if (!tokens.empty() && 1159 HtmlFieldMode mode = HTML_MODE_NONE;
1158 (tokens.back() == kShippingSection || 1160 if (!tokens.empty()) {
1159 tokens.back() == kBillingSection)) { 1161 if (tokens.back() == kShippingMode)
1160 // Set Autofill field type to billing if section is billing. 1162 mode = HTML_MODE_SHIPPING;
1161 if (tokens.back() == kBillingSection) { 1163 else if (tokens.back() == kBillingMode)
1162 field_type = AutofillType::GetEquivalentBillingFieldType(field_type); 1164 mode = HTML_MODE_BILLING;
1165 }
1163 1166
1164 // The Autofill dialog uses the type CREDIT_CARD_NAME to refer to both 1167 if (mode != HTML_MODE_NONE) {
1165 // the credit card holder's name and the name on the billing address.
1166 if (parse_target == PARSE_FOR_AUTOFILL_DIALOG &&
1167 field_type == NAME_FULL) {
1168 field_type = CREDIT_CARD_NAME;
1169 }
1170 }
1171
1172 section = "-" + tokens.back(); 1168 section = "-" + tokens.back();
1173 tokens.pop_back(); 1169 tokens.pop_back();
1174 } 1170 }
1175 1171
1176 // The preceding token, if any, may be a named section. 1172 // The preceding token, if any, may be a named section.
1177 const std::string kSectionPrefix = "section-"; 1173 const std::string kSectionPrefix = "section-";
1178 if (!tokens.empty() && 1174 if (!tokens.empty() &&
1179 StartsWithASCII(tokens.back(), kSectionPrefix, true)) { 1175 StartsWithASCII(tokens.back(), kSectionPrefix, true)) {
1180 // Prepend this section name to the suffix set in the preceding block. 1176 // Prepend this section name to the suffix set in the preceding block.
1181 section = tokens.back().substr(kSectionPrefix.size()) + section; 1177 section = tokens.back().substr(kSectionPrefix.size()) + section;
1182 tokens.pop_back(); 1178 tokens.pop_back();
1183 } 1179 }
1184 1180
1185 // No other tokens are allowed. If there are any remaining, abort. 1181 // No other tokens are allowed. If there are any remaining, abort.
1186 if (!tokens.empty()) 1182 if (!tokens.empty())
1187 continue; 1183 continue;
1188 1184
1189 if (section != kDefaultSection) { 1185 if (section != kDefaultSection) {
1190 *found_sections = true; 1186 *found_sections = true;
1191 field->set_section(section); 1187 field->set_section(section);
1192 } 1188 }
1193 1189
1194 // No errors encountered while parsing! 1190 // No errors encountered while parsing!
1195 // Update the |field|'s type based on what was parsed from the attribute. 1191 // Update the |field|'s type based on what was parsed from the attribute.
1196 field->set_heuristic_type(field_type); 1192 field->SetHtmlType(field_type, mode);
1197 if (field_type_token == "tel-local-prefix")
1198 field->set_phone_part(AutofillField::PHONE_PREFIX);
1199 else if (field_type_token == "tel-local-suffix")
1200 field->set_phone_part(AutofillField::PHONE_SUFFIX);
1201 } 1193 }
1202 } 1194 }
1203 1195
1204 void FormStructure::IdentifySections(bool has_author_specified_sections) { 1196 void FormStructure::IdentifySections(bool has_author_specified_sections) {
1205 if (fields_.empty()) 1197 if (fields_.empty())
1206 return; 1198 return;
1207 1199
1208 if (!has_author_specified_sections) { 1200 if (!has_author_specified_sections) {
1209 // Name sections after the first field in the section. 1201 // Name sections after the first field in the section.
1210 base::string16 current_section = fields_.front()->unique_name(); 1202 base::string16 current_section = fields_.front()->unique_name();
1211 1203
1212 // Keep track of the types we've seen in this section. 1204 // Keep track of the types we've seen in this section.
1213 std::set<NativeFieldType> seen_types; 1205 std::set<NativeFieldType> seen_types;
1214 NativeFieldType previous_type = UNKNOWN_TYPE; 1206 NativeFieldType previous_type = UNKNOWN_TYPE;
1215 1207
1216 for (std::vector<AutofillField*>::iterator field = fields_.begin(); 1208 for (std::vector<AutofillField*>::iterator field = fields_.begin();
1217 field != fields_.end(); ++field) { 1209 field != fields_.end(); ++field) {
1218 const NativeFieldType current_type = 1210 const NativeFieldType current_type =
1219 AutofillType::GetEquivalentFieldType((*field)->Type().native_type()); 1211 (*field)->Type().GetApproximateNativeFieldType();
1220 1212
1221 bool already_saw_current_type = seen_types.count(current_type) > 0; 1213 bool already_saw_current_type = seen_types.count(current_type) > 0;
1222 1214
1223 // Forms often ask for multiple phone numbers -- e.g. both a daytime and 1215 // Forms often ask for multiple phone numbers -- e.g. both a daytime and
1224 // evening phone number. Our phone number detection is also generally a 1216 // evening phone number. Our phone number detection is also generally a
1225 // little off. Hence, ignore this field type as a signal here. 1217 // little off. Hence, ignore this field type as a signal here.
1226 if (AutofillType(current_type).group() == PHONE_HOME) 1218 if (AutofillType(current_type).group() == PHONE_HOME)
1227 already_saw_current_type = false; 1219 already_saw_current_type = false;
1228 1220
1229 // Some forms have adjacent fields of the same type. Two common examples: 1221 // Some forms have adjacent fields of the same type. Two common examples:
(...skipping 27 matching lines...) Expand all
1257 field != fields_.end(); ++field) { 1249 field != fields_.end(); ++field) {
1258 FieldTypeGroup field_type_group = (*field)->Type().group(); 1250 FieldTypeGroup field_type_group = (*field)->Type().group();
1259 if (field_type_group == CREDIT_CARD) 1251 if (field_type_group == CREDIT_CARD)
1260 (*field)->set_section((*field)->section() + "-cc"); 1252 (*field)->set_section((*field)->section() + "-cc");
1261 else 1253 else
1262 (*field)->set_section((*field)->section() + "-default"); 1254 (*field)->set_section((*field)->section() + "-default");
1263 } 1255 }
1264 } 1256 }
1265 1257
1266 } // namespace autofill 1258 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698