credit_card.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// found in the LICENSE file.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "components/autofill/core/browser/credit_card.h"
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <stddef.h>
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <algorithm>
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <ostream>
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <string>
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/basictypes.h"
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/guid.h"
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/logging.h"
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/strings/string16.h"
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/strings/string_split.h"
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/strings/string_util.h"
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/strings/utf_string_conversions.h"
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/time/time.h"
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "components/autofill/core/browser/autofill_field.h"
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "components/autofill/core/browser/autofill_regexes.h"
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "components/autofill/core/browser/autofill_type.h"
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "components/autofill/core/browser/validation.h"
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "components/autofill/core/common/form_field_data.h"
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "grit/component_scaled_resources.h"
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "grit/component_strings.h"
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "third_party/icu/source/common/unicode/uloc.h"
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "third_party/icu/source/i18n/unicode/dtfmtsym.h"
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace autofill {
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace {
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const base::char16 kCreditCardObfuscationSymbol = '*';
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This is the maximum obfuscated symbols displayed.
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// It is introduced to avoid rare cases where the credit card number is
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// too large and fills the screen.
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const size_t kMaxObfuscationSize = 20;
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool ConvertYear(const base::string16& year, int* num) {
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // If the |year| is empty, clear the stored value.
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  if (year.empty()) {
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    *num = 0;
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
4953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  }
5053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
517242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci  // Try parsing the |year| as a number.
5253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  if (base::StringToInt(year, num))
53f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return true;
54f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
55f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)  *num = 0;
5653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  return false;
577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccibool ConvertMonth(const base::string16& month,
607242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                  const std::string& app_locale,
617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                  int* num) {
627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci  // If the |month| is empty, clear the stored value.
637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci  if (month.empty()) {
647242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    *num = 0;
65e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    return true;
66e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  }
67e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
687242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci  // Try parsing the |month| as a number.
697242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci  if (base::StringToInt(month, num))
70e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    return true;
71e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
72e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  // If the locale is unknown, give up.
73e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  if (app_locale.empty())
74e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    return false;
757242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
76e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  // Otherwise, try parsing the |month| as a named month, e.g. "January" or
77e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  // "Jan".
78e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  base::string16 lowercased_month = StringToLowerASCII(month);
7953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
807242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci  UErrorCode status = U_ZERO_ERROR;
817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci  icu::Locale locale(app_locale.c_str());
827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci  icu::DateFormatSymbols date_format_symbols(locale, status);
837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci  DCHECK(status == U_ZERO_ERROR || status == U_USING_FALLBACK_WARNING ||
847242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci         status == U_USING_DEFAULT_WARNING);
857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
867242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci  int32_t num_months;
877242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci  const icu::UnicodeString* months = date_format_symbols.getMonths(num_months);
887242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci  for (int32_t i = 0; i < num_months; ++i) {
897242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    const base::string16 icu_month = base::string16(months[i].getBuffer(),
907242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                                        months[i].length());
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (lowercased_month == StringToLowerASCII(icu_month)) {
92f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)      *num = i + 1;  // Adjust from 0-indexed to 1-indexed.
93e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      return true;
94e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    }
959e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)  }
969e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
97e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  months = date_format_symbols.getShortMonths(num_months);
987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci  for (int32_t i = 0; i < num_months; ++i) {
99e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    const base::string16 icu_month = base::string16(months[i].getBuffer(),
100e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                                        months[i].length());
101e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (lowercased_month == StringToLowerASCII(icu_month)) {
102e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      *num = i + 1;  // Adjust from 0-indexed to 1-indexed.
103f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)      return true;
104f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    }
105f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)  }
106f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
1077242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci  *num = 0;
108e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  return false;
10953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
110f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}  // namespace
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)CreditCard::CreditCard(const std::string& guid, const std::string& origin)
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : AutofillDataModel(guid, origin),
115e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      type_(kGenericCard),
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      expiration_month_(0),
1177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci      expiration_year_(0) {
1187242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)CreditCard::CreditCard()
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : AutofillDataModel(base::GenerateGUID(), std::string()),
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      type_(kGenericCard),
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      expiration_month_(0),
12453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      expiration_year_(0) {
125e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch}
12653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
1277242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciCreditCard::CreditCard(const CreditCard& credit_card)
1287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    : AutofillDataModel(std::string(), std::string()) {
12953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  operator=(credit_card);
13053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
13153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
132e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben MurdochCreditCard::~CreditCard() {}
13353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
13453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)// static
135e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochconst base::string16 CreditCard::StripSeparators(const base::string16& number) {
13653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  const base::char16 kSeparators[] = {'-', ' ', '\0'};
13753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  base::string16 stripped;
13853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  base::RemoveChars(number, kSeparators, &stripped);
139e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  return stripped;
14053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
14153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
14253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)// static
14353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)base::string16 CreditCard::TypeForDisplay(const std::string& type) {
14453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  if (type == kAmericanExpressCard)
14553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_AMEX);
14653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  if (type == kDinersCard)
14753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_DINERS);
14853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  if (type == kDiscoverCard)
14953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_DISCOVER);
15053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  if (type == kJCBCard)
15153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_JCB);
15253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  if (type == kMasterCard)
15353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_MASTERCARD);
15453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  if (type == kUnionPay)
1557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_UNION_PAY);
156e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  if (type == kVisaCard)
15753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_VISA);
15853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
15953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  // If you hit this DCHECK, the above list of cases needs to be updated to
160e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  // include a new card.
161e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  DCHECK_EQ(kGenericCard, type);
16253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  return base::string16();
16353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
164e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
16553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)// static
16653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)int CreditCard::IconResourceId(const std::string& type) {
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  if (type == kAmericanExpressCard)
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return IDR_AUTOFILL_CC_AMEX;
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  if (type == kDinersCard)
170e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    return IDR_AUTOFILL_CC_DINERS;
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  if (type == kDiscoverCard)
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return IDR_AUTOFILL_CC_DISCOVER;
173e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  if (type == kJCBCard)
174e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    return IDR_AUTOFILL_CC_JCB;
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  if (type == kMasterCard)
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return IDR_AUTOFILL_CC_MASTERCARD;
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  if (type == kUnionPay)
178e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    return IDR_AUTOFILL_CC_GENERIC;  // Needs resource: http://crbug.com/259211
17953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  if (type == kVisaCard)
1807242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return IDR_AUTOFILL_CC_VISA;
18153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
18253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  // If you hit this DCHECK, the above list of cases needs to be updated to
18353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  // include a new card.
18453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  DCHECK_EQ(kGenericCard, type);
18553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  return IDR_AUTOFILL_CC_GENERIC;
18653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
1877242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
18853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)// static
18953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)std::string CreditCard::GetCreditCardType(const base::string16& number) {
19053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  // Credit card number specifications taken from:
19153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  // http://en.wikipedia.org/wiki/Credit_card_numbers,
19253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  // http://en.wikipedia.org/wiki/List_of_Issuer_Identification_Numbers,
19353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  // http://www.discovernetwork.com/merchants/images/Merchant_Marketing_PDF.pdf,
19453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  // http://www.regular-expressions.info/creditcard.html,
19553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  // http://developer.ean.com/general_info/Valid_Credit_Card_Types,
19653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  // http://www.bincodes.com/,
19753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  // http://www.fraudpractice.com/FL-binCC.html, and
19853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  // http://www.beachnet.com/~hstiles/cardtype.html
19953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  //
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // The last site is currently unavailable, but a cached version remains at
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // http://web.archive.org/web/20120923111349/http://www.beachnet.com/~hstiles/cardtype.html
20253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  //
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Card Type              Prefix(es)                      Length
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // ---------------------------------------------------------------
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Visa                   4                               13,16
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // American Express       34,37                           15
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Diners Club            300-305,3095,36,38-39           14
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Discover Card          6011,644-649,65                 16
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // JCB                    3528-3589                       16
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // MasterCard             51-55                           16
21153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  // UnionPay               62                              16-19
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Check for prefixes of length 1.
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  if (number.empty())
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return kGenericCard;
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  if (number[0] == '4')
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return kVisaCard;
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Check for prefixes of length 2.
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  if (number.size() < 2)
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return kGenericCard;
223f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  int first_two_digits = 0;
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  if (!base::StringToInt(number.substr(0, 2), &first_two_digits))
22609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return kGenericCard;
22709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  if (first_two_digits == 34 || first_two_digits == 37)
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return kAmericanExpressCard;
23009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
23109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)  if (first_two_digits == 36 ||
23209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)      first_two_digits == 38 ||
23309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)      first_two_digits == 39)
23409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return kDinersCard;
23509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
23609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)  if (first_two_digits >= 51 && first_two_digits <= 55)
23709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return kMasterCard;
23809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
23909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)  if (first_two_digits == 62)
24009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return kUnionPay;
241f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
242f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)  if (first_two_digits == 65)
243f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return kDiscoverCard;
244f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
24509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)  // Check for prefixes of length 3.
24609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)  if (number.size() < 3)
24709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return kGenericCard;
24809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
24909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)  int first_three_digits = 0;
25009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)  if (!base::StringToInt(number.substr(0, 3), &first_three_digits))
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return kGenericCard;
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  if (first_three_digits >= 300 && first_three_digits <= 305)
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return kDinersCard;
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  if (first_three_digits >= 644 && first_three_digits <= 649)
257f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    return kDiscoverCard;
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  // Check for prefixes of length 4.
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  if (number.size() < 4)
261f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    return kGenericCard;
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  int first_four_digits = 0;
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  if (!base::StringToInt(number.substr(0, 4), &first_four_digits))
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return kGenericCard;
266f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
267f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)  if (first_four_digits == 3095)
268f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return kDinersCard;
269f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
270f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)  if (first_four_digits >= 3528 && first_four_digits <= 3589)
271f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return kJCBCard;
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  if (first_four_digits == 6011)
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return kDiscoverCard;
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  return kGenericCard;
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
279e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochbase::string16 CreditCard::GetRawInfo(ServerFieldType type) const {
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  DCHECK_EQ(CREDIT_CARD, AutofillType(type).group());
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  switch (type) {
28253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    case CREDIT_CARD_NAME:
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return name_on_card_;
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case CREDIT_CARD_EXP_MONTH:
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return ExpirationMonthAsString();
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case CREDIT_CARD_EXP_2_DIGIT_YEAR:
28953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      return Expiration2DigitYearAsString();
290e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case CREDIT_CARD_EXP_4_DIGIT_YEAR:
29253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      return Expiration4DigitYearAsString();
293e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
29453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR: {
29553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      base::string16 month = ExpirationMonthAsString();
29653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      base::string16 year = Expiration2DigitYearAsString();
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (!month.empty() && !year.empty())
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return month + base::ASCIIToUTF16("/") + year;
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return base::string16();
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR: {
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      base::string16 month = ExpirationMonthAsString();
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      base::string16 year = Expiration4DigitYearAsString();
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (!month.empty() && !year.empty())
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return month + base::ASCIIToUTF16("/") + year;
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return base::string16();
308e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    }
309e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
3107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    case CREDIT_CARD_TYPE:
311e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      return TypeForDisplay();
312e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
313e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    case CREDIT_CARD_NUMBER:
314e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      return number_;
315e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
316e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    case CREDIT_CARD_VERIFICATION_CODE:
3177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci      // Chrome doesn't store credit card verification codes.
3187242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci      return base::string16();
319e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
320e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    default:
321e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      // ComputeDataPresentForArray will hit this repeatedly.
322e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      return base::string16();
323e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  }
324e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch}
325e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
326f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)void CreditCard::SetRawInfo(ServerFieldType type,
327c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                            const base::string16& value) {
328c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)  DCHECK_EQ(CREDIT_CARD, AutofillType(type).group());
329c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)  switch (type) {
330c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    case CREDIT_CARD_NAME:
331c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)      name_on_card_ = value;
332c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)      break;
333c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
334c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    case CREDIT_CARD_EXP_MONTH:
335f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)      SetExpirationMonthFromString(value, std::string());
336c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)      break;
337c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
338e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    case CREDIT_CARD_EXP_2_DIGIT_YEAR:
339e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      // This is a read-only attribute.
340e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      break;
341e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
342e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    case CREDIT_CARD_EXP_4_DIGIT_YEAR:
343e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      SetExpirationYearFromString(value);
344e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      break;
345e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
3467242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR:
3477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci      // This is a read-only attribute.
348e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      break;
349e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
3507242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR:
351e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      // This is a read-only attribute.
352f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)      break;
353e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
354e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    case CREDIT_CARD_TYPE:
355e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      // This is a read-only attribute, determined by the credit card number.
356e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch      break;
357e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
358f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    case CREDIT_CARD_NUMBER: {
359      // Don't change the real value if the input is an obfuscated string.
360      if (value.size() > 0 && value[0] != kCreditCardObfuscationSymbol)
361        SetNumber(value);
362      break;
363    }
364
365    case CREDIT_CARD_VERIFICATION_CODE:
366      // Chrome doesn't store the credit card verification code.
367      break;
368
369    default:
370      NOTREACHED() << "Attempting to set unknown info-type " << type;
371      break;
372  }
373}
374
375base::string16 CreditCard::GetInfo(const AutofillType& type,
376                                   const std::string& app_locale) const {
377  ServerFieldType storable_type = type.GetStorableType();
378  if (storable_type == CREDIT_CARD_NUMBER)
379    return StripSeparators(number_);
380
381  return GetRawInfo(storable_type);
382}
383
384bool CreditCard::SetInfo(const AutofillType& type,
385                         const base::string16& value,
386                         const std::string& app_locale) {
387  ServerFieldType storable_type = type.GetStorableType();
388  if (storable_type == CREDIT_CARD_NUMBER)
389    SetRawInfo(storable_type, StripSeparators(value));
390  else if (storable_type == CREDIT_CARD_EXP_MONTH)
391    SetExpirationMonthFromString(value, app_locale);
392  else
393    SetRawInfo(storable_type, value);
394
395  return true;
396}
397
398void CreditCard::GetMatchingTypes(const base::string16& text,
399                                  const std::string& app_locale,
400                                  ServerFieldTypeSet* matching_types) const {
401  FormGroup::GetMatchingTypes(text, app_locale, matching_types);
402
403  base::string16 card_number =
404      GetInfo(AutofillType(CREDIT_CARD_NUMBER), app_locale);
405  if (!card_number.empty() && StripSeparators(text) == card_number)
406    matching_types->insert(CREDIT_CARD_NUMBER);
407
408  int month;
409  if (ConvertMonth(text, app_locale, &month) && month != 0 &&
410      month == expiration_month_) {
411    matching_types->insert(CREDIT_CARD_EXP_MONTH);
412  }
413}
414
415const base::string16 CreditCard::Label() const {
416  base::string16 label;
417  if (number().empty())
418    return name_on_card_;  // No CC number, return name only.
419
420  base::string16 obfuscated_cc_number = ObfuscatedNumber();
421  if (!expiration_month_ || !expiration_year_)
422    return obfuscated_cc_number;  // No expiration date set.
423
424  // TODO(georgey): Internationalize date.
425  base::string16 formatted_date(ExpirationMonthAsString());
426  formatted_date.append(base::ASCIIToUTF16("/"));
427  formatted_date.append(Expiration4DigitYearAsString());
428
429  label = l10n_util::GetStringFUTF16(IDS_CREDIT_CARD_NUMBER_PREVIEW_FORMAT,
430                                     obfuscated_cc_number,
431                                     formatted_date);
432  return label;
433}
434
435void CreditCard::SetInfoForMonthInputType(const base::string16& value) {
436  // Check if |text| is "yyyy-mm" format first, and check normal month format.
437  if (!autofill::MatchesPattern(value,
438                                base::UTF8ToUTF16("^[0-9]{4}-[0-9]{1,2}$"))) {
439    return;
440  }
441
442  std::vector<base::string16> year_month;
443  base::SplitString(value, L'-', &year_month);
444  DCHECK_EQ((int)year_month.size(), 2);
445  int num = 0;
446  bool converted = false;
447  converted = base::StringToInt(year_month[0], &num);
448  DCHECK(converted);
449  SetExpirationYear(num);
450  converted = base::StringToInt(year_month[1], &num);
451  DCHECK(converted);
452  SetExpirationMonth(num);
453}
454
455base::string16 CreditCard::ObfuscatedNumber() const {
456  // If the number is shorter than four digits, there's no need to obfuscate it.
457  if (number_.size() < 4)
458    return number_;
459
460  base::string16 number = StripSeparators(number_);
461
462  // Avoid making very long obfuscated numbers.
463  size_t obfuscated_digits = std::min(kMaxObfuscationSize, number.size() - 4);
464  base::string16 result(obfuscated_digits, kCreditCardObfuscationSymbol);
465  return result.append(LastFourDigits());
466}
467
468base::string16 CreditCard::LastFourDigits() const {
469  static const size_t kNumLastDigits = 4;
470
471  base::string16 number = StripSeparators(number_);
472  if (number.size() < kNumLastDigits)
473    return base::string16();
474
475  return number.substr(number.size() - kNumLastDigits, kNumLastDigits);
476}
477
478base::string16 CreditCard::TypeForDisplay() const {
479  return CreditCard::TypeForDisplay(type_);
480}
481
482base::string16 CreditCard::TypeAndLastFourDigits() const {
483  base::string16 type = TypeForDisplay();
484  // TODO(estade): type may be empty, we probably want to return
485  // "Card - 1234" or something in that case.
486
487  base::string16 digits = LastFourDigits();
488  if (digits.empty())
489    return type;
490
491  // TODO(estade): i18n.
492  return type + base::ASCIIToUTF16(" - ") + digits;
493}
494
495void CreditCard::operator=(const CreditCard& credit_card) {
496  if (this == &credit_card)
497    return;
498
499  number_ = credit_card.number_;
500  name_on_card_ = credit_card.name_on_card_;
501  type_ = credit_card.type_;
502  expiration_month_ = credit_card.expiration_month_;
503  expiration_year_ = credit_card.expiration_year_;
504
505  set_guid(credit_card.guid());
506  set_origin(credit_card.origin());
507}
508
509bool CreditCard::UpdateFromImportedCard(const CreditCard& imported_card,
510                                        const std::string& app_locale) {
511  if (this->GetInfo(AutofillType(CREDIT_CARD_NUMBER), app_locale) !=
512          imported_card.GetInfo(AutofillType(CREDIT_CARD_NUMBER), app_locale)) {
513    return false;
514  }
515
516  // Heuristically aggregated data should never overwrite verified data.
517  // Instead, discard any heuristically aggregated credit cards that disagree
518  // with explicitly entered data, so that the UI is not cluttered with
519  // duplicate cards.
520  if (this->IsVerified() && !imported_card.IsVerified())
521    return true;
522
523  set_origin(imported_card.origin());
524
525  // Note that the card number is intentionally not updated, so as to preserve
526  // any formatting (i.e. separator characters).  Since the card number is not
527  // updated, there is no reason to update the card type, either.
528  if (!imported_card.name_on_card_.empty())
529    name_on_card_ = imported_card.name_on_card_;
530
531  // The expiration date for |imported_card| should always be set.
532  DCHECK(imported_card.expiration_month_ && imported_card.expiration_year_);
533  expiration_month_ = imported_card.expiration_month_;
534  expiration_year_ = imported_card.expiration_year_;
535
536  return true;
537}
538
539int CreditCard::Compare(const CreditCard& credit_card) const {
540  // The following CreditCard field types are the only types we store in the
541  // WebDB so far, so we're only concerned with matching these types in the
542  // credit card.
543  const ServerFieldType types[] = { CREDIT_CARD_NAME,
544                                    CREDIT_CARD_NUMBER,
545                                    CREDIT_CARD_EXP_MONTH,
546                                    CREDIT_CARD_EXP_4_DIGIT_YEAR };
547  for (size_t i = 0; i < arraysize(types); ++i) {
548    int comparison =
549        GetRawInfo(types[i]).compare(credit_card.GetRawInfo(types[i]));
550    if (comparison != 0)
551      return comparison;
552  }
553
554  return 0;
555}
556
557bool CreditCard::operator==(const CreditCard& credit_card) const {
558  return guid() == credit_card.guid() &&
559         origin() == credit_card.origin() &&
560         Compare(credit_card) == 0;
561}
562
563bool CreditCard::operator!=(const CreditCard& credit_card) const {
564  return !operator==(credit_card);
565}
566
567bool CreditCard::IsEmpty(const std::string& app_locale) const {
568  ServerFieldTypeSet types;
569  GetNonEmptyTypes(app_locale, &types);
570  return types.empty();
571}
572
573bool CreditCard::IsComplete() const {
574  return
575      autofill::IsValidCreditCardNumber(number_) &&
576      expiration_month_ != 0 &&
577      expiration_year_ != 0;
578}
579
580bool CreditCard::IsValid() const {
581  return autofill::IsValidCreditCardNumber(number_) &&
582         autofill::IsValidCreditCardExpirationDate(
583             expiration_year_, expiration_month_, base::Time::Now());
584}
585
586void CreditCard::GetSupportedTypes(ServerFieldTypeSet* supported_types) const {
587  supported_types->insert(CREDIT_CARD_NAME);
588  supported_types->insert(CREDIT_CARD_NUMBER);
589  supported_types->insert(CREDIT_CARD_TYPE);
590  supported_types->insert(CREDIT_CARD_EXP_MONTH);
591  supported_types->insert(CREDIT_CARD_EXP_2_DIGIT_YEAR);
592  supported_types->insert(CREDIT_CARD_EXP_4_DIGIT_YEAR);
593  supported_types->insert(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR);
594  supported_types->insert(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR);
595}
596
597base::string16 CreditCard::ExpirationMonthAsString() const {
598  if (expiration_month_ == 0)
599    return base::string16();
600
601  base::string16 month = base::IntToString16(expiration_month_);
602  if (expiration_month_ >= 10)
603    return month;
604
605  base::string16 zero = base::ASCIIToUTF16("0");
606  zero.append(month);
607  return zero;
608}
609
610base::string16 CreditCard::Expiration4DigitYearAsString() const {
611  if (expiration_year_ == 0)
612    return base::string16();
613
614  return base::IntToString16(Expiration4DigitYear());
615}
616
617base::string16 CreditCard::Expiration2DigitYearAsString() const {
618  if (expiration_year_ == 0)
619    return base::string16();
620
621  return base::IntToString16(Expiration2DigitYear());
622}
623
624void CreditCard::SetExpirationMonthFromString(const base::string16& text,
625                                              const std::string& app_locale) {
626  int month;
627  if (!ConvertMonth(text, app_locale, &month))
628    return;
629
630  SetExpirationMonth(month);
631}
632
633void CreditCard::SetExpirationYearFromString(const base::string16& text) {
634  int year;
635  if (!ConvertYear(text, &year))
636    return;
637
638  SetExpirationYear(year);
639}
640
641void CreditCard::SetNumber(const base::string16& number) {
642  number_ = number;
643  type_ = GetCreditCardType(StripSeparators(number_));
644}
645
646void CreditCard::SetExpirationMonth(int expiration_month) {
647  if (expiration_month < 0 || expiration_month > 12)
648    return;
649
650  expiration_month_ = expiration_month;
651}
652
653void CreditCard::SetExpirationYear(int expiration_year) {
654  if (expiration_year != 0 &&
655      (expiration_year < 2006 || expiration_year > 10000)) {
656    return;
657  }
658
659  expiration_year_ = expiration_year;
660}
661
662// So we can compare CreditCards with EXPECT_EQ().
663std::ostream& operator<<(std::ostream& os, const CreditCard& credit_card) {
664  return os
665      << base::UTF16ToUTF8(credit_card.Label())
666      << " "
667      << credit_card.guid()
668      << " "
669      << credit_card.origin()
670      << " "
671      << base::UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_NAME))
672      << " "
673      << base::UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_TYPE))
674      << " "
675      << base::UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_NUMBER))
676      << " "
677      << base::UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_EXP_MONTH))
678      << " "
679      << base::UTF16ToUTF8(
680             credit_card.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
681}
682
683// These values must match the values in WebKitPlatformSupportImpl in
684// webkit/glue. We send these strings to WebKit, which then asks
685// WebKitPlatformSupportImpl to load the image data.
686const char* const kAmericanExpressCard = "americanExpressCC";
687const char* const kDinersCard = "dinersCC";
688const char* const kDiscoverCard = "discoverCC";
689const char* const kGenericCard = "genericCC";
690const char* const kJCBCard = "jcbCC";
691const char* const kMasterCard = "masterCardCC";
692const char* const kUnionPay = "unionPayCC";
693const char* const kVisaCard = "visaCC";
694
695}  // namespace autofill
696