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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 // Loop through the list of elements we need to find on the form in order to | 70 // 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 | 71 // autofill it. If we don't find any one of them, abort processing this |
72 // form; it can't be the right one. | 72 // form; it can't be the right one. |
73 for (size_t j = 0; j < data.fields.size(); j++) { | 73 for (size_t j = 0; j < data.fields.size(); ++j) { |
74 blink::WebVector<blink::WebNode> temp_elements; | 74 blink::WebVector<blink::WebNode> temp_elements; |
75 fe->getNamedElements(data.fields[j].name, temp_elements); | 75 fe->getNamedElements(data.fields[j].name, temp_elements); |
76 | 76 |
77 // Match the first input element, if any. | 77 // Match the first input element, if any. |
78 // |getNamedElements| may return non-input elements where the names match, | 78 // |getNamedElements| may return non-input elements where the names match, |
79 // so the results are filtered for input elements. | 79 // so the results are filtered for input elements. |
80 // If more than one match is made, then we have ambiguity (due to misuse | 80 // If more than one match is made, then we have ambiguity (due to misuse |
81 // of "name" attribute) so is it considered not found. | 81 // of "name" attribute) so is it considered not found. |
82 bool found_input = false; | 82 bool found_input = false; |
83 for (size_t i = 0; i < temp_elements.size(); ++i) { | 83 for (size_t i = 0; i < temp_elements.size(); ++i) { |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
211 | 211 |
212 // Log a message including the name, method and action of |form|. | 212 // Log a message including the name, method and action of |form|. |
213 void LogHTMLForm(SavePasswordProgressLogger* logger, | 213 void LogHTMLForm(SavePasswordProgressLogger* logger, |
214 SavePasswordProgressLogger::StringID message_id, | 214 SavePasswordProgressLogger::StringID message_id, |
215 const blink::WebFormElement& form) { | 215 const blink::WebFormElement& form) { |
216 logger->LogHTMLForm(message_id, | 216 logger->LogHTMLForm(message_id, |
217 form.name().utf8(), | 217 form.name().utf8(), |
218 GURL(form.action().utf8())); | 218 GURL(form.action().utf8())); |
219 } | 219 } |
220 | 220 |
221 bool FillDataContainsUsername(const PasswordFormFillData& fill_data) { | |
222 return (fill_data.basic_data.fields.size() == 2); | |
223 } | |
224 | |
221 } // namespace | 225 } // namespace |
222 | 226 |
223 //////////////////////////////////////////////////////////////////////////////// | 227 //////////////////////////////////////////////////////////////////////////////// |
224 // PasswordAutofillAgent, public: | 228 // PasswordAutofillAgent, public: |
225 | 229 |
226 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view) | 230 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view) |
227 : content::RenderViewObserver(render_view), | 231 : content::RenderViewObserver(render_view), |
228 usernames_usage_(NOTHING_TO_AUTOFILL), | 232 usernames_usage_(NOTHING_TO_AUTOFILL), |
229 web_view_(render_view->GetWebView()), | 233 web_view_(render_view->GetWebView()), |
230 logging_state_active_(false), | 234 logging_state_active_(false), |
(...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
795 } | 799 } |
796 | 800 |
797 FormElementsList forms; | 801 FormElementsList forms; |
798 // We own the FormElements* in forms. | 802 // We own the FormElements* in forms. |
799 FindFormElements(render_view()->GetWebView(), form_data.basic_data, &forms); | 803 FindFormElements(render_view()->GetWebView(), form_data.basic_data, &forms); |
800 FormElementsList::iterator iter; | 804 FormElementsList::iterator iter; |
801 for (iter = forms.begin(); iter != forms.end(); ++iter) { | 805 for (iter = forms.begin(); iter != forms.end(); ++iter) { |
802 scoped_ptr<FormElements> form_elements(*iter); | 806 scoped_ptr<FormElements> form_elements(*iter); |
803 | 807 |
804 // Attach autocomplete listener to enable selecting alternate logins. | 808 // Attach autocomplete listener to enable selecting alternate logins. |
805 // First, get pointers to username element. | 809 blink::WebInputElement username_element, password_element; |
806 blink::WebInputElement username_element = | 810 |
807 form_elements->input_elements[form_data.basic_data.fields[0].name]; | 811 // Check whether the password form has a username input field. |
812 bool form_contains_username_field = FillDataContainsUsername(form_data); | |
813 size_t field_index = 0; | |
814 if (form_contains_username_field) { | |
815 username_element = | |
816 form_elements | |
817 ->input_elements[form_data.basic_data.fields[field_index].name]; | |
818 | |
819 ++field_index; | |
820 } | |
821 | |
822 // No password field, bail out. | |
823 if (form_data.basic_data.fields[field_index].name.empty()) | |
824 break; | |
808 | 825 |
809 // Get pointer to password element. (We currently only support single | 826 // Get pointer to password element. (We currently only support single |
810 // password forms). | 827 // password forms). |
811 blink::WebInputElement password_element = | 828 password_element = |
812 form_elements->input_elements[form_data.basic_data.fields[1].name]; | 829 form_elements |
830 ->input_elements[form_data.basic_data.fields[field_index].name]; | |
813 | 831 |
814 // If wait_for_username is true, we don't want to initially fill the form | 832 // If wait_for_username is true, we don't want to initially fill the form |
815 // until the user types in a valid username. | 833 // until the user types in a valid username. |
816 if (!form_data.wait_for_username) | 834 if (!form_data.wait_for_username) |
817 FillFormOnPasswordRecieved(form_data, username_element, password_element); | 835 FillFormOnPasswordRecieved(form_data, username_element, password_element); |
818 | 836 |
819 // We might have already filled this form if there are two <form> elements | 837 // We might have already filled this form if there are two <form> elements |
820 // with identical markup. | 838 // with identical markup. |
821 if (login_to_password_info_.find(username_element) != | 839 if (login_to_password_info_.find(username_element) != |
822 login_to_password_info_.end()) | 840 login_to_password_info_.end()) |
823 continue; | 841 continue; |
824 | 842 |
825 PasswordInfo password_info; | 843 PasswordInfo password_info; |
826 password_info.fill_data = form_data; | 844 password_info.fill_data = form_data; |
827 password_info.password_field = password_element; | 845 password_info.password_field = password_element; |
828 login_to_password_info_[username_element] = password_info; | 846 login_to_password_info_[username_element] = password_info; |
829 password_to_username_[password_element] = username_element; | 847 password_to_username_[password_element] = username_element; |
830 | 848 |
831 FormData form; | 849 FormData form; |
832 FormFieldData field; | 850 FormFieldData field; |
833 FindFormAndFieldForFormControlElement( | 851 if (form_contains_username_field) { |
834 username_element, &form, &field, REQUIRE_NONE); | 852 FindFormAndFieldForFormControlElement( |
853 username_element, &form, &field, REQUIRE_NONE); | |
854 } | |
855 | |
835 Send(new AutofillHostMsg_AddPasswordFormMapping( | 856 Send(new AutofillHostMsg_AddPasswordFormMapping( |
836 routing_id(), field, form_data)); | 857 routing_id(), field, form_data)); |
837 } | 858 } |
838 } | 859 } |
839 | 860 |
840 void PasswordAutofillAgent::OnSetLoggingState(bool active) { | 861 void PasswordAutofillAgent::OnSetLoggingState(bool active) { |
841 logging_state_active_ = active; | 862 logging_state_active_ = active; |
842 } | 863 } |
843 | 864 |
844 //////////////////////////////////////////////////////////////////////////////// | 865 //////////////////////////////////////////////////////////////////////////////// |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
922 | 943 |
923 void PasswordAutofillAgent::FillFormOnPasswordRecieved( | 944 void PasswordAutofillAgent::FillFormOnPasswordRecieved( |
924 const PasswordFormFillData& fill_data, | 945 const PasswordFormFillData& fill_data, |
925 blink::WebInputElement username_element, | 946 blink::WebInputElement username_element, |
926 blink::WebInputElement password_element) { | 947 blink::WebInputElement password_element) { |
927 // Do not fill if the password field is in an iframe. | 948 // Do not fill if the password field is in an iframe. |
928 DCHECK(password_element.document().frame()); | 949 DCHECK(password_element.document().frame()); |
929 if (password_element.document().frame()->parent()) | 950 if (password_element.document().frame()->parent()) |
930 return; | 951 return; |
931 | 952 |
953 bool form_contains_username_field = FillDataContainsUsername(fill_data); | |
932 if (!ShouldIgnoreAutocompleteOffForPasswordFields() && | 954 if (!ShouldIgnoreAutocompleteOffForPasswordFields() && |
933 !username_element.form().autoComplete()) | 955 form_contains_username_field && !username_element.form().autoComplete()) |
934 return; | 956 return; |
935 | 957 |
936 // If we can't modify the password, don't try to set the username | 958 // If we can't modify the password, don't try to set the username |
937 if (!IsElementAutocompletable(password_element)) | 959 if (!IsElementAutocompletable(password_element)) |
938 return; | 960 return; |
939 | 961 |
940 // Try to set the username to the preferred name, but only if the field | 962 // Try to set the username to the preferred name, but only if the field |
941 // can be set and isn't prefilled. | 963 // can be set and isn't prefilled. |
942 if (IsElementAutocompletable(username_element) && | 964 if (form_contains_username_field && |
965 IsElementAutocompletable(username_element) && | |
943 username_element.value().isEmpty()) { | 966 username_element.value().isEmpty()) { |
944 // TODO(tkent): Check maxlength and pattern. | 967 // TODO(tkent): Check maxlength and pattern. |
945 username_element.setValue(fill_data.basic_data.fields[0].value, true); | 968 username_element.setValue(fill_data.basic_data.fields[0].value, true); |
946 } | 969 } |
947 | 970 |
948 // Fill if we have an exact match for the username. Note that this sets | 971 // Fill if we have an exact match for the username. Note that this sets |
949 // username to autofilled. | 972 // username to autofilled. |
950 FillUserNameAndPassword(&username_element, | 973 FillUserNameAndPassword(&username_element, |
951 &password_element, | 974 &password_element, |
952 fill_data, | 975 fill_data, |
953 true /* exact_username_match */, | 976 true /* exact_username_match */, |
954 false /* set_selection */); | 977 false /* set_selection */); |
955 } | 978 } |
956 | 979 |
957 bool PasswordAutofillAgent::FillUserNameAndPassword( | 980 bool PasswordAutofillAgent::FillUserNameAndPassword( |
958 blink::WebInputElement* username_element, | 981 blink::WebInputElement* username_element, |
959 blink::WebInputElement* password_element, | 982 blink::WebInputElement* password_element, |
960 const PasswordFormFillData& fill_data, | 983 const PasswordFormFillData& fill_data, |
961 bool exact_username_match, | 984 bool exact_username_match, |
962 bool set_selection) { | 985 bool set_selection) { |
963 base::string16 current_username = username_element->value(); | |
964 // username and password will contain the match found if any. | |
965 base::string16 username; | |
966 base::string16 password; | |
967 | |
968 // Don't fill username if password can't be set. | 986 // Don't fill username if password can't be set. |
969 if (!IsElementAutocompletable(*password_element)) | 987 if (!IsElementAutocompletable(*password_element)) |
970 return false; | 988 return false; |
971 | 989 |
990 // username and password will contain the match found if any. | |
991 base::string16 username; | |
992 base::string16 password; | |
993 base::string16 current_username; | |
994 if (!username_element->isNull()) { | |
995 current_username = username_element->value(); | |
996 } else { | |
997 password = fill_data.basic_data.fields[0].value; | |
998 } | |
999 | |
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, |
vabr (Chromium)
2014/09/25 10:39:59
This potentially tries to match |current_username|
Pritam Nikam
2014/09/25 11:22:46
Done.
Reverted refactoring.
| |
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. |
vabr (Chromium)
2014/09/25 10:39:59
This branch is entered for all forms without usern
Pritam Nikam
2014/09/25 11:22:45
Done.
Reverted refactoring.
| |
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(); |
982 iter != fill_data.additional_logins.end(); | 1010 iter != fill_data.additional_logins.end(); |
983 ++iter) { | 1011 ++iter) { |
984 if (DoUsernamesMatch( | 1012 if (DoUsernamesMatch( |
985 iter->first, current_username, exact_username_match)) { | 1013 iter->first, current_username, exact_username_match)) { |
986 username = iter->first; | 1014 username = iter->first; |
987 password = iter->second.password; | 1015 password = iter->second.password; |
988 break; | 1016 break; |
989 } | 1017 } |
(...skipping 19 matching lines...) Expand all Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |