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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 // necessary form elements. To avoid having to look these up again when we want | 54 // necessary form elements. To avoid having to look these up again when we want |
55 // to fill the form, the FindFormElements function stores the pointers | 55 // to fill the form, the FindFormElements function stores the pointers |
56 // in a FormElements* result, referenced to ensure they are safe to use. | 56 // in a FormElements* result, referenced to ensure they are safe to use. |
57 struct FormElements { | 57 struct FormElements { |
58 blink::WebFormElement form_element; | 58 blink::WebFormElement form_element; |
59 FormInputElementMap input_elements; | 59 FormInputElementMap input_elements; |
60 }; | 60 }; |
61 | 61 |
62 typedef std::vector<FormElements*> FormElementsList; | 62 typedef std::vector<FormElements*> FormElementsList; |
63 | 63 |
64 // Helper to search the given form element for the specified input elements | 64 // Utility function to find the unique entry of the |form_element| for the |
65 // in |data|, and add results to |result|. | 65 // specified input |field|. On successful find, adds it to |result| and returns |
66 static bool FindFormInputElements(blink::WebFormElement* fe, | 66 // |true|. Otherwise clears the references from each |HTMLInputElement| from |
67 const FormData& data, | 67 // |result| and returns |false|. |
68 FormElements* result) { | 68 bool FindFormInputElement(blink::WebFormElement* form_element, |
| 69 const FormFieldData& field, |
| 70 FormElements* result) { |
| 71 blink::WebVector<blink::WebNode> temp_elements; |
| 72 form_element->getNamedElements(field.name, temp_elements); |
| 73 |
| 74 // Match the first input element, if any. |
| 75 // |getNamedElements| may return non-input elements where the names match, |
| 76 // so the results are filtered for input elements. |
| 77 // If more than one match is made, then we have ambiguity (due to misuse |
| 78 // of "name" attribute) so is it considered not found. |
| 79 bool found_input = false; |
| 80 for (size_t i = 0; i < temp_elements.size(); ++i) { |
| 81 if (temp_elements[i].to<blink::WebElement>().hasHTMLTagName("input")) { |
| 82 // Check for a non-unique match. |
| 83 if (found_input) { |
| 84 found_input = false; |
| 85 break; |
| 86 } |
| 87 |
| 88 // Only fill saved passwords into password fields and usernames into |
| 89 // text fields. |
| 90 blink::WebInputElement input_element = |
| 91 temp_elements[i].to<blink::WebInputElement>(); |
| 92 if (input_element.isPasswordField() != |
| 93 (field.form_control_type == "password")) |
| 94 continue; |
| 95 |
| 96 // This element matched, add it to our temporary result. It's possible |
| 97 // there are multiple matches, but for purposes of identifying the form |
| 98 // one suffices and if some function needs to deal with multiple |
| 99 // matching elements it can get at them through the FormElement*. |
| 100 // Note: This assignment adds a reference to the InputElement. |
| 101 result->input_elements[field.name] = input_element; |
| 102 found_input = true; |
| 103 } |
| 104 } |
| 105 |
| 106 // A required element was not found. This is not the right form. |
| 107 // Make sure no input elements from a partially matched form in this |
| 108 // iteration remain in the result set. |
| 109 // Note: clear will remove a reference from each InputElement. |
| 110 if (!found_input) { |
| 111 result->input_elements.clear(); |
| 112 return false; |
| 113 } |
| 114 |
| 115 return true; |
| 116 } |
| 117 |
| 118 // Helper to search the given form element for the specified input elements in |
| 119 // |data|, and add results to |result|. |
| 120 bool FindFormInputElements(blink::WebFormElement* form_element, |
| 121 const FormData& data, |
| 122 FormElements* result) { |
69 const bool username_is_present = !data.fields[0].name.empty(); | 123 const bool username_is_present = !data.fields[0].name.empty(); |
70 | 124 |
71 // Loop through the list of elements we need to find on the form in order to | 125 // Loop through the list of elements we need to find on the form in order to |
72 // autofill it. If we don't find any one of them, abort processing this | 126 // autofill it. If we don't find any one of them, abort processing this |
73 // form; it can't be the right one. | 127 // form; it can't be the right one. |
74 // First field is the username, skip it if not present. | 128 // First field is the username, skip it if not present. |
75 for (size_t j = (username_is_present ? 0 : 1); j < data.fields.size(); ++j) { | 129 for (size_t j = (username_is_present ? 0 : 1); j < data.fields.size(); ++j) { |
76 blink::WebVector<blink::WebNode> temp_elements; | 130 if (!FindFormInputElement(form_element, data.fields[j], result)) |
77 fe->getNamedElements(data.fields[j].name, temp_elements); | 131 return false; |
| 132 } |
78 | 133 |
79 // Match the first input element, if any. | |
80 // |getNamedElements| may return non-input elements where the names match, | |
81 // so the results are filtered for input elements. | |
82 // If more than one match is made, then we have ambiguity (due to misuse | |
83 // of "name" attribute) so is it considered not found. | |
84 bool found_input = false; | |
85 for (size_t i = 0; i < temp_elements.size(); ++i) { | |
86 if (temp_elements[i].to<blink::WebElement>().hasHTMLTagName("input")) { | |
87 // Check for a non-unique match. | |
88 if (found_input) { | |
89 found_input = false; | |
90 break; | |
91 } | |
92 | |
93 // Only fill saved passwords into password fields and usernames into | |
94 // text fields. | |
95 blink::WebInputElement input_element = | |
96 temp_elements[i].to<blink::WebInputElement>(); | |
97 if (input_element.isPasswordField() != | |
98 (data.fields[j].form_control_type == "password")) | |
99 continue; | |
100 | |
101 // This element matched, add it to our temporary result. It's possible | |
102 // there are multiple matches, but for purposes of identifying the form | |
103 // one suffices and if some function needs to deal with multiple | |
104 // matching elements it can get at them through the FormElement*. | |
105 // Note: This assignment adds a reference to the InputElement. | |
106 result->input_elements[data.fields[j].name] = input_element; | |
107 found_input = true; | |
108 } | |
109 } | |
110 | |
111 // A required element was not found. This is not the right form. | |
112 // Make sure no input elements from a partially matched form in this | |
113 // iteration remain in the result set. | |
114 // Note: clear will remove a reference from each InputElement. | |
115 if (!found_input) { | |
116 result->input_elements.clear(); | |
117 return false; | |
118 } | |
119 } | |
120 return true; | 134 return true; |
121 } | 135 } |
122 | 136 |
123 // Helper to locate form elements identified by |data|. | 137 // Helper to locate form elements identified by |data|. |
124 void FindFormElements(blink::WebView* view, | 138 void FindFormElements(blink::WebView* view, |
125 const FormData& data, | 139 const FormData& data, |
126 FormElementsList* results) { | 140 FormElementsList* results) { |
127 DCHECK(view); | 141 DCHECK(view); |
128 DCHECK(results); | 142 DCHECK(results); |
129 blink::WebFrame* main_frame = view->mainFrame(); | 143 blink::WebFrame* main_frame = view->mainFrame(); |
(...skipping 1094 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1224 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); | 1238 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); |
1225 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && | 1239 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && |
1226 password_form->password_value.empty() && | 1240 password_form->password_value.empty() && |
1227 password_form->new_password_value.empty())) { | 1241 password_form->new_password_value.empty())) { |
1228 return; | 1242 return; |
1229 } | 1243 } |
1230 provisionally_saved_forms_[frame].reset(password_form.release()); | 1244 provisionally_saved_forms_[frame].reset(password_form.release()); |
1231 } | 1245 } |
1232 | 1246 |
1233 } // namespace autofill | 1247 } // namespace autofill |
OLD | NEW |