summaryrefslogtreecommitdiffstats
path: root/chrome/browser/autofill
diff options
context:
space:
mode:
authorjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-06 20:25:41 +0000
committerjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-06 20:25:41 +0000
commitd02de4556a244955abcc7de355a16e06020c91a7 (patch)
tree1d4db13f9e3a127d7a82801d779a49143020295b /chrome/browser/autofill
parent0aa936cb4abf259bf8f528d756d2c4aa65c130ef (diff)
downloadchromium_src-d02de4556a244955abcc7de355a16e06020c91a7.zip
chromium_src-d02de4556a244955abcc7de355a16e06020c91a7.tar.gz
chromium_src-d02de4556a244955abcc7de355a16e06020c91a7.tar.bz2
Add CreditCard, a form group that stores credit card information.
BUG=none TEST=none Review URL: http://codereview.chromium.org/518031 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35645 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/autofill')
-rw-r--r--chrome/browser/autofill/credit_card.cc397
-rw-r--r--chrome/browser/autofill/credit_card.h125
2 files changed, 522 insertions, 0 deletions
diff --git a/chrome/browser/autofill/credit_card.cc b/chrome/browser/autofill/credit_card.cc
new file mode 100644
index 0000000..97264de
--- /dev/null
+++ b/chrome/browser/autofill/credit_card.cc
@@ -0,0 +1,397 @@
+// Copyright (c) 2010 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.h"
+
+#include "base/basictypes.h"
+#include "base/string_util.h"
+#include "chrome/browser/autofill/autofill_type.h"
+#include "chrome/browser/autofill/field_types.h"
+
+static const string16 kCreditCardSeparators = ASCIIToUTF16(" -");
+
+static const AutoFillFieldType kAutoFillCreditCardTypes[] = {
+ CREDIT_CARD_NAME,
+ CREDIT_CARD_NUMBER,
+ CREDIT_CARD_TYPE,
+ CREDIT_CARD_EXP_MONTH,
+ CREDIT_CARD_EXP_4_DIGIT_YEAR,
+ CREDIT_CARD_VERIFICATION_CODE,
+};
+
+static const int kAutoFillCreditCardLength =
+ arraysize(kAutoFillCreditCardTypes);
+
+CreditCard::CreditCard(const string16& label)
+ : expiration_month_(0),
+ expiration_year_(0),
+ label_(label) {
+}
+
+FormGroup* CreditCard::Clone() const {
+ return new CreditCard(*this);
+}
+
+void CreditCard::GetPossibleFieldTypes(const string16& text,
+ FieldTypeSet* possible_types) const {
+ if (IsNameOnCard(text))
+ possible_types->insert(CREDIT_CARD_NAME);
+
+ if (IsCreditCardNumber(text))
+ possible_types->insert(CREDIT_CARD_NUMBER);
+
+ if (IsExpirationMonth(text))
+ possible_types->insert(CREDIT_CARD_EXP_MONTH);
+
+ if (Is2DigitExpirationYear(text))
+ possible_types->insert(CREDIT_CARD_EXP_2_DIGIT_YEAR);
+
+ if (Is4DigitExpirationYear(text))
+ possible_types->insert(CREDIT_CARD_EXP_4_DIGIT_YEAR);
+
+ if (IsCardType(text))
+ possible_types->insert(CREDIT_CARD_TYPE);
+
+ if (IsVerificationCode(text))
+ possible_types->insert(CREDIT_CARD_VERIFICATION_CODE);
+}
+
+void CreditCard::FindInfoMatches(const AutoFillType& type,
+ const string16& info,
+ std::vector<string16>* matched_text) const {
+ if (matched_text == NULL) {
+ DLOG(ERROR) << "NULL matched vector passed in";
+ return;
+ }
+
+ string16 match;
+ switch (type.field_type()) {
+ case CREDIT_CARD_NUMBER: {
+ // Because the credit card number is encrypted and we are not able to do
+ // comparisons with it we will say that any field that is known to be a
+ // credit card number field will match all credit card numbers.
+ string16 text = GetPreviewText(AutoFillType(CREDIT_CARD_NUMBER));
+ if (!text.empty())
+ matched_text->push_back(text);
+ break;
+ }
+
+ case CREDIT_CARD_VERIFICATION_CODE:
+ break;
+
+ case UNKNOWN_TYPE:
+ for (int i = 0; i < kAutoFillCreditCardLength; ++i) {
+ if (FindInfoMatchesHelper(kAutoFillCreditCardTypes[i], info, &match))
+ matched_text->push_back(match);
+ }
+ break;
+
+ default:
+ if (FindInfoMatchesHelper(type.field_type(), info, &match))
+ matched_text->push_back(match);
+ break;
+ }
+}
+
+string16 CreditCard::GetFieldText(const AutoFillType& type) const {
+ switch (type.field_type()) {
+ case CREDIT_CARD_NAME:
+ return name_on_card();
+
+ case CREDIT_CARD_EXP_MONTH:
+ return ExpirationMonthAsString();
+
+ case CREDIT_CARD_EXP_2_DIGIT_YEAR:
+ return Expiration2DigitYearAsString();
+
+ case CREDIT_CARD_EXP_4_DIGIT_YEAR:
+ return Expiration4DigitYearAsString();
+
+ case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR: {
+ string16 month = ExpirationMonthAsString();
+ string16 year = Expiration2DigitYearAsString();
+ if (!month.empty() && !year.empty())
+ return month + ASCIIToUTF16("/") + year;
+ return EmptyString16();
+ }
+
+ case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR: {
+ string16 month = ExpirationMonthAsString();
+ string16 year = Expiration4DigitYearAsString();
+ if (!month.empty() && !year.empty())
+ return month + ASCIIToUTF16("/") + year;
+ return EmptyString16();
+ }
+
+ case CREDIT_CARD_TYPE:
+ return this->type();
+
+ case CREDIT_CARD_NUMBER:
+ return number();
+
+ case CREDIT_CARD_VERIFICATION_CODE:
+ return verification_code();
+
+ default:
+ // ComputeDataPresentForArray will hit this repeatedly.
+ return EmptyString16();
+ }
+}
+
+string16 CreditCard::GetPreviewText(const AutoFillType& type) const {
+ switch (type.field_type()) {
+ case CREDIT_CARD_NUMBER:
+ return last_four_digits();
+
+ case CREDIT_CARD_VERIFICATION_CODE:
+ return ASCIIToUTF16("xxx");
+
+ default:
+ return GetFieldText(type);
+ }
+}
+
+void CreditCard::SetInfo(const AutoFillType& type, const string16& value) {
+ switch (type.field_type()) {
+ case CREDIT_CARD_NAME:
+ set_name_on_card(value);
+ break;
+
+ case CREDIT_CARD_EXP_MONTH:
+ SetExpirationMonthFromString(value);
+ break;
+
+ case CREDIT_CARD_EXP_4_DIGIT_YEAR:
+ SetExpirationYearFromString(value);
+ break;
+
+ case CREDIT_CARD_TYPE:
+ set_type(value);
+ break;
+
+ case CREDIT_CARD_NUMBER:
+ set_number(value);
+ break;
+
+ case CREDIT_CARD_VERIFICATION_CODE:
+ set_verification_code(value);
+ break;
+
+ default:
+ DLOG(ERROR) << "Attempting to set unknown info-type";
+ break;
+ }
+}
+
+string16 CreditCard::ExpirationMonthAsString() const {
+ if (expiration_month_ == 0)
+ return EmptyString16();
+
+ string16 month = IntToString16(expiration_month_);
+ if (expiration_month_ >= 10)
+ return month;
+
+ string16 zero = ASCIIToUTF16("0");
+ zero.append(month);
+ return zero;
+}
+
+string16 CreditCard::Expiration4DigitYearAsString() const {
+ if (expiration_year_ == 0)
+ return EmptyString16();
+
+ return IntToString16(Expiration4DigitYear());
+}
+
+string16 CreditCard::Expiration2DigitYearAsString() const {
+ if (expiration_year_ == 0)
+ return EmptyString16();
+
+ return IntToString16(Expiration2DigitYear());
+}
+
+void CreditCard::SetExpirationMonthFromString(const string16& text) {
+ int month;
+ if (!ConvertDate(text, &month))
+ return;
+
+ set_expiration_month(month);
+}
+
+void CreditCard::SetExpirationYearFromString(const string16& text) {
+ int year;
+ if (!ConvertDate(text, &year))
+ return;
+
+ set_expiration_year(year);
+}
+
+void CreditCard::set_expiration_month(int expiration_month) {
+ if (expiration_month < 0 || expiration_month > 12)
+ return;
+
+ expiration_month_ = expiration_month;
+}
+
+void CreditCard::set_expiration_year(int expiration_year) {
+ if (expiration_year != 0 &&
+ (expiration_year < 2006 || expiration_year > 10000)) {
+ return;
+ }
+
+ expiration_year_ = expiration_year;
+}
+
+CreditCard::CreditCard(const CreditCard& card)
+ : number_(card.number_),
+ name_on_card_(card.name_on_card_),
+ type_(card.type_),
+ verification_code_(card.verification_code_),
+ last_four_digits_(card.last_four_digits_),
+ expiration_month_(card.expiration_month_),
+ expiration_year_(card.expiration_year_),
+ label_(card.label_) {
+}
+
+bool CreditCard::FindInfoMatchesHelper(const AutoFillFieldType& field_type,
+ const string16& info,
+ string16* match) const {
+ if (match == NULL) {
+ DLOG(ERROR) << "NULL match string passed in";
+ return false;
+ }
+
+ match->clear();
+ switch (field_type) {
+ case CREDIT_CARD_NAME: {
+ if (StartsWith(name_on_card(), info, false))
+ *match = name_on_card();
+ break;
+ }
+
+ case CREDIT_CARD_EXP_MONTH: {
+ string16 exp_month(ExpirationMonthAsString());
+ if (StartsWith(exp_month, info, true))
+ *match = exp_month;
+ }
+
+ case CREDIT_CARD_EXP_2_DIGIT_YEAR: {
+ string16 exp_year(Expiration2DigitYearAsString());
+ if (StartsWith(exp_year, info, true))
+ *match = exp_year;
+ }
+
+ case CREDIT_CARD_EXP_4_DIGIT_YEAR: {
+ string16 exp_year(Expiration4DigitYearAsString());
+ if (StartsWith(exp_year, info, true))
+ *match = exp_year;
+ }
+
+ case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR: {
+ string16 exp_date(ExpirationMonthAsString() + ASCIIToUTF16("/") +
+ Expiration2DigitYearAsString());
+ if (StartsWith(exp_date, info, true))
+ *match = exp_date;
+ }
+
+ case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR: {
+ string16 exp_date(ExpirationMonthAsString() + ASCIIToUTF16("/") +
+ Expiration4DigitYearAsString());
+ if (StartsWith(exp_date, info, true))
+ *match = exp_date;
+ }
+
+ case CREDIT_CARD_TYPE: {
+ string16 card_type(this->type());
+ if (StartsWith(card_type, info, true))
+ *match = card_type;
+ }
+
+ case CREDIT_CARD_VERIFICATION_CODE: {
+ if (StartsWith(verification_code(), info, true))
+ *match = verification_code();
+ }
+
+ default:
+ break;
+ }
+ return !match->empty();
+}
+
+bool CreditCard::IsNameOnCard(const string16& text) const {
+ return StringToLowerASCII(text) == StringToLowerASCII(name_on_card_);
+}
+
+bool CreditCard::IsCreditCardNumber(const string16& text) {
+ string16 number;
+ TrimString(text, kCreditCardSeparators.c_str(), &number);
+
+ // We use the Luhn formula to validate the number; see
+ // http://www.beachnet.com/~hstiles/cardtype.html and
+ // http://www.webopedia.com/TERM/L/Luhn_formula.html.
+ int sum = 0;
+ bool odd = false;
+ string16::reverse_iterator iter;
+ for (iter = number.rbegin(); iter != number.rend(); ++iter) {
+ if (!IsAsciiDigit(*iter))
+ return false;
+
+ int digit = *iter - '0';
+ if (odd) {
+ digit *= 2;
+ sum += digit / 10 + digit % 10;
+ } else {
+ sum += digit;
+ }
+ odd = !odd;
+ }
+
+ return (sum % 10) == 0;
+}
+
+bool CreditCard::IsVerificationCode(const string16& text) const {
+ return StringToLowerASCII(text) == StringToLowerASCII(verification_code_);
+}
+
+bool CreditCard::IsExpirationMonth(const string16& text) const {
+ int month;
+ if (!StringToInt(text, &month))
+ return false;
+
+ return expiration_month_ == month;
+}
+
+bool CreditCard::Is2DigitExpirationYear(const string16& text) const {
+ int year;
+ if (!StringToInt(text, &year))
+ return false;
+
+ return year < 100 && (expiration_year_ % 100) == year;
+}
+
+bool CreditCard::Is4DigitExpirationYear(const string16& text) const {
+ int year;
+ if (!StringToInt(text, &year))
+ return false;
+
+ return expiration_year_ == year;
+}
+
+bool CreditCard::IsCardType(const string16& text) const {
+ return StringToLowerASCII(text) == StringToLowerASCII(type_);
+}
+
+bool CreditCard::ConvertDate(const string16& date, int* num) const {
+ if (!date.empty()) {
+ bool converted = StringToInt(date, num);
+ DCHECK(converted);
+ if (!converted)
+ return false;
+ } else {
+ // Clear the value.
+ *num = 0;
+ }
+
+ return true;
+}
diff --git a/chrome/browser/autofill/credit_card.h b/chrome/browser/autofill/credit_card.h
new file mode 100644
index 0000000..d686bbc
--- /dev/null
+++ b/chrome/browser/autofill/credit_card.h
@@ -0,0 +1,125 @@
+// Copyright (c) 2010 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_H_
+#define CHROME_BROWSER_AUTOFILL_CREDIT_CARD_H_
+
+#include <vector>
+
+#include "base/string16.h"
+#include "chrome/browser/autofill/form_group.h"
+
+// A form group that stores credit card information.
+class CreditCard : public FormGroup {
+ public:
+ explicit CreditCard(const string16& label);
+
+ // FormGroup implementation:
+ FormGroup* Clone() const;
+ virtual void GetPossibleFieldTypes(const string16& text,
+ FieldTypeSet* possible_types) const;
+ virtual void FindInfoMatches(const AutoFillType& type,
+ const string16& info,
+ std::vector<string16>* matched_text) const;
+ virtual string16 GetFieldText(const AutoFillType& type) const;
+ virtual string16 GetPreviewText(const AutoFillType& type) const;
+ virtual void SetInfo(const AutoFillType& type, const string16& value);
+ string16 Label() const { return label_; }
+
+ // The month and year are zero if not present.
+ int Expiration4DigitYear() const { return expiration_year_; }
+ int Expiration2DigitYear() const { return expiration_year_ % 100; }
+ string16 ExpirationMonthAsString() const;
+ string16 Expiration4DigitYearAsString() const;
+ string16 Expiration2DigitYearAsString() const;
+
+ // Sets |expiration_month_| to the integer conversion of |text|.
+ void SetExpirationMonthFromString(const string16& text);
+
+ // Sets |expiration_year_| to the integer conversion of |text|.
+ void SetExpirationYearFromString(const string16& text);
+
+ string16 number() const { return number_; }
+ string16 name_on_card() const { return name_on_card_; }
+ string16 type() const { return type_; }
+ string16 verification_code() const { return verification_code_; }
+ string16 last_four_digits() const { return last_four_digits_; }
+ int expiration_month() const { return expiration_month_; }
+ int expiration_year() const { return expiration_year_; }
+
+ void set_number(const string16& number) { number_ = number; }
+ void set_name_on_card(const string16& name_on_card) {
+ name_on_card_ = name_on_card;
+ }
+ void set_type(const string16& type) { type_ = type; }
+ void set_verification_code(const string16& verification_code) {
+ verification_code_ = verification_code;
+ }
+ void set_last_four_digits(const string16& last_four_digits) {
+ last_four_digits_ = last_four_digits;
+ }
+
+ // These setters verify that the month and year are within appropriate
+ // ranges.
+ void set_expiration_month(int expiration_month);
+ void set_expiration_year(int expiration_year);
+
+ private:
+ explicit CreditCard(const CreditCard& card);
+ void operator=(const CreditCard& card);
+
+ // A helper function for FindInfoMatches that only handles matching the info
+ // with the requested field type.
+ bool FindInfoMatchesHelper(const AutoFillFieldType& field_type,
+ const string16& info,
+ string16* match) const;
+
+ // Returns true if |text| matches the name on the card. The comparison is
+ // case-insensitive.
+ bool IsNameOnCard(const string16& text) const;
+
+ // Uses the Luhn formula to validate the credit card number in |text|.
+ static bool IsCreditCardNumber(const string16& text);
+
+ // Returns true if |text| matches the expiration month of the card.
+ bool IsExpirationMonth(const string16& text) const;
+
+ // Returns true if |text| matches the CVV of the card. The comparison is
+ // case-insensitive.
+ bool IsVerificationCode(const string16& text) const;
+
+ // Returns true if the integer value of |text| matches the 2-digit expiration
+ // year.
+ bool Is2DigitExpirationYear(const string16& text) const;
+
+ // Returns true if the integer value of |text| matches the 4-digit expiration
+ // year.
+ bool Is4DigitExpirationYear(const string16& text) const;
+
+ // Returns true if |text| matches the type of the card. The comparison is
+ // case-insensitive.
+ bool IsCardType(const string16& text) const;
+
+ // Converts |date| to an integer form. Returns true if the conversion
+ // succeeded.
+ bool ConvertDate(const string16& date, int* num) const;
+
+ // The credit card values.
+ string16 number_; // The encrypted credit card number.
+ string16 name_on_card_; // The cardholder's name.
+ string16 type_; // The type of the card.
+ string16 verification_code_; // The CVV.
+
+ // Stores the last four digits of the credit card number.
+ string16 last_four_digits_;
+
+ // These members are zero if not present.
+ int expiration_month_;
+ int expiration_year_;
+
+ // This is the display name of the card set by the user, e.g., Amazon Visa.
+ string16 label_;
+};
+
+#endif // CHROME_BROWSER_AUTOFILL_CREDIT_CARD_H_