blob: 80d01f2ca317cf4b5f6e9a705af6654545c0ca94 [file] [log] [blame]
/*
* 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 "FormController.h"
#include "HTMLFormControlElementWithState.h"
namespace WebCore {
using namespace HTMLNames;
FormController::FormController()
{
}
FormController::~FormController()
{
}
Vector<String> FormController::formElementsState() const
{
Vector<String> stateVector;
stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 3);
typedef FormElementListHashSet::const_iterator Iterator;
Iterator end = m_formElementsWithState.end();
for (Iterator it = m_formElementsWithState.begin(); it != end; ++it) {
HTMLFormControlElementWithState* elementWithState = *it;
if (!elementWithState->shouldSaveAndRestoreFormControlState())
continue;
FormControlState state = elementWithState->saveFormControlState();
if (!state.hasValue())
continue;
stateVector.append(elementWithState->name().string());
stateVector.append(elementWithState->formControlType().string());
stateVector.append(state.value());
}
return stateVector;
}
static bool isNotFormControlTypeCharacter(UChar ch)
{
return ch != '-' && (ch > 'z' || ch < 'a');
}
void FormController::setStateForNewFormElements(const Vector<String>& stateVector)
{
// Walk the state vector backwards so that the value to use for each
// name/type pair first is the one at the end of each individual vector
// in the FormElementStateMap. We're using them like stacks.
typedef FormElementStateMap::iterator Iterator;
m_formElementsWithState.clear();
if (stateVector.size() % 3)
return;
for (size_t i = 0; i < stateVector.size(); i += 3) {
if (stateVector[i + 1].find(isNotFormControlTypeCharacter) != notFound)
return;
}
for (size_t i = stateVector.size() / 3 * 3; i; i -= 3) {
AtomicString name = stateVector[i - 3];
AtomicString type = stateVector[i - 2];
const String& value = stateVector[i - 1];
FormElementKey key(name.impl(), type.impl());
Iterator it = m_stateForNewFormElements.find(key);
if (it != m_stateForNewFormElements.end())
it->second.append(value);
else {
Vector<String> valueList(1);
valueList[0] = value;
m_stateForNewFormElements.set(key, valueList);
}
}
}
bool FormController::hasStateForNewFormElements() const
{
return !m_stateForNewFormElements.isEmpty();
}
FormControlState FormController::takeStateForFormElement(AtomicStringImpl* name, AtomicStringImpl* type)
{
typedef FormElementStateMap::iterator Iterator;
Iterator it = m_stateForNewFormElements.find(FormElementKey(name, type));
if (it == m_stateForNewFormElements.end())
return FormControlState();
ASSERT(it->second.size());
FormControlState state(it->second.last());
if (it->second.size() > 1)
it->second.removeLast();
else
m_stateForNewFormElements.remove(it);
return state;
}
void FormController::registerFormElementWithFormAttribute(FormAssociatedElement* element)
{
ASSERT(toHTMLElement(element)->fastHasAttribute(formAttr));
m_formElementsWithFormAttribute.add(element);
}
void FormController::unregisterFormElementWithFormAttribute(FormAssociatedElement* element)
{
m_formElementsWithFormAttribute.remove(element);
}
void FormController::resetFormElementsOwner()
{
typedef FormAssociatedElementListHashSet::iterator Iterator;
Iterator end = m_formElementsWithFormAttribute.end();
for (Iterator it = m_formElementsWithFormAttribute.begin(); it != end; ++it)
(*it)->resetFormOwner();
}
FormElementKey::FormElementKey(AtomicStringImpl* name, AtomicStringImpl* 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();
}
unsigned FormElementKeyHash::hash(const FormElementKey& key)
{
return StringHasher::hashMemory<sizeof(FormElementKey)>(&key);
}
} // namespace WebCore