Rename GetIconID to GetIconId
[chromium-blink-merge.git] / components / autofill / core / browser / credit_card.cc
blob6f26a14ee36fe0051f209f6612b14c56a8bb1e8f
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_type.h"
24 #include "components/autofill/core/browser/validation.h"
25 #include "components/autofill/core/common/autofill_l10n_util.h"
26 #include "components/autofill/core/common/autofill_regexes.h"
27 #include "components/autofill/core/common/form_field_data.h"
28 #include "grit/components_scaled_resources.h"
29 #include "grit/components_strings.h"
30 #include "third_party/icu/source/common/unicode/uloc.h"
31 #include "third_party/icu/source/i18n/unicode/dtfmtsym.h"
32 #include "ui/base/l10n/l10n_util.h"
34 namespace autofill {
36 namespace {
38 const base::char16 kCreditCardObfuscationSymbol = '*';
40 bool ConvertYear(const base::string16& year, int* num) {
41 // If the |year| is empty, clear the stored value.
42 if (year.empty()) {
43 *num = 0;
44 return true;
47 // Try parsing the |year| as a number.
48 if (base::StringToInt(year, num))
49 return true;
51 *num = 0;
52 return false;
55 base::string16 TypeForFill(const std::string& type) {
56 if (type == kAmericanExpressCard)
57 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_AMEX);
58 if (type == kDinersCard)
59 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_DINERS);
60 if (type == kDiscoverCard)
61 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_DISCOVER);
62 if (type == kJCBCard)
63 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_JCB);
64 if (type == kMasterCard)
65 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_MASTERCARD);
66 if (type == kUnionPay)
67 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_UNION_PAY);
68 if (type == kVisaCard)
69 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_VISA);
71 // If you hit this DCHECK, the above list of cases needs to be updated to
72 // include a new card.
73 DCHECK_EQ(kGenericCard, type);
74 return base::string16();
77 } // namespace
79 CreditCard::CreditCard(const std::string& guid, const std::string& origin)
80 : AutofillDataModel(guid, origin),
81 record_type_(LOCAL_CARD),
82 type_(kGenericCard),
83 expiration_month_(0),
84 expiration_year_(0),
85 server_status_(OK) {
88 CreditCard::CreditCard(const base::string16& card_number,
89 int expiration_month,
90 int expiration_year)
91 : AutofillDataModel(std::string(), std::string()),
92 record_type_(LOCAL_CARD),
93 server_status_(OK) {
94 SetNumber(card_number);
95 SetExpirationMonth(expiration_month);
96 SetExpirationYear(expiration_year);
99 CreditCard::CreditCard(RecordType type, const std::string& server_id)
100 : AutofillDataModel(base::GenerateGUID(), std::string()),
101 record_type_(type),
102 type_(kGenericCard),
103 expiration_month_(0),
104 expiration_year_(0),
105 server_id_(server_id),
106 server_status_(OK) {
107 DCHECK(type == MASKED_SERVER_CARD || type == FULL_SERVER_CARD);
110 CreditCard::CreditCard()
111 : AutofillDataModel(base::GenerateGUID(), std::string()),
112 record_type_(LOCAL_CARD),
113 type_(kGenericCard),
114 expiration_month_(0),
115 expiration_year_(0),
116 server_status_(OK) {
119 CreditCard::CreditCard(const CreditCard& credit_card)
120 : AutofillDataModel(std::string(), std::string()) {
121 operator=(credit_card);
124 CreditCard::~CreditCard() {}
126 // static
127 const base::string16 CreditCard::StripSeparators(const base::string16& number) {
128 base::string16 stripped;
129 base::RemoveChars(number, base::ASCIIToUTF16("- "), &stripped);
130 return stripped;
133 // static
134 base::string16 CreditCard::TypeForDisplay(const std::string& type) {
135 if (kGenericCard == type)
136 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_GENERIC);
137 if (kAmericanExpressCard == type)
138 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_AMEX_SHORT);
140 return ::autofill::TypeForFill(type);
143 // This method is not compiled on iOS because the resources are not used and
144 // should not be shipped.
145 #if !defined(OS_IOS)
146 // static
147 int CreditCard::IconResourceId(const std::string& type) {
148 if (type == kAmericanExpressCard)
149 return IDR_AUTOFILL_CC_AMEX;
150 if (type == kDinersCard)
151 return IDR_AUTOFILL_CC_GENERIC;
152 if (type == kDiscoverCard)
153 return IDR_AUTOFILL_CC_DISCOVER;
154 if (type == kJCBCard)
155 return IDR_AUTOFILL_CC_GENERIC;
156 if (type == kMasterCard)
157 return IDR_AUTOFILL_CC_MASTERCARD;
158 if (type == kUnionPay)
159 return IDR_AUTOFILL_CC_GENERIC;
160 if (type == kVisaCard)
161 return IDR_AUTOFILL_CC_VISA;
163 // If you hit this DCHECK, the above list of cases needs to be updated to
164 // include a new card.
165 DCHECK_EQ(kGenericCard, type);
166 return IDR_AUTOFILL_CC_GENERIC;
168 #endif // #if !defined(OS_IOS)
170 // static
171 const char* CreditCard::GetCreditCardType(const base::string16& number) {
172 // Credit card number specifications taken from:
173 // http://en.wikipedia.org/wiki/Credit_card_numbers,
174 // http://en.wikipedia.org/wiki/List_of_Issuer_Identification_Numbers,
175 // http://www.discovernetwork.com/merchants/images/Merchant_Marketing_PDF.pdf,
176 // http://www.regular-expressions.info/creditcard.html,
177 // http://developer.ean.com/general_info/Valid_Credit_Card_Types,
178 // http://www.bincodes.com/,
179 // http://www.fraudpractice.com/FL-binCC.html, and
180 // http://www.beachnet.com/~hstiles/cardtype.html
182 // The last site is currently unavailable, but a cached version remains at
183 // http://web.archive.org/web/20120923111349/http://www.beachnet.com/~hstiles/cardtype.html
185 // Card Type Prefix(es) Length
186 // ---------------------------------------------------------------
187 // Visa 4 13,16
188 // American Express 34,37 15
189 // Diners Club 300-305,3095,36,38-39 14
190 // Discover Card 6011,644-649,65 16
191 // JCB 3528-3589 16
192 // MasterCard 51-55 16
193 // UnionPay 62 16-19
195 // Check for prefixes of length 1.
196 if (number.empty())
197 return kGenericCard;
199 if (number[0] == '4')
200 return kVisaCard;
202 // Check for prefixes of length 2.
203 if (number.size() < 2)
204 return kGenericCard;
206 int first_two_digits = 0;
207 if (!base::StringToInt(number.substr(0, 2), &first_two_digits))
208 return kGenericCard;
210 if (first_two_digits == 34 || first_two_digits == 37)
211 return kAmericanExpressCard;
213 if (first_two_digits == 36 ||
214 first_two_digits == 38 ||
215 first_two_digits == 39)
216 return kDinersCard;
218 if (first_two_digits >= 51 && first_two_digits <= 55)
219 return kMasterCard;
221 if (first_two_digits == 62)
222 return kUnionPay;
224 if (first_two_digits == 65)
225 return kDiscoverCard;
227 // Check for prefixes of length 3.
228 if (number.size() < 3)
229 return kGenericCard;
231 int first_three_digits = 0;
232 if (!base::StringToInt(number.substr(0, 3), &first_three_digits))
233 return kGenericCard;
235 if (first_three_digits >= 300 && first_three_digits <= 305)
236 return kDinersCard;
238 if (first_three_digits >= 644 && first_three_digits <= 649)
239 return kDiscoverCard;
241 // Check for prefixes of length 4.
242 if (number.size() < 4)
243 return kGenericCard;
245 int first_four_digits = 0;
246 if (!base::StringToInt(number.substr(0, 4), &first_four_digits))
247 return kGenericCard;
249 if (first_four_digits == 3095)
250 return kDinersCard;
252 if (first_four_digits >= 3528 && first_four_digits <= 3589)
253 return kJCBCard;
255 if (first_four_digits == 6011)
256 return kDiscoverCard;
258 return kGenericCard;
261 void CreditCard::SetTypeForMaskedCard(const char* type) {
262 DCHECK_EQ(MASKED_SERVER_CARD, record_type());
263 type_ = type;
266 void CreditCard::SetServerStatus(ServerStatus status) {
267 DCHECK_NE(LOCAL_CARD, record_type());
268 server_status_ = status;
271 CreditCard::ServerStatus CreditCard::GetServerStatus() const {
272 DCHECK_NE(LOCAL_CARD, record_type());
273 return server_status_;
276 base::string16 CreditCard::GetRawInfo(ServerFieldType type) const {
277 DCHECK_EQ(CREDIT_CARD, AutofillType(type).group());
278 switch (type) {
279 case CREDIT_CARD_NAME:
280 return name_on_card_;
282 case CREDIT_CARD_EXP_MONTH:
283 return ExpirationMonthAsString();
285 case CREDIT_CARD_EXP_2_DIGIT_YEAR:
286 return Expiration2DigitYearAsString();
288 case CREDIT_CARD_EXP_4_DIGIT_YEAR:
289 return Expiration4DigitYearAsString();
291 case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR: {
292 base::string16 month = ExpirationMonthAsString();
293 base::string16 year = Expiration2DigitYearAsString();
294 if (!month.empty() && !year.empty())
295 return month + base::ASCIIToUTF16("/") + year;
296 return base::string16();
299 case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR: {
300 base::string16 month = ExpirationMonthAsString();
301 base::string16 year = Expiration4DigitYearAsString();
302 if (!month.empty() && !year.empty())
303 return month + base::ASCIIToUTF16("/") + year;
304 return base::string16();
307 case CREDIT_CARD_TYPE:
308 return TypeForFill();
310 case CREDIT_CARD_NUMBER:
311 return number_;
313 case CREDIT_CARD_VERIFICATION_CODE:
314 // Chrome doesn't store credit card verification codes.
315 return base::string16();
317 default:
318 // ComputeDataPresentForArray will hit this repeatedly.
319 return base::string16();
323 void CreditCard::SetRawInfo(ServerFieldType type,
324 const base::string16& value) {
325 DCHECK_EQ(CREDIT_CARD, AutofillType(type).group());
326 switch (type) {
327 case CREDIT_CARD_NAME:
328 name_on_card_ = value;
329 break;
331 case CREDIT_CARD_EXP_MONTH:
332 SetExpirationMonthFromString(value, std::string());
333 break;
335 case CREDIT_CARD_EXP_2_DIGIT_YEAR:
336 // This is a read-only attribute.
337 break;
339 case CREDIT_CARD_EXP_4_DIGIT_YEAR:
340 SetExpirationYearFromString(value);
341 break;
343 case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR:
344 // This is a read-only attribute.
345 break;
347 case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR:
348 // This is a read-only attribute.
349 break;
351 case CREDIT_CARD_TYPE:
352 // This is a read-only attribute, determined by the credit card number.
353 break;
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;
362 case CREDIT_CARD_VERIFICATION_CODE:
363 // Chrome doesn't store the credit card verification code.
364 break;
366 default:
367 NOTREACHED() << "Attempting to set unknown info-type " << type;
368 break;
372 base::string16 CreditCard::GetInfo(const AutofillType& type,
373 const std::string& app_locale) const {
374 ServerFieldType storable_type = type.GetStorableType();
375 if (storable_type == CREDIT_CARD_NUMBER) {
376 // Web pages should never actually be filled by a masked server card,
377 // but this function is used at the preview stage.
378 if (record_type() == MASKED_SERVER_CARD)
379 return TypeAndLastFourDigits();
381 return StripSeparators(number_);
384 return GetRawInfo(storable_type);
387 bool CreditCard::SetInfo(const AutofillType& type,
388 const base::string16& value,
389 const std::string& app_locale) {
390 ServerFieldType storable_type = type.GetStorableType();
391 if (storable_type == CREDIT_CARD_NUMBER)
392 SetRawInfo(storable_type, StripSeparators(value));
393 else if (storable_type == CREDIT_CARD_EXP_MONTH)
394 SetExpirationMonthFromString(value, app_locale);
395 else
396 SetRawInfo(storable_type, value);
398 return true;
401 void CreditCard::GetMatchingTypes(const base::string16& text,
402 const std::string& app_locale,
403 ServerFieldTypeSet* matching_types) const {
404 FormGroup::GetMatchingTypes(text, app_locale, matching_types);
406 base::string16 card_number =
407 GetInfo(AutofillType(CREDIT_CARD_NUMBER), app_locale);
408 if (!card_number.empty() && StripSeparators(text) == card_number)
409 matching_types->insert(CREDIT_CARD_NUMBER);
411 int month;
412 if (ConvertMonth(text, app_locale, &month) &&
413 month == expiration_month_) {
414 matching_types->insert(CREDIT_CARD_EXP_MONTH);
418 const base::string16 CreditCard::Label() const {
419 std::pair<base::string16, base::string16> pieces = LabelPieces();
420 return pieces.first + pieces.second;
423 const std::pair<base::string16, base::string16> CreditCard::LabelPieces()
424 const {
425 base::string16 label;
426 // No CC number, return name only.
427 if (number().empty())
428 return std::make_pair(name_on_card_, base::string16());
430 base::string16 obfuscated_cc_number = TypeAndLastFourDigits();
431 // No expiration date set.
432 if (!expiration_month_ || !expiration_year_)
433 return std::make_pair(obfuscated_cc_number, base::string16());
435 base::string16 formatted_date(ExpirationMonthAsString());
436 formatted_date.append(base::ASCIIToUTF16("/"));
437 formatted_date.append(Expiration4DigitYearAsString());
439 base::string16 separator =
440 l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_SUMMARY_SEPARATOR);
441 return std::make_pair(obfuscated_cc_number, separator + formatted_date);
444 void CreditCard::SetInfoForMonthInputType(const base::string16& value) {
445 // Check if |text| is "yyyy-mm" format first, and check normal month format.
446 if (!autofill::MatchesPattern(value,
447 base::UTF8ToUTF16("^[0-9]{4}-[0-9]{1,2}$"))) {
448 return;
451 std::vector<base::StringPiece16> year_month = base::SplitStringPiece(
452 value, base::ASCIIToUTF16("-"),
453 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
454 DCHECK_EQ(2u, year_month.size());
455 int num = 0;
456 bool converted = false;
457 converted = base::StringToInt(year_month[0], &num);
458 DCHECK(converted);
459 SetExpirationYear(num);
460 converted = base::StringToInt(year_month[1], &num);
461 DCHECK(converted);
462 SetExpirationMonth(num);
465 void CreditCard::SetExpirationMonth(int expiration_month) {
466 if (expiration_month < 0 || expiration_month > 12)
467 return;
468 expiration_month_ = expiration_month;
471 void CreditCard::SetExpirationYear(int expiration_year) {
472 if (expiration_year != 0 &&
473 (expiration_year < 2006 || expiration_year > 10000))
474 return;
475 expiration_year_ = expiration_year;
478 base::string16 CreditCard::LastFourDigits() const {
479 static const size_t kNumLastDigits = 4;
481 base::string16 number = StripSeparators(number_);
482 if (number.size() <= kNumLastDigits)
483 return number;
485 return number.substr(number.size() - kNumLastDigits, kNumLastDigits);
488 base::string16 CreditCard::TypeForDisplay() const {
489 return CreditCard::TypeForDisplay(type_);
492 base::string16 CreditCard::TypeAndLastFourDigits() const {
493 base::string16 type = TypeForDisplay();
495 base::string16 digits = LastFourDigits();
496 if (digits.empty())
497 return type;
499 // The separator character is a non breaking space and a horizontal midline
500 // ellipsis.
501 // TODO(estade): i18n?
502 return type + base::UTF8ToUTF16("\xC2\xA0\xE2\x8B\xAF") + digits;
505 void CreditCard::operator=(const CreditCard& credit_card) {
506 set_use_count(credit_card.use_count());
507 set_use_date(credit_card.use_date());
508 set_modification_date(credit_card.modification_date());
510 if (this == &credit_card)
511 return;
513 record_type_ = credit_card.record_type_;
514 number_ = credit_card.number_;
515 name_on_card_ = credit_card.name_on_card_;
516 type_ = credit_card.type_;
517 expiration_month_ = credit_card.expiration_month_;
518 expiration_year_ = credit_card.expiration_year_;
519 server_id_ = credit_card.server_id_;
520 server_status_ = credit_card.server_status_;
522 set_guid(credit_card.guid());
523 set_origin(credit_card.origin());
526 bool CreditCard::UpdateFromImportedCard(const CreditCard& imported_card,
527 const std::string& app_locale) {
528 if (this->GetInfo(AutofillType(CREDIT_CARD_NUMBER), app_locale) !=
529 imported_card.GetInfo(AutofillType(CREDIT_CARD_NUMBER), app_locale)) {
530 return false;
533 // Heuristically aggregated data should never overwrite verified data.
534 // Instead, discard any heuristically aggregated credit cards that disagree
535 // with explicitly entered data, so that the UI is not cluttered with
536 // duplicate cards.
537 if (this->IsVerified() && !imported_card.IsVerified())
538 return true;
540 set_origin(imported_card.origin());
542 // Note that the card number is intentionally not updated, so as to preserve
543 // any formatting (i.e. separator characters). Since the card number is not
544 // updated, there is no reason to update the card type, either.
545 if (!imported_card.name_on_card_.empty())
546 name_on_card_ = imported_card.name_on_card_;
548 // The expiration date for |imported_card| should always be set.
549 DCHECK(imported_card.expiration_month_ && imported_card.expiration_year_);
550 expiration_month_ = imported_card.expiration_month_;
551 expiration_year_ = imported_card.expiration_year_;
553 return true;
556 int CreditCard::Compare(const CreditCard& credit_card) const {
557 // The following CreditCard field types are the only types we store in the
558 // WebDB so far, so we're only concerned with matching these types in the
559 // credit card.
560 const ServerFieldType types[] = { CREDIT_CARD_NAME,
561 CREDIT_CARD_NUMBER,
562 CREDIT_CARD_EXP_MONTH,
563 CREDIT_CARD_EXP_4_DIGIT_YEAR };
564 for (size_t i = 0; i < arraysize(types); ++i) {
565 int comparison =
566 GetRawInfo(types[i]).compare(credit_card.GetRawInfo(types[i]));
567 if (comparison != 0)
568 return comparison;
571 int comparison = server_id_.compare(credit_card.server_id_);
572 if (comparison != 0)
573 return comparison;
575 if (static_cast<int>(server_status_) <
576 static_cast<int>(credit_card.server_status_))
577 return -1;
578 if (static_cast<int>(server_status_) >
579 static_cast<int>(credit_card.server_status_))
580 return 1;
581 if (static_cast<int>(record_type_) <
582 static_cast<int>(credit_card.record_type_))
583 return -1;
584 if (static_cast<int>(record_type_) >
585 static_cast<int>(credit_card.record_type_))
586 return 1;
587 return 0;
590 bool CreditCard::IsLocalDuplicateOfServerCard(const CreditCard& other) const {
591 if (record_type() != LOCAL_CARD || other.record_type() == LOCAL_CARD)
592 return false;
594 // If |this| is only a partial card, i.e. some fields are missing, assume
595 // those fields match.
596 if ((!name_on_card_.empty() && name_on_card_ != other.name_on_card_) ||
597 (expiration_month_ != 0 &&
598 expiration_month_ != other.expiration_month_) ||
599 (expiration_year_ != 0 && expiration_year_ != other.expiration_year_)) {
600 return false;
603 if (number_.empty())
604 return true;
606 if (other.record_type() == FULL_SERVER_CARD)
607 return StripSeparators(number_) == StripSeparators(other.number_);
609 // For masked cards, this is the best we can do to compare card numbers.
610 return TypeAndLastFourDigits() == other.TypeAndLastFourDigits();
613 bool CreditCard::operator==(const CreditCard& credit_card) const {
614 return guid() == credit_card.guid() &&
615 origin() == credit_card.origin() &&
616 Compare(credit_card) == 0;
619 bool CreditCard::operator!=(const CreditCard& credit_card) const {
620 return !operator==(credit_card);
623 bool CreditCard::IsEmpty(const std::string& app_locale) const {
624 ServerFieldTypeSet types;
625 GetNonEmptyTypes(app_locale, &types);
626 return types.empty();
629 bool CreditCard::IsComplete() const {
630 return
631 autofill::IsValidCreditCardNumber(number_) &&
632 expiration_month_ != 0 &&
633 expiration_year_ != 0;
636 bool CreditCard::IsValid() const {
637 return autofill::IsValidCreditCardNumber(number_) &&
638 autofill::IsValidCreditCardExpirationDate(
639 expiration_year_, expiration_month_, base::Time::Now());
642 void CreditCard::GetSupportedTypes(ServerFieldTypeSet* supported_types) const {
643 supported_types->insert(CREDIT_CARD_NAME);
644 supported_types->insert(CREDIT_CARD_NUMBER);
645 supported_types->insert(CREDIT_CARD_TYPE);
646 supported_types->insert(CREDIT_CARD_EXP_MONTH);
647 supported_types->insert(CREDIT_CARD_EXP_2_DIGIT_YEAR);
648 supported_types->insert(CREDIT_CARD_EXP_4_DIGIT_YEAR);
649 supported_types->insert(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR);
650 supported_types->insert(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR);
653 base::string16 CreditCard::ExpirationMonthAsString() const {
654 if (expiration_month_ == 0)
655 return base::string16();
657 base::string16 month = base::IntToString16(expiration_month_);
658 if (expiration_month_ >= 10)
659 return month;
661 base::string16 zero = base::ASCIIToUTF16("0");
662 zero.append(month);
663 return zero;
666 base::string16 CreditCard::TypeForFill() const {
667 return ::autofill::TypeForFill(type_);
670 base::string16 CreditCard::Expiration4DigitYearAsString() const {
671 if (expiration_year_ == 0)
672 return base::string16();
674 return base::IntToString16(Expiration4DigitYear());
677 base::string16 CreditCard::Expiration2DigitYearAsString() const {
678 if (expiration_year_ == 0)
679 return base::string16();
681 return base::IntToString16(Expiration2DigitYear());
684 void CreditCard::SetExpirationMonthFromString(const base::string16& text,
685 const std::string& app_locale) {
686 int month = 0;
687 if (!text.empty() && !ConvertMonth(text, app_locale, &month))
688 return;
690 SetExpirationMonth(month);
693 void CreditCard::SetExpirationYearFromString(const base::string16& text) {
694 int year;
695 if (!ConvertYear(text, &year))
696 return;
698 SetExpirationYear(year);
701 void CreditCard::SetNumber(const base::string16& number) {
702 number_ = number;
704 // Set the type based on the card number, but only for full numbers, not
705 // when we have masked cards from the server (last 4 digits).
706 if (record_type_ != MASKED_SERVER_CARD)
707 type_ = GetCreditCardType(StripSeparators(number_));
710 // static
711 bool CreditCard::ConvertMonth(const base::string16& month,
712 const std::string& app_locale,
713 int* num) {
714 if (month.empty())
715 return false;
717 // Try parsing the |month| as a number (this doesn't require |app_locale|).
718 if (base::StringToInt(month, num))
719 return true;
721 if (app_locale.empty())
722 return false;
724 // Otherwise, try parsing the |month| as a named month, e.g. "January" or
725 // "Jan".
726 l10n::CaseInsensitiveCompare compare;
727 UErrorCode status = U_ZERO_ERROR;
728 icu::Locale locale(app_locale.c_str());
729 icu::DateFormatSymbols date_format_symbols(locale, status);
730 DCHECK(status == U_ZERO_ERROR || status == U_USING_FALLBACK_WARNING ||
731 status == U_USING_DEFAULT_WARNING);
733 int32_t num_months;
734 const icu::UnicodeString* months = date_format_symbols.getMonths(num_months);
735 for (int32_t i = 0; i < num_months; ++i) {
736 const base::string16 icu_month(months[i].getBuffer(), months[i].length());
737 if (compare.StringsEqual(icu_month, month)) {
738 *num = i + 1; // Adjust from 0-indexed to 1-indexed.
739 return true;
743 months = date_format_symbols.getShortMonths(num_months);
744 // Some abbreviations have . at the end (e.g., "janv." in French). We don't
745 // care about matching that.
746 base::string16 trimmed_month;
747 base::TrimString(month, base::ASCIIToUTF16("."), &trimmed_month);
748 for (int32_t i = 0; i < num_months; ++i) {
749 base::string16 icu_month(months[i].getBuffer(), months[i].length());
750 base::TrimString(icu_month, base::ASCIIToUTF16("."), &icu_month);
751 if (compare.StringsEqual(icu_month, trimmed_month)) {
752 *num = i + 1; // Adjust from 0-indexed to 1-indexed.
753 return true;
757 return false;
760 // So we can compare CreditCards with EXPECT_EQ().
761 std::ostream& operator<<(std::ostream& os, const CreditCard& credit_card) {
762 return os
763 << base::UTF16ToUTF8(credit_card.Label())
764 << " "
765 << credit_card.guid()
766 << " "
767 << credit_card.origin()
768 << " "
769 << base::UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_NAME))
770 << " "
771 << base::UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_TYPE))
772 << " "
773 << base::UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_NUMBER))
774 << " "
775 << base::UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_EXP_MONTH))
776 << " "
777 << base::UTF16ToUTF8(
778 credit_card.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
781 // These values must match the values in WebKitPlatformSupportImpl in
782 // webkit/glue. We send these strings to WebKit, which then asks
783 // WebKitPlatformSupportImpl to load the image data.
784 const char* const kAmericanExpressCard = "americanExpressCC";
785 const char* const kDinersCard = "dinersCC";
786 const char* const kDiscoverCard = "discoverCC";
787 const char* const kGenericCard = "genericCC";
788 const char* const kJCBCard = "jcbCC";
789 const char* const kMasterCard = "masterCardCC";
790 const char* const kUnionPay = "unionPayCC";
791 const char* const kVisaCard = "visaCC";
793 } // namespace autofill