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