blob: 31c776343cb3c6ffbc1f55a2e242647d8694d9c1 [file] [log] [blame]
tkent@chromium.org34554872012-06-08 09:53:52 +00001/*
2 * Copyright (C) 2006, 2008, 2009, 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2010, 2011, 2012 Google Inc. All rights reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21#include "config.h"
22#include "FormController.h"
23
24#include "HTMLFormControlElementWithState.h"
25
26namespace WebCore {
27
28using namespace HTMLNames;
29
tkent@chromium.org1c1b7542012-06-21 01:31:08 +000030// ----------------------------------------------------------------------------
31
32// Serilized form of FormControlState:
tkent@chromium.orgb5f15632012-06-26 01:20:05 +000033// (',' means strings around it are separated in stateVector.)
tkent@chromium.org1c1b7542012-06-21 01:31:08 +000034//
tkent@chromium.org98085312012-06-22 05:36:28 +000035// SerializedControlState ::= SkipState | RestoreState
tkent@chromium.orgb5f15632012-06-26 01:20:05 +000036// SkipState ::= '0'
37// RestoreState ::= UnsignedNumber, ControlValue+
38// UnsignedNumber ::= [0-9]+
39// ControlValue ::= arbitrary string
40//
41// RestoreState has a sequence of ControlValues. The length of the
42// sequence is represented by UnsignedNumber.
tkent@chromium.org1c1b7542012-06-21 01:31:08 +000043
tkent@chromium.orgb5f15632012-06-26 01:20:05 +000044void FormControlState::serializeTo(Vector<String>& stateVector) const
tkent@chromium.org1c1b7542012-06-21 01:31:08 +000045{
46 ASSERT(!isFailure());
tkent@chromium.orgb5f15632012-06-26 01:20:05 +000047 stateVector.append(String::number(m_values.size()));
tkent@chromium.org98085312012-06-22 05:36:28 +000048 for (size_t i = 0; i < m_values.size(); ++i)
tkent@chromium.orgb5f15632012-06-26 01:20:05 +000049 stateVector.append(m_values[i].isNull() ? emptyString() : m_values[i]);
tkent@chromium.org1c1b7542012-06-21 01:31:08 +000050}
51
tkent@chromium.orgb5f15632012-06-26 01:20:05 +000052FormControlState FormControlState::deserialize(const Vector<String>& stateVector, size_t& index)
tkent@chromium.org1c1b7542012-06-21 01:31:08 +000053{
tkent@chromium.orgb5f15632012-06-26 01:20:05 +000054 if (index >= stateVector.size())
tkent@chromium.org1c1b7542012-06-21 01:31:08 +000055 return FormControlState(TypeFailure);
tkent@chromium.orgb5f15632012-06-26 01:20:05 +000056 size_t valueSize = stateVector[index++].toUInt();
57 if (!valueSize)
58 return FormControlState();
59 if (index + valueSize > stateVector.size())
60 return FormControlState(TypeFailure);
tkent@chromium.org98085312012-06-22 05:36:28 +000061 FormControlState state;
62 state.m_values.reserveCapacity(valueSize);
tkent@chromium.orgb5f15632012-06-26 01:20:05 +000063 for (size_t i = 0; i < valueSize; ++i)
64 state.append(stateVector[index++]);
tkent@chromium.org98085312012-06-22 05:36:28 +000065 return state;
tkent@chromium.org1c1b7542012-06-21 01:31:08 +000066}
67
68// ----------------------------------------------------------------------------
69
70
tkent@chromium.org34554872012-06-08 09:53:52 +000071FormController::FormController()
72{
73}
74
75FormController::~FormController()
76{
77}
78
tkent@chromium.org1c1b7542012-06-21 01:31:08 +000079static String formStateSignature()
80{
81 // In the legacy version of serialized state, the first item was a name
82 // attribute value of a form control. The following string literal should
83 // contain some characters which are rarely used for name attribute values.
tkent@chromium.orgb5f15632012-06-26 01:20:05 +000084 DEFINE_STATIC_LOCAL(String, signature, ("\n\r?% WebKit serialized form state version 3 \n\r=&"));
tkent@chromium.org1c1b7542012-06-21 01:31:08 +000085 return signature;
86}
87
tkent@chromium.org34554872012-06-08 09:53:52 +000088Vector<String> FormController::formElementsState() const
89{
90 Vector<String> stateVector;
tkent@chromium.orgb5f15632012-06-26 01:20:05 +000091 stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 4 + 1);
tkent@chromium.org1c1b7542012-06-21 01:31:08 +000092 stateVector.append(formStateSignature());
tkent@chromium.org34554872012-06-08 09:53:52 +000093 typedef FormElementListHashSet::const_iterator Iterator;
94 Iterator end = m_formElementsWithState.end();
95 for (Iterator it = m_formElementsWithState.begin(); it != end; ++it) {
96 HTMLFormControlElementWithState* elementWithState = *it;
97 if (!elementWithState->shouldSaveAndRestoreFormControlState())
98 continue;
tkent@chromium.orgd442931e2012-06-12 09:10:04 +000099 stateVector.append(elementWithState->name().string());
tkent@chromium.org34554872012-06-08 09:53:52 +0000100 stateVector.append(elementWithState->formControlType().string());
tkent@chromium.orgb5f15632012-06-26 01:20:05 +0000101 elementWithState->saveFormControlState().serializeTo(stateVector);
tkent@chromium.org34554872012-06-08 09:53:52 +0000102 }
103 return stateVector;
104}
105
tkent@chromium.orgbcc71632012-06-15 04:34:25 +0000106static bool isNotFormControlTypeCharacter(UChar ch)
107{
108 return ch != '-' && (ch > 'z' || ch < 'a');
109}
110
tkent@chromium.org34554872012-06-08 09:53:52 +0000111void FormController::setStateForNewFormElements(const Vector<String>& stateVector)
112{
tkent@chromium.org34554872012-06-08 09:53:52 +0000113 typedef FormElementStateMap::iterator Iterator;
114 m_formElementsWithState.clear();
tkent@chromium.orgbcc71632012-06-15 04:34:25 +0000115
tkent@chromium.orgb5f15632012-06-26 01:20:05 +0000116 size_t i = 0;
117 if (stateVector.size() < 1 || stateVector[i++] != formStateSignature())
tkent@chromium.orgbcc71632012-06-15 04:34:25 +0000118 return;
tkent@chromium.orgbcc71632012-06-15 04:34:25 +0000119
tkent@chromium.orgb5f15632012-06-26 01:20:05 +0000120 while (i + 2 < stateVector.size()) {
121 AtomicString name = stateVector[i++];
122 AtomicString type = stateVector[i++];
123 FormControlState state = FormControlState::deserialize(stateVector, i);
tkent@chromium.org1c1b7542012-06-21 01:31:08 +0000124 if (type.isEmpty() || type.impl()->find(isNotFormControlTypeCharacter) != notFound || state.isFailure())
125 break;
126
tkent@chromium.orgbcc71632012-06-15 04:34:25 +0000127 FormElementKey key(name.impl(), type.impl());
tkent@chromium.org34554872012-06-08 09:53:52 +0000128 Iterator it = m_stateForNewFormElements.find(key);
129 if (it != m_stateForNewFormElements.end())
tkent@chromium.org1c1b7542012-06-21 01:31:08 +0000130 it->second.append(state);
tkent@chromium.org34554872012-06-08 09:53:52 +0000131 else {
tkent@chromium.org1c1b7542012-06-21 01:31:08 +0000132 Deque<FormControlState> stateList;
133 stateList.append(state);
134 m_stateForNewFormElements.set(key, stateList);
tkent@chromium.org34554872012-06-08 09:53:52 +0000135 }
136 }
tkent@chromium.orgb5f15632012-06-26 01:20:05 +0000137 if (i != stateVector.size())
138 m_stateForNewFormElements.clear();
tkent@chromium.org34554872012-06-08 09:53:52 +0000139}
140
141bool FormController::hasStateForNewFormElements() const
142{
143 return !m_stateForNewFormElements.isEmpty();
144}
145
tkent@chromium.orgd08b5512012-06-19 06:20:48 +0000146FormControlState FormController::takeStateForFormElement(AtomicStringImpl* name, AtomicStringImpl* type)
tkent@chromium.org34554872012-06-08 09:53:52 +0000147{
148 typedef FormElementStateMap::iterator Iterator;
149 Iterator it = m_stateForNewFormElements.find(FormElementKey(name, type));
150 if (it == m_stateForNewFormElements.end())
tkent@chromium.orgd08b5512012-06-19 06:20:48 +0000151 return FormControlState();
tkent@chromium.org34554872012-06-08 09:53:52 +0000152 ASSERT(it->second.size());
tkent@chromium.org1c1b7542012-06-21 01:31:08 +0000153 FormControlState state = it->second.takeFirst();
154 if (!it->second.size())
tkent@chromium.org34554872012-06-08 09:53:52 +0000155 m_stateForNewFormElements.remove(it);
tkent@chromium.orgd08b5512012-06-19 06:20:48 +0000156 return state;
tkent@chromium.org34554872012-06-08 09:53:52 +0000157}
158
159void FormController::registerFormElementWithFormAttribute(FormAssociatedElement* element)
160{
161 ASSERT(toHTMLElement(element)->fastHasAttribute(formAttr));
162 m_formElementsWithFormAttribute.add(element);
163}
164
165void FormController::unregisterFormElementWithFormAttribute(FormAssociatedElement* element)
166{
167 m_formElementsWithFormAttribute.remove(element);
168}
169
170void FormController::resetFormElementsOwner()
171{
172 typedef FormAssociatedElementListHashSet::iterator Iterator;
173 Iterator end = m_formElementsWithFormAttribute.end();
174 for (Iterator it = m_formElementsWithFormAttribute.begin(); it != end; ++it)
175 (*it)->resetFormOwner();
176}
177
178FormElementKey::FormElementKey(AtomicStringImpl* name, AtomicStringImpl* type)
179 : m_name(name), m_type(type)
180{
181 ref();
182}
183
184FormElementKey::~FormElementKey()
185{
186 deref();
187}
188
189FormElementKey::FormElementKey(const FormElementKey& other)
190 : m_name(other.name()), m_type(other.type())
191{
192 ref();
193}
194
195FormElementKey& FormElementKey::operator=(const FormElementKey& other)
196{
197 other.ref();
198 deref();
199 m_name = other.name();
200 m_type = other.type();
201 return *this;
202}
203
204void FormElementKey::ref() const
205{
206 if (name())
207 name()->ref();
208 if (type())
209 type()->ref();
210}
211
212void FormElementKey::deref() const
213{
214 if (name())
215 name()->deref();
216 if (type())
217 type()->deref();
218}
219
220unsigned FormElementKeyHash::hash(const FormElementKey& key)
221{
222 return StringHasher::hashMemory<sizeof(FormElementKey)>(&key);
223}
224
225} // namespace WebCore
226