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

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

Issue 2136453003: [Autofill] Improve support for various credit card expiration dates. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Initial Created 4 years, 5 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/credit_card.h" 5 #include "components/autofill/core/browser/credit_card.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 17 matching lines...) Expand all
28 #include "components/autofill/core/browser/validation.h" 28 #include "components/autofill/core/browser/validation.h"
29 #include "components/autofill/core/common/autofill_l10n_util.h" 29 #include "components/autofill/core/common/autofill_l10n_util.h"
30 #include "components/autofill/core/common/autofill_regexes.h" 30 #include "components/autofill/core/common/autofill_regexes.h"
31 #include "components/autofill/core/common/form_field_data.h" 31 #include "components/autofill/core/common/form_field_data.h"
32 #include "grit/components_scaled_resources.h" 32 #include "grit/components_scaled_resources.h"
33 #include "grit/components_strings.h" 33 #include "grit/components_strings.h"
34 #include "third_party/icu/source/common/unicode/uloc.h" 34 #include "third_party/icu/source/common/unicode/uloc.h"
35 #include "third_party/icu/source/i18n/unicode/dtfmtsym.h" 35 #include "third_party/icu/source/i18n/unicode/dtfmtsym.h"
36 #include "ui/base/l10n/l10n_util.h" 36 #include "ui/base/l10n/l10n_util.h"
37 37
38 using base::ASCIIToUTF16;
39
38 namespace autofill { 40 namespace autofill {
39 41
40 const base::char16 kMidlineEllipsis[] = { 0x22ef, 0 }; 42 const base::char16 kMidlineEllipsis[] = { 0x22ef, 0 };
41 43
42 namespace { 44 namespace {
43 45
44 const base::char16 kCreditCardObfuscationSymbol = '*'; 46 const base::char16 kCreditCardObfuscationSymbol = '*';
45 const base::char16 kNonBreakingSpace[] = { 0x00a0, 0 }; 47 const base::char16 kNonBreakingSpace[] = { 0x00a0, 0 };
46 48
47 bool ConvertYear(const base::string16& year, int* num) { 49 bool ConvertYear(const base::string16& year, int* num) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 113
112 CreditCard::CreditCard(const CreditCard& credit_card) : CreditCard() { 114 CreditCard::CreditCard(const CreditCard& credit_card) : CreditCard() {
113 operator=(credit_card); 115 operator=(credit_card);
114 } 116 }
115 117
116 CreditCard::~CreditCard() {} 118 CreditCard::~CreditCard() {}
117 119
118 // static 120 // static
119 const base::string16 CreditCard::StripSeparators(const base::string16& number) { 121 const base::string16 CreditCard::StripSeparators(const base::string16& number) {
120 base::string16 stripped; 122 base::string16 stripped;
121 base::RemoveChars(number, base::ASCIIToUTF16("- "), &stripped); 123 base::RemoveChars(number, ASCIIToUTF16("- "), &stripped);
122 return stripped; 124 return stripped;
123 } 125 }
124 126
125 // static 127 // static
126 base::string16 CreditCard::TypeForDisplay(const std::string& type) { 128 base::string16 CreditCard::TypeForDisplay(const std::string& type) {
127 if (kGenericCard == type) 129 if (kGenericCard == type)
128 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_GENERIC); 130 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_GENERIC);
129 if (kAmericanExpressCard == type) 131 if (kAmericanExpressCard == type)
130 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_AMEX_SHORT); 132 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_AMEX_SHORT);
131 133
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 case CREDIT_CARD_EXP_2_DIGIT_YEAR: 285 case CREDIT_CARD_EXP_2_DIGIT_YEAR:
284 return Expiration2DigitYearAsString(); 286 return Expiration2DigitYearAsString();
285 287
286 case CREDIT_CARD_EXP_4_DIGIT_YEAR: 288 case CREDIT_CARD_EXP_4_DIGIT_YEAR:
287 return Expiration4DigitYearAsString(); 289 return Expiration4DigitYearAsString();
288 290
289 case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR: { 291 case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR: {
290 base::string16 month = ExpirationMonthAsString(); 292 base::string16 month = ExpirationMonthAsString();
291 base::string16 year = Expiration2DigitYearAsString(); 293 base::string16 year = Expiration2DigitYearAsString();
292 if (!month.empty() && !year.empty()) 294 if (!month.empty() && !year.empty())
293 return month + base::ASCIIToUTF16("/") + year; 295 return month + ASCIIToUTF16("/") + year;
294 return base::string16(); 296 return base::string16();
295 } 297 }
296 298
297 case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR: { 299 case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR: {
298 base::string16 month = ExpirationMonthAsString(); 300 base::string16 month = ExpirationMonthAsString();
299 base::string16 year = Expiration4DigitYearAsString(); 301 base::string16 year = Expiration4DigitYearAsString();
300 if (!month.empty() && !year.empty()) 302 if (!month.empty() && !year.empty())
301 return month + base::ASCIIToUTF16("/") + year; 303 return month + ASCIIToUTF16("/") + year;
302 return base::string16(); 304 return base::string16();
303 } 305 }
304 306
305 case CREDIT_CARD_TYPE: 307 case CREDIT_CARD_TYPE:
306 return TypeForFill(); 308 return TypeForFill();
307 309
308 case CREDIT_CARD_NUMBER: 310 case CREDIT_CARD_NUMBER:
309 return number_; 311 return number_;
310 312
311 case CREDIT_CARD_VERIFICATION_CODE: 313 case CREDIT_CARD_VERIFICATION_CODE:
(...skipping 12 matching lines...) Expand all
324 switch (type) { 326 switch (type) {
325 case CREDIT_CARD_NAME_FULL: 327 case CREDIT_CARD_NAME_FULL:
326 name_on_card_ = value; 328 name_on_card_ = value;
327 break; 329 break;
328 330
329 case CREDIT_CARD_EXP_MONTH: 331 case CREDIT_CARD_EXP_MONTH:
330 SetExpirationMonthFromString(value, std::string()); 332 SetExpirationMonthFromString(value, std::string());
331 break; 333 break;
332 334
333 case CREDIT_CARD_EXP_2_DIGIT_YEAR: 335 case CREDIT_CARD_EXP_2_DIGIT_YEAR:
334 // This is a read-only attribute. 336 SetExpirationYearFromString(value);
335 break; 337 break;
336 338
337 case CREDIT_CARD_EXP_4_DIGIT_YEAR: 339 case CREDIT_CARD_EXP_4_DIGIT_YEAR:
338 SetExpirationYearFromString(value); 340 SetExpirationYearFromString(value);
339 break; 341 break;
340 342
341 case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR: 343 case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR:
342 // This is a read-only attribute. 344 SetExpirationDateFromString(value);
343 break; 345 break;
344 346
345 case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR: 347 case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR:
346 // This is a read-only attribute. 348 SetExpirationDateFromString(value);
347 break; 349 break;
348 350
349 case CREDIT_CARD_TYPE: 351 case CREDIT_CARD_TYPE:
350 // This is a read-only attribute, determined by the credit card number. 352 // This is a read-only attribute, determined by the credit card number.
351 break; 353 break;
352 354
353 case CREDIT_CARD_NUMBER: { 355 case CREDIT_CARD_NUMBER: {
354 // Don't change the real value if the input is an obfuscated string. 356 // Don't change the real value if the input is an obfuscated string.
355 if (value.size() > 0 && value[0] != kCreditCardObfuscationSymbol) 357 if (value.size() > 0 && value[0] != kCreditCardObfuscationSymbol)
356 SetNumber(value); 358 SetNumber(value);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 // No CC number, return name only. 426 // No CC number, return name only.
425 if (number().empty()) 427 if (number().empty())
426 return std::make_pair(name_on_card_, base::string16()); 428 return std::make_pair(name_on_card_, base::string16());
427 429
428 base::string16 obfuscated_cc_number = TypeAndLastFourDigits(); 430 base::string16 obfuscated_cc_number = TypeAndLastFourDigits();
429 // No expiration date set. 431 // No expiration date set.
430 if (!expiration_month_ || !expiration_year_) 432 if (!expiration_month_ || !expiration_year_)
431 return std::make_pair(obfuscated_cc_number, base::string16()); 433 return std::make_pair(obfuscated_cc_number, base::string16());
432 434
433 base::string16 formatted_date(ExpirationMonthAsString()); 435 base::string16 formatted_date(ExpirationMonthAsString());
434 formatted_date.append(base::ASCIIToUTF16("/")); 436 formatted_date.append(ASCIIToUTF16("/"));
435 formatted_date.append(Expiration4DigitYearAsString()); 437 formatted_date.append(Expiration4DigitYearAsString());
436 438
437 base::string16 separator = 439 base::string16 separator =
438 l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_SUMMARY_SEPARATOR); 440 l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_SUMMARY_SEPARATOR);
439 return std::make_pair(obfuscated_cc_number, separator + formatted_date); 441 return std::make_pair(obfuscated_cc_number, separator + formatted_date);
440 } 442 }
441 443
442 void CreditCard::SetInfoForMonthInputType(const base::string16& value) { 444 void CreditCard::SetInfoForMonthInputType(const base::string16& value) {
443 // Check if |text| is "yyyy-mm" format first, and check normal month format. 445 // Check if |text| is "yyyy-mm" format first, and check normal month format.
444 if (!MatchesPattern(value, base::UTF8ToUTF16("^[0-9]{4}-[0-9]{1,2}$"))) 446 if (!MatchesPattern(value, base::UTF8ToUTF16("^[0-9]{4}-[0-9]{1,2}$")))
445 return; 447 return;
446 448
447 std::vector<base::StringPiece16> year_month = base::SplitStringPiece( 449 std::vector<base::StringPiece16> year_month = base::SplitStringPiece(
448 value, base::ASCIIToUTF16("-"), 450 value, ASCIIToUTF16("-"), base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
449 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
450 DCHECK_EQ(2u, year_month.size()); 451 DCHECK_EQ(2u, year_month.size());
451 int num = 0; 452 int num = 0;
452 bool converted = false; 453 bool converted = false;
453 converted = base::StringToInt(year_month[0], &num); 454 converted = base::StringToInt(year_month[0], &num);
454 DCHECK(converted); 455 DCHECK(converted);
455 SetExpirationYear(num); 456 SetExpirationYear(num);
456 converted = base::StringToInt(year_month[1], &num); 457 converted = base::StringToInt(year_month[1], &num);
457 DCHECK(converted); 458 DCHECK(converted);
458 SetExpirationMonth(num); 459 SetExpirationMonth(num);
459 } 460 }
460 461
461 void CreditCard::SetExpirationMonth(int expiration_month) { 462 void CreditCard::SetExpirationMonth(int expiration_month) {
462 if (expiration_month < 0 || expiration_month > 12) 463 if (expiration_month < 0 || expiration_month > 12)
463 return; 464 return;
464 expiration_month_ = expiration_month; 465 expiration_month_ = expiration_month;
465 } 466 }
466 467
467 void CreditCard::SetExpirationYear(int expiration_year) { 468 void CreditCard::SetExpirationYear(int expiration_year) {
468 if (expiration_year != 0 && 469 if (expiration_year != 0 && expiration_year > 10000)
469 (expiration_year < 2006 || expiration_year > 10000))
470 return; 470 return;
471
472 // Will normalize 2-digit years to the 4-digit version.
473 if (expiration_year > 0 && expiration_year < 100) {
474 base::Time::Exploded now_exploded;
475 base::Time::Now().LocalExplode(&now_exploded);
476 expiration_year += (now_exploded.year / 100) * 100;
477 }
478
471 expiration_year_ = expiration_year; 479 expiration_year_ = expiration_year;
472 } 480 }
473 481
474 base::string16 CreditCard::LastFourDigits() const { 482 base::string16 CreditCard::LastFourDigits() const {
475 static const size_t kNumLastDigits = 4; 483 static const size_t kNumLastDigits = 4;
476 484
477 base::string16 number = StripSeparators(number_); 485 base::string16 number = StripSeparators(number_);
478 if (number.size() <= kNumLastDigits) 486 if (number.size() <= kNumLastDigits)
479 return number; 487 return number;
480 488
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 } 673 }
666 674
667 base::string16 CreditCard::ExpirationMonthAsString() const { 675 base::string16 CreditCard::ExpirationMonthAsString() const {
668 if (expiration_month_ == 0) 676 if (expiration_month_ == 0)
669 return base::string16(); 677 return base::string16();
670 678
671 base::string16 month = base::IntToString16(expiration_month_); 679 base::string16 month = base::IntToString16(expiration_month_);
672 if (expiration_month_ >= 10) 680 if (expiration_month_ >= 10)
673 return month; 681 return month;
674 682
675 base::string16 zero = base::ASCIIToUTF16("0"); 683 base::string16 zero = ASCIIToUTF16("0");
676 zero.append(month); 684 zero.append(month);
677 return zero; 685 return zero;
678 } 686 }
679 687
680 base::string16 CreditCard::TypeForFill() const { 688 base::string16 CreditCard::TypeForFill() const {
681 return ::autofill::TypeForFill(type_); 689 return ::autofill::TypeForFill(type_);
682 } 690 }
683 691
684 base::string16 CreditCard::Expiration4DigitYearAsString() const { 692 base::string16 CreditCard::Expiration4DigitYearAsString() const {
685 if (expiration_year_ == 0) 693 if (expiration_year_ == 0)
(...skipping 23 matching lines...) Expand all
709 } 717 }
710 718
711 void CreditCard::SetExpirationYearFromString(const base::string16& text) { 719 void CreditCard::SetExpirationYearFromString(const base::string16& text) {
712 int year; 720 int year;
713 if (!ConvertYear(text, &year)) 721 if (!ConvertYear(text, &year))
714 return; 722 return;
715 723
716 SetExpirationYear(year); 724 SetExpirationYear(year);
717 } 725 }
718 726
727 void CreditCard::SetExpirationDateFromString(const base::string16& text) {
728 // Check that it fits the supported patterns: myy, myyyy, mmyy, mmyyyy, m-yy,
sebsg 2016/07/08 10:01:45 nit: it -> the |text|
Mathieu 2016/07/08 14:27:04 Done.
729 // mm-yy, m-yyyy and mm-yyyy. Separators: -, / and |.
730 if (!MatchesPattern(text, base::UTF8ToUTF16("^[0-9]{1,2}[-/|]?[0-9]{2,4}$")))
731 return;
732
733 base::string16 month;
734 base::string16 year;
735
736 // Check for a separator.
737 base::string16 found_separator;
738 const std::vector<const base::string16> kSeparators{
739 ASCIIToUTF16("-"), ASCIIToUTF16("/"), ASCIIToUTF16("|")};
740 for (const base::string16& separator : kSeparators) {
741 if (text.find(separator) != base::string16::npos)
742 found_separator = separator;
743 }
744
745 if (!found_separator.empty()) {
746 std::vector<base::string16> month_year = base::SplitString(
747 text, found_separator, base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
748 DCHECK_EQ(2u, month_year.size());
749 month = month_year[0];
750 year = month_year[1];
751 } else {
752 // There is no separator, the format is either myy, mmyy, myyyy or mmyyyy.
753 // Month is either 1 or 2 digits. Year is always even number of digits.
754 base::string16::size_type month_length = text.size() % 2 == 0 ? 2 : 1;
755 month = text.substr(0, month_length);
756 year = text.substr(month_length);
757 }
758
759 int num = 0;
760 bool converted = false;
761 converted = base::StringToInt(month, &num);
762 DCHECK(converted);
763 SetExpirationMonth(num);
764 converted = base::StringToInt(year, &num);
765 DCHECK(converted);
766 SetExpirationYear(num);
767 }
768
719 void CreditCard::SetNumber(const base::string16& number) { 769 void CreditCard::SetNumber(const base::string16& number) {
720 number_ = number; 770 number_ = number;
721 771
722 // Set the type based on the card number, but only for full numbers, not 772 // Set the type based on the card number, but only for full numbers, not
723 // when we have masked cards from the server (last 4 digits). 773 // when we have masked cards from the server (last 4 digits).
724 if (record_type_ != MASKED_SERVER_CARD) 774 if (record_type_ != MASKED_SERVER_CARD)
725 type_ = GetCreditCardType(StripSeparators(number_)); 775 type_ = GetCreditCardType(StripSeparators(number_));
726 } 776 }
727 777
728 void CreditCard::RecordAndLogUse() { 778 void CreditCard::RecordAndLogUse() {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
761 if (compare.StringsEqual(icu_month, month)) { 811 if (compare.StringsEqual(icu_month, month)) {
762 *num = i + 1; // Adjust from 0-indexed to 1-indexed. 812 *num = i + 1; // Adjust from 0-indexed to 1-indexed.
763 return true; 813 return true;
764 } 814 }
765 } 815 }
766 816
767 months = date_format_symbols.getShortMonths(num_months); 817 months = date_format_symbols.getShortMonths(num_months);
768 // Some abbreviations have . at the end (e.g., "janv." in French). We don't 818 // Some abbreviations have . at the end (e.g., "janv." in French). We don't
769 // care about matching that. 819 // care about matching that.
770 base::string16 trimmed_month; 820 base::string16 trimmed_month;
771 base::TrimString(month, base::ASCIIToUTF16("."), &trimmed_month); 821 base::TrimString(month, ASCIIToUTF16("."), &trimmed_month);
772 for (int32_t i = 0; i < num_months; ++i) { 822 for (int32_t i = 0; i < num_months; ++i) {
773 base::string16 icu_month(months[i].getBuffer(), months[i].length()); 823 base::string16 icu_month(months[i].getBuffer(), months[i].length());
774 base::TrimString(icu_month, base::ASCIIToUTF16("."), &icu_month); 824 base::TrimString(icu_month, ASCIIToUTF16("."), &icu_month);
775 if (compare.StringsEqual(icu_month, trimmed_month)) { 825 if (compare.StringsEqual(icu_month, trimmed_month)) {
776 *num = i + 1; // Adjust from 0-indexed to 1-indexed. 826 *num = i + 1; // Adjust from 0-indexed to 1-indexed.
777 return true; 827 return true;
778 } 828 }
779 } 829 }
780 830
781 return false; 831 return false;
782 } 832 }
783 833
784 bool CreditCard::IsExpired(const base::Time& current_time) const { 834 bool CreditCard::IsExpired(const base::Time& current_time) const {
(...skipping 28 matching lines...) Expand all
813 const char kAmericanExpressCard[] = "americanExpressCC"; 863 const char kAmericanExpressCard[] = "americanExpressCC";
814 const char kDinersCard[] = "dinersCC"; 864 const char kDinersCard[] = "dinersCC";
815 const char kDiscoverCard[] = "discoverCC"; 865 const char kDiscoverCard[] = "discoverCC";
816 const char kGenericCard[] = "genericCC"; 866 const char kGenericCard[] = "genericCC";
817 const char kJCBCard[] = "jcbCC"; 867 const char kJCBCard[] = "jcbCC";
818 const char kMasterCard[] = "masterCardCC"; 868 const char kMasterCard[] = "masterCardCC";
819 const char kUnionPay[] = "unionPayCC"; 869 const char kUnionPay[] = "unionPayCC";
820 const char kVisaCard[] = "visaCC"; 870 const char kVisaCard[] = "visaCC";
821 871
822 } // namespace autofill 872 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698