[WTF] Add makeUnique<T>, which ensures T is fast-allocated, makeUnique / makeUniqueWi...
[WebKit-https.git] / Source / WebCore / html / FormController.cpp
1 /*
2  * Copyright (C) 2006-2017 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 "ScriptDisallowedScope.h"
27 #include <wtf/NeverDestroyed.h>
28 #include <wtf/text/StringBuilder.h>
29 #include <wtf/text/StringConcatenateNumbers.h>
30
31 namespace WebCore {
32
33 using namespace HTMLNames;
34
35 static inline HTMLFormElement* ownerFormForState(const HTMLFormControlElementWithState& control)
36 {
37     // Assume controls with form attribute have no owners because we restore
38     // state during parsing and form owners of such controls might be
39     // indeterminate.
40     return control.hasAttributeWithoutSynchronization(formAttr) ? 0 : control.form();
41 }
42
43 // ----------------------------------------------------------------------------
44
45 // Serilized form of FormControlState:
46 //  (',' means strings around it are separated in stateVector.)
47 //
48 // SerializedControlState ::= SkipState | RestoreState
49 // SkipState ::= '0'
50 // RestoreState ::= UnsignedNumber, ControlValue+
51 // UnsignedNumber ::= [0-9]+
52 // ControlValue ::= arbitrary string
53 //
54 // RestoreState has a sequence of ControlValues. The length of the
55 // sequence is represented by UnsignedNumber.
56
57 static inline void serializeFormControlStateTo(const FormControlState& formControlState, Vector<String>& stateVector)
58 {
59     stateVector.append(String::number(formControlState.size()));
60     for (auto& value : formControlState)
61         stateVector.append(value.isNull() ? emptyString() : value);
62 }
63
64 static inline Optional<FormControlState> deserializeFormControlState(const Vector<String>& stateVector, size_t& index)
65 {
66     if (index >= stateVector.size())
67         return WTF::nullopt;
68     size_t size = stateVector[index++].toUInt();
69     if (index + size > stateVector.size())
70         return WTF::nullopt;
71     Vector<String> subvector;
72     subvector.reserveInitialCapacity(size);
73     for (size_t i = 0; i < size; ++i)
74         subvector.uncheckedAppend(stateVector[index++]);
75     return subvector;
76 }
77
78 // ----------------------------------------------------------------------------
79
80 class FormElementKey {
81 public:
82     explicit FormElementKey(AtomStringImpl* = nullptr, AtomStringImpl* = nullptr);
83     ~FormElementKey();
84     FormElementKey(const FormElementKey&);
85     FormElementKey& operator=(const FormElementKey&);
86
87     AtomStringImpl* name() const { return m_name; }
88     AtomStringImpl* 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 AtomStringImpl* hashTableDeletedValue() { return reinterpret_cast<AtomStringImpl*>(-1); }
99
100     AtomStringImpl* m_name;
101     AtomStringImpl* m_type;
102 };
103
104 FormElementKey::FormElementKey(AtomStringImpl* name, AtomStringImpl* 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() = default;
177     static std::unique_ptr<SavedFormState> deserialize(const Vector<String>&, size_t& index);
178     void serializeTo(Vector<String>&) const;
179     bool isEmpty() const { return m_stateForNewFormElements.isEmpty(); }
180     void appendControlState(const AtomString& name, const AtomString& type, const FormControlState&);
181     FormControlState takeControlState(const AtomString& name, const AtomString& type);
182
183     Vector<String> referencedFilePaths() const;
184
185 private:
186     HashMap<FormElementKey, Deque<FormControlState>, FormElementKeyHash, FormElementKeyHashTraits> m_stateForNewFormElements;
187     size_t m_controlStateCount { 0 };
188 };
189
190 static bool isNotFormControlTypeCharacter(UChar ch)
191 {
192     return !(ch == '-' || isASCIILower(ch));
193 }
194
195 std::unique_ptr<SavedFormState> SavedFormState::deserialize(const Vector<String>& stateVector, size_t& index)
196 {
197     if (index >= stateVector.size())
198         return nullptr;
199     // FIXME: We need String::toSizeT().
200     size_t itemCount = stateVector[index++].toUInt();
201     if (!itemCount)
202         return nullptr;
203     auto savedFormState = makeUnique<SavedFormState>();
204     while (itemCount--) {
205         if (index + 1 >= stateVector.size())
206             return nullptr;
207         String name = stateVector[index++];
208         String type = stateVector[index++];
209         auto state = deserializeFormControlState(stateVector, index);
210         if (type.isEmpty() || type.find(isNotFormControlTypeCharacter) != notFound || !state)
211             return nullptr;
212         savedFormState->appendControlState(name, type, state.value());
213     }
214     return savedFormState;
215 }
216
217 void SavedFormState::serializeTo(Vector<String>& stateVector) const
218 {
219     stateVector.append(String::number(m_controlStateCount));
220     for (auto& element : m_stateForNewFormElements) {
221         const FormElementKey& key = element.key;
222         for (auto& controlState : element.value) {
223             stateVector.append(key.name());
224             stateVector.append(key.type());
225             serializeFormControlStateTo(controlState, stateVector);
226         }
227     }
228 }
229
230 void SavedFormState::appendControlState(const AtomString& name, const AtomString& type, const FormControlState& state)
231 {
232     m_stateForNewFormElements.add(FormElementKey { name.impl(), type.impl() }, Deque<FormControlState> { }).iterator->value.append(state);
233     ++m_controlStateCount;
234 }
235
236 FormControlState SavedFormState::takeControlState(const AtomString& name, const AtomString& type)
237 {
238     auto iterator = m_stateForNewFormElements.find(FormElementKey { name.impl(), type.impl() });
239     if (iterator == m_stateForNewFormElements.end())
240         return { };
241
242     auto state = iterator->value.takeFirst();
243     --m_controlStateCount;
244     if (iterator->value.isEmpty())
245         m_stateForNewFormElements.remove(iterator);
246     return state;
247 }
248
249 Vector<String> SavedFormState::referencedFilePaths() const
250 {
251     Vector<String> toReturn;
252     for (auto& element : m_stateForNewFormElements) {
253         if (!equal(element.key.type(), "file", 4))
254             continue;
255         for (auto& state : element.value) {
256             for (auto& file : HTMLInputElement::filesFromFileInputFormControlState(state))
257                 toReturn.append(file.path);
258         }
259     }
260     return toReturn;
261 }
262
263 // ----------------------------------------------------------------------------
264
265 class FormKeyGenerator {
266     WTF_MAKE_NONCOPYABLE(FormKeyGenerator);
267     WTF_MAKE_FAST_ALLOCATED;
268
269 public:
270     FormKeyGenerator() = default;
271     AtomString formKey(const HTMLFormControlElementWithState&);
272     void willDeleteForm(HTMLFormElement*);
273
274 private:
275     typedef HashMap<HTMLFormElement*, AtomString> FormToKeyMap;
276     typedef HashMap<String, unsigned> FormSignatureToNextIndexMap;
277     FormToKeyMap m_formToKeyMap;
278     FormSignatureToNextIndexMap m_formSignatureToNextIndexMap;
279 };
280
281 static inline void recordFormStructure(const HTMLFormElement& form, StringBuilder& builder)
282 {
283     ScriptDisallowedScope::InMainThread scriptDisallowedScope;
284     // 2 is enough to distinguish forms in webkit.org/b/91209#c0
285     const size_t namedControlsToBeRecorded = 2;
286     auto& controls = form.unsafeAssociatedElements();
287     builder.appendLiteral(" [");
288     for (size_t i = 0, namedControls = 0; i < controls.size() && namedControls < namedControlsToBeRecorded; ++i) {
289         if (!controls[i]->isFormControlElementWithState())
290             continue;
291         RefPtr<HTMLFormControlElementWithState> control = static_cast<HTMLFormControlElementWithState*>(controls[i]);
292         if (!ownerFormForState(*control))
293             continue;
294         AtomString name = control->name();
295         if (name.isEmpty())
296             continue;
297         namedControls++;
298         builder.append(name);
299         builder.append(' ');
300     }
301     builder.append(']');
302 }
303
304 static inline String formSignature(const HTMLFormElement& form)
305 {
306     URL actionURL = form.getURLAttribute(actionAttr);
307     // Remove the query part because it might contain volatile parameters such
308     // as a session key.
309     actionURL.setQuery(String());
310     StringBuilder builder;
311     if (!actionURL.isEmpty())
312         builder.append(actionURL.string());
313
314     recordFormStructure(form, builder);
315     return builder.toString();
316 }
317
318 AtomString FormKeyGenerator::formKey(const HTMLFormControlElementWithState& control)
319 {
320     auto form = makeRefPtr(ownerFormForState(control));
321     if (!form) {
322         static NeverDestroyed<AtomString> formKeyForNoOwner("No owner", AtomString::ConstructFromLiteral);
323         return formKeyForNoOwner;
324     }
325
326     return m_formToKeyMap.ensure(form.get(), [this, &form] {
327         auto signature = formSignature(*form);
328         auto nextIndex = m_formSignatureToNextIndexMap.add(signature, 0).iterator->value++;
329         // FIXME: Would be nice to have makeAtomString to use to optimize the case where the string already exists.
330         return makeString(signature, " #", nextIndex);
331     }).iterator->value;
332 }
333
334 void FormKeyGenerator::willDeleteForm(HTMLFormElement* form)
335 {
336     ASSERT(form);
337     m_formToKeyMap.remove(form);
338 }
339
340 // ----------------------------------------------------------------------------
341
342 FormController::FormController() = default;
343
344 FormController::~FormController() = default;
345
346 unsigned FormController::formElementsCharacterCount() const
347 {
348     unsigned count = 0;
349     for (auto& element : m_formElementsWithState) {
350         if (element->isTextField())
351             count += element->saveFormControlState()[0].length();
352     }
353     return count;
354 }
355
356 static String formStateSignature()
357 {
358     // In the legacy version of serialized state, the first item was a name
359     // attribute value of a form control. The following string literal should
360     // contain some characters which are rarely used for name attribute values.
361     static NeverDestroyed<String> signature(MAKE_STATIC_STRING_IMPL("\n\r?% WebKit serialized form state version 8 \n\r=&"));
362     return signature;
363 }
364
365 std::unique_ptr<FormController::SavedFormStateMap> FormController::createSavedFormStateMap(const FormElementListHashSet& controlList)
366 {
367     FormKeyGenerator keyGenerator;
368     auto stateMap = makeUnique<SavedFormStateMap>();
369     for (auto& control : controlList) {
370         if (!control->shouldSaveAndRestoreFormControlState())
371             continue;
372         auto& formState = stateMap->add(keyGenerator.formKey(*control).impl(), nullptr).iterator->value;
373         if (!formState)
374             formState = makeUnique<SavedFormState>();
375         formState->appendControlState(control->name(), control->type(), control->saveFormControlState());
376     }
377     return stateMap;
378 }
379
380 Vector<String> FormController::formElementsState() const
381 {
382     std::unique_ptr<SavedFormStateMap> stateMap = createSavedFormStateMap(m_formElementsWithState);
383     Vector<String> stateVector;
384     stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 4);
385     stateVector.append(formStateSignature());
386     for (auto& state : *stateMap) {
387         stateVector.append(state.key.get());
388         state.value->serializeTo(stateVector);
389     }
390     bool hasOnlySignature = stateVector.size() == 1;
391     if (hasOnlySignature)
392         stateVector.clear();
393     return stateVector;
394 }
395
396 void FormController::setStateForNewFormElements(const Vector<String>& stateVector)
397 {
398     formStatesFromStateVector(stateVector, m_savedFormStateMap);
399 }
400
401 FormControlState FormController::takeStateForFormElement(const HTMLFormControlElementWithState& control)
402 {
403     if (m_savedFormStateMap.isEmpty())
404         return FormControlState();
405     if (!m_formKeyGenerator)
406         m_formKeyGenerator = makeUnique<FormKeyGenerator>();
407     SavedFormStateMap::iterator it = m_savedFormStateMap.find(m_formKeyGenerator->formKey(control).impl());
408     if (it == m_savedFormStateMap.end())
409         return FormControlState();
410     FormControlState state = it->value->takeControlState(control.name(), control.type());
411     if (it->value->isEmpty())
412         m_savedFormStateMap.remove(it);
413     return state;
414 }
415
416 void FormController::formStatesFromStateVector(const Vector<String>& stateVector, SavedFormStateMap& map)
417 {
418     map.clear();
419
420     size_t i = 0;
421     if (stateVector.size() < 1 || stateVector[i++] != formStateSignature())
422         return;
423
424     while (i + 1 < stateVector.size()) {
425         AtomString formKey = stateVector[i++];
426         auto state = SavedFormState::deserialize(stateVector, i);
427         if (!state) {
428             i = 0;
429             break;
430         }
431         map.add(formKey.impl(), WTFMove(state));
432     }
433     if (i != stateVector.size())
434         map.clear();
435 }
436
437 void FormController::willDeleteForm(HTMLFormElement& form)
438 {
439     if (m_formKeyGenerator)
440         m_formKeyGenerator->willDeleteForm(&form);
441 }
442
443 void FormController::restoreControlStateFor(HTMLFormControlElementWithState& control)
444 {
445     // We don't save state of a control with shouldSaveAndRestoreFormControlState()
446     // == false. But we need to skip restoring process too because a control in
447     // another form might have the same pair of name and type and saved its state.
448     if (!control.shouldSaveAndRestoreFormControlState())
449         return;
450     if (ownerFormForState(control))
451         return;
452     auto state = takeStateForFormElement(control);
453     if (!state.isEmpty())
454         control.restoreFormControlState(state);
455 }
456
457 void FormController::restoreControlStateIn(HTMLFormElement& form)
458 {
459     for (auto& element : form.copyAssociatedElementsVector()) {
460         if (!is<HTMLFormControlElementWithState>(element.get()))
461             continue;
462         auto& control = downcast<HTMLFormControlElementWithState>(element.get());
463         if (!control.shouldSaveAndRestoreFormControlState())
464             continue;
465         if (ownerFormForState(control) != &form)
466             continue;
467         auto state = takeStateForFormElement(control);
468         if (!state.isEmpty())
469             control.restoreFormControlState(state);
470     }
471 }
472
473 bool FormController::hasFormStateToRestore() const
474 {
475     return !m_savedFormStateMap.isEmpty();
476 }
477
478 Vector<String> FormController::referencedFilePaths(const Vector<String>& stateVector)
479 {
480     Vector<String> paths;
481     SavedFormStateMap map;
482     formStatesFromStateVector(stateVector, map);
483     for (auto& state : map.values())
484         paths.appendVector(state->referencedFilePaths());
485     return paths;
486 }
487
488 void FormController::registerFormElementWithState(HTMLFormControlElementWithState& control)
489 {
490     ASSERT(!m_formElementsWithState.contains(&control));
491     m_formElementsWithState.add(&control);
492 }
493
494 void FormController::unregisterFormElementWithState(HTMLFormControlElementWithState& control)
495 {
496     ASSERT(m_formElementsWithState.contains(&control));
497     m_formElementsWithState.remove(&control);
498 }
499
500 } // namespace WebCore