Make FormControlState capable to store multiple values
authortkent@chromium.org <tkent@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 22 Jun 2012 05:36:28 +0000 (05:36 +0000)
committertkent@chromium.org <tkent@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 22 Jun 2012 05:36:28 +0000 (05:36 +0000)
https://bugs.webkit.org/show_bug.cgi?id=89628

Reviewed by Hajime Morita.

Make FormControlState capable to store multiple values in order to
clean FileInputType.cpp up and prepare to fix Bug 89623.

No new tests. This doesn't change web-exposed behavior, and
fast/forms/file/recover-file-input-in-unposted-form.html covers
major part of this change.

* html/FormController.cpp:
(WebCore::FormControlState::serializeTo): Support for two or more values.
(WebCore::FormControlState::deserialize): ditto.
(WebCore::formStateSignature):
Bump up the version because the state format for <input type=file> is changed.
* html/FormController.h:
 - String m_value -> Vector<String> m_values
 - Add some functions.
 - Remove hasValue() and value().
(WebCore::FormControlState::FormControlState): m_value -> m_values.
(WebCore::FormControlState::valueSize): Added.
(WebCore::FormControlState::operator[]): Added.
(FormControlState): Add append() declaration, etc.
(WebCore::FormControlState::operator=): m_value -> m_values
(WebCore::FormControlState::append): Added.

* html/HTMLFormControlElementWithState.cpp:
(WebCore::HTMLFormControlElementWithState::finishParsingChildren):
Use valueSize() instead of hasValue().
* html/HTMLFormControlElementWithState.h:
(HTMLFormControlElementWithState): Update the comment.

* html/FileInputType.cpp:
(WebCore::FileInputType::saveFormControlState):
Use multiple value capability of FormControlState
(WebCore::FileInputType::restoreFormControlState): ditto.

* html/BaseCheckableInputType.cpp:
(WebCore::BaseCheckableInputType::restoreFormControlState): Use [0] instead of value().
* html/HTMLSelectElement.cpp:
(WebCore::HTMLSelectElement::restoreFormControlState): ditto.
* html/HTMLTextAreaElement.cpp:
(WebCore::HTMLTextAreaElement::restoreFormControlState): ditto.
* html/HiddenInputType.cpp:
(WebCore::HiddenInputType::restoreFormControlState): ditto.
* html/InputType.cpp:
(WebCore::InputType::restoreFormControlState): ditto.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@121004 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/html/BaseCheckableInputType.cpp
Source/WebCore/html/FileInputType.cpp
Source/WebCore/html/FormController.cpp
Source/WebCore/html/FormController.h
Source/WebCore/html/HTMLFormControlElementWithState.cpp
Source/WebCore/html/HTMLFormControlElementWithState.h
Source/WebCore/html/HTMLSelectElement.cpp
Source/WebCore/html/HTMLTextAreaElement.cpp
Source/WebCore/html/HiddenInputType.cpp
Source/WebCore/html/InputType.cpp

index b9ab1a9..0d656bf 100644 (file)
@@ -1,3 +1,55 @@
+2012-06-21  Kent Tamura  <tkent@chromium.org>
+
+        Make FormControlState capable to store multiple values
+        https://bugs.webkit.org/show_bug.cgi?id=89628
+
+        Reviewed by Hajime Morita.
+
+        Make FormControlState capable to store multiple values in order to
+        clean FileInputType.cpp up and prepare to fix Bug 89623.
+
+        No new tests. This doesn't change web-exposed behavior, and
+        fast/forms/file/recover-file-input-in-unposted-form.html covers
+        major part of this change.
+
+        * html/FormController.cpp:
+        (WebCore::FormControlState::serializeTo): Support for two or more values.
+        (WebCore::FormControlState::deserialize): ditto.
+        (WebCore::formStateSignature):
+        Bump up the version because the state format for <input type=file> is changed.
+        * html/FormController.h:
+         - String m_value -> Vector<String> m_values
+         - Add some functions.
+         - Remove hasValue() and value().
+        (WebCore::FormControlState::FormControlState): m_value -> m_values.
+        (WebCore::FormControlState::valueSize): Added.
+        (WebCore::FormControlState::operator[]): Added.
+        (FormControlState): Add append() declaration, etc.
+        (WebCore::FormControlState::operator=): m_value -> m_values
+        (WebCore::FormControlState::append): Added.
+
+        * html/HTMLFormControlElementWithState.cpp:
+        (WebCore::HTMLFormControlElementWithState::finishParsingChildren):
+        Use valueSize() instead of hasValue().
+        * html/HTMLFormControlElementWithState.h:
+        (HTMLFormControlElementWithState): Update the comment.
+
+        * html/FileInputType.cpp:
+        (WebCore::FileInputType::saveFormControlState):
+        Use multiple value capability of FormControlState
+        (WebCore::FileInputType::restoreFormControlState): ditto.
+
+        * html/BaseCheckableInputType.cpp:
+        (WebCore::BaseCheckableInputType::restoreFormControlState): Use [0] instead of value().
+        * html/HTMLSelectElement.cpp:
+        (WebCore::HTMLSelectElement::restoreFormControlState): ditto.
+        * html/HTMLTextAreaElement.cpp:
+        (WebCore::HTMLTextAreaElement::restoreFormControlState): ditto.
+        * html/HiddenInputType.cpp:
+        (WebCore::HiddenInputType::restoreFormControlState): ditto.
+        * html/InputType.cpp:
+        (WebCore::InputType::restoreFormControlState): ditto.
+
 2012-06-21  Ryosuke Niwa  <rniwa@webkit.org>
 
         LabelsNodeList isn't updated properly after its owner node is adopted into a new document
index 1900ad2..2812173 100644 (file)
@@ -50,7 +50,7 @@ FormControlState BaseCheckableInputType::saveFormControlState() const
 
 void BaseCheckableInputType::restoreFormControlState(const FormControlState& state)
 {
-    element()->setChecked(state.value() == "on");
+    element()->setChecked(state[0] == "on");
 }
 
 bool BaseCheckableInputType::appendFormData(FormDataList& encoding, bool) const
index f164511..f39733d 100644 (file)
@@ -105,31 +105,25 @@ FormControlState FileInputType::saveFormControlState() const
 {
     if (m_fileList->isEmpty())
         return FormControlState();
-    // FIXME: FormControlState should be capable to have multiple strings and we
-    // should stop the following ugly string concatenation.
-    StringBuilder result;
+    FormControlState state;
     unsigned numFiles = m_fileList->length();
     for (unsigned i = 0; i < numFiles; ++i) {
-        result.append(m_fileList->item(i)->path());
-        result.append('\1');
-        result.append(m_fileList->item(i)->name());
-        result.append('\0');
+        state.append(m_fileList->item(i)->path());
+        state.append(m_fileList->item(i)->name());
     }
-    return FormControlState(result.toString());
+    return state;
 }
 
 void FileInputType::restoreFormControlState(const FormControlState& state)
 {
+    if (state.valueSize() % 2)
+        return;
     Vector<FileChooserFileInfo> files;
-    Vector<String> paths;
-    state.value().split('\0', paths);
-    for (unsigned i = 0; i < paths.size(); ++i) {
-        Vector<String> pathAndName;
-        paths[i].split('\1', pathAndName);
-        if (pathAndName.size() > 1)
-            files.append(FileChooserFileInfo(pathAndName[0], pathAndName[1]));
+    for (size_t i = 0; i < state.valueSize(); i += 2) {
+        if (!state[i + 1].isEmpty())
+            files.append(FileChooserFileInfo(state[i], state[i + 1]));
         else
-            files.append(FileChooserFileInfo(paths[i]));
+            files.append(FileChooserFileInfo(state[i]));
     }
     filesChosen(files);
 }
index 46c93b3..74830b3 100644 (file)
@@ -32,20 +32,21 @@ using namespace HTMLNames;
 // Serilized form of FormControlState:
 //  (',' means strings around it are separated in stateVector.)
 //
-// SerializedControlState ::= SkipState | SingleValueState
+// SerializedControlState ::= SkipState | RestoreState
 // SkipState ::= '0'
-// SingleValueState ::= '1', ControlValue
+// RestoreState ::= UnsignedNumber, ControlValue+
+// UnsignedNumber ::= [0-9]+
 // ControlValue ::= arbitrary string
+//
+// RestoreState has a sequence of ControlValues. The length of the
+// sequence is represented by UnsignedNumber.
 
 void FormControlState::serializeTo(Vector<String>& stateVector) const
 {
     ASSERT(!isFailure());
-    if (!hasValue())
-        stateVector.append("0");
-    else {
-        stateVector.append("1");
-        stateVector.append(m_value);
-    }
+    stateVector.append(String::number(m_values.size()));
+    for (size_t i = 0; i < m_values.size(); ++i)
+        stateVector.append(m_values[i].isNull() ? emptyString() : m_values[i]);
 }
 
 FormControlState FormControlState::deserialize(const Vector<String>& stateVector, size_t& index)
@@ -55,9 +56,13 @@ FormControlState FormControlState::deserialize(const Vector<String>& stateVector
     uint64_t valueSize = stateVector[index++].toUInt64();
     if (!valueSize)
         return FormControlState();
-    if (valueSize != 1 || index + 1 > stateVector.size())
+    if (index + valueSize > stateVector.size())
         return FormControlState(TypeFailure);
-    return FormControlState(stateVector[index++]);
+    FormControlState state;
+    state.m_values.reserveCapacity(valueSize);
+    for (size_t i = 0; i < valueSize; ++i)
+        state.append(stateVector[index++]);
+    return state;
 }
 
 // ----------------------------------------------------------------------------
@@ -76,7 +81,7 @@ 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=&"));
+    DEFINE_STATIC_LOCAL(String, signature, ("\n\r?% WebKit serialized form state version 2 \n\r=&"));
     return signature;
 }
 
index 65f3117..fa5463b 100644 (file)
@@ -77,14 +77,15 @@ struct FormElementKeyHashTraits : WTF::GenericHashTraits<FormElementKey> {
 class FormControlState {
 public:
     FormControlState() : m_type(TypeSkip) { }
-    explicit FormControlState(const String& value) : m_type(TypeRestore), m_value(value) { }
+    explicit FormControlState(const String& value) : m_type(TypeRestore) { m_values.append(value); }
     static FormControlState deserialize(const Vector<String>& stateVector, size_t& index);
-    FormControlState(const FormControlState& another) : m_type(another.m_type), m_value(another.m_value) { }
+    FormControlState(const FormControlState& another) : m_type(another.m_type), m_values(another.m_values) { }
     FormControlState& operator=(const FormControlState&);
 
     bool isFailure() const { return m_type == TypeFailure; }
-    bool hasValue() const { return m_type == TypeRestore; }
-    String value() const { return m_value; }
+    size_t valueSize() const { return m_values.size(); }
+    const String& operator[](size_t i) const { return m_values[i]; }
+    void append(const String&);
     void serializeTo(Vector<String>& stateVector) const;
 
 private:
@@ -92,16 +93,22 @@ private:
     explicit FormControlState(Type type) : m_type(type) { }
 
     Type m_type;
-    String m_value;
+    Vector<String> m_values;
 };
 
 inline FormControlState& FormControlState::operator=(const FormControlState& another)
 {
     m_type = another.m_type;
-    m_value = another.m_value;
+    m_values = another.m_values;
     return *this;
 }
 
+inline void FormControlState::append(const String& value)
+{
+    m_type = TypeRestore;
+    m_values.append(value);
+}
+
 class FormController {
 public:
     static PassOwnPtr<FormController> create()
index 4152224..a884ee1 100644 (file)
@@ -80,7 +80,7 @@ void HTMLFormControlElementWithState::finishParsingChildren()
     Document* doc = document();
     if (doc->formController()->hasStateForNewFormElements()) {
         FormControlState state = doc->formController()->takeStateForFormElement(name().impl(), type().impl());
-        if (state.hasValue())
+        if (state.valueSize() > 0)
             restoreFormControlState(state);
     }
 }
index 0af98f8..f14d856 100644 (file)
@@ -38,7 +38,7 @@ public:
 
     bool shouldSaveAndRestoreFormControlState() const;
     virtual FormControlState saveFormControlState() const;
-    // The specified FormControlState must have one string value.
+    // The specified FormControlState must have at least one string value.
     virtual void restoreFormControlState(const FormControlState&) { }
 
 protected:
index a5d8ad2..11111d3 100644 (file)
@@ -936,7 +936,7 @@ void HTMLSelectElement::restoreFormControlState(const FormControlState& state)
     const Vector<HTMLElement*>& items = listItems();
     size_t length = items.size();
 
-    String mask = state.value();
+    String mask = state[0];
     for (size_t i = 0; i < length; ++i) {
         HTMLElement* element = items[i];
         if (element->hasTagName(optionTag))
index bf5125f..9f23013 100644 (file)
@@ -109,7 +109,7 @@ FormControlState HTMLTextAreaElement::saveFormControlState() const
 
 void HTMLTextAreaElement::restoreFormControlState(const FormControlState& state)
 {
-    setValue(state.value());
+    setValue(state[0]);
 }
 
 void HTMLTextAreaElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
index 96d4ce0..049637c 100644 (file)
@@ -60,7 +60,7 @@ FormControlState HiddenInputType::saveFormControlState() const
 
 void HiddenInputType::restoreFormControlState(const FormControlState& state)
 {
-    element()->setAttribute(valueAttr, state.value());
+    element()->setAttribute(valueAttr, state[0]);
 }
 
 bool HiddenInputType::supportsValidation() const
index 514119f..a6696d2 100644 (file)
@@ -179,7 +179,7 @@ FormControlState InputType::saveFormControlState() const
 
 void InputType::restoreFormControlState(const FormControlState& state)
 {
-    element()->setValue(state.value());
+    element()->setValue(state[0]);
 }
 
 bool InputType::isFormDataAppendable() const