| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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 "components/autofill/core/browser/credit_card_field.h" | 5 #include "components/autofill/core/browser/credit_card_field.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR: { | 65 case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR: { |
| 66 static int kMinimum4YearCcExpLength = strlen("12/2014"); | 66 static int kMinimum4YearCcExpLength = strlen("12/2014"); |
| 67 return max_length >= kMinimum4YearCcExpLength; | 67 return max_length >= kMinimum4YearCcExpLength; |
| 68 } | 68 } |
| 69 default: | 69 default: |
| 70 NOTREACHED(); | 70 NOTREACHED(); |
| 71 return false; | 71 return false; |
| 72 } | 72 } |
| 73 } | 73 } |
| 74 | 74 |
| 75 | |
| 76 } // namespace | 75 } // namespace |
| 77 | 76 |
| 78 // static | 77 // static |
| 79 scoped_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner) { | 78 scoped_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner) { |
| 80 if (scanner->IsEnd()) | 79 if (scanner->IsEnd()) |
| 81 return nullptr; | 80 return nullptr; |
| 82 | 81 |
| 83 scoped_ptr<CreditCardField> credit_card_field(new CreditCardField); | 82 scoped_ptr<CreditCardField> credit_card_field(new CreditCardField); |
| 84 size_t saved_cursor = scanner->SaveCursor(); | 83 size_t saved_cursor = scanner->SaveCursor(); |
| 85 | 84 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 scanner->Advance(); | 129 scanner->Advance(); |
| 131 continue; | 130 continue; |
| 132 } | 131 } |
| 133 | 132 |
| 134 // We look for a card security code before we look for a credit card number | 133 // We look for a card security code before we look for a credit card number |
| 135 // and match the general term "number". The security code has a plethora of | 134 // and match the general term "number". The security code has a plethora of |
| 136 // names; we've seen "verification #", "verification number", "card | 135 // names; we've seen "verification #", "verification number", "card |
| 137 // identification number", and others listed in the regex pattern used | 136 // identification number", and others listed in the regex pattern used |
| 138 // below. | 137 // below. |
| 139 // Note: Some sites use type="tel" or type="number" for numerical inputs. | 138 // Note: Some sites use type="tel" or type="number" for numerical inputs. |
| 140 const int kMatchNumAndTel = MATCH_DEFAULT | MATCH_NUMBER | MATCH_TELEPHONE; | 139 // They also sometimes use type="password" for sensitive types. |
| 140 const int kMatchNumTelAndPwd = |
| 141 MATCH_DEFAULT | MATCH_NUMBER | MATCH_TELEPHONE | MATCH_PASSWORD; |
| 141 if (!credit_card_field->verification_ && | 142 if (!credit_card_field->verification_ && |
| 142 ParseFieldSpecifics(scanner, | 143 ParseFieldSpecifics(scanner, base::UTF8ToUTF16(kCardCvcRe), |
| 143 base::UTF8ToUTF16(kCardCvcRe), | 144 kMatchNumTelAndPwd, |
| 144 kMatchNumAndTel | MATCH_PASSWORD, | |
| 145 &credit_card_field->verification_)) { | 145 &credit_card_field->verification_)) { |
| 146 // A couple of sites have multiple verification codes right after another. |
| 147 // Allow the classification of these codes one by one. |
| 148 AutofillField* const saved_cvv = credit_card_field->verification_; |
| 149 |
| 150 // Check if the verification code is the first detected field in the newly |
| 151 // started card. |
| 152 if (credit_card_field->numbers_.empty() && |
| 153 !credit_card_field->HasExpiration() && |
| 154 !credit_card_field->cardholder_ && scanner->SaveCursor() > 1) { |
| 155 // Check if the previous field was a verification code. |
| 156 scanner->RewindTo(scanner->SaveCursor() - 2); |
| 157 if (ParseFieldSpecifics(scanner, base::UTF8ToUTF16(kCardCvcRe), |
| 158 kMatchNumTelAndPwd, |
| 159 &credit_card_field->verification_)) { |
| 160 // Reset the current cvv (The verification parse overwrote it). |
| 161 credit_card_field->verification_ = saved_cvv; |
| 162 // Put the scanner back to the field right after the current cvv. |
| 163 scanner->Advance(); |
| 164 return std::move(credit_card_field); |
| 165 } else { |
| 166 // Put the scanner back to the field right after the current cvv. |
| 167 scanner->Advance(); |
| 168 scanner->Advance(); |
| 169 } |
| 170 } |
| 171 |
| 146 continue; | 172 continue; |
| 147 } | 173 } |
| 148 | 174 |
| 149 // TODO(crbug.com/591816): Make sure parsing cc-numbers of type password | 175 // TODO(crbug.com/591816): Make sure parsing cc-numbers of type password |
| 150 // doesn't have bad side effects. | 176 // doesn't have bad side effects. |
| 151 AutofillField* current_number_field; | 177 AutofillField* current_number_field; |
| 152 if (ParseFieldSpecifics(scanner, base::UTF8ToUTF16(kCardNumberRe), | 178 if (ParseFieldSpecifics(scanner, base::UTF8ToUTF16(kCardNumberRe), |
| 153 kMatchNumAndTel | MATCH_PASSWORD, | 179 kMatchNumTelAndPwd, ¤t_number_field)) { |
| 154 ¤t_number_field)) { | |
| 155 // Avoid autofilling any credit card number field having very low or high | 180 // Avoid autofilling any credit card number field having very low or high |
| 156 // |start_index| on the HTML form. | 181 // |start_index| on the HTML form. |
| 157 size_t start_index = 0; | 182 size_t start_index = 0; |
| 158 if (!credit_card_field->numbers_.empty()) { | 183 if (!credit_card_field->numbers_.empty()) { |
| 159 size_t last_number_field_size = | 184 size_t last_number_field_size = |
| 160 credit_card_field->numbers_.back()->credit_card_number_offset() + | 185 credit_card_field->numbers_.back()->credit_card_number_offset() + |
| 161 credit_card_field->numbers_.back()->max_length; | 186 credit_card_field->numbers_.back()->max_length; |
| 162 | 187 |
| 163 // Distinguish between | 188 // Distinguish between |
| 164 // (a) one card split across multiple fields | 189 // (a) one card split across multiple fields |
| (...skipping 29 matching lines...) Expand all Loading... |
| 194 if (credit_card_field->cardholder_) | 219 if (credit_card_field->cardholder_) |
| 195 return std::move(credit_card_field); | 220 return std::move(credit_card_field); |
| 196 | 221 |
| 197 // On some pages, the user selects a card type using radio buttons | 222 // On some pages, the user selects a card type using radio buttons |
| 198 // (e.g. test page Apple Store Billing.html). We can't handle that yet, | 223 // (e.g. test page Apple Store Billing.html). We can't handle that yet, |
| 199 // so we treat the card type as optional for now. | 224 // so we treat the card type as optional for now. |
| 200 // The existence of a number or cvc in combination with expiration date is | 225 // The existence of a number or cvc in combination with expiration date is |
| 201 // a strong enough signal that this is a credit card. It is possible that | 226 // a strong enough signal that this is a credit card. It is possible that |
| 202 // the number and name were parsed in a separate part of the form. So if | 227 // the number and name were parsed in a separate part of the form. So if |
| 203 // the cvc and date were found independently they are returned. | 228 // the cvc and date were found independently they are returned. |
| 204 bool has_cc_number_or_verification = (credit_card_field->verification_ || | 229 const bool has_cc_number_or_verification = |
| 205 !credit_card_field->numbers_.empty()); | 230 (credit_card_field->verification_ || |
| 206 bool has_date_or_mm_yy = (credit_card_field->expiration_date_ || | 231 !credit_card_field->numbers_.empty()); |
| 207 (credit_card_field->expiration_month_ && | 232 if (has_cc_number_or_verification && credit_card_field->HasExpiration()) |
| 208 credit_card_field->expiration_year_)); | |
| 209 if (has_cc_number_or_verification && has_date_or_mm_yy) | |
| 210 return std::move(credit_card_field); | 233 return std::move(credit_card_field); |
| 211 | 234 |
| 212 scanner->RewindTo(saved_cursor); | 235 scanner->RewindTo(saved_cursor); |
| 213 return nullptr; | 236 return nullptr; |
| 214 } | 237 } |
| 215 | 238 |
| 216 // static | 239 // static |
| 217 bool CreditCardField::LikelyCardMonthSelectField(AutofillScanner* scanner) { | 240 bool CreditCardField::LikelyCardMonthSelectField(AutofillScanner* scanner) { |
| 218 if (scanner->IsEnd()) | 241 if (scanner->IsEnd()) |
| 219 return false; | 242 return false; |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 } | 498 } |
| 476 | 499 |
| 477 ServerFieldType CreditCardField::GetExpirationYearType() const { | 500 ServerFieldType CreditCardField::GetExpirationYearType() const { |
| 478 return (expiration_date_ | 501 return (expiration_date_ |
| 479 ? exp_year_type_ | 502 ? exp_year_type_ |
| 480 : ((expiration_year_ && expiration_year_->max_length == 2) | 503 : ((expiration_year_ && expiration_year_->max_length == 2) |
| 481 ? CREDIT_CARD_EXP_2_DIGIT_YEAR | 504 ? CREDIT_CARD_EXP_2_DIGIT_YEAR |
| 482 : CREDIT_CARD_EXP_4_DIGIT_YEAR)); | 505 : CREDIT_CARD_EXP_4_DIGIT_YEAR)); |
| 483 } | 506 } |
| 484 | 507 |
| 508 bool CreditCardField::HasExpiration() const { |
| 509 return expiration_date_ || (expiration_month_ && expiration_year_); |
| 510 } |
| 511 |
| 485 } // namespace autofill | 512 } // namespace autofill |
| OLD | NEW |