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

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

Issue 548953002: [Password Manager] Modified to support saving passwords on forms without username fields. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Reverted refactoring changes. 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 // The password form may not contain a username field
71 // (http://crbug.com/406343), but continue autofilling password field.
72 size_t j = 0;
vabr (Chromium) 2014/09/25 12:39:48 Out of the for-loop, this looks a bit strange. Wha
Pritam Nikam 2014/09/25 13:38:18 Done.
73 if (data.fields[0].name.empty())
74 ++j;
75
70 // Loop through the list of elements we need to find on the form in order to 76 // Loop through the list of elements we need to find on the form in order to
71 // autofill it. If we don't find any one of them, abort processing this 77 // autofill it. If we don't find any one of them, abort processing this
72 // form; it can't be the right one. 78 // form; it can't be the right one.
73 for (size_t j = 0; j < data.fields.size(); j++) { 79 for (; j < data.fields.size(); ++j) {
74 blink::WebVector<blink::WebNode> temp_elements; 80 blink::WebVector<blink::WebNode> temp_elements;
75 fe->getNamedElements(data.fields[j].name, temp_elements); 81 fe->getNamedElements(data.fields[j].name, temp_elements);
76 82
77 // Match the first input element, if any. 83 // Match the first input element, if any.
78 // |getNamedElements| may return non-input elements where the names match, 84 // |getNamedElements| may return non-input elements where the names match,
79 // so the results are filtered for input elements. 85 // so the results are filtered for input elements.
80 // If more than one match is made, then we have ambiguity (due to misuse 86 // If more than one match is made, then we have ambiguity (due to misuse
81 // of "name" attribute) so is it considered not found. 87 // of "name" attribute) so is it considered not found.
82 bool found_input = false; 88 bool found_input = false;
83 for (size_t i = 0; i < temp_elements.size(); ++i) { 89 for (size_t i = 0; i < temp_elements.size(); ++i) {
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 217
212 // Log a message including the name, method and action of |form|. 218 // Log a message including the name, method and action of |form|.
213 void LogHTMLForm(SavePasswordProgressLogger* logger, 219 void LogHTMLForm(SavePasswordProgressLogger* logger,
214 SavePasswordProgressLogger::StringID message_id, 220 SavePasswordProgressLogger::StringID message_id,
215 const blink::WebFormElement& form) { 221 const blink::WebFormElement& form) {
216 logger->LogHTMLForm(message_id, 222 logger->LogHTMLForm(message_id,
217 form.name().utf8(), 223 form.name().utf8(),
218 GURL(form.action().utf8())); 224 GURL(form.action().utf8()));
219 } 225 }
220 226
227 bool FillDataContainsUsername(const PasswordFormFillData& fill_data) {
228 return !fill_data.basic_data.fields[0].name.empty();
229 }
230
221 } // namespace 231 } // namespace
222 232
223 //////////////////////////////////////////////////////////////////////////////// 233 ////////////////////////////////////////////////////////////////////////////////
224 // PasswordAutofillAgent, public: 234 // PasswordAutofillAgent, public:
225 235
226 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view) 236 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view)
227 : content::RenderViewObserver(render_view), 237 : content::RenderViewObserver(render_view),
228 usernames_usage_(NOTHING_TO_AUTOFILL), 238 usernames_usage_(NOTHING_TO_AUTOFILL),
229 web_view_(render_view->GetWebView()), 239 web_view_(render_view->GetWebView()),
230 logging_state_active_(false), 240 logging_state_active_(false),
(...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after
795 } 805 }
796 806
797 FormElementsList forms; 807 FormElementsList forms;
798 // We own the FormElements* in forms. 808 // We own the FormElements* in forms.
799 FindFormElements(render_view()->GetWebView(), form_data.basic_data, &forms); 809 FindFormElements(render_view()->GetWebView(), form_data.basic_data, &forms);
800 FormElementsList::iterator iter; 810 FormElementsList::iterator iter;
801 for (iter = forms.begin(); iter != forms.end(); ++iter) { 811 for (iter = forms.begin(); iter != forms.end(); ++iter) {
802 scoped_ptr<FormElements> form_elements(*iter); 812 scoped_ptr<FormElements> form_elements(*iter);
803 813
804 // Attach autocomplete listener to enable selecting alternate logins. 814 // Attach autocomplete listener to enable selecting alternate logins.
805 // First, get pointers to username element. 815 blink::WebInputElement username_element, password_element;
806 blink::WebInputElement username_element = 816
807 form_elements->input_elements[form_data.basic_data.fields[0].name]; 817 // Check whether the password form has a username input field.
818 bool form_contains_username_field = FillDataContainsUsername(form_data);
819 if (form_contains_username_field) {
820 username_element =
821 form_elements->input_elements[form_data.basic_data.fields[0].name];
822 }
823
824 // No password field, bail out.
825 if (form_data.basic_data.fields[1].name.empty())
826 break;
808 827
809 // Get pointer to password element. (We currently only support single 828 // Get pointer to password element. (We currently only support single
810 // password forms). 829 // password forms).
811 blink::WebInputElement password_element = 830 password_element =
812 form_elements->input_elements[form_data.basic_data.fields[1].name]; 831 form_elements->input_elements[form_data.basic_data.fields[1].name];
813 832
814 // If wait_for_username is true, we don't want to initially fill the form 833 // If wait_for_username is true, we don't want to initially fill the form
815 // until the user types in a valid username. 834 // until the user types in a valid username.
816 if (!form_data.wait_for_username) 835 if (!form_data.wait_for_username)
817 FillFormOnPasswordRecieved(form_data, username_element, password_element); 836 FillFormOnPasswordRecieved(form_data, username_element, password_element);
818 837
819 // We might have already filled this form if there are two <form> elements 838 // We might have already filled this form if there are two <form> elements
820 // with identical markup. 839 // with identical markup.
821 if (login_to_password_info_.find(username_element) != 840 if (login_to_password_info_.find(username_element) !=
822 login_to_password_info_.end()) 841 login_to_password_info_.end())
823 continue; 842 continue;
824 843
825 PasswordInfo password_info; 844 PasswordInfo password_info;
826 password_info.fill_data = form_data; 845 password_info.fill_data = form_data;
827 password_info.password_field = password_element; 846 password_info.password_field = password_element;
828 login_to_password_info_[username_element] = password_info; 847 login_to_password_info_[username_element] = password_info;
829 password_to_username_[password_element] = username_element; 848 password_to_username_[password_element] = username_element;
830 849
831 FormData form; 850 FormData form;
832 FormFieldData field; 851 FormFieldData field;
833 FindFormAndFieldForFormControlElement( 852 if (form_contains_username_field) {
834 username_element, &form, &field, REQUIRE_NONE); 853 FindFormAndFieldForFormControlElement(
854 username_element, &form, &field, REQUIRE_NONE);
855 }
856
835 Send(new AutofillHostMsg_AddPasswordFormMapping( 857 Send(new AutofillHostMsg_AddPasswordFormMapping(
836 routing_id(), field, form_data)); 858 routing_id(), field, form_data));
837 } 859 }
838 } 860 }
839 861
840 void PasswordAutofillAgent::OnSetLoggingState(bool active) { 862 void PasswordAutofillAgent::OnSetLoggingState(bool active) {
841 logging_state_active_ = active; 863 logging_state_active_ = active;
842 } 864 }
843 865
844 //////////////////////////////////////////////////////////////////////////////// 866 ////////////////////////////////////////////////////////////////////////////////
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
922 944
923 void PasswordAutofillAgent::FillFormOnPasswordRecieved( 945 void PasswordAutofillAgent::FillFormOnPasswordRecieved(
924 const PasswordFormFillData& fill_data, 946 const PasswordFormFillData& fill_data,
925 blink::WebInputElement username_element, 947 blink::WebInputElement username_element,
926 blink::WebInputElement password_element) { 948 blink::WebInputElement password_element) {
927 // Do not fill if the password field is in an iframe. 949 // Do not fill if the password field is in an iframe.
928 DCHECK(password_element.document().frame()); 950 DCHECK(password_element.document().frame());
929 if (password_element.document().frame()->parent()) 951 if (password_element.document().frame()->parent())
930 return; 952 return;
931 953
954 bool form_contains_username_field = FillDataContainsUsername(fill_data);
932 if (!ShouldIgnoreAutocompleteOffForPasswordFields() && 955 if (!ShouldIgnoreAutocompleteOffForPasswordFields() &&
933 !username_element.form().autoComplete()) 956 form_contains_username_field && !username_element.form().autoComplete())
934 return; 957 return;
935 958
936 // If we can't modify the password, don't try to set the username 959 // If we can't modify the password, don't try to set the username
937 if (!IsElementAutocompletable(password_element)) 960 if (!IsElementAutocompletable(password_element))
938 return; 961 return;
939 962
940 // Try to set the username to the preferred name, but only if the field 963 // Try to set the username to the preferred name, but only if the field
941 // can be set and isn't prefilled. 964 // can be set and isn't prefilled.
942 if (IsElementAutocompletable(username_element) && 965 if (form_contains_username_field &&
966 IsElementAutocompletable(username_element) &&
943 username_element.value().isEmpty()) { 967 username_element.value().isEmpty()) {
944 // TODO(tkent): Check maxlength and pattern. 968 // TODO(tkent): Check maxlength and pattern.
945 username_element.setValue(fill_data.basic_data.fields[0].value, true); 969 username_element.setValue(fill_data.basic_data.fields[0].value, true);
946 } 970 }
947 971
948 // Fill if we have an exact match for the username. Note that this sets 972 // Fill if we have an exact match for the username. Note that this sets
949 // username to autofilled. 973 // username to autofilled.
950 FillUserNameAndPassword(&username_element, 974 FillUserNameAndPassword(&username_element,
951 &password_element, 975 &password_element,
952 fill_data, 976 fill_data,
953 true /* exact_username_match */, 977 true /* exact_username_match */,
954 false /* set_selection */); 978 false /* set_selection */);
955 } 979 }
956 980
957 bool PasswordAutofillAgent::FillUserNameAndPassword( 981 bool PasswordAutofillAgent::FillUserNameAndPassword(
958 blink::WebInputElement* username_element, 982 blink::WebInputElement* username_element,
959 blink::WebInputElement* password_element, 983 blink::WebInputElement* password_element,
960 const PasswordFormFillData& fill_data, 984 const PasswordFormFillData& fill_data,
961 bool exact_username_match, 985 bool exact_username_match,
962 bool set_selection) { 986 bool set_selection) {
963 base::string16 current_username = username_element->value(); 987 // Don't fill username if password can't be set.
988 if (!IsElementAutocompletable(*password_element))
989 return false;
990
991 base::string16 current_username;
992 if (!username_element->isNull()) {
993 current_username = username_element->value();
994 }
995
964 // username and password will contain the match found if any. 996 // username and password will contain the match found if any.
965 base::string16 username; 997 base::string16 username;
966 base::string16 password; 998 base::string16 password;
967 999
968 // Don't fill username if password can't be set.
969 if (!IsElementAutocompletable(*password_element))
970 return false;
971
972 // Look for any suitable matches to current field text. 1000 // Look for any suitable matches to current field text.
973 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value, 1001 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value,
974 current_username, 1002 current_username,
975 exact_username_match)) { 1003 exact_username_match)) {
976 username = fill_data.basic_data.fields[0].value; 1004 username = fill_data.basic_data.fields[0].value;
977 password = fill_data.basic_data.fields[1].value; 1005 password = fill_data.basic_data.fields[1].value;
978 } else { 1006 } else {
979 // Scan additional logins for a match. 1007 // Scan additional logins for a match.
980 PasswordFormFillData::LoginCollection::const_iterator iter; 1008 PasswordFormFillData::LoginCollection::const_iterator iter;
981 for (iter = fill_data.additional_logins.begin(); 1009 for (iter = fill_data.additional_logins.begin();
(...skipping 27 matching lines...) Expand all
1009 } 1037 }
1010 } 1038 }
1011 } 1039 }
1012 if (password.empty()) 1040 if (password.empty())
1013 return false; // No match was found. 1041 return false; // No match was found.
1014 1042
1015 // TODO(tkent): Check maxlength and pattern for both username and password 1043 // TODO(tkent): Check maxlength and pattern for both username and password
1016 // fields. 1044 // fields.
1017 1045
1018 // Input matches the username, fill in required values. 1046 // Input matches the username, fill in required values.
1019 if (IsElementAutocompletable(*username_element)) { 1047 if (!username_element->isNull() &&
1048 IsElementAutocompletable(*username_element)) {
1020 username_element->setValue(username, true); 1049 username_element->setValue(username, true);
1021 username_element->setAutofilled(true); 1050 username_element->setAutofilled(true);
1022 1051
1023 if (set_selection) { 1052 if (set_selection) {
1024 username_element->setSelectionRange(current_username.length(), 1053 username_element->setSelectionRange(current_username.length(),
1025 username.length()); 1054 username.length());
1026 } 1055 }
1027 } else if (current_username != username) { 1056 } else if (current_username != username) {
1028 // If the username can't be filled and it doesn't match a saved password 1057 // If the username can't be filled and it doesn't match a saved password
1029 // as is, don't autofill a password. 1058 // as is, don't autofill a password.
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1067 &password, 1096 &password,
1068 fill_data, 1097 fill_data,
1069 false /* exact_username_match */, 1098 false /* exact_username_match */,
1070 true /* set_selection */); 1099 true /* set_selection */);
1071 #endif 1100 #endif
1072 } 1101 }
1073 1102
1074 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { 1103 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) {
1075 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); 1104 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin();
1076 iter != login_to_password_info_.end();) { 1105 iter != login_to_password_info_.end();) {
1077 if (iter->first.document().frame() == frame) { 1106 // There may not be a username field, so get the frame from the password
1107 // field.
1108 if (iter->second.password_field.document().frame() == frame) {
1078 password_to_username_.erase(iter->second.password_field); 1109 password_to_username_.erase(iter->second.password_field);
1079 login_to_password_info_.erase(iter++); 1110 login_to_password_info_.erase(iter++);
1080 } else { 1111 } else {
1081 ++iter; 1112 ++iter;
1082 } 1113 }
1083 } 1114 }
1084 for (FrameToPasswordFormMap::iterator iter = 1115 for (FrameToPasswordFormMap::iterator iter =
1085 provisionally_saved_forms_.begin(); 1116 provisionally_saved_forms_.begin();
1086 iter != provisionally_saved_forms_.end();) { 1117 iter != provisionally_saved_forms_.end();) {
1087 if (iter->first == frame) 1118 if (iter->first == frame)
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1134 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); 1165 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form));
1135 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && 1166 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD &&
1136 password_form->password_value.empty() && 1167 password_form->password_value.empty() &&
1137 password_form->new_password_value.empty())) { 1168 password_form->new_password_value.empty())) {
1138 return; 1169 return;
1139 } 1170 }
1140 provisionally_saved_forms_[frame].reset(password_form.release()); 1171 provisionally_saved_forms_[frame].reset(password_form.release());
1141 } 1172 }
1142 1173
1143 } // namespace autofill 1174 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698