1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "components/autofill/core/browser/credit_card_field.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stddef.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "components/autofill/core/browser/autofill_field.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "components/autofill/core/browser/autofill_regex_constants.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "components/autofill/core/browser/autofill_scanner.h"
17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "components/autofill/core/browser/field_types.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace autofill {
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Credit card numbers are at most 19 digits in length.
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// [Ref: http://en.wikipedia.org/wiki/Bank_card_number]
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic const size_t kMaxValidCardNumberSize = 19;
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FormField* CreditCardField::Parse(AutofillScanner* scanner) {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (scanner->IsEnd())
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<CreditCardField> credit_card_field(new CreditCardField);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t saved_cursor = scanner->SaveCursor();
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool form_has_valid_card_number_fields = true;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Credit card fields can appear in many different orders.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We loop until no more credit card related fields are found, see |break| at
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bottom of the loop.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int fields = 0; !scanner->IsEnd(); ++fields) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Ignore gift card fields.
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (ParseField(scanner, base::UTF8ToUTF16(autofill::kGiftCardRe), NULL))
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Sometimes the cardholder field is just labeled "name". Unfortunately this
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // is a dangerously generic word to search for, since it will often match a
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // name (not cardholder name) field before or after credit card fields. So
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we search for "name" only when we've already parsed at least one other
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // credit card field and haven't yet parsed the expiration date (which
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // usually appears at the end).
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (credit_card_field->cardholder_ == NULL) {
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::string16 name_pattern;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (fields == 0 || credit_card_field->expiration_month_) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // at beginning or end
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        name_pattern = base::UTF8ToUTF16(autofill::kNameOnCardRe);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        name_pattern = base::UTF8ToUTF16(autofill::kNameOnCardContextualRe);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (ParseField(scanner, name_pattern, &credit_card_field->cardholder_))
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // As a hard-coded hack for Expedia's billing pages (expedia_checkout.html
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // and ExpediaBilling.html in our test suite), recognize separate fields
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // for the cardholder's first and last name if they have the labels "cfnm"
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // and "clnm".
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scanner->SaveCursor();
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      AutofillField* first;
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (ParseField(scanner, base::ASCIIToUTF16("^cfnm"), &first) &&
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          ParseField(scanner,
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     base::ASCIIToUTF16("^clnm"),
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     &credit_card_field->cardholder_last_)) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        credit_card_field->cardholder_ = first;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scanner->Rewind();
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check for a credit card type (Visa, MasterCard, etc.) field.
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::string16 type_pattern = base::UTF8ToUTF16(autofill::kCardTypeRe);
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!credit_card_field->type_ &&
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        ParseFieldSpecifics(scanner,
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            type_pattern,
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            MATCH_DEFAULT | MATCH_SELECT,
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            &credit_card_field->type_)) {
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We look for a card security code before we look for a credit
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // card number and match the general term "number".  The security code
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // has a plethora of names; we've seen "verification #",
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // "verification number", "card identification number" and others listed
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // in the |pattern| below.
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::string16 pattern = base::UTF8ToUTF16(autofill::kCardCvcRe);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!credit_card_field->verification_ &&
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ParseField(scanner, pattern, &credit_card_field->verification_)) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pattern = base::UTF8ToUTF16(autofill::kCardNumberRe);
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    AutofillField* current_number_field;
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (ParseField(scanner, pattern, &current_number_field)) {
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Avoid autofilling any credit card number field having very low or high
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |start_index| on the HTML form.
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      size_t start_index = 0;
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (!credit_card_field->numbers_.empty()) {
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        size_t last_number_field_size =
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            credit_card_field->numbers_.back()->credit_card_number_offset() +
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            credit_card_field->numbers_.back()->max_length;
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        // In some cases, HTML form may have credit card number split across
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        // multiple input fields and either one or cumulatively having
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        // |max_length| more than |kMaxValidCardNumberSize|, mark these input
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        // form fields as invalid and skip autofilling them.
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (last_number_field_size == 0U ||
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            last_number_field_size >= kMaxValidCardNumberSize) {
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          // Mark that the credit card number splits are invalid. But keep
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          // scanning HTML form so that cursor moves beyond related fields.
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          form_has_valid_card_number_fields = false;
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        start_index = last_number_field_size;
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      current_number_field->set_credit_card_number_offset(start_index);
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      credit_card_field->numbers_.push_back(current_number_field);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (LowerCaseEqualsASCII(scanner->Cursor()->form_control_type, "month")) {
1291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      credit_card_field->expiration_date_ = scanner->Cursor();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scanner->Advance();
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // First try to parse split month/year expiration fields.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scanner->SaveCursor();
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      pattern = base::UTF8ToUTF16(autofill::kExpirationMonthRe);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!credit_card_field->expiration_month_ &&
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          ParseFieldSpecifics(scanner,
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              pattern,
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              MATCH_DEFAULT | MATCH_SELECT,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              &credit_card_field->expiration_month_)) {
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        pattern = base::UTF8ToUTF16(autofill::kExpirationYearRe);
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (ParseFieldSpecifics(scanner,
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                pattern,
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                MATCH_DEFAULT | MATCH_SELECT,
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                &credit_card_field->expiration_year_)) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          continue;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If that fails, try to parse a combined expiration field.
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!credit_card_field->expiration_date_) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Look for a 2-digit year first.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        scanner->Rewind();
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        pattern = base::UTF8ToUTF16(autofill::kExpirationDate2DigitYearRe);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We allow <select> fields, because they're used e.g. on qvc.com.
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (ParseFieldSpecifics(
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                scanner,
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                pattern,
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                MATCH_LABEL | MATCH_VALUE | MATCH_TEXT | MATCH_SELECT,
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                &credit_card_field->expiration_date_)) {
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          credit_card_field->exp_year_type_ = CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          continue;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        pattern = base::UTF8ToUTF16(autofill::kExpirationDateRe);
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (ParseFieldSpecifics(
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                scanner,
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                pattern,
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                MATCH_LABEL | MATCH_VALUE | MATCH_TEXT | MATCH_SELECT,
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                &credit_card_field->expiration_date_)) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          continue;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (credit_card_field->expiration_month_ &&
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          !credit_card_field->expiration_year_ &&
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          !credit_card_field->expiration_date_) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Parsed a month but couldn't parse a year; give up.
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        scanner->RewindTo(saved_cursor);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Some pages (e.g. ExpediaBilling.html) have a "card description"
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // field; we parse this field but ignore it.
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We also ignore any other fields within a credit card block that
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // start with "card", under the assumption that they are related to
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the credit card section being processed but are uninteresting to us.
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (ParseField(scanner, base::UTF8ToUTF16(autofill::kCardIgnoredRe), NULL))
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    break;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Cases where heuristic misinterprets input field as credit card number
1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // field, refuse to autofill credit card number fields.
1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!form_has_valid_card_number_fields)
1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    credit_card_field->numbers_.clear();
1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Some pages have a billing address field after the cardholder name field.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For that case, allow only just the cardholder name field.  The remaining
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CC fields will be picked up in a following CreditCardField.
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (credit_card_field->cardholder_)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return credit_card_field.release();
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On some pages, the user selects a card type using radio buttons
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (e.g. test page Apple Store Billing.html).  We can't handle that yet,
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so we treat the card type as optional for now.
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The existence of a number or cvc in combination with expiration date is
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a strong enough signal that this is a credit card.  It is possible that
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the number and name were parsed in a separate part of the form.  So if
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the cvc and date were found independently they are returned.
2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if ((!credit_card_field->numbers_.empty() ||
2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       credit_card_field->verification_ ||
2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       !form_has_valid_card_number_fields) &&
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (credit_card_field->expiration_date_ ||
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       (credit_card_field->expiration_month_ &&
2171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        credit_card_field->expiration_year_))) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return credit_card_field.release();
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scanner->RewindTo(saved_cursor);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CreditCardField::CreditCardField()
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : cardholder_(NULL),
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cardholder_last_(NULL),
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      type_(NULL),
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      verification_(NULL),
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      expiration_month_(NULL),
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      expiration_year_(NULL),
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      expiration_date_(NULL),
2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      exp_year_type_(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR) {
2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciCreditCardField::~CreditCardField() {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochbool CreditCardField::ClassifyField(ServerFieldTypeMap* map) const {
2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool ok = true;
2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (size_t index = 0; index < numbers_.size(); ++index) {
2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ok = ok && AddClassification(numbers_[index], CREDIT_CARD_NUMBER, map);
2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ok = ok && AddClassification(type_, CREDIT_CARD_TYPE, map);
2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ok = ok &&
2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       AddClassification(verification_, CREDIT_CARD_VERIFICATION_CODE, map);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the heuristics detected first and last name in separate fields,
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // then ignore both fields. Putting them into separate fields is probably
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // wrong, because the credit card can also contain a middle name or middle
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // initial.
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cardholder_last_ == NULL)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ok = ok && AddClassification(cardholder_, CREDIT_CARD_NAME, map);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (expiration_date_) {
2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ok =
2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        ok && AddClassification(expiration_date_, GetExpirationYearType(), map);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ok = ok && AddClassification(expiration_month_, CREDIT_CARD_EXP_MONTH, map);
2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ok =
2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        ok && AddClassification(expiration_year_, GetExpirationYearType(), map);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ok;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciServerFieldType CreditCardField::GetExpirationYearType() const {
2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return (expiration_date_
2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              ? exp_year_type_
2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              : ((expiration_year_ && expiration_year_->max_length == 2)
2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     ? CREDIT_CARD_EXP_2_DIGIT_YEAR
2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     : CREDIT_CARD_EXP_4_DIGIT_YEAR));
2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace autofill
277