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

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

Issue 1645493002: [Password Manager] Enables processing invisible username fields even if visible password field was … (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 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/content/renderer/password_form_conversion_utils_browsertest.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/content/renderer/password_form_conversion_utils.h" 5 #include "components/autofill/content/renderer/password_form_conversion_utils.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <string> 10 #include <string>
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 base::LazyInstance<re2::RE2, PasswordSiteUrlLazyInstanceTraits> 306 base::LazyInstance<re2::RE2, PasswordSiteUrlLazyInstanceTraits>
307 g_password_site_matcher = LAZY_INSTANCE_INITIALIZER; 307 g_password_site_matcher = LAZY_INSTANCE_INITIALIZER;
308 308
309 // Returns the |input_field| name if its non-empty; otherwise a |dummy_name|. 309 // Returns the |input_field| name if its non-empty; otherwise a |dummy_name|.
310 base::string16 FieldName(const WebInputElement& input_field, 310 base::string16 FieldName(const WebInputElement& input_field,
311 const char dummy_name[]) { 311 const char dummy_name[]) {
312 base::string16 field_name = input_field.nameForAutofill(); 312 base::string16 field_name = input_field.nameForAutofill();
313 return field_name.empty() ? base::ASCIIToUTF16(dummy_name) : field_name; 313 return field_name.empty() ? base::ASCIIToUTF16(dummy_name) : field_name;
314 } 314 }
315 315
316 bool FormContainsVisiblePasswordFields(const SyntheticForm& form) { 316 // Helper function that checks the presence of visible password and username
317 // fields in |form.control_elements|.
318 // Iff a visible password found, then |*found_visible_password| is set to true.
319 // Iff a visible password found AND there is a visible username before it, then
320 // |*found_visible_username_before_visible_password| is set to true.
321 void FoundVisiblePasswordAndVisibleUsernameBeforePassword(
322 const SyntheticForm& form,
323 bool* found_visible_password,
324 bool* found_visible_username_before_visible_password) {
325 DCHECK(found_visible_password != nullptr);
dvadym 2016/01/27 14:05:51 You don't need to write != nullptr, DCHECK(found_v
kolos1 2016/01/27 15:14:24 Thanks. Fixed
326 DCHECK(found_visible_username_before_visible_password != nullptr);
327 *found_visible_password = false;
328 *found_visible_username_before_visible_password = false;
329
330 bool found_visible_username = false;
317 for (auto& control_element : form.control_elements) { 331 for (auto& control_element : form.control_elements) {
318 const WebInputElement* input_element = toWebInputElement(&control_element); 332 const WebInputElement* input_element = toWebInputElement(&control_element);
319 if (!input_element || !input_element->isEnabled()) 333 if (!input_element || !input_element->isEnabled() ||
334 !input_element->isTextField())
320 continue; 335 continue;
321 336
322 if (input_element->isPasswordField() && 337 if (!form_util::IsWebNodeVisible(*input_element))
323 form_util::IsWebNodeVisible(*input_element)) 338 continue;
324 return true; 339
340 if (input_element->isPasswordField()) {
341 *found_visible_password = true;
342 *found_visible_username_before_visible_password = found_visible_username;
343 break;
344 } else {
345 found_visible_username = true;
346 }
325 } 347 }
326 return false;
327 } 348 }
328 349
329 // Get information about a login form encapsulated in a PasswordForm struct. 350 // Get information about a login form encapsulated in a PasswordForm struct.
330 // If an element of |form| has an entry in |nonscript_modified_values|, the 351 // If an element of |form| has an entry in |nonscript_modified_values|, the
331 // associated string is used instead of the element's value to create 352 // associated string is used instead of the element's value to create
332 // the PasswordForm. 353 // the PasswordForm.
333 bool GetPasswordForm(const SyntheticForm& form, 354 bool GetPasswordForm(const SyntheticForm& form,
334 PasswordForm* password_form, 355 PasswordForm* password_form,
335 const ModifiedValues* nonscript_modified_values, 356 const ModifiedValues* nonscript_modified_values,
336 const FormsPredictionsMap* form_predictions) { 357 const FormsPredictionsMap* form_predictions) {
(...skipping 13 matching lines...) Expand all
350 form.control_elements)) { 371 form.control_elements)) {
351 return false; 372 return false;
352 } 373 }
353 374
354 std::map<WebInputElement, PasswordFormFieldPredictionType> predicted_elements; 375 std::map<WebInputElement, PasswordFormFieldPredictionType> predicted_elements;
355 if (form_predictions) { 376 if (form_predictions) {
356 FindPredictedElements(form, password_form->form_data, *form_predictions, 377 FindPredictedElements(form, password_form->form_data, *form_predictions,
357 &predicted_elements); 378 &predicted_elements);
358 } 379 }
359 380
381 // Check the presence of visible password and username fields.
382 // If there is a visible password field, then ignore invisible password
383 // fields. If there is a visible username before visible password, then ignore
384 // invisible username fields.
385 // If there is no visible password field, don't ignore any elements (i.e. use
386 // the latest username field just before selected password field).
387 bool ignore_invisible_passwords = false;
388 bool ignore_invisible_usernames = false;
389 FoundVisiblePasswordAndVisibleUsernameBeforePassword(
390 form, &ignore_invisible_passwords, &ignore_invisible_usernames);
360 std::string layout_sequence; 391 std::string layout_sequence;
361 layout_sequence.reserve(form.control_elements.size()); 392 layout_sequence.reserve(form.control_elements.size());
362 bool ignore_invisible_fields = FormContainsVisiblePasswordFields(form);
363 for (size_t i = 0; i < form.control_elements.size(); ++i) { 393 for (size_t i = 0; i < form.control_elements.size(); ++i) {
364 WebFormControlElement control_element = form.control_elements[i]; 394 WebFormControlElement control_element = form.control_elements[i];
365 395
366 WebInputElement* input_element = toWebInputElement(&control_element); 396 WebInputElement* input_element = toWebInputElement(&control_element);
367 if (!input_element || !input_element->isEnabled()) 397 if (!input_element || !input_element->isEnabled())
368 continue; 398 continue;
369 if (ignore_invisible_fields && !form_util::IsWebNodeVisible(*input_element)) 399
370 continue; 400 bool element_is_invisible = !form_util::IsWebNodeVisible(*input_element);
371 if (input_element->isTextField()) { 401 if (input_element->isTextField()) {
372 if (input_element->isPasswordField()) 402 if (input_element->isPasswordField()) {
403 if (element_is_invisible && ignore_invisible_passwords)
404 continue;
373 layout_sequence.push_back('P'); 405 layout_sequence.push_back('P');
374 else 406 } else {
407 if (element_is_invisible && ignore_invisible_usernames)
408 continue;
375 layout_sequence.push_back('N'); 409 layout_sequence.push_back('N');
410 }
376 } 411 }
377 412
378 bool password_marked_by_autocomplete_attribute = 413 bool password_marked_by_autocomplete_attribute =
379 HasAutocompleteAttributeValue(*input_element, 414 HasAutocompleteAttributeValue(*input_element,
380 kAutocompleteCurrentPassword) || 415 kAutocompleteCurrentPassword) ||
381 HasAutocompleteAttributeValue(*input_element, kAutocompleteNewPassword); 416 HasAutocompleteAttributeValue(*input_element, kAutocompleteNewPassword);
382 417
383 // If the password field is readonly, the page is likely using a virtual 418 // If the password field is readonly, the page is likely using a virtual
384 // keyboard and bypassing the password field value (see 419 // keyboard and bypassing the password field value (see
385 // http://crbug.com/475488). There is nothing Chrome can do to fill 420 // http://crbug.com/475488). There is nothing Chrome can do to fill
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 } 687 }
653 688
654 bool HasAutocompleteAttributeValue(const blink::WebInputElement& element, 689 bool HasAutocompleteAttributeValue(const blink::WebInputElement& element,
655 const char* value_in_lowercase) { 690 const char* value_in_lowercase) {
656 return base::LowerCaseEqualsASCII( 691 return base::LowerCaseEqualsASCII(
657 base::StringPiece16(element.getAttribute("autocomplete")), 692 base::StringPiece16(element.getAttribute("autocomplete")),
658 value_in_lowercase); 693 value_in_lowercase);
659 } 694 }
660 695
661 } // namespace autofill 696 } // namespace autofill
OLDNEW
« no previous file with comments | « no previous file | components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698