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 http://is.gd/whatwg_autocomplete |
90 if (autocomplete_type == ASCIIToUTF16("given-name")) { | 90 // Note that "fax" and "pager" are intentionally ignored, as Chrome does not |
91 field->set_heuristic_type(NAME_FIRST); | 91 // support filling either type of information. |
92 return true; | 92 bool IsContactTypeHint(const string16& token) { |
93 return | |
94 token == ASCIIToUTF16("home") || | |
Evan Stade
2012/10/19 20:36:47
use LowerCaseEqualsASCII (here and many other plac
Evan Stade
2012/10/19 20:38:13
(meant to delete this comment)
| |
95 token == ASCIIToUTF16("work") || | |
96 token == ASCIIToUTF16("mobile") || | |
97 token == ASCIIToUTF16("pager"); | |
98 } | |
99 | |
100 // Returns |true| iff the |token| is a type hint appropriate for a field of the | |
101 // given |field_type|, as specified in the implementation section of | |
102 // http://is.gd/whatwg_autocomplete | |
103 bool ContactTypeHintMatchesFieldType(const string16& token, | |
104 AutofillFieldType field_type) { | |
105 // The "home" and "work" type hints are only appropriate for email and phone | |
106 // number field types. | |
107 if (token == ASCIIToUTF16("home") || token == ASCIIToUTF16("work")) { | |
108 return field_type == EMAIL_ADDRESS || | |
109 (field_type >= PHONE_HOME_NUMBER && | |
Evan Stade
2012/10/19 20:36:47
why is it called PHONE_HOME if it applies to work
Ilya Sherman
2012/10/20 05:16:08
Historical reasons. We used to have more phone nu
| |
110 field_type <= PHONE_HOME_WHOLE_NUMBER); | |
93 } | 111 } |
94 | 112 |
95 if (autocomplete_type == ASCIIToUTF16("middle-name")) { | 113 // The "mobile" type hint is only appropriate for phone number field types. |
96 field->set_heuristic_type(NAME_MIDDLE); | 114 // Note that "fax" and "pager" are intentionally ignored, as Chrome does not |
97 return true; | 115 // support filling either type of information. |
98 } | 116 if (token == ASCIIToUTF16("mobile")) { |
99 | 117 return field_type >= PHONE_HOME_NUMBER && |
100 if (autocomplete_type == ASCIIToUTF16("middle-initial")) { | 118 field_type <= PHONE_HOME_WHOLE_NUMBER; |
101 field->set_heuristic_type(NAME_MIDDLE_INITIAL); | |
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 } | 119 } |
227 | 120 |
228 return false; | 121 return false; |
229 } | 122 } |
230 | 123 |
124 // Returns the Chrome Autofill-supported field type corresponding to the given | |
125 // |autocomplete_type|, if there is one, in the context of the given |field|. | |
126 // Chrome Autofill supports a subset of the field types listed at | |
127 // http://is.gd/whatwg_autocomplete | |
128 AutofillFieldType FieldTypeFromAutocompleteType( | |
129 const string16& autocomplete_type, | |
130 const AutofillField& field) { | |
131 if (autocomplete_type == ASCIIToUTF16("name")) | |
132 return NAME_FULL; | |
133 | |
134 if (autocomplete_type == ASCIIToUTF16("given-name")) | |
135 return NAME_FIRST; | |
136 | |
137 if (autocomplete_type == ASCIIToUTF16("additional-name")) { | |
138 if (field.max_length == 1) | |
139 return NAME_MIDDLE_INITIAL; | |
140 else | |
141 return NAME_MIDDLE; | |
142 } | |
143 | |
144 if (autocomplete_type == ASCIIToUTF16("family-name")) | |
145 return NAME_LAST; | |
146 | |
147 if (autocomplete_type == ASCIIToUTF16("honorific-suffix")) | |
148 return NAME_SUFFIX; | |
149 | |
150 if (autocomplete_type == ASCIIToUTF16("organization")) | |
151 return COMPANY_NAME; | |
152 | |
153 if (autocomplete_type == ASCIIToUTF16("street-address") || | |
154 autocomplete_type == ASCIIToUTF16("address-line1")) | |
155 return ADDRESS_HOME_LINE1; | |
156 | |
157 if (autocomplete_type == ASCIIToUTF16("address-line2")) | |
158 return ADDRESS_HOME_LINE2; | |
159 | |
160 if (autocomplete_type == ASCIIToUTF16("locality")) | |
161 return ADDRESS_HOME_CITY; | |
162 | |
163 if (autocomplete_type == ASCIIToUTF16("region")) | |
164 return ADDRESS_HOME_STATE; | |
165 | |
166 if (autocomplete_type == ASCIIToUTF16("country")) | |
167 return ADDRESS_HOME_COUNTRY; | |
168 | |
169 if (autocomplete_type == ASCIIToUTF16("postal-code")) | |
170 return ADDRESS_HOME_ZIP; | |
171 | |
172 if (autocomplete_type == ASCIIToUTF16("cc-name")) | |
173 return CREDIT_CARD_NAME; | |
174 | |
175 if (autocomplete_type == ASCIIToUTF16("cc-number")) | |
176 return CREDIT_CARD_NUMBER; | |
177 | |
178 if (autocomplete_type == ASCIIToUTF16("cc-exp")) { | |
179 if (field.max_length == 5) | |
180 return CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR; | |
181 else | |
182 return CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR; | |
183 } | |
184 | |
185 if (autocomplete_type == ASCIIToUTF16("cc-exp-month")) | |
186 return CREDIT_CARD_EXP_MONTH; | |
187 | |
188 if (autocomplete_type == ASCIIToUTF16("cc-exp-year")) { | |
189 if (field.max_length == 2) | |
190 return CREDIT_CARD_EXP_2_DIGIT_YEAR; | |
191 else | |
192 return CREDIT_CARD_EXP_4_DIGIT_YEAR; | |
193 } | |
194 | |
195 if (autocomplete_type == ASCIIToUTF16("tel")) | |
196 return PHONE_HOME_WHOLE_NUMBER; | |
197 | |
198 if (autocomplete_type == ASCIIToUTF16("tel-country-code")) | |
199 return PHONE_HOME_COUNTRY_CODE; | |
200 | |
201 if (autocomplete_type == ASCIIToUTF16("tel-national")) | |
202 return PHONE_HOME_CITY_AND_NUMBER; | |
203 | |
204 if (autocomplete_type == ASCIIToUTF16("tel-area-code")) | |
205 return PHONE_HOME_CITY_CODE; | |
206 | |
207 if (autocomplete_type == ASCIIToUTF16("tel-local")) | |
208 return PHONE_HOME_NUMBER; | |
209 | |
210 if (autocomplete_type == ASCIIToUTF16("tel-local-prefix")) | |
211 return PHONE_HOME_NUMBER; | |
212 | |
213 if (autocomplete_type == ASCIIToUTF16("tel-local-suffix")) | |
214 return PHONE_HOME_NUMBER; | |
215 | |
216 if (autocomplete_type == ASCIIToUTF16("email")) | |
217 return EMAIL_ADDRESS; | |
218 | |
219 return UNKNOWN_TYPE; | |
220 } | |
221 | |
231 } // namespace | 222 } // namespace |
232 | 223 |
233 FormStructure::FormStructure(const FormData& form) | 224 FormStructure::FormStructure(const FormData& form) |
234 : form_name_(form.name), | 225 : form_name_(form.name), |
235 source_url_(form.origin), | 226 source_url_(form.origin), |
236 target_url_(form.action), | 227 target_url_(form.action), |
237 autofill_count_(0), | 228 autofill_count_(0), |
238 upload_required_(USE_UPLOAD_RATES), | 229 upload_required_(USE_UPLOAD_RATES), |
239 server_experiment_id_("no server response"), | 230 server_experiment_id_("no server response"), |
240 has_author_specified_types_(false) { | 231 has_author_specified_types_(false) { |
(...skipping 25 matching lines...) Expand all Loading... | |
266 } else { | 257 } else { |
267 // Either the method is 'get', or we don't know. In this case we default | 258 // Either the method is 'get', or we don't know. In this case we default |
268 // to GET. | 259 // to GET. |
269 method_ = GET; | 260 method_ = GET; |
270 } | 261 } |
271 } | 262 } |
272 | 263 |
273 FormStructure::~FormStructure() {} | 264 FormStructure::~FormStructure() {} |
274 | 265 |
275 void FormStructure::DetermineHeuristicTypes() { | 266 void FormStructure::DetermineHeuristicTypes() { |
276 // First, try to detect field types based on the fields' |autocompletetype| | 267 // 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 | 268 // attribute value. If there is at least one form field that specifies an |
278 // try to apply other heuristics to match fields in this form. | 269 // autocomplete type hint, don't try to apply other heuristics to match fields |
270 // in this form. | |
279 bool has_author_specified_sections; | 271 bool has_author_specified_sections; |
280 ParseAutocompletetypeAttributes(&has_author_specified_types_, | 272 ParseFieldTypesFromAutocompleteAttributes(&has_author_specified_types_, |
281 &has_author_specified_sections); | 273 &has_author_specified_sections); |
282 | 274 |
283 if (!has_author_specified_types_) { | 275 if (!has_author_specified_types_) { |
284 FieldTypeMap field_type_map; | 276 FieldTypeMap field_type_map; |
285 FormField::ParseFormFields(fields_.get(), &field_type_map); | 277 FormField::ParseFormFields(fields_.get(), &field_type_map); |
286 for (size_t index = 0; index < field_count(); index++) { | 278 for (size_t index = 0; index < field_count(); index++) { |
287 AutofillField* field = fields_[index]; | 279 AutofillField* field = fields_[index]; |
288 FieldTypeMap::iterator iter = field_type_map.find(field->unique_name()); | 280 FieldTypeMap::iterator iter = field_type_map.find(field->unique_name()); |
289 if (iter != field_type_map.end()) | 281 if (iter != field_type_map.end()) |
290 field->set_heuristic_type(iter->second); | 282 field->set_heuristic_type(iter->second); |
291 } | 283 } |
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
871 buzz::XmlElement *field_element = new buzz::XmlElement( | 863 buzz::XmlElement *field_element = new buzz::XmlElement( |
872 buzz::QName(kXMLElementField)); | 864 buzz::QName(kXMLElementField)); |
873 field_element->SetAttr(buzz::QName(kAttributeSignature), | 865 field_element->SetAttr(buzz::QName(kAttributeSignature), |
874 field->FieldSignature()); | 866 field->FieldSignature()); |
875 encompassing_xml_element->AddElement(field_element); | 867 encompassing_xml_element->AddElement(field_element); |
876 } | 868 } |
877 } | 869 } |
878 return true; | 870 return true; |
879 } | 871 } |
880 | 872 |
881 void FormStructure::ParseAutocompletetypeAttributes(bool* found_attribute, | 873 void FormStructure::ParseFieldTypesFromAutocompleteAttributes( |
882 bool* found_sections) { | 874 bool* found_types, |
883 *found_attribute = false; | 875 bool* found_sections) { |
876 *found_types = false; | |
884 *found_sections = false; | 877 *found_sections = false; |
885 for (std::vector<AutofillField*>::iterator field = fields_.begin(); | 878 for (std::vector<AutofillField*>::iterator field = fields_.begin(); |
886 field != fields_.end(); ++field) { | 879 field != fields_.end(); ++field) { |
Evan Stade
2012/10/19 20:36:47
nit: can you call field iter, and then do
Autofil
Ilya Sherman
2012/10/20 05:16:08
Done.
| |
887 if ((*field)->autocomplete_type.empty()) | 880 // Canonicalize the attribute value by trimming whitespace and converting to |
881 // lowercase ASCII. | |
882 string16 autocomplete_attribute = (*field)->autocomplete_attribute; | |
Evan Stade
2012/10/19 20:36:47
see my note elsewhere that the field's attribute s
Ilya Sherman
2012/10/20 05:16:08
Done.
| |
883 TrimWhitespace(autocomplete_attribute, TRIM_ALL, &autocomplete_attribute); | |
884 autocomplete_attribute = StringToLowerASCII(autocomplete_attribute); | |
885 | |
886 // The autocomplete attribute is overloaded: it can specify either a field | |
887 // type hint or whether autocomplete should be enabled at all. Ignore the | |
888 // latter type of attribute value. | |
889 if (autocomplete_attribute.empty() || | |
890 autocomplete_attribute == ASCIIToUTF16("on") || | |
891 autocomplete_attribute == ASCIIToUTF16("off")) { | |
892 continue; | |
893 } | |
894 | |
895 // Any other value, even it is invalid, is considered to be a type hint. | |
896 // This allows a website's author to specify an attribute like | |
897 // autocomplete="other" on a field to disable all Autofill heuristics for | |
Evan Stade
2012/10/19 20:36:47
don't follow this logic. Are you saying that autoc
Ilya Sherman
2012/10/20 05:16:08
The two are different. autocomplete="off" means d
| |
898 // the form. | |
899 *found_types = true; | |
900 | |
901 // Tokenize the attribute value. Per the spec, the tokens are parsed in | |
902 // reverse order. | |
903 std::vector<string16> tokens; | |
Evan Stade
2012/10/19 20:36:47
likewise, should be std::string
Ilya Sherman
2012/10/20 05:16:08
Done.
| |
904 Tokenize(autocomplete_attribute, ASCIIToUTF16(" "), &tokens); | |
Evan Stade
2012/10/19 20:59:44
should this include other space characters, or wer
Ilya Sherman
2012/10/20 05:16:08
Done + added test coverage (to the advanced.html t
| |
905 | |
906 // The final token must be the field type. | |
907 // If it is not one of the known types, abort. | |
908 DCHECK(!tokens.empty()); | |
909 string16 field_type_token = tokens.back(); | |
910 tokens.pop_back(); | |
911 AutofillFieldType field_type = | |
912 FieldTypeFromAutocompleteType(field_type_token, **field); | |
913 if (field_type == UNKNOWN_TYPE) | |
888 continue; | 914 continue; |
889 | 915 |
890 *found_attribute = true; | 916 // The preceding token, if any, may be a type hint. |
891 std::vector<string16> types; | 917 if (!tokens.empty() && IsContactTypeHint(tokens.back())) { |
892 Tokenize((*field)->autocomplete_type, ASCIIToUTF16(" "), &types); | 918 // If it is, it must match the field type; otherwise, abort. |
919 // Note that an invalid token invalidates the entire attribute value, even | |
920 // if the other tokens are valid. | |
921 if (!ContactTypeHintMatchesFieldType(tokens.back(), field_type)) | |
922 continue; | |
893 | 923 |
894 // Look for a named section. | 924 // Chrome Autofill ignores these type hints. |
895 const string16 kSectionPrefix = ASCIIToUTF16("section-"); | 925 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 } | 926 } |
900 | 927 |
901 // Look for specified types. | 928 // The preceding token, if any, may be a fixed string that is either |
902 for (std::vector<string16>::const_iterator type = types.begin(); | 929 // "shipping" or "billing". Chrome Autofill treats these as implicit |
903 type != types.end(); ++type) { | 930 // section name suffixes. |
904 if (UpdateFromAutocompleteType(*type, *field)) | 931 if (!tokens.empty() && |
905 break; | 932 (tokens.back() == ASCIIToUTF16("shipping") || |
933 tokens.back() == ASCIIToUTF16("billing"))) { | |
934 *found_sections = true; | |
935 (*field)->set_section(ASCIIToUTF16("-") + tokens.back()); | |
936 tokens.pop_back(); | |
937 } else { | |
938 // To prevent potential section name collisions, add a default suffix for | |
939 // other fields. Without this, 'autocomplete' attribute values | |
940 // "section--shipping street-address" and "shipping street-address" would | |
Evan Stade
2012/10/19 20:36:47
can you help me understand this section? It seems
Evan Stade
2012/10/19 20:57:27
Dan explained this to me. So is it intentional tha
Ilya Sherman
2012/10/20 05:16:08
Yes, it's intentional. We fill differently named
| |
941 // be parsed identically. | |
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()); | |
Evan Stade
2012/10/19 20:57:27
do you need to check for "section- " (i.e. with no
Ilya Sherman
2012/10/20 05:16:08
It's covered in the tests: we treat this as equiva
| |
952 tokens.pop_back(); | |
953 } | |
954 | |
955 // No other tokens are allowed. If there are any remaining, abort. | |
Evan Stade
2012/10/19 20:36:47
if you are aborting, and you just set found_sectio
Ilya Sherman
2012/10/20 05:16:08
Good call. Fixed, and added test coverage. The f
| |
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 |