Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(973)

Side by Side Diff: components/autofill/core/browser/credit_card_field.cc

Issue 654223004: Autofill: Allow forms to have multiple distinct CC number inputs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git/+/master
Patch Set: better test Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | components/autofill/core/browser/credit_card_field_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 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"
(...skipping 12 matching lines...) Expand all
23 // [Ref: http://en.wikipedia.org/wiki/Bank_card_number] 23 // [Ref: http://en.wikipedia.org/wiki/Bank_card_number]
24 static const size_t kMaxValidCardNumberSize = 19; 24 static const size_t kMaxValidCardNumberSize = 19;
25 25
26 // static 26 // static
27 FormField* CreditCardField::Parse(AutofillScanner* scanner) { 27 FormField* CreditCardField::Parse(AutofillScanner* scanner) {
28 if (scanner->IsEnd()) 28 if (scanner->IsEnd())
29 return NULL; 29 return NULL;
30 30
31 scoped_ptr<CreditCardField> credit_card_field(new CreditCardField); 31 scoped_ptr<CreditCardField> credit_card_field(new CreditCardField);
32 size_t saved_cursor = scanner->SaveCursor(); 32 size_t saved_cursor = scanner->SaveCursor();
33 bool form_has_valid_card_number_fields = true;
34 33
35 // Credit card fields can appear in many different orders. 34 // Credit card fields can appear in many different orders.
36 // We loop until no more credit card related fields are found, see |break| at 35 // We loop until no more credit card related fields are found, see |break| at
37 // bottom of the loop. 36 // bottom of the loop.
38 for (int fields = 0; !scanner->IsEnd(); ++fields) { 37 for (int fields = 0; !scanner->IsEnd(); ++fields) {
39 // Ignore gift card fields. 38 // Ignore gift card fields.
40 if (ParseField(scanner, base::UTF8ToUTF16(autofill::kGiftCardRe), NULL)) 39 if (ParseField(scanner, base::UTF8ToUTF16(autofill::kGiftCardRe), NULL))
41 break; 40 break;
42 41
43 // Sometimes the cardholder field is just labeled "name". Unfortunately this 42 // Sometimes the cardholder field is just labeled "name". Unfortunately this
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 AutofillField* current_number_field; 98 AutofillField* current_number_field;
100 if (ParseField(scanner, pattern, &current_number_field)) { 99 if (ParseField(scanner, pattern, &current_number_field)) {
101 // Avoid autofilling any credit card number field having very low or high 100 // Avoid autofilling any credit card number field having very low or high
102 // |start_index| on the HTML form. 101 // |start_index| on the HTML form.
103 size_t start_index = 0; 102 size_t start_index = 0;
104 if (!credit_card_field->numbers_.empty()) { 103 if (!credit_card_field->numbers_.empty()) {
105 size_t last_number_field_size = 104 size_t last_number_field_size =
106 credit_card_field->numbers_.back()->credit_card_number_offset() + 105 credit_card_field->numbers_.back()->credit_card_number_offset() +
107 credit_card_field->numbers_.back()->max_length; 106 credit_card_field->numbers_.back()->max_length;
108 107
109 // In some cases, HTML form may have credit card number split across 108 // Distinguish between
110 // multiple input fields and either one or cumulatively having 109 // (a) one card split across multiple fields
111 // |max_length| more than |kMaxValidCardNumberSize|, mark these input 110 // (b) multiple fields for multiple cards
112 // form fields as invalid and skip autofilling them. 111 // Treat this field as a part of the same card as the last field, except
113 if (last_number_field_size == 0U || 112 // when doing so would cause overflow.
114 last_number_field_size >= kMaxValidCardNumberSize) { 113 if (last_number_field_size < kMaxValidCardNumberSize)
115 // Mark that the credit card number splits are invalid. But keep 114 start_index = last_number_field_size;
116 // scanning HTML form so that cursor moves beyond related fields.
117 form_has_valid_card_number_fields = false;
118 }
119
120 start_index = last_number_field_size;
121 } 115 }
122 116
123 current_number_field->set_credit_card_number_offset(start_index); 117 current_number_field->set_credit_card_number_offset(start_index);
124 credit_card_field->numbers_.push_back(current_number_field); 118 credit_card_field->numbers_.push_back(current_number_field);
125 continue; 119 continue;
126 } 120 }
127 121
128 if (LowerCaseEqualsASCII(scanner->Cursor()->form_control_type, "month")) { 122 if (LowerCaseEqualsASCII(scanner->Cursor()->form_control_type, "month")) {
129 credit_card_field->expiration_date_ = scanner->Cursor(); 123 credit_card_field->expiration_date_ = scanner->Cursor();
130 scanner->Advance(); 124 scanner->Advance();
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 // field; we parse this field but ignore it. 178 // field; we parse this field but ignore it.
185 // We also ignore any other fields within a credit card block that 179 // We also ignore any other fields within a credit card block that
186 // start with "card", under the assumption that they are related to 180 // start with "card", under the assumption that they are related to
187 // the credit card section being processed but are uninteresting to us. 181 // the credit card section being processed but are uninteresting to us.
188 if (ParseField(scanner, base::UTF8ToUTF16(autofill::kCardIgnoredRe), NULL)) 182 if (ParseField(scanner, base::UTF8ToUTF16(autofill::kCardIgnoredRe), NULL))
189 continue; 183 continue;
190 184
191 break; 185 break;
192 } 186 }
193 187
194 // Cases where heuristic misinterprets input field as credit card number
195 // field, refuse to autofill credit card number fields.
196 if (!form_has_valid_card_number_fields)
197 credit_card_field->numbers_.clear();
198
199 // Some pages have a billing address field after the cardholder name field. 188 // Some pages have a billing address field after the cardholder name field.
200 // For that case, allow only just the cardholder name field. The remaining 189 // For that case, allow only just the cardholder name field. The remaining
201 // CC fields will be picked up in a following CreditCardField. 190 // CC fields will be picked up in a following CreditCardField.
202 if (credit_card_field->cardholder_) 191 if (credit_card_field->cardholder_)
203 return credit_card_field.release(); 192 return credit_card_field.release();
204 193
205 // On some pages, the user selects a card type using radio buttons 194 // On some pages, the user selects a card type using radio buttons
206 // (e.g. test page Apple Store Billing.html). We can't handle that yet, 195 // (e.g. test page Apple Store Billing.html). We can't handle that yet,
207 // so we treat the card type as optional for now. 196 // so we treat the card type as optional for now.
208 // The existence of a number or cvc in combination with expiration date is 197 // The existence of a number or cvc in combination with expiration date is
209 // a strong enough signal that this is a credit card. It is possible that 198 // a strong enough signal that this is a credit card. It is possible that
210 // the number and name were parsed in a separate part of the form. So if 199 // the number and name were parsed in a separate part of the form. So if
211 // the cvc and date were found independently they are returned. 200 // the cvc and date were found independently they are returned.
212 if ((!credit_card_field->numbers_.empty() || 201 if ((!credit_card_field->numbers_.empty() ||
213 credit_card_field->verification_ || 202 credit_card_field->verification_) &&
214 !form_has_valid_card_number_fields) &&
215 (credit_card_field->expiration_date_ || 203 (credit_card_field->expiration_date_ ||
216 (credit_card_field->expiration_month_ && 204 (credit_card_field->expiration_month_ &&
217 credit_card_field->expiration_year_))) { 205 credit_card_field->expiration_year_))) {
218 return credit_card_field.release(); 206 return credit_card_field.release();
219 } 207 }
220 208
221 scanner->RewindTo(saved_cursor); 209 scanner->RewindTo(saved_cursor);
222 return NULL; 210 return NULL;
223 } 211 }
224 212
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 255
268 ServerFieldType CreditCardField::GetExpirationYearType() const { 256 ServerFieldType CreditCardField::GetExpirationYearType() const {
269 return (expiration_date_ 257 return (expiration_date_
270 ? exp_year_type_ 258 ? exp_year_type_
271 : ((expiration_year_ && expiration_year_->max_length == 2) 259 : ((expiration_year_ && expiration_year_->max_length == 2)
272 ? CREDIT_CARD_EXP_2_DIGIT_YEAR 260 ? CREDIT_CARD_EXP_2_DIGIT_YEAR
273 : CREDIT_CARD_EXP_4_DIGIT_YEAR)); 261 : CREDIT_CARD_EXP_4_DIGIT_YEAR));
274 } 262 }
275 263
276 } // namespace autofill 264 } // namespace autofill
OLDNEW
« no previous file with comments | « no previous file | components/autofill/core/browser/credit_card_field_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698