| Index: components/autofill/core/browser/credit_card_field.cc
|
| diff --git a/components/autofill/core/browser/credit_card_field.cc b/components/autofill/core/browser/credit_card_field.cc
|
| index ba9c001022dc69ced0d5207c70f5d64b26d4550b..50662b56e18aef1ffeb7c44d0d69c4a1d4bffef1 100644
|
| --- a/components/autofill/core/browser/credit_card_field.cc
|
| +++ b/components/autofill/core/browser/credit_card_field.cc
|
| @@ -22,6 +22,14 @@ namespace autofill {
|
| static const size_t kMaxValidCardNumberSize = 19;
|
|
|
| // static
|
| +const int CreditCardField::kMatchNumAndTel =
|
| + MATCH_DEFAULT | MATCH_NUMBER | MATCH_TELEPHONE;
|
| +
|
| +// static
|
| +const int CreditCardField::kMatchNumTelAndPass =
|
| + kMatchNumAndTel | MATCH_PASSWORD;
|
| +
|
| +// static
|
| scoped_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner) {
|
| if (scanner->IsEnd())
|
| return nullptr;
|
| @@ -31,13 +39,15 @@ 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))
|
| break;
|
|
|
| - if (!credit_card_field->cardholder_) {
|
| + if (!credit_card_field->cardholder_ &&
|
| + !LikelyCardNumberField(scanner) &&
|
| + !MayBeCardCVCField(scanner)) {
|
| if (ParseField(scanner,
|
| base::UTF8ToUTF16(kNameOnCardRe),
|
| &credit_card_field->cardholder_)) {
|
| @@ -60,11 +70,9 @@ 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_)) {
|
| + if (!credit_card_field->type_ && LikelyCardType(scanner)) {
|
| + credit_card_field->type_ = scanner->Cursor();
|
| + scanner->Advance();
|
| continue;
|
| }
|
|
|
| @@ -74,11 +82,11 @@ scoped_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner) {
|
| // identification number", and others listed in the regex pattern used
|
| // below.
|
| // Note: Some sites use type="tel" or type="number" for numerical inputs.
|
| - const int kMatchNumAndTel = MATCH_DEFAULT | MATCH_NUMBER | MATCH_TELEPHONE;
|
| if (!credit_card_field->verification_ &&
|
| + !LikelyCardNumberField(scanner) &&
|
| ParseFieldSpecifics(scanner,
|
| base::UTF8ToUTF16(kCardCvcRe),
|
| - kMatchNumAndTel | MATCH_PASSWORD,
|
| + kMatchNumTelAndPass,
|
| &credit_card_field->verification_)) {
|
| continue;
|
| }
|
| @@ -121,14 +129,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;
|
| }
|
|
|
| @@ -157,6 +157,53 @@ scoped_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner) {
|
| return nullptr;
|
| }
|
|
|
| +// static
|
| +bool CreditCardField::LikelyCardNumberField(AutofillScanner* scanner) {
|
| + if (scanner->IsEnd())
|
| + return false;
|
| +
|
| + // Look for a form of the right type with a 16 to 19 digit maxlength.
|
| + AutofillField* field = scanner->Cursor();
|
| + return (MatchesFormControlType(field->form_control_type, kMatchNumAndTel) &&
|
| + field->max_length >= 16 &&
|
| + field->max_length <= kMaxValidCardNumberSize);
|
| +}
|
| +
|
| +// static
|
| +bool CreditCardField::LikelyCardType(AutofillScanner* scanner) {
|
| + if (scanner->IsEnd())
|
| + return false;
|
| +
|
| + AutofillField* field = scanner->Cursor();
|
| + if (MatchesFormControlType(field->form_control_type, MATCH_SELECT)) {
|
| + // VISA and Mastercard are oftentimes branded as is in other countries, so
|
| + // translations are probably not needed.
|
| + const char* const kCardBrands[] = {
|
| + "visa",
|
| + "mastercard",
|
| + };
|
| + for (const char* brand : kCardBrands) {
|
| + if (AutofillField::FindValueInCreditTypeSelectControl(
|
| + *field, base::ASCIIToUTF16(brand), nullptr)) {
|
| + return true;
|
| + }
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +// static
|
| +bool CreditCardField::MayBeCardCVCField(AutofillScanner* scanner) {
|
| + if (scanner->IsEnd())
|
| + return false;
|
| +
|
| + // Look for a form of the right type with a 3 or 4 digit maxlength.
|
| + AutofillField* field = scanner->Cursor();
|
| + return (MatchesFormControlType(field->form_control_type,
|
| + kMatchNumTelAndPass) &&
|
| + (field->max_length == 3 || field->max_length == 4));
|
| +}
|
| +
|
| CreditCardField::CreditCardField()
|
| : cardholder_(nullptr),
|
| cardholder_last_(nullptr),
|
|
|