Change the serialization format of form control state to make the code simple
[WebKit-https.git] / Source / WebCore / html / FormController.cpp
1 /*
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 #include <wtf/text/StringBuilder.h>
26
27 namespace WebCore {
28
29 using namespace HTMLNames;
30
31 // ----------------------------------------------------------------------------
32
33 // Serilized form of FormControlState:
34 //
35 // SerializedControlState ::= SkipState | RestoreState
36 // SkipState ::= ''
37 // RestoreState ::= (',' EscapedValue )+
38 // EscapedValue ::= ('\\' | '\,' | [^\,])+
39
40 String FormControlState::serialize() const
41 {
42     ASSERT(!isFailure());
43     if (!m_values.size())
44         return emptyString();
45
46     size_t enoughSize = 0;
47     for (size_t i = 0; i < m_values.size(); ++i)
48         enoughSize += 1 + m_values[i].length() * 2;
49     StringBuilder builder;
50     builder.reserveCapacity(enoughSize);
51     for (size_t i = 0; i < m_values.size(); ++i) {
52         builder.append(',');
53         builder.appendEscaped(m_values[i], '\\', ',');
54     }
55     return builder.toString();
56 }
57
58 FormControlState FormControlState::deserialize(const String& escaped)
59 {
60     if (!escaped.length())
61         return FormControlState();
62     if (escaped[0] != ',')
63         return FormControlState(TypeFailure);
64
65     size_t valueSize = 1;
66     for (unsigned i = 1; i < escaped.length(); ++i) {
67         if (escaped[i] == '\\') {
68             if (++i >= escaped.length())
69                 return FormControlState(TypeFailure);
70         } else if (escaped[i] == ',')
71             valueSize++;
72     }
73
74     FormControlState state;
75     state.m_values.reserveCapacity(valueSize);
76     StringBuilder builder;
77     for (unsigned i = 1; i < escaped.length(); ++i) {
78         if (escaped[i] == '\\') {
79             if (++i >= escaped.length())
80                 return FormControlState(TypeFailure);
81             builder.append(escaped[i]);
82         } else if (escaped[i] == ',') {
83             state.append(builder.toString());
84             builder.clear();
85         } else
86             builder.append(escaped[i]);
87     }
88     state.append(builder.toString());
89     return state;
90 }
91
92 // ----------------------------------------------------------------------------
93
94
95 FormController::FormController()
96 {
97 }
98
99 FormController::~FormController()
100 {
101 }
102
103 static String formStateSignature()
104 {
105     // In the legacy version of serialized state, the first item was a name
106     // attribute value of a form control. The following string literal should
107     // contain some characters which are rarely used for name attribute values.
108     DEFINE_STATIC_LOCAL(String, signature, ("\n\r?% WebKit serialized form state version 4 \n\r=&"));
109     return signature;
110 }
111
112 Vector<String> FormController::formElementsState() const
113 {
114     Vector<String> stateVector;
115     stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 3 + 1);
116     stateVector.append(formStateSignature());
117     typedef FormElementListHashSet::const_iterator Iterator;
118     Iterator end = m_formElementsWithState.end();
119     for (Iterator it = m_formElementsWithState.begin(); it != end; ++it) {
120         HTMLFormControlElementWithState* elementWithState = *it;
121         if (!elementWithState->shouldSaveAndRestoreFormControlState())
122             continue;
123         stateVector.append(elementWithState->name().string());
124         stateVector.append(elementWithState->formControlType().string());
125         stateVector.append(elementWithState->saveFormControlState().serialize());
126     }
127     return stateVector;
128 }
129
130 static bool isNotFormControlTypeCharacter(UChar ch)
131 {
132     return ch != '-' && (ch > 'z' || ch < 'a');
133 }
134
135 void FormController::setStateForNewFormElements(const Vector<String>& stateVector)
136 {
137     typedef FormElementStateMap::iterator Iterator;
138     m_formElementsWithState.clear();
139
140     if (stateVector.size() < 1 || stateVector[0] != formStateSignature())
141         return;
142     if ((stateVector.size() - 1) % 3)
143         return;
144
145     for (size_t i = 1; i < stateVector.size(); i += 3) {
146         AtomicString name = stateVector[i];
147         AtomicString type = stateVector[i + 1];
148         FormControlState state = FormControlState::deserialize(stateVector[i + 2]);
149         if (type.isEmpty() || type.impl()->find(isNotFormControlTypeCharacter) != notFound || state.isFailure())
150             break;
151
152         FormElementKey key(name.impl(), type.impl());
153         Iterator it = m_stateForNewFormElements.find(key);
154         if (it != m_stateForNewFormElements.end())
155             it->second.append(state);
156         else {
157             Deque<FormControlState> stateList;
158             stateList.append(state);
159             m_stateForNewFormElements.set(key, stateList);
160         }
161     }
162 }
163
164 bool FormController::hasStateForNewFormElements() const
165 {
166     return !m_stateForNewFormElements.isEmpty();
167 }
168
169 FormControlState FormController::takeStateForFormElement(AtomicStringImpl* name, AtomicStringImpl* type)
170 {
171     typedef FormElementStateMap::iterator Iterator;
172     Iterator it = m_stateForNewFormElements.find(FormElementKey(name, type));
173     if (it == m_stateForNewFormElements.end())
174         return FormControlState();
175     ASSERT(it->second.size());
176     FormControlState state = it->second.takeFirst();
177     if (!it->second.size())
178         m_stateForNewFormElements.remove(it);
179     return state;
180 }
181
182 void FormController::registerFormElementWithFormAttribute(FormAssociatedElement* element)
183 {
184     ASSERT(toHTMLElement(element)->fastHasAttribute(formAttr));
185     m_formElementsWithFormAttribute.add(element);
186 }
187
188 void FormController::unregisterFormElementWithFormAttribute(FormAssociatedElement* element)
189 {
190     m_formElementsWithFormAttribute.remove(element);
191 }
192
193 void FormController::resetFormElementsOwner()
194 {
195     typedef FormAssociatedElementListHashSet::iterator Iterator;
196     Iterator end = m_formElementsWithFormAttribute.end();
197     for (Iterator it = m_formElementsWithFormAttribute.begin(); it != end; ++it)
198         (*it)->resetFormOwner();
199 }
200
201 FormElementKey::FormElementKey(AtomicStringImpl* name, AtomicStringImpl* type)
202     : m_name(name), m_type(type)
203 {
204     ref();
205 }
206
207 FormElementKey::~FormElementKey()
208 {
209     deref();
210 }
211
212 FormElementKey::FormElementKey(const FormElementKey& other)
213     : m_name(other.name()), m_type(other.type())
214 {
215     ref();
216 }
217
218 FormElementKey& FormElementKey::operator=(const FormElementKey& other)
219 {
220     other.ref();
221     deref();
222     m_name = other.name();
223     m_type = other.type();
224     return *this;
225 }
226
227 void FormElementKey::ref() const
228 {
229     if (name())
230         name()->ref();
231     if (type())
232         type()->ref();
233 }
234
235 void FormElementKey::deref() const
236 {
237     if (name())
238         name()->deref();
239     if (type())
240         type()->deref();
241 }
242
243 unsigned FormElementKeyHash::hash(const FormElementKey& key)
244 {
245     return StringHasher::hashMemory<sizeof(FormElementKey)>(&key);
246 }
247
248 } // namespace WebCore
249