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