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), |