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