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

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

Issue 1453193002: autofill: switch autofill_regexes to RE2 library (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 14 tests failing Created 5 years 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/credit_card_field.h" 5 #include "components/autofill/core/browser/credit_card_field.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/scoped_ptr.h"
10 #include "base/stl_util.h" 10 #include "base/stl_util.h"
11 #include "base/strings/string16.h" 11 #include "base/strings/string16.h"
12 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_util.h" 13 #include "base/strings/string_util.h"
14 #include "base/strings/utf_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h"
Ilya Sherman 2015/11/26 02:25:09 Is this include still needed?
tfarina 2015/11/26 14:22:27 Done.
15 #include "base/time/time.h" 15 #include "base/time/time.h"
16 #include "components/autofill/core/browser/autofill_field.h" 16 #include "components/autofill/core/browser/autofill_field.h"
17 #include "components/autofill/core/browser/autofill_regex_constants.h" 17 #include "components/autofill/core/browser/autofill_regex_constants.h"
18 #include "components/autofill/core/browser/autofill_scanner.h" 18 #include "components/autofill/core/browser/autofill_scanner.h"
19 #include "components/autofill/core/browser/field_types.h" 19 #include "components/autofill/core/browser/field_types.h"
20 #include "components/autofill/core/common/autofill_regexes.h" 20 #include "components/autofill/core/common/autofill_regexes.h"
21 #include "grit/components_strings.h" 21 #include "grit/components_strings.h"
22 #include "ui/base/l10n/l10n_util.h" 22 #include "ui/base/l10n/l10n_util.h"
23 23
24 namespace autofill { 24 namespace autofill {
25 25
26 namespace { 26 namespace {
27 27
28 // Credit card numbers are at most 19 digits in length. 28 // Credit card numbers are at most 19 digits in length.
29 // [Ref: http://en.wikipedia.org/wiki/Bank_card_number] 29 // [Ref: http://en.wikipedia.org/wiki/Bank_card_number]
30 const size_t kMaxValidCardNumberSize = 19; 30 const size_t kMaxValidCardNumberSize = 19;
31 31
32 // Look for the vector |regex_needles| in |haystack|. Returns true if a 32 // Look for the vector |regex_needles| in |haystack|. Returns true if a
33 // consecutive section of |haystack| matches |regex_needles|. 33 // consecutive section of |haystack| matches |regex_needles|.
34 bool FindConsecutiveStrings(const std::vector<base::string16>& regex_needles, 34 bool FindConsecutiveStrings(const std::vector<base::string16>& regex_needles,
Ilya Sherman 2015/11/26 02:25:09 Please make this type also be std::string
tfarina 2015/11/26 14:22:27 Done.
35 const std::vector<base::string16>& haystack) { 35 const std::vector<base::string16>& haystack) {
36 if (regex_needles.empty() || 36 if (regex_needles.empty() ||
37 haystack.empty() || 37 haystack.empty() ||
38 (haystack.size() < regex_needles.size())) 38 (haystack.size() < regex_needles.size()))
39 return false; 39 return false;
40 40
41 for (size_t i = 0; i < haystack.size() - regex_needles.size() + 1; ++i) { 41 for (size_t i = 0; i < haystack.size() - regex_needles.size() + 1; ++i) {
42 for (size_t j = 0; j < regex_needles.size(); ++j) { 42 for (size_t j = 0; j < regex_needles.size(); ++j) {
43 if (!MatchesPattern(haystack[i + j], regex_needles[j])) 43 if (!MatchesPattern(haystack[i + j], base::UTF16ToUTF8(regex_needles[j])))
44 break; 44 break;
45 45
46 if (j == regex_needles.size() - 1) 46 if (j == regex_needles.size() - 1)
47 return true; 47 return true;
48 } 48 }
49 } 49 }
50 return false; 50 return false;
51 } 51 }
52 52
53 // Returns true if a field that has |max_length| can fit the data for a field of 53 // Returns true if a field that has |max_length| can fit the data for a field of
(...skipping 30 matching lines...) Expand all
84 84
85 // Credit card fields can appear in many different orders. 85 // Credit card fields can appear in many different orders.
86 // We loop until no more credit card related fields are found, see |break| at 86 // We loop until no more credit card related fields are found, see |break| at
87 // the bottom of the loop. 87 // the bottom of the loop.
88 for (int fields = 0; !scanner->IsEnd(); ++fields) { 88 for (int fields = 0; !scanner->IsEnd(); ++fields) {
89 // Ignore gift card fields. 89 // Ignore gift card fields.
90 if (IsGiftCardField(scanner)) 90 if (IsGiftCardField(scanner))
91 break; 91 break;
92 92
93 if (!credit_card_field->cardholder_) { 93 if (!credit_card_field->cardholder_) {
94 if (ParseField(scanner, 94 if (ParseField(scanner, kNameOnCardRe, &credit_card_field->cardholder_)) {
95 base::UTF8ToUTF16(kNameOnCardRe),
96 &credit_card_field->cardholder_)) {
97 continue; 95 continue;
98 } 96 }
99 97
100 // Sometimes the cardholder field is just labeled "name". Unfortunately 98 // Sometimes the cardholder field is just labeled "name". Unfortunately
101 // this is a dangerously generic word to search for, since it will often 99 // this is a dangerously generic word to search for, since it will often
102 // match a name (not cardholder name) field before or after credit card 100 // match a name (not cardholder name) field before or after credit card
103 // fields. So we search for "name" only when we've already parsed at 101 // fields. So we search for "name" only when we've already parsed at
104 // least one other credit card field and haven't yet parsed the 102 // least one other credit card field and haven't yet parsed the
105 // expiration date (which usually appears at the end). 103 // expiration date (which usually appears at the end).
106 if (fields > 0 && 104 if (fields > 0 && !credit_card_field->expiration_month_ &&
107 !credit_card_field->expiration_month_ && 105 ParseField(scanner, kNameOnCardContextualRe,
108 ParseField(scanner,
109 base::UTF8ToUTF16(kNameOnCardContextualRe),
110 &credit_card_field->cardholder_)) { 106 &credit_card_field->cardholder_)) {
111 continue; 107 continue;
112 } 108 }
113 } 109 }
114 110
115 // Check for a credit card type (Visa, MasterCard, etc.) field. 111 // Check for a credit card type (Visa, MasterCard, etc.) field.
116 // All CC type fields encountered so far have been of type select. 112 // All CC type fields encountered so far have been of type select.
117 if (!credit_card_field->type_ && LikelyCardTypeSelectField(scanner)) { 113 if (!credit_card_field->type_ && LikelyCardTypeSelectField(scanner)) {
118 credit_card_field->type_ = scanner->Cursor(); 114 credit_card_field->type_ = scanner->Cursor();
119 scanner->Advance(); 115 scanner->Advance();
120 continue; 116 continue;
121 } 117 }
122 118
123 // We look for a card security code before we look for a credit card number 119 // We look for a card security code before we look for a credit card number
124 // and match the general term "number". The security code has a plethora of 120 // and match the general term "number". The security code has a plethora of
125 // names; we've seen "verification #", "verification number", "card 121 // names; we've seen "verification #", "verification number", "card
126 // identification number", and others listed in the regex pattern used 122 // identification number", and others listed in the regex pattern used
127 // below. 123 // below.
128 // Note: Some sites use type="tel" or type="number" for numerical inputs. 124 // Note: Some sites use type="tel" or type="number" for numerical inputs.
129 const int kMatchNumAndTel = MATCH_DEFAULT | MATCH_NUMBER | MATCH_TELEPHONE; 125 const int kMatchNumAndTel = MATCH_DEFAULT | MATCH_NUMBER | MATCH_TELEPHONE;
130 if (!credit_card_field->verification_ && 126 if (!credit_card_field->verification_ &&
131 ParseFieldSpecifics(scanner, 127 ParseFieldSpecifics(scanner,
132 base::UTF8ToUTF16(kCardCvcRe), 128 kCardCvcRe,
133 kMatchNumAndTel | MATCH_PASSWORD, 129 kMatchNumAndTel | MATCH_PASSWORD,
134 &credit_card_field->verification_)) { 130 &credit_card_field->verification_)) {
135 continue; 131 continue;
136 } 132 }
137 133
138 AutofillField* current_number_field; 134 AutofillField* current_number_field;
139 if (ParseFieldSpecifics(scanner, 135 if (ParseFieldSpecifics(scanner,
140 base::UTF8ToUTF16(kCardNumberRe), 136 kCardNumberRe,
141 kMatchNumAndTel, 137 kMatchNumAndTel,
142 &current_number_field)) { 138 &current_number_field)) {
143 // Avoid autofilling any credit card number field having very low or high 139 // Avoid autofilling any credit card number field having very low or high
144 // |start_index| on the HTML form. 140 // |start_index| on the HTML form.
145 size_t start_index = 0; 141 size_t start_index = 0;
146 if (!credit_card_field->numbers_.empty()) { 142 if (!credit_card_field->numbers_.empty()) {
147 size_t last_number_field_size = 143 size_t last_number_field_size =
148 credit_card_field->numbers_.back()->credit_card_number_offset() + 144 credit_card_field->numbers_.back()->credit_card_number_offset() +
149 credit_card_field->numbers_.back()->max_length; 145 credit_card_field->numbers_.back()->max_length;
150 146
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 return false; 203 return false;
208 204
209 AutofillField* field = scanner->Cursor(); 205 AutofillField* field = scanner->Cursor();
210 if (!MatchesFormControlType(field->form_control_type, MATCH_SELECT)) 206 if (!MatchesFormControlType(field->form_control_type, MATCH_SELECT))
211 return false; 207 return false;
212 208
213 if (field->option_values.size() < 12 || field->option_values.size() > 13) 209 if (field->option_values.size() < 12 || field->option_values.size() > 13)
214 return false; 210 return false;
215 211
216 // Filter out years. 212 // Filter out years.
217 const base::string16 kNumericalYearRe = 213 const char kNumericalYearRe[] = "[1-9][0-9][0-9][0-9]";
218 base::ASCIIToUTF16("[1-9][0-9][0-9][0-9]");
219 for (const auto& value : field->option_values) { 214 for (const auto& value : field->option_values) {
220 if (MatchesPattern(value, kNumericalYearRe)) 215 if (MatchesPattern(value, kNumericalYearRe))
221 return false; 216 return false;
222 } 217 }
223 for (const auto& value : field->option_contents) { 218 for (const auto& value : field->option_contents) {
224 if (MatchesPattern(value, kNumericalYearRe)) 219 if (MatchesPattern(value, kNumericalYearRe))
225 return false; 220 return false;
226 } 221 }
227 222
228 // Look for numerical months. 223 // Look for numerical months.
229 const base::string16 kNumericalMonthRe = base::ASCIIToUTF16("12"); 224 const char kNumericalMonthRe[] = "12";
230 if (MatchesPattern(field->option_values.back(), kNumericalMonthRe) || 225 if (MatchesPattern(field->option_values.back(), kNumericalMonthRe) ||
231 MatchesPattern(field->option_contents.back(), kNumericalMonthRe)) { 226 MatchesPattern(field->option_contents.back(), kNumericalMonthRe)) {
232 return true; 227 return true;
233 } 228 }
234 229
235 // Maybe do more matches here. e.g. look for (translated) December. 230 // Maybe do more matches here. e.g. look for (translated) December.
236 231
237 // Unsure? Return false. 232 // Unsure? Return false.
238 return false; 233 return false;
239 } 234 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 *field, l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_MASTERCARD), 273 *field, l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_MASTERCARD),
279 nullptr); 274 nullptr);
280 } 275 }
281 276
282 // static 277 // static
283 bool CreditCardField::IsGiftCardField(AutofillScanner* scanner) { 278 bool CreditCardField::IsGiftCardField(AutofillScanner* scanner) {
284 if (scanner->IsEnd()) 279 if (scanner->IsEnd())
285 return false; 280 return false;
286 281
287 size_t saved_cursor = scanner->SaveCursor(); 282 size_t saved_cursor = scanner->SaveCursor();
288 if (ParseField(scanner, base::UTF8ToUTF16(kDebitCardRe), nullptr)) { 283 if (ParseField(scanner, kDebitCardRe, nullptr)) {
289 scanner->RewindTo(saved_cursor); 284 scanner->RewindTo(saved_cursor);
290 return false; 285 return false;
291 } 286 }
292 if (ParseField(scanner, base::UTF8ToUTF16(kDebitGiftCardRe), nullptr)) { 287 if (ParseField(scanner, kDebitGiftCardRe, nullptr)) {
293 scanner->RewindTo(saved_cursor); 288 scanner->RewindTo(saved_cursor);
294 return false; 289 return false;
295 } 290 }
296 291
297 return ParseField(scanner, base::UTF8ToUTF16(kGiftCardRe), nullptr); 292 return ParseField(scanner, kGiftCardRe, nullptr);
298 } 293 }
299 294
300 CreditCardField::CreditCardField() 295 CreditCardField::CreditCardField()
301 : cardholder_(nullptr), 296 : cardholder_(nullptr),
302 cardholder_last_(nullptr), 297 cardholder_last_(nullptr),
303 type_(nullptr), 298 type_(nullptr),
304 verification_(nullptr), 299 verification_(nullptr),
305 expiration_month_(nullptr), 300 expiration_month_(nullptr),
306 expiration_year_(nullptr), 301 expiration_year_(nullptr),
307 expiration_date_(nullptr), 302 expiration_date_(nullptr),
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 return true; 364 return true;
370 } 365 }
371 expiration_month_ = nullptr; 366 expiration_month_ = nullptr;
372 expiration_year_ = nullptr; 367 expiration_year_ = nullptr;
373 } 368 }
374 369
375 // If that fails, do a general regex search. 370 // If that fails, do a general regex search.
376 scanner->RewindTo(month_year_saved_cursor); 371 scanner->RewindTo(month_year_saved_cursor);
377 const int kMatchTelAndSelect = MATCH_DEFAULT | MATCH_TELEPHONE | MATCH_SELECT; 372 const int kMatchTelAndSelect = MATCH_DEFAULT | MATCH_TELEPHONE | MATCH_SELECT;
378 if (ParseFieldSpecifics(scanner, 373 if (ParseFieldSpecifics(scanner,
379 base::UTF8ToUTF16(kExpirationMonthRe), 374 kExpirationMonthRe,
380 kMatchTelAndSelect, 375 kMatchTelAndSelect,
381 &expiration_month_) && 376 &expiration_month_) &&
382 ParseFieldSpecifics(scanner, 377 ParseFieldSpecifics(scanner,
383 base::UTF8ToUTF16(kExpirationYearRe), 378 kExpirationYearRe,
384 kMatchTelAndSelect, 379 kMatchTelAndSelect,
385 &expiration_year_)) { 380 &expiration_year_)) {
386 return true; 381 return true;
387 } 382 }
388 383
389 // If that fails, look for just MM/YY(YY). 384 // If that fails, look for just MM/YY(YY).
390 scanner->RewindTo(month_year_saved_cursor); 385 scanner->RewindTo(month_year_saved_cursor);
391 if (ParseFieldSpecifics(scanner, 386 if (ParseFieldSpecifics(scanner,
392 base::ASCIIToUTF16("^mm$"), 387 "^mm$",
393 kMatchTelAndSelect, 388 kMatchTelAndSelect,
394 &expiration_month_) && 389 &expiration_month_) &&
395 ParseFieldSpecifics(scanner, 390 ParseFieldSpecifics(scanner,
396 base::ASCIIToUTF16("^(yy|yyyy)$"), 391 "^(yy|yyyy)$",
397 kMatchTelAndSelect, 392 kMatchTelAndSelect,
398 &expiration_year_)) { 393 &expiration_year_)) {
399 return true; 394 return true;
400 } 395 }
401 396
402 // If that fails, try to parse a combined expiration field. 397 // If that fails, try to parse a combined expiration field.
403 // We allow <select> fields, because they're used e.g. on qvc.com. 398 // We allow <select> fields, because they're used e.g. on qvc.com.
404 scanner->RewindTo(month_year_saved_cursor); 399 scanner->RewindTo(month_year_saved_cursor);
405 400
406 // Bail out if the field cannot fit a 2-digit year expiration date. 401 // Bail out if the field cannot fit a 2-digit year expiration date.
407 const int current_field_max_length = scanner->Cursor()->max_length; 402 const int current_field_max_length = scanner->Cursor()->max_length;
408 if (!FieldCanFitDataForFieldType(current_field_max_length, 403 if (!FieldCanFitDataForFieldType(current_field_max_length,
409 CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR)) { 404 CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR)) {
410 return false; 405 return false;
411 } 406 }
412 407
413 // Try to look for a 2-digit year expiration date. 408 // Try to look for a 2-digit year expiration date.
414 if (ParseFieldSpecifics(scanner, 409 if (ParseFieldSpecifics(scanner,
415 base::UTF8ToUTF16(kExpirationDate2DigitYearRe), 410 kExpirationDate2DigitYearRe,
416 kMatchTelAndSelect, 411 kMatchTelAndSelect,
417 &expiration_date_)) { 412 &expiration_date_)) {
418 exp_year_type_ = CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR; 413 exp_year_type_ = CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR;
419 expiration_month_ = nullptr; 414 expiration_month_ = nullptr;
420 return true; 415 return true;
421 } 416 }
422 417
423 // Try to look for a generic expiration date field. (2 or 4 digit year) 418 // Try to look for a generic expiration date field. (2 or 4 digit year)
424 if (ParseFieldSpecifics(scanner, 419 if (ParseFieldSpecifics(scanner,
425 base::UTF8ToUTF16(kExpirationDateRe), 420 kExpirationDateRe,
426 kMatchTelAndSelect, 421 kMatchTelAndSelect,
427 &expiration_date_)) { 422 &expiration_date_)) {
428 // If such a field exists, but it cannot fit a 4-digit year expiration 423 // If such a field exists, but it cannot fit a 4-digit year expiration
429 // date, then the likely possibility is that it is a 2-digit year expiration 424 // date, then the likely possibility is that it is a 2-digit year expiration
430 // date. 425 // date.
431 if (!FieldCanFitDataForFieldType(current_field_max_length, 426 if (!FieldCanFitDataForFieldType(current_field_max_length,
432 CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR)) { 427 CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR)) {
433 exp_year_type_ = CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR; 428 exp_year_type_ = CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR;
434 } 429 }
435 expiration_month_ = nullptr; 430 expiration_month_ = nullptr;
436 return true; 431 return true;
437 } 432 }
438 433
439 // Try to look for a 4-digit year expiration date. 434 // Try to look for a 4-digit year expiration date.
440 if (FieldCanFitDataForFieldType(current_field_max_length, 435 if (FieldCanFitDataForFieldType(current_field_max_length,
441 CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR) && 436 CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR) &&
442 ParseFieldSpecifics(scanner, 437 ParseFieldSpecifics(scanner,
443 base::UTF8ToUTF16(kExpirationDate4DigitYearRe), 438 kExpirationDate4DigitYearRe,
444 kMatchTelAndSelect, 439 kMatchTelAndSelect,
445 &expiration_date_)) { 440 &expiration_date_)) {
446 expiration_month_ = nullptr; 441 expiration_month_ = nullptr;
447 return true; 442 return true;
448 } 443 }
449 444
450 return false; 445 return false;
451 } 446 }
452 447
453 ServerFieldType CreditCardField::GetExpirationYearType() const { 448 ServerFieldType CreditCardField::GetExpirationYearType() const {
454 return (expiration_date_ 449 return (expiration_date_
455 ? exp_year_type_ 450 ? exp_year_type_
456 : ((expiration_year_ && expiration_year_->max_length == 2) 451 : ((expiration_year_ && expiration_year_->max_length == 2)
457 ? CREDIT_CARD_EXP_2_DIGIT_YEAR 452 ? CREDIT_CARD_EXP_2_DIGIT_YEAR
458 : CREDIT_CARD_EXP_4_DIGIT_YEAR)); 453 : CREDIT_CARD_EXP_4_DIGIT_YEAR));
459 } 454 }
460 455
461 } // namespace autofill 456 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698