| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "app/l10n_util.h" |
| 7 #include "base/scoped_ptr.h" | 8 #include "base/scoped_ptr.h" |
| 8 #include "base/string16.h" | 9 #include "base/string16.h" |
| 9 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
| 10 #include "chrome/browser/autofill/autofill_field.h" | 11 #include "chrome/browser/autofill/autofill_field.h" |
| 12 #include "grit/autofill_resources.h" |
| 11 | 13 |
| 12 bool CreditCardField::GetFieldInfo(FieldTypeMap* field_type_map) const { | 14 bool CreditCardField::GetFieldInfo(FieldTypeMap* field_type_map) const { |
| 13 bool ok = Add(field_type_map, number_, AutoFillType(CREDIT_CARD_NUMBER)); | 15 bool ok = Add(field_type_map, number_, AutoFillType(CREDIT_CARD_NUMBER)); |
| 14 DCHECK(ok); | 16 DCHECK(ok); |
| 15 | 17 |
| 16 // If the heuristics detected first and last name in separate fields, | 18 // If the heuristics detected first and last name in separate fields, |
| 17 // then ignore both fields. Putting them into separate fields is probably | 19 // then ignore both fields. Putting them into separate fields is probably |
| 18 // wrong, because the credit card can also contain a middle name or middle | 20 // wrong, because the credit card can also contain a middle name or middle |
| 19 // initial. | 21 // initial. |
| 20 if (cardholder_last_ == NULL) { | 22 if (cardholder_last_ == NULL) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 // we search for "name" only when we've already parsed at least one other | 59 // we search for "name" only when we've already parsed at least one other |
| 58 // credit card field and haven't yet parsed the expiration date (which | 60 // credit card field and haven't yet parsed the expiration date (which |
| 59 // usually appears at the end). | 61 // usually appears at the end). |
| 60 if (credit_card_field->cardholder_ == NULL) { | 62 if (credit_card_field->cardholder_ == NULL) { |
| 61 string16 name_pattern; | 63 string16 name_pattern; |
| 62 if (is_ecml) { | 64 if (is_ecml) { |
| 63 name_pattern = GetEcmlPattern(kEcmlCardHolder); | 65 name_pattern = GetEcmlPattern(kEcmlCardHolder); |
| 64 } else { | 66 } else { |
| 65 if (fields == 0 || credit_card_field->expiration_month_) { | 67 if (fields == 0 || credit_card_field->expiration_month_) { |
| 66 // at beginning or end | 68 // at beginning or end |
| 67 name_pattern = ASCIIToUTF16("card holder|name on card|nameoncard"); | 69 name_pattern = l10n_util::GetStringUTF16( |
| 70 IDS_AUTOFILL_NAME_ON_CARD_RE); |
| 68 } else { | 71 } else { |
| 69 name_pattern = ASCIIToUTF16("name"); | 72 name_pattern = l10n_util::GetStringUTF16( |
| 73 IDS_AUTOFILL_NAME_ON_CARD_CONTEXTUAL_RE); |
| 70 } | 74 } |
| 71 } | 75 } |
| 72 | 76 |
| 73 if (ParseText(&q, name_pattern, &credit_card_field->cardholder_)) | 77 if (ParseText(&q, name_pattern, &credit_card_field->cardholder_)) |
| 74 continue; | 78 continue; |
| 75 | 79 |
| 76 // As a hard-coded hack for Expedia's billing pages (expedia_checkout.html | 80 // As a hard-coded hack for Expedia's billing pages (expedia_checkout.html |
| 77 // and ExpediaBilling.html in our test suite), recognize separate fields | 81 // and ExpediaBilling.html in our test suite), recognize separate fields |
| 78 // for the cardholder's first and last name if they have the labels "cfnm" | 82 // for the cardholder's first and last name if they have the labels "cfnm" |
| 79 // and "clnm". | 83 // and "clnm". |
| 80 std::vector<AutoFillField*>::const_iterator p = q; | 84 std::vector<AutoFillField*>::const_iterator p = q; |
| 81 AutoFillField* first; | 85 AutoFillField* first; |
| 82 if (!is_ecml && ParseText(&p, ASCIIToUTF16("^cfnm"), &first) && | 86 if (!is_ecml && ParseText(&p, ASCIIToUTF16("^cfnm"), &first) && |
| 83 ParseText(&p, ASCIIToUTF16("^clnm"), | 87 ParseText(&p, ASCIIToUTF16("^clnm"), |
| 84 &credit_card_field->cardholder_last_)) { | 88 &credit_card_field->cardholder_last_)) { |
| 85 credit_card_field->cardholder_ = first; | 89 credit_card_field->cardholder_ = first; |
| 86 q = p; | 90 q = p; |
| 87 continue; | 91 continue; |
| 88 } | 92 } |
| 89 } | 93 } |
| 90 | 94 |
| 91 // We look for a card security code before we look for a credit | 95 // We look for a card security code before we look for a credit |
| 92 // card number and match the general term "number". The security code | 96 // card number and match the general term "number". The security code |
| 93 // has a plethora of names; we've seen "verification #", | 97 // has a plethora of names; we've seen "verification #", |
| 94 // "verification number", "card identification number" and others listed | 98 // "verification number", "card identification number" and others listed |
| 95 // in the |pattern| below. | 99 // in the |pattern| below. |
| 96 if (is_ecml) { | 100 if (is_ecml) { |
| 97 pattern = GetEcmlPattern(kEcmlCardVerification); | 101 pattern = GetEcmlPattern(kEcmlCardVerification); |
| 98 } else { | 102 } else { |
| 99 pattern = ASCIIToUTF16("verification|card identification|cvn|" | 103 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_CARD_CVC_RE); |
| 100 "security code|cvv code|cvc"); | |
| 101 } | 104 } |
| 102 | 105 |
| 103 if (credit_card_field->verification_ == NULL && | 106 if (credit_card_field->verification_ == NULL && |
| 104 ParseText(&q, pattern, &credit_card_field->verification_)) | 107 ParseText(&q, pattern, &credit_card_field->verification_)) |
| 105 continue; | 108 continue; |
| 106 | 109 |
| 107 // TODO(jhawkins): Parse the type select control. | 110 // TODO(jhawkins): Parse the type select control. |
| 108 | 111 |
| 109 if (is_ecml) | 112 if (is_ecml) |
| 110 pattern = GetEcmlPattern(kEcmlCardNumber); | 113 pattern = GetEcmlPattern(kEcmlCardNumber); |
| 111 else | 114 else |
| 112 pattern = ASCIIToUTF16("number|card #|card no.|card_number|card number"); | 115 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_CARD_NUMBER_RE); |
| 113 | 116 |
| 114 if (credit_card_field->number_ == NULL && ParseText(&q, pattern, | 117 if (credit_card_field->number_ == NULL && ParseText(&q, pattern, |
| 115 &credit_card_field->number_)) | 118 &credit_card_field->number_)) |
| 116 continue; | 119 continue; |
| 117 | 120 |
| 118 // "Expiration date" is the most common label here, but some pages have | 121 // "Expiration date" is the most common label here, but some pages have |
| 119 // "Expires", "exp. date" or "exp. month" and "exp. year". We also look for | 122 // "Expires", "exp. date" or "exp. month" and "exp. year". We also look for |
| 120 // the field names ccmonth and ccyear, which appear on at least 4 of our | 123 // the field names ccmonth and ccyear, which appear on at least 4 of our |
| 121 // test pages. | 124 // test pages. |
| 122 // | 125 // |
| 123 // -> On at least one page (The China Shop2.html) we find only the labels | 126 // -> On at least one page (The China Shop2.html) we find only the labels |
| 124 // "month" and "year". So for now we match these words directly; we'll | 127 // "month" and "year". So for now we match these words directly; we'll |
| 125 // see if this turns out to be too general. | 128 // see if this turns out to be too general. |
| 126 // | 129 // |
| 127 // Toolbar Bug 51451: indeed, simply matching "month" is too general for | 130 // Toolbar Bug 51451: indeed, simply matching "month" is too general for |
| 128 // https://rps.fidelity.com/ftgw/rps/RtlCust/CreatePIN/Init. | 131 // https://rps.fidelity.com/ftgw/rps/RtlCust/CreatePIN/Init. |
| 129 // Instead, we match only words beginning with "month". | 132 // Instead, we match only words beginning with "month". |
| 130 if (is_ecml) | 133 if (is_ecml) |
| 131 pattern = GetEcmlPattern(kEcmlCardExpireMonth); | 134 pattern = GetEcmlPattern(kEcmlCardExpireMonth); |
| 132 else | 135 else |
| 133 pattern = ASCIIToUTF16("expir|exp.*month|exp date|ccmonth"); | 136 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_EXPIRATION_MONTH_RE); |
| 134 | 137 |
| 135 if ((!credit_card_field->expiration_month_ || | 138 if ((!credit_card_field->expiration_month_ || |
| 136 credit_card_field->expiration_month_->IsEmpty()) && | 139 credit_card_field->expiration_month_->IsEmpty()) && |
| 137 ParseText(&q, pattern, &credit_card_field->expiration_month_)) { | 140 ParseText(&q, pattern, &credit_card_field->expiration_month_)) { |
| 138 if (is_ecml) | 141 if (is_ecml) |
| 139 pattern = GetEcmlPattern(kEcmlCardExpireYear); | 142 pattern = GetEcmlPattern(kEcmlCardExpireYear); |
| 140 else | 143 else |
| 141 pattern = ASCIIToUTF16("|exp|^/|ccyear|year"); | 144 pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_EXPIRATION_DATE_RE); |
| 142 | 145 |
| 143 if (!ParseText(&q, pattern, &credit_card_field->expiration_year_)) | 146 if (!ParseText(&q, pattern, &credit_card_field->expiration_year_)) |
| 144 return NULL; | 147 return NULL; |
| 145 | 148 |
| 146 continue; | 149 continue; |
| 147 } | 150 } |
| 148 | 151 |
| 149 if (ParseText(&q, GetEcmlPattern(kEcmlCardExpireDay))) | 152 if (ParseText(&q, GetEcmlPattern(kEcmlCardExpireDay))) |
| 150 continue; | 153 continue; |
| 151 | 154 |
| 152 // Some pages (e.g. ExpediaBilling.html) have a "card description" | 155 // Some pages (e.g. ExpediaBilling.html) have a "card description" |
| 153 // field; we parse this field but ignore it. | 156 // field; we parse this field but ignore it. |
| 154 // We also ignore any other fields within a credit card block that | 157 // We also ignore any other fields within a credit card block that |
| 155 // start with "card", under the assumption that they are related to | 158 // start with "card", under the assumption that they are related to |
| 156 // the credit card section being processed but are uninteresting to us. | 159 // the credit card section being processed but are uninteresting to us. |
| 157 if (ParseText(&q, ASCIIToUTF16("^card"))) | 160 if (ParseText(&q, l10n_util::GetStringUTF16(IDS_AUTOFILL_CARD_IGNORED_RE))) |
| 158 continue; | 161 continue; |
| 159 | 162 |
| 160 break; | 163 break; |
| 161 } | 164 } |
| 162 | 165 |
| 163 // Some pages have a billing address field after the cardholder name field. | 166 // Some pages have a billing address field after the cardholder name field. |
| 164 // For that case, allow only just the cardholder name field. The remaining | 167 // For that case, allow only just the cardholder name field. The remaining |
| 165 // CC fields will be picked up in a following CreditCardField. | 168 // CC fields will be picked up in a following CreditCardField. |
| 166 if (credit_card_field->cardholder_) { | 169 if (credit_card_field->cardholder_) { |
| 167 *iter = q; | 170 *iter = q; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 187 | 190 |
| 188 CreditCardField::CreditCardField() | 191 CreditCardField::CreditCardField() |
| 189 : cardholder_(NULL), | 192 : cardholder_(NULL), |
| 190 cardholder_last_(NULL), | 193 cardholder_last_(NULL), |
| 191 type_(NULL), | 194 type_(NULL), |
| 192 number_(NULL), | 195 number_(NULL), |
| 193 verification_(NULL), | 196 verification_(NULL), |
| 194 expiration_month_(NULL), | 197 expiration_month_(NULL), |
| 195 expiration_year_(NULL) { | 198 expiration_year_(NULL) { |
| 196 } | 199 } |
| OLD | NEW |