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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
60 FormInputElementMap input_elements; | 60 FormInputElementMap input_elements; |
61 }; | 61 }; |
62 | 62 |
63 typedef std::vector<FormElements*> FormElementsList; | 63 typedef std::vector<FormElements*> FormElementsList; |
64 | 64 |
65 // Helper to search the given form element for the specified input elements | 65 // Helper to search the given form element for the specified input elements |
66 // in |data|, and add results to |result|. | 66 // in |data|, and add results to |result|. |
67 static bool FindFormInputElements(blink::WebFormElement* fe, | 67 static bool FindFormInputElements(blink::WebFormElement* fe, |
68 const FormData& data, | 68 const FormData& data, |
69 FormElements* result) { | 69 FormElements* result) { |
70 const bool username_is_present = !data.fields[0].name.empty(); | 70 const bool username_is_present = !data.username.name.empty(); |
71 | 71 blink::WebVector<blink::WebNode> temp_elements; |
72 // Loop through the list of elements we need to find on the form in order to | 72 bool found_input = false; |
73 // autofill it. If we don't find any one of them, abort processing this | 73 if (username_is_present) { |
74 // form; it can't be the right one. | 74 // Fill the username input field. |
75 // First field is the username, skip it if not present. | 75 fe->getNamedElements(data.username.name, temp_elements); |
76 for (size_t j = (username_is_present ? 0 : 1); j < data.fields.size(); ++j) { | |
77 blink::WebVector<blink::WebNode> temp_elements; | |
78 fe->getNamedElements(data.fields[j].name, temp_elements); | |
79 | |
80 // Match the first input element, if any. | |
81 // |getNamedElements| may return non-input elements where the names match, | |
82 // so the results are filtered for input elements. | |
83 // If more than one match is made, then we have ambiguity (due to misuse | |
84 // of "name" attribute) so is it considered not found. | |
85 bool found_input = false; | |
86 for (size_t i = 0; i < temp_elements.size(); ++i) { | 76 for (size_t i = 0; i < temp_elements.size(); ++i) { |
87 if (temp_elements[i].to<blink::WebElement>().hasHTMLTagName("input")) { | 77 if (temp_elements[i].to<blink::WebElement>().hasHTMLTagName("input")) { |
88 // Check for a non-unique match. | 78 // Check for a non-unique match. |
89 if (found_input) { | 79 if (found_input) { |
90 found_input = false; | 80 found_input = false; |
91 break; | 81 break; |
92 } | 82 } |
93 | 83 |
94 // Only fill saved passwords into password fields and usernames into | 84 // Only fill saved passwords into password fields and usernames into |
95 // text fields. | 85 // text fields. |
Ilya Sherman
2014/09/30 20:02:32
It looks like you removed the code that addresses
Ilya Sherman
2014/09/30 20:02:32
Also, if there aren't any existing test cases that
Pritam Nikam
2014/10/13 10:48:00
Done.
Pritam Nikam
2014/10/13 10:48:00
Test already exists.
| |
96 blink::WebInputElement input_element = | 86 blink::WebInputElement input_element = |
97 temp_elements[i].to<blink::WebInputElement>(); | 87 temp_elements[i].to<blink::WebInputElement>(); |
98 if (input_element.isPasswordField() != | |
99 (data.fields[j].form_control_type == "password")) | |
100 continue; | |
101 | 88 |
102 // This element matched, add it to our temporary result. It's possible | 89 // This element matched, add it to our temporary result. It's possible |
103 // there are multiple matches, but for purposes of identifying the form | 90 // there are multiple matches, but for purposes of identifying the form |
104 // one suffices and if some function needs to deal with multiple | 91 // one suffices and if some function needs to deal with multiple |
105 // matching elements it can get at them through the FormElement*. | 92 // matching elements it can get at them through the FormElement*. |
106 // Note: This assignment adds a reference to the InputElement. | 93 // Note: This assignment adds a reference to the InputElement. |
107 result->input_elements[data.fields[j].name] = input_element; | 94 result->input_elements[data.username.name] = input_element; |
108 found_input = true; | 95 found_input = true; |
109 } | 96 } |
110 } | 97 } |
98 } | |
111 | 99 |
112 // A required element was not found. This is not the right form. | 100 // Fill the password input field. |
113 // Make sure no input elements from a partially matched form in this | 101 found_input = false; |
vabr (Chromium)
2014/09/30 14:19:49
At this point you throw out the previous value of
Pritam Nikam
2014/10/13 10:48:00
Done.
| |
114 // iteration remain in the result set. | 102 fe->getNamedElements(data.password.name, temp_elements); |
115 // Note: clear will remove a reference from each InputElement. | 103 for (size_t i = 0; i < temp_elements.size(); ++i) { |
vabr (Chromium)
2014/09/30 14:19:48
Before you prepare the final version of this CL, p
Ilya Sherman
2014/09/30 20:02:32
I will emphasize this comment by phrasing it more
Pritam Nikam
2014/10/13 10:48:00
Done.
Pritam Nikam
2014/10/13 10:48:00
Done.
| |
116 if (!found_input) { | 104 if (temp_elements[i].to<blink::WebElement>().hasHTMLTagName("input")) { |
117 result->input_elements.clear(); | 105 // Check for a non-unique match. |
118 return false; | 106 if (found_input) { |
107 found_input = false; | |
108 break; | |
109 } | |
110 | |
111 // Only fill saved passwords into password fields and usernames into | |
112 // text fields. | |
113 blink::WebInputElement input_element = | |
114 temp_elements[i].to<blink::WebInputElement>(); | |
115 | |
116 // This element matched, add it to our temporary result. It's possible | |
117 // there are multiple matches, but for purposes of identifying the form | |
118 // one suffices and if some function needs to deal with multiple | |
119 // matching elements it can get at them through the FormElement*. | |
120 // Note: This assignment adds a reference to the InputElement. | |
121 result->input_elements[data.password.name] = input_element; | |
122 found_input = true; | |
119 } | 123 } |
120 } | 124 } |
125 | |
126 // A required element was not found. This is not the right form. | |
127 // Make sure no input elements from a partially matched form in this | |
128 // iteration remain in the result set. | |
129 // Note: clear will remove a reference from each InputElement. | |
130 if (!found_input) { | |
131 result->input_elements.clear(); | |
132 return false; | |
133 } | |
134 | |
121 return true; | 135 return true; |
122 } | 136 } |
123 | 137 |
124 // Helper to locate form elements identified by |data|. | 138 // Helper to locate form elements identified by |data|. |
125 void FindFormElements(blink::WebView* view, | 139 void FindFormElements(blink::WebView* view, |
126 const FormData& data, | 140 const FormData& data, |
127 FormElementsList* results) { | 141 FormElementsList* results) { |
128 DCHECK(view); | 142 DCHECK(view); |
129 DCHECK(results); | 143 DCHECK(results); |
130 blink::WebFrame* main_frame = view->mainFrame(); | 144 blink::WebFrame* main_frame = view->mainFrame(); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
215 // Log a message including the name, method and action of |form|. | 229 // Log a message including the name, method and action of |form|. |
216 void LogHTMLForm(SavePasswordProgressLogger* logger, | 230 void LogHTMLForm(SavePasswordProgressLogger* logger, |
217 SavePasswordProgressLogger::StringID message_id, | 231 SavePasswordProgressLogger::StringID message_id, |
218 const blink::WebFormElement& form) { | 232 const blink::WebFormElement& form) { |
219 logger->LogHTMLForm(message_id, | 233 logger->LogHTMLForm(message_id, |
220 form.name().utf8(), | 234 form.name().utf8(), |
221 GURL(form.action().utf8())); | 235 GURL(form.action().utf8())); |
222 } | 236 } |
223 | 237 |
224 bool FillDataContainsUsername(const PasswordFormFillData& fill_data) { | 238 bool FillDataContainsUsername(const PasswordFormFillData& fill_data) { |
225 return !fill_data.basic_data.fields[0].name.empty(); | 239 return !fill_data.basic_data.username.name.empty(); |
226 } | 240 } |
227 | 241 |
228 } // namespace | 242 } // namespace |
229 | 243 |
230 //////////////////////////////////////////////////////////////////////////////// | 244 //////////////////////////////////////////////////////////////////////////////// |
231 // PasswordAutofillAgent, public: | 245 // PasswordAutofillAgent, public: |
232 | 246 |
233 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view) | 247 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view) |
234 : content::RenderViewObserver(render_view), | 248 : content::RenderViewObserver(render_view), |
235 usernames_usage_(NOTHING_TO_AUTOFILL), | 249 usernames_usage_(NOTHING_TO_AUTOFILL), |
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
808 for (iter = forms.begin(); iter != forms.end(); ++iter) { | 822 for (iter = forms.begin(); iter != forms.end(); ++iter) { |
809 scoped_ptr<FormElements> form_elements(*iter); | 823 scoped_ptr<FormElements> form_elements(*iter); |
810 | 824 |
811 // Attach autocomplete listener to enable selecting alternate logins. | 825 // Attach autocomplete listener to enable selecting alternate logins. |
812 blink::WebInputElement username_element, password_element; | 826 blink::WebInputElement username_element, password_element; |
813 | 827 |
814 // Check whether the password form has a username input field. | 828 // Check whether the password form has a username input field. |
815 bool form_contains_username_field = FillDataContainsUsername(form_data); | 829 bool form_contains_username_field = FillDataContainsUsername(form_data); |
816 if (form_contains_username_field) { | 830 if (form_contains_username_field) { |
817 username_element = | 831 username_element = |
818 form_elements->input_elements[form_data.basic_data.fields[0].name]; | 832 form_elements->input_elements[form_data.basic_data.username.name]; |
819 } | 833 } |
820 | 834 |
821 // No password field, bail out. | 835 // No password field, bail out. |
822 if (form_data.basic_data.fields[1].name.empty()) | 836 if (form_data.basic_data.password.name.empty()) |
823 break; | 837 break; |
824 | 838 |
825 // Get pointer to password element. (We currently only support single | 839 // Get pointer to password element. (We currently only support single |
826 // password forms). | 840 // password forms). |
827 password_element = | 841 password_element = |
828 form_elements->input_elements[form_data.basic_data.fields[1].name]; | 842 form_elements->input_elements[form_data.basic_data.password.name]; |
829 | 843 |
830 // If wait_for_username is true, we don't want to initially fill the form | 844 // If wait_for_username is true, we don't want to initially fill the form |
831 // until the user types in a valid username. | 845 // until the user types in a valid username. |
832 if (!form_data.wait_for_username) | 846 if (!form_data.wait_for_username) |
833 FillFormOnPasswordRecieved(form_data, username_element, password_element); | 847 FillFormOnPasswordRecieved(form_data, username_element, password_element); |
834 | 848 |
835 // We might have already filled this form if there are two <form> elements | 849 // We might have already filled this form if there are two <form> elements |
836 // with identical markup. | 850 // with identical markup. |
837 if (login_to_password_info_.find(username_element) != | 851 if (login_to_password_info_.find(username_element) != |
838 login_to_password_info_.end()) | 852 login_to_password_info_.end()) |
(...skipping 28 matching lines...) Expand all Loading... | |
867 : backspace_pressed_last(false), password_was_edited_last(false) { | 881 : backspace_pressed_last(false), password_was_edited_last(false) { |
868 } | 882 } |
869 | 883 |
870 void PasswordAutofillAgent::GetSuggestions( | 884 void PasswordAutofillAgent::GetSuggestions( |
871 const PasswordFormFillData& fill_data, | 885 const PasswordFormFillData& fill_data, |
872 const base::string16& input, | 886 const base::string16& input, |
873 std::vector<base::string16>* suggestions, | 887 std::vector<base::string16>* suggestions, |
874 std::vector<base::string16>* realms, | 888 std::vector<base::string16>* realms, |
875 bool show_all) { | 889 bool show_all) { |
876 if (show_all || | 890 if (show_all || |
877 StartsWith(fill_data.basic_data.fields[0].value, input, false)) { | 891 StartsWith(fill_data.basic_data.username.value, input, false)) { |
878 suggestions->push_back(fill_data.basic_data.fields[0].value); | 892 suggestions->push_back(fill_data.basic_data.username.value); |
879 realms->push_back(base::UTF8ToUTF16(fill_data.preferred_realm)); | 893 realms->push_back(base::UTF8ToUTF16(fill_data.preferred_realm)); |
880 } | 894 } |
881 | 895 |
882 for (PasswordFormFillData::LoginCollection::const_iterator iter = | 896 for (PasswordFormFillData::LoginCollection::const_iterator iter = |
883 fill_data.additional_logins.begin(); | 897 fill_data.additional_logins.begin(); |
884 iter != fill_data.additional_logins.end(); | 898 iter != fill_data.additional_logins.end(); |
885 ++iter) { | 899 ++iter) { |
886 if (show_all || StartsWith(iter->first, input, false)) { | 900 if (show_all || StartsWith(iter->first, input, false)) { |
887 suggestions->push_back(iter->first); | 901 suggestions->push_back(iter->first); |
888 realms->push_back(base::UTF8ToUTF16(iter->second.realm)); | 902 realms->push_back(base::UTF8ToUTF16(iter->second.realm)); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
956 // If we can't modify the password, don't try to set the username | 970 // If we can't modify the password, don't try to set the username |
957 if (!IsElementAutocompletable(password_element)) | 971 if (!IsElementAutocompletable(password_element)) |
958 return; | 972 return; |
959 | 973 |
960 // Try to set the username to the preferred name, but only if the field | 974 // Try to set the username to the preferred name, but only if the field |
961 // can be set and isn't prefilled. | 975 // can be set and isn't prefilled. |
962 if (form_contains_username_field && | 976 if (form_contains_username_field && |
963 IsElementAutocompletable(username_element) && | 977 IsElementAutocompletable(username_element) && |
964 username_element.value().isEmpty()) { | 978 username_element.value().isEmpty()) { |
965 // TODO(tkent): Check maxlength and pattern. | 979 // TODO(tkent): Check maxlength and pattern. |
966 username_element.setValue(fill_data.basic_data.fields[0].value, true); | 980 username_element.setValue(fill_data.basic_data.username.value, true); |
967 } | 981 } |
968 | 982 |
969 // Fill if we have an exact match for the username. Note that this sets | 983 // Fill if we have an exact match for the username. Note that this sets |
970 // username to autofilled. | 984 // username to autofilled. |
971 FillUserNameAndPassword(&username_element, | 985 FillUserNameAndPassword(&username_element, |
972 &password_element, | 986 &password_element, |
973 fill_data, | 987 fill_data, |
974 true /* exact_username_match */, | 988 true /* exact_username_match */, |
975 false /* set_selection */); | 989 false /* set_selection */); |
976 } | 990 } |
(...skipping 11 matching lines...) Expand all Loading... | |
988 base::string16 current_username; | 1002 base::string16 current_username; |
989 if (!username_element->isNull()) { | 1003 if (!username_element->isNull()) { |
990 current_username = username_element->value(); | 1004 current_username = username_element->value(); |
991 } | 1005 } |
992 | 1006 |
993 // username and password will contain the match found if any. | 1007 // username and password will contain the match found if any. |
994 base::string16 username; | 1008 base::string16 username; |
995 base::string16 password; | 1009 base::string16 password; |
996 | 1010 |
997 // Look for any suitable matches to current field text. | 1011 // Look for any suitable matches to current field text. |
998 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value, | 1012 if (DoUsernamesMatch(fill_data.basic_data.username.value, |
999 current_username, | 1013 current_username, |
1000 exact_username_match)) { | 1014 exact_username_match)) { |
1001 username = fill_data.basic_data.fields[0].value; | 1015 username = fill_data.basic_data.username.value; |
1002 password = fill_data.basic_data.fields[1].value; | 1016 password = fill_data.basic_data.password.value; |
1003 } else { | 1017 } else { |
1004 // Scan additional logins for a match. | 1018 // Scan additional logins for a match. |
1005 PasswordFormFillData::LoginCollection::const_iterator iter; | 1019 PasswordFormFillData::LoginCollection::const_iterator iter; |
1006 for (iter = fill_data.additional_logins.begin(); | 1020 for (iter = fill_data.additional_logins.begin(); |
1007 iter != fill_data.additional_logins.end(); | 1021 iter != fill_data.additional_logins.end(); |
1008 ++iter) { | 1022 ++iter) { |
1009 if (DoUsernamesMatch( | 1023 if (DoUsernamesMatch( |
1010 iter->first, current_username, exact_username_match)) { | 1024 iter->first, current_username, exact_username_match)) { |
1011 username = iter->first; | 1025 username = iter->first; |
1012 password = iter->second.password; | 1026 password = iter->second.password; |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1162 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); | 1176 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); |
1163 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && | 1177 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && |
1164 password_form->password_value.empty() && | 1178 password_form->password_value.empty() && |
1165 password_form->new_password_value.empty())) { | 1179 password_form->new_password_value.empty())) { |
1166 return; | 1180 return; |
1167 } | 1181 } |
1168 provisionally_saved_forms_[frame].reset(password_form.release()); | 1182 provisionally_saved_forms_[frame].reset(password_form.release()); |
1169 } | 1183 } |
1170 | 1184 |
1171 } // namespace autofill | 1185 } // namespace autofill |
OLD | NEW |