ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / components / autofill / core / browser / credit_card.cc
blob34b78b20b395b4b33c13f192c1d328e3e9f3ad4a
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"
7 #include <stddef.h>
9 #include <algorithm>
10 #include <ostream>
11 #include <string>
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"
33 namespace autofill {
35 namespace {
37 const base::char16 kCreditCardObfuscationSymbol = '*';
39 bool ConvertYear(const base::string16& year, int* num) {
40 // If the |year| is empty, clear the stored value.
41 if (year.empty()) {
42 *num = 0;
43 return true;
46 // Try parsing the |year| as a number.
47 if (base::StringToInt(year, num))
48 return true;
50 *num = 0;
51 return false;
54 bool ConvertMonth(const base::string16& month,
55 const std::string& app_locale,
56 int* num) {
57 // If the |month| is empty, clear the stored value.
58 if (month.empty()) {
59 *num = 0;
60 return true;
63 // Try parsing the |month| as a number.
64 if (base::StringToInt(month, num))
65 return true;
67 // If the locale is unknown, give up.
68 if (app_locale.empty())
69 return false;
71 // Otherwise, try parsing the |month| as a named month, e.g. "January" or
72 // "Jan".
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);
81 int32_t num_months;
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(),
85 months[i].length());
86 if (lowercased_month == base::StringToLowerASCII(icu_month)) {
87 *num = i + 1; // Adjust from 0-indexed to 1-indexed.
88 return true;
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(),
95 months[i].length());
96 if (lowercased_month == base::StringToLowerASCII(icu_month)) {
97 *num = i + 1; // Adjust from 0-indexed to 1-indexed.
98 return true;
102 *num = 0;
103 return false;
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();
128 } // namespace
130 CreditCard::CreditCard(const std::string& guid, const std::string& origin)
131 : AutofillDataModel(guid, origin),
132 record_type_(LOCAL_CARD),
133 type_(kGenericCard),
134 expiration_month_(0),
135 expiration_year_(0),
136 server_status_(OK) {
139 CreditCard::CreditCard(const base::string16& card_number,
140 int expiration_month,
141 int expiration_year)
142 : AutofillDataModel(std::string(), std::string()),
143 record_type_(LOCAL_CARD),
144 server_status_(OK) {
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()),
152 record_type_(type),
153 type_(kGenericCard),
154 expiration_month_(0),
155 expiration_year_(0),
156 server_id_(server_id),
157 server_status_(OK) {
158 DCHECK(type == MASKED_SERVER_CARD || type == FULL_SERVER_CARD);
161 CreditCard::CreditCard()
162 : AutofillDataModel(base::GenerateGUID(), std::string()),
163 record_type_(LOCAL_CARD),
164 type_(kGenericCard),
165 expiration_month_(0),
166 expiration_year_(0),
167 server_status_(OK) {
170 CreditCard::CreditCard(const CreditCard& credit_card)
171 : AutofillDataModel(std::string(), std::string()) {
172 operator=(credit_card);
175 CreditCard::~CreditCard() {}
177 // static
178 const base::string16 CreditCard::StripSeparators(const base::string16& number) {
179 base::string16 stripped;
180 base::RemoveChars(number, base::ASCIIToUTF16("- "), &stripped);
181 return stripped;
184 // static
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.
196 #if !defined(OS_IOS)
197 // static
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)
221 // static
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 // ---------------------------------------------------------------
238 // Visa 4 13,16
239 // American Express 34,37 15
240 // Diners Club 300-305,3095,36,38-39 14
241 // Discover Card 6011,644-649,65 16
242 // JCB 3528-3589 16
243 // MasterCard 51-55 16
244 // UnionPay 62 16-19
246 // Check for prefixes of length 1.
247 if (number.empty())
248 return kGenericCard;
250 if (number[0] == '4')
251 return kVisaCard;
253 // Check for prefixes of length 2.
254 if (number.size() < 2)
255 return kGenericCard;
257 int first_two_digits = 0;
258 if (!base::StringToInt(number.substr(0, 2), &first_two_digits))
259 return kGenericCard;
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)
267 return kDinersCard;
269 if (first_two_digits >= 51 && first_two_digits <= 55)
270 return kMasterCard;
272 if (first_two_digits == 62)
273 return kUnionPay;
275 if (first_two_digits == 65)
276 return kDiscoverCard;
278 // Check for prefixes of length 3.
279 if (number.size() < 3)
280 return kGenericCard;
282 int first_three_digits = 0;
283 if (!base::StringToInt(number.substr(0, 3), &first_three_digits))
284 return kGenericCard;
286 if (first_three_digits >= 300 && first_three_digits <= 305)
287 return kDinersCard;
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)
294 return kGenericCard;
296 int first_four_digits = 0;
297 if (!base::StringToInt(number.substr(0, 4), &first_four_digits))
298 return kGenericCard;
300 if (first_four_digits == 3095)
301 return kDinersCard;
303 if (first_four_digits >= 3528 && first_four_digits <= 3589)
304 return kJCBCard;
306 if (first_four_digits == 6011)
307 return kDiscoverCard;
309 return kGenericCard;
312 void CreditCard::SetTypeForMaskedCard(const char* type) {
313 DCHECK_EQ(MASKED_SERVER_CARD, record_type());
314 type_ = 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());
329 switch (type) {
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:
362 return number_;
364 case CREDIT_CARD_VERIFICATION_CODE:
365 // Chrome doesn't store credit card verification codes.
366 return base::string16();
368 default:
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());
377 switch (type) {
378 case CREDIT_CARD_NAME:
379 name_on_card_ = value;
380 break;
382 case CREDIT_CARD_EXP_MONTH:
383 SetExpirationMonthFromString(value, std::string());
384 break;
386 case CREDIT_CARD_EXP_2_DIGIT_YEAR:
387 // This is a read-only attribute.
388 break;
390 case CREDIT_CARD_EXP_4_DIGIT_YEAR:
391 SetExpirationYearFromString(value);
392 break;
394 case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR:
395 // This is a read-only attribute.
396 break;
398 case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR:
399 // This is a read-only attribute.
400 break;
402 case CREDIT_CARD_TYPE:
403 // This is a read-only attribute, determined by the credit card number.
404 break;
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)
409 SetNumber(value);
410 break;
413 case CREDIT_CARD_VERIFICATION_CODE:
414 // Chrome doesn't store the credit card verification code.
415 break;
417 default:
418 NOTREACHED() << "Attempting to set unknown info-type " << type;
419 break;
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);
446 else
447 SetRawInfo(storable_type, value);
449 return true;
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);
462 int month;
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,
485 formatted_date);
486 return label;
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}$"))) {
493 return;
496 std::vector<base::string16> year_month;
497 base::SplitString(value, L'-', &year_month);
498 DCHECK_EQ((int)year_month.size(), 2);
499 int num = 0;
500 bool converted = false;
501 converted = base::StringToInt(year_month[0], &num);
502 DCHECK(converted);
503 SetExpirationYear(num);
504 converted = base::StringToInt(year_month[1], &num);
505 DCHECK(converted);
506 SetExpirationMonth(num);
509 void CreditCard::SetExpirationMonth(int expiration_month) {
510 if (expiration_month < 0 || expiration_month > 12)
511 return;
512 expiration_month_ = expiration_month;
515 void CreditCard::SetExpirationYear(int expiration_year) {
516 if (expiration_year != 0 &&
517 (expiration_year < 2006 || expiration_year > 10000))
518 return;
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)
527 return number;
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();
540 if (digits.empty())
541 return type;
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)
553 return;
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)) {
572 return false;
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
578 // duplicate cards.
579 if (this->IsVerified() && !imported_card.IsVerified())
580 return true;
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_;
595 return true;
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
601 // credit card.
602 const ServerFieldType types[] = { CREDIT_CARD_NAME,
603 CREDIT_CARD_NUMBER,
604 CREDIT_CARD_EXP_MONTH,
605 CREDIT_CARD_EXP_4_DIGIT_YEAR };
606 for (size_t i = 0; i < arraysize(types); ++i) {
607 int comparison =
608 GetRawInfo(types[i]).compare(credit_card.GetRawInfo(types[i]));
609 if (comparison != 0)
610 return comparison;
613 int comparison = server_id_.compare(credit_card.server_id_);
614 if (comparison != 0)
615 return comparison;
617 if (static_cast<int>(server_status_) <
618 static_cast<int>(credit_card.server_status_))
619 return -1;
620 if (static_cast<int>(server_status_) >
621 static_cast<int>(credit_card.server_status_))
622 return 1;
623 if (static_cast<int>(record_type_) <
624 static_cast<int>(credit_card.record_type_))
625 return -1;
626 if (static_cast<int>(record_type_) >
627 static_cast<int>(credit_card.record_type_))
628 return 1;
629 return 0;
632 bool CreditCard::IsLocalDuplicateOfServerCard(const CreditCard& other) const {
633 if (record_type() != LOCAL_CARD || other.record_type() == LOCAL_CARD)
634 return false;
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_)) {
642 return false;
645 if (number_.empty())
646 return true;
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 {
672 return
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)
701 return month;
703 base::string16 zero = base::ASCIIToUTF16("0");
704 zero.append(month);
705 return zero;
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) {
728 int month;
729 if (!ConvertMonth(text, app_locale, &month))
730 return;
732 SetExpirationMonth(month);
735 void CreditCard::SetExpirationYearFromString(const base::string16& text) {
736 int year;
737 if (!ConvertYear(text, &year))
738 return;
740 SetExpirationYear(year);
743 void CreditCard::SetNumber(const base::string16& number) {
744 number_ = 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) {
754 return os
755 << base::UTF16ToUTF8(credit_card.Label())
756 << " "
757 << credit_card.guid()
758 << " "
759 << credit_card.origin()
760 << " "
761 << base::UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_NAME))
762 << " "
763 << base::UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_TYPE))
764 << " "
765 << base::UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_NUMBER))
766 << " "
767 << base::UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_EXP_MONTH))
768 << " "
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