Commit e2f6955f authored by thestig's avatar thestig Committed by Commit bot

Autofill: Better recognize credit card type fields.

BUG=464002, 466685, 469012

Review URL: https://codereview.chromium.org/1030073003

Cr-Commit-Position: refs/heads/master@{#322325}
parent e823d885
This diff is collapsed.
This diff is collapsed.
......@@ -18,7 +18,7 @@ UNKNOWN_TYPE | identificationValue | CPF/CNPJ | | salutation_1-default
CREDIT_CARD_EXP_MONTH | accountExpiryMonth | Expiration Date | - | salutation_1-cc
CREDIT_CARD_EXP_4_DIGIT_YEAR | accountExpiryYear | Expiration Date | - | salutation_1-cc
CREDIT_CARD_VERIFICATION_CODE | accountVerification | Verification Number * | | salutation_1-cc
CREDIT_CARD_TYPE | accountBrandDropDown | Card Brand | | salutation_1-cc
UNKNOWN_TYPE | accountBrandDropDown | Card Brand | | salutation_1-default
CREDIT_CARD_NUMBER | cardNumber | Card Number | | salutation_1-cc
CREDIT_CARD_NAME | ccHolder | Card holder | | salutation_1-cc
CREDIT_CARD_EXP_MONTH | accountExpiryMonth | Expiration Date | - | salutation_1-cc
......
CREDIT_CARD_NAME | paymentMethodForm.newCreditCardCustomerName | Name on card* | | paymentMethodForm.newCreditCardCustomerName_1-cc
CREDIT_CARD_NUMBER | paymentMethodForm.cardNumber | Card number* | | paymentMethodForm.newCreditCardCustomerName_1-cc
CREDIT_CARD_VERIFICATION_CODE | paymentMethodForm.cardVerificationNumber | Security code* | | paymentMethodForm.newCreditCardCustomerName_1-cc
CREDIT_CARD_EXP_MONTH | paymentMethodForm.expirationMonth | 04 | | paymentMethodForm.newCreditCardCustomerName_1-cc
CREDIT_CARD_EXP_4_DIGIT_YEAR | paymentMethodForm.expirationYear | 2018 | | paymentMethodForm.newCreditCardCustomerName_1-cc
ADDRESS_HOME_ZIP | paymentMethodForm.zip | Card billing ZIP Code* | | paymentMethodForm.newCreditCardCustomerName_1-default
UNKNOWN_TYPE | paymentMethodForm.custCode | Customer code | | paymentMethodForm.newCreditCardCustomerName_1-default
CREDIT_CARD_TYPE | cardissuer | Card Issuer | | cardissuer_1-cc
CREDIT_CARD_NUMBER | cardnumber | Your cardnumber | | cardissuer_1-cc
CREDIT_CARD_EXP_MONTH | expire_month | Expiration Date | | cardissuer_1-cc
CREDIT_CARD_EXP_4_DIGIT_YEAR | expire_year | | | cardissuer_1-cc
NAME_FIRST | firstname | First Name * | | cardissuer_1-default
NAME_LAST | lastname | Last Name * | | cardissuer_1-default
ADDRESS_HOME_LINE1 | address1 | Address * | | cardissuer_1-default
ADDRESS_HOME_LINE2 | unit | Unit # | | cardissuer_1-default
ADDRESS_HOME_LINE3 | address2 | Address Line 2 | | cardissuer_1-default
ADDRESS_HOME_CITY | city | City * | | cardissuer_1-default
ADDRESS_HOME_STATE | state | State * | | cardissuer_1-default
ADDRESS_HOME_ZIP | zip | State * | | cardissuer_1-default
ADDRESS_HOME_COUNTRY | country | Country * | us | cardissuer_1-default
UNKNOWN_TYPE | phonenumber | Mobile Phone* | | cardissuer_1-default
......@@ -248,26 +248,10 @@ bool FillYearSelectControl(const base::string16& value,
// given |field|.
bool FillCreditCardTypeSelectControl(const base::string16& value,
FormFieldData* field) {
// Try stripping off spaces.
base::string16 value_stripped;
base::RemoveChars(base::StringToLowerASCII(value), base::kWhitespaceUTF16,
&value_stripped);
for (size_t i = 0; i < field->option_values.size(); ++i) {
base::string16 option_value_lowercase;
base::RemoveChars(base::StringToLowerASCII(field->option_values[i]),
base::kWhitespaceUTF16, &option_value_lowercase);
base::string16 option_contents_lowercase;
base::RemoveChars(base::StringToLowerASCII(field->option_contents[i]),
base::kWhitespaceUTF16, &option_contents_lowercase);
// Perform a case-insensitive comparison; but fill the form with the
// original text, not the lowercased version.
if (value_stripped == option_value_lowercase ||
value_stripped == option_contents_lowercase) {
field->value = field->option_values[i];
return true;
}
size_t idx;
if (AutofillField::FindValueInSelectControl(*field, value, &idx)) {
field->value = field->option_values[idx];
return true;
}
// For American Express, also try filling as "AmEx".
......@@ -541,4 +525,32 @@ base::string16 AutofillField::GetPhoneNumberValue(
return number;
}
// static
bool AutofillField::FindValueInSelectControl(const FormFieldData& field,
const base::string16& value,
size_t* index) {
// TODO(thestig): Improve this. See http://crbug.com/470726)
// Try stripping off spaces.
base::string16 value_stripped;
base::RemoveChars(base::StringToLowerASCII(value), base::kWhitespaceUTF16,
&value_stripped);
for (size_t i = 0; i < field.option_values.size(); ++i) {
base::string16 option_value_lowercase;
base::RemoveChars(base::StringToLowerASCII(field.option_values[i]),
base::kWhitespaceUTF16, &option_value_lowercase);
base::string16 option_contents_lowercase;
base::RemoveChars(base::StringToLowerASCII(field.option_contents[i]),
base::kWhitespaceUTF16, &option_contents_lowercase);
// Perform a case-insensitive comparison.
if (value_stripped == option_value_lowercase ||
value_stripped == option_contents_lowercase) {
if (index)
*index = i;
return true;
}
}
return false;
}
} // namespace autofill
......@@ -89,6 +89,13 @@ class AutofillField : public FormFieldData {
const base::string16& number,
const FormFieldData& field_data);
// Returns true if the select |field| contains an option that matches |value|.
// If the return value is true and |index| is non-NULL, write the index of the
// matching option into |index|.
static bool FindValueInSelectControl(const FormFieldData& field,
const base::string16& value,
size_t* index);
private:
// The unique name of this field, generated by Autofill.
base::string16 unique_name_;
......
......@@ -149,8 +149,6 @@ const char kCardCvcRe[] =
"verification|card identification|security code|card code"
"|cvn|cvv|cvc|csc|cvd|cid|ccv"
"|\\bcid\\b";
const char kCardTypeRe[] =
"(card|cc|payment).?type|payment.?method|card.*brand";
// "Expiration date" is the most common label here, but some pages have
// "Expires", "exp. date" or "exp. month" and "exp. year". We also look
......@@ -197,8 +195,6 @@ const char kExpirationDateRe[] =
"|有効期限" // ja-JP
"|validade" // pt-BR, pt-PT
"|Срок действия карты"; // ru
const char kCardIgnoredRe[] =
"^card";
const char kGiftCardRe[] =
"gift.?card";
......
......@@ -18,6 +18,8 @@
#include "components/autofill/core/browser/autofill_regexes.h"
#include "components/autofill/core/browser/autofill_scanner.h"
#include "components/autofill/core/browser/field_types.h"
#include "grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"
namespace autofill {
......@@ -60,7 +62,7 @@ scoped_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner) {
// Credit card fields can appear in many different orders.
// We loop until no more credit card related fields are found, see |break| at
// bottom of the loop.
// the bottom of the loop.
for (int fields = 0; !scanner->IsEnd(); ++fields) {
// Ignore gift card fields.
if (ParseField(scanner, base::UTF8ToUTF16(kGiftCardRe), nullptr))
......@@ -89,11 +91,10 @@ scoped_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner) {
}
// Check for a credit card type (Visa, MasterCard, etc.) field.
if (!credit_card_field->type_ &&
ParseFieldSpecifics(scanner,
base::UTF8ToUTF16(kCardTypeRe),
MATCH_DEFAULT | MATCH_SELECT,
&credit_card_field->type_)) {
// All CC type fields encountered so far have been of type select.
if (!credit_card_field->type_ && LikelyCardTypeSelectField(scanner)) {
credit_card_field->type_ = scanner->Cursor();
scanner->Advance();
continue;
}
......@@ -150,14 +151,6 @@ scoped_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner) {
return nullptr;
}
// Some pages (e.g. ExpediaBilling.html) have a "card description"
// field; we parse this field but ignore it.
// We also ignore any other fields within a credit card block that
// start with "card", under the assumption that they are related to
// the credit card section being processed but are uninteresting to us.
if (ParseField(scanner, base::UTF8ToUTF16(kCardIgnoredRe), nullptr))
continue;
break;
}
......@@ -247,6 +240,23 @@ bool CreditCardField::LikelyCardYearSelectField(AutofillScanner* scanner) {
FindConsecutiveStrings(years_to_check, field->option_contents));
}
// static
bool CreditCardField::LikelyCardTypeSelectField(AutofillScanner* scanner) {
if (scanner->IsEnd())
return false;
AutofillField* field = scanner->Cursor();
if (!MatchesFormControlType(field->form_control_type, MATCH_SELECT))
return false;
return AutofillField::FindValueInSelectControl(
*field, l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_VISA),
nullptr) ||
AutofillField::FindValueInSelectControl(
*field, l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_MASTERCARD),
nullptr);
}
CreditCardField::CreditCardField()
: cardholder_(nullptr),
cardholder_last_(nullptr),
......
......@@ -40,6 +40,10 @@ class CreditCardField : public FormField {
// the next few years.
static bool LikelyCardYearSelectField(AutofillScanner* scanner);
// Returns true if |scanner| points to a <select> field that contains credit
// card type options.
static bool LikelyCardTypeSelectField(AutofillScanner* scanner);
CreditCardField();
// Parses the expiration month/year/date fields. Returns true if it finds
......
......@@ -117,10 +117,6 @@ TEST_F(CreditCardFieldTest, ParseFullCreditCard) {
FormFieldData field;
field.form_control_type = "text";
field.label = ASCIIToUTF16("Card Type");
field.name = ASCIIToUTF16("card_type");
list_.push_back(new AutofillField(field, ASCIIToUTF16("type")));
field.label = ASCIIToUTF16("Name on Card");
field.name = ASCIIToUTF16("name_on_card");
list_.push_back(new AutofillField(field, ASCIIToUTF16("name")));
......@@ -141,6 +137,13 @@ TEST_F(CreditCardFieldTest, ParseFullCreditCard) {
field.name = ASCIIToUTF16("verification");
list_.push_back(new AutofillField(field, ASCIIToUTF16("cvc")));
field.form_control_type = "select-one";
field.label = ASCIIToUTF16("Card Type");
field.name = ASCIIToUTF16("card_type");
field.option_contents.push_back(ASCIIToUTF16("visa"));
field.option_values.push_back(ASCIIToUTF16("visa"));
list_.push_back(new AutofillField(field, ASCIIToUTF16("type")));
Parse();
ASSERT_NE(nullptr, field_.get());
EXPECT_TRUE(ClassifyField());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment