diff options
author | pritam.nikam <pritam.nikam@samsung.com> | 2014-08-25 12:15:00 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-08-25 19:16:56 +0000 |
commit | 401f3492b9eaac6a3d964b7d5147f1e532fa95dc (patch) | |
tree | 264f9d23452e71955aea57bdcf12b2db58ab7d31 | |
parent | 9b2d620f013ea943478c1bdca1f570df5ccab8ca (diff) | |
download | chromium_src-401f3492b9eaac6a3d964b7d5147f1e532fa95dc.zip chromium_src-401f3492b9eaac6a3d964b7d5147f1e532fa95dc.tar.gz chromium_src-401f3492b9eaac6a3d964b7d5147f1e532fa95dc.tar.bz2 |
[Autofill] Autofill incorrectly fills credit card expiration year in 2-digit fields.
With current implementation the on parsing the credit card field heuristics
matches to the autofill::kExpirationYearRe and apparently it's assumes that a
4-digit credit card field (i.e. ServerFieldType CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR).
This patch considers *maxlength* attribute in addition to see whether the feild
is 2-digit input field or not.
BUG=406247
Review URL: https://codereview.chromium.org/493393003
Cr-Commit-Position: refs/heads/master@{#291734}
3 files changed, 81 insertions, 38 deletions
diff --git a/components/autofill/core/browser/credit_card_field.cc b/components/autofill/core/browser/credit_card_field.cc index 09dab1e..73dc90d 100644 --- a/components/autofill/core/browser/credit_card_field.cc +++ b/components/autofill/core/browser/credit_card_field.cc @@ -60,7 +60,8 @@ FormField* CreditCardField::Parse(AutofillScanner* scanner) { scanner->SaveCursor(); const AutofillField* first; if (ParseField(scanner, base::ASCIIToUTF16("^cfnm"), &first) && - ParseField(scanner, base::ASCIIToUTF16("^clnm"), + ParseField(scanner, + base::ASCIIToUTF16("^clnm"), &credit_card_field->cardholder_last_)) { credit_card_field->cardholder_ = first; continue; @@ -71,7 +72,8 @@ FormField* CreditCardField::Parse(AutofillScanner* scanner) { // Check for a credit card type (Visa, MasterCard, etc.) field. base::string16 type_pattern = base::UTF8ToUTF16(autofill::kCardTypeRe); if (!credit_card_field->type_ && - ParseFieldSpecifics(scanner, type_pattern, + ParseFieldSpecifics(scanner, + type_pattern, MATCH_DEFAULT | MATCH_SELECT, &credit_card_field->type_)) { continue; @@ -102,11 +104,15 @@ FormField* CreditCardField::Parse(AutofillScanner* scanner) { scanner->SaveCursor(); pattern = base::UTF8ToUTF16(autofill::kExpirationMonthRe); if (!credit_card_field->expiration_month_ && - ParseFieldSpecifics(scanner, pattern, MATCH_DEFAULT | MATCH_SELECT, + ParseFieldSpecifics(scanner, + pattern, + MATCH_DEFAULT | MATCH_SELECT, &credit_card_field->expiration_month_)) { pattern = base::UTF8ToUTF16(autofill::kExpirationYearRe); - if (ParseFieldSpecifics(scanner, pattern, MATCH_DEFAULT | MATCH_SELECT, - &credit_card_field->expiration_year_)) { + if (ParseFieldSpecifics(scanner, + pattern, + MATCH_DEFAULT | MATCH_SELECT, + &credit_card_field->expiration_year_)) { continue; } } @@ -117,19 +123,21 @@ FormField* CreditCardField::Parse(AutofillScanner* scanner) { scanner->Rewind(); pattern = base::UTF8ToUTF16(autofill::kExpirationDate2DigitYearRe); // We allow <select> fields, because they're used e.g. on qvc.com. - if (ParseFieldSpecifics(scanner, pattern, - MATCH_LABEL | MATCH_VALUE | MATCH_TEXT | - MATCH_SELECT, - &credit_card_field->expiration_date_)) { - credit_card_field->is_two_digit_year_ = true; + if (ParseFieldSpecifics( + scanner, + pattern, + MATCH_LABEL | MATCH_VALUE | MATCH_TEXT | MATCH_SELECT, + &credit_card_field->expiration_date_)) { + credit_card_field->exp_year_type_ = CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR; continue; } pattern = base::UTF8ToUTF16(autofill::kExpirationDateRe); - if (ParseFieldSpecifics(scanner, pattern, - MATCH_LABEL | MATCH_VALUE | MATCH_TEXT | - MATCH_SELECT, - &credit_card_field->expiration_date_)) { + if (ParseFieldSpecifics( + scanner, + pattern, + MATCH_LABEL | MATCH_VALUE | MATCH_TEXT | MATCH_SELECT, + &credit_card_field->expiration_date_)) { continue; } } @@ -187,14 +195,14 @@ CreditCardField::CreditCardField() expiration_month_(NULL), expiration_year_(NULL), expiration_date_(NULL), - is_two_digit_year_(false) { + exp_year_type_(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR) { } bool CreditCardField::ClassifyField(ServerFieldTypeMap* map) const { bool ok = AddClassification(number_, CREDIT_CARD_NUMBER, map); ok = ok && AddClassification(type_, CREDIT_CARD_TYPE, map); - ok = ok && AddClassification(verification_, CREDIT_CARD_VERIFICATION_CODE, - map); + ok = ok && + AddClassification(verification_, CREDIT_CARD_VERIFICATION_CODE, map); // If the heuristics detected first and last name in separate fields, // then ignore both fields. Putting them into separate fields is probably @@ -204,27 +212,23 @@ bool CreditCardField::ClassifyField(ServerFieldTypeMap* map) const { ok = ok && AddClassification(cardholder_, CREDIT_CARD_NAME, map); if (expiration_date_) { - if (is_two_digit_year_) { - ok = ok && AddClassification(expiration_date_, - CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, map); - } else { - ok = ok && AddClassification(expiration_date_, - CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, map); - } + ok = + ok && AddClassification(expiration_date_, GetExpirationYearType(), map); } else { ok = ok && AddClassification(expiration_month_, CREDIT_CARD_EXP_MONTH, map); - if (is_two_digit_year_) { - ok = ok && AddClassification(expiration_year_, - CREDIT_CARD_EXP_2_DIGIT_YEAR, - map); - } else { - ok = ok && AddClassification(expiration_year_, - CREDIT_CARD_EXP_4_DIGIT_YEAR, - map); - } + ok = + ok && AddClassification(expiration_year_, GetExpirationYearType(), map); } return ok; } +ServerFieldType CreditCardField::GetExpirationYearType() const { + return (expiration_date_ + ? exp_year_type_ + : ((expiration_year_ && expiration_year_->max_length == 2) + ? CREDIT_CARD_EXP_2_DIGIT_YEAR + : CREDIT_CARD_EXP_4_DIGIT_YEAR)); +} + } // namespace autofill diff --git a/components/autofill/core/browser/credit_card_field.h b/components/autofill/core/browser/credit_card_field.h index bf45e7e..64fa4ed 100644 --- a/components/autofill/core/browser/credit_card_field.h +++ b/components/autofill/core/browser/credit_card_field.h @@ -31,12 +31,17 @@ class CreditCardField : public FormField { CreditCardField(); + // For the combined expiration field we return |exp_year_type_|; otherwise if + // |expiration_year_| is having year with |max_length| of 2-digits we return + // |CREDIT_CARD_EXP_2_DIGIT_YEAR|; otherwise |CREDIT_CARD_EXP_4_DIGIT_YEAR|. + ServerFieldType GetExpirationYearType() const; + const AutofillField* cardholder_; // Optional. // Occasionally pages have separate fields for the cardholder's first and - // last names; for such pages cardholder_ holds the first name field and + // last names; for such pages |cardholder_| holds the first name field and // we store the last name field here. - // (We could store an embedded NameField object here, but we don't do so + // (We could store an embedded |NameField| object here, but we don't do so // because the text patterns for matching a cardholder name are different // than for ordinary names, and because cardholder names never have titles, // middle names or suffixes.) @@ -55,9 +60,10 @@ class CreditCardField : public FormField { const AutofillField* expiration_year_; const AutofillField* expiration_date_; - // True if the year is detected to be a 2-digit year; otherwise, we assume - // a 4-digit year. - bool is_two_digit_year_; + // For combined expiration field having year as 2-digits we store here + // |CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR|; otherwise we store + // |CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR|. + ServerFieldType exp_year_type_; DISALLOW_COPY_AND_ASSIGN(CreditCardField); }; diff --git a/components/autofill/core/browser/credit_card_field_unittest.cc b/components/autofill/core/browser/credit_card_field_unittest.cc index 037a302..39e222f 100644 --- a/components/autofill/core/browser/credit_card_field_unittest.cc +++ b/components/autofill/core/browser/credit_card_field_unittest.cc @@ -347,4 +347,37 @@ TEST_F(CreditCardFieldTest, ParseMonthControl) { field_type_map_[ASCIIToUTF16("date2")]); } +// Verify that heuristics <input name="ccyear" maxlength="2"/> considers +// *maxlength* attribute while parsing 2 Digit expiration year. +TEST_F(CreditCardFieldTest, ParseCreditCardExpYear_2DigitMaxLength) { + FormFieldData field; + field.form_control_type = "text"; + + field.label = ASCIIToUTF16("Card Number"); + field.name = ASCIIToUTF16("card_number"); + list_.push_back(new AutofillField(field, ASCIIToUTF16("number"))); + + field.label = ASCIIToUTF16("Expiration Date"); + field.name = ASCIIToUTF16("ccmonth"); + list_.push_back(new AutofillField(field, ASCIIToUTF16("month"))); + + field.name = ASCIIToUTF16("ccyear"); + field.max_length = 2; + list_.push_back(new AutofillField(field, ASCIIToUTF16("year"))); + + Parse(); + ASSERT_NE(static_cast<CreditCardField*>(NULL), field_.get()); + EXPECT_TRUE(ClassifyField()); + ASSERT_TRUE(field_type_map_.find(ASCIIToUTF16("number")) != + field_type_map_.end()); + EXPECT_EQ(CREDIT_CARD_NUMBER, field_type_map_[ASCIIToUTF16("number")]); + ASSERT_TRUE(field_type_map_.find(ASCIIToUTF16("month")) != + field_type_map_.end()); + EXPECT_EQ(CREDIT_CARD_EXP_MONTH, field_type_map_[ASCIIToUTF16("month")]); + ASSERT_TRUE(field_type_map_.find(ASCIIToUTF16("year")) != + field_type_map_.end()); + EXPECT_EQ(CREDIT_CARD_EXP_2_DIGIT_YEAR, + field_type_map_[ASCIIToUTF16("year")]); +} + } // namespace autofill |