/*
 * Copyright (C) 2006-2017 Apple Inc. All rights reserved.
 * Copyright (C) 2010, 2011, 2012 Google Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "config.h"
#include "FormController.h"

#include "HTMLFormElement.h"
#include "HTMLInputElement.h"
#include "ScriptDisallowedScope.h"
#include <wtf/NeverDestroyed.h>
#include <wtf/text/StringBuilder.h>
#include <wtf/text/StringConcatenateNumbers.h>

namespace WebCore {

using namespace HTMLNames;

static inline HTMLFormElement* ownerFormForState(const HTMLFormControlElementWithState& control)
{
    // Assume controls with form attribute have no owners because we restore
    // state during parsing and form owners of such controls might be
    // indeterminate.
    return control.hasAttributeWithoutSynchronization(formAttr) ? 0 : control.form();
}

// ----------------------------------------------------------------------------

// Serilized form of FormControlState:
//  (',' means strings around it are separated in stateVector.)
//
// SerializedControlState ::= SkipState | RestoreState
// SkipState ::= '0'
// RestoreState ::= UnsignedNumber, ControlValue+
// UnsignedNumber ::= [0-9]+
// ControlValue ::= arbitrary string
//
// RestoreState has a sequence of ControlValues. The length of the
// sequence is represented by UnsignedNumber.

static inline void serializeFormControlStateTo(const FormControlState& formControlState, Vector<String>& stateVector)
{
    stateVector.append(String::number(formControlState.size()));
    for (auto& value : formControlState)
        stateVector.append(value.isNull() ? emptyString() : value);
}

static inline Optional<FormControlState> deserializeFormControlState(const Vector<String>& stateVector, size_t& index)
{
    if (index >= stateVector.size())
        return WTF::nullopt;
    size_t size = stateVector[index++].toUInt();
    if (index + size > stateVector.size())
        return WTF::nullopt;
    Vector<String> subvector;
    subvector.reserveInitialCapacity(size);
    for (size_t i = 0; i < size; ++i)
        subvector.uncheckedAppend(stateVector[index++]);
    return subvector;
}

// ----------------------------------------------------------------------------

class FormElementKey {
public:
    explicit FormElementKey(AtomStringImpl* = nullptr, AtomStringImpl* = nullptr);
    ~FormElementKey();
    FormElementKey(const FormElementKey&);
    FormElementKey& operator=(const FormElementKey&);

    AtomStringImpl* name() const { return m_name; }
    AtomStringImpl* type() const { return m_type; }

    // Hash table deleted values, which are only constructed and never copied or destroyed.
    FormElementKey(WTF::HashTableDeletedValueType) : m_name(hashTableDeletedValue()) { }
    bool isHashTableDeletedValue() const { return m_name == hashTableDeletedValue(); }

private:
    void ref() const;
    void deref() const;

    static AtomStringImpl* hashTableDeletedValue() { return reinterpret_cast<AtomStringImpl*>(-1); }

    AtomStringImpl* m_name;
    AtomStringImpl* m_type;
};

FormElementKey::FormElementKey(AtomStringImpl* name, AtomStringImpl* type)
    : m_name(name)
    , m_type(type)
{
    ref();
}

FormElementKey::~FormElementKey()
{
    deref();
}

FormElementKey::FormElementKey(const FormElementKey& other)
    : m_name(other.name())
    , m_type(other.type())
{
    ref();
}

FormElementKey& FormElementKey::operator=(const FormElementKey& other)
{
    other.ref();
    deref();
    m_name = other.name();
    m_type = other.type();
    return *this;
}

void FormElementKey::ref() const
{
    if (name())
        name()->ref();
    if (type())
        type()->ref();
}

void FormElementKey::deref() const
{
    if (name())
        name()->deref();
    if (type())
        type()->deref();
}

inline bool operator==(const FormElementKey& a, const FormElementKey& b)
{
    return a.name() == b.name() && a.type() == b.type();
}

struct FormElementKeyHash {
    static unsigned hash(const FormElementKey&);
    static bool equal(const FormElementKey& a, const FormElementKey& b) { return a == b; }
    static const bool safeToCompareToEmptyOrDeleted = true;
};

unsigned FormElementKeyHash::hash(const FormElementKey& key)
{
    return StringHasher::hashMemory<sizeof(FormElementKey)>(&key);
}

struct FormElementKeyHashTraits : WTF::GenericHashTraits<FormElementKey> {
    static void constructDeletedValue(FormElementKey& slot) { new (NotNull, &slot) FormElementKey(WTF::HashTableDeletedValue); }
    static bool isDeletedValue(const FormElementKey& value) { return value.isHashTableDeletedValue(); }
};

// ----------------------------------------------------------------------------

class SavedFormState {
    WTF_MAKE_NONCOPYABLE(SavedFormState);
    WTF_MAKE_FAST_ALLOCATED;

public:
    SavedFormState() = default;
    static std::unique_ptr<SavedFormState> deserialize(const Vector<String>&, size_t& index);
    void serializeTo(Vector<String>&) const;
    bool isEmpty() const { return m_stateForNewFormElements.isEmpty(); }
    void appendControlState(const AtomString& name, const AtomString& type, const FormControlState&);
    FormControlState takeControlState(const AtomString& name, const AtomString& type);

    Vector<String> referencedFilePaths() const;

private:
    HashMap<FormElementKey, Deque<FormControlState>, FormElementKeyHash, FormElementKeyHashTraits> m_stateForNewFormElements;
    size_t m_controlStateCount { 0 };
};

static bool isNotFormControlTypeCharacter(UChar ch)
{
    return !(ch == '-' || isASCIILower(ch));
}

std::unique_ptr<SavedFormState> SavedFormState::deserialize(const Vector<String>& stateVector, size_t& index)
{
    if (index >= stateVector.size())
        return nullptr;
    // FIXME: We need String::toSizeT().
    size_t itemCount = stateVector[index++].toUInt();
    if (!itemCount)
        return nullptr;
    auto savedFormState = makeUnique<SavedFormState>();
    while (itemCount--) {
        if (index + 1 >= stateVector.size())
            return nullptr;
        String name = stateVector[index++];
        String type = stateVector[index++];
        auto state = deserializeFormControlState(stateVector, index);
        if (type.isEmpty() || type.find(isNotFormControlTypeCharacter) != notFound || !state)
            return nullptr;
        savedFormState->appendControlState(name, type, state.value());
    }
    return savedFormState;
}

void SavedFormState::serializeTo(Vector<String>& stateVector) const
{
    stateVector.append(String::number(m_controlStateCount));
    for (auto& element : m_stateForNewFormElements) {
        const FormElementKey& key = element.key;
        for (auto& controlState : element.value) {
            stateVector.append(key.name());
            stateVector.append(key.type());
            serializeFormControlStateTo(controlState, stateVector);
        }
    }
}

void SavedFormState::appendControlState(const AtomString& name, const AtomString& type, const FormControlState& state)
{
    m_stateForNewFormElements.add(FormElementKey { name.impl(), type.impl() }, Deque<FormControlState> { }).iterator->value.append(state);
    ++m_controlStateCount;
}

FormControlState SavedFormState::takeControlState(const AtomString& name, const AtomString& type)
{
    auto iterator = m_stateForNewFormElements.find(FormElementKey { name.impl(), type.impl() });
    if (iterator == m_stateForNewFormElements.end())
        return { };

    auto state = iterator->value.takeFirst();
    --m_controlStateCount;
    if (iterator->value.isEmpty())
        m_stateForNewFormElements.remove(iterator);
    return state;
}

Vector<String> SavedFormState::referencedFilePaths() const
{
    Vector<String> toReturn;
    for (auto& element : m_stateForNewFormElements) {
        if (!equal(element.key.type(), "file", 4))
            continue;
        for (auto& state : element.value) {
            for (auto& file : HTMLInputElement::filesFromFileInputFormControlState(state))
                toReturn.append(file.path);
        }
    }
    return toReturn;
}

// ----------------------------------------------------------------------------

class FormKeyGenerator {
    WTF_MAKE_NONCOPYABLE(FormKeyGenerator);
    WTF_MAKE_FAST_ALLOCATED;

public:
    FormKeyGenerator() = default;
    AtomString formKey(const HTMLFormControlElementWithState&);
    void willDeleteForm(HTMLFormElement*);

private:
    typedef HashMap<HTMLFormElement*, AtomString> FormToKeyMap;
    typedef HashMap<String, unsigned> FormSignatureToNextIndexMap;
    FormToKeyMap m_formToKeyMap;
    FormSignatureToNextIndexMap m_formSignatureToNextIndexMap;
};

static inline void recordFormStructure(const HTMLFormElement& form, StringBuilder& builder)
{
    ScriptDisallowedScope::InMainThread scriptDisallowedScope;
    // 2 is enough to distinguish forms in webkit.org/b/91209#c0
    const size_t namedControlsToBeRecorded = 2;
    auto& controls = form.unsafeAssociatedElements();
    builder.appendLiteral(" [");
    for (size_t i = 0, namedControls = 0; i < controls.size() && namedControls < namedControlsToBeRecorded; ++i) {
        auto* formAssociatedElement = controls[i]->asFormAssociatedElement();
        if (!formAssociatedElement->isFormControlElementWithState())
            continue;
        RefPtr<HTMLFormControlElementWithState> control = static_cast<HTMLFormControlElementWithState*>(formAssociatedElement);
        if (!ownerFormForState(*control))
            continue;
        AtomString name = control->name();
        if (name.isEmpty())
            continue;
        namedControls++;
        builder.append(name);
        builder.append(' ');
    }
    builder.append(']');
}

static inline String formSignature(const HTMLFormElement& form)
{
    URL actionURL = form.getURLAttribute(actionAttr);
    // Remove the query part because it might contain volatile parameters such
    // as a session key.
    actionURL.setQuery(String());
    StringBuilder builder;
    if (!actionURL.isEmpty())
        builder.append(actionURL.string());

    recordFormStructure(form, builder);
    return builder.toString();
}

AtomString FormKeyGenerator::formKey(const HTMLFormControlElementWithState& control)
{
    auto form = makeRefPtr(ownerFormForState(control));
    if (!form) {
        static NeverDestroyed<AtomString> formKeyForNoOwner("No owner", AtomString::ConstructFromLiteral);
        return formKeyForNoOwner;
    }

    return m_formToKeyMap.ensure(form.get(), [this, &form] {
        auto signature = formSignature(*form);
        auto nextIndex = m_formSignatureToNextIndexMap.add(signature, 0).iterator->value++;
        // FIXME: Would be nice to have makeAtomString to use to optimize the case where the string already exists.
        return makeString(signature, " #", nextIndex);
    }).iterator->value;
}

void FormKeyGenerator::willDeleteForm(HTMLFormElement* form)
{
    ASSERT(form);
    m_formToKeyMap.remove(form);
}

// ----------------------------------------------------------------------------

FormController::FormController() = default;

FormController::~FormController() = default;

unsigned FormController::formElementsCharacterCount() const
{
    unsigned count = 0;
    for (auto& element : m_formElementsWithState) {
        if (element->isTextField())
            count += element->saveFormControlState()[0].length();
    }
    return count;
}

static String formStateSignature()
{
    // In the legacy version of serialized state, the first item was a name
    // attribute value of a form control. The following string literal should
    // contain some characters which are rarely used for name attribute values.
    static NeverDestroyed<String> signature(MAKE_STATIC_STRING_IMPL("\n\r?% WebKit serialized form state version 8 \n\r=&"));
    return signature;
}

std::unique_ptr<FormController::SavedFormStateMap> FormController::createSavedFormStateMap(const FormElementListHashSet& controlList)
{
    FormKeyGenerator keyGenerator;
    auto stateMap = makeUnique<SavedFormStateMap>();
    for (auto& control : controlList) {
        if (!control->shouldSaveAndRestoreFormControlState())
            continue;
        auto& formState = stateMap->add(keyGenerator.formKey(*control).impl(), nullptr).iterator->value;
        if (!formState)
            formState = makeUnique<SavedFormState>();
        formState->appendControlState(control->name(), control->type(), control->saveFormControlState());
    }
    return stateMap;
}

Vector<String> FormController::formElementsState() const
{
    std::unique_ptr<SavedFormStateMap> stateMap = createSavedFormStateMap(m_formElementsWithState);
    Vector<String> stateVector;
    stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 4);
    stateVector.append(formStateSignature());
    for (auto& state : *stateMap) {
        stateVector.append(state.key.get());
        state.value->serializeTo(stateVector);
    }
    bool hasOnlySignature = stateVector.size() == 1;
    if (hasOnlySignature)
        stateVector.clear();
    return stateVector;
}

void FormController::setStateForNewFormElements(const Vector<String>& stateVector)
{
    formStatesFromStateVector(stateVector, m_savedFormStateMap);
}

FormControlState FormController::takeStateForFormElement(const HTMLFormControlElementWithState& control)
{
    if (m_savedFormStateMap.isEmpty())
        return FormControlState();
    if (!m_formKeyGenerator)
        m_formKeyGenerator = makeUnique<FormKeyGenerator>();
    SavedFormStateMap::iterator it = m_savedFormStateMap.find(m_formKeyGenerator->formKey(control).impl());
    if (it == m_savedFormStateMap.end())
        return FormControlState();
    FormControlState state = it->value->takeControlState(control.name(), control.type());
    if (it->value->isEmpty())
        m_savedFormStateMap.remove(it);
    return state;
}

void FormController::formStatesFromStateVector(const Vector<String>& stateVector, SavedFormStateMap& map)
{
    map.clear();

    size_t i = 0;
    if (stateVector.size() < 1 || stateVector[i++] != formStateSignature())
        return;

    while (i + 1 < stateVector.size()) {
        AtomString formKey = stateVector[i++];
        auto state = SavedFormState::deserialize(stateVector, i);
        if (!state) {
            i = 0;
            break;
        }
        map.add(formKey.impl(), WTFMove(state));
    }
    if (i != stateVector.size())
        map.clear();
}

void FormController::willDeleteForm(HTMLFormElement& form)
{
    if (m_formKeyGenerator)
        m_formKeyGenerator->willDeleteForm(&form);
}

void FormController::restoreControlStateFor(HTMLFormControlElementWithState& control)
{
    // We don't save state of a control with shouldSaveAndRestoreFormControlState()
    // == false. But we need to skip restoring process too because a control in
    // another form might have the same pair of name and type and saved its state.
    if (!control.shouldSaveAndRestoreFormControlState())
        return;
    if (ownerFormForState(control))
        return;
    auto state = takeStateForFormElement(control);
    if (!state.isEmpty())
        control.restoreFormControlState(state);
}

void FormController::restoreControlStateIn(HTMLFormElement& form)
{
    for (auto& element : form.copyAssociatedElementsVector()) {
        if (!is<HTMLFormControlElementWithState>(element.get()))
            continue;
        auto& control = downcast<HTMLFormControlElementWithState>(element.get());
        if (!control.shouldSaveAndRestoreFormControlState())
            continue;
        if (ownerFormForState(control) != &form)
            continue;
        auto state = takeStateForFormElement(control);
        if (!state.isEmpty())
            control.restoreFormControlState(state);
    }
}

bool FormController::hasFormStateToRestore() const
{
    return !m_savedFormStateMap.isEmpty();
}

Vector<String> FormController::referencedFilePaths(const Vector<String>& stateVector)
{
    Vector<String> paths;
    SavedFormStateMap map;
    formStatesFromStateVector(stateVector, map);
    for (auto& state : map.values())
        paths.appendVector(state->referencedFilePaths());
    return paths;
}

void FormController::registerFormElementWithState(HTMLFormControlElementWithState& control)
{
    ASSERT(!m_formElementsWithState.contains(&control));
    m_formElementsWithState.add(&control);
}

void FormController::unregisterFormElementWithState(HTMLFormControlElementWithState& control)
{
    ASSERT(m_formElementsWithState.contains(&control));
    m_formElementsWithState.remove(&control);
}

} // namespace WebCore
