| Index: components/autofill/core/browser/credit_card.cc
|
| diff --git a/components/autofill/core/browser/credit_card.cc b/components/autofill/core/browser/credit_card.cc
|
| index 77800cac4a0d312f5945dc8b0550968090e8a3d1..a37f16fba01030b2145d4c0ccf8bf1505cfd4660 100644
|
| --- a/components/autofill/core/browser/credit_card.cc
|
| +++ b/components/autofill/core/browser/credit_card.cc
|
| @@ -35,6 +35,8 @@
|
| #include "third_party/icu/source/i18n/unicode/dtfmtsym.h"
|
| #include "ui/base/l10n/l10n_util.h"
|
|
|
| +using base::ASCIIToUTF16;
|
| +
|
| namespace autofill {
|
|
|
| const base::char16 kMidlineEllipsis[] = { 0x22ef, 0 };
|
| @@ -118,7 +120,7 @@ CreditCard::~CreditCard() {}
|
| // static
|
| const base::string16 CreditCard::StripSeparators(const base::string16& number) {
|
| base::string16 stripped;
|
| - base::RemoveChars(number, base::ASCIIToUTF16("- "), &stripped);
|
| + base::RemoveChars(number, ASCIIToUTF16("- "), &stripped);
|
| return stripped;
|
| }
|
|
|
| @@ -290,7 +292,7 @@ base::string16 CreditCard::GetRawInfo(ServerFieldType type) const {
|
| base::string16 month = ExpirationMonthAsString();
|
| base::string16 year = Expiration2DigitYearAsString();
|
| if (!month.empty() && !year.empty())
|
| - return month + base::ASCIIToUTF16("/") + year;
|
| + return month + ASCIIToUTF16("/") + year;
|
| return base::string16();
|
| }
|
|
|
| @@ -298,7 +300,7 @@ base::string16 CreditCard::GetRawInfo(ServerFieldType type) const {
|
| base::string16 month = ExpirationMonthAsString();
|
| base::string16 year = Expiration4DigitYearAsString();
|
| if (!month.empty() && !year.empty())
|
| - return month + base::ASCIIToUTF16("/") + year;
|
| + return month + ASCIIToUTF16("/") + year;
|
| return base::string16();
|
| }
|
|
|
| @@ -331,7 +333,7 @@ void CreditCard::SetRawInfo(ServerFieldType type,
|
| break;
|
|
|
| case CREDIT_CARD_EXP_2_DIGIT_YEAR:
|
| - // This is a read-only attribute.
|
| + SetExpirationYearFromString(value);
|
| break;
|
|
|
| case CREDIT_CARD_EXP_4_DIGIT_YEAR:
|
| @@ -339,11 +341,11 @@ void CreditCard::SetRawInfo(ServerFieldType type,
|
| break;
|
|
|
| case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR:
|
| - // This is a read-only attribute.
|
| + SetExpirationDateFromString(value);
|
| break;
|
|
|
| case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR:
|
| - // This is a read-only attribute.
|
| + SetExpirationDateFromString(value);
|
| break;
|
|
|
| case CREDIT_CARD_TYPE:
|
| @@ -431,7 +433,7 @@ const std::pair<base::string16, base::string16> CreditCard::LabelPieces()
|
| return std::make_pair(obfuscated_cc_number, base::string16());
|
|
|
| base::string16 formatted_date(ExpirationMonthAsString());
|
| - formatted_date.append(base::ASCIIToUTF16("/"));
|
| + formatted_date.append(ASCIIToUTF16("/"));
|
| formatted_date.append(Expiration4DigitYearAsString());
|
|
|
| base::string16 separator =
|
| @@ -445,8 +447,7 @@ void CreditCard::SetInfoForMonthInputType(const base::string16& value) {
|
| return;
|
|
|
| std::vector<base::StringPiece16> year_month = base::SplitStringPiece(
|
| - value, base::ASCIIToUTF16("-"),
|
| - base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
|
| + value, ASCIIToUTF16("-"), base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
|
| DCHECK_EQ(2u, year_month.size());
|
| int num = 0;
|
| bool converted = false;
|
| @@ -465,9 +466,20 @@ void CreditCard::SetExpirationMonth(int expiration_month) {
|
| }
|
|
|
| void CreditCard::SetExpirationYear(int expiration_year) {
|
| - if (expiration_year != 0 &&
|
| - (expiration_year < 2006 || expiration_year > 10000))
|
| + // If |expiration_year| is beyond this millenium, or more than 2 digits but
|
| + // before the current millenium (e.g. "545", "1995"), return. What is left are
|
| + // values like "45" or "2018".
|
| + if (expiration_year > 2999 ||
|
| + (expiration_year > 99 && expiration_year < 2000))
|
| return;
|
| +
|
| + // Will normalize 2-digit years to the 4-digit version.
|
| + if (expiration_year > 0 && expiration_year < 100) {
|
| + base::Time::Exploded now_exploded;
|
| + base::Time::Now().LocalExplode(&now_exploded);
|
| + expiration_year += (now_exploded.year / 100) * 100;
|
| + }
|
| +
|
| expiration_year_ = expiration_year;
|
| }
|
|
|
| @@ -677,7 +689,7 @@ base::string16 CreditCard::ExpirationMonthAsString() const {
|
| if (expiration_month_ >= 10)
|
| return month;
|
|
|
| - base::string16 zero = base::ASCIIToUTF16("0");
|
| + base::string16 zero = ASCIIToUTF16("0");
|
| zero.append(month);
|
| return zero;
|
| }
|
| @@ -721,6 +733,52 @@ void CreditCard::SetExpirationYearFromString(const base::string16& text) {
|
| SetExpirationYear(year);
|
| }
|
|
|
| +void CreditCard::SetExpirationDateFromString(const base::string16& text) {
|
| + // Check that |text| fits the supported patterns: mmyy, mmyyyy, m-yy,
|
| + // mm-yy, m-yyyy and mm-yyyy. Note that myy and myyyy matched by this pattern
|
| + // but are not supported (ambiguous). Separators: -, / and |.
|
| + if (!MatchesPattern(text, base::UTF8ToUTF16("^[0-9]{1,2}[-/|]?[0-9]{2,4}$")))
|
| + return;
|
| +
|
| + base::string16 month;
|
| + base::string16 year;
|
| +
|
| + // Check for a separator.
|
| + base::string16 found_separator;
|
| + const std::vector<base::string16> kSeparators{
|
| + ASCIIToUTF16("-"), ASCIIToUTF16("/"), ASCIIToUTF16("|")};
|
| + for (const base::string16& separator : kSeparators) {
|
| + if (text.find(separator) != base::string16::npos) {
|
| + found_separator = separator;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + if (!found_separator.empty()) {
|
| + std::vector<base::string16> month_year = base::SplitString(
|
| + text, found_separator, base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
|
| + DCHECK_EQ(2u, month_year.size());
|
| + month = month_year[0];
|
| + year = month_year[1];
|
| + } else if (text.size() % 2 == 0) {
|
| + // If there are no separators, the supported formats are mmyy and mmyyyy.
|
| + month = text.substr(0, 2);
|
| + year = text.substr(2);
|
| + } else {
|
| + // Odd number of digits with no separator is too ambiguous.
|
| + return;
|
| + }
|
| +
|
| + int num = 0;
|
| + bool converted = false;
|
| + converted = base::StringToInt(month, &num);
|
| + DCHECK(converted);
|
| + SetExpirationMonth(num);
|
| + converted = base::StringToInt(year, &num);
|
| + DCHECK(converted);
|
| + SetExpirationYear(num);
|
| +}
|
| +
|
| void CreditCard::SetNumber(const base::string16& number) {
|
| number_ = number;
|
|
|
| @@ -773,10 +831,10 @@ bool CreditCard::ConvertMonth(const base::string16& month,
|
| // Some abbreviations have . at the end (e.g., "janv." in French). We don't
|
| // care about matching that.
|
| base::string16 trimmed_month;
|
| - base::TrimString(month, base::ASCIIToUTF16("."), &trimmed_month);
|
| + base::TrimString(month, ASCIIToUTF16("."), &trimmed_month);
|
| for (int32_t i = 0; i < num_months; ++i) {
|
| base::string16 icu_month(months[i].getBuffer(), months[i].length());
|
| - base::TrimString(icu_month, base::ASCIIToUTF16("."), &icu_month);
|
| + base::TrimString(icu_month, ASCIIToUTF16("."), &icu_month);
|
| if (compare.StringsEqual(icu_month, trimmed_month)) {
|
| *num = i + 1; // Adjust from 0-indexed to 1-indexed.
|
| return true;
|
|
|