diff options
author | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-16 19:40:29 +0000 |
---|---|---|
committer | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-16 19:40:29 +0000 |
commit | 9bd382a74497d0564c5e6feee48c1fea34c43d27 (patch) | |
tree | 34fff0a7a729eb15b109d41306f98542e39b62de /chrome/browser/autofill | |
parent | b882d76636d5380e88904446c0c5d81a40cef9a1 (diff) | |
download | chromium_src-9bd382a74497d0564c5e6feee48c1fea34c43d27.zip chromium_src-9bd382a74497d0564c5e6feee48c1fea34c43d27.tar.gz chromium_src-9bd382a74497d0564c5e6feee48c1fea34c43d27.tar.bz2 |
Implement CreditCardField, a FormField that matches a credit card field in a form.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/502018
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@34736 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/autofill')
-rw-r--r-- | chrome/browser/autofill/credit_card_field.cc | 163 | ||||
-rw-r--r-- | chrome/browser/autofill/credit_card_field.h | 52 | ||||
-rw-r--r-- | chrome/browser/autofill/form_field.cc | 5 |
3 files changed, 219 insertions, 1 deletions
diff --git a/chrome/browser/autofill/credit_card_field.cc b/chrome/browser/autofill/credit_card_field.cc new file mode 100644 index 0000000..976ea07 --- /dev/null +++ b/chrome/browser/autofill/credit_card_field.cc @@ -0,0 +1,163 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/autofill/credit_card_field.h" + +#include "base/string16.h" +#include "chrome/browser/autofill/autofill_field.h" + +bool CreditCardField::GetFieldInfo(FieldTypeMap* field_type_map) const { + return false; +} + +// static +CreditCardField* CreditCardField::Parse( + std::vector<AutoFillField*>::const_iterator* iter, + bool is_ecml) { + CreditCardField credit_card_field; + std::vector<AutoFillField*>::const_iterator q = *iter; + string16 pattern; + + // Credit card fields can appear in many different orders. + for (int fields = 0; q != *iter; ++fields) { + // Sometimes the cardholder field is just labeled "name" (e.g. on test page + // Starbucks - Credit card.html). Unfortunately this is a dangerously + // generic word to search for, since it will often match a name (not + // cardholder name) field before or after credit card fields. So we search + // for "name" only when we've already parsed at least one other credit card + // field and haven't yet parsed the expiration date (which usually appears + // at the end). + if (credit_card_field.cardholder_ == NULL) { + string16 name_pattern; + if (is_ecml) { + name_pattern = GetEcmlPattern(kEcmlCardHolder); + } else { + if (fields == 0 || credit_card_field.expiration_month_) { + // at beginning or end + name_pattern = ASCIIToUTF16("card holder|name on card"); + } else { + name_pattern = ASCIIToUTF16("name"); + } + } + + if (ParseText(&q, name_pattern, &credit_card_field.cardholder_)) { + continue; + } + + // As a hard-coded hack for Expedia's billing pages (expedia_checkout.html + // and ExpediaBilling.html in our test suite), recognize separate fields + // for the cardholder's first and last name if they have the labels "cfnm" + // and "clnm". + std::vector<AutoFillField*>::const_iterator p = q; + AutoFillField* first; + if (!is_ecml && ParseText(&p, ASCIIToUTF16("^cfnm"), &first) && + ParseText(&p, ASCIIToUTF16("^clnm"), + &credit_card_field.cardholder_last_)) { + credit_card_field.cardholder_ = first; + q = p; + continue; + } + } + + // TODO(jhawkins): Parse the type select control. + + // We look for a card security code before we look for a credit card number + // and match the general term "number". The security code has a plethora of + // names; we've seen "verification #", "verification number", + // "card identification number" and others listed in the ParseText() call + // below. + if (is_ecml) { + pattern = GetEcmlPattern(kEcmlCardVerification); + } else { + pattern = ASCIIToUTF16( + "verification|card identification|cvn|security code|cvv code|cvc"); + } + + if (credit_card_field.verification_ == NULL && + ParseText(&q, pattern, &credit_card_field.verification_)) { + continue; + } + + if (is_ecml) + pattern = GetEcmlPattern(kEcmlCardNumber); + else + pattern = ASCIIToUTF16("number|card #|card no.|card_number"); + + if (credit_card_field.number_ == NULL && ParseText(&q, pattern, + &credit_card_field.number_)) { + continue; + } + + // "Expiration date" is the most common label here, but some pages have + // "Expires", "exp. date" or "exp. month" and "exp. year". We also look for + // the field names ccmonth and ccyear, which appear on at least 4 of our + // test pages. + // + // -> On at least one page (The China Shop2.html) we find only the labels + // "month" and "year". So for now we match these words directly; we'll + // see if this turns out to be too general. + // + // Toolbar Bug 51451: indeed, simply matching "month" is too general for + // https://rps.fidelity.com/ftgw/rps/RtlCust/CreatePIN/Init. + // Instead, we match only words beginning with "month". + if (is_ecml) + pattern = GetEcmlPattern(kEcmlCardExpireMonth); + else + pattern = ASCIIToUTF16("expir|exp month|exp date|ccmonth|&month"); + + if (!credit_card_field.expiration_month_ || + credit_card_field.expiration_month_->IsEmpty() && + ParseText(&q, pattern, &credit_card_field.expiration_month_)) { + if (is_ecml) + pattern = GetEcmlPattern(kEcmlCardExpireYear); + else + pattern = ASCIIToUTF16("|exp|^/|ccyear|year"); + + if (!ParseText(&q, pattern, &credit_card_field.expiration_year_)) { + return NULL; + } + + continue; + } + + if (ParseText(&q, GetEcmlPattern(kEcmlCardExpireDay))) + continue; + + // Some pages (e.g. ExpediaBilling.html) have a "card description" + // field; we parse this field but ignore it. + ParseText(&q, ASCIIToUTF16("card description")); + } + + // On some pages, the user selects a card type using radio buttons + // (e.g. test page Apple Store Billing.html). We can't handle that yet, + // so we treat the card type as optional for now. + if (credit_card_field.number_ != NULL && + credit_card_field.expiration_month_ && + !credit_card_field.expiration_month_->IsEmpty()) { + *iter = q; + return new CreditCardField(credit_card_field); + } + + return NULL; +} + +CreditCardField::CreditCardField() + : cardholder_(NULL), + cardholder_last_(NULL), + type_(NULL), + number_(NULL), + verification_(NULL), + expiration_month_(NULL), + expiration_year_(NULL) { +} + +CreditCardField::CreditCardField(const CreditCardField& field) + : cardholder_(field.cardholder_), + cardholder_last_(field.cardholder_last_), + type_(field.type_), + number_(field.number_), + verification_(field.verification_), + expiration_month_(field.expiration_month_), + expiration_year_(field.expiration_year_) { +} diff --git a/chrome/browser/autofill/credit_card_field.h b/chrome/browser/autofill/credit_card_field.h new file mode 100644 index 0000000..4fed417 --- /dev/null +++ b/chrome/browser/autofill/credit_card_field.h @@ -0,0 +1,52 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_AUTOFILL_CREDIT_CARD_FIELD_H_ +#define CHROME_BROWSER_AUTOFILL_CREDIT_CARD_FIELD_H_ + +#include <vector> + +#include "chrome/browser/autofill/form_field.h" + +class AutoFillField; + +class CreditCardField : public FormField { + public: + // FormField implementation: + virtual bool GetFieldInfo(FieldTypeMap* field_type_map) const; + virtual FormFieldType GetFormFieldType() { return kCreditCardType; } + virtual int priority() const { return 4; } + + static CreditCardField* Parse( + std::vector<AutoFillField*>::const_iterator* iter, + bool is_ecml); + + private: + CreditCardField(); + explicit CreditCardField(const CreditCardField& field); + void operator=(const CreditCardField&); + + AutoFillField* cardholder_; // Optional. + + // Occasionally pages have separate fields for the cardholder's first and + // last names; for such pages cardholder_ holds the first name field and + // we store the last name field here. + // (We could store an embedded NameField object here, but we don't do so + // because the text patterns for matching a cardholder name are different + // than for ordinary names, and because cardholder names never have titles, + // middle names or suffixes.) + AutoFillField* cardholder_last_; + + AutoFillField* type_; // Optional. TODO(jhawkins): Parse the select control. + AutoFillField* number_; + + // The 3-digit card verification number; we don't currently fill this. + AutoFillField* verification_; + + // Both optional. TODO(jhawkins): Parse the select control. + AutoFillField* expiration_month_; + AutoFillField* expiration_year_; +}; + +#endif // CHROME_BROWSER_AUTOFILL_CREDIT_CARD_FIELD_H_ diff --git a/chrome/browser/autofill/form_field.cc b/chrome/browser/autofill/form_field.cc index 1ab2c88..ec15120 100644 --- a/chrome/browser/autofill/form_field.cc +++ b/chrome/browser/autofill/form_field.cc @@ -6,6 +6,7 @@ #include "chrome/browser/autofill/address_field.h" #include "chrome/browser/autofill/autofill_field.h" +#include "chrome/browser/autofill/credit_card_field.h" #include "chrome/browser/autofill/phone_field.h" #include "third_party/WebKit/WebKit/chromium/public/WebRegularExpression.h" #include "third_party/WebKit/WebKit/chromium/public/WebString.h" @@ -72,9 +73,11 @@ FormField* FormField::ParseFormField( field = AddressField::Parse(iter, is_ecml); if (field != NULL) return field; + field = CreditCardField::Parse(iter, is_ecml); + if (field != NULL) + return field; // TODO(jhawkins): - // - CreditCardField // - NameField return NULL; |