OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/autofill/core/browser/phone_field.h" | 5 #include "components/autofill/core/browser/phone_field.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
9 #include "base/strings/string16.h" | 9 #include "base/strings/string16.h" |
10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
12 #include "components/autofill/core/browser/autofill_field.h" | 12 #include "components/autofill/core/browser/autofill_field.h" |
13 #include "components/autofill/core/browser/autofill_regex_constants.h" | 13 #include "components/autofill/core/browser/autofill_regex_constants.h" |
14 #include "components/autofill/core/browser/autofill_scanner.h" | 14 #include "components/autofill/core/browser/autofill_scanner.h" |
15 | 15 |
16 namespace autofill { | 16 namespace autofill { |
17 namespace { | 17 namespace { |
18 | 18 |
19 // This string includes all area code separators, including NoText. | 19 // This string includes all area code separators, including NoText. |
20 base::string16 GetAreaRegex() { | 20 std::string GetAreaRegex() { |
21 base::string16 area_code = base::UTF8ToUTF16(kAreaCodeRe); | 21 std::string area_code = kAreaCodeRe; |
22 area_code.append(base::ASCIIToUTF16("|")); // Regexp separator. | 22 area_code.append("|"); // Regexp separator. |
23 area_code.append(base::UTF8ToUTF16(kAreaCodeNotextRe)); | 23 area_code.append(kAreaCodeNotextRe); |
24 return area_code; | 24 return area_code; |
25 } | 25 } |
26 | 26 |
27 } // namespace | 27 } // namespace |
28 | 28 |
29 PhoneField::~PhoneField() {} | 29 PhoneField::~PhoneField() {} |
30 | 30 |
31 // Phone field grammars - first matched grammar will be parsed. Grammars are | 31 // Phone field grammars - first matched grammar will be parsed. Grammars are |
32 // separated by { REGEX_SEPARATOR, FIELD_NONE, 0 }. Suffix and extension are | 32 // separated by { REGEX_SEPARATOR, FIELD_NONE, 0 }. Suffix and extension are |
33 // parsed separately unless they are necessary parts of the match. | 33 // parsed separately unless they are necessary parts of the match. |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 { REGEX_PHONE, FIELD_PHONE, 10 }, | 112 { REGEX_PHONE, FIELD_PHONE, 10 }, |
113 { REGEX_SEPARATOR, FIELD_NONE, 0 }, | 113 { REGEX_SEPARATOR, FIELD_NONE, 0 }, |
114 // Phone: <phone> (Ext: <ext>)? | 114 // Phone: <phone> (Ext: <ext>)? |
115 { REGEX_PHONE, FIELD_PHONE, 0 }, | 115 { REGEX_PHONE, FIELD_PHONE, 0 }, |
116 { REGEX_SEPARATOR, FIELD_NONE, 0 }, | 116 { REGEX_SEPARATOR, FIELD_NONE, 0 }, |
117 }; | 117 }; |
118 | 118 |
119 // static | 119 // static |
120 scoped_ptr<FormField> PhoneField::Parse(AutofillScanner* scanner) { | 120 scoped_ptr<FormField> PhoneField::Parse(AutofillScanner* scanner) { |
121 if (scanner->IsEnd()) | 121 if (scanner->IsEnd()) |
122 return NULL; | 122 return nullptr; |
123 | 123 |
124 scanner->SaveCursor(); | 124 size_t start_cursor = scanner->SaveCursor(); |
125 | 125 |
126 // The form owns the following variables, so they should not be deleted. | 126 // The form owns the following variables, so they should not be deleted. |
127 AutofillField* parsed_fields[FIELD_MAX]; | 127 AutofillField* parsed_fields[FIELD_MAX]; |
128 | 128 |
129 for (size_t i = 0; i < arraysize(kPhoneFieldGrammars); ++i) { | 129 for (size_t i = 0; i < arraysize(kPhoneFieldGrammars); ++i) { |
130 memset(parsed_fields, 0, sizeof(parsed_fields)); | 130 memset(parsed_fields, 0, sizeof(parsed_fields)); |
131 scanner->SaveCursor(); | 131 size_t saved_cursor = scanner->SaveCursor(); |
132 | 132 |
133 // Attempt to parse according to the next grammar. | 133 // Attempt to parse according to the next grammar. |
134 for (; i < arraysize(kPhoneFieldGrammars) && | 134 for (; i < arraysize(kPhoneFieldGrammars) && |
135 kPhoneFieldGrammars[i].regex != REGEX_SEPARATOR; ++i) { | 135 kPhoneFieldGrammars[i].regex != REGEX_SEPARATOR; ++i) { |
136 if (!ParseFieldSpecifics( | 136 if (!ParsePhoneField( |
137 scanner, | 137 scanner, |
138 GetRegExp(kPhoneFieldGrammars[i].regex), | 138 GetRegExp(kPhoneFieldGrammars[i].regex), |
139 MATCH_DEFAULT | MATCH_TELEPHONE, | |
140 &parsed_fields[kPhoneFieldGrammars[i].phone_part])) | 139 &parsed_fields[kPhoneFieldGrammars[i].phone_part])) |
141 break; | 140 break; |
142 if (kPhoneFieldGrammars[i].max_size && | 141 if (kPhoneFieldGrammars[i].max_size && |
143 (!parsed_fields[kPhoneFieldGrammars[i].phone_part]->max_length || | 142 (!parsed_fields[kPhoneFieldGrammars[i].phone_part]->max_length || |
144 kPhoneFieldGrammars[i].max_size < | 143 kPhoneFieldGrammars[i].max_size < |
145 parsed_fields[kPhoneFieldGrammars[i].phone_part]->max_length)) { | 144 parsed_fields[kPhoneFieldGrammars[i].phone_part]->max_length)) { |
146 break; | 145 break; |
147 } | 146 } |
148 } | 147 } |
149 | 148 |
150 if (i >= arraysize(kPhoneFieldGrammars)) { | 149 if (i >= arraysize(kPhoneFieldGrammars)) { |
151 scanner->Rewind(); | 150 scanner->RewindTo(saved_cursor); |
152 return NULL; // Parsing failed. | 151 return nullptr; // Parsing failed. |
153 } | 152 } |
154 if (kPhoneFieldGrammars[i].regex == REGEX_SEPARATOR) | 153 if (kPhoneFieldGrammars[i].regex == REGEX_SEPARATOR) |
155 break; // Parsing succeeded. | 154 break; // Parsing succeeded. |
156 | 155 |
157 // Proceed to the next grammar. | 156 // Proceed to the next grammar. |
158 do { | 157 do { |
159 ++i; | 158 ++i; |
160 } while (i < arraysize(kPhoneFieldGrammars) && | 159 } while (i < arraysize(kPhoneFieldGrammars) && |
161 kPhoneFieldGrammars[i].regex != REGEX_SEPARATOR); | 160 kPhoneFieldGrammars[i].regex != REGEX_SEPARATOR); |
162 | 161 |
| 162 scanner->RewindTo(saved_cursor); |
163 if (i + 1 == arraysize(kPhoneFieldGrammars)) { | 163 if (i + 1 == arraysize(kPhoneFieldGrammars)) { |
164 scanner->Rewind(); | 164 return nullptr; // Tried through all the possibilities - did not match. |
165 return NULL; // Tried through all the possibilities - did not match. | |
166 } | 165 } |
167 | |
168 scanner->Rewind(); | |
169 } | 166 } |
170 | 167 |
171 if (!parsed_fields[FIELD_PHONE]) { | 168 if (!parsed_fields[FIELD_PHONE]) { |
172 scanner->Rewind(); | 169 scanner->RewindTo(start_cursor); |
173 return NULL; | 170 return nullptr; |
174 } | 171 } |
175 | 172 |
176 scoped_ptr<PhoneField> phone_field(new PhoneField); | 173 scoped_ptr<PhoneField> phone_field(new PhoneField); |
177 for (int i = 0; i < FIELD_MAX; ++i) | 174 for (int i = 0; i < FIELD_MAX; ++i) |
178 phone_field->parsed_phone_fields_[i] = parsed_fields[i]; | 175 phone_field->parsed_phone_fields_[i] = parsed_fields[i]; |
179 | 176 |
180 // Look for optional fields. | 177 // Look for optional fields. |
181 | 178 |
182 // Look for a third text box. | 179 // Look for a third text box. |
183 if (!phone_field->parsed_phone_fields_[FIELD_SUFFIX]) { | 180 if (!phone_field->parsed_phone_fields_[FIELD_SUFFIX]) { |
184 if (!ParseField(scanner, base::UTF8ToUTF16(kPhoneSuffixRe), | 181 if (!ParsePhoneField(scanner, kPhoneSuffixRe, |
185 &phone_field->parsed_phone_fields_[FIELD_SUFFIX])) { | 182 &phone_field->parsed_phone_fields_[FIELD_SUFFIX])) { |
186 ParseField(scanner, base::UTF8ToUTF16(kPhoneSuffixSeparatorRe), | 183 ParsePhoneField(scanner, kPhoneSuffixSeparatorRe, |
187 &phone_field->parsed_phone_fields_[FIELD_SUFFIX]); | 184 &phone_field->parsed_phone_fields_[FIELD_SUFFIX]); |
188 } | 185 } |
189 } | 186 } |
190 | 187 |
191 // Now look for an extension. | 188 // Now look for an extension. |
192 ParseField(scanner, base::UTF8ToUTF16(kPhoneExtensionRe), | 189 // The extension is not actually used, so this just eats the field so other |
193 &phone_field->parsed_phone_fields_[FIELD_EXTENSION]); | 190 // parsers do not mistaken it for something else. |
| 191 ParsePhoneField(scanner, |
| 192 kPhoneExtensionRe, |
| 193 &phone_field->parsed_phone_fields_[FIELD_EXTENSION]); |
194 | 194 |
195 return phone_field.Pass(); | 195 return phone_field.Pass(); |
196 } | 196 } |
197 | 197 |
198 bool PhoneField::ClassifyField(ServerFieldTypeMap* map) const { | 198 bool PhoneField::ClassifyField(ServerFieldTypeMap* map) const { |
199 bool ok = true; | 199 bool ok = true; |
200 | 200 |
201 DCHECK(parsed_phone_fields_[FIELD_PHONE]); // Phone was correctly parsed. | 201 DCHECK(parsed_phone_fields_[FIELD_PHONE]); // Phone was correctly parsed. |
202 | 202 |
203 if ((parsed_phone_fields_[FIELD_COUNTRY_CODE] != NULL) || | 203 if ((parsed_phone_fields_[FIELD_COUNTRY_CODE]) || |
204 (parsed_phone_fields_[FIELD_AREA_CODE] != NULL) || | 204 (parsed_phone_fields_[FIELD_AREA_CODE]) || |
205 (parsed_phone_fields_[FIELD_SUFFIX] != NULL)) { | 205 (parsed_phone_fields_[FIELD_SUFFIX])) { |
206 if (parsed_phone_fields_[FIELD_COUNTRY_CODE] != NULL) { | 206 if (parsed_phone_fields_[FIELD_COUNTRY_CODE]) { |
207 ok = ok && AddClassification(parsed_phone_fields_[FIELD_COUNTRY_CODE], | 207 ok = ok && AddClassification(parsed_phone_fields_[FIELD_COUNTRY_CODE], |
208 PHONE_HOME_COUNTRY_CODE, | 208 PHONE_HOME_COUNTRY_CODE, |
209 map); | 209 map); |
210 } | 210 } |
211 | 211 |
212 ServerFieldType field_number_type = PHONE_HOME_NUMBER; | 212 ServerFieldType field_number_type = PHONE_HOME_NUMBER; |
213 if (parsed_phone_fields_[FIELD_AREA_CODE] != NULL) { | 213 if (parsed_phone_fields_[FIELD_AREA_CODE]) { |
214 ok = ok && AddClassification(parsed_phone_fields_[FIELD_AREA_CODE], | 214 ok = ok && AddClassification(parsed_phone_fields_[FIELD_AREA_CODE], |
215 PHONE_HOME_CITY_CODE, | 215 PHONE_HOME_CITY_CODE, |
216 map); | 216 map); |
217 } else if (parsed_phone_fields_[FIELD_COUNTRY_CODE] != NULL) { | 217 } else if (parsed_phone_fields_[FIELD_COUNTRY_CODE]) { |
218 // Only if we can find country code without city code, it means the phone | 218 // Only if we can find country code without city code, it means the phone |
219 // number include city code. | 219 // number include city code. |
220 field_number_type = PHONE_HOME_CITY_AND_NUMBER; | 220 field_number_type = PHONE_HOME_CITY_AND_NUMBER; |
221 } | 221 } |
222 // We tag the prefix as PHONE_HOME_NUMBER, then when filling the form | 222 // We tag the prefix as PHONE_HOME_NUMBER, then when filling the form |
223 // we fill only the prefix depending on the size of the input field. | 223 // we fill only the prefix depending on the size of the input field. |
224 ok = ok && AddClassification(parsed_phone_fields_[FIELD_PHONE], | 224 ok = ok && AddClassification(parsed_phone_fields_[FIELD_PHONE], |
225 field_number_type, | 225 field_number_type, |
226 map); | 226 map); |
227 // We tag the suffix as PHONE_HOME_NUMBER, then when filling the form | 227 // We tag the suffix as PHONE_HOME_NUMBER, then when filling the form |
228 // we fill only the suffix depending on the size of the input field. | 228 // we fill only the suffix depending on the size of the input field. |
229 if (parsed_phone_fields_[FIELD_SUFFIX] != NULL) { | 229 if (parsed_phone_fields_[FIELD_SUFFIX]) { |
230 ok = ok && AddClassification(parsed_phone_fields_[FIELD_SUFFIX], | 230 ok = ok && AddClassification(parsed_phone_fields_[FIELD_SUFFIX], |
231 PHONE_HOME_NUMBER, | 231 PHONE_HOME_NUMBER, |
232 map); | 232 map); |
233 } | 233 } |
234 } else { | 234 } else { |
235 ok = AddClassification(parsed_phone_fields_[FIELD_PHONE], | 235 ok = AddClassification(parsed_phone_fields_[FIELD_PHONE], |
236 PHONE_HOME_WHOLE_NUMBER, | 236 PHONE_HOME_WHOLE_NUMBER, |
237 map); | 237 map); |
238 } | 238 } |
239 | 239 |
240 return ok; | 240 return ok; |
241 } | 241 } |
242 | 242 |
243 PhoneField::PhoneField() { | 243 PhoneField::PhoneField() { |
244 memset(parsed_phone_fields_, 0, sizeof(parsed_phone_fields_)); | 244 memset(parsed_phone_fields_, 0, sizeof(parsed_phone_fields_)); |
245 } | 245 } |
246 | 246 |
247 // static | 247 // static |
248 base::string16 PhoneField::GetRegExp(RegexType regex_id) { | 248 std::string PhoneField::GetRegExp(RegexType regex_id) { |
249 switch (regex_id) { | 249 switch (regex_id) { |
250 case REGEX_COUNTRY: | 250 case REGEX_COUNTRY: |
251 return base::UTF8ToUTF16(kCountryCodeRe); | 251 return kCountryCodeRe; |
252 case REGEX_AREA: | 252 case REGEX_AREA: |
253 return GetAreaRegex(); | 253 return GetAreaRegex(); |
254 case REGEX_AREA_NOTEXT: | 254 case REGEX_AREA_NOTEXT: |
255 return base::UTF8ToUTF16(kAreaCodeNotextRe); | 255 return kAreaCodeNotextRe; |
256 case REGEX_PHONE: | 256 case REGEX_PHONE: |
257 return base::UTF8ToUTF16(kPhoneRe); | 257 return kPhoneRe; |
258 case REGEX_PREFIX_SEPARATOR: | 258 case REGEX_PREFIX_SEPARATOR: |
259 return base::UTF8ToUTF16(kPhonePrefixSeparatorRe); | 259 return kPhonePrefixSeparatorRe; |
260 case REGEX_PREFIX: | 260 case REGEX_PREFIX: |
261 return base::UTF8ToUTF16(kPhonePrefixRe); | 261 return kPhonePrefixRe; |
262 case REGEX_SUFFIX_SEPARATOR: | 262 case REGEX_SUFFIX_SEPARATOR: |
263 return base::UTF8ToUTF16(kPhoneSuffixSeparatorRe); | 263 return kPhoneSuffixSeparatorRe; |
264 case REGEX_SUFFIX: | 264 case REGEX_SUFFIX: |
265 return base::UTF8ToUTF16(kPhoneSuffixRe); | 265 return kPhoneSuffixRe; |
266 case REGEX_EXTENSION: | 266 case REGEX_EXTENSION: |
267 return base::UTF8ToUTF16(kPhoneExtensionRe); | 267 return kPhoneExtensionRe; |
268 default: | 268 default: |
269 NOTREACHED(); | 269 NOTREACHED(); |
270 break; | 270 break; |
271 } | 271 } |
272 return base::string16(); | 272 return std::string(); |
| 273 } |
| 274 |
| 275 // static |
| 276 bool PhoneField::ParsePhoneField(AutofillScanner* scanner, |
| 277 const std::string& regex, |
| 278 AutofillField** field) { |
| 279 return ParseFieldSpecifics(scanner, |
| 280 base::UTF8ToUTF16(regex), |
| 281 MATCH_DEFAULT | MATCH_TELEPHONE, |
| 282 field); |
273 } | 283 } |
274 | 284 |
275 } // namespace autofill | 285 } // namespace autofill |
OLD | NEW |