| Index: Source/core/html/FormController.cpp
|
| diff --git a/Source/core/html/FormController.cpp b/Source/core/html/FormController.cpp
|
| deleted file mode 100644
|
| index 92b574732204d39e51a13db32a9356f5c757208e..0000000000000000000000000000000000000000
|
| --- a/Source/core/html/FormController.cpp
|
| +++ /dev/null
|
| @@ -1,528 +0,0 @@
|
| -/*
|
| - * Copyright (C) 2006, 2008, 2009, 2010 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 "core/html/FormController.h"
|
| -
|
| -#include "core/html/HTMLFormControlElementWithState.h"
|
| -#include "core/html/HTMLFormElement.h"
|
| -#include "core/html/HTMLInputElement.h"
|
| -#include "core/platform/FileChooser.h"
|
| -#include "wtf/Deque.h"
|
| -#include "wtf/HashTableDeletedValueType.h"
|
| -#include "wtf/text/StringBuilder.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.fastHasAttribute(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.
|
| -
|
| -void FormControlState::serializeTo(Vector<String>& stateVector) const
|
| -{
|
| - ASSERT(!isFailure());
|
| - stateVector.append(String::number(m_values.size()));
|
| - for (size_t i = 0; i < m_values.size(); ++i)
|
| - stateVector.append(m_values[i].isNull() ? emptyString() : m_values[i]);
|
| -}
|
| -
|
| -FormControlState FormControlState::deserialize(const Vector<String>& stateVector, size_t& index)
|
| -{
|
| - if (index >= stateVector.size())
|
| - return FormControlState(TypeFailure);
|
| - size_t valueSize = stateVector[index++].toUInt();
|
| - if (!valueSize)
|
| - return FormControlState();
|
| - if (index + valueSize > stateVector.size())
|
| - return FormControlState(TypeFailure);
|
| - FormControlState state;
|
| - state.m_values.reserveCapacity(valueSize);
|
| - for (size_t i = 0; i < valueSize; ++i)
|
| - state.append(stateVector[index++]);
|
| - return state;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -class FormElementKey {
|
| -public:
|
| - FormElementKey(StringImpl* = 0, StringImpl* = 0);
|
| - ~FormElementKey();
|
| - FormElementKey(const FormElementKey&);
|
| - FormElementKey& operator=(const FormElementKey&);
|
| -
|
| - StringImpl* name() const { return m_name; }
|
| - StringImpl* 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 StringImpl* hashTableDeletedValue() { return reinterpret_cast<StringImpl*>(-1); }
|
| -
|
| - StringImpl* m_name;
|
| - StringImpl* m_type;
|
| -};
|
| -
|
| -FormElementKey::FormElementKey(StringImpl* name, StringImpl* 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:
|
| - static PassOwnPtr<SavedFormState> create();
|
| - static PassOwnPtr<SavedFormState> deserialize(const Vector<String>&, size_t& index);
|
| - void serializeTo(Vector<String>&) const;
|
| - bool isEmpty() const { return m_stateForNewFormElements.isEmpty(); }
|
| - void appendControlState(const AtomicString& name, const AtomicString& type, const FormControlState&);
|
| - FormControlState takeControlState(const AtomicString& name, const AtomicString& type);
|
| -
|
| - Vector<String> getReferencedFilePaths() const;
|
| -
|
| -private:
|
| - SavedFormState() : m_controlStateCount(0) { }
|
| -
|
| - typedef HashMap<FormElementKey, Deque<FormControlState>, FormElementKeyHash, FormElementKeyHashTraits> FormElementStateMap;
|
| - FormElementStateMap m_stateForNewFormElements;
|
| - size_t m_controlStateCount;
|
| -};
|
| -
|
| -PassOwnPtr<SavedFormState> SavedFormState::create()
|
| -{
|
| - return adoptPtr(new SavedFormState);
|
| -}
|
| -
|
| -static bool isNotFormControlTypeCharacter(UChar ch)
|
| -{
|
| - return ch != '-' && (ch > 'z' || ch < 'a');
|
| -}
|
| -
|
| -PassOwnPtr<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;
|
| - OwnPtr<SavedFormState> savedFormState = adoptPtr(new SavedFormState);
|
| - while (itemCount--) {
|
| - if (index + 1 >= stateVector.size())
|
| - return nullptr;
|
| - String name = stateVector[index++];
|
| - String type = stateVector[index++];
|
| - FormControlState state = FormControlState::deserialize(stateVector, index);
|
| - if (type.isEmpty() || type.find(isNotFormControlTypeCharacter) != kNotFound || state.isFailure())
|
| - return nullptr;
|
| - savedFormState->appendControlState(name, type, state);
|
| - }
|
| - return savedFormState.release();
|
| -}
|
| -
|
| -void SavedFormState::serializeTo(Vector<String>& stateVector) const
|
| -{
|
| - stateVector.append(String::number(m_controlStateCount));
|
| - for (FormElementStateMap::const_iterator it = m_stateForNewFormElements.begin(); it != m_stateForNewFormElements.end(); ++it) {
|
| - const FormElementKey& key = it->key;
|
| - const Deque<FormControlState>& queue = it->value;
|
| - for (Deque<FormControlState>::const_iterator queIterator = queue.begin(); queIterator != queue.end(); ++queIterator) {
|
| - stateVector.append(key.name());
|
| - stateVector.append(key.type());
|
| - queIterator->serializeTo(stateVector);
|
| - }
|
| - }
|
| -}
|
| -
|
| -void SavedFormState::appendControlState(const AtomicString& name, const AtomicString& type, const FormControlState& state)
|
| -{
|
| - FormElementKey key(name.impl(), type.impl());
|
| - FormElementStateMap::iterator it = m_stateForNewFormElements.find(key);
|
| - if (it != m_stateForNewFormElements.end())
|
| - it->value.append(state);
|
| - else {
|
| - Deque<FormControlState> stateList;
|
| - stateList.append(state);
|
| - m_stateForNewFormElements.set(key, stateList);
|
| - }
|
| - m_controlStateCount++;
|
| -}
|
| -
|
| -FormControlState SavedFormState::takeControlState(const AtomicString& name, const AtomicString& type)
|
| -{
|
| - if (m_stateForNewFormElements.isEmpty())
|
| - return FormControlState();
|
| - FormElementStateMap::iterator it = m_stateForNewFormElements.find(FormElementKey(name.impl(), type.impl()));
|
| - if (it == m_stateForNewFormElements.end())
|
| - return FormControlState();
|
| - ASSERT(it->value.size());
|
| - FormControlState state = it->value.takeFirst();
|
| - m_controlStateCount--;
|
| - if (!it->value.size())
|
| - m_stateForNewFormElements.remove(it);
|
| - return state;
|
| -}
|
| -
|
| -Vector<String> SavedFormState::getReferencedFilePaths() const
|
| -{
|
| - Vector<String> toReturn;
|
| - for (FormElementStateMap::const_iterator it = m_stateForNewFormElements.begin(); it != m_stateForNewFormElements.end(); ++it) {
|
| - const FormElementKey& key = it->key;
|
| - if (!equal(key.type(), "file", 4))
|
| - continue;
|
| - const Deque<FormControlState>& queue = it->value;
|
| - for (Deque<FormControlState>::const_iterator queIterator = queue.begin(); queIterator != queue.end(); ++queIterator) {
|
| - const Vector<FileChooserFileInfo>& selectedFiles = HTMLInputElement::filesFromFileInputFormControlState(*queIterator);
|
| - for (size_t i = 0; i < selectedFiles.size(); ++i)
|
| - toReturn.append(selectedFiles[i].path);
|
| - }
|
| - }
|
| - return toReturn;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -class FormKeyGenerator {
|
| - WTF_MAKE_NONCOPYABLE(FormKeyGenerator);
|
| - WTF_MAKE_FAST_ALLOCATED;
|
| -
|
| -public:
|
| - static PassOwnPtr<FormKeyGenerator> create() { return adoptPtr(new FormKeyGenerator); }
|
| - AtomicString formKey(const HTMLFormControlElementWithState&);
|
| - void willDeleteForm(HTMLFormElement*);
|
| -
|
| -private:
|
| - FormKeyGenerator() { }
|
| -
|
| - typedef HashMap<HTMLFormElement*, AtomicString> FormToKeyMap;
|
| - typedef HashMap<String, unsigned> FormSignatureToNextIndexMap;
|
| - FormToKeyMap m_formToKeyMap;
|
| - FormSignatureToNextIndexMap m_formSignatureToNextIndexMap;
|
| -};
|
| -
|
| -static inline void recordFormStructure(const HTMLFormElement& form, StringBuilder& builder)
|
| -{
|
| - // 2 is enough to distinguish forms in webkit.org/b/91209#c0
|
| - const size_t namedControlsToBeRecorded = 2;
|
| - const Vector<FormAssociatedElement*>& controls = form.associatedElements();
|
| - builder.append(" [");
|
| - for (size_t i = 0, namedControls = 0; i < controls.size() && namedControls < namedControlsToBeRecorded; ++i) {
|
| - if (!controls[i]->isFormControlElementWithState())
|
| - continue;
|
| - HTMLFormControlElementWithState* control = toHTMLFormControlElementWithState(controls[i]);
|
| - if (!ownerFormForState(*control))
|
| - continue;
|
| - AtomicString name = control->name();
|
| - if (name.isEmpty())
|
| - continue;
|
| - namedControls++;
|
| - builder.append(name);
|
| - builder.append(" ");
|
| - }
|
| - builder.append("]");
|
| -}
|
| -
|
| -static inline String formSignature(const HTMLFormElement& form)
|
| -{
|
| - KURL 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();
|
| -}
|
| -
|
| -AtomicString FormKeyGenerator::formKey(const HTMLFormControlElementWithState& control)
|
| -{
|
| - HTMLFormElement* form = ownerFormForState(control);
|
| - if (!form) {
|
| - DEFINE_STATIC_LOCAL(AtomicString, formKeyForNoOwner, ("No owner", AtomicString::ConstructFromLiteral));
|
| - return formKeyForNoOwner;
|
| - }
|
| - FormToKeyMap::const_iterator it = m_formToKeyMap.find(form);
|
| - if (it != m_formToKeyMap.end())
|
| - return it->value;
|
| -
|
| - String signature = formSignature(*form);
|
| - ASSERT(!signature.isNull());
|
| - FormSignatureToNextIndexMap::AddResult result = m_formSignatureToNextIndexMap.add(signature, 0);
|
| - unsigned nextIndex = result.iterator->value++;
|
| -
|
| - StringBuilder builder;
|
| - builder.append(signature);
|
| - builder.appendLiteral(" #");
|
| - builder.appendNumber(nextIndex);
|
| - AtomicString formKey = builder.toAtomicString();
|
| - m_formToKeyMap.add(form, formKey);
|
| - return formKey;
|
| -}
|
| -
|
| -void FormKeyGenerator::willDeleteForm(HTMLFormElement* form)
|
| -{
|
| - ASSERT(form);
|
| - m_formToKeyMap.remove(form);
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -FormController::FormController()
|
| -{
|
| -}
|
| -
|
| -FormController::~FormController()
|
| -{
|
| -}
|
| -
|
| -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.
|
| - DEFINE_STATIC_LOCAL(String, signature, ("\n\r?% WebKit serialized form state version 8 \n\r=&"));
|
| - return signature;
|
| -}
|
| -
|
| -PassOwnPtr<FormController::SavedFormStateMap> FormController::createSavedFormStateMap(const FormElementListHashSet& controlList)
|
| -{
|
| - OwnPtr<FormKeyGenerator> keyGenerator = FormKeyGenerator::create();
|
| - OwnPtr<SavedFormStateMap> stateMap = adoptPtr(new SavedFormStateMap);
|
| - for (FormElementListHashSet::const_iterator it = controlList.begin(); it != controlList.end(); ++it) {
|
| - HTMLFormControlElementWithState* control = (*it).get();
|
| - ASSERT(control->inDocument());
|
| - if (!control->shouldSaveAndRestoreFormControlState())
|
| - continue;
|
| - SavedFormStateMap::AddResult result = stateMap->add(keyGenerator->formKey(*control).impl(), nullptr);
|
| - if (result.isNewEntry)
|
| - result.iterator->value = SavedFormState::create();
|
| - result.iterator->value->appendControlState(control->name(), control->type(), control->saveFormControlState());
|
| - }
|
| - return stateMap.release();
|
| -}
|
| -
|
| -Vector<String> FormController::formElementsState() const
|
| -{
|
| - OwnPtr<SavedFormStateMap> stateMap = createSavedFormStateMap(m_formElementsWithState);
|
| - Vector<String> stateVector;
|
| - stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 4);
|
| - stateVector.append(formStateSignature());
|
| - for (SavedFormStateMap::const_iterator it = stateMap->begin(); it != stateMap->end(); ++it) {
|
| - stateVector.append(it->key);
|
| - it->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 = FormKeyGenerator::create();
|
| - 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()) {
|
| - AtomicString formKey = stateVector[i++];
|
| - OwnPtr<SavedFormState> state = SavedFormState::deserialize(stateVector, i);
|
| - if (!state) {
|
| - i = 0;
|
| - break;
|
| - }
|
| - map.add(formKey.impl(), state.release());
|
| - }
|
| - 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;
|
| - FormControlState state = takeStateForFormElement(control);
|
| - if (state.valueSize() > 0)
|
| - control.restoreFormControlState(state);
|
| -}
|
| -
|
| -void FormController::restoreControlStateIn(HTMLFormElement& form)
|
| -{
|
| - const Vector<FormAssociatedElement*>& elements = form.associatedElements();
|
| - for (size_t i = 0; i < elements.size(); ++i) {
|
| - if (!elements[i]->isFormControlElementWithState())
|
| - continue;
|
| - HTMLFormControlElementWithState* control = toHTMLFormControlElementWithState(elements[i]);
|
| - if (!control->shouldSaveAndRestoreFormControlState())
|
| - continue;
|
| - if (ownerFormForState(*control) != &form)
|
| - continue;
|
| - FormControlState state = takeStateForFormElement(*control);
|
| - if (state.valueSize() > 0)
|
| - control->restoreFormControlState(state);
|
| - }
|
| -}
|
| -
|
| -Vector<String> FormController::getReferencedFilePaths(const Vector<String>& stateVector)
|
| -{
|
| - Vector<String> toReturn;
|
| - SavedFormStateMap map;
|
| - formStatesFromStateVector(stateVector, map);
|
| - for (SavedFormStateMap::const_iterator it = map.begin(); it != map.end(); ++it)
|
| - toReturn.append(it->value->getReferencedFilePaths());
|
| - return toReturn;
|
| -}
|
| -
|
| -void FormController::registerFormElementWithState(HTMLFormControlElementWithState* control)
|
| -{
|
| - ASSERT(!m_formElementsWithState.contains(control));
|
| - m_formElementsWithState.add(control);
|
| -}
|
| -
|
| -void FormController::unregisterFormElementWithState(HTMLFormControlElementWithState* control)
|
| -{
|
| - RELEASE_ASSERT(m_formElementsWithState.contains(control));
|
| - m_formElementsWithState.remove(control);
|
| -}
|
| -
|
| -} // namespace WebCore
|
|
|