Unmodified form control value are overwritten by another form
control value with the same name after navigating and going back
https://bugs.webkit.org/show_bug.cgi?id=89409

Reviewed by Hajime Morita.

Source/WebCore:

Detail of the bug:
If a page had multiple form controls of which names and types were
identical like the following:
  <input type=text name=name1 id=input1>
  <input type=text name=name1 id=input2>
and a user updated the value of the second control, then went to
another page and went back to the page again, we restored the updated
value to the first element, and didn't update the second element.

We didn't save unmodified control state, and the form state data
had no ways to represent "this control should be skipped".

How to resovle the bug:
We need to represent "this control should be skipped" in the
seriazlied form state vector.

- A serialized control state had three items:
        name, type, value.
  Now we change it to:
        name, type, flag, optional value

- It is definitely incompatible with serizlized state produced by
older WebCore. So, we need to add the signature string to
represent the version of serialized state format.

- Because the state for a form control is variable-length and we
can't deserialize it in reverse-order, we change the on-memory
representation from Vector<> to Deque<>.

Test: fast/forms/state-restore-to-non-edited-controls.html

* html/FormController.cpp:
(WebCore::FormControlState::serializeTo):
Added. Serialize a state for a form control to a string vector.
(WebCore::FormControlState::deserialize):
Added. Produce a FormControlState object from the specified string vector.
It can produce a FromControlState of the failure type.
(WebCore::formStateSignature): The signature string of the serialized state.
(WebCore::FormController::formElementsState):
 - Capacity:
  The size of seirlized data for one form control is typically 4.
  +1 for the signature.
 - We need to store a FormControlState with no values.
(WebCore::FormController::setStateForNewFormElements):
 - We can't iterate over the stateVector in reverse order any more
   because serialized control state is variable-length.
 - We put FormControlState objects to HashMap instead of String objects.
(WebCore::FormController::takeStateForFormElement):
 Updated for Deque<>.
* html/FormController.h:
(FormControlState): Declare deserialize() and serializeTo().
(WebCore::FormControlState::isFailure): Added.
(WebCore::FormControlState::FormControlState):
Added to create a FormControlState with failure type.
(FormController):
Change the value type of m_stateForNewFormElements from Vector<String>
to Deque<FormControlState>.

LayoutTests:

* fast/forms/resources/state-restore-broken-state-2.html:
Take care of the signature string at the beginning of the array.
* fast/forms/state-restore-broken-state-expected.txt:
Updated for the serialized format change.
* fast/forms/state-restore-to-non-edited-controls-expected.txt:
* fast/forms/state-restore-to-non-edited-controls.html:
Add a test for a case of duplicated names.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@120895 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/html/FormController.cpp b/Source/WebCore/html/FormController.cpp
index 80d01f2..46c93b3 100644
--- a/Source/WebCore/html/FormController.cpp
+++ b/Source/WebCore/html/FormController.cpp
@@ -27,6 +27,42 @@
 
 using namespace HTMLNames;
 
+// ----------------------------------------------------------------------------
+
+// Serilized form of FormControlState:
+//  (',' means strings around it are separated in stateVector.)
+//
+// SerializedControlState ::= SkipState | SingleValueState
+// SkipState ::= '0'
+// SingleValueState ::= '1', ControlValue
+// ControlValue ::= arbitrary string
+
+void FormControlState::serializeTo(Vector<String>& stateVector) const
+{
+    ASSERT(!isFailure());
+    if (!hasValue())
+        stateVector.append("0");
+    else {
+        stateVector.append("1");
+        stateVector.append(m_value);
+    }
+}
+
+FormControlState FormControlState::deserialize(const Vector<String>& stateVector, size_t& index)
+{
+    if (index >= stateVector.size())
+        return FormControlState(TypeFailure);
+    uint64_t valueSize = stateVector[index++].toUInt64();
+    if (!valueSize)
+        return FormControlState();
+    if (valueSize != 1 || index + 1 > stateVector.size())
+        return FormControlState(TypeFailure);
+    return FormControlState(stateVector[index++]);
+}
+
+// ----------------------------------------------------------------------------
+
+
 FormController::FormController()
 {
 }
@@ -35,22 +71,29 @@
 {
 }
 
+static String formStateSignature()
+{
+    // In the legacy version of serialized state, the first item was a name
+    // attribute value of a form control. The following string literal should
+    // contain some characters which are rarely used for name attribute values.
+    DEFINE_STATIC_LOCAL(String, signature, ("\n\r?% WebKit serialized form state version 1 \n\r=&"));
+    return signature;
+}
+
 Vector<String> FormController::formElementsState() const
 {
     Vector<String> stateVector;
-    stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 3);
+    stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 4 + 1);
+    stateVector.append(formStateSignature());
     typedef FormElementListHashSet::const_iterator Iterator;
     Iterator end = m_formElementsWithState.end();
     for (Iterator it = m_formElementsWithState.begin(); it != end; ++it) {
         HTMLFormControlElementWithState* elementWithState = *it;
         if (!elementWithState->shouldSaveAndRestoreFormControlState())
             continue;
-        FormControlState state = elementWithState->saveFormControlState();
-        if (!state.hasValue())
-            continue;
         stateVector.append(elementWithState->name().string());
         stateVector.append(elementWithState->formControlType().string());
-        stateVector.append(state.value());
+        elementWithState->saveFormControlState().serializeTo(stateVector);
     }
     return stateVector;
 }
@@ -62,33 +105,32 @@
 
 void FormController::setStateForNewFormElements(const Vector<String>& stateVector)
 {
-    // Walk the state vector backwards so that the value to use for each
-    // name/type pair first is the one at the end of each individual vector
-    // in the FormElementStateMap. We're using them like stacks.
     typedef FormElementStateMap::iterator Iterator;
     m_formElementsWithState.clear();
 
-    if (stateVector.size() % 3)
+    size_t i = 0;
+    if (stateVector.size() < 1 || stateVector[i++] != formStateSignature())
         return;
-    for (size_t i = 0; i < stateVector.size(); i += 3) {
-        if (stateVector[i + 1].find(isNotFormControlTypeCharacter) != notFound)
-            return;
-    }
 
-    for (size_t i = stateVector.size() / 3 * 3; i; i -= 3) {
-        AtomicString name = stateVector[i - 3];
-        AtomicString type = stateVector[i - 2];
-        const String& value = stateVector[i - 1];
+    while (i + 2 < stateVector.size()) {
+        AtomicString name = stateVector[i++];
+        AtomicString type = stateVector[i++];
+        FormControlState state = FormControlState::deserialize(stateVector, i);
+        if (type.isEmpty() || type.impl()->find(isNotFormControlTypeCharacter) != notFound || state.isFailure())
+            break;
+
         FormElementKey key(name.impl(), type.impl());
         Iterator it = m_stateForNewFormElements.find(key);
         if (it != m_stateForNewFormElements.end())
-            it->second.append(value);
+            it->second.append(state);
         else {
-            Vector<String> valueList(1);
-            valueList[0] = value;
-            m_stateForNewFormElements.set(key, valueList);
+            Deque<FormControlState> stateList;
+            stateList.append(state);
+            m_stateForNewFormElements.set(key, stateList);
         }
     }
+    if (i != stateVector.size())
+        m_stateForNewFormElements.clear();
 }
 
 bool FormController::hasStateForNewFormElements() const
@@ -103,10 +145,8 @@
     if (it == m_stateForNewFormElements.end())
         return FormControlState();
     ASSERT(it->second.size());
-    FormControlState state(it->second.last());
-    if (it->second.size() > 1)
-        it->second.removeLast();
-    else
+    FormControlState state = it->second.takeFirst();
+    if (!it->second.size())
         m_stateForNewFormElements.remove(it);
     return state;
 }