/*
 * Copyright (c) 2010 The Chromium Authors. All rights reserved.
 * Copyright 2010, The Android Open Source Project
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "FormManagerAndroid.h"

#include "DocumentLoader.h"
#include "Element.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "HTMLCollection.h"
#include "HTMLFormControlElement.h"
#include "HTMLFormElement.h"
#include "HTMLInputElement.h"
#include "HTMLLabelElement.h"
#include "HTMLNames.h"
#include "HTMLOptionElement.h"
#include "HTMLSelectElement.h"
#include "InputElement.h"
#include "Node.h"
#include "NodeList.h"
#include "HTMLCollection.h"
#include "FormAssociatedElement.h"
#include "QualifiedName.h"
#include "StringUtils.h"

// TODO: This file is taken from chromium/chrome/renderer/form_manager.cc and
// customised to use WebCore types rather than WebKit API types. It would be
// nice and would ease future merge pain if the two could be combined.

using webkit_glue::FormData;
using webkit_glue::FormField;
using WebCore::Element;
using WebCore::FormAssociatedElement;
using WebCore::HTMLCollection;
using WebCore::HTMLElement;
using WebCore::HTMLFormControlElement;
using WebCore::HTMLFormElement;
using WebCore::HTMLInputElement;
using WebCore::HTMLLabelElement;
using WebCore::HTMLOptionElement;
using WebCore::HTMLSelectElement;
using WebCore::InputElement;
using WebCore::Node;
using WebCore::NodeList;

using namespace WebCore::HTMLNames;

namespace {

// Android helper function.
HTMLInputElement* HTMLFormControlElementToHTMLInputElement(const HTMLFormControlElement& element) {
    Node* node = const_cast<Node*>(static_cast<const Node*>(&element));
    InputElement* input_element = node->toInputElement();
    if (node && node->isHTMLElement())
        return static_cast<HTMLInputElement*>(input_element);

    return 0;
}

// The number of fields required by Autofill.  Ideally we could send the forms
// to Autofill no matter how many fields are in the forms; however, finding the
// label for each field is a costly operation and we can't spare the cycles if
// it's not necessary.
// Note the on ANDROID we reduce this from Chromium's 3 as it allows us to
// Autofill simple name/email forms for example. This improves the mobile
// device experience where form filling can be time consuming and frustrating.
const size_t kRequiredAutofillFields = 2;

// The maximum number of form fields we are willing to parse, due to
// computational costs. This is a very conservative upper bound.
const size_t kMaxParseableFields = 1000;

// The maximum length allowed for form data.
const size_t kMaxDataLength = 1024;

// In HTML5, all text fields except password are text input fields to
// autocomplete.
bool IsTextInput(const HTMLInputElement* element) {
    if (!element)
        return false;

    return element->isTextField() && !element->isPasswordField();
}

bool IsSelectElement(const HTMLFormControlElement& element) {
    return formControlType(element) == kSelectOne;
}

bool IsOptionElement(Element& element) {
    return element.hasTagName(optionTag);
}

bool IsAutofillableElement(const HTMLFormControlElement& element) {
    HTMLInputElement* html_input_element = HTMLFormControlElementToHTMLInputElement(element);
    return (html_input_element && IsTextInput(html_input_element)) || IsSelectElement(element);
}

// This is a helper function for the FindChildText() function (see below).
// Search depth is limited with the |depth| parameter.
string16 FindChildTextInner(Node* node, int depth) {
    string16 element_text;
    if (!node || depth <= 0)
        return element_text;

    string16 node_text = WTFStringToString16(node->nodeValue());
    TrimWhitespace(node_text, TRIM_ALL, &node_text);
    if (!node_text.empty())
        element_text = node_text;

    string16 child_text = FindChildTextInner(node->firstChild(), depth-1);
    if (!child_text.empty())
        element_text = element_text + child_text;

    string16 sibling_text = FindChildTextInner(node->nextSibling(), depth-1);
    if (!sibling_text.empty())
        element_text = element_text + sibling_text;

    return element_text;
}

// Returns the aggregated values of the decendants or siblings of |element| that
// are non-empty text nodes. This is a faster alternative to |innerText()| for
// performance critical operations. It does a full depth-first search so can be
// used when the structure is not directly known. Whitesapce is trimmed from
// text accumulated at descendant and sibling. Search is limited to within 10
// siblings and/or descendants.
string16 FindChildText(Element* element) {
    Node* child = element->firstChild();

    const int kChildSearchDepth = 10;
    return FindChildTextInner(child, kChildSearchDepth);
}

// Helper for |InferLabelForElement()| that infers a label, if possible, from
// a previous node of |element|.
string16 InferLabelFromPrevious(const HTMLFormControlElement& element) {
    string16 inferred_label;
    Node* previous = element.previousSibling();
    if (!previous)
        return string16();

    if (previous->isTextNode()) {
        inferred_label = WTFStringToString16(previous->nodeValue());
        TrimWhitespace(inferred_label, TRIM_ALL, &inferred_label);
    }

    // If we didn't find text, check for previous paragraph.
    // Eg. <p>Some Text</p><input ...>
    // Note the lack of whitespace between <p> and <input> elements.
    if (inferred_label.empty() && previous->isElementNode()) {
        Element* element = static_cast<Element*>(previous);
        if (element->hasTagName(pTag))
            inferred_label = FindChildText(element);
    }

    // If we didn't find paragraph, check for previous paragraph to this.
    // Eg. <p>Some Text</p>   <input ...>
    // Note the whitespace between <p> and <input> elements.
    if (inferred_label.empty()) {
        Node* sibling = previous->previousSibling();
        if (sibling && sibling->isElementNode()) {
            Element* element = static_cast<Element*>(sibling);
            if (element->hasTagName(pTag))
                inferred_label = FindChildText(element);
        }
    }

    // Look for text node prior to <img> tag.
    // Eg. Some Text<img/><input ...>
    if (inferred_label.empty()) {
        while (inferred_label.empty() && previous) {
            if (previous->isTextNode()) {
                inferred_label = WTFStringToString16(previous->nodeValue());
                TrimWhitespace(inferred_label, TRIM_ALL, &inferred_label);
            } else if (previous->isElementNode()) {
                Element* element = static_cast<Element*>(previous);
                if (!element->hasTagName(imgTag))
                    break;
            } else
                break;
            previous = previous->previousSibling();
        }
    }

    // Look for label node prior to <input> tag.
    // Eg. <label>Some Text</label><input ...>
    if (inferred_label.empty()) {
        while (inferred_label.empty() && previous) {
            if (previous->isTextNode()) {
                inferred_label = WTFStringToString16(previous->nodeValue());
                TrimWhitespace(inferred_label, TRIM_ALL, &inferred_label);
            } else if (previous->isElementNode()) {
                Element* element = static_cast<Element*>(previous);
                if (element->hasTagName(labelTag)) {
                    inferred_label = FindChildText(element);
                } else {
                    break;
                }
            } else {
                break;
            }

            previous = previous->previousSibling();
         }
    }

    return inferred_label;
}

// Helper for |InferLabelForElement()| that infers a label, if possible, from
// surrounding table structure.
// Eg. <tr><td>Some Text</td><td><input ...></td></tr>
// Eg. <tr><td><b>Some Text</b></td><td><b><input ...></b></td></tr>
string16 InferLabelFromTable(const HTMLFormControlElement& element) {
    string16 inferred_label;
    Node* parent = element.parentNode();
    while (parent && parent->isElementNode() && !static_cast<Element*>(parent)->hasTagName(tdTag))
        parent = parent->parentNode();

    // Check all previous siblings, skipping non-element nodes, until we find a
    // non-empty text block.
    Node* previous = parent;
    while(previous) {
        if (previous->isElementNode()) {
            Element* e = static_cast<Element*>(previous);
            if (e->hasTagName(tdTag)) {
                inferred_label = FindChildText(e);
                if (!inferred_label.empty())
                    break;
            }
        }
        previous = previous->previousSibling();
    }
    return inferred_label;
}

// Helper for |InferLabelForElement()| that infers a label, if possible, from
// a surrounding div table.
// Eg. <div>Some Text<span><input ...></span></div>
string16 InferLabelFromDivTable(const HTMLFormControlElement& element) {
    Node* parent = element.parentNode();
    while (parent && parent->isElementNode() && !static_cast<Element*>(parent)->hasTagName(divTag))
        parent = parent->parentNode();

    if (!parent || !parent->isElementNode())
        return string16();

    Element* e = static_cast<Element*>(parent);
    if (!e || !e->hasTagName(divTag))
        return string16();

    return FindChildText(e);
}

// Helper for |InferLabelForElement()| that infers a label, if possible, from
// a surrounding definition list.
// Eg. <dl><dt>Some Text</dt><dd><input ...></dd></dl>
// Eg. <dl><dt><b>Some Text</b></dt><dd><b><input ...></b></dd></dl>
string16 InferLabelFromDefinitionList(const HTMLFormControlElement& element) {
    string16 inferred_label;
    Node* parent = element.parentNode();
    while (parent && parent->isElementNode() && !static_cast<Element*>(parent)->hasTagName(ddTag))
        parent = parent->parentNode();

    if (parent && parent->isElementNode()) {
        Element* element = static_cast<Element*>(parent);
        if (element->hasTagName(ddTag)) {
            Node* previous = parent->previousSibling();

            // Skip by any intervening text nodes.
            while (previous && previous->isTextNode())
                previous = previous->previousSibling();

            if (previous && previous->isElementNode()) {
                element = static_cast<Element*>(previous);
                if (element->hasTagName(dtTag))
                    inferred_label = FindChildText(element);
            }
        }
    }
    return inferred_label;
}

// Infers corresponding label for |element| from surrounding context in the DOM.
// Contents of preceding <p> tag or preceding text element found in the form.
string16 InferLabelForElement(const HTMLFormControlElement& element) {
    string16 inferred_label = InferLabelFromPrevious(element);

    // If we didn't find a label, check for table cell case.
    if (inferred_label.empty())
        inferred_label = InferLabelFromTable(element);

    // If we didn't find a label, check for div table case.
    if (inferred_label.empty())
        inferred_label = InferLabelFromDivTable(element);

    // If we didn't find a label, check for definition list case.
    if (inferred_label.empty())
        inferred_label = InferLabelFromDefinitionList(element);

    return inferred_label;
}

void GetOptionStringsFromElement(const HTMLSelectElement& select_element, std::vector<string16>* option_strings) {
    DCHECK(option_strings);
    option_strings->clear();
    WTF::Vector<Element*> list_items = select_element.listItems();
    option_strings->reserve(list_items.size());
    for (size_t i = 0; i < list_items.size(); ++i) {
        if (IsOptionElement(*list_items[i])) {
                option_strings->push_back(WTFStringToString16(static_cast<HTMLOptionElement*>(list_items[i])->value()));
        }
    }
}

// Returns the form's |name| attribute if non-empty; otherwise the form's |id|
// attribute.
const string16 GetFormIdentifier(const HTMLFormElement& form) {
    string16 identifier = WTFStringToString16(form.name());
    if (identifier.empty())
        identifier = WTFStringToString16(form.getIdAttribute());
    return identifier;
}

}  // namespace

namespace android {

struct FormManager::FormElement {
    RefPtr<HTMLFormElement> form_element;
    std::vector<RefPtr<HTMLFormControlElement> > control_elements;
    std::vector<string16> control_values;
};

FormManager::FormManager() {
}

FormManager::~FormManager() {
    Reset();
}

// static
void FormManager::HTMLFormControlElementToFormField(HTMLFormControlElement* element, ExtractMask extract_mask, FormField* field) {
    DCHECK(field);
    DCHECK(element);

    // The label is not officially part of a HTMLFormControlElement; however, the
    // labels for all form control elements are scraped from the DOM and set in
    // WebFormElementToFormData.
    field->name = nameForAutofill(*element);
    field->form_control_type = formControlType(*element);

    if (!IsAutofillableElement(*element))
        return;

    HTMLInputElement* input_element = HTMLFormControlElementToHTMLInputElement(*element);

    if (IsTextInput(input_element)) {
        field->max_length = input_element->maxLength();
        field->is_autofilled = input_element->isAutofilled();
    } else if (extract_mask & EXTRACT_OPTIONS) {
        // Set option strings on the field is available.
        DCHECK(IsSelectElement(*element));
        HTMLSelectElement* select_element = static_cast<HTMLSelectElement*>(element);
        std::vector<string16> option_strings;
        GetOptionStringsFromElement(*select_element, &option_strings);
        field->option_strings = option_strings;
    }

    if (!(extract_mask & EXTRACT_VALUE))
        return;

    string16 value;
    if (IsTextInput(input_element)) {
        value = WTFStringToString16(input_element->value());
    } else {
        DCHECK(IsSelectElement(*element));
        HTMLSelectElement* select_element = static_cast<HTMLSelectElement*>(element);
        value = WTFStringToString16(select_element->value());

        // Convert the |select_element| value to text if requested.
        if (extract_mask & EXTRACT_OPTION_TEXT) {
            Vector<Element*> list_items = select_element->listItems();
            for (size_t i = 0; i < list_items.size(); ++i) {
                if (IsOptionElement(*list_items[i]) &&
                    WTFStringToString16(static_cast<HTMLOptionElement*>(list_items[i])->value()) == value) {
                    value = WTFStringToString16(static_cast<HTMLOptionElement*>(list_items[i])->text());
                    break;
                }
            }
        }
    }

    // TODO: This is a temporary stop-gap measure designed to prevent
    // a malicious site from DOS'ing the browser with extremely large profile
    // data.  The correct solution is to parse this data asynchronously.
    // See http://crbug.com/49332.
    if (value.size() > kMaxDataLength)
        value = value.substr(0, kMaxDataLength);

    field->value = value;
}

// static
string16 FormManager::LabelForElement(const HTMLFormControlElement& element) {
    // Don't scrape labels for elements we can't possible autofill anyway.
    if (!IsAutofillableElement(element))
        return string16();

    RefPtr<NodeList> labels = element.document()->getElementsByTagName("label");
    for (unsigned i = 0; i < labels->length(); ++i) {
        Node* e = labels->item(i);
        DCHECK(e->hasTagName(labelTag));
        HTMLLabelElement* label = static_cast<HTMLLabelElement*>(e);
        if (label->control() == &element)
            return FindChildText(label);
    }

    // Infer the label from context if not found in label element.
    return InferLabelForElement(element);
}

// static
bool FormManager::HTMLFormElementToFormData(HTMLFormElement* element, RequirementsMask requirements, ExtractMask extract_mask, FormData* form) {
    DCHECK(form);

    Frame* frame = element->document()->frame();
    if (!frame)
        return false;

    if (requirements & REQUIRE_AUTOCOMPLETE && !element->autoComplete())
        return false;

    form->name = GetFormIdentifier(*element);
    form->method = WTFStringToString16(element->method());
    form->origin = GURL(WTFStringToString16(frame->loader()->documentLoader()->url().string()));
    form->action = GURL(WTFStringToString16(frame->document()->completeURL(element->action())));
    form->user_submitted = element->wasUserSubmitted();

    // If the completed URL is not valid, just use the action we get from
    // WebKit.
    if (!form->action.is_valid())
        form->action = GURL(WTFStringToString16(element->action()));

    // A map from a FormField's name to the FormField itself.
    std::map<string16, FormField*> name_map;

    // The extracted FormFields.  We use pointers so we can store them in
    // |name_map|.
    ScopedVector<FormField> form_fields;

    WTF::Vector<WebCore::FormAssociatedElement*> control_elements = element->associatedElements();

    // A vector of bools that indicate whether each field in the form meets the
    // requirements and thus will be in the resulting |form|.
    std::vector<bool> fields_extracted(control_elements.size(), false);

    for (size_t i = 0; i < control_elements.size(); ++i) {
        if (!control_elements[i]->isFormControlElement())
            continue;

        HTMLFormControlElement* control_element = static_cast<HTMLFormControlElement*>(control_elements[i]);

        if(!IsAutofillableElement(*control_element))
            continue;

        HTMLInputElement* input_element = HTMLFormControlElementToHTMLInputElement(*control_element);
        if (requirements & REQUIRE_AUTOCOMPLETE && IsTextInput(input_element) &&
                !input_element->autoComplete())
                continue;

        if (requirements & REQUIRE_ENABLED && !control_element->isEnabledFormControl())
            continue;

        // Create a new FormField, fill it out and map it to the field's name.
        FormField* field = new FormField;
        HTMLFormControlElementToFormField(control_element, extract_mask, field);
        form_fields.push_back(field);
        // TODO: A label element is mapped to a form control element's id.
        // field->name() will contain the id only if the name does not exist.  Add
        // an id() method to HTMLFormControlElement and use that here.
        name_map[field->name] = field;
        fields_extracted[i] = true;
    }

    // Don't extract field labels if we have no fields.
    if (form_fields.empty())
        return false;

    // Loop through the label elements inside the form element.  For each label
    // element, get the corresponding form control element, use the form control
    // element's name as a key into the <name, FormField> map to find the
    // previously created FormField and set the FormField's label to the
    // label.firstChild().nodeValue() of the label element.
    RefPtr<WebCore::NodeList> labels = element->getElementsByTagName("label");
    for (unsigned i = 0; i < labels->length(); ++i) {
        HTMLLabelElement* label = static_cast<WebCore::HTMLLabelElement*>(labels->item(i));
        HTMLFormControlElement* field_element = label->control();
        if (!field_element || field_element->type() == "hidden")
            continue;

        std::map<string16, FormField*>::iterator iter =
            name_map.find(nameForAutofill(*field_element));
        // Concatenate labels because some sites might have multiple label
        // candidates.
        if (iter != name_map.end())
            iter->second->label += FindChildText(label);
    }

    // Loop through the form control elements, extracting the label text from the
    // DOM.  We use the |fields_extracted| vector to make sure we assign the
    // extracted label to the correct field, as it's possible |form_fields| will
    // not contain all of the elements in |control_elements|.
    for (size_t i = 0, field_idx = 0; i < control_elements.size() && field_idx < form_fields.size(); ++i) {
        // This field didn't meet the requirements, so don't try to find a label for
        // it.
        if (!fields_extracted[i])
            continue;

        if (!control_elements[i]->isFormControlElement())
            continue;

        const HTMLFormControlElement* control_element = static_cast<HTMLFormControlElement*>(control_elements[i]);
        if (form_fields[field_idx]->label.empty())
            form_fields[field_idx]->label = InferLabelForElement(*control_element);

        ++field_idx;

    }
    // Copy the created FormFields into the resulting FormData object.
    for (ScopedVector<FormField>::const_iterator iter = form_fields.begin(); iter != form_fields.end(); ++iter)
        form->fields.push_back(**iter);

    return true;
}

void FormManager::ExtractForms(Frame* frame) {

    ResetFrame(frame);

    WTF::RefPtr<HTMLCollection> web_forms = frame->document()->forms();

    for (size_t i = 0; i < web_forms->length(); ++i) {
        // Owned by |form_elements|.
        FormElement* form_element = new FormElement;
        HTMLFormElement* html_form_element = static_cast<HTMLFormElement*>(web_forms->item(i));
        form_element->form_element = html_form_element;

        WTF::Vector<FormAssociatedElement*> control_elements = html_form_element->associatedElements();
        for (size_t j = 0; j < control_elements.size(); ++j) {
            if (!control_elements[j]->isFormControlElement())
                continue;

            HTMLFormControlElement* element = static_cast<HTMLFormControlElement*>(control_elements[j]);

            if (!IsAutofillableElement(*element))
                continue;

            form_element->control_elements.push_back(element);

            // Save original values of <select> elements so we can restore them
            // when |ClearFormWithNode()| is invoked.
            if (IsSelectElement(*element)) {
                HTMLSelectElement* select_element = static_cast<HTMLSelectElement*>(element);
                form_element->control_values.push_back(WTFStringToString16(select_element->value()));
            } else
                form_element->control_values.push_back(string16());
        }

        form_elements_.push_back(form_element);
    }
}

void FormManager::GetFormsInFrame(const Frame* frame, RequirementsMask requirements, std::vector<FormData>* forms) {
    DCHECK(frame);
    DCHECK(forms);

    size_t num_fields_seen = 0;
    for (FormElementList::const_iterator form_iter = form_elements_.begin(); form_iter != form_elements_.end(); ++form_iter) {
        FormElement* form_element = *form_iter;

        if (form_element->form_element->document()->frame() != frame)
            continue;

        // To avoid overly expensive computation, we impose both a minimum and a
        // maximum number of allowable fields.
        if (form_element->control_elements.size() < kRequiredAutofillFields ||
            form_element->control_elements.size() > kMaxParseableFields)
            continue;

        if (requirements & REQUIRE_AUTOCOMPLETE && !form_element->form_element->autoComplete())
            continue;

        FormData form;
        HTMLFormElementToFormData(form_element->form_element.get(), requirements, EXTRACT_VALUE, &form);

        num_fields_seen += form.fields.size();
        if (num_fields_seen > kMaxParseableFields)
            break;

        if (form.fields.size() >= kRequiredAutofillFields)
            forms->push_back(form);
    }
}

bool FormManager::FindFormWithFormControlElement(HTMLFormControlElement* element, RequirementsMask requirements, FormData* form) {
    DCHECK(form);

    const Frame* frame = element->document()->frame();
    if (!frame)
        return false;

    for (FormElementList::const_iterator iter = form_elements_.begin(); iter != form_elements_.end(); ++iter) {
        const FormElement* form_element = *iter;

        if (form_element->form_element->document()->frame() != frame)
            continue;

        for (std::vector<RefPtr<HTMLFormControlElement> >::const_iterator iter = form_element->control_elements.begin(); iter != form_element->control_elements.end(); ++iter) {
            HTMLFormControlElement* candidate = iter->get();
            if (nameForAutofill(*candidate) == nameForAutofill(*element)) {
                ExtractMask extract_mask = static_cast<ExtractMask>(EXTRACT_VALUE | EXTRACT_OPTIONS);
                return HTMLFormElementToFormData(form_element->form_element.get(), requirements, extract_mask, form);
            }
        }
    }
    return false;
}

bool FormManager::FillForm(const FormData& form, Node* node) {
    FormElement* form_element = NULL;
    if (!FindCachedFormElement(form, &form_element))
        return false;

    RequirementsMask requirements = static_cast<RequirementsMask>(REQUIRE_AUTOCOMPLETE | REQUIRE_ENABLED | REQUIRE_EMPTY);
    ForEachMatchingFormField(form_element, node, requirements, form, NewCallback(this, &FormManager::FillFormField));

    return true;
}

bool FormManager::PreviewForm(const FormData& form, Node* node) {
    FormElement* form_element = NULL;
    if (!FindCachedFormElement(form, &form_element))
        return false;

    RequirementsMask requirements = static_cast<RequirementsMask>(REQUIRE_AUTOCOMPLETE | REQUIRE_ENABLED | REQUIRE_EMPTY);
    ForEachMatchingFormField(form_element, node, requirements, form, NewCallback(this, &FormManager::PreviewFormField));

    return true;
}

bool FormManager::ClearFormWithNode(Node* node) {
    FormElement* form_element = NULL;
    if (!FindCachedFormElementWithNode(node, &form_element))
        return false;

    for (size_t i = 0; i < form_element->control_elements.size(); ++i) {
        HTMLFormControlElement* element = form_element->control_elements[i].get();
        HTMLInputElement* input_element = HTMLFormControlElementToHTMLInputElement(*element);
        if (IsTextInput(input_element)) {

            // We don't modify the value of disabled fields.
            if (!input_element->isEnabledFormControl())
                continue;

            input_element->setValue("");
            input_element->setAutofilled(false);
             // Clearing the value in the focused node (above) can cause selection
             // to be lost. We force selection range to restore the text cursor.
             if (node == input_element) {
                 int length = input_element->value().length();
                 input_element->setSelectionRange(length, length);
             }
        } else {
            DCHECK(IsSelectElement(*element));
            HTMLSelectElement* select_element = static_cast<HTMLSelectElement*>(element);
            if (WTFStringToString16(select_element->value()) != form_element->control_values[i]) {
                select_element->setValue(form_element->control_values[i].c_str());
                select_element->dispatchFormControlChangeEvent();
            }
        }
    }

    return true;
}

bool FormManager::ClearPreviewedFormWithNode(Node* node, bool was_autofilled) {
    FormElement* form_element = NULL;
    if (!FindCachedFormElementWithNode(node, &form_element))
        return false;

    for (size_t i = 0; i < form_element->control_elements.size(); ++i) {
        HTMLFormControlElement* element = form_element->control_elements[i].get();
        HTMLInputElement* input_element = HTMLFormControlElementToHTMLInputElement(*element);

        // Only input elements can be previewed.
        if (!IsTextInput(input_element))
            continue;

        // If the input element has not been auto-filled, FormManager has not
        // previewed this field, so we have nothing to reset.
        if (!input_element->isAutofilled())
            continue;

        // There might be unrelated elements in this form which have already been
        // auto-filled. For example, the user might have already filled the address
        // part of a form and now be dealing with the credit card section. We only
        // want to reset the auto-filled status for fields that were previewed.
        if (input_element->suggestedValue().isEmpty())
            continue;

        // Clear the suggested value. For the initiating node, also restore the
        // original value.
        input_element->setSuggestedValue("");
        bool is_initiating_node = (node == input_element);
        if (is_initiating_node) {
            input_element->setAutofilled(was_autofilled);
        } else {
            input_element->setAutofilled(false);
        }

        // Clearing the suggested value in the focused node (above) can cause
        // selection to be lost. We force selection range to restore the text
        // cursor.
        if (is_initiating_node) {
            int length = input_element->value().length();
            input_element->setSelectionRange(length, length);
        }
    }

    return true;
}

void FormManager::Reset() {
    form_elements_.reset();
}

void FormManager::ResetFrame(const Frame* frame) {
    FormElementList::iterator iter = form_elements_.begin();
    while (iter != form_elements_.end()) {
        if ((*iter)->form_element->document()->frame() == frame)
            iter = form_elements_.erase(iter);
        else
            ++iter;
    }
}

bool FormManager::FormWithNodeIsAutofilled(Node* node) {
    FormElement* form_element = NULL;
    if (!FindCachedFormElementWithNode(node, &form_element))
        return false;

    for (size_t i = 0; i < form_element->control_elements.size(); ++i) {
        HTMLFormControlElement* element = form_element->control_elements[i].get();
        HTMLInputElement* input_element = HTMLFormControlElementToHTMLInputElement(*element);
        if (!IsTextInput(input_element))
            continue;

        if (input_element->isAutofilled())
            return true;
    }

    return false;
}

bool FormManager::FindCachedFormElementWithNode(Node* node, FormElement** form_element) {
    for (FormElementList::const_iterator form_iter = form_elements_.begin(); form_iter != form_elements_.end(); ++form_iter) {
        for (std::vector<RefPtr<HTMLFormControlElement> >::const_iterator iter = (*form_iter)->control_elements.begin(); iter != (*form_iter)->control_elements.end(); ++iter) {
            if (iter->get() == node) {
                *form_element = *form_iter;
                return true;
            }
        }
    }

    return false;
}

bool FormManager::FindCachedFormElement(const FormData& form, FormElement** form_element) {
    for (FormElementList::iterator form_iter = form_elements_.begin(); form_iter != form_elements_.end(); ++form_iter) {
        // TODO: matching on form name here which is not guaranteed to
        // be unique for the page, nor is it guaranteed to be non-empty.  Need to
        // find a way to uniquely identify the form cross-process.  For now we'll
        // check form name and form action for identity.
        // http://crbug.com/37990 test file sample8.html.
        // Also note that WebString() == WebString(string16()) does not evaluate to
        // |true| -- WebKit distinguisges between a "null" string (lhs) and an
        // "empty" string (rhs). We don't want that distinction, so forcing to
        // string16.
        string16 element_name = GetFormIdentifier(*(*form_iter)->form_element);
        GURL action(WTFStringToString16((*form_iter)->form_element->document()->completeURL((*form_iter)->form_element->action()).string()));
        if (element_name == form.name && action == form.action) {
            *form_element = *form_iter;
            return true;
        }
    }

    return false;
}


void FormManager::ForEachMatchingFormField(FormElement* form, Node* node, RequirementsMask requirements, const FormData& data, Callback* callback) {
    // It's possible that the site has injected fields into the form after the
    // page has loaded, so we can't assert that the size of the cached control
    // elements is equal to the size of the fields in |form|.  Fortunately, the
    // one case in the wild where this happens, paypal.com signup form, the fields
    // are appended to the end of the form and are not visible.
    for (size_t i = 0, j = 0; i < form->control_elements.size() && j < data.fields.size(); ++i) {
        HTMLFormControlElement* element = form->control_elements[i].get();
        string16 element_name = nameForAutofill(*element);

        // Search forward in the |form| for a corresponding field.
        size_t k = j;
        while (k < data.fields.size() && element_name != data.fields[k].name)
               k++;

        if (k >= data.fields.size())
            continue;

        DCHECK_EQ(data.fields[k].name, element_name);

        bool is_initiating_node = false;

        HTMLInputElement* input_element = HTMLFormControlElementToHTMLInputElement(*element);
        if (IsTextInput(input_element)) {
            // TODO: WebKit currently doesn't handle the autocomplete
            // attribute for select control elements, but it probably should.
            if (!input_element->autoComplete())
                continue;

            is_initiating_node = (input_element == node);

            // Only autofill empty fields and the firls that initiated the filling,
            // i.e. the field the user is currently editing and interacting with.
            if (!is_initiating_node && !input_element->value().isEmpty())
               continue;
        }

        if (!element->isEnabledFormControl() || element->isReadOnlyFormControl() || !element->isFocusable())
            continue;

        callback->Run(element, &data.fields[k], is_initiating_node);

        // We found a matching form field so move on to the next.
        ++j;
    }

    delete callback;
}

void FormManager::FillFormField(HTMLFormControlElement* field, const FormField* data, bool is_initiating_node) {
    // Nothing to fill.
    if (data->value.empty())
        return;

    HTMLInputElement* input_element = HTMLFormControlElementToHTMLInputElement(*field);

    if (IsTextInput(input_element)) {
        // If the maxlength attribute contains a negative value, maxLength()
        // returns the default maxlength value.
        input_element->setValue(data->value.substr(0, input_element->maxLength()).c_str(), true);
        input_element->setAutofilled(true);
        if (is_initiating_node) {
            int length = input_element->value().length();
            input_element->setSelectionRange(length, length);
        }
    } else {
        DCHECK(IsSelectElement(*field));
        HTMLSelectElement* select_element = static_cast<HTMLSelectElement*>(field);
        if (WTFStringToString16(select_element->value()) != data->value) {
            select_element->setValue(data->value.c_str());
            select_element->dispatchFormControlChangeEvent();
        }
    }
}

void FormManager::PreviewFormField(HTMLFormControlElement* field, const FormField* data, bool is_initiating_node) {
    // Nothing to preview.
    if (data->value.empty())
        return;

    // Only preview input fields.
    HTMLInputElement* input_element = HTMLFormControlElementToHTMLInputElement(*field);
    if (!IsTextInput(input_element))
        return;

    // If the maxlength attribute contains a negative value, maxLength()
    // returns the default maxlength value.
    input_element->setSuggestedValue(data->value.substr(0, input_element->maxLength()).c_str());
    input_element->setAutofilled(true);
    if (is_initiating_node) {
        // Select the part of the text that the user didn't type.
        input_element->setSelectionRange(input_element->value().length(), input_element->suggestedValue().length());
    }
}

}
