| 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_autofill_agent.h" | 5 #include "components/autofill/content/renderer/password_autofill_agent.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> |
| 9 #include <memory> | 10 #include <memory> |
| 10 #include <string> | 11 #include <string> |
| 11 #include <utility> | 12 #include <utility> |
| 12 #include <vector> | 13 #include <vector> |
| 13 | 14 |
| 14 #include "base/bind.h" | 15 #include "base/bind.h" |
| 15 #include "base/i18n/case_conversion.h" | 16 #include "base/i18n/case_conversion.h" |
| 16 #include "base/memory/linked_ptr.h" | 17 #include "base/memory/linked_ptr.h" |
| 17 #include "base/memory/ptr_util.h" | 18 #include "base/memory/ptr_util.h" |
| 18 #include "base/message_loop/message_loop.h" | 19 #include "base/message_loop/message_loop.h" |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 | 270 |
| 270 bool DoUsernamesMatch(const base::string16& username1, | 271 bool DoUsernamesMatch(const base::string16& username1, |
| 271 const base::string16& username2, | 272 const base::string16& username2, |
| 272 bool exact_match) { | 273 bool exact_match) { |
| 273 if (exact_match) | 274 if (exact_match) |
| 274 return username1 == username2; | 275 return username1 == username2; |
| 275 return FieldIsSuggestionSubstringStartingOnTokenBoundary(username1, username2, | 276 return FieldIsSuggestionSubstringStartingOnTokenBoundary(username1, username2, |
| 276 true); | 277 true); |
| 277 } | 278 } |
| 278 | 279 |
| 279 // Returns |true| if the given element is editable. Otherwise, returns |false|. | 280 // Returns whether the given |element| is editable. |
| 280 bool IsElementAutocompletable(const blink::WebInputElement& element) { | 281 bool IsElementAutocompletable(const blink::WebInputElement& element) { |
| 281 return IsElementEditable(element); | 282 return IsElementEditable(element); |
| 282 } | 283 } |
| 283 | 284 |
| 284 // Returns whether the |username_element| is allowed to be autofilled. | 285 // Returns whether the |username_element| is allowed to be autofilled. |
| 285 // | 286 // |
| 286 // Note that if the user interacts with the |password_field| and the | 287 // Note that if the user interacts with the |password_field| and the |
| 287 // |username_element| is user-defined (i.e., non-empty and non-autofilled), then | 288 // |username_element| is user-defined (i.e., non-empty and non-autofilled), then |
| 288 // this function returns false. This is a precaution, to not override the field | 289 // this function returns false. This is a precaution, to not override the field |
| 289 // if it has been classified as username by accident. | 290 // if it has been classified as username by accident. |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 600 if (element.IsFormControlElement()) { | 601 if (element.IsFormControlElement()) { |
| 601 const blink::WebFormControlElement& control = | 602 const blink::WebFormControlElement& control = |
| 602 element.To<blink::WebFormControlElement>(); | 603 element.To<blink::WebFormControlElement>(); |
| 603 if (control.FormControlType() == kPassword) | 604 if (control.FormControlType() == kPassword) |
| 604 return true; | 605 return true; |
| 605 } | 606 } |
| 606 } | 607 } |
| 607 return false; | 608 return false; |
| 608 } | 609 } |
| 609 | 610 |
| 611 // Returns the closest visible autocompletable non-password text element |
| 612 // preceding the |password_element| either in a form, if it belongs to one, or |
| 613 // in the |frame|. |
| 614 blink::WebInputElement FindUsernameElementPrecedingPasswordElement( |
| 615 blink::WebFrame* frame, |
| 616 const blink::WebInputElement& password_element) { |
| 617 DCHECK(!password_element.IsNull()); |
| 618 |
| 619 std::vector<blink::WebFormControlElement> elements; |
| 620 if (password_element.Form().IsNull()) { |
| 621 elements = form_util::GetUnownedAutofillableFormFieldElements( |
| 622 frame->GetDocument().All(), nullptr); |
| 623 } else { |
| 624 blink::WebVector<blink::WebFormControlElement> web_control_elements; |
| 625 password_element.Form().GetFormControlElements(web_control_elements); |
| 626 elements.assign(web_control_elements.begin(), web_control_elements.end()); |
| 627 } |
| 628 |
| 629 auto iter = std::find(elements.begin(), elements.end(), password_element); |
| 630 if (iter == elements.end()) |
| 631 return blink::WebInputElement(); |
| 632 |
| 633 for (auto begin = elements.begin(); iter != begin;) { |
| 634 --iter; |
| 635 const blink::WebInputElement* input = blink::ToWebInputElement(&*iter); |
| 636 if (input && input->IsTextField() && !input->IsPasswordField() && |
| 637 IsElementAutocompletable(*input) && |
| 638 form_util::IsWebElementVisible(*input)) { |
| 639 return *input; |
| 640 } |
| 641 } |
| 642 |
| 643 return blink::WebInputElement(); |
| 644 } |
| 645 |
| 610 } // namespace | 646 } // namespace |
| 611 | 647 |
| 612 class PasswordAutofillAgent::FormElementObserverCallback | 648 class PasswordAutofillAgent::FormElementObserverCallback |
| 613 : public blink::WebFormElementObserverCallback { | 649 : public blink::WebFormElementObserverCallback { |
| 614 public: | 650 public: |
| 615 explicit FormElementObserverCallback(PasswordAutofillAgent* agent) | 651 explicit FormElementObserverCallback(PasswordAutofillAgent* agent) |
| 616 : agent_(agent) {} | 652 : agent_(agent) {} |
| 617 ~FormElementObserverCallback() override = default; | 653 ~FormElementObserverCallback() override = default; |
| 618 | 654 |
| 619 void ElementWasHiddenOrRemoved() override { | 655 void ElementWasHiddenOrRemoved() override { |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 768 const blink::WebFormControlElement& control_element, | 804 const blink::WebFormControlElement& control_element, |
| 769 const base::string16& username, | 805 const base::string16& username, |
| 770 const base::string16& password) { | 806 const base::string16& password) { |
| 771 // The element in context of the suggestion popup. | 807 // The element in context of the suggestion popup. |
| 772 const blink::WebInputElement* element = ToWebInputElement(&control_element); | 808 const blink::WebInputElement* element = ToWebInputElement(&control_element); |
| 773 if (!element) | 809 if (!element) |
| 774 return false; | 810 return false; |
| 775 | 811 |
| 776 blink::WebInputElement username_element; | 812 blink::WebInputElement username_element; |
| 777 blink::WebInputElement password_element; | 813 blink::WebInputElement password_element; |
| 778 PasswordInfo* password_info; | 814 PasswordInfo* password_info = nullptr; |
| 779 | 815 |
| 780 if (!FindPasswordInfoForElement(*element, &username_element, | 816 if (!FindPasswordInfoForElement(*element, &username_element, |
| 781 &password_element, &password_info) || | 817 &password_element, &password_info) || |
| 782 !IsElementAutocompletable(password_element)) { | 818 !IsElementAutocompletable(password_element)) { |
| 783 return false; | 819 return false; |
| 784 } | 820 } |
| 785 | 821 |
| 786 password_info->password_was_edited_last = false; | 822 password_info->password_was_edited_last = false; |
| 787 if (element->IsPasswordField()) { | 823 if (element->IsPasswordField()) { |
| 788 password_info->password_field_suggestion_was_accepted = true; | 824 password_info->password_field_suggestion_was_accepted = true; |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 876 if (!element.IsPasswordField()) { | 912 if (!element.IsPasswordField()) { |
| 877 *username_element = element; | 913 *username_element = element; |
| 878 } else { | 914 } else { |
| 879 // If there is a password field, but a request to the store hasn't been sent | 915 // If there is a password field, but a request to the store hasn't been sent |
| 880 // yet, then do fetch saved credentials now. | 916 // yet, then do fetch saved credentials now. |
| 881 if (!sent_request_to_store_) { | 917 if (!sent_request_to_store_) { |
| 882 SendPasswordForms(false); | 918 SendPasswordForms(false); |
| 883 return false; | 919 return false; |
| 884 } | 920 } |
| 885 | 921 |
| 922 *password_element = element; |
| 923 |
| 886 WebInputToPasswordInfoMap::iterator iter = | 924 WebInputToPasswordInfoMap::iterator iter = |
| 887 web_input_to_password_info_.find(element); | 925 web_input_to_password_info_.find(element); |
| 926 if (iter == web_input_to_password_info_.end()) { |
| 927 PasswordToLoginMap::const_iterator password_iter = |
| 928 password_to_username_.find(element); |
| 929 if (password_iter == password_to_username_.end()) { |
| 930 if (web_input_to_password_info_.empty()) |
| 931 return false; |
| 932 // Now all PasswordInfo items refer to the same set of credentials for |
| 933 // fill, so it is ok to take any of them. |
| 934 iter = web_input_to_password_info_.begin(); |
| 935 } else { |
| 936 *username_element = password_iter->second; |
| 937 } |
| 938 } |
| 939 |
| 888 if (iter != web_input_to_password_info_.end()) { | 940 if (iter != web_input_to_password_info_.end()) { |
| 889 // It's a password field without corresponding username field. | 941 // It's a password field without corresponding username field. Try to find |
| 890 *password_element = element; | 942 // the username field based on visibility. |
| 943 *username_element = FindUsernameElementPrecedingPasswordElement( |
| 944 render_frame()->GetWebFrame(), *password_element); |
| 891 *password_info = &iter->second; | 945 *password_info = &iter->second; |
| 892 return true; | 946 return true; |
| 893 } | 947 } |
| 894 PasswordToLoginMap::const_iterator password_iter = | 948 // Otherwise |username_element| has been set above. |
| 895 password_to_username_.find(element); | |
| 896 if (password_iter == password_to_username_.end()) { | |
| 897 if (web_input_to_password_info_.empty()) | |
| 898 return false; | |
| 899 | |
| 900 *password_element = element; | |
| 901 // Now all PasswordInfo items refer to the same set of credentials for | |
| 902 // fill, so it is ok to take any of them. | |
| 903 *password_info = &web_input_to_password_info_.begin()->second; | |
| 904 return true; | |
| 905 } | |
| 906 *username_element = password_iter->second; | |
| 907 *password_element = element; | |
| 908 } | 949 } |
| 909 | 950 |
| 910 WebInputToPasswordInfoMap::iterator iter = | 951 WebInputToPasswordInfoMap::iterator iter = |
| 911 web_input_to_password_info_.find(*username_element); | 952 web_input_to_password_info_.find(*username_element); |
| 912 | |
| 913 if (iter == web_input_to_password_info_.end()) | 953 if (iter == web_input_to_password_info_.end()) |
| 914 return false; | 954 return false; |
| 915 | 955 |
| 916 *password_info = &iter->second; | 956 *password_info = &iter->second; |
| 917 if (password_element->IsNull()) | 957 if (password_element->IsNull()) |
| 918 *password_element = (*password_info)->password_field; | 958 *password_element = (*password_info)->password_field; |
| 919 | 959 |
| 920 return true; | 960 return true; |
| 921 } | 961 } |
| 922 | 962 |
| (...skipping 809 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1732 PasswordAutofillAgent::GetPasswordManagerDriver() { | 1772 PasswordAutofillAgent::GetPasswordManagerDriver() { |
| 1733 if (!password_manager_driver_) { | 1773 if (!password_manager_driver_) { |
| 1734 render_frame()->GetRemoteInterfaces()->GetInterface( | 1774 render_frame()->GetRemoteInterfaces()->GetInterface( |
| 1735 mojo::MakeRequest(&password_manager_driver_)); | 1775 mojo::MakeRequest(&password_manager_driver_)); |
| 1736 } | 1776 } |
| 1737 | 1777 |
| 1738 return password_manager_driver_; | 1778 return password_manager_driver_; |
| 1739 } | 1779 } |
| 1740 | 1780 |
| 1741 } // namespace autofill | 1781 } // namespace autofill |
| OLD | NEW |