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 "third_party/blink/renderer/core/html/forms/form_controller.h"
22
23 #include <memory>
24 #include <utility>
25
26 #include "base/macros.h"
27 #include "base/memory/ptr_util.h"
28 #include "third_party/blink/renderer/core/dom/document.h"
29 #include "third_party/blink/renderer/core/dom/element_traversal.h"
30 #include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
31 #include "third_party/blink/renderer/core/html/custom/custom_element.h"
32 #include "third_party/blink/renderer/core/html/custom/element_internals.h"
33 #include "third_party/blink/renderer/core/html/forms/file_chooser.h"
34 #include "third_party/blink/renderer/core/html/forms/html_form_element.h"
35 #include "third_party/blink/renderer/core/html/forms/html_input_element.h"
36 #include "third_party/blink/renderer/core/html/forms/listed_element.h"
37 #include "third_party/blink/renderer/platform/wtf/deque.h"
38 #include "third_party/blink/renderer/platform/wtf/hash_table_deleted_value_type.h"
39 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
40
41 namespace blink {
42
43 namespace {
44
OwnerFormForState(const ListedElement & control)45 inline HTMLFormElement* OwnerFormForState(const ListedElement& control) {
46 // Assume controls with form attribute have no owners because we restore
47 // state during parsing and form owners of such controls might be
48 // indeterminate.
49 return control.ToHTMLElement().FastHasAttribute(html_names::kFormAttr)
50 ? nullptr
51 : control.Form();
52 }
53
ControlType(const ListedElement & control)54 const AtomicString& ControlType(const ListedElement& control) {
55 if (auto* control_element = DynamicTo<HTMLFormControlElement>(control))
56 return control_element->type();
57 return To<ElementInternals>(control).Target().localName();
58 }
59
IsDirtyControl(const ListedElement & control)60 bool IsDirtyControl(const ListedElement& control) {
61 if (auto* form_control_element =
62 DynamicTo<HTMLFormControlElementWithState>(control))
63 return form_control_element->UserHasEditedTheField();
64 if (control.IsElementInternals()) {
65 // We have no ways to know the dirtiness of a form-associated custom
66 // element. Assume it is dirty if it has focus.
67 // TODO(tkent): If this approach is not enough, we should check existence
68 // of past user-input events such as 'mousedown', 'keydown', 'touchstart'.
69 return control.ToHTMLElement().HasFocusWithin();
70 }
71 DCHECK(!control.ClassSupportsStateRestore());
72 return false;
73 }
74
75 } // namespace
76
77 // ----------------------------------------------------------------------------
78
79 // Serilized form of FormControlState:
80 // (',' means strings around it are separated in stateVector.)
81 //
82 // SerializedControlState ::= SkipState | RestoreState
83 // SkipState ::= '0'
84 // RestoreState ::= UnsignedNumber, ControlValue+
85 // UnsignedNumber ::= [0-9]+
86 // ControlValue ::= arbitrary string
87 //
88 // RestoreState has a sequence of ControlValues. The length of the
89 // sequence is represented by UnsignedNumber.
90
SerializeTo(Vector<String> & state_vector) const91 void FormControlState::SerializeTo(Vector<String>& state_vector) const {
92 DCHECK(!IsFailure());
93 state_vector.push_back(String::Number(values_.size()));
94 for (const auto& value : values_)
95 state_vector.push_back(value.IsNull() ? g_empty_string : value);
96 }
97
Deserialize(const Vector<String> & state_vector,wtf_size_t & index)98 FormControlState FormControlState::Deserialize(
99 const Vector<String>& state_vector,
100 wtf_size_t& index) {
101 if (index >= state_vector.size())
102 return FormControlState(kTypeFailure);
103 unsigned value_size = state_vector[index++].ToUInt();
104 if (!value_size)
105 return FormControlState();
106 if (index + value_size > state_vector.size())
107 return FormControlState(kTypeFailure);
108 FormControlState state;
109 state.values_.ReserveCapacity(value_size);
110 for (unsigned i = 0; i < value_size; ++i)
111 state.Append(state_vector[index++]);
112 return state;
113 }
114
115 // ----------------------------------------------------------------------------
116
117 class ControlKey {
118 public:
119 ControlKey(StringImpl* = nullptr, StringImpl* = nullptr);
120 ~ControlKey();
121 ControlKey(const ControlKey&);
122 ControlKey& operator=(const ControlKey&);
123
GetName() const124 StringImpl* GetName() const { return name_; }
GetType() const125 StringImpl* GetType() const { return type_; }
126
127 // Hash table deleted values, which are only constructed and never copied or
128 // destroyed.
ControlKey(WTF::HashTableDeletedValueType)129 ControlKey(WTF::HashTableDeletedValueType) : name_(HashTableDeletedValue()) {}
IsHashTableDeletedValue() const130 bool IsHashTableDeletedValue() const {
131 return name_ == HashTableDeletedValue();
132 }
133
134 private:
135 void Ref() const;
136 void Deref() const;
137
HashTableDeletedValue()138 static StringImpl* HashTableDeletedValue() {
139 return reinterpret_cast<StringImpl*>(-1);
140 }
141
142 StringImpl* name_;
143 StringImpl* type_;
144 };
145
ControlKey(StringImpl * name,StringImpl * type)146 ControlKey::ControlKey(StringImpl* name, StringImpl* type)
147 : name_(name), type_(type) {
148 Ref();
149 }
150
~ControlKey()151 ControlKey::~ControlKey() {
152 Deref();
153 }
154
ControlKey(const ControlKey & other)155 ControlKey::ControlKey(const ControlKey& other)
156 : name_(other.GetName()), type_(other.GetType()) {
157 Ref();
158 }
159
operator =(const ControlKey & other)160 ControlKey& ControlKey::operator=(const ControlKey& other) {
161 other.Ref();
162 Deref();
163 name_ = other.GetName();
164 type_ = other.GetType();
165 return *this;
166 }
167
Ref() const168 void ControlKey::Ref() const {
169 if (GetName())
170 GetName()->AddRef();
171 if (GetType())
172 GetType()->AddRef();
173 }
174
Deref() const175 void ControlKey::Deref() const {
176 if (GetName())
177 GetName()->Release();
178 if (GetType())
179 GetType()->Release();
180 }
181
operator ==(const ControlKey & a,const ControlKey & b)182 inline bool operator==(const ControlKey& a, const ControlKey& b) {
183 return a.GetName() == b.GetName() && a.GetType() == b.GetType();
184 }
185
186 struct ControlKeyHash {
187 static unsigned GetHash(const ControlKey&);
Equalblink::ControlKeyHash188 static bool Equal(const ControlKey& a, const ControlKey& b) { return a == b; }
189 static const bool safe_to_compare_to_empty_or_deleted = true;
190 };
191
GetHash(const ControlKey & key)192 unsigned ControlKeyHash::GetHash(const ControlKey& key) {
193 return StringHasher::HashMemory<sizeof(ControlKey)>(&key);
194 }
195
196 struct ControlKeyHashTraits : WTF::GenericHashTraits<ControlKey> {
ConstructDeletedValueblink::ControlKeyHashTraits197 static void ConstructDeletedValue(ControlKey& slot, bool) {
198 new (NotNull, &slot) ControlKey(WTF::kHashTableDeletedValue);
199 }
IsDeletedValueblink::ControlKeyHashTraits200 static bool IsDeletedValue(const ControlKey& value) {
201 return value.IsHashTableDeletedValue();
202 }
203 };
204
205 // ----------------------------------------------------------------------------
206
207 // SavedFormState represents a set of FormControlState.
208 // It typically manages controls associated to a single <form>. Controls
209 // without owner forms are managed by a dedicated SavedFormState.
210 class SavedFormState {
211 USING_FAST_MALLOC(SavedFormState);
212
213 public:
SavedFormState()214 SavedFormState() : control_state_count_(0) {}
215
216 static std::unique_ptr<SavedFormState> Deserialize(const Vector<String>&,
217 wtf_size_t& index);
218 void SerializeTo(Vector<String>&) const;
IsEmpty() const219 bool IsEmpty() const { return state_for_new_controls_.IsEmpty(); }
220 void AppendControlState(const AtomicString& name,
221 const AtomicString& type,
222 const FormControlState&);
223 FormControlState TakeControlState(const AtomicString& name,
224 const AtomicString& type);
225
226 Vector<String> GetReferencedFilePaths() const;
227
228 private:
229 using ControlStateMap = HashMap<ControlKey,
230 Deque<FormControlState>,
231 ControlKeyHash,
232 ControlKeyHashTraits>;
233 ControlStateMap state_for_new_controls_;
234 wtf_size_t control_state_count_;
235
236 DISALLOW_COPY_AND_ASSIGN(SavedFormState);
237 };
238
IsNotFormControlTypeCharacter(UChar ch)239 static bool IsNotFormControlTypeCharacter(UChar ch) {
240 return ch != '-' && (ch > 'z' || ch < 'a');
241 }
242
Deserialize(const Vector<String> & state_vector,wtf_size_t & index)243 std::unique_ptr<SavedFormState> SavedFormState::Deserialize(
244 const Vector<String>& state_vector,
245 wtf_size_t& index) {
246 if (index >= state_vector.size())
247 return nullptr;
248 // FIXME: We need String::toSizeT().
249 wtf_size_t item_count = state_vector[index++].ToUInt();
250 if (!item_count)
251 return nullptr;
252 std::unique_ptr<SavedFormState> saved_form_state =
253 base::WrapUnique(new SavedFormState);
254 while (item_count--) {
255 if (index + 1 >= state_vector.size())
256 return nullptr;
257 String name = state_vector[index++];
258 String type = state_vector[index++];
259 FormControlState state = FormControlState::Deserialize(state_vector, index);
260 if (type.IsEmpty() ||
261 (type.Find(IsNotFormControlTypeCharacter) != kNotFound &&
262 !CustomElement::IsValidName(AtomicString(type))) ||
263 state.IsFailure())
264 return nullptr;
265 saved_form_state->AppendControlState(AtomicString(name), AtomicString(type),
266 state);
267 }
268 return saved_form_state;
269 }
270
SerializeTo(Vector<String> & state_vector) const271 void SavedFormState::SerializeTo(Vector<String>& state_vector) const {
272 state_vector.push_back(String::Number(control_state_count_));
273 for (const auto& form_control : state_for_new_controls_) {
274 const ControlKey& key = form_control.key;
275 const Deque<FormControlState>& queue = form_control.value;
276 for (const FormControlState& form_control_state : queue) {
277 state_vector.push_back(key.GetName());
278 state_vector.push_back(key.GetType());
279 form_control_state.SerializeTo(state_vector);
280 }
281 }
282 }
283
AppendControlState(const AtomicString & name,const AtomicString & type,const FormControlState & state)284 void SavedFormState::AppendControlState(const AtomicString& name,
285 const AtomicString& type,
286 const FormControlState& state) {
287 ControlKey key(name.Impl(), type.Impl());
288 ControlStateMap::iterator it = state_for_new_controls_.find(key);
289 if (it != state_for_new_controls_.end()) {
290 it->value.push_back(state);
291 } else {
292 Deque<FormControlState> state_list;
293 state_list.push_back(state);
294 state_for_new_controls_.Set(key, state_list);
295 }
296 control_state_count_++;
297 }
298
TakeControlState(const AtomicString & name,const AtomicString & type)299 FormControlState SavedFormState::TakeControlState(const AtomicString& name,
300 const AtomicString& type) {
301 if (state_for_new_controls_.IsEmpty())
302 return FormControlState();
303 ControlStateMap::iterator it =
304 state_for_new_controls_.find(ControlKey(name.Impl(), type.Impl()));
305 if (it == state_for_new_controls_.end())
306 return FormControlState();
307 DCHECK_GT(it->value.size(), 0u);
308 FormControlState state = it->value.TakeFirst();
309 control_state_count_--;
310 if (it->value.empty())
311 state_for_new_controls_.erase(it);
312 return state;
313 }
314
GetReferencedFilePaths() const315 Vector<String> SavedFormState::GetReferencedFilePaths() const {
316 Vector<String> to_return;
317 for (const auto& form_control : state_for_new_controls_) {
318 const ControlKey& key = form_control.key;
319 if (!Equal(key.GetType(), "file", 4))
320 continue;
321 const Deque<FormControlState>& queue = form_control.value;
322 for (const FormControlState& form_control_state : queue) {
323 to_return.AppendVector(
324 HTMLInputElement::FilesFromFileInputFormControlState(
325 form_control_state));
326 }
327 }
328 return to_return;
329 }
330
331 // ----------------------------------------------------------------------------
332
333 class FormKeyGenerator final : public GarbageCollected<FormKeyGenerator> {
334 public:
335 FormKeyGenerator() = default;
336
Trace(Visitor * visitor) const337 void Trace(Visitor* visitor) const { visitor->Trace(form_to_key_map_); }
338 const AtomicString& FormKey(const ListedElement&);
339 void WillDeleteForm(HTMLFormElement*);
340
341 private:
342 using FormToKeyMap = HeapHashMap<Member<HTMLFormElement>, AtomicString>;
343 using FormSignatureToNextIndexMap = HashMap<String, unsigned>;
344 FormToKeyMap form_to_key_map_;
345 FormSignatureToNextIndexMap form_signature_to_next_index_map_;
346
347 DISALLOW_COPY_AND_ASSIGN(FormKeyGenerator);
348 };
349
RecordFormStructure(const HTMLFormElement & form,StringBuilder & builder)350 static inline void RecordFormStructure(const HTMLFormElement& form,
351 StringBuilder& builder) {
352 // 2 is enough to distinguish forms in webkit.org/b/91209#c0
353 const wtf_size_t kNamedControlsToBeRecorded = 2;
354 const ListedElement::List& controls = form.ListedElements();
355 builder.Append(" [");
356 for (wtf_size_t i = 0, named_controls = 0;
357 i < controls.size() && named_controls < kNamedControlsToBeRecorded;
358 ++i) {
359 ListedElement& control = *controls[i];
360 if (!control.ClassSupportsStateRestore())
361 continue;
362 // The resultant string will be fragile if it contains a name of a
363 // form-associated custom element. It's associated to the |form| only if its
364 // custom element definition is available. It's not associated if the
365 // definition is unavailable though the element structure is identical.
366 if (control.IsElementInternals())
367 continue;
368 if (!OwnerFormForState(control))
369 continue;
370 AtomicString name = control.GetName();
371 if (name.IsEmpty())
372 continue;
373 named_controls++;
374 builder.Append(name);
375 builder.Append(' ');
376 }
377 builder.Append(']');
378 }
379
FormSignature(const HTMLFormElement & form)380 String FormSignature(const HTMLFormElement& form) {
381 KURL action_url = form.GetURLAttribute(html_names::kActionAttr);
382 // Remove the query part because it might contain volatile parameters such
383 // as a session key.
384 if (!action_url.IsEmpty())
385 action_url.SetQuery(String());
386
387 StringBuilder builder;
388 if (!action_url.IsEmpty())
389 builder.Append(action_url.GetString());
390
391 RecordFormStructure(form, builder);
392 return builder.ToString();
393 }
394
FormKey(const ListedElement & control)395 const AtomicString& FormKeyGenerator::FormKey(const ListedElement& control) {
396 HTMLFormElement* form = OwnerFormForState(control);
397 if (!form) {
398 DEFINE_STATIC_LOCAL(const AtomicString, form_key_for_no_owner,
399 ("No owner"));
400 return form_key_for_no_owner;
401 }
402 FormToKeyMap::const_iterator it = form_to_key_map_.find(form);
403 if (it != form_to_key_map_.end())
404 return it->value;
405
406 String signature = FormSignature(*form);
407 DCHECK(!signature.IsNull());
408 FormSignatureToNextIndexMap::AddResult result =
409 form_signature_to_next_index_map_.insert(signature, 0);
410 unsigned next_index = result.stored_value->value++;
411
412 StringBuilder form_key_builder;
413 form_key_builder.Append(signature);
414 form_key_builder.Append(" #");
415 form_key_builder.AppendNumber(next_index);
416 FormToKeyMap::AddResult add_form_keyresult =
417 form_to_key_map_.insert(form, form_key_builder.ToAtomicString());
418 return add_form_keyresult.stored_value->value;
419 }
420
WillDeleteForm(HTMLFormElement * form)421 void FormKeyGenerator::WillDeleteForm(HTMLFormElement* form) {
422 DCHECK(form);
423 form_to_key_map_.erase(form);
424 }
425
426 // ----------------------------------------------------------------------------
427
DocumentState(Document & document)428 DocumentState::DocumentState(Document& document) : document_(document) {}
429
Trace(Visitor * visitor) const430 void DocumentState::Trace(Visitor* visitor) const {
431 visitor->Trace(document_);
432 visitor->Trace(control_list_);
433 }
434
InvalidateControlList()435 void DocumentState::InvalidateControlList() {
436 if (is_control_list_dirty_)
437 return;
438 control_list_.resize(0);
439 is_control_list_dirty_ = true;
440 }
441
GetControlList()442 const DocumentState::ControlList& DocumentState::GetControlList() {
443 if (is_control_list_dirty_) {
444 for (auto& element : Traversal<Element>::DescendantsOf(*document_)) {
445 if (auto* control = ListedElement::From(element)) {
446 if (control->ClassSupportsStateRestore())
447 control_list_.push_back(control);
448 }
449 }
450 is_control_list_dirty_ = false;
451 }
452 return control_list_;
453 }
454
FormStateSignature()455 static String FormStateSignature() {
456 // In the legacy version of serialized state, the first item was a name
457 // attribute value of a form control. The following string literal should
458 // contain some characters which are rarely used for name attribute values.
459 DEFINE_STATIC_LOCAL(String, signature,
460 ("\n\r?% Blink serialized form state version 10 \n\r=&"));
461 return signature;
462 }
463
ToStateVector()464 Vector<String> DocumentState::ToStateVector() {
465 auto* key_generator = MakeGarbageCollected<FormKeyGenerator>();
466 std::unique_ptr<SavedFormStateMap> state_map =
467 base::WrapUnique(new SavedFormStateMap);
468 for (auto& control : GetControlList()) {
469 DCHECK(control->ToHTMLElement().isConnected());
470 if (!control->ShouldSaveAndRestoreFormControlState())
471 continue;
472 SavedFormStateMap::AddResult result =
473 state_map->insert(key_generator->FormKey(*control), nullptr);
474 if (result.is_new_entry)
475 result.stored_value->value = std::make_unique<SavedFormState>();
476 result.stored_value->value->AppendControlState(
477 control->GetName(), ControlType(*control),
478 control->SaveFormControlState());
479 }
480
481 Vector<String> state_vector;
482 state_vector.ReserveInitialCapacity(GetControlList().size() * 4);
483 state_vector.push_back(FormStateSignature());
484 for (const auto& saved_form_state : *state_map) {
485 state_vector.push_back(saved_form_state.key);
486 saved_form_state.value->SerializeTo(state_vector);
487 }
488 bool has_only_signature = state_vector.size() == 1;
489 if (has_only_signature)
490 state_vector.clear();
491 return state_vector;
492 }
493
494 // ----------------------------------------------------------------------------
495
FormController(Document & document)496 FormController::FormController(Document& document)
497 : document_(document),
498 document_state_(MakeGarbageCollected<DocumentState>(document)) {}
499
500 FormController::~FormController() = default;
501
Trace(Visitor * visitor) const502 void FormController::Trace(Visitor* visitor) const {
503 visitor->Trace(document_);
504 visitor->Trace(document_state_);
505 visitor->Trace(form_key_generator_);
506 }
507
ControlStates() const508 DocumentState* FormController::ControlStates() const {
509 return document_state_.Get();
510 }
511
SetStateForNewControls(const Vector<String> & state_vector)512 void FormController::SetStateForNewControls(
513 const Vector<String>& state_vector) {
514 ControlStatesFromStateVector(state_vector, saved_form_state_map_);
515 }
516
HasControlStates() const517 bool FormController::HasControlStates() const {
518 return !saved_form_state_map_.IsEmpty();
519 }
520
TakeStateForControl(const ListedElement & control)521 FormControlState FormController::TakeStateForControl(
522 const ListedElement& control) {
523 if (saved_form_state_map_.IsEmpty())
524 return FormControlState();
525 if (!form_key_generator_)
526 form_key_generator_ = MakeGarbageCollected<FormKeyGenerator>();
527 SavedFormStateMap::iterator it =
528 saved_form_state_map_.find(form_key_generator_->FormKey(control));
529 if (it == saved_form_state_map_.end())
530 return FormControlState();
531 FormControlState state =
532 it->value->TakeControlState(control.GetName(), ControlType(control));
533 if (it->value->IsEmpty())
534 saved_form_state_map_.erase(it);
535 return state;
536 }
537
ControlStatesFromStateVector(const Vector<String> & state_vector,SavedFormStateMap & map)538 void FormController::ControlStatesFromStateVector(
539 const Vector<String>& state_vector,
540 SavedFormStateMap& map) {
541 map.clear();
542
543 wtf_size_t i = 0;
544 if (state_vector.size() < 1 || state_vector[i++] != FormStateSignature())
545 return;
546
547 while (i + 1 < state_vector.size()) {
548 AtomicString form_key = AtomicString(state_vector[i++]);
549 std::unique_ptr<SavedFormState> state =
550 SavedFormState::Deserialize(state_vector, i);
551 if (!state) {
552 i = 0;
553 break;
554 }
555 map.insert(form_key, std::move(state));
556 }
557 if (i != state_vector.size())
558 map.clear();
559 }
560
WillDeleteForm(HTMLFormElement * form)561 void FormController::WillDeleteForm(HTMLFormElement* form) {
562 if (form_key_generator_)
563 form_key_generator_->WillDeleteForm(form);
564 }
565
RestoreControlStateFor(ListedElement & control)566 void FormController::RestoreControlStateFor(ListedElement& control) {
567 if (!document_->HasFinishedParsing())
568 return;
569 if (OwnerFormForState(control))
570 return;
571 RestoreControlStateInternal(control);
572 }
573
RestoreControlStateIn(HTMLFormElement & form)574 void FormController::RestoreControlStateIn(HTMLFormElement& form) {
575 if (!document_->HasFinishedParsing())
576 return;
577 EventQueueScope scope;
578 const ListedElement::List& elements = form.ListedElements();
579 for (const auto& control : elements) {
580 if (!control->ClassSupportsStateRestore())
581 continue;
582 if (OwnerFormForState(*control) != &form)
583 continue;
584 RestoreControlStateInternal(*control);
585 }
586 }
587
RestoreControlStateInternal(ListedElement & control)588 void FormController::RestoreControlStateInternal(ListedElement& control) {
589 // We don't save state of a control with
590 // ShouldSaveAndRestoreFormControlState() == false. But we need to skip
591 // restoring process too because a control in another form might have the same
592 // pair of name and type and saved its state.
593 if (!control.ShouldSaveAndRestoreFormControlState())
594 return;
595 FormControlState state = TakeStateForControl(control);
596 if (state.ValueSize() <= 0)
597 return;
598 HTMLElement& element = control.ToHTMLElement();
599 if (element.IsDisabledFormControl() ||
600 element.FastHasAttribute(html_names::kReadonlyAttr))
601 return;
602 // If a user already edited the control, we should not overwrite it.
603 if (IsDirtyControl(control))
604 return;
605 // RestoreFormControlState might dispatch input/change events.
606 control.RestoreFormControlState(state);
607 }
608
RestoreControlStateOnUpgrade(ListedElement & control)609 void FormController::RestoreControlStateOnUpgrade(ListedElement& control) {
610 DCHECK(control.ClassSupportsStateRestore());
611 if (!control.ShouldSaveAndRestoreFormControlState())
612 return;
613 FormControlState state = TakeStateForControl(control);
614 if (state.ValueSize() > 0)
615 control.RestoreFormControlState(state);
616 }
617
ScheduleRestore()618 void FormController::ScheduleRestore() {
619 document_->GetTaskRunner(TaskType::kInternalLoading)
620 ->PostTask(FROM_HERE,
621 WTF::Bind(&FormController::RestoreAllControlsInDocumentOrder,
622 WrapPersistent(this)));
623 }
624
RestoreImmediately()625 void FormController::RestoreImmediately() {
626 if (did_restore_all_ || !HasControlStates())
627 return;
628 RestoreAllControlsInDocumentOrder();
629 }
630
RestoreAllControlsInDocumentOrder()631 void FormController::RestoreAllControlsInDocumentOrder() {
632 if (!document_->IsActive() || did_restore_all_)
633 return;
634 HeapHashSet<Member<HTMLFormElement>> finished_forms;
635 EventQueueScope scope;
636 for (auto& control : document_state_->GetControlList()) {
637 auto* owner = OwnerFormForState(*control);
638 if (!owner)
639 RestoreControlStateFor(*control);
640 else if (finished_forms.insert(owner).is_new_entry)
641 RestoreControlStateIn(*owner);
642 }
643 did_restore_all_ = true;
644 }
645
GetReferencedFilePaths(const Vector<String> & state_vector)646 Vector<String> FormController::GetReferencedFilePaths(
647 const Vector<String>& state_vector) {
648 Vector<String> to_return;
649 SavedFormStateMap map;
650 ControlStatesFromStateVector(state_vector, map);
651 for (const auto& saved_form_state : map)
652 to_return.AppendVector(saved_form_state.value->GetReferencedFilePaths());
653 return to_return;
654 }
655
InvalidateStatefulFormControlList()656 void FormController::InvalidateStatefulFormControlList() {
657 document_state_->InvalidateControlList();
658 }
659
660 } // namespace blink
661