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/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 Loading... |
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); |
| 326 DCHECK(found_visible_username_before_visible_password); |
| 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 Loading... |
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 Loading... |
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 |
OLD | NEW |