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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |