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 73dc90db9fc32658b470ec80b5d732fc5865e73d..f82dc063293ba3741b28ca440c6c907e4be366ad 100644 |
--- a/components/autofill/core/browser/credit_card_field.cc |
+++ b/components/autofill/core/browser/credit_card_field.cc |
@@ -19,6 +19,10 @@ |
namespace autofill { |
+// Credit card numbers are at most 19 digits in length. |
+// [Ref: http://en.wikipedia.org/wiki/Bank_card_number] |
+static const size_t kMaxValidCardNumberSize = 19; |
+ |
// static |
FormField* CreditCardField::Parse(AutofillScanner* scanner) { |
if (scanner->IsEnd()) |
@@ -26,6 +30,7 @@ FormField* CreditCardField::Parse(AutofillScanner* scanner) { |
scoped_ptr<CreditCardField> credit_card_field(new CreditCardField); |
size_t saved_cursor = scanner->SaveCursor(); |
+ bool form_has_valid_card_number_fields = true; |
// Credit card fields can appear in many different orders. |
// We loop until no more credit card related fields are found, see |break| at |
@@ -58,7 +63,7 @@ FormField* CreditCardField::Parse(AutofillScanner* scanner) { |
// for the cardholder's first and last name if they have the labels "cfnm" |
// and "clnm". |
scanner->SaveCursor(); |
- const AutofillField* first; |
+ AutofillField* first; |
if (ParseField(scanner, base::ASCIIToUTF16("^cfnm"), &first) && |
ParseField(scanner, |
base::ASCIIToUTF16("^clnm"), |
@@ -91,8 +96,32 @@ FormField* CreditCardField::Parse(AutofillScanner* scanner) { |
} |
pattern = base::UTF8ToUTF16(autofill::kCardNumberRe); |
- if (!credit_card_field->number_ && |
- ParseField(scanner, pattern, &credit_card_field->number_)) { |
+ AutofillField* current_number_field; |
+ if (ParseField(scanner, pattern, ¤t_number_field)) { |
+ // Avoid autofilling any credit card number field having very low or high |
+ // |start_index| on the HTML form. |
+ size_t start_index = 0; |
+ if (!credit_card_field->numbers_.empty()) { |
+ size_t last_number_field_size = |
+ credit_card_field->numbers_.back()->credit_card_number_offset() + |
+ credit_card_field->numbers_.back()->max_length; |
+ |
+ // In some cases, HTML form may have credit card number split across |
+ // multiple input fields and either one or cumulatively having |
+ // |max_length| more than |kMaxValidCardNumberSize|, mark these input |
+ // form fields as invalid and skip autofilling them. |
+ if (last_number_field_size == 0U || |
+ last_number_field_size >= kMaxValidCardNumberSize) { |
+ // Mark that the credit card number splits are invalid. But keep |
+ // scanning HTML form so that cursor moves beyond related fields. |
+ form_has_valid_card_number_fields = false; |
+ } |
+ |
+ start_index = last_number_field_size; |
+ } |
+ |
+ current_number_field->set_credit_card_number_offset(start_index); |
+ credit_card_field->numbers_.push_back(current_number_field); |
continue; |
} |
@@ -162,6 +191,11 @@ FormField* CreditCardField::Parse(AutofillScanner* scanner) { |
break; |
} |
+ // Cases where heuristic misinterprets input field as credit card number |
+ // field, refuse to autofill credit card number fields. |
+ if (!form_has_valid_card_number_fields) |
+ credit_card_field->numbers_.clear(); |
+ |
// Some pages have a billing address field after the cardholder name field. |
// For that case, allow only just the cardholder name field. The remaining |
// CC fields will be picked up in a following CreditCardField. |
@@ -175,7 +209,9 @@ FormField* CreditCardField::Parse(AutofillScanner* scanner) { |
// a strong enough signal that this is a credit card. It is possible that |
// the number and name were parsed in a separate part of the form. So if |
// the cvc and date were found independently they are returned. |
- if ((credit_card_field->number_ || credit_card_field->verification_) && |
+ if ((!credit_card_field->numbers_.empty() || |
+ credit_card_field->verification_ || |
+ !form_has_valid_card_number_fields) && |
(credit_card_field->expiration_date_ || |
(credit_card_field->expiration_month_ && |
credit_card_field->expiration_year_))) { |
@@ -190,7 +226,6 @@ CreditCardField::CreditCardField() |
: cardholder_(NULL), |
cardholder_last_(NULL), |
type_(NULL), |
- number_(NULL), |
verification_(NULL), |
expiration_month_(NULL), |
expiration_year_(NULL), |
@@ -198,8 +233,15 @@ CreditCardField::CreditCardField() |
exp_year_type_(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR) { |
} |
+CreditCardField::~CreditCardField() { |
+} |
+ |
bool CreditCardField::ClassifyField(ServerFieldTypeMap* map) const { |
- bool ok = AddClassification(number_, CREDIT_CARD_NUMBER, map); |
+ bool ok = true; |
+ for (size_t index = 0; index < numbers_.size(); ++index) { |
+ ok = ok && AddClassification(numbers_[index], CREDIT_CARD_NUMBER, map); |
+ } |
+ |
ok = ok && AddClassification(type_, CREDIT_CARD_TYPE, map); |
ok = ok && |
AddClassification(verification_, CREDIT_CARD_VERIFICATION_CODE, map); |