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

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

Issue 1010743007: Autofill: Apply the same field match mask to all phone field subtypes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 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
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/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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698