1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/autofill/credit_card_field.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <stddef.h>
8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/logging.h"
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string16.h"
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/string_util.h"
133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/autofill/autofill_field.h"
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/autofill/field_types.h"
163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "grit/autofill_resources.h"
1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool CreditCardField::GetFieldInfo(FieldTypeMap* field_type_map) const {
20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bool ok = Add(field_type_map, number_, AutofillType(CREDIT_CARD_NUMBER));
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(ok);
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If the heuristics detected first and last name in separate fields,
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // then ignore both fields. Putting them into separate fields is probably
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // wrong, because the credit card can also contain a middle name or middle
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // initial.
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cardholder_last_ == NULL) {
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Add() will check if cardholder_ is != NULL.
29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ok = ok && Add(field_type_map, cardholder_, AutofillType(CREDIT_CARD_NAME));
303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DCHECK(ok);
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ok = ok && Add(field_type_map, type_, AutofillType(CREDIT_CARD_TYPE));
343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(ok);
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ok = ok && Add(field_type_map, expiration_month_,
36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      AutofillType(CREDIT_CARD_EXP_MONTH));
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(ok);
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ok = ok && Add(field_type_map, expiration_year_,
39dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      AutofillType(CREDIT_CARD_EXP_4_DIGIT_YEAR));
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(ok);
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return ok;
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
45731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickFormFieldType CreditCardField::GetFormFieldType() const {
46731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return kCreditCardType;
47731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
48731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochCreditCardField* CreditCardField::Parse(
51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    std::vector<AutofillField*>::const_iterator* iter,
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool is_ecml) {
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<CreditCardField> credit_card_field(new CreditCardField);
54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  std::vector<AutofillField*>::const_iterator q = *iter;
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  string16 pattern;
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Credit card fields can appear in many different orders.
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We loop until no more credit card related fields are found, see |break| at
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // bottom of the loop.
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int fields = 0; true; ++fields) {
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Sometimes the cardholder field is just labeled "name". Unfortunately this
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // is a dangerously generic word to search for, since it will often match a
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // name (not cardholder name) field before or after credit card fields. So
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // we search for "name" only when we've already parsed at least one other
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // credit card field and haven't yet parsed the expiration date (which
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // usually appears at the end).
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (credit_card_field->cardholder_ == NULL) {
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      string16 name_pattern;
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (is_ecml) {
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        name_pattern = GetEcmlPattern(kEcmlCardHolder);
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (fields == 0 || credit_card_field->expiration_month_) {
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // at beginning or end
74d8e800e5cd4b5ff1c84124f27b98f9c174ec2738Ben Murdoch          name_pattern = l10n_util::GetStringUTF16(
75d8e800e5cd4b5ff1c84124f27b98f9c174ec2738Ben Murdoch              IDS_AUTOFILL_NAME_ON_CARD_RE);
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        } else {
77d8e800e5cd4b5ff1c84124f27b98f9c174ec2738Ben Murdoch          name_pattern = l10n_util::GetStringUTF16(
78d8e800e5cd4b5ff1c84124f27b98f9c174ec2738Ben Murdoch              IDS_AUTOFILL_NAME_ON_CARD_CONTEXTUAL_RE);
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
82731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      if (ParseText(&q, name_pattern, &credit_card_field->cardholder_))
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        continue;
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // As a hard-coded hack for Expedia's billing pages (expedia_checkout.html
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // and ExpediaBilling.html in our test suite), recognize separate fields
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // for the cardholder's first and last name if they have the labels "cfnm"
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // and "clnm".
89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      std::vector<AutofillField*>::const_iterator p = q;
90dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      AutofillField* first;
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (!is_ecml && ParseText(&p, ASCIIToUTF16("^cfnm"), &first) &&
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          ParseText(&p, ASCIIToUTF16("^clnm"),
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    &credit_card_field->cardholder_last_)) {
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        credit_card_field->cardholder_ = first;
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        q = p;
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        continue;
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
100201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // We look for a card security code before we look for a credit
101201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // card number and match the general term "number".  The security code
102201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // has a plethora of names; we've seen "verification #",
103201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // "verification number", "card identification number" and others listed
104201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // in the |pattern| below.
105201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (is_ecml) {
106201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      pattern = GetEcmlPattern(kEcmlCardVerification);
107201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    } else {
108d8e800e5cd4b5ff1c84124f27b98f9c174ec2738Ben Murdoch      pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_CARD_CVC_RE);
109201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    }
110201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
111201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (credit_card_field->verification_ == NULL &&
112201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        ParseText(&q, pattern, &credit_card_field->verification_))
113201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      continue;
114201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // TODO(jhawkins): Parse the type select control.
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (is_ecml)
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      pattern = GetEcmlPattern(kEcmlCardNumber);
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    else
120d8e800e5cd4b5ff1c84124f27b98f9c174ec2738Ben Murdoch      pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_CARD_NUMBER_RE);
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (credit_card_field->number_ == NULL && ParseText(&q, pattern,
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        &credit_card_field->number_))
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      continue;
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if ((*q) && LowerCaseEqualsASCII((*q)->form_control_type, "month")) {
12772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      credit_card_field->expiration_month_ = *q++;
12872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    } else {
12972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // "Expiration date" is the most common label here, but some pages have
13072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // "Expires", "exp. date" or "exp. month" and "exp. year".  We also look
13172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // for the field names ccmonth and ccyear, which appear on at least 4 of
13272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // our test pages.
13372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      //
13472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // -> On at least one page (The China Shop2.html) we find only the labels
13572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // "month" and "year".  So for now we match these words directly; we'll
13672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // see if this turns out to be too general.
13772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      //
13872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // Toolbar Bug 51451: indeed, simply matching "month" is too general for
13972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      //   https://rps.fidelity.com/ftgw/rps/RtlCust/CreatePIN/Init.
14072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // Instead, we match only words beginning with "month".
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (is_ecml)
14272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        pattern = GetEcmlPattern(kEcmlCardExpireMonth);
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      else
14472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_EXPIRATION_MONTH_RE);
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
14672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if ((!credit_card_field->expiration_month_ ||
14772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          credit_card_field->expiration_month_->IsEmpty()) &&
14872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        ParseText(&q, pattern, &credit_card_field->expiration_month_)) {
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
15072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        if (is_ecml)
15172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          pattern = GetEcmlPattern(kEcmlCardExpireYear);
15272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        else
15372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_EXPIRATION_DATE_RE);
15472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
15572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        if (!ParseText(&q, pattern, &credit_card_field->expiration_year_)) {
15672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          return NULL;
15772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        }
15872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        continue;
15972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (ParseText(&q, GetEcmlPattern(kEcmlCardExpireDay)))
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      continue;
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Some pages (e.g. ExpediaBilling.html) have a "card description"
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // field; we parse this field but ignore it.
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We also ignore any other fields within a credit card block that
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // start with "card", under the assumption that they are related to
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // the credit card section being processed but are uninteresting to us.
170d8e800e5cd4b5ff1c84124f27b98f9c174ec2738Ben Murdoch    if (ParseText(&q, l10n_util::GetStringUTF16(IDS_AUTOFILL_CARD_IGNORED_RE)))
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      continue;
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    break;
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
176731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Some pages have a billing address field after the cardholder name field.
177731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // For that case, allow only just the cardholder name field.  The remaining
178731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // CC fields will be picked up in a following CreditCardField.
179731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (credit_card_field->cardholder_) {
180731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    *iter = q;
181731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return credit_card_field.release();
182731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
183731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // On some pages, the user selects a card type using radio buttons
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // (e.g. test page Apple Store Billing.html).  We can't handle that yet,
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // so we treat the card type as optional for now.
187201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // The existence of a number or cvc in combination with expiration date is
188201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // a strong enough signal that this is a credit card.  It is possible that
189201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // the number and name were parsed in a separate part of the form.  So if
190201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // the cvc and date were found independently they are returned.
191201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if ((credit_card_field->number_ || credit_card_field->verification_) &&
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      credit_card_field->expiration_month_ &&
19372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      (credit_card_field->expiration_year_ ||
19472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      (LowerCaseEqualsASCII(
195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen           credit_card_field->expiration_month_->form_control_type,
19672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen           "month")))) {
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      *iter = q;
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return credit_card_field.release();
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return NULL;
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochCreditCardField::CreditCardField()
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : cardholder_(NULL),
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      cardholder_last_(NULL),
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      type_(NULL),
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      number_(NULL),
209201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      verification_(NULL),
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      expiration_month_(NULL),
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      expiration_year_(NULL) {
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
213