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

Side by Side Diff: components/autofill/content/renderer/password_form_conversion_utils.cc

Issue 1265203002: Convert autocomplete attribute values to constants (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebasing to latest code Created 5 years, 4 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 | no next file » | 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/content/renderer/password_form_conversion_utils.h" 5 #include "components/autofill/content/renderer/password_form_conversion_utils.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/i18n/case_conversion.h" 9 #include "base/i18n/case_conversion.h"
10 #include "base/lazy_instance.h" 10 #include "base/lazy_instance.h"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 // LAYOUT_LOGIN_AND_SIGNUP is classified by NPN+P.*. This corresponds to a form 51 // LAYOUT_LOGIN_AND_SIGNUP is classified by NPN+P.*. This corresponds to a form
52 // which starts with a login section (NP) and continues with a sign-up section 52 // which starts with a login section (NP) and continues with a sign-up section
53 // (N+P.*). The aim is to distinguish such forms from change password-forms 53 // (N+P.*). The aim is to distinguish such forms from change password-forms
54 // (N*PPP?.*) and forms which use password fields to store private but 54 // (N*PPP?.*) and forms which use password fields to store private but
55 // non-password data (could look like, e.g., PN+P.*). 55 // non-password data (could look like, e.g., PN+P.*).
56 const char kLoginAndSignupRegex[] = 56 const char kLoginAndSignupRegex[] =
57 "NP" // Login section. 57 "NP" // Login section.
58 "N+P" // Sign-up section. 58 "N+P" // Sign-up section.
59 ".*"; // Anything beyond that. 59 ".*"; // Anything beyond that.
60 60
61 const char kAutocompleteUsername[] = "username";
62 const char kAutocompleteCurrentPassword[] = "current-password";
63 const char kAutocompleteNewPassword[] = "new-password";
64
61 struct LoginAndSignupLazyInstanceTraits 65 struct LoginAndSignupLazyInstanceTraits
62 : public base::DefaultLazyInstanceTraits<icu::RegexMatcher> { 66 : public base::DefaultLazyInstanceTraits<icu::RegexMatcher> {
63 static icu::RegexMatcher* New(void* instance) { 67 static icu::RegexMatcher* New(void* instance) {
64 const icu::UnicodeString icu_pattern(kLoginAndSignupRegex); 68 const icu::UnicodeString icu_pattern(kLoginAndSignupRegex);
65 69
66 UErrorCode status = U_ZERO_ERROR; 70 UErrorCode status = U_ZERO_ERROR;
67 // Use placement new to initialize the instance in the preallocated space. 71 // Use placement new to initialize the instance in the preallocated space.
68 // The "(instance)" is very important to force POD type initialization. 72 // The "(instance)" is very important to force POD type initialization.
69 scoped_ptr<icu::RegexMatcher> matcher(new (instance) icu::RegexMatcher( 73 scoped_ptr<icu::RegexMatcher> matcher(new (instance) icu::RegexMatcher(
70 icu_pattern, UREGEX_CASE_INSENSITIVE, status)); 74 icu_pattern, UREGEX_CASE_INSENSITIVE, status));
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 WebInputElement* current_password, 116 WebInputElement* current_password,
113 WebInputElement* new_password) { 117 WebInputElement* new_password) {
114 DCHECK(current_password && current_password->isNull()); 118 DCHECK(current_password && current_password->isNull());
115 DCHECK(new_password && new_password->isNull()); 119 DCHECK(new_password && new_password->isNull());
116 120
117 // First, look for elements marked with either autocomplete='current-password' 121 // First, look for elements marked with either autocomplete='current-password'
118 // or 'new-password' -- if we find any, take the hint, and treat the first of 122 // or 'new-password' -- if we find any, take the hint, and treat the first of
119 // each kind as the element we are looking for. 123 // each kind as the element we are looking for.
120 for (std::vector<WebInputElement>::const_iterator it = passwords.begin(); 124 for (std::vector<WebInputElement>::const_iterator it = passwords.begin();
121 it != passwords.end(); it++) { 125 it != passwords.end(); it++) {
122 if (HasAutocompleteAttributeValue(*it, "current-password") && 126 if (HasAutocompleteAttributeValue(*it, kAutocompleteCurrentPassword) &&
123 current_password->isNull()) { 127 current_password->isNull()) {
124 *current_password = *it; 128 *current_password = *it;
125 } else if (HasAutocompleteAttributeValue(*it, "new-password") && 129 } else if (HasAutocompleteAttributeValue(*it, kAutocompleteNewPassword) &&
126 new_password->isNull()) { 130 new_password->isNull()) {
127 *new_password = *it; 131 *new_password = *it;
128 } 132 }
129 } 133 }
130 134
131 // If we have seen an element with either of autocomplete attributes above, 135 // If we have seen an element with either of autocomplete attributes above,
132 // take that as a signal that the page author must have intentionally left the 136 // take that as a signal that the page author must have intentionally left the
133 // rest of the password fields unmarked. Perhaps they are used for other 137 // rest of the password fields unmarked. Perhaps they are used for other
134 // purposes, e.g., PINs, OTPs, and the like. So we skip all the heuristics we 138 // purposes, e.g., PINs, OTPs, and the like. So we skip all the heuristics we
135 // normally do, and ignore the rest of the password fields. 139 // normally do, and ignore the rest of the password fields.
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 // keyboard and bypassing the password field value (see 286 // keyboard and bypassing the password field value (see
283 // http://crbug.com/475488). There is nothing Chrome can do to fill 287 // http://crbug.com/475488). There is nothing Chrome can do to fill
284 // passwords for now. Continue processing in case when the password field 288 // passwords for now. Continue processing in case when the password field
285 // was made readonly by JavaScript before submission. We can do this by 289 // was made readonly by JavaScript before submission. We can do this by
286 // checking whether password element was updated not from JavaScript. 290 // checking whether password element was updated not from JavaScript.
287 if (input_element->isPasswordField() && 291 if (input_element->isPasswordField() &&
288 (!input_element->isReadOnly() || 292 (!input_element->isReadOnly() ||
289 (nonscript_modified_values && 293 (nonscript_modified_values &&
290 nonscript_modified_values->find(*input_element) != 294 nonscript_modified_values->find(*input_element) !=
291 nonscript_modified_values->end()) || 295 nonscript_modified_values->end()) ||
292 HasAutocompleteAttributeValue(*input_element, "current-password") || 296 HasAutocompleteAttributeValue(*input_element,
293 HasAutocompleteAttributeValue(*input_element, "new-password"))) { 297 kAutocompleteCurrentPassword) ||
298 HasAutocompleteAttributeValue(*input_element,
299 kAutocompleteNewPassword))) {
294 passwords.push_back(*input_element); 300 passwords.push_back(*input_element);
295 // If we have not yet considered any element to be the username so far, 301 // If we have not yet considered any element to be the username so far,
296 // provisionally select the input element just before the first password 302 // provisionally select the input element just before the first password
297 // element to be the username. This choice will be overruled if we later 303 // element to be the username. This choice will be overruled if we later
298 // find an element with autocomplete='username'. 304 // find an element with autocomplete='username'.
299 if (username_element.isNull() && !latest_input_element.isNull()) { 305 if (username_element.isNull() && !latest_input_element.isNull()) {
300 username_element = latest_input_element; 306 username_element = latest_input_element;
301 // Remove the selected username from other_possible_usernames. 307 // Remove the selected username from other_possible_usernames.
302 if (!latest_input_element.value().isEmpty()) { 308 if (!latest_input_element.value().isEmpty()) {
303 DCHECK(!other_possible_usernames.empty()); 309 DCHECK(!other_possible_usernames.empty());
304 DCHECK_EQ(base::string16(latest_input_element.value()), 310 DCHECK_EQ(base::string16(latest_input_element.value()),
305 other_possible_usernames.back()); 311 other_possible_usernames.back());
306 other_possible_usernames.pop_back(); 312 other_possible_usernames.pop_back();
307 } 313 }
308 } 314 }
309 } 315 }
310 316
311 // Various input types such as text, url, email can be a username field. 317 // Various input types such as text, url, email can be a username field.
312 if (input_element->isTextField() && !input_element->isPasswordField()) { 318 if (input_element->isTextField() && !input_element->isPasswordField()) {
313 if (HasAutocompleteAttributeValue(*input_element, "username")) { 319 if (HasAutocompleteAttributeValue(*input_element,
320 kAutocompleteUsername)) {
314 if (password_form->username_marked_by_site) { 321 if (password_form->username_marked_by_site) {
315 // A second or subsequent element marked with autocomplete='username'. 322 // A second or subsequent element marked with autocomplete='username'.
316 // This makes us less confident that we have understood the form. We 323 // This makes us less confident that we have understood the form. We
317 // will stick to our choice that the first such element was the real 324 // will stick to our choice that the first such element was the real
318 // username, but will start collecting other_possible_usernames from 325 // username, but will start collecting other_possible_usernames from
319 // the extra elements marked with autocomplete='username'. Note that 326 // the extra elements marked with autocomplete='username'. Note that
320 // unlike username_element, other_possible_usernames is used only for 327 // unlike username_element, other_possible_usernames is used only for
321 // autofill, not for form identification, and blank autofill entries 328 // autofill, not for form identification, and blank autofill entries
322 // are not useful, so we do not collect empty strings. 329 // are not useful, so we do not collect empty strings.
323 if (!input_element->value().isEmpty()) 330 if (!input_element->value().isEmpty())
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 if (nonscript_modified_values != nullptr) { 425 if (nonscript_modified_values != nullptr) {
419 auto password_iterator = nonscript_modified_values->find(password); 426 auto password_iterator = nonscript_modified_values->find(password);
420 if (password_iterator != nonscript_modified_values->end()) 427 if (password_iterator != nonscript_modified_values->end())
421 password_value = password_iterator->second; 428 password_value = password_iterator->second;
422 } 429 }
423 password_form->password_value = password_value; 430 password_form->password_value = password_value;
424 } 431 }
425 if (!new_password.isNull()) { 432 if (!new_password.isNull()) {
426 password_form->new_password_element = new_password.nameForAutofill(); 433 password_form->new_password_element = new_password.nameForAutofill();
427 password_form->new_password_value = new_password.value(); 434 password_form->new_password_value = new_password.value();
428 if (HasAutocompleteAttributeValue(new_password, "new-password")) 435 if (HasAutocompleteAttributeValue(new_password, kAutocompleteNewPassword))
429 password_form->new_password_marked_by_site = true; 436 password_form->new_password_marked_by_site = true;
430 } 437 }
431 438
432 if (username_element.isNull()) { 439 if (username_element.isNull()) {
433 // To get a better idea on how password forms without a username field 440 // To get a better idea on how password forms without a username field
434 // look like, report the total number of text and password fields. 441 // look like, report the total number of text and password fields.
435 UMA_HISTOGRAM_COUNTS_100( 442 UMA_HISTOGRAM_COUNTS_100(
436 "PasswordManager.EmptyUsernames.TextAndPasswordFieldCount", 443 "PasswordManager.EmptyUsernames.TextAndPasswordFieldCount",
437 layout_sequence.size()); 444 layout_sequence.size());
438 // For comparison, also report the number of password fields. 445 // For comparison, also report the number of password fields.
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
494 WebFormElementToFormData(web_form, 501 WebFormElementToFormData(web_form,
495 blink::WebFormControlElement(), 502 blink::WebFormControlElement(),
496 EXTRACT_NONE, 503 EXTRACT_NONE,
497 &password_form->form_data, 504 &password_form->form_data,
498 NULL /* FormFieldData */); 505 NULL /* FormFieldData */);
499 506
500 return password_form.Pass(); 507 return password_form.Pass();
501 } 508 }
502 509
503 } // namespace autofill 510 } // namespace autofill
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698