• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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