OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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/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 "components/autofill/browser/autofill_field.h" | |
21 #include "components/autofill/browser/autofill_regexes.h" | |
22 #include "components/autofill/browser/autofill_type.h" | |
23 #include "components/autofill/browser/field_types.h" | |
24 #include "components/autofill/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/public/common/unicode/uloc.h" | |
29 #include "third_party/icu/public/i18n/unicode/dtfmtsym.h" | |
30 #include "ui/base/l10n/l10n_util.h" | |
31 | |
32 namespace autofill { | |
33 | |
34 namespace { | |
35 | |
36 const 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. | |
41 const size_t kMaxObfuscationSize = 20; | |
42 | |
43 bool 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 | |
58 bool 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 | |
112 CreditCard::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 | |
119 CreditCard::CreditCard() | |
120 : AutofillDataModel(base::GenerateGUID(), std::string()), | |
121 type_(kGenericCard), | |
122 expiration_month_(0), | |
123 expiration_year_(0) { | |
124 } | |
125 | |
126 CreditCard::CreditCard(const CreditCard& credit_card) | |
127 : AutofillDataModel(std::string(), std::string()) { | |
128 operator=(credit_card); | |
129 } | |
130 | |
131 CreditCard::~CreditCard() {} | |
132 | |
133 // static | |
134 const 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 | |
142 base::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 == kSoloCard) | |
154 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_SOLO); | |
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 | |
165 int 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 == kSoloCard) | |
177 return IDR_AUTOFILL_CC_SOLO; | |
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 | |
188 std::string CreditCard::GetCreditCardType(const base::string16& number) { | |
189 // Don't check for a specific type if this is not a credit card number. | |
190 if (!autofill::IsValidCreditCardNumber(number)) | |
191 return kGenericCard; | |
192 | |
193 // Credit card number specifications taken from: | |
194 // http://en.wikipedia.org/wiki/Credit_card_numbers and | |
195 // http://www.beachnet.com/~hstiles/cardtype.html | |
196 // Card Type Prefix(es) Length | |
197 // --------------------------------------------------------------- | |
198 // Visa 4 13,16 | |
199 // American Express 34,37 15 | |
200 // Diners Club 300-305,2014,2149,36, 14,15 | |
201 // Discover Card 6011,65 16 | |
202 // JCB 3 16 | |
203 // JCB 2131,1800 15 | |
204 // MasterCard 51-55 16 | |
205 // Solo (debit card) 6334,6767 16,18,19 | |
206 | |
207 // We need at least 4 digits to work with. | |
208 if (number.length() < 4) | |
209 return kGenericCard; | |
210 | |
211 int first_four_digits = 0; | |
212 if (!base::StringToInt(number.substr(0, 4), &first_four_digits)) | |
213 return kGenericCard; | |
214 | |
215 int first_three_digits = first_four_digits / 10; | |
216 int first_two_digits = first_three_digits / 10; | |
217 int first_digit = first_two_digits / 10; | |
218 | |
219 switch (number.length()) { | |
220 case 13: | |
221 if (first_digit == 4) | |
222 return kVisaCard; | |
223 | |
224 break; | |
225 case 14: | |
226 if (first_three_digits >= 300 && first_three_digits <= 305) | |
227 return kDinersCard; | |
228 | |
229 if (first_digit == 36) | |
230 return kDinersCard; | |
231 | |
232 break; | |
233 case 15: | |
234 if (first_two_digits == 34 || first_two_digits == 37) | |
235 return kAmericanExpressCard; | |
236 | |
237 if (first_four_digits == 2131 || first_four_digits == 1800) | |
238 return kJCBCard; | |
239 | |
240 if (first_four_digits == 2014 || first_four_digits == 2149) | |
241 return kDinersCard; | |
242 | |
243 break; | |
244 case 16: | |
245 if (first_four_digits == 6011 || first_two_digits == 65) | |
246 return kDiscoverCard; | |
247 | |
248 if (first_four_digits == 6334 || first_four_digits == 6767) | |
249 return kSoloCard; | |
250 | |
251 if (first_two_digits >= 51 && first_two_digits <= 55) | |
252 return kMasterCard; | |
253 | |
254 if (first_digit == 3) | |
255 return kJCBCard; | |
256 | |
257 if (first_digit == 4) | |
258 return kVisaCard; | |
259 | |
260 break; | |
261 case 18: | |
262 case 19: | |
263 if (first_four_digits == 6334 || first_four_digits == 6767) | |
264 return kSoloCard; | |
265 | |
266 break; | |
267 } | |
268 | |
269 return kGenericCard; | |
270 } | |
271 | |
272 base::string16 CreditCard::GetRawInfo(AutofillFieldType type) const { | |
273 switch (type) { | |
274 case CREDIT_CARD_NAME: | |
275 return name_on_card_; | |
276 | |
277 case CREDIT_CARD_EXP_MONTH: | |
278 return ExpirationMonthAsString(); | |
279 | |
280 case CREDIT_CARD_EXP_2_DIGIT_YEAR: | |
281 return Expiration2DigitYearAsString(); | |
282 | |
283 case CREDIT_CARD_EXP_4_DIGIT_YEAR: | |
284 return Expiration4DigitYearAsString(); | |
285 | |
286 case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR: { | |
287 base::string16 month = ExpirationMonthAsString(); | |
288 base::string16 year = Expiration2DigitYearAsString(); | |
289 if (!month.empty() && !year.empty()) | |
290 return month + ASCIIToUTF16("/") + year; | |
291 return base::string16(); | |
292 } | |
293 | |
294 case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR: { | |
295 base::string16 month = ExpirationMonthAsString(); | |
296 base::string16 year = Expiration4DigitYearAsString(); | |
297 if (!month.empty() && !year.empty()) | |
298 return month + ASCIIToUTF16("/") + year; | |
299 return base::string16(); | |
300 } | |
301 | |
302 case CREDIT_CARD_TYPE: | |
303 return TypeForDisplay(); | |
304 | |
305 case CREDIT_CARD_NUMBER: | |
306 return number_; | |
307 | |
308 case CREDIT_CARD_VERIFICATION_CODE: | |
309 // Chrome doesn't store credit card verification codes. | |
310 return base::string16(); | |
311 | |
312 default: | |
313 // ComputeDataPresentForArray will hit this repeatedly. | |
314 return base::string16(); | |
315 } | |
316 } | |
317 | |
318 void CreditCard::SetRawInfo(AutofillFieldType type, | |
319 const base::string16& value) { | |
320 switch (type) { | |
321 case CREDIT_CARD_NAME: | |
322 name_on_card_ = value; | |
323 break; | |
324 | |
325 case CREDIT_CARD_EXP_MONTH: | |
326 SetExpirationMonthFromString(value, std::string()); | |
327 break; | |
328 | |
329 case CREDIT_CARD_EXP_2_DIGIT_YEAR: | |
330 // This is a read-only attribute. | |
331 break; | |
332 | |
333 case CREDIT_CARD_EXP_4_DIGIT_YEAR: | |
334 SetExpirationYearFromString(value); | |
335 break; | |
336 | |
337 case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR: | |
338 // This is a read-only attribute. | |
339 break; | |
340 | |
341 case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR: | |
342 // This is a read-only attribute. | |
343 break; | |
344 | |
345 case CREDIT_CARD_TYPE: | |
346 // This is a read-only attribute, determined by the credit card number. | |
347 break; | |
348 | |
349 case CREDIT_CARD_NUMBER: { | |
350 // Don't change the real value if the input is an obfuscated string. | |
351 if (value.size() > 0 && value[0] != kCreditCardObfuscationSymbol) | |
352 SetNumber(value); | |
353 break; | |
354 } | |
355 | |
356 case CREDIT_CARD_VERIFICATION_CODE: | |
357 // Chrome doesn't store the credit card verification code. | |
358 break; | |
359 | |
360 default: | |
361 NOTREACHED() << "Attempting to set unknown info-type " << type; | |
362 break; | |
363 } | |
364 } | |
365 | |
366 base::string16 CreditCard::GetInfo(AutofillFieldType type, | |
367 const std::string& app_locale) const { | |
368 if (type == CREDIT_CARD_NUMBER) | |
369 return StripSeparators(number_); | |
370 | |
371 return GetRawInfo(type); | |
372 } | |
373 | |
374 bool CreditCard::SetInfo(AutofillFieldType type, | |
375 const base::string16& value, | |
376 const std::string& app_locale) { | |
377 if (type == CREDIT_CARD_NUMBER) | |
378 SetRawInfo(type, StripSeparators(value)); | |
379 else if (type == CREDIT_CARD_EXP_MONTH) | |
380 SetExpirationMonthFromString(value, app_locale); | |
381 else | |
382 SetRawInfo(type, value); | |
383 | |
384 return true; | |
385 } | |
386 | |
387 void CreditCard::GetMatchingTypes(const base::string16& text, | |
388 const std::string& app_locale, | |
389 FieldTypeSet* matching_types) const { | |
390 FormGroup::GetMatchingTypes(text, app_locale, matching_types); | |
391 | |
392 base::string16 card_number = GetInfo(CREDIT_CARD_NUMBER, app_locale); | |
393 if (!card_number.empty() && StripSeparators(text) == card_number) | |
394 matching_types->insert(CREDIT_CARD_NUMBER); | |
395 | |
396 int month; | |
397 if (ConvertMonth(text, app_locale, &month) && month != 0 && | |
398 month == expiration_month_) { | |
399 matching_types->insert(CREDIT_CARD_EXP_MONTH); | |
400 } | |
401 } | |
402 | |
403 const base::string16 CreditCard::Label() const { | |
404 base::string16 label; | |
405 if (number().empty()) | |
406 return name_on_card_; // No CC number, return name only. | |
407 | |
408 base::string16 obfuscated_cc_number = ObfuscatedNumber(); | |
409 if (!expiration_month_ || !expiration_year_) | |
410 return obfuscated_cc_number; // No expiration date set. | |
411 | |
412 // TODO(georgey): Internationalize date. | |
413 base::string16 formatted_date(ExpirationMonthAsString()); | |
414 formatted_date.append(ASCIIToUTF16("/")); | |
415 formatted_date.append(Expiration4DigitYearAsString()); | |
416 | |
417 label = l10n_util::GetStringFUTF16(IDS_CREDIT_CARD_NUMBER_PREVIEW_FORMAT, | |
418 obfuscated_cc_number, | |
419 formatted_date); | |
420 return label; | |
421 } | |
422 | |
423 void CreditCard::SetInfoForMonthInputType(const base::string16& value) { | |
424 // Check if |text| is "yyyy-mm" format first, and check normal month format. | |
425 if (!autofill::MatchesPattern(value, UTF8ToUTF16("^[0-9]{4}-[0-9]{1,2}$"))) | |
426 return; | |
427 | |
428 std::vector<base::string16> year_month; | |
429 base::SplitString(value, L'-', &year_month); | |
430 DCHECK_EQ((int)year_month.size(), 2); | |
431 int num = 0; | |
432 bool converted = false; | |
433 converted = base::StringToInt(year_month[0], &num); | |
434 DCHECK(converted); | |
435 SetExpirationYear(num); | |
436 converted = base::StringToInt(year_month[1], &num); | |
437 DCHECK(converted); | |
438 SetExpirationMonth(num); | |
439 } | |
440 | |
441 base::string16 CreditCard::ObfuscatedNumber() const { | |
442 // If the number is shorter than four digits, there's no need to obfuscate it. | |
443 if (number_.size() < 4) | |
444 return number_; | |
445 | |
446 base::string16 number = StripSeparators(number_); | |
447 | |
448 // Avoid making very long obfuscated numbers. | |
449 size_t obfuscated_digits = std::min(kMaxObfuscationSize, number.size() - 4); | |
450 base::string16 result(obfuscated_digits, kCreditCardObfuscationSymbol); | |
451 return result.append(LastFourDigits()); | |
452 } | |
453 | |
454 base::string16 CreditCard::LastFourDigits() const { | |
455 static const size_t kNumLastDigits = 4; | |
456 | |
457 base::string16 number = StripSeparators(number_); | |
458 if (number.size() < kNumLastDigits) | |
459 return base::string16(); | |
460 | |
461 return number.substr(number.size() - kNumLastDigits, kNumLastDigits); | |
462 } | |
463 | |
464 base::string16 CreditCard::TypeForDisplay() const { | |
465 return CreditCard::TypeForDisplay(type_); | |
466 } | |
467 | |
468 base::string16 CreditCard::TypeAndLastFourDigits() const { | |
469 base::string16 type = TypeForDisplay(); | |
470 // TODO(estade): type may be empty, we probably want to return | |
471 // "Card - 1234" or something in that case. | |
472 | |
473 base::string16 digits = LastFourDigits(); | |
474 if (digits.empty()) | |
475 return type; | |
476 | |
477 // TODO(estade): i18n. | |
478 return type + ASCIIToUTF16(" - ") + digits; | |
479 } | |
480 | |
481 void CreditCard::operator=(const CreditCard& credit_card) { | |
482 if (this == &credit_card) | |
483 return; | |
484 | |
485 number_ = credit_card.number_; | |
486 name_on_card_ = credit_card.name_on_card_; | |
487 type_ = credit_card.type_; | |
488 expiration_month_ = credit_card.expiration_month_; | |
489 expiration_year_ = credit_card.expiration_year_; | |
490 | |
491 set_guid(credit_card.guid()); | |
492 set_origin(credit_card.origin()); | |
493 } | |
494 | |
495 bool CreditCard::UpdateFromImportedCard(const CreditCard& imported_card, | |
496 const std::string& app_locale) { | |
497 if (this->GetInfo(CREDIT_CARD_NUMBER, app_locale) != | |
498 imported_card.GetInfo(CREDIT_CARD_NUMBER, app_locale)) { | |
499 return false; | |
500 } | |
501 | |
502 // Heuristically aggregated data should never overwrite verified data. | |
503 // Instead, discard any heuristically aggregated credit cards that disagree | |
504 // with explicitly entered data, so that the UI is not cluttered with | |
505 // duplicate cards. | |
506 if (this->IsVerified() && !imported_card.IsVerified()) | |
507 return true; | |
508 | |
509 set_origin(imported_card.origin()); | |
510 | |
511 // Note that the card number is intentionally not updated, so as to preserve | |
512 // any formatting (i.e. separator characters). Since the card number is not | |
513 // updated, there is no reason to update the card type, either. | |
514 if (!imported_card.name_on_card_.empty()) | |
515 name_on_card_ = imported_card.name_on_card_; | |
516 | |
517 // The expiration date for |imported_card| should always be set. | |
518 DCHECK(imported_card.expiration_month_ && imported_card.expiration_year_); | |
519 expiration_month_ = imported_card.expiration_month_; | |
520 expiration_year_ = imported_card.expiration_year_; | |
521 | |
522 return true; | |
523 } | |
524 | |
525 void CreditCard::FillFormField(const AutofillField& field, | |
526 size_t /*variant*/, | |
527 const std::string& app_locale, | |
528 FormFieldData* field_data) const { | |
529 DCHECK_EQ(AutofillType::CREDIT_CARD, AutofillType(field.type()).group()); | |
530 DCHECK(field_data); | |
531 | |
532 if (field_data->form_control_type == "select-one") { | |
533 FillSelectControl(field.type(), app_locale, field_data); | |
534 } else if (field_data->form_control_type == "month") { | |
535 // HTML5 input="month" consists of year-month. | |
536 base::string16 year = GetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, app_locale); | |
537 base::string16 month = GetInfo(CREDIT_CARD_EXP_MONTH, app_locale); | |
538 if (!year.empty() && !month.empty()) { | |
539 // Fill the value only if |this| includes both year and month | |
540 // information. | |
541 field_data->value = year + ASCIIToUTF16("-") + month; | |
542 } | |
543 } else { | |
544 field_data->value = GetInfo(field.type(), app_locale); | |
545 } | |
546 } | |
547 | |
548 int CreditCard::Compare(const CreditCard& credit_card) const { | |
549 // The following CreditCard field types are the only types we store in the | |
550 // WebDB so far, so we're only concerned with matching these types in the | |
551 // credit card. | |
552 const AutofillFieldType types[] = { CREDIT_CARD_NAME, | |
553 CREDIT_CARD_NUMBER, | |
554 CREDIT_CARD_EXP_MONTH, | |
555 CREDIT_CARD_EXP_4_DIGIT_YEAR }; | |
556 for (size_t index = 0; index < arraysize(types); ++index) { | |
557 int comparison = GetRawInfo(types[index]).compare( | |
558 credit_card.GetRawInfo(types[index])); | |
559 if (comparison != 0) | |
560 return comparison; | |
561 } | |
562 | |
563 return 0; | |
564 } | |
565 | |
566 bool CreditCard::operator==(const CreditCard& credit_card) const { | |
567 return guid() == credit_card.guid() && | |
568 origin() == credit_card.origin() && | |
569 Compare(credit_card) == 0; | |
570 } | |
571 | |
572 bool CreditCard::operator!=(const CreditCard& credit_card) const { | |
573 return !operator==(credit_card); | |
574 } | |
575 | |
576 bool CreditCard::IsEmpty(const std::string& app_locale) const { | |
577 FieldTypeSet types; | |
578 GetNonEmptyTypes(app_locale, &types); | |
579 return types.empty(); | |
580 } | |
581 | |
582 bool CreditCard::IsComplete() const { | |
583 return | |
584 autofill::IsValidCreditCardNumber(number_) && | |
585 expiration_month_ != 0 && | |
586 expiration_year_ != 0; | |
587 } | |
588 | |
589 void CreditCard::GetSupportedTypes(FieldTypeSet* supported_types) const { | |
590 supported_types->insert(CREDIT_CARD_NAME); | |
591 supported_types->insert(CREDIT_CARD_NUMBER); | |
592 supported_types->insert(CREDIT_CARD_TYPE); | |
593 supported_types->insert(CREDIT_CARD_EXP_MONTH); | |
594 supported_types->insert(CREDIT_CARD_EXP_2_DIGIT_YEAR); | |
595 supported_types->insert(CREDIT_CARD_EXP_4_DIGIT_YEAR); | |
596 supported_types->insert(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR); | |
597 supported_types->insert(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR); | |
598 } | |
599 | |
600 base::string16 CreditCard::ExpirationMonthAsString() const { | |
601 if (expiration_month_ == 0) | |
602 return base::string16(); | |
603 | |
604 base::string16 month = base::IntToString16(expiration_month_); | |
605 if (expiration_month_ >= 10) | |
606 return month; | |
607 | |
608 base::string16 zero = ASCIIToUTF16("0"); | |
609 zero.append(month); | |
610 return zero; | |
611 } | |
612 | |
613 base::string16 CreditCard::Expiration4DigitYearAsString() const { | |
614 if (expiration_year_ == 0) | |
615 return base::string16(); | |
616 | |
617 return base::IntToString16(Expiration4DigitYear()); | |
618 } | |
619 | |
620 base::string16 CreditCard::Expiration2DigitYearAsString() const { | |
621 if (expiration_year_ == 0) | |
622 return base::string16(); | |
623 | |
624 return base::IntToString16(Expiration2DigitYear()); | |
625 } | |
626 | |
627 void CreditCard::SetExpirationMonthFromString(const base::string16& text, | |
628 const std::string& app_locale) { | |
629 int month; | |
630 if (!ConvertMonth(text, app_locale, &month)) | |
631 return; | |
632 | |
633 SetExpirationMonth(month); | |
634 } | |
635 | |
636 void CreditCard::SetExpirationYearFromString(const base::string16& text) { | |
637 int year; | |
638 if (!ConvertYear(text, &year)) | |
639 return; | |
640 | |
641 SetExpirationYear(year); | |
642 } | |
643 | |
644 void CreditCard::SetNumber(const base::string16& number) { | |
645 number_ = number; | |
646 type_ = GetCreditCardType(StripSeparators(number_)); | |
647 } | |
648 | |
649 void CreditCard::SetExpirationMonth(int expiration_month) { | |
650 if (expiration_month < 0 || expiration_month > 12) | |
651 return; | |
652 | |
653 expiration_month_ = expiration_month; | |
654 } | |
655 | |
656 void CreditCard::SetExpirationYear(int expiration_year) { | |
657 if (expiration_year != 0 && | |
658 (expiration_year < 2006 || expiration_year > 10000)) { | |
659 return; | |
660 } | |
661 | |
662 expiration_year_ = expiration_year; | |
663 } | |
664 | |
665 // So we can compare CreditCards with EXPECT_EQ(). | |
666 std::ostream& operator<<(std::ostream& os, const CreditCard& credit_card) { | |
667 return os | |
668 << UTF16ToUTF8(credit_card.Label()) | |
669 << " " | |
670 << credit_card.guid() | |
671 << " " | |
672 << credit_card.origin() | |
673 << " " | |
674 << UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_NAME)) | |
675 << " " | |
676 << UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_TYPE)) | |
677 << " " | |
678 << UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_NUMBER)) | |
679 << " " | |
680 << UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_EXP_MONTH)) | |
681 << " " | |
682 << UTF16ToUTF8(credit_card.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR)); | |
683 } | |
684 | |
685 // These values must match the values in WebKitPlatformSupportImpl in | |
686 // webkit/glue. We send these strings to WebKit, which then asks | |
687 // WebKitPlatformSupportImpl to load the image data. | |
688 const char* const kAmericanExpressCard = "americanExpressCC"; | |
689 const char* const kDinersCard = "dinersCC"; | |
690 const char* const kDiscoverCard = "discoverCC"; | |
691 const char* const kGenericCard = "genericCC"; | |
692 const char* const kJCBCard = "jcbCC"; | |
693 const char* const kMasterCard = "masterCardCC"; | |
694 const char* const kSoloCard = "soloCC"; | |
695 const char* const kVisaCard = "visaCC"; | |
696 | |
697 } // namespace autofill | |
OLD | NEW |