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

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

Issue 614023002: [Password manager] Relplace the FormFieldData vector from autofill::FormData with named fields… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 2 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
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_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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698