Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: Source/core/html/FormController.cpp

Issue 24246011: Move form-related 78 files to core/html/forms/. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/html/FormController.h ('k') | Source/core/html/HTMLFormControlElement.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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/FormController.h"
23
24 #include "core/html/HTMLFormControlElementWithState.h"
25 #include "core/html/HTMLFormElement.h"
26 #include "core/html/HTMLInputElement.h"
27 #include "core/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 HTMLFormControlElementWit hState& 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(hashTableDeletedValu e()) { }
96 bool isHashTableDeletedValue() const { return m_name == hashTableDeletedValu e(); }
97
98 private:
99 void ref() const;
100 void deref() const;
101
102 static StringImpl* hashTableDeletedValue() { return reinterpret_cast<StringI mpl*>(-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, &slo t) FormElementKey(WTF::HashTableDeletedValue); }
170 static bool isDeletedValue(const FormElementKey& value) { return value.isHas hTableDeletedValue(); }
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 AtomicStri ng& 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>& sta teVector, 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, inde x);
222 if (type.isEmpty() || type.find(isNotFormControlTypeCharacter) != kNotFo und || state.isFailure())
223 return nullptr;
224 savedFormState->appendControlState(name, 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.begi n(); 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 AtomicSt ring& 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, cons t AtomicString& type)
258 {
259 if (m_stateForNewFormElements.isEmpty())
260 return FormControlState();
261 FormElementStateMap::iterator it = m_stateForNewFormElements.find(FormElemen tKey(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.begi n(); 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 {
292 WTF_MAKE_NONCOPYABLE(FormKeyGenerator);
293 WTF_MAKE_FAST_ALLOCATED;
294
295 public:
296 static PassOwnPtr<FormKeyGenerator> create() { return adoptPtr(new FormKeyGe nerator); }
297 AtomicString formKey(const HTMLFormControlElementWithState&);
298 void willDeleteForm(HTMLFormElement*);
299
300 private:
301 FormKeyGenerator() { }
302
303 typedef HashMap<HTMLFormElement*, AtomicString> FormToKeyMap;
304 typedef HashMap<String, unsigned> FormSignatureToNextIndexMap;
305 FormToKeyMap m_formToKeyMap;
306 FormSignatureToNextIndexMap m_formSignatureToNextIndexMap;
307 };
308
309 static inline void recordFormStructure(const HTMLFormElement& form, StringBuilde r& builder)
310 {
311 // 2 is enough to distinguish forms in webkit.org/b/91209#c0
312 const size_t namedControlsToBeRecorded = 2;
313 const Vector<FormAssociatedElement*>& controls = form.associatedElements();
314 builder.append(" [");
315 for (size_t i = 0, namedControls = 0; i < controls.size() && namedControls < namedControlsToBeRecorded; ++i) {
316 if (!controls[i]->isFormControlElementWithState())
317 continue;
318 HTMLFormControlElementWithState* control = toHTMLFormControlElementWithS tate(controls[i]);
319 if (!ownerFormForState(*control))
320 continue;
321 AtomicString name = control->name();
322 if (name.isEmpty())
323 continue;
324 namedControls++;
325 builder.append(name);
326 builder.append(" ");
327 }
328 builder.append("]");
329 }
330
331 static inline String formSignature(const HTMLFormElement& form)
332 {
333 KURL actionURL = form.getURLAttribute(actionAttr);
334 // Remove the query part because it might contain volatile parameters such
335 // as a session key.
336 actionURL.setQuery(String());
337 StringBuilder builder;
338 if (!actionURL.isEmpty())
339 builder.append(actionURL.string());
340
341 recordFormStructure(form, builder);
342 return builder.toString();
343 }
344
345 AtomicString FormKeyGenerator::formKey(const HTMLFormControlElementWithState& co ntrol)
346 {
347 HTMLFormElement* form = ownerFormForState(control);
348 if (!form) {
349 DEFINE_STATIC_LOCAL(AtomicString, formKeyForNoOwner, ("No owner", Atomic String::ConstructFromLiteral));
350 return formKeyForNoOwner;
351 }
352 FormToKeyMap::const_iterator it = m_formToKeyMap.find(form);
353 if (it != m_formToKeyMap.end())
354 return it->value;
355
356 String signature = formSignature(*form);
357 ASSERT(!signature.isNull());
358 FormSignatureToNextIndexMap::AddResult result = m_formSignatureToNextIndexMa p.add(signature, 0);
359 unsigned nextIndex = result.iterator->value++;
360
361 StringBuilder builder;
362 builder.append(signature);
363 builder.appendLiteral(" #");
364 builder.appendNumber(nextIndex);
365 AtomicString formKey = builder.toAtomicString();
366 m_formToKeyMap.add(form, formKey);
367 return formKey;
368 }
369
370 void FormKeyGenerator::willDeleteForm(HTMLFormElement* form)
371 {
372 ASSERT(form);
373 m_formToKeyMap.remove(form);
374 }
375
376 // ----------------------------------------------------------------------------
377
378 FormController::FormController()
379 {
380 }
381
382 FormController::~FormController()
383 {
384 }
385
386 static String formStateSignature()
387 {
388 // In the legacy version of serialized state, the first item was a name
389 // attribute value of a form control. The following string literal should
390 // contain some characters which are rarely used for name attribute values.
391 DEFINE_STATIC_LOCAL(String, signature, ("\n\r?% WebKit serialized form state version 8 \n\r=&"));
392 return signature;
393 }
394
395 PassOwnPtr<FormController::SavedFormStateMap> FormController::createSavedFormSta teMap(const FormElementListHashSet& controlList)
396 {
397 OwnPtr<FormKeyGenerator> keyGenerator = FormKeyGenerator::create();
398 OwnPtr<SavedFormStateMap> stateMap = adoptPtr(new SavedFormStateMap);
399 for (FormElementListHashSet::const_iterator it = controlList.begin(); it != controlList.end(); ++it) {
400 HTMLFormControlElementWithState* control = (*it).get();
401 ASSERT(control->inDocument());
402 if (!control->shouldSaveAndRestoreFormControlState())
403 continue;
404 SavedFormStateMap::AddResult result = stateMap->add(keyGenerator->formKe y(*control).impl(), nullptr);
405 if (result.isNewEntry)
406 result.iterator->value = SavedFormState::create();
407 result.iterator->value->appendControlState(control->name(), control->typ e(), control->saveFormControlState());
408 }
409 return stateMap.release();
410 }
411
412 Vector<String> FormController::formElementsState() const
413 {
414 OwnPtr<SavedFormStateMap> stateMap = createSavedFormStateMap(m_formElementsW ithState);
415 Vector<String> stateVector;
416 stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 4);
417 stateVector.append(formStateSignature());
418 for (SavedFormStateMap::const_iterator it = stateMap->begin(); it != stateMa p->end(); ++it) {
419 stateVector.append(it->key);
420 it->value->serializeTo(stateVector);
421 }
422 bool hasOnlySignature = stateVector.size() == 1;
423 if (hasOnlySignature)
424 stateVector.clear();
425 return stateVector;
426 }
427
428 void FormController::setStateForNewFormElements(const Vector<String>& stateVecto r)
429 {
430 formStatesFromStateVector(stateVector, m_savedFormStateMap);
431 }
432
433 FormControlState FormController::takeStateForFormElement(const HTMLFormControlEl ementWithState& control)
434 {
435 if (m_savedFormStateMap.isEmpty())
436 return FormControlState();
437 if (!m_formKeyGenerator)
438 m_formKeyGenerator = FormKeyGenerator::create();
439 SavedFormStateMap::iterator it = m_savedFormStateMap.find(m_formKeyGenerator ->formKey(control).impl());
440 if (it == m_savedFormStateMap.end())
441 return FormControlState();
442 FormControlState state = it->value->takeControlState(control.name(), control .type());
443 if (it->value->isEmpty())
444 m_savedFormStateMap.remove(it);
445 return state;
446 }
447
448 void FormController::formStatesFromStateVector(const Vector<String>& stateVector , SavedFormStateMap& map)
449 {
450 map.clear();
451
452 size_t i = 0;
453 if (stateVector.size() < 1 || stateVector[i++] != formStateSignature())
454 return;
455
456 while (i + 1 < stateVector.size()) {
457 AtomicString formKey = stateVector[i++];
458 OwnPtr<SavedFormState> state = SavedFormState::deserialize(stateVector, i);
459 if (!state) {
460 i = 0;
461 break;
462 }
463 map.add(formKey.impl(), state.release());
464 }
465 if (i != stateVector.size())
466 map.clear();
467 }
468
469 void FormController::willDeleteForm(HTMLFormElement* form)
470 {
471 if (m_formKeyGenerator)
472 m_formKeyGenerator->willDeleteForm(form);
473 }
474
475 void FormController::restoreControlStateFor(HTMLFormControlElementWithState& con trol)
476 {
477 // We don't save state of a control with shouldSaveAndRestoreFormControlStat e()
478 // == false. But we need to skip restoring process too because a control in
479 // another form might have the same pair of name and type and saved its stat e.
480 if (!control.shouldSaveAndRestoreFormControlState())
481 return;
482 if (ownerFormForState(control))
483 return;
484 FormControlState state = takeStateForFormElement(control);
485 if (state.valueSize() > 0)
486 control.restoreFormControlState(state);
487 }
488
489 void FormController::restoreControlStateIn(HTMLFormElement& form)
490 {
491 const Vector<FormAssociatedElement*>& elements = form.associatedElements();
492 for (size_t i = 0; i < elements.size(); ++i) {
493 if (!elements[i]->isFormControlElementWithState())
494 continue;
495 HTMLFormControlElementWithState* control = toHTMLFormControlElementWithS tate(elements[i]);
496 if (!control->shouldSaveAndRestoreFormControlState())
497 continue;
498 if (ownerFormForState(*control) != &form)
499 continue;
500 FormControlState state = takeStateForFormElement(*control);
501 if (state.valueSize() > 0)
502 control->restoreFormControlState(state);
503 }
504 }
505
506 Vector<String> FormController::getReferencedFilePaths(const Vector<String>& stat eVector)
507 {
508 Vector<String> toReturn;
509 SavedFormStateMap map;
510 formStatesFromStateVector(stateVector, map);
511 for (SavedFormStateMap::const_iterator it = map.begin(); it != map.end(); ++ it)
512 toReturn.append(it->value->getReferencedFilePaths());
513 return toReturn;
514 }
515
516 void FormController::registerFormElementWithState(HTMLFormControlElementWithStat e* control)
517 {
518 ASSERT(!m_formElementsWithState.contains(control));
519 m_formElementsWithState.add(control);
520 }
521
522 void FormController::unregisterFormElementWithState(HTMLFormControlElementWithSt ate* control)
523 {
524 RELEASE_ASSERT(m_formElementsWithState.contains(control));
525 m_formElementsWithState.remove(control);
526 }
527
528 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/html/FormController.h ('k') | Source/core/html/HTMLFormControlElement.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698