1 /*
2 * Copyright (c) 2010 The Chromium Authors. All rights reserved.
3 * Copyright 2010, The Android Open Source Project
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include "config.h"
28 #include "FormManagerAndroid.h"
29
30 #include "DocumentLoader.h"
31 #include "Element.h"
32 #include "Frame.h"
33 #include "FrameLoader.h"
34 #include "HTMLCollection.h"
35 #include "HTMLFormControlElement.h"
36 #include "HTMLFormElement.h"
37 #include "HTMLInputElement.h"
38 #include "HTMLLabelElement.h"
39 #include "HTMLNames.h"
40 #include "HTMLOptionElement.h"
41 #include "HTMLSelectElement.h"
42 #include "InputElement.h"
43 #include "Node.h"
44 #include "NodeList.h"
45 #include "HTMLCollection.h"
46 #include "FormAssociatedElement.h"
47 #include "QualifiedName.h"
48 #include "StringUtils.h"
49
50 // TODO: This file is taken from chromium/chrome/renderer/form_manager.cc and
51 // customised to use WebCore types rather than WebKit API types. It would be
52 // nice and would ease future merge pain if the two could be combined.
53
54 using webkit_glue::FormData;
55 using webkit_glue::FormField;
56 using WebCore::Element;
57 using WebCore::FormAssociatedElement;
58 using WebCore::HTMLCollection;
59 using WebCore::HTMLElement;
60 using WebCore::HTMLFormControlElement;
61 using WebCore::HTMLFormElement;
62 using WebCore::HTMLInputElement;
63 using WebCore::HTMLLabelElement;
64 using WebCore::HTMLOptionElement;
65 using WebCore::HTMLSelectElement;
66 using WebCore::InputElement;
67 using WebCore::Node;
68 using WebCore::NodeList;
69
70 using namespace WebCore::HTMLNames;
71
72 namespace {
73
74 // Android helper function.
HTMLFormControlElementToHTMLInputElement(const HTMLFormControlElement & element)75 HTMLInputElement* HTMLFormControlElementToHTMLInputElement(const HTMLFormControlElement& element) {
76 Node* node = const_cast<Node*>(static_cast<const Node*>(&element));
77 InputElement* input_element = node->toInputElement();
78 if (node && node->isHTMLElement())
79 return static_cast<HTMLInputElement*>(input_element);
80
81 return 0;
82 }
83
84 // The number of fields required by Autofill. Ideally we could send the forms
85 // to Autofill no matter how many fields are in the forms; however, finding the
86 // label for each field is a costly operation and we can't spare the cycles if
87 // it's not necessary.
88 // Note the on ANDROID we reduce this from Chromium's 3 as it allows us to
89 // Autofill simple name/email forms for example. This improves the mobile
90 // device experience where form filling can be time consuming and frustrating.
91 const size_t kRequiredAutofillFields = 2;
92
93 // The maximum number of form fields we are willing to parse, due to
94 // computational costs. This is a very conservative upper bound.
95 const size_t kMaxParseableFields = 1000;
96
97 // The maximum length allowed for form data.
98 const size_t kMaxDataLength = 1024;
99
100 // In HTML5, all text fields except password are text input fields to
101 // autocomplete.
IsTextInput(const HTMLInputElement * element)102 bool IsTextInput(const HTMLInputElement* element) {
103 if (!element)
104 return false;
105
106 return element->isTextField() && !element->isPasswordField();
107 }
108
IsSelectElement(const HTMLFormControlElement & element)109 bool IsSelectElement(const HTMLFormControlElement& element) {
110 return formControlType(element) == kSelectOne;
111 }
112
IsOptionElement(Element & element)113 bool IsOptionElement(Element& element) {
114 return element.hasTagName(optionTag);
115 }
116
IsAutofillableElement(const HTMLFormControlElement & element)117 bool IsAutofillableElement(const HTMLFormControlElement& element) {
118 HTMLInputElement* html_input_element = HTMLFormControlElementToHTMLInputElement(element);
119 return (html_input_element && IsTextInput(html_input_element)) || IsSelectElement(element);
120 }
121
122 // This is a helper function for the FindChildText() function (see below).
123 // Search depth is limited with the |depth| parameter.
FindChildTextInner(Node * node,int depth)124 string16 FindChildTextInner(Node* node, int depth) {
125 string16 element_text;
126 if (!node || depth <= 0)
127 return element_text;
128
129 string16 node_text = WTFStringToString16(node->nodeValue());
130 TrimWhitespace(node_text, TRIM_ALL, &node_text);
131 if (!node_text.empty())
132 element_text = node_text;
133
134 string16 child_text = FindChildTextInner(node->firstChild(), depth-1);
135 if (!child_text.empty())
136 element_text = element_text + child_text;
137
138 string16 sibling_text = FindChildTextInner(node->nextSibling(), depth-1);
139 if (!sibling_text.empty())
140 element_text = element_text + sibling_text;
141
142 return element_text;
143 }
144
145 // Returns the aggregated values of the decendants or siblings of |element| that
146 // are non-empty text nodes. This is a faster alternative to |innerText()| for
147 // performance critical operations. It does a full depth-first search so can be
148 // used when the structure is not directly known. Whitesapce is trimmed from
149 // text accumulated at descendant and sibling. Search is limited to within 10
150 // siblings and/or descendants.
FindChildText(Element * element)151 string16 FindChildText(Element* element) {
152 Node* child = element->firstChild();
153
154 const int kChildSearchDepth = 10;
155 return FindChildTextInner(child, kChildSearchDepth);
156 }
157
158 // Helper for |InferLabelForElement()| that infers a label, if possible, from
159 // a previous node of |element|.
InferLabelFromPrevious(const HTMLFormControlElement & element)160 string16 InferLabelFromPrevious(const HTMLFormControlElement& element) {
161 string16 inferred_label;
162 Node* previous = element.previousSibling();
163 if (!previous)
164 return string16();
165
166 if (previous->isTextNode()) {
167 inferred_label = WTFStringToString16(previous->nodeValue());
168 TrimWhitespace(inferred_label, TRIM_ALL, &inferred_label);
169 }
170
171 // If we didn't find text, check for previous paragraph.
172 // Eg. <p>Some Text</p><input ...>
173 // Note the lack of whitespace between <p> and <input> elements.
174 if (inferred_label.empty() && previous->isElementNode()) {
175 Element* element = static_cast<Element*>(previous);
176 if (element->hasTagName(pTag))
177 inferred_label = FindChildText(element);
178 }
179
180 // If we didn't find paragraph, check for previous paragraph to this.
181 // Eg. <p>Some Text</p> <input ...>
182 // Note the whitespace between <p> and <input> elements.
183 if (inferred_label.empty()) {
184 Node* sibling = previous->previousSibling();
185 if (sibling && sibling->isElementNode()) {
186 Element* element = static_cast<Element*>(sibling);
187 if (element->hasTagName(pTag))
188 inferred_label = FindChildText(element);
189 }
190 }
191
192 // Look for text node prior to <img> tag.
193 // Eg. Some Text<img/><input ...>
194 if (inferred_label.empty()) {
195 while (inferred_label.empty() && previous) {
196 if (previous->isTextNode()) {
197 inferred_label = WTFStringToString16(previous->nodeValue());
198 TrimWhitespace(inferred_label, TRIM_ALL, &inferred_label);
199 } else if (previous->isElementNode()) {
200 Element* element = static_cast<Element*>(previous);
201 if (!element->hasTagName(imgTag))
202 break;
203 } else
204 break;
205 previous = previous->previousSibling();
206 }
207 }
208
209 // Look for label node prior to <input> tag.
210 // Eg. <label>Some Text</label><input ...>
211 if (inferred_label.empty()) {
212 while (inferred_label.empty() && previous) {
213 if (previous->isTextNode()) {
214 inferred_label = WTFStringToString16(previous->nodeValue());
215 TrimWhitespace(inferred_label, TRIM_ALL, &inferred_label);
216 } else if (previous->isElementNode()) {
217 Element* element = static_cast<Element*>(previous);
218 if (element->hasTagName(labelTag)) {
219 inferred_label = FindChildText(element);
220 } else {
221 break;
222 }
223 } else {
224 break;
225 }
226
227 previous = previous->previousSibling();
228 }
229 }
230
231 return inferred_label;
232 }
233
234 // Helper for |InferLabelForElement()| that infers a label, if possible, from
235 // surrounding table structure.
236 // Eg. <tr><td>Some Text</td><td><input ...></td></tr>
237 // Eg. <tr><td><b>Some Text</b></td><td><b><input ...></b></td></tr>
InferLabelFromTable(const HTMLFormControlElement & element)238 string16 InferLabelFromTable(const HTMLFormControlElement& element) {
239 string16 inferred_label;
240 Node* parent = element.parentNode();
241 while (parent && parent->isElementNode() && !static_cast<Element*>(parent)->hasTagName(tdTag))
242 parent = parent->parentNode();
243
244 // Check all previous siblings, skipping non-element nodes, until we find a
245 // non-empty text block.
246 Node* previous = parent;
247 while(previous) {
248 if (previous->isElementNode()) {
249 Element* e = static_cast<Element*>(previous);
250 if (e->hasTagName(tdTag)) {
251 inferred_label = FindChildText(e);
252 if (!inferred_label.empty())
253 break;
254 }
255 }
256 previous = previous->previousSibling();
257 }
258 return inferred_label;
259 }
260
261 // Helper for |InferLabelForElement()| that infers a label, if possible, from
262 // a surrounding div table.
263 // Eg. <div>Some Text<span><input ...></span></div>
InferLabelFromDivTable(const HTMLFormControlElement & element)264 string16 InferLabelFromDivTable(const HTMLFormControlElement& element) {
265 Node* parent = element.parentNode();
266 while (parent && parent->isElementNode() && !static_cast<Element*>(parent)->hasTagName(divTag))
267 parent = parent->parentNode();
268
269 if (!parent || !parent->isElementNode())
270 return string16();
271
272 Element* e = static_cast<Element*>(parent);
273 if (!e || !e->hasTagName(divTag))
274 return string16();
275
276 return FindChildText(e);
277 }
278
279 // Helper for |InferLabelForElement()| that infers a label, if possible, from
280 // a surrounding definition list.
281 // Eg. <dl><dt>Some Text</dt><dd><input ...></dd></dl>
282 // Eg. <dl><dt><b>Some Text</b></dt><dd><b><input ...></b></dd></dl>
InferLabelFromDefinitionList(const HTMLFormControlElement & element)283 string16 InferLabelFromDefinitionList(const HTMLFormControlElement& element) {
284 string16 inferred_label;
285 Node* parent = element.parentNode();
286 while (parent && parent->isElementNode() && !static_cast<Element*>(parent)->hasTagName(ddTag))
287 parent = parent->parentNode();
288
289 if (parent && parent->isElementNode()) {
290 Element* element = static_cast<Element*>(parent);
291 if (element->hasTagName(ddTag)) {
292 Node* previous = parent->previousSibling();
293
294 // Skip by any intervening text nodes.
295 while (previous && previous->isTextNode())
296 previous = previous->previousSibling();
297
298 if (previous && previous->isElementNode()) {
299 element = static_cast<Element*>(previous);
300 if (element->hasTagName(dtTag))
301 inferred_label = FindChildText(element);
302 }
303 }
304 }
305 return inferred_label;
306 }
307
308 // Infers corresponding label for |element| from surrounding context in the DOM.
309 // Contents of preceding <p> tag or preceding text element found in the form.
InferLabelForElement(const HTMLFormControlElement & element)310 string16 InferLabelForElement(const HTMLFormControlElement& element) {
311 string16 inferred_label = InferLabelFromPrevious(element);
312
313 // If we didn't find a label, check for table cell case.
314 if (inferred_label.empty())
315 inferred_label = InferLabelFromTable(element);
316
317 // If we didn't find a label, check for div table case.
318 if (inferred_label.empty())
319 inferred_label = InferLabelFromDivTable(element);
320
321 // If we didn't find a label, check for definition list case.
322 if (inferred_label.empty())
323 inferred_label = InferLabelFromDefinitionList(element);
324
325 return inferred_label;
326 }
327
GetOptionStringsFromElement(const HTMLSelectElement & select_element,std::vector<string16> * option_strings)328 void GetOptionStringsFromElement(const HTMLSelectElement& select_element, std::vector<string16>* option_strings) {
329 DCHECK(option_strings);
330 option_strings->clear();
331 WTF::Vector<Element*> list_items = select_element.listItems();
332 option_strings->reserve(list_items.size());
333 for (size_t i = 0; i < list_items.size(); ++i) {
334 if (IsOptionElement(*list_items[i])) {
335 option_strings->push_back(WTFStringToString16(static_cast<HTMLOptionElement*>(list_items[i])->value()));
336 }
337 }
338 }
339
340 // Returns the form's |name| attribute if non-empty; otherwise the form's |id|
341 // attribute.
GetFormIdentifier(const HTMLFormElement & form)342 const string16 GetFormIdentifier(const HTMLFormElement& form) {
343 string16 identifier = WTFStringToString16(form.name());
344 if (identifier.empty())
345 identifier = WTFStringToString16(form.getIdAttribute());
346 return identifier;
347 }
348
349 } // namespace
350
351 namespace android {
352
353 struct FormManager::FormElement {
354 RefPtr<HTMLFormElement> form_element;
355 std::vector<RefPtr<HTMLFormControlElement> > control_elements;
356 std::vector<string16> control_values;
357 };
358
FormManager()359 FormManager::FormManager() {
360 }
361
~FormManager()362 FormManager::~FormManager() {
363 Reset();
364 }
365
366 // static
HTMLFormControlElementToFormField(HTMLFormControlElement * element,ExtractMask extract_mask,FormField * field)367 void FormManager::HTMLFormControlElementToFormField(HTMLFormControlElement* element, ExtractMask extract_mask, FormField* field) {
368 DCHECK(field);
369 DCHECK(element);
370
371 // The label is not officially part of a HTMLFormControlElement; however, the
372 // labels for all form control elements are scraped from the DOM and set in
373 // WebFormElementToFormData.
374 field->name = nameForAutofill(*element);
375 field->form_control_type = formControlType(*element);
376
377 if (!IsAutofillableElement(*element))
378 return;
379
380 HTMLInputElement* input_element = HTMLFormControlElementToHTMLInputElement(*element);
381
382 if (IsTextInput(input_element)) {
383 field->max_length = input_element->maxLength();
384 field->is_autofilled = input_element->isAutofilled();
385 } else if (extract_mask & EXTRACT_OPTIONS) {
386 // Set option strings on the field is available.
387 DCHECK(IsSelectElement(*element));
388 HTMLSelectElement* select_element = static_cast<HTMLSelectElement*>(element);
389 std::vector<string16> option_strings;
390 GetOptionStringsFromElement(*select_element, &option_strings);
391 field->option_strings = option_strings;
392 }
393
394 if (!(extract_mask & EXTRACT_VALUE))
395 return;
396
397 string16 value;
398 if (IsTextInput(input_element)) {
399 value = WTFStringToString16(input_element->value());
400 } else {
401 DCHECK(IsSelectElement(*element));
402 HTMLSelectElement* select_element = static_cast<HTMLSelectElement*>(element);
403 value = WTFStringToString16(select_element->value());
404
405 // Convert the |select_element| value to text if requested.
406 if (extract_mask & EXTRACT_OPTION_TEXT) {
407 Vector<Element*> list_items = select_element->listItems();
408 for (size_t i = 0; i < list_items.size(); ++i) {
409 if (IsOptionElement(*list_items[i]) &&
410 WTFStringToString16(static_cast<HTMLOptionElement*>(list_items[i])->value()) == value) {
411 value = WTFStringToString16(static_cast<HTMLOptionElement*>(list_items[i])->text());
412 break;
413 }
414 }
415 }
416 }
417
418 // TODO: This is a temporary stop-gap measure designed to prevent
419 // a malicious site from DOS'ing the browser with extremely large profile
420 // data. The correct solution is to parse this data asynchronously.
421 // See http://crbug.com/49332.
422 if (value.size() > kMaxDataLength)
423 value = value.substr(0, kMaxDataLength);
424
425 field->value = value;
426 }
427
428 // static
LabelForElement(const HTMLFormControlElement & element)429 string16 FormManager::LabelForElement(const HTMLFormControlElement& element) {
430 // Don't scrape labels for elements we can't possible autofill anyway.
431 if (!IsAutofillableElement(element))
432 return string16();
433
434 RefPtr<NodeList> labels = element.document()->getElementsByTagName("label");
435 for (unsigned i = 0; i < labels->length(); ++i) {
436 Node* e = labels->item(i);
437 DCHECK(e->hasTagName(labelTag));
438 HTMLLabelElement* label = static_cast<HTMLLabelElement*>(e);
439 if (label->control() == &element)
440 return FindChildText(label);
441 }
442
443 // Infer the label from context if not found in label element.
444 return InferLabelForElement(element);
445 }
446
447 // static
HTMLFormElementToFormData(HTMLFormElement * element,RequirementsMask requirements,ExtractMask extract_mask,FormData * form)448 bool FormManager::HTMLFormElementToFormData(HTMLFormElement* element, RequirementsMask requirements, ExtractMask extract_mask, FormData* form) {
449 DCHECK(form);
450
451 Frame* frame = element->document()->frame();
452 if (!frame)
453 return false;
454
455 if (requirements & REQUIRE_AUTOCOMPLETE && !element->autoComplete())
456 return false;
457
458 form->name = GetFormIdentifier(*element);
459 form->method = WTFStringToString16(element->method());
460 form->origin = GURL(WTFStringToString16(frame->loader()->documentLoader()->url().string()));
461 form->action = GURL(WTFStringToString16(frame->document()->completeURL(element->action())));
462 form->user_submitted = element->wasUserSubmitted();
463
464 // If the completed URL is not valid, just use the action we get from
465 // WebKit.
466 if (!form->action.is_valid())
467 form->action = GURL(WTFStringToString16(element->action()));
468
469 // A map from a FormField's name to the FormField itself.
470 std::map<string16, FormField*> name_map;
471
472 // The extracted FormFields. We use pointers so we can store them in
473 // |name_map|.
474 ScopedVector<FormField> form_fields;
475
476 WTF::Vector<WebCore::FormAssociatedElement*> control_elements = element->associatedElements();
477
478 // A vector of bools that indicate whether each field in the form meets the
479 // requirements and thus will be in the resulting |form|.
480 std::vector<bool> fields_extracted(control_elements.size(), false);
481
482 for (size_t i = 0; i < control_elements.size(); ++i) {
483 if (!control_elements[i]->isFormControlElement())
484 continue;
485
486 HTMLFormControlElement* control_element = static_cast<HTMLFormControlElement*>(control_elements[i]);
487
488 if(!IsAutofillableElement(*control_element))
489 continue;
490
491 HTMLInputElement* input_element = HTMLFormControlElementToHTMLInputElement(*control_element);
492 if (requirements & REQUIRE_AUTOCOMPLETE && IsTextInput(input_element) &&
493 !input_element->autoComplete())
494 continue;
495
496 if (requirements & REQUIRE_ENABLED && !control_element->isEnabledFormControl())
497 continue;
498
499 // Create a new FormField, fill it out and map it to the field's name.
500 FormField* field = new FormField;
501 HTMLFormControlElementToFormField(control_element, extract_mask, field);
502 form_fields.push_back(field);
503 // TODO: A label element is mapped to a form control element's id.
504 // field->name() will contain the id only if the name does not exist. Add
505 // an id() method to HTMLFormControlElement and use that here.
506 name_map[field->name] = field;
507 fields_extracted[i] = true;
508 }
509
510 // Don't extract field labels if we have no fields.
511 if (form_fields.empty())
512 return false;
513
514 // Loop through the label elements inside the form element. For each label
515 // element, get the corresponding form control element, use the form control
516 // element's name as a key into the <name, FormField> map to find the
517 // previously created FormField and set the FormField's label to the
518 // label.firstChild().nodeValue() of the label element.
519 RefPtr<WebCore::NodeList> labels = element->getElementsByTagName("label");
520 for (unsigned i = 0; i < labels->length(); ++i) {
521 HTMLLabelElement* label = static_cast<WebCore::HTMLLabelElement*>(labels->item(i));
522 HTMLFormControlElement* field_element = label->control();
523 if (!field_element || field_element->type() == "hidden")
524 continue;
525
526 std::map<string16, FormField*>::iterator iter =
527 name_map.find(nameForAutofill(*field_element));
528 // Concatenate labels because some sites might have multiple label
529 // candidates.
530 if (iter != name_map.end())
531 iter->second->label += FindChildText(label);
532 }
533
534 // Loop through the form control elements, extracting the label text from the
535 // DOM. We use the |fields_extracted| vector to make sure we assign the
536 // extracted label to the correct field, as it's possible |form_fields| will
537 // not contain all of the elements in |control_elements|.
538 for (size_t i = 0, field_idx = 0; i < control_elements.size() && field_idx < form_fields.size(); ++i) {
539 // This field didn't meet the requirements, so don't try to find a label for
540 // it.
541 if (!fields_extracted[i])
542 continue;
543
544 if (!control_elements[i]->isFormControlElement())
545 continue;
546
547 const HTMLFormControlElement* control_element = static_cast<HTMLFormControlElement*>(control_elements[i]);
548 if (form_fields[field_idx]->label.empty())
549 form_fields[field_idx]->label = InferLabelForElement(*control_element);
550
551 ++field_idx;
552
553 }
554 // Copy the created FormFields into the resulting FormData object.
555 for (ScopedVector<FormField>::const_iterator iter = form_fields.begin(); iter != form_fields.end(); ++iter)
556 form->fields.push_back(**iter);
557
558 return true;
559 }
560
ExtractForms(Frame * frame)561 void FormManager::ExtractForms(Frame* frame) {
562
563 ResetFrame(frame);
564
565 WTF::RefPtr<HTMLCollection> web_forms = frame->document()->forms();
566
567 for (size_t i = 0; i < web_forms->length(); ++i) {
568 // Owned by |form_elements|.
569 FormElement* form_element = new FormElement;
570 HTMLFormElement* html_form_element = static_cast<HTMLFormElement*>(web_forms->item(i));
571 form_element->form_element = html_form_element;
572
573 WTF::Vector<FormAssociatedElement*> control_elements = html_form_element->associatedElements();
574 for (size_t j = 0; j < control_elements.size(); ++j) {
575 if (!control_elements[j]->isFormControlElement())
576 continue;
577
578 HTMLFormControlElement* element = static_cast<HTMLFormControlElement*>(control_elements[j]);
579
580 if (!IsAutofillableElement(*element))
581 continue;
582
583 form_element->control_elements.push_back(element);
584
585 // Save original values of <select> elements so we can restore them
586 // when |ClearFormWithNode()| is invoked.
587 if (IsSelectElement(*element)) {
588 HTMLSelectElement* select_element = static_cast<HTMLSelectElement*>(element);
589 form_element->control_values.push_back(WTFStringToString16(select_element->value()));
590 } else
591 form_element->control_values.push_back(string16());
592 }
593
594 form_elements_.push_back(form_element);
595 }
596 }
597
GetFormsInFrame(const Frame * frame,RequirementsMask requirements,std::vector<FormData> * forms)598 void FormManager::GetFormsInFrame(const Frame* frame, RequirementsMask requirements, std::vector<FormData>* forms) {
599 DCHECK(frame);
600 DCHECK(forms);
601
602 size_t num_fields_seen = 0;
603 for (FormElementList::const_iterator form_iter = form_elements_.begin(); form_iter != form_elements_.end(); ++form_iter) {
604 FormElement* form_element = *form_iter;
605
606 if (form_element->form_element->document()->frame() != frame)
607 continue;
608
609 // To avoid overly expensive computation, we impose both a minimum and a
610 // maximum number of allowable fields.
611 if (form_element->control_elements.size() < kRequiredAutofillFields ||
612 form_element->control_elements.size() > kMaxParseableFields)
613 continue;
614
615 if (requirements & REQUIRE_AUTOCOMPLETE && !form_element->form_element->autoComplete())
616 continue;
617
618 FormData form;
619 HTMLFormElementToFormData(form_element->form_element.get(), requirements, EXTRACT_VALUE, &form);
620
621 num_fields_seen += form.fields.size();
622 if (num_fields_seen > kMaxParseableFields)
623 break;
624
625 if (form.fields.size() >= kRequiredAutofillFields)
626 forms->push_back(form);
627 }
628 }
629
FindFormWithFormControlElement(HTMLFormControlElement * element,RequirementsMask requirements,FormData * form)630 bool FormManager::FindFormWithFormControlElement(HTMLFormControlElement* element, RequirementsMask requirements, FormData* form) {
631 DCHECK(form);
632
633 const Frame* frame = element->document()->frame();
634 if (!frame)
635 return false;
636
637 for (FormElementList::const_iterator iter = form_elements_.begin(); iter != form_elements_.end(); ++iter) {
638 const FormElement* form_element = *iter;
639
640 if (form_element->form_element->document()->frame() != frame)
641 continue;
642
643 for (std::vector<RefPtr<HTMLFormControlElement> >::const_iterator iter = form_element->control_elements.begin(); iter != form_element->control_elements.end(); ++iter) {
644 HTMLFormControlElement* candidate = iter->get();
645 if (nameForAutofill(*candidate) == nameForAutofill(*element)) {
646 ExtractMask extract_mask = static_cast<ExtractMask>(EXTRACT_VALUE | EXTRACT_OPTIONS);
647 return HTMLFormElementToFormData(form_element->form_element.get(), requirements, extract_mask, form);
648 }
649 }
650 }
651 return false;
652 }
653
FillForm(const FormData & form,Node * node)654 bool FormManager::FillForm(const FormData& form, Node* node) {
655 FormElement* form_element = NULL;
656 if (!FindCachedFormElement(form, &form_element))
657 return false;
658
659 RequirementsMask requirements = static_cast<RequirementsMask>(REQUIRE_AUTOCOMPLETE | REQUIRE_ENABLED | REQUIRE_EMPTY);
660 ForEachMatchingFormField(form_element, node, requirements, form, NewCallback(this, &FormManager::FillFormField));
661
662 return true;
663 }
664
PreviewForm(const FormData & form,Node * node)665 bool FormManager::PreviewForm(const FormData& form, Node* node) {
666 FormElement* form_element = NULL;
667 if (!FindCachedFormElement(form, &form_element))
668 return false;
669
670 RequirementsMask requirements = static_cast<RequirementsMask>(REQUIRE_AUTOCOMPLETE | REQUIRE_ENABLED | REQUIRE_EMPTY);
671 ForEachMatchingFormField(form_element, node, requirements, form, NewCallback(this, &FormManager::PreviewFormField));
672
673 return true;
674 }
675
ClearFormWithNode(Node * node)676 bool FormManager::ClearFormWithNode(Node* node) {
677 FormElement* form_element = NULL;
678 if (!FindCachedFormElementWithNode(node, &form_element))
679 return false;
680
681 for (size_t i = 0; i < form_element->control_elements.size(); ++i) {
682 HTMLFormControlElement* element = form_element->control_elements[i].get();
683 HTMLInputElement* input_element = HTMLFormControlElementToHTMLInputElement(*element);
684 if (IsTextInput(input_element)) {
685
686 // We don't modify the value of disabled fields.
687 if (!input_element->isEnabledFormControl())
688 continue;
689
690 input_element->setValue("");
691 input_element->setAutofilled(false);
692 // Clearing the value in the focused node (above) can cause selection
693 // to be lost. We force selection range to restore the text cursor.
694 if (node == input_element) {
695 int length = input_element->value().length();
696 input_element->setSelectionRange(length, length);
697 }
698 } else {
699 DCHECK(IsSelectElement(*element));
700 HTMLSelectElement* select_element = static_cast<HTMLSelectElement*>(element);
701 if (WTFStringToString16(select_element->value()) != form_element->control_values[i]) {
702 select_element->setValue(form_element->control_values[i].c_str());
703 select_element->dispatchFormControlChangeEvent();
704 }
705 }
706 }
707
708 return true;
709 }
710
ClearPreviewedFormWithNode(Node * node,bool was_autofilled)711 bool FormManager::ClearPreviewedFormWithNode(Node* node, bool was_autofilled) {
712 FormElement* form_element = NULL;
713 if (!FindCachedFormElementWithNode(node, &form_element))
714 return false;
715
716 for (size_t i = 0; i < form_element->control_elements.size(); ++i) {
717 HTMLFormControlElement* element = form_element->control_elements[i].get();
718 HTMLInputElement* input_element = HTMLFormControlElementToHTMLInputElement(*element);
719
720 // Only input elements can be previewed.
721 if (!IsTextInput(input_element))
722 continue;
723
724 // If the input element has not been auto-filled, FormManager has not
725 // previewed this field, so we have nothing to reset.
726 if (!input_element->isAutofilled())
727 continue;
728
729 // There might be unrelated elements in this form which have already been
730 // auto-filled. For example, the user might have already filled the address
731 // part of a form and now be dealing with the credit card section. We only
732 // want to reset the auto-filled status for fields that were previewed.
733 if (input_element->suggestedValue().isEmpty())
734 continue;
735
736 // Clear the suggested value. For the initiating node, also restore the
737 // original value.
738 input_element->setSuggestedValue("");
739 bool is_initiating_node = (node == input_element);
740 if (is_initiating_node) {
741 input_element->setAutofilled(was_autofilled);
742 } else {
743 input_element->setAutofilled(false);
744 }
745
746 // Clearing the suggested value in the focused node (above) can cause
747 // selection to be lost. We force selection range to restore the text
748 // cursor.
749 if (is_initiating_node) {
750 int length = input_element->value().length();
751 input_element->setSelectionRange(length, length);
752 }
753 }
754
755 return true;
756 }
757
Reset()758 void FormManager::Reset() {
759 form_elements_.reset();
760 }
761
ResetFrame(const Frame * frame)762 void FormManager::ResetFrame(const Frame* frame) {
763 FormElementList::iterator iter = form_elements_.begin();
764 while (iter != form_elements_.end()) {
765 if ((*iter)->form_element->document()->frame() == frame)
766 iter = form_elements_.erase(iter);
767 else
768 ++iter;
769 }
770 }
771
FormWithNodeIsAutofilled(Node * node)772 bool FormManager::FormWithNodeIsAutofilled(Node* node) {
773 FormElement* form_element = NULL;
774 if (!FindCachedFormElementWithNode(node, &form_element))
775 return false;
776
777 for (size_t i = 0; i < form_element->control_elements.size(); ++i) {
778 HTMLFormControlElement* element = form_element->control_elements[i].get();
779 HTMLInputElement* input_element = HTMLFormControlElementToHTMLInputElement(*element);
780 if (!IsTextInput(input_element))
781 continue;
782
783 if (input_element->isAutofilled())
784 return true;
785 }
786
787 return false;
788 }
789
FindCachedFormElementWithNode(Node * node,FormElement ** form_element)790 bool FormManager::FindCachedFormElementWithNode(Node* node, FormElement** form_element) {
791 for (FormElementList::const_iterator form_iter = form_elements_.begin(); form_iter != form_elements_.end(); ++form_iter) {
792 for (std::vector<RefPtr<HTMLFormControlElement> >::const_iterator iter = (*form_iter)->control_elements.begin(); iter != (*form_iter)->control_elements.end(); ++iter) {
793 if (iter->get() == node) {
794 *form_element = *form_iter;
795 return true;
796 }
797 }
798 }
799
800 return false;
801 }
802
FindCachedFormElement(const FormData & form,FormElement ** form_element)803 bool FormManager::FindCachedFormElement(const FormData& form, FormElement** form_element) {
804 for (FormElementList::iterator form_iter = form_elements_.begin(); form_iter != form_elements_.end(); ++form_iter) {
805 // TODO: matching on form name here which is not guaranteed to
806 // be unique for the page, nor is it guaranteed to be non-empty. Need to
807 // find a way to uniquely identify the form cross-process. For now we'll
808 // check form name and form action for identity.
809 // http://crbug.com/37990 test file sample8.html.
810 // Also note that WebString() == WebString(string16()) does not evaluate to
811 // |true| -- WebKit distinguisges between a "null" string (lhs) and an
812 // "empty" string (rhs). We don't want that distinction, so forcing to
813 // string16.
814 string16 element_name = GetFormIdentifier(*(*form_iter)->form_element);
815 GURL action(WTFStringToString16((*form_iter)->form_element->document()->completeURL((*form_iter)->form_element->action()).string()));
816 if (element_name == form.name && action == form.action) {
817 *form_element = *form_iter;
818 return true;
819 }
820 }
821
822 return false;
823 }
824
825
ForEachMatchingFormField(FormElement * form,Node * node,RequirementsMask requirements,const FormData & data,Callback * callback)826 void FormManager::ForEachMatchingFormField(FormElement* form, Node* node, RequirementsMask requirements, const FormData& data, Callback* callback) {
827 // It's possible that the site has injected fields into the form after the
828 // page has loaded, so we can't assert that the size of the cached control
829 // elements is equal to the size of the fields in |form|. Fortunately, the
830 // one case in the wild where this happens, paypal.com signup form, the fields
831 // are appended to the end of the form and are not visible.
832 for (size_t i = 0, j = 0; i < form->control_elements.size() && j < data.fields.size(); ++i) {
833 HTMLFormControlElement* element = form->control_elements[i].get();
834 string16 element_name = nameForAutofill(*element);
835
836 // Search forward in the |form| for a corresponding field.
837 size_t k = j;
838 while (k < data.fields.size() && element_name != data.fields[k].name)
839 k++;
840
841 if (k >= data.fields.size())
842 continue;
843
844 DCHECK_EQ(data.fields[k].name, element_name);
845
846 bool is_initiating_node = false;
847
848 HTMLInputElement* input_element = HTMLFormControlElementToHTMLInputElement(*element);
849 if (IsTextInput(input_element)) {
850 // TODO: WebKit currently doesn't handle the autocomplete
851 // attribute for select control elements, but it probably should.
852 if (!input_element->autoComplete())
853 continue;
854
855 is_initiating_node = (input_element == node);
856
857 // Only autofill empty fields and the firls that initiated the filling,
858 // i.e. the field the user is currently editing and interacting with.
859 if (!is_initiating_node && !input_element->value().isEmpty())
860 continue;
861 }
862
863 if (!element->isEnabledFormControl() || element->isReadOnlyFormControl() || !element->isFocusable())
864 continue;
865
866 callback->Run(element, &data.fields[k], is_initiating_node);
867
868 // We found a matching form field so move on to the next.
869 ++j;
870 }
871
872 delete callback;
873 }
874
FillFormField(HTMLFormControlElement * field,const FormField * data,bool is_initiating_node)875 void FormManager::FillFormField(HTMLFormControlElement* field, const FormField* data, bool is_initiating_node) {
876 // Nothing to fill.
877 if (data->value.empty())
878 return;
879
880 HTMLInputElement* input_element = HTMLFormControlElementToHTMLInputElement(*field);
881
882 if (IsTextInput(input_element)) {
883 // If the maxlength attribute contains a negative value, maxLength()
884 // returns the default maxlength value.
885 input_element->setValue(data->value.substr(0, input_element->maxLength()).c_str(), true);
886 input_element->setAutofilled(true);
887 if (is_initiating_node) {
888 int length = input_element->value().length();
889 input_element->setSelectionRange(length, length);
890 }
891 } else {
892 DCHECK(IsSelectElement(*field));
893 HTMLSelectElement* select_element = static_cast<HTMLSelectElement*>(field);
894 if (WTFStringToString16(select_element->value()) != data->value) {
895 select_element->setValue(data->value.c_str());
896 select_element->dispatchFormControlChangeEvent();
897 }
898 }
899 }
900
PreviewFormField(HTMLFormControlElement * field,const FormField * data,bool is_initiating_node)901 void FormManager::PreviewFormField(HTMLFormControlElement* field, const FormField* data, bool is_initiating_node) {
902 // Nothing to preview.
903 if (data->value.empty())
904 return;
905
906 // Only preview input fields.
907 HTMLInputElement* input_element = HTMLFormControlElementToHTMLInputElement(*field);
908 if (!IsTextInput(input_element))
909 return;
910
911 // If the maxlength attribute contains a negative value, maxLength()
912 // returns the default maxlength value.
913 input_element->setSuggestedValue(data->value.substr(0, input_element->maxLength()).c_str());
914 input_element->setAutofilled(true);
915 if (is_initiating_node) {
916 // Select the part of the text that the user didn't type.
917 input_element->setSelectionRange(input_element->value().length(), input_element->suggestedValue().length());
918 }
919 }
920
921 }
922