Home | History | Annotate | Download | only in autofill
      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.
     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.
    102 bool IsTextInput(const HTMLInputElement* element) {
    103     if (!element)
    104         return false;
    105 
    106     return element->isTextField() && !element->isPasswordField();
    107 }
    108 
    109 bool IsSelectElement(const HTMLFormControlElement& element) {
    110     return formControlType(element) == kSelectOne;
    111 }
    112 
    113 bool IsOptionElement(Element& element) {
    114     return element.hasTagName(optionTag);
    115 }
    116 
    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.
    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.
    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|.
    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>
    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>
    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>
    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.
    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 
    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.
    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 
    359 FormManager::FormManager() {
    360 }
    361 
    362 FormManager::~FormManager() {
    363     Reset();
    364 }
    365 
    366 // static
    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
    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
    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 
    561 void FormManager::ExtractForms(Frame* frame) {
    562 
    563     ResetFrame(frame);
    564 
    565     WTF::PassRefPtr<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 
    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 
    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 
    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 
    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 
    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 
    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 
    758 void FormManager::Reset() {
    759     form_elements_.reset();
    760 }
    761 
    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 
    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 
    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 
    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 
    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 
    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 
    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