2 * Copyright (C) 2006, 2008, 2009, 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2010, 2011, 2012 Google Inc. All rights reserved.
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.
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.
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.
22 #include "core/html/forms/FormController.h"
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"
34 using namespace HTMLNames;
36 static inline HTMLFormElement* ownerFormForState(const HTMLFormControlElementWithState& control)
38 // Assume controls with form attribute have no owners because we restore
39 // state during parsing and form owners of such controls might be
41 return control.fastHasAttribute(formAttr) ? 0 : control.form();
44 // ----------------------------------------------------------------------------
46 // Serilized form of FormControlState:
47 // (',' means strings around it are separated in stateVector.)
49 // SerializedControlState ::= SkipState | RestoreState
51 // RestoreState ::= UnsignedNumber, ControlValue+
52 // UnsignedNumber ::= [0-9]+
53 // ControlValue ::= arbitrary string
55 // RestoreState has a sequence of ControlValues. The length of the
56 // sequence is represented by UnsignedNumber.
58 void FormControlState::serializeTo(Vector<String>& stateVector) const
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]);
66 FormControlState FormControlState::deserialize(const Vector<String>& stateVector, size_t& index)
68 if (index >= stateVector.size())
69 return FormControlState(TypeFailure);
70 size_t valueSize = stateVector[index++].toUInt();
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++]);
82 // ----------------------------------------------------------------------------
84 class FormElementKey {
86 FormElementKey(StringImpl* = 0, StringImpl* = 0);
88 FormElementKey(const FormElementKey&);
89 FormElementKey& operator=(const FormElementKey&);
91 StringImpl* name() const { return m_name; }
92 StringImpl* type() const { return m_type; }
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(); }
102 static StringImpl* hashTableDeletedValue() { return reinterpret_cast<StringImpl*>(-1); }
108 FormElementKey::FormElementKey(StringImpl* name, StringImpl* type)
115 FormElementKey::~FormElementKey()
120 FormElementKey::FormElementKey(const FormElementKey& other)
121 : m_name(other.name())
122 , m_type(other.type())
127 FormElementKey& FormElementKey::operator=(const FormElementKey& other)
131 m_name = other.name();
132 m_type = other.type();
136 void FormElementKey::ref() const
144 void FormElementKey::deref() const
152 inline bool operator==(const FormElementKey& a, const FormElementKey& b)
154 return a.name() == b.name() && a.type() == b.type();
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;
163 unsigned FormElementKeyHash::hash(const FormElementKey& key)
165 return StringHasher::hashMemory<sizeof(FormElementKey)>(&key);
168 struct FormElementKeyHashTraits : WTF::GenericHashTraits<FormElementKey> {
169 static void constructDeletedValue(FormElementKey& slot, bool) { new (NotNull, &slot) FormElementKey(WTF::HashTableDeletedValue); }
170 static bool isDeletedValue(const FormElementKey& value) { return value.isHashTableDeletedValue(); }
173 // ----------------------------------------------------------------------------
175 class SavedFormState {
176 WTF_MAKE_NONCOPYABLE(SavedFormState);
177 WTF_MAKE_FAST_ALLOCATED;
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);
187 Vector<String> getReferencedFilePaths() const;
190 SavedFormState() : m_controlStateCount(0) { }
192 typedef HashMap<FormElementKey, Deque<FormControlState>, FormElementKeyHash, FormElementKeyHashTraits> FormElementStateMap;
193 FormElementStateMap m_stateForNewFormElements;
194 size_t m_controlStateCount;
197 PassOwnPtr<SavedFormState> SavedFormState::create()
199 return adoptPtr(new SavedFormState);
202 static bool isNotFormControlTypeCharacter(UChar ch)
204 return ch != '-' && (ch > 'z' || ch < 'a');
207 PassOwnPtr<SavedFormState> SavedFormState::deserialize(const Vector<String>& stateVector, size_t& index)
209 if (index >= stateVector.size())
211 // FIXME: We need String::toSizeT().
212 size_t itemCount = stateVector[index++].toUInt();
215 OwnPtr<SavedFormState> savedFormState = adoptPtr(new SavedFormState);
216 while (itemCount--) {
217 if (index + 1 >= stateVector.size())
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())
224 savedFormState->appendControlState(AtomicString(name), AtomicString(type), state);
226 return savedFormState.release();
229 void SavedFormState::serializeTo(Vector<String>& stateVector) const
231 stateVector.append(String::number(m_controlStateCount));
232 for (const auto& formControl : m_stateForNewFormElements) {
233 const FormElementKey& key = formControl.key;
234 const Deque<FormControlState>& queue = formControl.value;
235 for (const FormControlState& formControlState : queue) {
236 stateVector.append(key.name());
237 stateVector.append(key.type());
238 formControlState.serializeTo(stateVector);
243 void SavedFormState::appendControlState(const AtomicString& name, const AtomicString& type, const FormControlState& state)
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);
250 Deque<FormControlState> stateList;
251 stateList.append(state);
252 m_stateForNewFormElements.set(key, stateList);
254 m_controlStateCount++;
257 FormControlState SavedFormState::takeControlState(const AtomicString& name, const AtomicString& type)
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);
272 Vector<String> SavedFormState::getReferencedFilePaths() const
274 Vector<String> toReturn;
275 for (const auto& formControl : m_stateForNewFormElements) {
276 const FormElementKey& key = formControl.key;
277 if (!equal(key.type(), "file", 4))
279 const Deque<FormControlState>& queue = formControl.value;
280 for (const FormControlState& formControlState : queue) {
281 const Vector<FileChooserFileInfo>& selectedFiles = HTMLInputElement::filesFromFileInputFormControlState(formControlState);
282 for (size_t i = 0; i < selectedFiles.size(); ++i)
283 toReturn.append(selectedFiles[i].path);
289 // ----------------------------------------------------------------------------
291 class FormKeyGenerator final : public NoBaseWillBeGarbageCollectedFinalized<FormKeyGenerator> {
292 WTF_MAKE_NONCOPYABLE(FormKeyGenerator);
293 WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED;
296 static PassOwnPtrWillBeRawPtr<FormKeyGenerator> create() { return adoptPtrWillBeNoop(new FormKeyGenerator); }
297 void trace(Visitor* visitor)
300 visitor->trace(m_formToKeyMap);
303 const AtomicString& formKey(const HTMLFormControlElementWithState&);
304 void willDeleteForm(HTMLFormElement*);
307 FormKeyGenerator() { }
309 typedef WillBeHeapHashMap<RawPtrWillBeMember<HTMLFormElement>, AtomicString> FormToKeyMap;
310 typedef HashMap<String, unsigned> FormSignatureToNextIndexMap;
311 FormToKeyMap m_formToKeyMap;
312 FormSignatureToNextIndexMap m_formSignatureToNextIndexMap;
315 static inline void recordFormStructure(const HTMLFormElement& form, StringBuilder& builder)
317 // 2 is enough to distinguish forms in webkit.org/b/91209#c0
318 const size_t namedControlsToBeRecorded = 2;
319 const FormAssociatedElement::List& controls = form.associatedElements();
320 builder.appendLiteral(" [");
321 for (size_t i = 0, namedControls = 0; i < controls.size() && namedControls < namedControlsToBeRecorded; ++i) {
322 if (!controls[i]->isFormControlElementWithState())
324 HTMLFormControlElementWithState* control = toHTMLFormControlElementWithState(controls[i]);
325 if (!ownerFormForState(*control))
327 AtomicString name = control->name();
331 builder.append(name);
337 static inline String formSignature(const HTMLFormElement& form)
339 KURL actionURL = form.getURLAttribute(actionAttr);
340 // Remove the query part because it might contain volatile parameters such
342 if (!actionURL.isEmpty())
343 actionURL.setQuery(String());
345 StringBuilder builder;
346 if (!actionURL.isEmpty())
347 builder.append(actionURL.string());
349 recordFormStructure(form, builder);
350 return builder.toString();
353 const AtomicString& FormKeyGenerator::formKey(const HTMLFormControlElementWithState& control)
355 HTMLFormElement* form = ownerFormForState(control);
357 DEFINE_STATIC_LOCAL(const AtomicString, formKeyForNoOwner, ("No owner", AtomicString::ConstructFromLiteral));
358 return formKeyForNoOwner;
360 FormToKeyMap::const_iterator it = m_formToKeyMap.find(form);
361 if (it != m_formToKeyMap.end())
364 String signature = formSignature(*form);
365 ASSERT(!signature.isNull());
366 FormSignatureToNextIndexMap::AddResult result = m_formSignatureToNextIndexMap.add(signature, 0);
367 unsigned nextIndex = result.storedValue->value++;
369 StringBuilder formKeyBuilder;
370 formKeyBuilder.append(signature);
371 formKeyBuilder.appendLiteral(" #");
372 formKeyBuilder.appendNumber(nextIndex);
373 FormToKeyMap::AddResult addFormKeyresult = m_formToKeyMap.add(form, formKeyBuilder.toAtomicString());
374 return addFormKeyresult.storedValue->value;
377 void FormKeyGenerator::willDeleteForm(HTMLFormElement* form)
380 m_formToKeyMap.remove(form);
383 // ----------------------------------------------------------------------------
385 PassRefPtrWillBeRawPtr<DocumentState> DocumentState::create()
387 return adoptRefWillBeNoop(new DocumentState);
390 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(DocumentState)
392 void DocumentState::trace(Visitor* visitor)
395 visitor->trace(m_formControls);
399 void DocumentState::addControl(HTMLFormControlElementWithState* control)
401 ASSERT(!m_formControls.contains(control));
402 m_formControls.add(control);
405 void DocumentState::removeControl(HTMLFormControlElementWithState* control)
407 RELEASE_ASSERT(m_formControls.contains(control));
408 m_formControls.remove(control);
411 static String formStateSignature()
413 // In the legacy version of serialized state, the first item was a name
414 // attribute value of a form control. The following string literal should
415 // contain some characters which are rarely used for name attribute values.
416 DEFINE_STATIC_LOCAL(String, signature, ("\n\r?% Blink serialized form state version 9 \n\r=&"));
420 Vector<String> DocumentState::toStateVector()
422 OwnPtrWillBeRawPtr<FormKeyGenerator> keyGenerator = FormKeyGenerator::create();
423 OwnPtr<SavedFormStateMap> stateMap = adoptPtr(new SavedFormStateMap);
424 for (const auto& formControl : m_formControls) {
425 HTMLFormControlElementWithState* control = formControl.get();
426 ASSERT(control->inDocument());
427 if (!control->shouldSaveAndRestoreFormControlState())
429 SavedFormStateMap::AddResult result = stateMap->add(keyGenerator->formKey(*control), nullptr);
430 if (result.isNewEntry)
431 result.storedValue->value = SavedFormState::create();
432 result.storedValue->value->appendControlState(control->name(), control->type(), control->saveFormControlState());
435 Vector<String> stateVector;
436 stateVector.reserveInitialCapacity(m_formControls.size() * 4);
437 stateVector.append(formStateSignature());
438 for (const auto& savedFormState : *stateMap) {
439 stateVector.append(savedFormState.key);
440 savedFormState.value->serializeTo(stateVector);
442 bool hasOnlySignature = stateVector.size() == 1;
443 if (hasOnlySignature)
448 // ----------------------------------------------------------------------------
450 FormController::FormController()
451 : m_documentState(DocumentState::create())
455 FormController::~FormController()
459 void FormController::trace(Visitor* visitor)
461 visitor->trace(m_radioButtonGroupScope);
462 visitor->trace(m_documentState);
463 visitor->trace(m_formKeyGenerator);
466 DocumentState* FormController::formElementsState() const
468 return m_documentState.get();
471 void FormController::setStateForNewFormElements(const Vector<String>& stateVector)
473 formStatesFromStateVector(stateVector, m_savedFormStateMap);
476 FormControlState FormController::takeStateForFormElement(const HTMLFormControlElementWithState& control)
478 if (m_savedFormStateMap.isEmpty())
479 return FormControlState();
480 if (!m_formKeyGenerator)
481 m_formKeyGenerator = FormKeyGenerator::create();
482 SavedFormStateMap::iterator it = m_savedFormStateMap.find(m_formKeyGenerator->formKey(control));
483 if (it == m_savedFormStateMap.end())
484 return FormControlState();
485 FormControlState state = it->value->takeControlState(control.name(), control.type());
486 if (it->value->isEmpty())
487 m_savedFormStateMap.remove(it);
491 void FormController::formStatesFromStateVector(const Vector<String>& stateVector, SavedFormStateMap& map)
496 if (stateVector.size() < 1 || stateVector[i++] != formStateSignature())
499 while (i + 1 < stateVector.size()) {
500 AtomicString formKey = AtomicString(stateVector[i++]);
501 OwnPtr<SavedFormState> state = SavedFormState::deserialize(stateVector, i);
506 map.add(formKey, state.release());
508 if (i != stateVector.size())
512 void FormController::willDeleteForm(HTMLFormElement* form)
514 if (m_formKeyGenerator)
515 m_formKeyGenerator->willDeleteForm(form);
518 void FormController::restoreControlStateFor(HTMLFormControlElementWithState& control)
520 // We don't save state of a control with shouldSaveAndRestoreFormControlState()
521 // == false. But we need to skip restoring process too because a control in
522 // another form might have the same pair of name and type and saved its state.
523 if (!control.shouldSaveAndRestoreFormControlState())
525 if (ownerFormForState(control))
527 FormControlState state = takeStateForFormElement(control);
528 if (state.valueSize() > 0)
529 control.restoreFormControlState(state);
532 void FormController::restoreControlStateIn(HTMLFormElement& form)
534 const FormAssociatedElement::List& elements = form.associatedElements();
535 for (const auto& element : elements) {
536 if (!element->isFormControlElementWithState())
538 HTMLFormControlElementWithState* control = toHTMLFormControlElementWithState(element);
539 if (!control->shouldSaveAndRestoreFormControlState())
541 if (ownerFormForState(*control) != &form)
543 FormControlState state = takeStateForFormElement(*control);
544 if (state.valueSize() > 0)
545 control->restoreFormControlState(state);
549 Vector<String> FormController::getReferencedFilePaths(const Vector<String>& stateVector)
551 Vector<String> toReturn;
552 SavedFormStateMap map;
553 formStatesFromStateVector(stateVector, map);
554 for (const auto& savedFormState : map)
555 toReturn.appendVector(savedFormState.value->getReferencedFilePaths());
559 void FormController::registerStatefulFormControl(HTMLFormControlElementWithState& control)
561 m_documentState->addControl(&control);
564 void FormController::unregisterStatefulFormControl(HTMLFormControlElementWithState& control)
566 m_documentState->removeControl(&control);