| 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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 scanner->Advance(); | 119 scanner->Advance(); |
| 121 continue; | 120 continue; |
| 122 } | 121 } |
| 123 | 122 |
| 124 // We look for a card security code before we look for a credit card number | 123 // We look for a card security code before we look for a credit card number |
| 125 // and match the general term "number". The security code has a plethora of | 124 // and match the general term "number". The security code has a plethora of |
| 126 // names; we've seen "verification #", "verification number", "card | 125 // names; we've seen "verification #", "verification number", "card |
| 127 // identification number", and others listed in the regex pattern used | 126 // identification number", and others listed in the regex pattern used |
| 128 // below. | 127 // below. |
| 129 // Note: Some sites use type="tel" or type="number" for numerical inputs. | 128 // Note: Some sites use type="tel" or type="number" for numerical inputs. |
| 130 const int kMatchNumAndTel = MATCH_DEFAULT | MATCH_NUMBER | MATCH_TELEPHONE; | 129 // They also sometimes use type="password" for sensitive types. |
| 130 const int kMatchNumTelAndPwd = |
| 131 MATCH_DEFAULT | MATCH_NUMBER | MATCH_TELEPHONE | MATCH_PASSWORD; |
| 131 if (!credit_card_field->verification_ && | 132 if (!credit_card_field->verification_ && |
| 132 ParseFieldSpecifics(scanner, | 133 ParseFieldSpecifics(scanner, base::UTF8ToUTF16(kCardCvcRe), |
| 133 base::UTF8ToUTF16(kCardCvcRe), | 134 kMatchNumTelAndPwd, |
| 134 kMatchNumAndTel | MATCH_PASSWORD, | |
| 135 &credit_card_field->verification_)) { | 135 &credit_card_field->verification_)) { |
| 136 // A couple of sites have multiple verification codes right after another. |
| 137 // Allow the classification of these codes one by one. |
| 138 AutofillField* const saved_cvv = credit_card_field->verification_; |
| 139 |
| 140 // Check if the verification code is the first detected field in the newly |
| 141 // started card. |
| 142 if (credit_card_field->numbers_.empty() && |
| 143 !credit_card_field->HasExpiration() && |
| 144 !credit_card_field->cardholder_ && scanner->SaveCursor() > 1) { |
| 145 // Check if the previous field was a verification code. |
| 146 scanner->RewindTo(scanner->SaveCursor() - 2); |
| 147 if (ParseFieldSpecifics(scanner, base::UTF8ToUTF16(kCardCvcRe), |
| 148 kMatchNumTelAndPwd, |
| 149 &credit_card_field->verification_)) { |
| 150 // Reset the current cvv (The verification parse overwrote it). |
| 151 credit_card_field->verification_ = saved_cvv; |
| 152 // Put the scanner back to the field right after the current cvv. |
| 153 scanner->Advance(); |
| 154 return std::move(credit_card_field); |
| 155 } else { |
| 156 // Put the scanner back to the field right after the current cvv. |
| 157 scanner->Advance(); |
| 158 scanner->Advance(); |
| 159 } |
| 160 } |
| 161 |
| 136 continue; | 162 continue; |
| 137 } | 163 } |
| 138 | 164 |
| 139 // TODO(crbug.com/591816): Make sure parsing cc-numbers of type password | 165 // TODO(crbug.com/591816): Make sure parsing cc-numbers of type password |
| 140 // doesn't have bad side effects. | 166 // doesn't have bad side effects. |
| 141 AutofillField* current_number_field; | 167 AutofillField* current_number_field; |
| 142 if (ParseFieldSpecifics(scanner, base::UTF8ToUTF16(kCardNumberRe), | 168 if (ParseFieldSpecifics(scanner, base::UTF8ToUTF16(kCardNumberRe), |
| 143 kMatchNumAndTel | MATCH_PASSWORD, | 169 kMatchNumTelAndPwd, ¤t_number_field)) { |
| 144 ¤t_number_field)) { | |
| 145 // Avoid autofilling any credit card number field having very low or high | 170 // Avoid autofilling any credit card number field having very low or high |
| 146 // |start_index| on the HTML form. | 171 // |start_index| on the HTML form. |
| 147 size_t start_index = 0; | 172 size_t start_index = 0; |
| 148 if (!credit_card_field->numbers_.empty()) { | 173 if (!credit_card_field->numbers_.empty()) { |
| 149 size_t last_number_field_size = | 174 size_t last_number_field_size = |
| 150 credit_card_field->numbers_.back()->credit_card_number_offset() + | 175 credit_card_field->numbers_.back()->credit_card_number_offset() + |
| 151 credit_card_field->numbers_.back()->max_length; | 176 credit_card_field->numbers_.back()->max_length; |
| 152 | 177 |
| 153 // Distinguish between | 178 // Distinguish between |
| 154 // (a) one card split across multiple fields | 179 // (a) one card split across multiple fields |
| (...skipping 29 matching lines...) Expand all Loading... |
| 184 if (credit_card_field->cardholder_) | 209 if (credit_card_field->cardholder_) |
| 185 return std::move(credit_card_field); | 210 return std::move(credit_card_field); |
| 186 | 211 |
| 187 // On some pages, the user selects a card type using radio buttons | 212 // On some pages, the user selects a card type using radio buttons |
| 188 // (e.g. test page Apple Store Billing.html). We can't handle that yet, | 213 // (e.g. test page Apple Store Billing.html). We can't handle that yet, |
| 189 // so we treat the card type as optional for now. | 214 // so we treat the card type as optional for now. |
| 190 // The existence of a number or cvc in combination with expiration date is | 215 // The existence of a number or cvc in combination with expiration date is |
| 191 // a strong enough signal that this is a credit card. It is possible that | 216 // a strong enough signal that this is a credit card. It is possible that |
| 192 // the number and name were parsed in a separate part of the form. So if | 217 // the number and name were parsed in a separate part of the form. So if |
| 193 // the cvc and date were found independently they are returned. | 218 // the cvc and date were found independently they are returned. |
| 194 bool has_cc_number_or_verification = (credit_card_field->verification_ || | 219 const bool has_cc_number_or_verification = |
| 195 !credit_card_field->numbers_.empty()); | 220 (credit_card_field->verification_ || |
| 196 bool has_date_or_mm_yy = (credit_card_field->expiration_date_ || | 221 !credit_card_field->numbers_.empty()); |
| 197 (credit_card_field->expiration_month_ && | 222 if (has_cc_number_or_verification && credit_card_field->HasExpiration()) |
| 198 credit_card_field->expiration_year_)); | |
| 199 if (has_cc_number_or_verification && has_date_or_mm_yy) | |
| 200 return std::move(credit_card_field); | 223 return std::move(credit_card_field); |
| 201 | 224 |
| 202 scanner->RewindTo(saved_cursor); | 225 scanner->RewindTo(saved_cursor); |
| 203 return nullptr; | 226 return nullptr; |
| 204 } | 227 } |
| 205 | 228 |
| 206 // static | 229 // static |
| 207 bool CreditCardField::LikelyCardMonthSelectField(AutofillScanner* scanner) { | 230 bool CreditCardField::LikelyCardMonthSelectField(AutofillScanner* scanner) { |
| 208 if (scanner->IsEnd()) | 231 if (scanner->IsEnd()) |
| 209 return false; | 232 return false; |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 } | 478 } |
| 456 | 479 |
| 457 ServerFieldType CreditCardField::GetExpirationYearType() const { | 480 ServerFieldType CreditCardField::GetExpirationYearType() const { |
| 458 return (expiration_date_ | 481 return (expiration_date_ |
| 459 ? exp_year_type_ | 482 ? exp_year_type_ |
| 460 : ((expiration_year_ && expiration_year_->max_length == 2) | 483 : ((expiration_year_ && expiration_year_->max_length == 2) |
| 461 ? CREDIT_CARD_EXP_2_DIGIT_YEAR | 484 ? CREDIT_CARD_EXP_2_DIGIT_YEAR |
| 462 : CREDIT_CARD_EXP_4_DIGIT_YEAR)); | 485 : CREDIT_CARD_EXP_4_DIGIT_YEAR)); |
| 463 } | 486 } |
| 464 | 487 |
| 488 bool CreditCardField::HasExpiration() const { |
| 489 return expiration_date_ || (expiration_month_ && expiration_year_); |
| 490 } |
| 491 |
| 465 } // namespace autofill | 492 } // namespace autofill |
| OLD | NEW |