OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "webkit/glue/dom_operations.h" | 5 #include "webkit/glue/dom_operations.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
10 #include "base/string_number_conversions.h" | 10 #include "base/string_number_conversions.h" |
11 #include "base/string_split.h" | 11 #include "base/string_split.h" |
| 12 #include "base/string_util.h" |
12 #include "third_party/WebKit/WebKit/chromium/public/WebAnimationController.h" | 13 #include "third_party/WebKit/WebKit/chromium/public/WebAnimationController.h" |
13 #include "third_party/WebKit/WebKit/chromium/public/WebDocument.h" | 14 #include "third_party/WebKit/WebKit/chromium/public/WebDocument.h" |
14 #include "third_party/WebKit/WebKit/chromium/public/WebElement.h" | 15 #include "third_party/WebKit/WebKit/chromium/public/WebElement.h" |
15 #include "third_party/WebKit/WebKit/chromium/public/WebFormElement.h" | |
16 #include "third_party/WebKit/WebKit/chromium/public/WebFrame.h" | 16 #include "third_party/WebKit/WebKit/chromium/public/WebFrame.h" |
17 #include "third_party/WebKit/WebKit/chromium/public/WebInputElement.h" | 17 #include "third_party/WebKit/WebKit/chromium/public/WebInputElement.h" |
18 #include "third_party/WebKit/WebKit/chromium/public/WebNode.h" | 18 #include "third_party/WebKit/WebKit/chromium/public/WebNode.h" |
19 #include "third_party/WebKit/WebKit/chromium/public/WebNodeCollection.h" | 19 #include "third_party/WebKit/WebKit/chromium/public/WebNodeCollection.h" |
20 #include "third_party/WebKit/WebKit/chromium/public/WebNodeList.h" | 20 #include "third_party/WebKit/WebKit/chromium/public/WebNodeList.h" |
| 21 #include "third_party/WebKit/WebKit/chromium/public/WebString.h" |
21 #include "third_party/WebKit/WebKit/chromium/public/WebVector.h" | 22 #include "third_party/WebKit/WebKit/chromium/public/WebVector.h" |
22 #include "third_party/WebKit/WebKit/chromium/public/WebView.h" | 23 #include "third_party/WebKit/WebKit/chromium/public/WebView.h" |
23 #include "webkit/glue/form_data.h" | |
24 #include "webkit/glue/password_form_dom_manager.h" | |
25 #include "webkit/glue/webpasswordautocompletelistener_impl.h" | |
26 | 24 |
27 using WebKit::WebAnimationController; | 25 using WebKit::WebAnimationController; |
28 using WebKit::WebDocument; | 26 using WebKit::WebDocument; |
29 using WebKit::WebElement; | 27 using WebKit::WebElement; |
30 using WebKit::WebFormElement; | |
31 using WebKit::WebFrame; | 28 using WebKit::WebFrame; |
32 using WebKit::WebInputElement; | 29 using WebKit::WebInputElement; |
33 using WebKit::WebNode; | 30 using WebKit::WebNode; |
34 using WebKit::WebNodeCollection; | 31 using WebKit::WebNodeCollection; |
35 using WebKit::WebNodeList; | 32 using WebKit::WebNodeList; |
| 33 using WebKit::WebString; |
36 using WebKit::WebVector; | 34 using WebKit::WebVector; |
37 using WebKit::WebView; | 35 using WebKit::WebView; |
38 | 36 |
39 namespace { | 37 namespace { |
40 | 38 |
41 // Structure for storage the unique set of all savable resource links for | 39 // Structure for storage the unique set of all savable resource links for |
42 // making sure that no duplicated resource link in final result. The consumer | 40 // making sure that no duplicated resource link in final result. The consumer |
43 // of the SavableResourcesUniqueCheck is responsible for keeping these pointers | 41 // of the SavableResourcesUniqueCheck is responsible for keeping these pointers |
44 // valid for the lifetime of the SavableResourcesUniqueCheck instance. | 42 // valid for the lifetime of the SavableResourcesUniqueCheck instance. |
45 struct SavableResourcesUniqueCheck { | 43 struct SavableResourcesUniqueCheck { |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 current_doc, | 144 current_doc, |
147 unique_check, | 145 unique_check, |
148 result); | 146 result); |
149 } | 147 } |
150 } | 148 } |
151 | 149 |
152 } // namespace | 150 } // namespace |
153 | 151 |
154 namespace webkit_glue { | 152 namespace webkit_glue { |
155 | 153 |
156 // Map element name to a list of pointers to corresponding elements to simplify | |
157 // form filling. | |
158 typedef std::map<string16, WebKit::WebInputElement> | |
159 FormInputElementMap; | |
160 | |
161 // Utility struct for form lookup and autofill. When we parse the DOM to lookup | |
162 // a form, in addition to action and origin URL's we have to compare all | |
163 // necessary form elements. To avoid having to look these up again when we want | |
164 // to fill the form, the FindFormElements function stores the pointers | |
165 // in a FormElements* result, referenced to ensure they are safe to use. | |
166 struct FormElements { | |
167 WebFormElement form_element; | |
168 FormInputElementMap input_elements; | |
169 FormElements() { | |
170 } | |
171 }; | |
172 | |
173 typedef std::vector<FormElements*> FormElementsList; | |
174 | |
175 // Internal implementation of FillForm API. | |
176 static bool FillFormImpl(FormElements* fe, const FormData& data) { | |
177 if (!fe->form_element.autoComplete()) | |
178 return false; | |
179 | |
180 std::map<string16, string16> data_map; | |
181 for (size_t i = 0; i < data.fields.size(); i++) | |
182 data_map[data.fields[i].name()] = data.fields[i].value(); | |
183 | |
184 for (FormInputElementMap::iterator it = fe->input_elements.begin(); | |
185 it != fe->input_elements.end(); ++it) { | |
186 WebKit::WebInputElement& element = it->second; | |
187 if (!element.value().isEmpty()) // Don't overwrite pre-filled values. | |
188 continue; | |
189 if (element.isPasswordField() && | |
190 (!element.isEnabledFormControl() || element.hasAttribute("readonly"))) { | |
191 continue; // Don't fill uneditable password fields. | |
192 } | |
193 if (!element.isValidValue(data_map[it->first])) | |
194 continue; | |
195 | |
196 element.setValue(data_map[it->first]); | |
197 element.setAutofilled(true); | |
198 element.dispatchFormControlChangeEvent(); | |
199 } | |
200 | |
201 return false; | |
202 } | |
203 | |
204 // Helper to search the given form element for the specified input elements | |
205 // in |data|, and add results to |result|. | |
206 static bool FindFormInputElements(WebFormElement* fe, | |
207 const FormData& data, | |
208 FormElements* result) { | |
209 // Loop through the list of elements we need to find on the form in | |
210 // order to autofill it. If we don't find any one of them, abort | |
211 // processing this form; it can't be the right one. | |
212 for (size_t j = 0; j < data.fields.size(); j++) { | |
213 WebVector<WebNode> temp_elements; | |
214 fe->getNamedElements(data.fields[j].name(), temp_elements); | |
215 if (temp_elements.isEmpty()) { | |
216 // We didn't find a required element. This is not the right form. | |
217 // Make sure no input elements from a partially matched form | |
218 // in this iteration remain in the result set. | |
219 // Note: clear will remove a reference from each InputElement. | |
220 result->input_elements.clear(); | |
221 return false; | |
222 } | |
223 // This element matched, add it to our temporary result. It's possible | |
224 // there are multiple matches, but for purposes of identifying the form | |
225 // one suffices and if some function needs to deal with multiple | |
226 // matching elements it can get at them through the FormElement*. | |
227 // Note: This assignment adds a reference to the InputElement. | |
228 result->input_elements[data.fields[j].name()] = | |
229 temp_elements[0].to<WebInputElement>(); | |
230 } | |
231 return true; | |
232 } | |
233 | |
234 // Helper to locate form elements identified by |data|. | |
235 static void FindFormElements(WebView* view, | |
236 const FormData& data, | |
237 FormElementsList* results) { | |
238 DCHECK(view); | |
239 DCHECK(results); | |
240 WebFrame* main_frame = view->mainFrame(); | |
241 if (!main_frame) | |
242 return; | |
243 | |
244 GURL::Replacements rep; | |
245 rep.ClearQuery(); | |
246 rep.ClearRef(); | |
247 | |
248 // Loop through each frame. | |
249 for (WebFrame* f = main_frame; f; f = f->traverseNext(false)) { | |
250 WebDocument doc = f->document(); | |
251 if (!doc.isHTMLDocument()) | |
252 continue; | |
253 | |
254 GURL full_origin(f->url()); | |
255 if (data.origin != full_origin.ReplaceComponents(rep)) | |
256 continue; | |
257 | |
258 WebVector<WebFormElement> forms; | |
259 f->forms(forms); | |
260 | |
261 for (size_t i = 0; i < forms.size(); ++i) { | |
262 WebFormElement fe = forms[i]; | |
263 // Action URL must match. | |
264 GURL full_action(f->document().completeURL(fe.action())); | |
265 if (data.action != full_action.ReplaceComponents(rep)) | |
266 continue; | |
267 | |
268 scoped_ptr<FormElements> curr_elements(new FormElements); | |
269 if (!FindFormInputElements(&fe, data, curr_elements.get())) | |
270 continue; | |
271 | |
272 // We found the right element. | |
273 // Note: this assignment adds a reference to |fe|. | |
274 curr_elements->form_element = fe; | |
275 results->push_back(curr_elements.release()); | |
276 } | |
277 } | |
278 } | |
279 | |
280 void FillPasswordForm(WebView* view, | |
281 const PasswordFormFillData& data) { | |
282 FormElementsList forms; | |
283 // We own the FormElements* in forms. | |
284 FindFormElements(view, data.basic_data, &forms); | |
285 FormElementsList::iterator iter; | |
286 for (iter = forms.begin(); iter != forms.end(); ++iter) { | |
287 scoped_ptr<FormElements> form_elements(*iter); | |
288 | |
289 // If wait_for_username is true, we don't want to initially fill the form | |
290 // until the user types in a valid username. | |
291 if (!data.wait_for_username) | |
292 FillFormImpl(form_elements.get(), data.basic_data); | |
293 | |
294 // Attach autocomplete listener to enable selecting alternate logins. | |
295 // First, get pointers to username element. | |
296 WebInputElement username_element = | |
297 form_elements->input_elements[data.basic_data.fields[0].name()]; | |
298 | |
299 // Get pointer to password element. (We currently only support single | |
300 // password forms). | |
301 WebInputElement password_element = | |
302 form_elements->input_elements[data.basic_data.fields[1].name()]; | |
303 | |
304 username_element.document().frame()->registerPasswordListener( | |
305 username_element, | |
306 new WebPasswordAutocompleteListenerImpl( | |
307 new WebInputElementDelegate(username_element), | |
308 new WebInputElementDelegate(password_element), | |
309 data)); | |
310 } | |
311 } | |
312 | |
313 WebString GetSubResourceLinkFromElement(const WebElement& element) { | 154 WebString GetSubResourceLinkFromElement(const WebElement& element) { |
314 const char* attribute_name = NULL; | 155 const char* attribute_name = NULL; |
315 if (element.hasTagName("img") || | 156 if (element.hasTagName("img") || |
316 element.hasTagName("script")) { | 157 element.hasTagName("script")) { |
317 attribute_name = "src"; | 158 attribute_name = "src"; |
318 } else if (element.hasTagName("input")) { | 159 } else if (element.hasTagName("input")) { |
319 const WebInputElement input = element.toConst<WebInputElement>(); | 160 const WebInputElement input = element.toConst<WebInputElement>(); |
320 if (input.isImageButton()) { | 161 if (input.isImageButton()) { |
321 attribute_name = "src"; | 162 attribute_name = "src"; |
322 } | 163 } |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
620 if (!element.hasTagName("meta")) | 461 if (!element.hasTagName("meta")) |
621 continue; | 462 continue; |
622 WebString value = element.getAttribute(attribute_name); | 463 WebString value = element.getAttribute(attribute_name); |
623 if (value.isNull() || value != attribute_value) | 464 if (value.isNull() || value != attribute_value) |
624 continue; | 465 continue; |
625 meta_elements->push_back(element); | 466 meta_elements->push_back(element); |
626 } | 467 } |
627 } | 468 } |
628 | 469 |
629 } // webkit_glue | 470 } // webkit_glue |
OLD | NEW |