credit_card.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "components/autofill/core/browser/credit_card.h"
6
7#include <stddef.h>
8
9#include <ostream>
10#include <string>
11
12#include "base/basictypes.h"
13#include "base/guid.h"
14#include "base/logging.h"
15#include "base/strings/string16.h"
16#include "base/strings/string_number_conversions.h"
17#include "base/strings/string_split.h"
18#include "base/strings/string_util.h"
19#include "base/strings/utf_string_conversions.h"
20#include "base/time/time.h"
21#include "components/autofill/core/browser/autofill_field.h"
22#include "components/autofill/core/browser/autofill_regexes.h"
23#include "components/autofill/core/browser/autofill_type.h"
24#include "components/autofill/core/browser/field_types.h"
25#include "components/autofill/core/browser/validation.h"
26#include "components/autofill/core/common/form_field_data.h"
27#include "grit/component_strings.h"
28#include "grit/webkit_resources.h"
29#include "third_party/icu/public/common/unicode/uloc.h"
30#include "third_party/icu/public/i18n/unicode/dtfmtsym.h"
31#include "ui/base/l10n/l10n_util.h"
32
33namespace autofill {
34
35namespace {
36
37const char16 kCreditCardObfuscationSymbol = '*';
38
39// This is the maximum obfuscated symbols displayed.
40// It is introduced to avoid rare cases where the credit card number is
41// too large and fills the screen.
42const size_t kMaxObfuscationSize = 20;
43
44bool ConvertYear(const base::string16& year, int* num) {
45  // If the |year| is empty, clear the stored value.
46  if (year.empty()) {
47    *num = 0;
48    return true;
49  }
50
51  // Try parsing the |year| as a number.
52  if (base::StringToInt(year, num))
53    return true;
54
55  *num = 0;
56  return false;
57}
58
59bool ConvertMonth(const base::string16& month,
60                  const std::string& app_locale,
61                  int* num) {
62  // If the |month| is empty, clear the stored value.
63  if (month.empty()) {
64    *num = 0;
65    return true;
66  }
67
68  // Try parsing the |month| as a number.
69  if (base::StringToInt(month, num))
70    return true;
71
72  // If the locale is unknown, give up.
73  if (app_locale.empty())
74    return false;
75
76  // Otherwise, try parsing the |month| as a named month, e.g. "January" or
77  // "Jan".
78  base::string16 lowercased_month = StringToLowerASCII(month);
79
80  UErrorCode status = U_ZERO_ERROR;
81  icu::Locale locale(app_locale.c_str());
82  icu::DateFormatSymbols date_format_symbols(locale, status);
83  DCHECK(status == U_ZERO_ERROR || status == U_USING_FALLBACK_WARNING ||
84         status == U_USING_DEFAULT_WARNING);
85
86  int32_t num_months;
87  const icu::UnicodeString* months = date_format_symbols.getMonths(num_months);
88  for (int32_t i = 0; i < num_months; ++i) {
89    const base::string16 icu_month = base::string16(months[i].getBuffer(),
90                                        months[i].length());
91    if (lowercased_month == StringToLowerASCII(icu_month)) {
92      *num = i + 1;  // Adjust from 0-indexed to 1-indexed.
93      return true;
94    }
95  }
96
97  months = date_format_symbols.getShortMonths(num_months);
98  for (int32_t i = 0; i < num_months; ++i) {
99    const base::string16 icu_month = base::string16(months[i].getBuffer(),
100                                        months[i].length());
101    if (lowercased_month == StringToLowerASCII(icu_month)) {
102      *num = i + 1;  // Adjust from 0-indexed to 1-indexed.
103      return true;
104    }
105  }
106
107  *num = 0;
108  return false;
109}
110
111}  // namespace
112
113CreditCard::CreditCard(const std::string& guid, const std::string& origin)
114    : AutofillDataModel(guid, origin),
115      type_(kGenericCard),
116      expiration_month_(0),
117      expiration_year_(0) {
118}
119
120CreditCard::CreditCard()
121    : AutofillDataModel(base::GenerateGUID(), std::string()),
122      type_(kGenericCard),
123      expiration_month_(0),
124      expiration_year_(0) {
125}
126
127CreditCard::CreditCard(const CreditCard& credit_card)
128    : AutofillDataModel(std::string(), std::string()) {
129  operator=(credit_card);
130}
131
132CreditCard::~CreditCard() {}
133
134// static
135const base::string16 CreditCard::StripSeparators(const base::string16& number) {
136  const char16 kSeparators[] = {'-', ' ', '\0'};
137  base::string16 stripped;
138  RemoveChars(number, kSeparators, &stripped);
139  return stripped;
140}
141
142// static
143base::string16 CreditCard::TypeForDisplay(const std::string& type) {
144  if (type == kAmericanExpressCard)
145    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_AMEX);
146  if (type == kDinersCard)
147    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_DINERS);
148  if (type == kDiscoverCard)
149    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_DISCOVER);
150  if (type == kJCBCard)
151    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_JCB);
152  if (type == kMasterCard)
153    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_MASTERCARD);
154  if (type == kUnionPay)
155    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_UNION_PAY);
156  if (type == kVisaCard)
157    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_VISA);
158
159  // If you hit this DCHECK, the above list of cases needs to be updated to
160  // include a new card.
161  DCHECK_EQ(kGenericCard, type);
162  return base::string16();
163}
164
165// static
166int CreditCard::IconResourceId(const std::string& type) {
167  if (type == kAmericanExpressCard)
168    return IDR_AUTOFILL_CC_AMEX;
169  if (type == kDinersCard)
170    return IDR_AUTOFILL_CC_DINERS;
171  if (type == kDiscoverCard)
172    return IDR_AUTOFILL_CC_DISCOVER;
173  if (type == kJCBCard)
174    return IDR_AUTOFILL_CC_JCB;
175  if (type == kMasterCard)
176    return IDR_AUTOFILL_CC_MASTERCARD;
177  if (type == kUnionPay)
178    return IDR_AUTOFILL_CC_GENERIC;  // Needs resource: http://crbug.com/259211
179  if (type == kVisaCard)
180    return IDR_AUTOFILL_CC_VISA;
181
182  // If you hit this DCHECK, the above list of cases needs to be updated to
183  // include a new card.
184  DCHECK_EQ(kGenericCard, type);
185  return IDR_AUTOFILL_CC_GENERIC;
186}
187
188// static
189std::string CreditCard::GetCreditCardType(const base::string16& number) {
190  // Credit card number specifications taken from:
191  // http://en.wikipedia.org/wiki/Credit_card_numbers,
192  // http://en.wikipedia.org/wiki/List_of_Issuer_Identification_Numbers,
193  // http://www.discovernetwork.com/merchants/images/Merchant_Marketing_PDF.pdf,
194  // http://www.regular-expressions.info/creditcard.html,
195  // http://developer.ean.com/general_info/Valid_Credit_Card_Types,
196  // http://www.bincodes.com/,
197  // http://www.fraudpractice.com/FL-binCC.html, and
198  // http://www.beachnet.com/~hstiles/cardtype.html
199  //
200  // The last site is currently unavailable, but a cached version remains at
201  // http://web.archive.org/web/20120923111349/http://www.beachnet.com/~hstiles/cardtype.html
202  //
203  // Card Type              Prefix(es)                      Length
204  // ---------------------------------------------------------------
205  // Visa                   4                               13,16
206  // American Express       34,37                           15
207  // Diners Club            300-305,3095,36,38-39           14
208  // Discover Card          6011,644-649,65                 16
209  // JCB                    3528-3589                       16
210  // MasterCard             51-55                           16
211  // UnionPay               62                              16-19
212
213  // Check for prefixes of length 1.
214  if (number.empty())
215    return kGenericCard;
216
217  if (number[0] == '4')
218    return kVisaCard;
219
220  // Check for prefixes of length 2.
221  if (number.size() < 2)
222    return kGenericCard;
223
224  int first_two_digits = 0;
225  if (!base::StringToInt(number.substr(0, 2), &first_two_digits))
226    return kGenericCard;
227
228  if (first_two_digits == 34 || first_two_digits == 37)
229    return kAmericanExpressCard;
230
231  if (first_two_digits == 36 ||
232      first_two_digits == 38 ||
233      first_two_digits == 39)
234    return kDinersCard;
235
236  if (first_two_digits >= 51 && first_two_digits <= 55)
237    return kMasterCard;
238
239  if (first_two_digits == 62)
240    return kUnionPay;
241
242  if (first_two_digits == 65)
243    return kDiscoverCard;
244
245  // Check for prefixes of length 3.
246  if (number.size() < 3)
247    return kGenericCard;
248
249  int first_three_digits = 0;
250  if (!base::StringToInt(number.substr(0, 3), &first_three_digits))
251    return kGenericCard;
252
253  if (first_three_digits >= 300 && first_three_digits <= 305)
254    return kDinersCard;
255
256  if (first_three_digits >= 644 && first_three_digits <= 649)
257    return kDiscoverCard;
258
259  // Check for prefixes of length 4.
260  if (number.size() < 4)
261    return kGenericCard;
262
263  int first_four_digits = 0;
264  if (!base::StringToInt(number.substr(0, 4), &first_four_digits))
265    return kGenericCard;
266
267  if (first_four_digits == 3095)
268    return kDinersCard;
269
270  if (first_four_digits >= 3528 && first_four_digits <= 3589)
271    return kJCBCard;
272
273  if (first_four_digits == 6011)
274    return kDiscoverCard;
275
276  return kGenericCard;
277}
278
279base::string16 CreditCard::GetRawInfo(AutofillFieldType type) const {
280  switch (type) {
281    case CREDIT_CARD_NAME:
282      return name_on_card_;
283
284    case CREDIT_CARD_EXP_MONTH:
285      return ExpirationMonthAsString();
286
287    case CREDIT_CARD_EXP_2_DIGIT_YEAR:
288      return Expiration2DigitYearAsString();
289
290    case CREDIT_CARD_EXP_4_DIGIT_YEAR:
291      return Expiration4DigitYearAsString();
292
293    case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR: {
294      base::string16 month = ExpirationMonthAsString();
295      base::string16 year = Expiration2DigitYearAsString();
296      if (!month.empty() && !year.empty())
297        return month + ASCIIToUTF16("/") + year;
298      return base::string16();
299    }
300
301    case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR: {
302      base::string16 month = ExpirationMonthAsString();
303      base::string16 year = Expiration4DigitYearAsString();
304      if (!month.empty() && !year.empty())
305        return month + ASCIIToUTF16("/") + year;
306      return base::string16();
307    }
308
309    case CREDIT_CARD_TYPE:
310      return TypeForDisplay();
311
312    case CREDIT_CARD_NUMBER:
313      return number_;
314
315    case CREDIT_CARD_VERIFICATION_CODE:
316      // Chrome doesn't store credit card verification codes.
317      return base::string16();
318
319    default:
320      // ComputeDataPresentForArray will hit this repeatedly.
321      return base::string16();
322  }
323}
324
325void CreditCard::SetRawInfo(AutofillFieldType type,
326                            const base::string16& value) {
327  switch (type) {
328    case CREDIT_CARD_NAME:
329      name_on_card_ = value;
330      break;
331
332    case CREDIT_CARD_EXP_MONTH:
333      SetExpirationMonthFromString(value, std::string());
334      break;
335
336    case CREDIT_CARD_EXP_2_DIGIT_YEAR:
337      // This is a read-only attribute.
338      break;
339
340    case CREDIT_CARD_EXP_4_DIGIT_YEAR:
341      SetExpirationYearFromString(value);
342      break;
343
344    case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR:
345      // This is a read-only attribute.
346      break;
347
348    case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR:
349      // This is a read-only attribute.
350      break;
351
352    case CREDIT_CARD_TYPE:
353      // This is a read-only attribute, determined by the credit card number.
354      break;
355
356    case CREDIT_CARD_NUMBER: {
357      // Don't change the real value if the input is an obfuscated string.
358      if (value.size() > 0 && value[0] != kCreditCardObfuscationSymbol)
359        SetNumber(value);
360      break;
361    }
362
363    case CREDIT_CARD_VERIFICATION_CODE:
364      // Chrome doesn't store the credit card verification code.
365      break;
366
367    default:
368      NOTREACHED() << "Attempting to set unknown info-type " << type;
369      break;
370  }
371}
372
373base::string16 CreditCard::GetInfo(AutofillFieldType type,
374                                   const std::string& app_locale) const {
375  if (type == CREDIT_CARD_NUMBER)
376    return StripSeparators(number_);
377
378  return GetRawInfo(type);
379}
380
381bool CreditCard::SetInfo(AutofillFieldType type,
382                         const base::string16& value,
383                         const std::string& app_locale) {
384  if (type == CREDIT_CARD_NUMBER)
385    SetRawInfo(type, StripSeparators(value));
386  else if (type == CREDIT_CARD_EXP_MONTH)
387    SetExpirationMonthFromString(value, app_locale);
388  else
389    SetRawInfo(type, value);
390
391  return true;
392}
393
394void CreditCard::GetMatchingTypes(const base::string16& text,
395                                  const std::string& app_locale,
396                                  FieldTypeSet* matching_types) const {
397  FormGroup::GetMatchingTypes(text, app_locale, matching_types);
398
399  base::string16 card_number = GetInfo(CREDIT_CARD_NUMBER, app_locale);
400  if (!card_number.empty() && StripSeparators(text) == card_number)
401    matching_types->insert(CREDIT_CARD_NUMBER);
402
403  int month;
404  if (ConvertMonth(text, app_locale, &month) && month != 0 &&
405      month == expiration_month_) {
406    matching_types->insert(CREDIT_CARD_EXP_MONTH);
407  }
408}
409
410const base::string16 CreditCard::Label() const {
411  base::string16 label;
412  if (number().empty())
413    return name_on_card_;  // No CC number, return name only.
414
415  base::string16 obfuscated_cc_number = ObfuscatedNumber();
416  if (!expiration_month_ || !expiration_year_)
417    return obfuscated_cc_number;  // No expiration date set.
418
419  // TODO(georgey): Internationalize date.
420  base::string16 formatted_date(ExpirationMonthAsString());
421  formatted_date.append(ASCIIToUTF16("/"));
422  formatted_date.append(Expiration4DigitYearAsString());
423
424  label = l10n_util::GetStringFUTF16(IDS_CREDIT_CARD_NUMBER_PREVIEW_FORMAT,
425                                     obfuscated_cc_number,
426                                     formatted_date);
427  return label;
428}
429
430void CreditCard::SetInfoForMonthInputType(const base::string16& value) {
431  // Check if |text| is "yyyy-mm" format first, and check normal month format.
432  if (!autofill::MatchesPattern(value, UTF8ToUTF16("^[0-9]{4}-[0-9]{1,2}$")))
433    return;
434
435  std::vector<base::string16> year_month;
436  base::SplitString(value, L'-', &year_month);
437  DCHECK_EQ((int)year_month.size(), 2);
438  int num = 0;
439  bool converted = false;
440  converted = base::StringToInt(year_month[0], &num);
441  DCHECK(converted);
442  SetExpirationYear(num);
443  converted = base::StringToInt(year_month[1], &num);
444  DCHECK(converted);
445  SetExpirationMonth(num);
446}
447
448base::string16 CreditCard::ObfuscatedNumber() const {
449  // If the number is shorter than four digits, there's no need to obfuscate it.
450  if (number_.size() < 4)
451    return number_;
452
453  base::string16 number = StripSeparators(number_);
454
455  // Avoid making very long obfuscated numbers.
456  size_t obfuscated_digits = std::min(kMaxObfuscationSize, number.size() - 4);
457  base::string16 result(obfuscated_digits, kCreditCardObfuscationSymbol);
458  return result.append(LastFourDigits());
459}
460
461base::string16 CreditCard::LastFourDigits() const {
462  static const size_t kNumLastDigits = 4;
463
464  base::string16 number = StripSeparators(number_);
465  if (number.size() < kNumLastDigits)
466    return base::string16();
467
468  return number.substr(number.size() - kNumLastDigits, kNumLastDigits);
469}
470
471base::string16 CreditCard::TypeForDisplay() const {
472  return CreditCard::TypeForDisplay(type_);
473}
474
475base::string16 CreditCard::TypeAndLastFourDigits() const {
476  base::string16 type = TypeForDisplay();
477  // TODO(estade): type may be empty, we probably want to return
478  // "Card - 1234" or something in that case.
479
480  base::string16 digits = LastFourDigits();
481  if (digits.empty())
482    return type;
483
484  // TODO(estade): i18n.
485  return type + ASCIIToUTF16(" - ") + digits;
486}
487
488void CreditCard::operator=(const CreditCard& credit_card) {
489  if (this == &credit_card)
490    return;
491
492  number_ = credit_card.number_;
493  name_on_card_ = credit_card.name_on_card_;
494  type_ = credit_card.type_;
495  expiration_month_ = credit_card.expiration_month_;
496  expiration_year_ = credit_card.expiration_year_;
497
498  set_guid(credit_card.guid());
499  set_origin(credit_card.origin());
500}
501
502bool CreditCard::UpdateFromImportedCard(const CreditCard& imported_card,
503                                        const std::string& app_locale) {
504  if (this->GetInfo(CREDIT_CARD_NUMBER, app_locale) !=
505          imported_card.GetInfo(CREDIT_CARD_NUMBER, app_locale)) {
506    return false;
507  }
508
509  // Heuristically aggregated data should never overwrite verified data.
510  // Instead, discard any heuristically aggregated credit cards that disagree
511  // with explicitly entered data, so that the UI is not cluttered with
512  // duplicate cards.
513  if (this->IsVerified() && !imported_card.IsVerified())
514    return true;
515
516  set_origin(imported_card.origin());
517
518  // Note that the card number is intentionally not updated, so as to preserve
519  // any formatting (i.e. separator characters).  Since the card number is not
520  // updated, there is no reason to update the card type, either.
521  if (!imported_card.name_on_card_.empty())
522    name_on_card_ = imported_card.name_on_card_;
523
524  // The expiration date for |imported_card| should always be set.
525  DCHECK(imported_card.expiration_month_ && imported_card.expiration_year_);
526  expiration_month_ = imported_card.expiration_month_;
527  expiration_year_ = imported_card.expiration_year_;
528
529  return true;
530}
531
532void CreditCard::FillFormField(const AutofillField& field,
533                               size_t /*variant*/,
534                               const std::string& app_locale,
535                               FormFieldData* field_data) const {
536  DCHECK_EQ(AutofillType::CREDIT_CARD, AutofillType(field.type()).group());
537  DCHECK(field_data);
538
539  if (field_data->form_control_type == "select-one") {
540    FillSelectControl(field.type(), app_locale, field_data);
541  } else if (field_data->form_control_type == "month") {
542    // HTML5 input="month" consists of year-month.
543    base::string16 year = GetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, app_locale);
544    base::string16 month = GetInfo(CREDIT_CARD_EXP_MONTH, app_locale);
545    if (!year.empty() && !month.empty()) {
546      // Fill the value only if |this| includes both year and month
547      // information.
548      field_data->value = year + ASCIIToUTF16("-") + month;
549    }
550  } else {
551    field_data->value = GetInfo(field.type(), app_locale);
552  }
553}
554
555int CreditCard::Compare(const CreditCard& credit_card) const {
556  // The following CreditCard field types are the only types we store in the
557  // WebDB so far, so we're only concerned with matching these types in the
558  // credit card.
559  const AutofillFieldType types[] = { CREDIT_CARD_NAME,
560                                      CREDIT_CARD_NUMBER,
561                                      CREDIT_CARD_EXP_MONTH,
562                                      CREDIT_CARD_EXP_4_DIGIT_YEAR };
563  for (size_t index = 0; index < arraysize(types); ++index) {
564    int comparison = GetRawInfo(types[index]).compare(
565        credit_card.GetRawInfo(types[index]));
566    if (comparison != 0)
567      return comparison;
568  }
569
570  return 0;
571}
572
573bool CreditCard::operator==(const CreditCard& credit_card) const {
574  return guid() == credit_card.guid() &&
575         origin() == credit_card.origin() &&
576         Compare(credit_card) == 0;
577}
578
579bool CreditCard::operator!=(const CreditCard& credit_card) const {
580  return !operator==(credit_card);
581}
582
583bool CreditCard::IsEmpty(const std::string& app_locale) const {
584  FieldTypeSet types;
585  GetNonEmptyTypes(app_locale, &types);
586  return types.empty();
587}
588
589bool CreditCard::IsComplete() const {
590  return
591      autofill::IsValidCreditCardNumber(number_) &&
592      expiration_month_ != 0 &&
593      expiration_year_ != 0;
594}
595
596bool CreditCard::IsValid() const {
597  return autofill::IsValidCreditCardNumber(number_) &&
598         autofill::IsValidCreditCardExpirationDate(
599             expiration_year_, expiration_month_, base::Time::Now());
600}
601
602void CreditCard::GetSupportedTypes(FieldTypeSet* supported_types) const {
603  supported_types->insert(CREDIT_CARD_NAME);
604  supported_types->insert(CREDIT_CARD_NUMBER);
605  supported_types->insert(CREDIT_CARD_TYPE);
606  supported_types->insert(CREDIT_CARD_EXP_MONTH);
607  supported_types->insert(CREDIT_CARD_EXP_2_DIGIT_YEAR);
608  supported_types->insert(CREDIT_CARD_EXP_4_DIGIT_YEAR);
609  supported_types->insert(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR);
610  supported_types->insert(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR);
611}
612
613base::string16 CreditCard::ExpirationMonthAsString() const {
614  if (expiration_month_ == 0)
615    return base::string16();
616
617  base::string16 month = base::IntToString16(expiration_month_);
618  if (expiration_month_ >= 10)
619    return month;
620
621  base::string16 zero = ASCIIToUTF16("0");
622  zero.append(month);
623  return zero;
624}
625
626base::string16 CreditCard::Expiration4DigitYearAsString() const {
627  if (expiration_year_ == 0)
628    return base::string16();
629
630  return base::IntToString16(Expiration4DigitYear());
631}
632
633base::string16 CreditCard::Expiration2DigitYearAsString() const {
634  if (expiration_year_ == 0)
635    return base::string16();
636
637  return base::IntToString16(Expiration2DigitYear());
638}
639
640void CreditCard::SetExpirationMonthFromString(const base::string16& text,
641                                              const std::string& app_locale) {
642  int month;
643  if (!ConvertMonth(text, app_locale, &month))
644    return;
645
646  SetExpirationMonth(month);
647}
648
649void CreditCard::SetExpirationYearFromString(const base::string16& text) {
650  int year;
651  if (!ConvertYear(text, &year))
652    return;
653
654  SetExpirationYear(year);
655}
656
657void CreditCard::SetNumber(const base::string16& number) {
658  number_ = number;
659  type_ = GetCreditCardType(StripSeparators(number_));
660}
661
662void CreditCard::SetExpirationMonth(int expiration_month) {
663  if (expiration_month < 0 || expiration_month > 12)
664    return;
665
666  expiration_month_ = expiration_month;
667}
668
669void CreditCard::SetExpirationYear(int expiration_year) {
670  if (expiration_year != 0 &&
671      (expiration_year < 2006 || expiration_year > 10000)) {
672    return;
673  }
674
675  expiration_year_ = expiration_year;
676}
677
678// So we can compare CreditCards with EXPECT_EQ().
679std::ostream& operator<<(std::ostream& os, const CreditCard& credit_card) {
680  return os
681      << UTF16ToUTF8(credit_card.Label())
682      << " "
683      << credit_card.guid()
684      << " "
685      << credit_card.origin()
686      << " "
687      << UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_NAME))
688      << " "
689      << UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_TYPE))
690      << " "
691      << UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_NUMBER))
692      << " "
693      << UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_EXP_MONTH))
694      << " "
695      << UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
696}
697
698// These values must match the values in WebKitPlatformSupportImpl in
699// webkit/glue. We send these strings to WebKit, which then asks
700// WebKitPlatformSupportImpl to load the image data.
701const char* const kAmericanExpressCard = "americanExpressCC";
702const char* const kDinersCard = "dinersCC";
703const char* const kDiscoverCard = "discoverCC";
704const char* const kGenericCard = "genericCC";
705const char* const kJCBCard = "jcbCC";
706const char* const kMasterCard = "masterCardCC";
707const char* const kUnionPay = "unionPayCC";
708const char* const kVisaCard = "visaCC";
709
710}  // namespace autofill
711