OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/autofill/credit_card_field.h" | 5 #include "chrome/browser/autofill/credit_card_field.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
11 #include "base/string16.h" | 11 #include "base/string16.h" |
12 #include "base/string_util.h" | 12 #include "base/string_util.h" |
13 #include "base/utf_string_conversions.h" | 13 #include "base/utf_string_conversions.h" |
14 #include "chrome/browser/autofill/autofill_ecml.h" | |
15 #include "chrome/browser/autofill/autofill_field.h" | 14 #include "chrome/browser/autofill/autofill_field.h" |
16 #include "chrome/browser/autofill/autofill_scanner.h" | 15 #include "chrome/browser/autofill/autofill_scanner.h" |
17 #include "chrome/browser/autofill/field_types.h" | 16 #include "chrome/browser/autofill/field_types.h" |
18 #include "grit/autofill_resources.h" | 17 #include "grit/autofill_resources.h" |
19 #include "ui/base/l10n/l10n_util.h" | 18 #include "ui/base/l10n/l10n_util.h" |
20 | 19 |
21 using autofill::GetEcmlPattern; | |
22 | |
23 // static | 20 // static |
24 FormField* CreditCardField::Parse(AutofillScanner* scanner, | 21 FormField* CreditCardField::Parse(AutofillScanner* scanner) { |
25 bool is_ecml) { | |
26 if (scanner->IsEnd()) | 22 if (scanner->IsEnd()) |
27 return NULL; | 23 return NULL; |
28 | 24 |
29 scoped_ptr<CreditCardField> credit_card_field(new CreditCardField); | 25 scoped_ptr<CreditCardField> credit_card_field(new CreditCardField); |
30 size_t saved_cursor = scanner->SaveCursor(); | 26 size_t saved_cursor = scanner->SaveCursor(); |
31 | 27 |
32 // Credit card fields can appear in many different orders. | 28 // Credit card fields can appear in many different orders. |
33 // We loop until no more credit card related fields are found, see |break| at | 29 // We loop until no more credit card related fields are found, see |break| at |
34 // bottom of the loop. | 30 // bottom of the loop. |
35 for (int fields = 0; !scanner->IsEnd(); ++fields) { | 31 for (int fields = 0; !scanner->IsEnd(); ++fields) { |
36 // Sometimes the cardholder field is just labeled "name". Unfortunately this | 32 // Sometimes the cardholder field is just labeled "name". Unfortunately this |
37 // is a dangerously generic word to search for, since it will often match a | 33 // is a dangerously generic word to search for, since it will often match a |
38 // name (not cardholder name) field before or after credit card fields. So | 34 // name (not cardholder name) field before or after credit card fields. So |
39 // we search for "name" only when we've already parsed at least one other | 35 // we search for "name" only when we've already parsed at least one other |
40 // credit card field and haven't yet parsed the expiration date (which | 36 // credit card field and haven't yet parsed the expiration date (which |
41 // usually appears at the end). | 37 // usually appears at the end). |
42 if (credit_card_field->cardholder_ == NULL) { | 38 if (credit_card_field->cardholder_ == NULL) { |
43 string16 name_pattern; | 39 string16 name_pattern; |
44 if (is_ecml) { | 40 if (fields == 0 || credit_card_field->expiration_month_) { |
45 name_pattern = GetEcmlPattern(kEcmlCardHolder); | 41 // at beginning or end |
| 42 name_pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_NAME_ON_CARD_RE); |
46 } else { | 43 } else { |
47 if (fields == 0 || credit_card_field->expiration_month_) { | 44 name_pattern = l10n_util::GetStringUTF16( |
48 // at beginning or end | 45 IDS_AUTOFILL_NAME_ON_CARD_CONTEXTUAL_RE); |
49 name_pattern = l10n_util::GetStringUTF16( | |
50 IDS_AUTOFILL_NAME_ON_CARD_RE); | |
51 } else { | |
52 name_pattern = l10n_util::GetStringUTF16( | |
53 IDS_AUTOFILL_NAME_ON_CARD_CONTEXTUAL_RE); | |
54 } | |
55 } | 46 } |
56 | 47 |
57 if (ParseField(scanner, name_pattern, &credit_card_field->cardholder_)) | 48 if (ParseField(scanner, name_pattern, &credit_card_field->cardholder_)) |
58 continue; | 49 continue; |
59 | 50 |
60 // As a hard-coded hack for Expedia's billing pages (expedia_checkout.html | 51 // As a hard-coded hack for Expedia's billing pages (expedia_checkout.html |
61 // and ExpediaBilling.html in our test suite), recognize separate fields | 52 // and ExpediaBilling.html in our test suite), recognize separate fields |
62 // for the cardholder's first and last name if they have the labels "cfnm" | 53 // for the cardholder's first and last name if they have the labels "cfnm" |
63 // and "clnm". | 54 // and "clnm". |
64 scanner->SaveCursor(); | 55 scanner->SaveCursor(); |
65 const AutofillField* first; | 56 const AutofillField* first; |
66 if (!is_ecml && ParseField(scanner, ASCIIToUTF16("^cfnm"), &first) && | 57 if (ParseField(scanner, ASCIIToUTF16("^cfnm"), &first) && |
67 ParseField(scanner, ASCIIToUTF16("^clnm"), | 58 ParseField(scanner, ASCIIToUTF16("^clnm"), |
68 &credit_card_field->cardholder_last_)) { | 59 &credit_card_field->cardholder_last_)) { |
69 credit_card_field->cardholder_ = first; | 60 credit_card_field->cardholder_ = first; |
70 continue; | 61 continue; |
71 } | 62 } |
72 scanner->Rewind(); | 63 scanner->Rewind(); |
73 } | 64 } |
74 | 65 |
75 // We look for a card security code before we look for a credit | 66 // We look for a card security code before we look for a credit |
76 // card number and match the general term "number". The security code | 67 // card number and match the general term "number". The security code |
77 // has a plethora of names; we've seen "verification #", | 68 // has a plethora of names; we've seen "verification #", |
78 // "verification number", "card identification number" and others listed | 69 // "verification number", "card identification number" and others listed |
79 // in the |pattern| below. | 70 // in the |pattern| below. |
80 string16 pattern; | 71 string16 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_CARD_CVC_RE); |
81 if (is_ecml) | |
82 pattern = GetEcmlPattern(kEcmlCardVerification); | |
83 else | |
84 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_CARD_CVC_RE); | |
85 | |
86 if (!credit_card_field->verification_ && | 72 if (!credit_card_field->verification_ && |
87 ParseField(scanner, pattern, &credit_card_field->verification_)) { | 73 ParseField(scanner, pattern, &credit_card_field->verification_)) { |
88 continue; | 74 continue; |
89 } | 75 } |
90 // TODO(jhawkins): Parse the type select control. | 76 // TODO(jhawkins): Parse the type select control. |
91 | 77 |
92 if (is_ecml) | 78 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_CARD_NUMBER_RE); |
93 pattern = GetEcmlPattern(kEcmlCardNumber); | |
94 else | |
95 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_CARD_NUMBER_RE); | |
96 | |
97 if (!credit_card_field->number_ && | 79 if (!credit_card_field->number_ && |
98 ParseField(scanner, pattern, &credit_card_field->number_)) { | 80 ParseField(scanner, pattern, &credit_card_field->number_)) { |
99 continue; | 81 continue; |
100 } | 82 } |
101 | 83 |
102 if (LowerCaseEqualsASCII(scanner->Cursor()->form_control_type, "month")) { | 84 if (LowerCaseEqualsASCII(scanner->Cursor()->form_control_type, "month")) { |
103 credit_card_field->expiration_month_ = scanner->Cursor(); | 85 credit_card_field->expiration_month_ = scanner->Cursor(); |
104 scanner->Advance(); | 86 scanner->Advance(); |
105 } else { | 87 } else { |
106 // "Expiration date" is the most common label here, but some pages have | 88 // "Expiration date" is the most common label here, but some pages have |
107 // "Expires", "exp. date" or "exp. month" and "exp. year". We also look | 89 // "Expires", "exp. date" or "exp. month" and "exp. year". We also look |
108 // for the field names ccmonth and ccyear, which appear on at least 4 of | 90 // for the field names ccmonth and ccyear, which appear on at least 4 of |
109 // our test pages. | 91 // our test pages. |
110 // | 92 // |
111 // -> On at least one page (The China Shop2.html) we find only the labels | 93 // -> On at least one page (The China Shop2.html) we find only the labels |
112 // "month" and "year". So for now we match these words directly; we'll | 94 // "month" and "year". So for now we match these words directly; we'll |
113 // see if this turns out to be too general. | 95 // see if this turns out to be too general. |
114 // | 96 // |
115 // Toolbar Bug 51451: indeed, simply matching "month" is too general for | 97 // Toolbar Bug 51451: indeed, simply matching "month" is too general for |
116 // https://rps.fidelity.com/ftgw/rps/RtlCust/CreatePIN/Init. | 98 // https://rps.fidelity.com/ftgw/rps/RtlCust/CreatePIN/Init. |
117 // Instead, we match only words beginning with "month". | 99 // Instead, we match only words beginning with "month". |
118 if (is_ecml) | 100 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_EXPIRATION_MONTH_RE); |
119 pattern = GetEcmlPattern(kEcmlCardExpireMonth); | |
120 else | |
121 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_EXPIRATION_MONTH_RE); | |
122 | |
123 if ((!credit_card_field->expiration_month_ || | 101 if ((!credit_card_field->expiration_month_ || |
124 credit_card_field->expiration_month_->IsEmpty()) && | 102 credit_card_field->expiration_month_->IsEmpty()) && |
125 ParseFieldSpecifics(scanner, pattern, MATCH_DEFAULT | MATCH_SELECT, | 103 ParseFieldSpecifics(scanner, pattern, MATCH_DEFAULT | MATCH_SELECT, |
126 &credit_card_field->expiration_month_)) { | 104 &credit_card_field->expiration_month_)) { |
127 if (is_ecml) | 105 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_EXPIRATION_DATE_RE); |
128 pattern = GetEcmlPattern(kEcmlCardExpireYear); | |
129 else | |
130 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_EXPIRATION_DATE_RE); | |
131 | |
132 if (!ParseFieldSpecifics(scanner, pattern, MATCH_DEFAULT | MATCH_SELECT, | 106 if (!ParseFieldSpecifics(scanner, pattern, MATCH_DEFAULT | MATCH_SELECT, |
133 &credit_card_field->expiration_year_)) { | 107 &credit_card_field->expiration_year_)) { |
134 scanner->RewindTo(saved_cursor); | 108 scanner->RewindTo(saved_cursor); |
135 return NULL; | 109 return NULL; |
136 } | 110 } |
137 continue; | 111 continue; |
138 } | 112 } |
139 } | 113 } |
140 | 114 |
141 if (ParseFieldSpecifics(scanner, GetEcmlPattern(kEcmlCardExpireDay), | |
142 MATCH_DEFAULT | MATCH_SELECT, NULL)) { | |
143 continue; | |
144 } | |
145 | |
146 // Some pages (e.g. ExpediaBilling.html) have a "card description" | 115 // Some pages (e.g. ExpediaBilling.html) have a "card description" |
147 // field; we parse this field but ignore it. | 116 // field; we parse this field but ignore it. |
148 // We also ignore any other fields within a credit card block that | 117 // We also ignore any other fields within a credit card block that |
149 // start with "card", under the assumption that they are related to | 118 // start with "card", under the assumption that they are related to |
150 // the credit card section being processed but are uninteresting to us. | 119 // the credit card section being processed but are uninteresting to us. |
151 if (ParseField(scanner, | 120 if (ParseField(scanner, |
152 l10n_util::GetStringUTF16(IDS_AUTOFILL_CARD_IGNORED_RE), | 121 l10n_util::GetStringUTF16(IDS_AUTOFILL_CARD_IGNORED_RE), |
153 NULL)) { | 122 NULL)) { |
154 continue; | 123 continue; |
155 } | 124 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 if (cardholder_last_ == NULL) | 172 if (cardholder_last_ == NULL) |
204 ok = ok && AddClassification(cardholder_, CREDIT_CARD_NAME, map); | 173 ok = ok && AddClassification(cardholder_, CREDIT_CARD_NAME, map); |
205 | 174 |
206 ok = ok && AddClassification(type_, CREDIT_CARD_TYPE, map); | 175 ok = ok && AddClassification(type_, CREDIT_CARD_TYPE, map); |
207 ok = ok && AddClassification(expiration_month_, CREDIT_CARD_EXP_MONTH, map); | 176 ok = ok && AddClassification(expiration_month_, CREDIT_CARD_EXP_MONTH, map); |
208 ok = ok && AddClassification(expiration_year_, | 177 ok = ok && AddClassification(expiration_year_, |
209 CREDIT_CARD_EXP_4_DIGIT_YEAR, | 178 CREDIT_CARD_EXP_4_DIGIT_YEAR, |
210 map); | 179 map); |
211 return ok; | 180 return ok; |
212 } | 181 } |
OLD | NEW |