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

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: Incorporated review inputs. 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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 // necessary form elements. To avoid having to look these up again when we want 55 // necessary form elements. To avoid having to look these up again when we want
56 // to fill the form, the FindFormElements function stores the pointers 56 // to fill the form, the FindFormElements function stores the pointers
57 // in a FormElements* result, referenced to ensure they are safe to use. 57 // in a FormElements* result, referenced to ensure they are safe to use.
58 struct FormElements { 58 struct FormElements {
59 blink::WebFormElement form_element; 59 blink::WebFormElement form_element;
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 funtion to fill the input field.
vabr (Chromium) 2014/10/13 12:30:52 The comment is not useful -- it only says what the
Pritam Nikam 2014/10/16 12:55:13 Done.
66 static bool FillInputField(blink::WebFormElement* fe,
vabr (Chromium) 2014/10/13 12:30:52 Drop the "static", this is already in the anonymou
vabr (Chromium) 2014/10/13 12:30:52 nit: fe -> form_element http://google-styleguide.g
Pritam Nikam 2014/10/16 12:55:13 Done.
Pritam Nikam 2014/10/16 12:55:13 Done.
67 const base::string16& field_name,
68 FormElements* result,
69 bool is_password_field) {
vabr (Chromium) 2014/10/13 12:30:53 optional nit: To make the callsite easier to read,
Pritam Nikam 2014/10/16 12:55:13 Done.
70 bool found_input = false;
71 blink::WebVector<blink::WebNode> temp_elements;
72
73 // Fill the username input field.
74 fe->getNamedElements(field_name, temp_elements);
75 for (size_t i = 0; i < temp_elements.size(); ++i) {
76 if (temp_elements[i].to<blink::WebElement>().hasHTMLTagName("input")) {
77 // Check for a non-unique match.
78 if (found_input) {
79 found_input = false;
vabr (Chromium) 2014/10/13 12:30:53 While you are changing this code anyway: the old w
Pritam Nikam 2014/10/16 12:55:13 Done.
80 break;
81 }
82
83 // Only fill saved passwords into password fields and usernames into
84 // text fields.
85 blink::WebInputElement input_element =
86 temp_elements[i].to<blink::WebInputElement>();
87 if (input_element.isPasswordField() != is_password_field)
88 continue;
89
90 // This element matched, add it to our temporary result. It's possible
91 // there are multiple matches, but for purposes of identifying the form
92 // one suffices and if some function needs to deal with multiple
93 // matching elements it can get at them through the FormElement*.
94 // Note: This assignment adds a reference to the InputElement.
vabr (Chromium) 2014/10/13 12:30:53 While at it, please replace InputElement with HTML
Pritam Nikam 2014/10/16 12:55:13 Done.
95 result->input_elements[field_name] = input_element;
96 found_input = true;
97 }
98 }
99
100 // A required element was not found. This is not the right form.
101 // Make sure no input elements from a partially matched form in this
102 // iteration remain in the result set.
103 // Note: clear will remove a reference from each InputElement.
104 if (!found_input)
105 result->input_elements.clear();
106
107 return found_input;
108 }
109
65 // Helper to search the given form element for the specified input elements 110 // Helper to search the given form element for the specified input elements
66 // in |data|, and add results to |result|. 111 // in |data|, and add results to |result|.
67 static bool FindFormInputElements(blink::WebFormElement* fe, 112 static bool FindFormInputElements(blink::WebFormElement* fe,
68 const FormData& data, 113 const FormData& data,
69 FormElements* result) { 114 FormElements* result) {
70 const bool username_is_present = !data.fields[0].name.empty(); 115 bool found_input = FillInputField(fe, data.password.name, result, true);
vabr (Chromium) 2014/10/13 12:30:52 The code will be easier to read if you rename: fou
Pritam Nikam 2014/10/16 12:55:13 Done.
116 if (found_input && !data.username.name.empty())
117 found_input = FillInputField(fe, data.username.name, result, false);
vabr (Chromium) 2014/10/13 12:30:53 You can just exit early by return found_input &&
Pritam Nikam 2014/10/16 12:55:13 Done.
71 118
72 // Loop through the list of elements we need to find on the form in order to 119 return found_input;
73 // autofill it. If we don't find any one of them, abort processing this
74 // form; it can't be the right one.
75 // First field is the username, skip it if not present.
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) {
87 if (temp_elements[i].to<blink::WebElement>().hasHTMLTagName("input")) {
88 // Check for a non-unique match.
89 if (found_input) {
90 found_input = false;
91 break;
92 }
93
94 // Only fill saved passwords into password fields and usernames into
95 // text fields.
96 blink::WebInputElement input_element =
97 temp_elements[i].to<blink::WebInputElement>();
98 if (input_element.isPasswordField() !=
99 (data.fields[j].form_control_type == "password"))
100 continue;
101
102 // This element matched, add it to our temporary result. It's possible
103 // there are multiple matches, but for purposes of identifying the form
104 // one suffices and if some function needs to deal with multiple
105 // matching elements it can get at them through the FormElement*.
106 // Note: This assignment adds a reference to the InputElement.
107 result->input_elements[data.fields[j].name] = input_element;
108 found_input = true;
109 }
110 }
111
112 // A required element was not found. This is not the right form.
113 // Make sure no input elements from a partially matched form in this
114 // iteration remain in the result set.
115 // Note: clear will remove a reference from each InputElement.
116 if (!found_input) {
117 result->input_elements.clear();
118 return false;
119 }
120 }
121 return true;
122 } 120 }
123 121
124 // Helper to locate form elements identified by |data|. 122 // Helper to locate form elements identified by |data|.
125 void FindFormElements(blink::WebView* view, 123 void FindFormElements(blink::WebView* view,
126 const FormData& data, 124 const FormData& data,
127 FormElementsList* results) { 125 FormElementsList* results) {
128 DCHECK(view); 126 DCHECK(view);
129 DCHECK(results); 127 DCHECK(results);
130 blink::WebFrame* main_frame = view->mainFrame(); 128 blink::WebFrame* main_frame = view->mainFrame();
131 if (!main_frame) 129 if (!main_frame)
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 // Log a message including the name, method and action of |form|. 213 // Log a message including the name, method and action of |form|.
216 void LogHTMLForm(SavePasswordProgressLogger* logger, 214 void LogHTMLForm(SavePasswordProgressLogger* logger,
217 SavePasswordProgressLogger::StringID message_id, 215 SavePasswordProgressLogger::StringID message_id,
218 const blink::WebFormElement& form) { 216 const blink::WebFormElement& form) {
219 logger->LogHTMLForm(message_id, 217 logger->LogHTMLForm(message_id,
220 form.name().utf8(), 218 form.name().utf8(),
221 GURL(form.action().utf8())); 219 GURL(form.action().utf8()));
222 } 220 }
223 221
224 bool FillDataContainsUsername(const PasswordFormFillData& fill_data) { 222 bool FillDataContainsUsername(const PasswordFormFillData& fill_data) {
225 return !fill_data.basic_data.fields[0].name.empty(); 223 return !fill_data.basic_data.username.name.empty();
226 } 224 }
227 225
228 } // namespace 226 } // namespace
229 227
230 //////////////////////////////////////////////////////////////////////////////// 228 ////////////////////////////////////////////////////////////////////////////////
231 // PasswordAutofillAgent, public: 229 // PasswordAutofillAgent, public:
232 230
233 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view) 231 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view)
234 : content::RenderViewObserver(render_view), 232 : content::RenderViewObserver(render_view),
235 usernames_usage_(NOTHING_TO_AUTOFILL), 233 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) { 806 for (iter = forms.begin(); iter != forms.end(); ++iter) {
809 scoped_ptr<FormElements> form_elements(*iter); 807 scoped_ptr<FormElements> form_elements(*iter);
810 808
811 // Attach autocomplete listener to enable selecting alternate logins. 809 // Attach autocomplete listener to enable selecting alternate logins.
812 blink::WebInputElement username_element, password_element; 810 blink::WebInputElement username_element, password_element;
813 811
814 // Check whether the password form has a username input field. 812 // Check whether the password form has a username input field.
815 bool form_contains_username_field = FillDataContainsUsername(form_data); 813 bool form_contains_username_field = FillDataContainsUsername(form_data);
816 if (form_contains_username_field) { 814 if (form_contains_username_field) {
817 username_element = 815 username_element =
818 form_elements->input_elements[form_data.basic_data.fields[0].name]; 816 form_elements->input_elements[form_data.basic_data.username.name];
819 } 817 }
820 818
821 // No password field, bail out. 819 // No password field, bail out.
822 if (form_data.basic_data.fields[1].name.empty()) 820 if (form_data.basic_data.password.name.empty())
823 break; 821 break;
824 822
825 // Get pointer to password element. (We currently only support single 823 // Get pointer to password element. (We currently only support single
826 // password forms). 824 // password forms).
827 password_element = 825 password_element =
828 form_elements->input_elements[form_data.basic_data.fields[1].name]; 826 form_elements->input_elements[form_data.basic_data.password.name];
829 827
830 // If wait_for_username is true, we don't want to initially fill the form 828 // If wait_for_username is true, we don't want to initially fill the form
831 // until the user types in a valid username. 829 // until the user types in a valid username.
832 if (!form_data.wait_for_username) 830 if (!form_data.wait_for_username)
833 FillFormOnPasswordRecieved(form_data, username_element, password_element); 831 FillFormOnPasswordRecieved(form_data, username_element, password_element);
834 832
835 // We might have already filled this form if there are two <form> elements 833 // We might have already filled this form if there are two <form> elements
836 // with identical markup. 834 // with identical markup.
837 if (login_to_password_info_.find(username_element) != 835 if (login_to_password_info_.find(username_element) !=
838 login_to_password_info_.end()) 836 login_to_password_info_.end())
(...skipping 28 matching lines...) Expand all
867 : backspace_pressed_last(false), password_was_edited_last(false) { 865 : backspace_pressed_last(false), password_was_edited_last(false) {
868 } 866 }
869 867
870 void PasswordAutofillAgent::GetSuggestions( 868 void PasswordAutofillAgent::GetSuggestions(
871 const PasswordFormFillData& fill_data, 869 const PasswordFormFillData& fill_data,
872 const base::string16& input, 870 const base::string16& input,
873 std::vector<base::string16>* suggestions, 871 std::vector<base::string16>* suggestions,
874 std::vector<base::string16>* realms, 872 std::vector<base::string16>* realms,
875 bool show_all) { 873 bool show_all) {
876 if (show_all || 874 if (show_all ||
877 StartsWith(fill_data.basic_data.fields[0].value, input, false)) { 875 StartsWith(fill_data.basic_data.username.value, input, false)) {
878 suggestions->push_back(fill_data.basic_data.fields[0].value); 876 suggestions->push_back(fill_data.basic_data.username.value);
879 realms->push_back(base::UTF8ToUTF16(fill_data.preferred_realm)); 877 realms->push_back(base::UTF8ToUTF16(fill_data.preferred_realm));
880 } 878 }
881 879
882 for (PasswordFormFillData::LoginCollection::const_iterator iter = 880 for (PasswordFormFillData::LoginCollection::const_iterator iter =
883 fill_data.additional_logins.begin(); 881 fill_data.additional_logins.begin();
884 iter != fill_data.additional_logins.end(); 882 iter != fill_data.additional_logins.end();
885 ++iter) { 883 ++iter) {
886 if (show_all || StartsWith(iter->first, input, false)) { 884 if (show_all || StartsWith(iter->first, input, false)) {
887 suggestions->push_back(iter->first); 885 suggestions->push_back(iter->first);
888 realms->push_back(base::UTF8ToUTF16(iter->second.realm)); 886 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 954 // If we can't modify the password, don't try to set the username
957 if (!IsElementAutocompletable(password_element)) 955 if (!IsElementAutocompletable(password_element))
958 return; 956 return;
959 957
960 // Try to set the username to the preferred name, but only if the field 958 // Try to set the username to the preferred name, but only if the field
961 // can be set and isn't prefilled. 959 // can be set and isn't prefilled.
962 if (form_contains_username_field && 960 if (form_contains_username_field &&
963 IsElementAutocompletable(username_element) && 961 IsElementAutocompletable(username_element) &&
964 username_element.value().isEmpty()) { 962 username_element.value().isEmpty()) {
965 // TODO(tkent): Check maxlength and pattern. 963 // TODO(tkent): Check maxlength and pattern.
966 username_element.setValue(fill_data.basic_data.fields[0].value, true); 964 username_element.setValue(fill_data.basic_data.username.value, true);
967 } 965 }
968 966
969 // Fill if we have an exact match for the username. Note that this sets 967 // Fill if we have an exact match for the username. Note that this sets
970 // username to autofilled. 968 // username to autofilled.
971 FillUserNameAndPassword(&username_element, 969 FillUserNameAndPassword(&username_element,
972 &password_element, 970 &password_element,
973 fill_data, 971 fill_data,
974 true /* exact_username_match */, 972 true /* exact_username_match */,
975 false /* set_selection */); 973 false /* set_selection */);
976 } 974 }
(...skipping 11 matching lines...) Expand all
988 base::string16 current_username; 986 base::string16 current_username;
989 if (!username_element->isNull()) { 987 if (!username_element->isNull()) {
990 current_username = username_element->value(); 988 current_username = username_element->value();
991 } 989 }
992 990
993 // username and password will contain the match found if any. 991 // username and password will contain the match found if any.
994 base::string16 username; 992 base::string16 username;
995 base::string16 password; 993 base::string16 password;
996 994
997 // Look for any suitable matches to current field text. 995 // Look for any suitable matches to current field text.
998 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value, 996 if (DoUsernamesMatch(fill_data.basic_data.username.value,
999 current_username, 997 current_username,
1000 exact_username_match)) { 998 exact_username_match)) {
1001 username = fill_data.basic_data.fields[0].value; 999 username = fill_data.basic_data.username.value;
1002 password = fill_data.basic_data.fields[1].value; 1000 password = fill_data.basic_data.password.value;
1003 } else { 1001 } else {
1004 // Scan additional logins for a match. 1002 // Scan additional logins for a match.
1005 PasswordFormFillData::LoginCollection::const_iterator iter; 1003 PasswordFormFillData::LoginCollection::const_iterator iter;
1006 for (iter = fill_data.additional_logins.begin(); 1004 for (iter = fill_data.additional_logins.begin();
1007 iter != fill_data.additional_logins.end(); 1005 iter != fill_data.additional_logins.end();
1008 ++iter) { 1006 ++iter) {
1009 if (DoUsernamesMatch( 1007 if (DoUsernamesMatch(
1010 iter->first, current_username, exact_username_match)) { 1008 iter->first, current_username, exact_username_match)) {
1011 username = iter->first; 1009 username = iter->first;
1012 password = iter->second.password; 1010 password = iter->second.password;
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
1162 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); 1160 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form));
1163 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && 1161 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD &&
1164 password_form->password_value.empty() && 1162 password_form->password_value.empty() &&
1165 password_form->new_password_value.empty())) { 1163 password_form->new_password_value.empty())) {
1166 return; 1164 return;
1167 } 1165 }
1168 provisionally_saved_forms_[frame].reset(password_form.release()); 1166 provisionally_saved_forms_[frame].reset(password_form.release());
1169 } 1167 }
1170 1168
1171 } // namespace autofill 1169 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698