b7df2d4dc79248b3792938ff485dd1a0e6d70829
[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 "HTMLFormElement.h"
25 #include "HTMLInputElement.h"
26 #include <wtf/text/StringBuilder.h>
27
28 namespace WebCore {
29
30 using namespace HTMLNames;
31
32 static inline HTMLFormElement* ownerFormForState(const HTMLFormControlElementWithState& control)
33 {
34     // Assume controls with form attribute have no owners because we restore
35     // state during parsing and form owners of such controls might be
36     // indeterminate.
37     return control.fastHasAttribute(formAttr) ? 0 : control.form();
38 }
39
40 // ----------------------------------------------------------------------------
41
42 // Serilized form of FormControlState:
43 //  (',' means strings around it are separated in stateVector.)
44 //
45 // SerializedControlState ::= SkipState | RestoreState
46 // SkipState ::= '0'
47 // RestoreState ::= UnsignedNumber, ControlValue+
48 // UnsignedNumber ::= [0-9]+
49 // ControlValue ::= arbitrary string
50 //
51 // RestoreState has a sequence of ControlValues. The length of the
52 // sequence is represented by UnsignedNumber.
53
54 void FormControlState::serializeTo(Vector<String>& stateVector) const
55 {
56     ASSERT(!isFailure());
57     stateVector.append(String::number(m_values.size()));
58     for (size_t i = 0; i < m_values.size(); ++i)
59         stateVector.append(m_values[i].isNull() ? emptyString() : m_values[i]);
60 }
61
62 FormControlState FormControlState::deserialize(const Vector<String>& stateVector, size_t& index)
63 {
64     if (index >= stateVector.size())
65         return FormControlState(TypeFailure);
66     size_t valueSize = stateVector[index++].toUInt();
67     if (!valueSize)
68         return FormControlState();
69     if (index + valueSize > stateVector.size())
70         return FormControlState(TypeFailure);
71     FormControlState state;
72     state.m_values.reserveCapacity(valueSize);
73     for (size_t i = 0; i < valueSize; ++i)
74         state.append(stateVector[index++]);
75     return state;
76 }
77
78 // ----------------------------------------------------------------------------
79
80 class FormElementKey {
81 public:
82     FormElementKey(AtomicStringImpl* = 0, AtomicStringImpl* = 0);
83     ~FormElementKey();
84     FormElementKey(const FormElementKey&);
85     FormElementKey& operator=(const FormElementKey&);
86
87     AtomicStringImpl* name() const { return m_name; }
88     AtomicStringImpl* type() const { return m_type; }
89
90     // Hash table deleted values, which are only constructed and never copied or destroyed.
91     FormElementKey(WTF::HashTableDeletedValueType) : m_name(hashTableDeletedValue()) { }
92     bool isHashTableDeletedValue() const { return m_name == hashTableDeletedValue(); }
93
94 private:
95     void ref() const;
96     void deref() const;
97
98     static AtomicStringImpl* hashTableDeletedValue() { return reinterpret_cast<AtomicStringImpl*>(-1); }
99
100     AtomicStringImpl* m_name;
101     AtomicStringImpl* m_type;
102 };
103
104 FormElementKey::FormElementKey(AtomicStringImpl* name, AtomicStringImpl* type)
105     : m_name(name)
106     , m_type(type)
107 {
108     ref();
109 }
110
111 FormElementKey::~FormElementKey()
112 {
113     deref();
114 }
115
116 FormElementKey::FormElementKey(const FormElementKey& other)
117     : m_name(other.name())
118     , m_type(other.type())
119 {
120     ref();
121 }
122
123 FormElementKey& FormElementKey::operator=(const FormElementKey& other)
124 {
125     other.ref();
126     deref();
127     m_name = other.name();
128     m_type = other.type();
129     return *this;
130 }
131
132 void FormElementKey::ref() const
133 {
134     if (name())
135         name()->ref();
136     if (type())
137         type()->ref();
138 }
139
140 void FormElementKey::deref() const
141 {
142     if (name())
143         name()->deref();
144     if (type())
145         type()->deref();
146 }
147
148 inline bool operator==(const FormElementKey& a, const FormElementKey& b)
149 {
150     return a.name() == b.name() && a.type() == b.type();
151 }
152
153 struct FormElementKeyHash {
154     static unsigned hash(const FormElementKey&);
155     static bool equal(const FormElementKey& a, const FormElementKey& b) { return a == b; }
156     static const bool safeToCompareToEmptyOrDeleted = true;
157 };
158
159 unsigned FormElementKeyHash::hash(const FormElementKey& key)
160 {
161     return StringHasher::hashMemory<sizeof(FormElementKey)>(&key);
162 }
163
164 struct FormElementKeyHashTraits : WTF::GenericHashTraits<FormElementKey> {
165     static void constructDeletedValue(FormElementKey& slot) { new (NotNull, &slot) FormElementKey(WTF::HashTableDeletedValue); }
166     static bool isDeletedValue(const FormElementKey& value) { return value.isHashTableDeletedValue(); }
167 };
168
169 // ----------------------------------------------------------------------------
170
171 class SavedFormState {
172     WTF_MAKE_NONCOPYABLE(SavedFormState);
173     WTF_MAKE_FAST_ALLOCATED;
174
175 public:
176     SavedFormState()
177         : m_controlStateCount(0)
178     {
179     }
180
181     static std::unique_ptr<SavedFormState> deserialize(const Vector<String>&, size_t& index);
182     void serializeTo(Vector<String>&) const;
183     bool isEmpty() const { return m_stateForNewFormElements.isEmpty(); }
184     void appendControlState(const AtomicString& name, const AtomicString& type, const FormControlState&);
185     FormControlState takeControlState(const AtomicString& name, const AtomicString& type);
186
187     Vector<String> getReferencedFilePaths() const;
188
189 private:
190     typedef HashMap<FormElementKey, Deque<FormControlState>, FormElementKeyHash, FormElementKeyHashTraits> FormElementStateMap;
191     FormElementStateMap m_stateForNewFormElements;
192     size_t m_controlStateCount;
193 };
194
195 static bool isNotFormControlTypeCharacter(UChar ch)
196 {
197     return ch != '-' && (ch > 'z' || ch < 'a');
198 }
199
200 std::unique_ptr<SavedFormState> SavedFormState::deserialize(const Vector<String>& stateVector, size_t& index)
201 {
202     if (index >= stateVector.size())
203         return nullptr;
204     // FIXME: We need String::toSizeT().
205     size_t itemCount = stateVector[index++].toUInt();
206     if (!itemCount)
207         return nullptr;
208     auto savedFormState = std::make_unique<SavedFormState>();
209     while (itemCount--) {
210         if (index + 1 >= stateVector.size())
211             return nullptr;
212         String name = stateVector[index++];
213         String type = stateVector[index++];
214         FormControlState state = FormControlState::deserialize(stateVector, index);
215         if (type.isEmpty() || type.find(isNotFormControlTypeCharacter) != notFound || state.isFailure())
216             return nullptr;
217         savedFormState->appendControlState(name, type, state);
218     }
219     return savedFormState;
220 }
221
222 void SavedFormState::serializeTo(Vector<String>& stateVector) const
223 {
224     stateVector.append(String::number(m_controlStateCount));
225     for (FormElementStateMap::const_iterator it = m_stateForNewFormElements.begin(); it != m_stateForNewFormElements.end(); ++it) {
226         const FormElementKey& key = it->key;
227         const Deque<FormControlState>& queue = it->value;
228         for (Deque<FormControlState>::const_iterator queIterator = queue.begin(); queIterator != queue.end(); ++queIterator) {
229             stateVector.append(key.name());
230             stateVector.append(key.type());
231             queIterator->serializeTo(stateVector);
232         }
233     }
234 }
235
236 void SavedFormState::appendControlState(const AtomicString& name, const AtomicString& type, const FormControlState& state)
237 {
238     FormElementKey key(name.impl(), type.impl());
239     FormElementStateMap::iterator it = m_stateForNewFormElements.find(key);
240     if (it != m_stateForNewFormElements.end())
241         it->value.append(state);
242     else {
243         Deque<FormControlState> stateList;
244         stateList.append(state);
245         m_stateForNewFormElements.set(key, stateList);
246     }
247     m_controlStateCount++;
248 }
249
250 FormControlState SavedFormState::takeControlState(const AtomicString& name, const AtomicString& type)
251 {
252     if (m_stateForNewFormElements.isEmpty())
253         return FormControlState();
254     FormElementStateMap::iterator it = m_stateForNewFormElements.find(FormElementKey(name.impl(), type.impl()));
255     if (it == m_stateForNewFormElements.end())
256         return FormControlState();
257     ASSERT(it->value.size());
258     FormControlState state = it->value.takeFirst();
259     m_controlStateCount--;
260     if (!it->value.size())
261         m_stateForNewFormElements.remove(it);
262     return state;
263 }
264
265 Vector<String> SavedFormState::getReferencedFilePaths() const
266 {
267     Vector<String> toReturn;
268     for (FormElementStateMap::const_iterator it = m_stateForNewFormElements.begin(); it != m_stateForNewFormElements.end(); ++it) {
269         const FormElementKey& key = it->key;
270         if (!equal(key.type(), "file", 4))
271             continue;
272         const Deque<FormControlState>& queue = it->value;
273         for (Deque<FormControlState>::const_iterator queIterator = queue.begin(); queIterator != queue.end(); ++queIterator) {
274             const Vector<FileChooserFileInfo>& selectedFiles = HTMLInputElement::filesFromFileInputFormControlState(*queIterator);
275             for (size_t i = 0; i < selectedFiles.size(); ++i)
276                 toReturn.append(selectedFiles[i].path);
277         }
278     }
279     return toReturn;
280 }
281
282 // ----------------------------------------------------------------------------
283
284 class FormKeyGenerator {
285     WTF_MAKE_NONCOPYABLE(FormKeyGenerator);
286     WTF_MAKE_FAST_ALLOCATED;
287
288 public:
289     FormKeyGenerator() = default;
290     AtomicString formKey(const HTMLFormControlElementWithState&);
291     void willDeleteForm(HTMLFormElement*);
292
293 private:
294     typedef HashMap<HTMLFormElement*, AtomicString> FormToKeyMap;
295     typedef HashMap<String, unsigned> FormSignatureToNextIndexMap;
296     FormToKeyMap m_formToKeyMap;
297     FormSignatureToNextIndexMap m_formSignatureToNextIndexMap;
298 };
299
300 static inline void recordFormStructure(const HTMLFormElement& form, StringBuilder& builder)
301 {
302     // 2 is enough to distinguish forms in webkit.org/b/91209#c0
303     const size_t namedControlsToBeRecorded = 2;
304     const Vector<FormAssociatedElement*>& controls = form.associatedElements();
305     builder.appendLiteral(" [");
306     for (size_t i = 0, namedControls = 0; i < controls.size() && namedControls < namedControlsToBeRecorded; ++i) {
307         if (!controls[i]->isFormControlElementWithState())
308             continue;
309         HTMLFormControlElementWithState* control = static_cast<HTMLFormControlElementWithState*>(controls[i]);
310         if (!ownerFormForState(*control))
311             continue;
312         AtomicString name = control->name();
313         if (name.isEmpty())
314             continue;
315         namedControls++;
316         builder.append(name);
317         builder.append(' ');
318     }
319     builder.append(']');
320 }
321
322 static inline String formSignature(const HTMLFormElement& form)
323 {
324     URL actionURL = form.getURLAttribute(actionAttr);
325     // Remove the query part because it might contain volatile parameters such
326     // as a session key.
327     actionURL.setQuery(String());
328     StringBuilder builder;
329     if (!actionURL.isEmpty())
330         builder.append(actionURL.string());
331
332     recordFormStructure(form, builder);
333     return builder.toString();
334 }
335
336 AtomicString FormKeyGenerator::formKey(const HTMLFormControlElementWithState& control)
337 {
338     HTMLFormElement* form = ownerFormForState(control);
339     if (!form) {
340         DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, formKeyForNoOwner, ("No owner", AtomicString::ConstructFromLiteral));
341         return formKeyForNoOwner;
342     }
343     FormToKeyMap::const_iterator it = m_formToKeyMap.find(form);
344     if (it != m_formToKeyMap.end())
345         return it->value;
346
347     String signature = formSignature(*form);
348     ASSERT(!signature.isNull());
349     FormSignatureToNextIndexMap::AddResult result = m_formSignatureToNextIndexMap.add(signature, 0);
350     unsigned nextIndex = result.iterator->value++;
351
352     StringBuilder builder;
353     builder.append(signature);
354     builder.appendLiteral(" #");
355     builder.appendNumber(nextIndex);
356     AtomicString formKey = builder.toAtomicString();
357     m_formToKeyMap.add(form, formKey);
358     return formKey;
359 }
360
361 void FormKeyGenerator::willDeleteForm(HTMLFormElement* form)
362 {
363     ASSERT(form);
364     m_formToKeyMap.remove(form);
365 }
366
367 // ----------------------------------------------------------------------------
368
369 FormController::FormController()
370 {
371 }
372
373 FormController::~FormController()
374 {
375 }
376
377 unsigned FormController::formElementsCharacterCount() const
378 {
379     unsigned count = 0;
380     for (auto& element : m_formElementsWithState) {
381         FormControlState state = element->saveFormControlState();
382         if (state.valueSize() && element->isTextFormControl())
383             count += state[0].length();
384     }
385     return count;
386 }
387
388 static String formStateSignature()
389 {
390     // In the legacy version of serialized state, the first item was a name
391     // attribute value of a form control. The following string literal should
392     // contain some characters which are rarely used for name attribute values.
393     DEPRECATED_DEFINE_STATIC_LOCAL(String, signature, (ASCIILiteral("\n\r?% WebKit serialized form state version 8 \n\r=&")));
394     return signature;
395 }
396
397 std::unique_ptr<FormController::SavedFormStateMap> FormController::createSavedFormStateMap(const FormElementListHashSet& controlList)
398 {
399     FormKeyGenerator keyGenerator;
400     auto stateMap = std::make_unique<SavedFormStateMap>();
401     for (FormElementListHashSet::const_iterator it = controlList.begin(); it != controlList.end(); ++it) {
402         HTMLFormControlElementWithState* control = it->get();
403         if (!control->shouldSaveAndRestoreFormControlState())
404             continue;
405         auto& formState = stateMap->add(keyGenerator.formKey(*control).impl(), nullptr).iterator->value;
406         if (!formState)
407             formState = std::make_unique<SavedFormState>();
408         formState->appendControlState(control->name(), control->type(), control->saveFormControlState());
409     }
410     return stateMap;
411 }
412
413 Vector<String> FormController::formElementsState() const
414 {
415     std::unique_ptr<SavedFormStateMap> stateMap = createSavedFormStateMap(m_formElementsWithState);
416     Vector<String> stateVector;
417     stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 4);
418     stateVector.append(formStateSignature());
419     for (SavedFormStateMap::const_iterator it = stateMap->begin(); it != stateMap->end(); ++it) {
420         stateVector.append(it->key.get());
421         it->value->serializeTo(stateVector);
422     }
423     bool hasOnlySignature = stateVector.size() == 1;
424     if (hasOnlySignature)
425         stateVector.clear();
426     return stateVector;
427 }
428
429 void FormController::setStateForNewFormElements(const Vector<String>& stateVector)
430 {
431     formStatesFromStateVector(stateVector, m_savedFormStateMap);
432 }
433
434 FormControlState FormController::takeStateForFormElement(const HTMLFormControlElementWithState& control)
435 {
436     if (m_savedFormStateMap.isEmpty())
437         return FormControlState();
438     if (!m_formKeyGenerator)
439         m_formKeyGenerator = std::make_unique<FormKeyGenerator>();
440     SavedFormStateMap::iterator it = m_savedFormStateMap.find(m_formKeyGenerator->formKey(control).impl());
441     if (it == m_savedFormStateMap.end())
442         return FormControlState();
443     FormControlState state = it->value->takeControlState(control.name(), control.type());
444     if (it->value->isEmpty())
445         m_savedFormStateMap.remove(it);
446     return state;
447 }
448
449 void FormController::formStatesFromStateVector(const Vector<String>& stateVector, SavedFormStateMap& map)
450 {
451     map.clear();
452
453     size_t i = 0;
454     if (stateVector.size() < 1 || stateVector[i++] != formStateSignature())
455         return;
456
457     while (i + 1 < stateVector.size()) {
458         AtomicString formKey = stateVector[i++];
459         auto state = SavedFormState::deserialize(stateVector, i);
460         if (!state) {
461             i = 0;
462             break;
463         }
464         map.add(formKey.impl(), WTF::move(state));
465     }
466     if (i != stateVector.size())
467         map.clear();
468 }
469
470 void FormController::willDeleteForm(HTMLFormElement* form)
471 {
472     if (m_formKeyGenerator)
473         m_formKeyGenerator->willDeleteForm(form);
474 }
475
476 void FormController::restoreControlStateFor(HTMLFormControlElementWithState& control)
477 {
478     // We don't save state of a control with shouldSaveAndRestoreFormControlState()
479     // == false. But we need to skip restoring process too because a control in
480     // another form might have the same pair of name and type and saved its state.
481     if (!control.shouldSaveAndRestoreFormControlState())
482         return;
483     if (ownerFormForState(control))
484         return;
485     FormControlState state = takeStateForFormElement(control);
486     if (state.valueSize() > 0)
487         control.restoreFormControlState(state);
488 }
489
490 void FormController::restoreControlStateIn(HTMLFormElement& form)
491 {
492     const Vector<FormAssociatedElement*>& elements = form.associatedElements();
493     for (size_t i = 0; i < elements.size(); ++i) {
494         if (!elements[i]->isFormControlElementWithState())
495             continue;
496         HTMLFormControlElementWithState* control = static_cast<HTMLFormControlElementWithState*>(elements[i]);
497         if (!control->shouldSaveAndRestoreFormControlState())
498             continue;
499         if (ownerFormForState(*control) != &form)
500             continue;
501         FormControlState state = takeStateForFormElement(*control);
502         if (state.valueSize() > 0)
503             control->restoreFormControlState(state);
504     }
505 }
506
507 Vector<String> FormController::getReferencedFilePaths(const Vector<String>& stateVector)
508 {
509     Vector<String> toReturn;
510     SavedFormStateMap map;
511     formStatesFromStateVector(stateVector, map);
512     for (SavedFormStateMap::const_iterator it = map.begin(), end = map.end(); it != end; ++it)
513         toReturn.appendVector(it->value->getReferencedFilePaths());
514     return toReturn;
515 }
516
517 void FormController::registerFormElementWithState(HTMLFormControlElementWithState* control)
518 {
519     ASSERT(!m_formElementsWithState.contains(control));
520     m_formElementsWithState.add(control);
521 }
522
523 void FormController::unregisterFormElementWithState(HTMLFormControlElementWithState* control)
524 {
525     ASSERT(m_formElementsWithState.contains(control));
526     m_formElementsWithState.remove(control);
527 }
528
529 } // namespace WebCore