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.
5 #include "components/autofill/core/browser/credit_card.h"
13 #include "base/basictypes.h"
14 #include "base/guid.h"
15 #include "base/logging.h"
16 #include "base/strings/string16.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_split.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "base/time/time.h"
22 #include "components/autofill/core/browser/autofill_field.h"
23 #include "components/autofill/core/browser/autofill_regexes.h"
24 #include "components/autofill/core/browser/autofill_type.h"
25 #include "components/autofill/core/browser/validation.h"
26 #include "components/autofill/core/common/form_field_data.h"
27 #include "grit/components_scaled_resources.h"
28 #include "grit/components_strings.h"
29 #include "third_party/icu/source/common/unicode/uloc.h"
30 #include "third_party/icu/source/i18n/unicode/dtfmtsym.h"
31 #include "ui/base/l10n/l10n_util.h"
37 const base::char16 kCreditCardObfuscationSymbol
= '*';
39 bool ConvertYear(const base::string16
& year
, int* num
) {
40 // If the |year| is empty, clear the stored value.
46 // Try parsing the |year| as a number.
47 if (base::StringToInt(year
, num
))
54 bool ConvertMonth(const base::string16
& month
,
55 const std::string
& app_locale
,
57 // If the |month| is empty, clear the stored value.
63 // Try parsing the |month| as a number.
64 if (base::StringToInt(month
, num
))
67 // If the locale is unknown, give up.
68 if (app_locale
.empty())
71 // Otherwise, try parsing the |month| as a named month, e.g. "January" or
73 base::string16 lowercased_month
= base::StringToLowerASCII(month
);
75 UErrorCode status
= U_ZERO_ERROR
;
76 icu::Locale
locale(app_locale
.c_str());
77 icu::DateFormatSymbols
date_format_symbols(locale
, status
);
78 DCHECK(status
== U_ZERO_ERROR
|| status
== U_USING_FALLBACK_WARNING
||
79 status
== U_USING_DEFAULT_WARNING
);
82 const icu::UnicodeString
* months
= date_format_symbols
.getMonths(num_months
);
83 for (int32_t i
= 0; i
< num_months
; ++i
) {
84 const base::string16 icu_month
= base::string16(months
[i
].getBuffer(),
86 if (lowercased_month
== base::StringToLowerASCII(icu_month
)) {
87 *num
= i
+ 1; // Adjust from 0-indexed to 1-indexed.
92 months
= date_format_symbols
.getShortMonths(num_months
);
93 for (int32_t i
= 0; i
< num_months
; ++i
) {
94 const base::string16 icu_month
= base::string16(months
[i
].getBuffer(),
96 if (lowercased_month
== base::StringToLowerASCII(icu_month
)) {
97 *num
= i
+ 1; // Adjust from 0-indexed to 1-indexed.
106 base::string16
TypeForFill(const std::string
& type
) {
107 if (type
== kAmericanExpressCard
)
108 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_AMEX
);
109 if (type
== kDinersCard
)
110 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_DINERS
);
111 if (type
== kDiscoverCard
)
112 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_DISCOVER
);
113 if (type
== kJCBCard
)
114 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_JCB
);
115 if (type
== kMasterCard
)
116 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_MASTERCARD
);
117 if (type
== kUnionPay
)
118 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_UNION_PAY
);
119 if (type
== kVisaCard
)
120 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_VISA
);
122 // If you hit this DCHECK, the above list of cases needs to be updated to
123 // include a new card.
124 DCHECK_EQ(kGenericCard
, type
);
125 return base::string16();
130 CreditCard::CreditCard(const std::string
& guid
, const std::string
& origin
)
131 : AutofillDataModel(guid
, origin
),
132 record_type_(LOCAL_CARD
),
134 expiration_month_(0),
139 CreditCard::CreditCard(const base::string16
& card_number
,
140 int expiration_month
,
142 : AutofillDataModel(std::string(), std::string()),
143 record_type_(LOCAL_CARD
),
145 SetNumber(card_number
);
146 SetExpirationMonth(expiration_month
);
147 SetExpirationYear(expiration_year
);
150 CreditCard::CreditCard(RecordType type
, const std::string
& server_id
)
151 : AutofillDataModel(base::GenerateGUID(), std::string()),
154 expiration_month_(0),
156 server_id_(server_id
),
158 DCHECK(type
== MASKED_SERVER_CARD
|| type
== FULL_SERVER_CARD
);
161 CreditCard::CreditCard()
162 : AutofillDataModel(base::GenerateGUID(), std::string()),
163 record_type_(LOCAL_CARD
),
165 expiration_month_(0),
170 CreditCard::CreditCard(const CreditCard
& credit_card
)
171 : AutofillDataModel(std::string(), std::string()) {
172 operator=(credit_card
);
175 CreditCard::~CreditCard() {}
178 const base::string16
CreditCard::StripSeparators(const base::string16
& number
) {
179 base::string16 stripped
;
180 base::RemoveChars(number
, base::ASCIIToUTF16("- "), &stripped
);
185 base::string16
CreditCard::TypeForDisplay(const std::string
& type
) {
186 if (kGenericCard
== type
)
187 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_GENERIC
);
188 if (kAmericanExpressCard
== type
)
189 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_AMEX_SHORT
);
191 return ::autofill::TypeForFill(type
);
194 // This method is not compiled on iOS because the resources are not used and
195 // should not be shipped.
198 int CreditCard::IconResourceId(const std::string
& type
) {
199 if (type
== kAmericanExpressCard
)
200 return IDR_AUTOFILL_CC_AMEX
;
201 if (type
== kDinersCard
)
202 return IDR_AUTOFILL_CC_GENERIC
;
203 if (type
== kDiscoverCard
)
204 return IDR_AUTOFILL_CC_DISCOVER
;
205 if (type
== kJCBCard
)
206 return IDR_AUTOFILL_CC_GENERIC
;
207 if (type
== kMasterCard
)
208 return IDR_AUTOFILL_CC_MASTERCARD
;
209 if (type
== kUnionPay
)
210 return IDR_AUTOFILL_CC_GENERIC
;
211 if (type
== kVisaCard
)
212 return IDR_AUTOFILL_CC_VISA
;
214 // If you hit this DCHECK, the above list of cases needs to be updated to
215 // include a new card.
216 DCHECK_EQ(kGenericCard
, type
);
217 return IDR_AUTOFILL_CC_GENERIC
;
219 #endif // #if !defined(OS_IOS)
222 const char* CreditCard::GetCreditCardType(const base::string16
& number
) {
223 // Credit card number specifications taken from:
224 // http://en.wikipedia.org/wiki/Credit_card_numbers,
225 // http://en.wikipedia.org/wiki/List_of_Issuer_Identification_Numbers,
226 // http://www.discovernetwork.com/merchants/images/Merchant_Marketing_PDF.pdf,
227 // http://www.regular-expressions.info/creditcard.html,
228 // http://developer.ean.com/general_info/Valid_Credit_Card_Types,
229 // http://www.bincodes.com/,
230 // http://www.fraudpractice.com/FL-binCC.html, and
231 // http://www.beachnet.com/~hstiles/cardtype.html
233 // The last site is currently unavailable, but a cached version remains at
234 // http://web.archive.org/web/20120923111349/http://www.beachnet.com/~hstiles/cardtype.html
236 // Card Type Prefix(es) Length
237 // ---------------------------------------------------------------
239 // American Express 34,37 15
240 // Diners Club 300-305,3095,36,38-39 14
241 // Discover Card 6011,644-649,65 16
243 // MasterCard 51-55 16
246 // Check for prefixes of length 1.
250 if (number
[0] == '4')
253 // Check for prefixes of length 2.
254 if (number
.size() < 2)
257 int first_two_digits
= 0;
258 if (!base::StringToInt(number
.substr(0, 2), &first_two_digits
))
261 if (first_two_digits
== 34 || first_two_digits
== 37)
262 return kAmericanExpressCard
;
264 if (first_two_digits
== 36 ||
265 first_two_digits
== 38 ||
266 first_two_digits
== 39)
269 if (first_two_digits
>= 51 && first_two_digits
<= 55)
272 if (first_two_digits
== 62)
275 if (first_two_digits
== 65)
276 return kDiscoverCard
;
278 // Check for prefixes of length 3.
279 if (number
.size() < 3)
282 int first_three_digits
= 0;
283 if (!base::StringToInt(number
.substr(0, 3), &first_three_digits
))
286 if (first_three_digits
>= 300 && first_three_digits
<= 305)
289 if (first_three_digits
>= 644 && first_three_digits
<= 649)
290 return kDiscoverCard
;
292 // Check for prefixes of length 4.
293 if (number
.size() < 4)
296 int first_four_digits
= 0;
297 if (!base::StringToInt(number
.substr(0, 4), &first_four_digits
))
300 if (first_four_digits
== 3095)
303 if (first_four_digits
>= 3528 && first_four_digits
<= 3589)
306 if (first_four_digits
== 6011)
307 return kDiscoverCard
;
312 void CreditCard::SetTypeForMaskedCard(const char* type
) {
313 DCHECK_EQ(MASKED_SERVER_CARD
, record_type());
317 void CreditCard::SetServerStatus(ServerStatus status
) {
318 DCHECK_NE(LOCAL_CARD
, record_type());
319 server_status_
= status
;
322 CreditCard::ServerStatus
CreditCard::GetServerStatus() const {
323 DCHECK_NE(LOCAL_CARD
, record_type());
324 return server_status_
;
327 base::string16
CreditCard::GetRawInfo(ServerFieldType type
) const {
328 DCHECK_EQ(CREDIT_CARD
, AutofillType(type
).group());
330 case CREDIT_CARD_NAME
:
331 return name_on_card_
;
333 case CREDIT_CARD_EXP_MONTH
:
334 return ExpirationMonthAsString();
336 case CREDIT_CARD_EXP_2_DIGIT_YEAR
:
337 return Expiration2DigitYearAsString();
339 case CREDIT_CARD_EXP_4_DIGIT_YEAR
:
340 return Expiration4DigitYearAsString();
342 case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR
: {
343 base::string16 month
= ExpirationMonthAsString();
344 base::string16 year
= Expiration2DigitYearAsString();
345 if (!month
.empty() && !year
.empty())
346 return month
+ base::ASCIIToUTF16("/") + year
;
347 return base::string16();
350 case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR
: {
351 base::string16 month
= ExpirationMonthAsString();
352 base::string16 year
= Expiration4DigitYearAsString();
353 if (!month
.empty() && !year
.empty())
354 return month
+ base::ASCIIToUTF16("/") + year
;
355 return base::string16();
358 case CREDIT_CARD_TYPE
:
359 return TypeForFill();
361 case CREDIT_CARD_NUMBER
:
364 case CREDIT_CARD_VERIFICATION_CODE
:
365 // Chrome doesn't store credit card verification codes.
366 return base::string16();
369 // ComputeDataPresentForArray will hit this repeatedly.
370 return base::string16();
374 void CreditCard::SetRawInfo(ServerFieldType type
,
375 const base::string16
& value
) {
376 DCHECK_EQ(CREDIT_CARD
, AutofillType(type
).group());
378 case CREDIT_CARD_NAME
:
379 name_on_card_
= value
;
382 case CREDIT_CARD_EXP_MONTH
:
383 SetExpirationMonthFromString(value
, std::string());
386 case CREDIT_CARD_EXP_2_DIGIT_YEAR
:
387 // This is a read-only attribute.
390 case CREDIT_CARD_EXP_4_DIGIT_YEAR
:
391 SetExpirationYearFromString(value
);
394 case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR
:
395 // This is a read-only attribute.
398 case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR
:
399 // This is a read-only attribute.
402 case CREDIT_CARD_TYPE
:
403 // This is a read-only attribute, determined by the credit card number.
406 case CREDIT_CARD_NUMBER
: {
407 // Don't change the real value if the input is an obfuscated string.
408 if (value
.size() > 0 && value
[0] != kCreditCardObfuscationSymbol
)
413 case CREDIT_CARD_VERIFICATION_CODE
:
414 // Chrome doesn't store the credit card verification code.
418 NOTREACHED() << "Attempting to set unknown info-type " << type
;
423 base::string16
CreditCard::GetInfo(const AutofillType
& type
,
424 const std::string
& app_locale
) const {
425 ServerFieldType storable_type
= type
.GetStorableType();
426 if (storable_type
== CREDIT_CARD_NUMBER
) {
427 // Web pages should never actually be filled by a masked server card,
428 // but this function is used at the preview stage.
429 if (record_type() == MASKED_SERVER_CARD
)
430 return TypeAndLastFourDigits();
432 return StripSeparators(number_
);
435 return GetRawInfo(storable_type
);
438 bool CreditCard::SetInfo(const AutofillType
& type
,
439 const base::string16
& value
,
440 const std::string
& app_locale
) {
441 ServerFieldType storable_type
= type
.GetStorableType();
442 if (storable_type
== CREDIT_CARD_NUMBER
)
443 SetRawInfo(storable_type
, StripSeparators(value
));
444 else if (storable_type
== CREDIT_CARD_EXP_MONTH
)
445 SetExpirationMonthFromString(value
, app_locale
);
447 SetRawInfo(storable_type
, value
);
452 void CreditCard::GetMatchingTypes(const base::string16
& text
,
453 const std::string
& app_locale
,
454 ServerFieldTypeSet
* matching_types
) const {
455 FormGroup::GetMatchingTypes(text
, app_locale
, matching_types
);
457 base::string16 card_number
=
458 GetInfo(AutofillType(CREDIT_CARD_NUMBER
), app_locale
);
459 if (!card_number
.empty() && StripSeparators(text
) == card_number
)
460 matching_types
->insert(CREDIT_CARD_NUMBER
);
463 if (ConvertMonth(text
, app_locale
, &month
) && month
!= 0 &&
464 month
== expiration_month_
) {
465 matching_types
->insert(CREDIT_CARD_EXP_MONTH
);
469 const base::string16
CreditCard::Label() const {
470 base::string16 label
;
471 if (number().empty())
472 return name_on_card_
; // No CC number, return name only.
474 base::string16 obfuscated_cc_number
= TypeAndLastFourDigits();
475 if (!expiration_month_
|| !expiration_year_
)
476 return obfuscated_cc_number
; // No expiration date set.
478 // TODO(georgey): Internationalize date.
479 base::string16
formatted_date(ExpirationMonthAsString());
480 formatted_date
.append(base::ASCIIToUTF16("/"));
481 formatted_date
.append(Expiration4DigitYearAsString());
483 label
= l10n_util::GetStringFUTF16(IDS_CREDIT_CARD_NUMBER_PREVIEW_FORMAT
,
484 obfuscated_cc_number
,
489 void CreditCard::SetInfoForMonthInputType(const base::string16
& value
) {
490 // Check if |text| is "yyyy-mm" format first, and check normal month format.
491 if (!autofill::MatchesPattern(value
,
492 base::UTF8ToUTF16("^[0-9]{4}-[0-9]{1,2}$"))) {
496 std::vector
<base::string16
> year_month
;
497 base::SplitString(value
, L
'-', &year_month
);
498 DCHECK_EQ((int)year_month
.size(), 2);
500 bool converted
= false;
501 converted
= base::StringToInt(year_month
[0], &num
);
503 SetExpirationYear(num
);
504 converted
= base::StringToInt(year_month
[1], &num
);
506 SetExpirationMonth(num
);
509 void CreditCard::SetExpirationMonth(int expiration_month
) {
510 if (expiration_month
< 0 || expiration_month
> 12)
512 expiration_month_
= expiration_month
;
515 void CreditCard::SetExpirationYear(int expiration_year
) {
516 if (expiration_year
!= 0 &&
517 (expiration_year
< 2006 || expiration_year
> 10000))
519 expiration_year_
= expiration_year
;
522 base::string16
CreditCard::LastFourDigits() const {
523 static const size_t kNumLastDigits
= 4;
525 base::string16 number
= StripSeparators(number_
);
526 if (number
.size() <= kNumLastDigits
)
529 return number
.substr(number
.size() - kNumLastDigits
, kNumLastDigits
);
532 base::string16
CreditCard::TypeForDisplay() const {
533 return CreditCard::TypeForDisplay(type_
);
536 base::string16
CreditCard::TypeAndLastFourDigits() const {
537 base::string16 type
= TypeForDisplay();
539 base::string16 digits
= LastFourDigits();
543 // TODO(estade): i18n.
544 return type
+ base::ASCIIToUTF16(" - ") + digits
;
547 void CreditCard::operator=(const CreditCard
& credit_card
) {
548 set_use_count(credit_card
.use_count());
549 set_use_date(credit_card
.use_date());
550 set_modification_date(credit_card
.modification_date());
552 if (this == &credit_card
)
555 record_type_
= credit_card
.record_type_
;
556 number_
= credit_card
.number_
;
557 name_on_card_
= credit_card
.name_on_card_
;
558 type_
= credit_card
.type_
;
559 expiration_month_
= credit_card
.expiration_month_
;
560 expiration_year_
= credit_card
.expiration_year_
;
561 server_id_
= credit_card
.server_id_
;
562 server_status_
= credit_card
.server_status_
;
564 set_guid(credit_card
.guid());
565 set_origin(credit_card
.origin());
568 bool CreditCard::UpdateFromImportedCard(const CreditCard
& imported_card
,
569 const std::string
& app_locale
) {
570 if (this->GetInfo(AutofillType(CREDIT_CARD_NUMBER
), app_locale
) !=
571 imported_card
.GetInfo(AutofillType(CREDIT_CARD_NUMBER
), app_locale
)) {
575 // Heuristically aggregated data should never overwrite verified data.
576 // Instead, discard any heuristically aggregated credit cards that disagree
577 // with explicitly entered data, so that the UI is not cluttered with
579 if (this->IsVerified() && !imported_card
.IsVerified())
582 set_origin(imported_card
.origin());
584 // Note that the card number is intentionally not updated, so as to preserve
585 // any formatting (i.e. separator characters). Since the card number is not
586 // updated, there is no reason to update the card type, either.
587 if (!imported_card
.name_on_card_
.empty())
588 name_on_card_
= imported_card
.name_on_card_
;
590 // The expiration date for |imported_card| should always be set.
591 DCHECK(imported_card
.expiration_month_
&& imported_card
.expiration_year_
);
592 expiration_month_
= imported_card
.expiration_month_
;
593 expiration_year_
= imported_card
.expiration_year_
;
598 int CreditCard::Compare(const CreditCard
& credit_card
) const {
599 // The following CreditCard field types are the only types we store in the
600 // WebDB so far, so we're only concerned with matching these types in the
602 const ServerFieldType types
[] = { CREDIT_CARD_NAME
,
604 CREDIT_CARD_EXP_MONTH
,
605 CREDIT_CARD_EXP_4_DIGIT_YEAR
};
606 for (size_t i
= 0; i
< arraysize(types
); ++i
) {
608 GetRawInfo(types
[i
]).compare(credit_card
.GetRawInfo(types
[i
]));
613 int comparison
= server_id_
.compare(credit_card
.server_id_
);
617 if (static_cast<int>(server_status_
) <
618 static_cast<int>(credit_card
.server_status_
))
620 if (static_cast<int>(server_status_
) >
621 static_cast<int>(credit_card
.server_status_
))
623 if (static_cast<int>(record_type_
) <
624 static_cast<int>(credit_card
.record_type_
))
626 if (static_cast<int>(record_type_
) >
627 static_cast<int>(credit_card
.record_type_
))
632 bool CreditCard::IsLocalDuplicateOfServerCard(const CreditCard
& other
) const {
633 if (record_type() != LOCAL_CARD
|| other
.record_type() == LOCAL_CARD
)
636 // If |this| is only a partial card, i.e. some fields are missing, assume
637 // those fields match.
638 if ((!name_on_card_
.empty() && name_on_card_
!= other
.name_on_card_
) ||
639 (expiration_month_
!= 0 &&
640 expiration_month_
!= other
.expiration_month_
) ||
641 (expiration_year_
!= 0 && expiration_year_
!= other
.expiration_year_
)) {
648 if (other
.record_type() == FULL_SERVER_CARD
)
649 return StripSeparators(number_
) == StripSeparators(other
.number_
);
651 // For masked cards, this is the best we can do to compare card numbers.
652 return TypeAndLastFourDigits() == other
.TypeAndLastFourDigits();
655 bool CreditCard::operator==(const CreditCard
& credit_card
) const {
656 return guid() == credit_card
.guid() &&
657 origin() == credit_card
.origin() &&
658 Compare(credit_card
) == 0;
661 bool CreditCard::operator!=(const CreditCard
& credit_card
) const {
662 return !operator==(credit_card
);
665 bool CreditCard::IsEmpty(const std::string
& app_locale
) const {
666 ServerFieldTypeSet types
;
667 GetNonEmptyTypes(app_locale
, &types
);
668 return types
.empty();
671 bool CreditCard::IsComplete() const {
673 autofill::IsValidCreditCardNumber(number_
) &&
674 expiration_month_
!= 0 &&
675 expiration_year_
!= 0;
678 bool CreditCard::IsValid() const {
679 return autofill::IsValidCreditCardNumber(number_
) &&
680 autofill::IsValidCreditCardExpirationDate(
681 expiration_year_
, expiration_month_
, base::Time::Now());
684 void CreditCard::GetSupportedTypes(ServerFieldTypeSet
* supported_types
) const {
685 supported_types
->insert(CREDIT_CARD_NAME
);
686 supported_types
->insert(CREDIT_CARD_NUMBER
);
687 supported_types
->insert(CREDIT_CARD_TYPE
);
688 supported_types
->insert(CREDIT_CARD_EXP_MONTH
);
689 supported_types
->insert(CREDIT_CARD_EXP_2_DIGIT_YEAR
);
690 supported_types
->insert(CREDIT_CARD_EXP_4_DIGIT_YEAR
);
691 supported_types
->insert(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR
);
692 supported_types
->insert(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR
);
695 base::string16
CreditCard::ExpirationMonthAsString() const {
696 if (expiration_month_
== 0)
697 return base::string16();
699 base::string16 month
= base::IntToString16(expiration_month_
);
700 if (expiration_month_
>= 10)
703 base::string16 zero
= base::ASCIIToUTF16("0");
708 base::string16
CreditCard::TypeForFill() const {
709 return ::autofill::TypeForFill(type_
);
712 base::string16
CreditCard::Expiration4DigitYearAsString() const {
713 if (expiration_year_
== 0)
714 return base::string16();
716 return base::IntToString16(Expiration4DigitYear());
719 base::string16
CreditCard::Expiration2DigitYearAsString() const {
720 if (expiration_year_
== 0)
721 return base::string16();
723 return base::IntToString16(Expiration2DigitYear());
726 void CreditCard::SetExpirationMonthFromString(const base::string16
& text
,
727 const std::string
& app_locale
) {
729 if (!ConvertMonth(text
, app_locale
, &month
))
732 SetExpirationMonth(month
);
735 void CreditCard::SetExpirationYearFromString(const base::string16
& text
) {
737 if (!ConvertYear(text
, &year
))
740 SetExpirationYear(year
);
743 void CreditCard::SetNumber(const base::string16
& number
) {
746 // Set the type based on the card number, but only for full numbers, not
747 // when we have masked cards from the server (last 4 digits).
748 if (record_type_
!= MASKED_SERVER_CARD
)
749 type_
= GetCreditCardType(StripSeparators(number_
));
752 // So we can compare CreditCards with EXPECT_EQ().
753 std::ostream
& operator<<(std::ostream
& os
, const CreditCard
& credit_card
) {
755 << base::UTF16ToUTF8(credit_card
.Label())
757 << credit_card
.guid()
759 << credit_card
.origin()
761 << base::UTF16ToUTF8(credit_card
.GetRawInfo(CREDIT_CARD_NAME
))
763 << base::UTF16ToUTF8(credit_card
.GetRawInfo(CREDIT_CARD_TYPE
))
765 << base::UTF16ToUTF8(credit_card
.GetRawInfo(CREDIT_CARD_NUMBER
))
767 << base::UTF16ToUTF8(credit_card
.GetRawInfo(CREDIT_CARD_EXP_MONTH
))
769 << base::UTF16ToUTF8(
770 credit_card
.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR
));
773 // These values must match the values in WebKitPlatformSupportImpl in
774 // webkit/glue. We send these strings to WebKit, which then asks
775 // WebKitPlatformSupportImpl to load the image data.
776 const char* const kAmericanExpressCard
= "americanExpressCC";
777 const char* const kDinersCard
= "dinersCC";
778 const char* const kDiscoverCard
= "discoverCC";
779 const char* const kGenericCard
= "genericCC";
780 const char* const kJCBCard
= "jcbCC";
781 const char* const kMasterCard
= "masterCardCC";
782 const char* const kUnionPay
= "unionPayCC";
783 const char* const kVisaCard
= "visaCC";
785 } // namespace autofill