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