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