OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/autofill/form_structure.h" | 5 #include "chrome/browser/autofill/form_structure.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
78 // Print all meaningfull bytes into a string. | 78 // Print all meaningfull bytes into a string. |
79 std::string data_presence; | 79 std::string data_presence; |
80 data_presence.reserve(data_end * 2 + 1); | 80 data_presence.reserve(data_end * 2 + 1); |
81 for (size_t i = 0; i < data_end; ++i) { | 81 for (size_t i = 0; i < data_end; ++i) { |
82 base::StringAppendF(&data_presence, "%02x", bit_field[i]); | 82 base::StringAppendF(&data_presence, "%02x", bit_field[i]); |
83 } | 83 } |
84 | 84 |
85 return data_presence; | 85 return data_presence; |
86 } | 86 } |
87 | 87 |
88 bool UpdateFromAutocompleteType(const string16& autocomplete_type, | 88 // Returns |true| iff the |token| is a type hint for a contact field, as |
89 AutofillField* field) { | 89 // specified in the implementation section of |
90 if (autocomplete_type == ASCIIToUTF16("given-name")) { | 90 // http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-co ntrols-and-forms.html#autofilling-form-controls:-the-autocomplete-attribute |
Dan Beam
2012/10/19 00:12:44
nit: it might be useful to URL shorten some of the
Ilya Sherman
2012/10/19 04:19:32
Done.
| |
91 field->set_heuristic_type(NAME_FIRST); | 91 // Note that "fax" is intentionally ignored, as Chrome does not support filling |
92 return true; | 92 // fax information. |
93 bool IsContactTypeHint(const string16& token) { | |
94 return | |
Dan Beam
2012/10/19 00:12:44
nit: isn't the chromium style more
return token
Ilya Sherman
2012/10/19 04:19:32
Done.
Dan Beam
2012/10/23 00:28:59
it doesn't seem like anything other than stripping
Ilya Sherman
2012/10/23 01:06:12
Whoops. Actually done now.
| |
95 token == ASCIIToUTF16("home") || | |
96 token == ASCIIToUTF16("work") || | |
97 token == ASCIIToUTF16("mobile") || | |
98 token == ASCIIToUTF16("pager"); | |
99 } | |
100 | |
101 // Returns |true| iff the |token| is a type hint appropriate for a field of the | |
102 // given |field_type|, as specified in the implementation section of | |
103 // http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-co ntrols-and-forms.html#autofilling-form-controls:-the-autocomplete-attribute | |
104 bool ContactTypeHintMatchesFieldType(const string16& token, | |
105 AutofillFieldType field_type) { | |
106 // The "home" and "work" type hints are only appropriate for email and phone | |
107 // number field types. | |
108 if (token == ASCIIToUTF16("home") || token == ASCIIToUTF16("work")) { | |
109 return | |
110 field_type == EMAIL_ADDRESS || | |
111 (field_type >= PHONE_HOME_NUMBER && | |
112 field_type <= PHONE_HOME_WHOLE_NUMBER); | |
93 } | 113 } |
94 | 114 |
95 if (autocomplete_type == ASCIIToUTF16("middle-name")) { | 115 // The remaining type hints are only appropriate for phone number field types. |
96 field->set_heuristic_type(NAME_MIDDLE); | 116 // Note that "fax" is intentionally ignored, as Chrome does not support |
97 return true; | 117 // filling fax information. |
98 } | 118 if (token == ASCIIToUTF16("mobile") || token == ASCIIToUTF16("pager")) { |
99 | 119 return |
100 if (autocomplete_type == ASCIIToUTF16("middle-initial")) { | 120 field_type >= PHONE_HOME_NUMBER && |
101 field->set_heuristic_type(NAME_MIDDLE_INITIAL); | 121 field_type <= PHONE_HOME_WHOLE_NUMBER; |
102 return true; | |
103 } | |
104 | |
105 if (autocomplete_type == ASCIIToUTF16("surname")) { | |
106 field->set_heuristic_type(NAME_LAST); | |
107 return true; | |
108 } | |
109 | |
110 if (autocomplete_type == ASCIIToUTF16("full-name")) { | |
111 field->set_heuristic_type(NAME_FULL); | |
112 return true; | |
113 } | |
114 | |
115 if (autocomplete_type == ASCIIToUTF16("street-address") || | |
116 autocomplete_type == ASCIIToUTF16("address-line1")) { | |
117 field->set_heuristic_type(ADDRESS_HOME_LINE1); | |
118 return true; | |
119 } | |
120 | |
121 if (autocomplete_type == ASCIIToUTF16("address-line2")) { | |
122 field->set_heuristic_type(ADDRESS_HOME_LINE2); | |
123 return true; | |
124 } | |
125 | |
126 if (autocomplete_type == ASCIIToUTF16("locality") || | |
127 autocomplete_type == ASCIIToUTF16("city")) { | |
128 field->set_heuristic_type(ADDRESS_HOME_CITY); | |
129 return true; | |
130 } | |
131 | |
132 if (autocomplete_type == ASCIIToUTF16("administrative-area") || | |
133 autocomplete_type == ASCIIToUTF16("state") || | |
134 autocomplete_type == ASCIIToUTF16("province") || | |
135 autocomplete_type == ASCIIToUTF16("region")) { | |
136 field->set_heuristic_type(ADDRESS_HOME_STATE); | |
137 return true; | |
138 } | |
139 | |
140 if (autocomplete_type == ASCIIToUTF16("postal-code")) { | |
141 field->set_heuristic_type(ADDRESS_HOME_ZIP); | |
142 return true; | |
143 } | |
144 | |
145 if (autocomplete_type == ASCIIToUTF16("country")) { | |
146 field->set_heuristic_type(ADDRESS_HOME_COUNTRY); | |
147 return true; | |
148 } | |
149 | |
150 if (autocomplete_type == ASCIIToUTF16("organization")) { | |
151 field->set_heuristic_type(COMPANY_NAME); | |
152 return true; | |
153 } | |
154 | |
155 if (autocomplete_type == ASCIIToUTF16("email")) { | |
156 field->set_heuristic_type(EMAIL_ADDRESS); | |
157 return true; | |
158 } | |
159 | |
160 if (autocomplete_type == ASCIIToUTF16("phone-full")) { | |
161 field->set_heuristic_type(PHONE_HOME_WHOLE_NUMBER); | |
162 return true; | |
163 } | |
164 | |
165 if (autocomplete_type == ASCIIToUTF16("phone-country-code")) { | |
166 field->set_heuristic_type(PHONE_HOME_COUNTRY_CODE); | |
167 return true; | |
168 } | |
169 | |
170 if (autocomplete_type == ASCIIToUTF16("phone-national")) { | |
171 field->set_heuristic_type(PHONE_HOME_CITY_AND_NUMBER); | |
172 return true; | |
173 } | |
174 | |
175 if (autocomplete_type == ASCIIToUTF16("phone-area-code")) { | |
176 field->set_heuristic_type(PHONE_HOME_CITY_CODE); | |
177 return true; | |
178 } | |
179 | |
180 if (autocomplete_type == ASCIIToUTF16("phone-local")) { | |
181 field->set_heuristic_type(PHONE_HOME_NUMBER); | |
182 return true; | |
183 } | |
184 | |
185 if (autocomplete_type == ASCIIToUTF16("phone-local-prefix")) { | |
186 field->set_heuristic_type(PHONE_HOME_NUMBER); | |
187 field->set_phone_part(AutofillField::PHONE_PREFIX); | |
188 return true; | |
189 } | |
190 | |
191 if (autocomplete_type == ASCIIToUTF16("phone-local-suffix")) { | |
192 field->set_heuristic_type(PHONE_HOME_NUMBER); | |
193 field->set_phone_part(AutofillField::PHONE_SUFFIX); | |
194 return true; | |
195 } | |
196 | |
197 if (autocomplete_type == ASCIIToUTF16("cc-full-name")) { | |
198 field->set_heuristic_type(CREDIT_CARD_NAME); | |
199 return true; | |
200 } | |
201 | |
202 if (autocomplete_type == ASCIIToUTF16("cc-number")) { | |
203 field->set_heuristic_type(CREDIT_CARD_NUMBER); | |
204 return true; | |
205 } | |
206 | |
207 if (autocomplete_type == ASCIIToUTF16("cc-exp-month")) { | |
208 field->set_heuristic_type(CREDIT_CARD_EXP_MONTH); | |
209 return true; | |
210 } | |
211 | |
212 if (autocomplete_type == ASCIIToUTF16("cc-exp-year")) { | |
213 if (field->max_length == 2) | |
214 field->set_heuristic_type(CREDIT_CARD_EXP_2_DIGIT_YEAR); | |
215 else | |
216 field->set_heuristic_type(CREDIT_CARD_EXP_4_DIGIT_YEAR); | |
217 return true; | |
218 } | |
219 | |
220 if (autocomplete_type == ASCIIToUTF16("cc-exp")) { | |
221 if (field->max_length == 5) | |
222 field->set_heuristic_type(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR); | |
223 else | |
224 field->set_heuristic_type(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR); | |
225 return true; | |
226 } | 122 } |
227 | 123 |
228 return false; | 124 return false; |
229 } | 125 } |
230 | 126 |
127 // Returns the Chrome Autofill-supported field type corresponding to the given | |
128 // |autocomplete_type|, if there is one, in the context of the given |field|. | |
129 // Chrome Autofill supports a subset of the field types listed at | |
130 // http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-co ntrols-and-forms.html#autofilling-form-controls:-the-autocomplete-attribute | |
131 AutofillFieldType FieldTypeFromAutocompleteType( | |
132 const string16& autocomplete_type, | |
133 const AutofillField& field) { | |
134 if (autocomplete_type == ASCIIToUTF16("name")) | |
135 return NAME_FULL; | |
136 | |
137 if (autocomplete_type == ASCIIToUTF16("given-name")) | |
138 return NAME_FIRST; | |
139 | |
140 if (autocomplete_type == ASCIIToUTF16("additional-name")) { | |
141 if (field.max_length == 1) | |
142 return NAME_MIDDLE_INITIAL; | |
143 else | |
144 return NAME_MIDDLE; | |
145 } | |
146 | |
147 if (autocomplete_type == ASCIIToUTF16("family-name")) | |
148 return NAME_LAST; | |
149 | |
150 if (autocomplete_type == ASCIIToUTF16("honorific-suffix")) | |
151 return NAME_SUFFIX; | |
152 | |
153 if (autocomplete_type == ASCIIToUTF16("organization")) | |
Dan Beam
2012/10/19 00:12:44
organization == company always?
Ilya Sherman
2012/10/19 04:19:32
The spec defines this token as meaning "Company na
Dan Beam
2012/10/19 04:25:41
I know, I noticed that. My issue is really with t
| |
154 return COMPANY_NAME; | |
155 | |
156 if (autocomplete_type == ASCIIToUTF16("street-address") || | |
157 autocomplete_type == ASCIIToUTF16("address-line1")) | |
158 return ADDRESS_HOME_LINE1; | |
159 | |
160 if (autocomplete_type == ASCIIToUTF16("address-line2")) | |
161 return ADDRESS_HOME_LINE2; | |
162 | |
163 if (autocomplete_type == ASCIIToUTF16("locality")) | |
164 return ADDRESS_HOME_CITY; | |
165 | |
166 if (autocomplete_type == ASCIIToUTF16("region")) | |
Dan Beam
2012/10/19 00:12:44
region == state always?
Ilya Sherman
2012/10/19 04:19:32
"state" is the name that Autofill internally uses
Dan Beam
2012/10/19 04:25:41
So we could have things like Bavaria as the state.
Ilya Sherman
2012/10/19 04:54:11
Yes, we could have things like Bavaria as the "sta
| |
167 return ADDRESS_HOME_STATE; | |
168 | |
169 if (autocomplete_type == ASCIIToUTF16("country")) | |
170 return ADDRESS_HOME_COUNTRY; | |
171 | |
172 if (autocomplete_type == ASCIIToUTF16("postal-code")) | |
173 return ADDRESS_HOME_ZIP; | |
Dan Beam
2012/10/19 00:12:44
postal-code == zip always?
Ilya Sherman
2012/10/19 04:19:32
Ditto: This is just what the Autofill code calls t
| |
174 | |
175 if (autocomplete_type == ASCIIToUTF16("cc-name")) | |
176 return CREDIT_CARD_NAME; | |
177 | |
178 if (autocomplete_type == ASCIIToUTF16("cc-number")) | |
179 return CREDIT_CARD_NUMBER; | |
180 | |
181 if (autocomplete_type == ASCIIToUTF16("cc-exp")) { | |
182 if (field.max_length == 5) | |
183 return CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR; | |
184 else | |
185 return CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR; | |
186 } | |
187 | |
188 if (autocomplete_type == ASCIIToUTF16("cc-exp-month")) | |
189 return CREDIT_CARD_EXP_MONTH; | |
190 | |
191 if (autocomplete_type == ASCIIToUTF16("cc-exp-year")) { | |
192 if (field.max_length == 2) | |
193 return CREDIT_CARD_EXP_2_DIGIT_YEAR; | |
194 else | |
195 return CREDIT_CARD_EXP_4_DIGIT_YEAR; | |
196 } | |
197 | |
198 if (autocomplete_type == ASCIIToUTF16("tel")) | |
199 return PHONE_HOME_WHOLE_NUMBER; | |
200 | |
201 if (autocomplete_type == ASCIIToUTF16("tel-country-code")) | |
202 return PHONE_HOME_COUNTRY_CODE; | |
203 | |
204 if (autocomplete_type == ASCIIToUTF16("tel-national")) | |
205 return PHONE_HOME_CITY_AND_NUMBER; | |
206 | |
207 if (autocomplete_type == ASCIIToUTF16("tel-area-code")) | |
208 return PHONE_HOME_CITY_CODE; | |
209 | |
210 if (autocomplete_type == ASCIIToUTF16("tel-local")) | |
211 return PHONE_HOME_NUMBER; | |
212 | |
213 if (autocomplete_type == ASCIIToUTF16("tel-local-prefix")) | |
214 return PHONE_HOME_NUMBER; | |
215 | |
216 if (autocomplete_type == ASCIIToUTF16("tel-local-suffix")) | |
217 return PHONE_HOME_NUMBER; | |
218 | |
219 if (autocomplete_type == ASCIIToUTF16("email")) | |
220 return EMAIL_ADDRESS; | |
221 | |
222 return UNKNOWN_TYPE; | |
223 } | |
224 | |
231 } // namespace | 225 } // namespace |
232 | 226 |
233 FormStructure::FormStructure(const FormData& form) | 227 FormStructure::FormStructure(const FormData& form) |
234 : form_name_(form.name), | 228 : form_name_(form.name), |
235 source_url_(form.origin), | 229 source_url_(form.origin), |
236 target_url_(form.action), | 230 target_url_(form.action), |
237 autofill_count_(0), | 231 autofill_count_(0), |
238 upload_required_(USE_UPLOAD_RATES), | 232 upload_required_(USE_UPLOAD_RATES), |
239 server_experiment_id_("no server response"), | 233 server_experiment_id_("no server response"), |
240 has_author_specified_types_(false) { | 234 has_author_specified_types_(false) { |
(...skipping 25 matching lines...) Expand all Loading... | |
266 } else { | 260 } else { |
267 // Either the method is 'get', or we don't know. In this case we default | 261 // Either the method is 'get', or we don't know. In this case we default |
268 // to GET. | 262 // to GET. |
269 method_ = GET; | 263 method_ = GET; |
270 } | 264 } |
271 } | 265 } |
272 | 266 |
273 FormStructure::~FormStructure() {} | 267 FormStructure::~FormStructure() {} |
274 | 268 |
275 void FormStructure::DetermineHeuristicTypes() { | 269 void FormStructure::DetermineHeuristicTypes() { |
276 // First, try to detect field types based on the fields' |autocompletetype| | 270 // First, try to detect field types based on each field's |autocomplete| |
277 // attributes. If there is at least one form field with this attribute, don't | 271 // attribute value. If there is at least one form field with that specifies |
Dan Beam
2012/10/19 00:12:44
If there is at least one form field that specifies
Ilya Sherman
2012/10/19 04:19:32
Done.
| |
278 // try to apply other heuristics to match fields in this form. | 272 // an autocomplete type hint, don't try to apply other heuristics to match |
273 // fields in this form. | |
279 bool has_author_specified_sections; | 274 bool has_author_specified_sections; |
280 ParseAutocompletetypeAttributes(&has_author_specified_types_, | 275 ParseFieldTypesFromAutocompleteAttributes(&has_author_specified_types_, |
281 &has_author_specified_sections); | 276 &has_author_specified_sections); |
282 | 277 |
283 if (!has_author_specified_types_) { | 278 if (!has_author_specified_types_) { |
284 FieldTypeMap field_type_map; | 279 FieldTypeMap field_type_map; |
285 FormField::ParseFormFields(fields_.get(), &field_type_map); | 280 FormField::ParseFormFields(fields_.get(), &field_type_map); |
286 for (size_t index = 0; index < field_count(); index++) { | 281 for (size_t index = 0; index < field_count(); index++) { |
287 AutofillField* field = fields_[index]; | 282 AutofillField* field = fields_[index]; |
288 FieldTypeMap::iterator iter = field_type_map.find(field->unique_name()); | 283 FieldTypeMap::iterator iter = field_type_map.find(field->unique_name()); |
289 if (iter != field_type_map.end()) | 284 if (iter != field_type_map.end()) |
290 field->set_heuristic_type(iter->second); | 285 field->set_heuristic_type(iter->second); |
291 } | 286 } |
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
871 buzz::XmlElement *field_element = new buzz::XmlElement( | 866 buzz::XmlElement *field_element = new buzz::XmlElement( |
872 buzz::QName(kXMLElementField)); | 867 buzz::QName(kXMLElementField)); |
873 field_element->SetAttr(buzz::QName(kAttributeSignature), | 868 field_element->SetAttr(buzz::QName(kAttributeSignature), |
874 field->FieldSignature()); | 869 field->FieldSignature()); |
875 encompassing_xml_element->AddElement(field_element); | 870 encompassing_xml_element->AddElement(field_element); |
876 } | 871 } |
877 } | 872 } |
878 return true; | 873 return true; |
879 } | 874 } |
880 | 875 |
881 void FormStructure::ParseAutocompletetypeAttributes(bool* found_attribute, | 876 // TODO(isherman): This method could use a shorter name... |
Ilya Sherman
2012/10/18 00:11:19
Any suggestions?
Dan Beam
2012/10/19 00:12:44
Not really, maybe just FieldTypeFromAutocompleteAt
Ilya Sherman
2012/10/19 04:19:32
Ok. I like having parse in the name, so I guess l
| |
882 bool* found_sections) { | 877 void FormStructure::ParseFieldTypesFromAutocompleteAttributes( |
883 *found_attribute = false; | 878 bool* found_types, |
879 bool* found_sections) { | |
880 *found_types = false; | |
884 *found_sections = false; | 881 *found_sections = false; |
885 for (std::vector<AutofillField*>::iterator field = fields_.begin(); | 882 for (std::vector<AutofillField*>::iterator field = fields_.begin(); |
886 field != fields_.end(); ++field) { | 883 field != fields_.end(); ++field) { |
887 if ((*field)->autocomplete_type.empty()) | 884 // Canonicalize the attribute value by trimming whitespace and converting to |
885 // lowercase ASCII. | |
886 string16 autocomplete_attribute = (*field)->autocomplete_attribute; | |
887 TrimWhitespace(autocomplete_attribute, TRIM_ALL, &autocomplete_attribute); | |
888 autocomplete_attribute = StringToLowerASCII(autocomplete_attribute); | |
889 | |
890 // The autocomplete attribute is overloaded: it can specify either a field | |
891 // type hint or whether autocomplete should be enabled at all. Ignore the | |
892 // latter type of attribute value. | |
893 if (autocomplete_attribute.empty() || | |
894 autocomplete_attribute == ASCIIToUTF16("on") || | |
895 autocomplete_attribute == ASCIIToUTF16("off")) { | |
896 continue; | |
897 } | |
898 | |
899 // Any other value, even it is invalid, is considered to be a type hint. | |
900 // This allows a website's author to specify an attribute like | |
901 // autocomplete="other" on a field to disable all Autofill heuristics for | |
902 // the form. | |
903 *found_types = true; | |
904 | |
905 // Tokenize the attribute value. Per the spec, the tokens are parsed in | |
906 // reverse order. | |
907 std::vector<string16> tokens; | |
908 Tokenize(autocomplete_attribute, ASCIIToUTF16(" "), &tokens); | |
909 | |
910 // The final token must be the field type. | |
911 // If it is not one of the known types, abort. | |
912 DCHECK(!tokens.empty()); | |
913 string16 field_type_token = tokens.back(); | |
914 tokens.pop_back(); | |
915 AutofillFieldType field_type = | |
916 FieldTypeFromAutocompleteType(field_type_token, **field); | |
917 if (field_type == UNKNOWN_TYPE) | |
888 continue; | 918 continue; |
889 | 919 |
890 *found_attribute = true; | 920 // The preceding token, if any, may be a type hint. |
891 std::vector<string16> types; | 921 if (!tokens.empty() && IsContactTypeHint(tokens.back())) { |
892 Tokenize((*field)->autocomplete_type, ASCIIToUTF16(" "), &types); | 922 // If it is, it must match the field type; otherwise, abort. |
Dan Beam
2012/10/19 00:12:44
you may want to add/hint at that there could be va
Ilya Sherman
2012/10/19 04:19:32
Done.
| |
923 if (!ContactTypeHintMatchesFieldType(tokens.back(), field_type)) | |
924 continue; | |
893 | 925 |
894 // Look for a named section. | 926 // Chrome Autofill ignore these type hints. |
Dan Beam
2012/10/19 00:12:44
ignores
Ilya Sherman
2012/10/19 04:19:32
Done.
| |
895 const string16 kSectionPrefix = ASCIIToUTF16("section-"); | 927 tokens.pop_back(); |
896 if (!types.empty() && StartsWith(types.front(), kSectionPrefix, true)) { | |
897 *found_sections = true; | |
898 (*field)->set_section(types.front().substr(kSectionPrefix.size())); | |
899 } | 928 } |
900 | 929 |
901 // Look for specified types. | 930 // The preceding token, if any, may be a fixed string that is either |
902 for (std::vector<string16>::const_iterator type = types.begin(); | 931 // "shipping" or "billing". Chrome Autofill treats these as implicit |
903 type != types.end(); ++type) { | 932 // section name suffixes. |
904 if (UpdateFromAutocompleteType(*type, *field)) | 933 if (!tokens.empty() && |
905 break; | 934 (tokens.back() == ASCIIToUTF16("shipping") || |
935 tokens.back() == ASCIIToUTF16("billing"))) { | |
936 *found_sections = true; | |
937 (*field)->set_section(ASCIIToUTF16("-") + tokens.back()); | |
938 tokens.pop_back(); | |
939 } else { | |
940 // To prevent potential section name collisions, add a default suffix for | |
Dan Beam
2012/10/19 00:12:44
you might want to add a comment here explaining wh
Ilya Sherman
2012/10/19 04:19:32
Done.
| |
941 // other fields. | |
942 (*field)->set_section(ASCIIToUTF16("-default")); | |
906 } | 943 } |
944 | |
945 // The preceding token, if any, may be a named section. | |
946 const string16 kSectionPrefix = ASCIIToUTF16("section-"); | |
947 if (!tokens.empty() && StartsWith(tokens.back(), kSectionPrefix, true)) { | |
948 *found_sections = true; | |
949 // Prepend this section name to the suffix set in the preceding block. | |
950 (*field)->set_section( | |
951 tokens.back().substr(kSectionPrefix.size()) + (*field)->section()); | |
952 tokens.pop_back(); | |
953 } | |
954 | |
955 // No other tokens are allowed. If there are any remaining, abort. | |
956 if (!tokens.empty()) | |
957 continue; | |
958 | |
959 // No errors encountered while parsing! | |
960 // Update the |field|'s type based on what was parsed from the attribute. | |
961 (*field)->set_heuristic_type(field_type); | |
962 if (field_type_token == ASCIIToUTF16("tel-local-prefix")) | |
963 (*field)->set_phone_part(AutofillField::PHONE_PREFIX); | |
964 else if (field_type_token == ASCIIToUTF16("tel-local-suffix")) | |
965 (*field)->set_phone_part(AutofillField::PHONE_SUFFIX); | |
907 } | 966 } |
908 } | 967 } |
909 | 968 |
910 void FormStructure::IdentifySections(bool has_author_specified_sections) { | 969 void FormStructure::IdentifySections(bool has_author_specified_sections) { |
911 if (fields_.empty()) | 970 if (fields_.empty()) |
912 return; | 971 return; |
913 | 972 |
914 if (!has_author_specified_sections) { | 973 if (!has_author_specified_sections) { |
915 // Name sections after the first field in the section. | 974 // Name sections after the first field in the section. |
916 string16 current_section = fields_.front()->unique_name(); | 975 string16 current_section = fields_.front()->unique_name(); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
962 for (std::vector<AutofillField*>::iterator field = fields_.begin(); | 1021 for (std::vector<AutofillField*>::iterator field = fields_.begin(); |
963 field != fields_.end(); ++field) { | 1022 field != fields_.end(); ++field) { |
964 AutofillType::FieldTypeGroup field_type_group = | 1023 AutofillType::FieldTypeGroup field_type_group = |
965 AutofillType((*field)->type()).group(); | 1024 AutofillType((*field)->type()).group(); |
966 if (field_type_group == AutofillType::CREDIT_CARD) | 1025 if (field_type_group == AutofillType::CREDIT_CARD) |
967 (*field)->set_section((*field)->section() + ASCIIToUTF16("-cc")); | 1026 (*field)->set_section((*field)->section() + ASCIIToUTF16("-cc")); |
968 else | 1027 else |
969 (*field)->set_section((*field)->section() + ASCIIToUTF16("-default")); | 1028 (*field)->set_section((*field)->section() + ASCIIToUTF16("-default")); |
970 } | 1029 } |
971 } | 1030 } |
OLD | NEW |