Title: [121420] trunk
Revision
121420
Author
[email protected]
Date
2012-06-28 01:48:20 -0700 (Thu, 28 Jun 2012)

Log Message

Classify form control states by their owner forms
https://bugs.webkit.org/show_bug.cgi?id=89950

Reviewed by Hajime Morita.

Source/_javascript_Core:

* _javascript_Core.vcproj/_javascript_Core/_javascript_Core.def:
Expose WTF::StringBuilder::canShrink()

Source/WebCore:

To improve robustness of the form state restore feature, we classify
form control states by their owner forms. Owner forms are identified by
their action URLs and index numbers in forms with the same action URLs.

Implementation approach:
Extend FormElementKey class to have "formKey" string, which is a
combination of the action URL and an index number, or a fixed string for
no form owner.
FormKeyGenerator class is responsible to generate the "formKey" strings

Test: fast/forms/state-restore-per-form.html

* html/FormController.cpp:
(FormKeyGenerator):
(WebCore::FormKeyGenerator::create): A factory function.
(WebCore::FormKeyGenerator::FormKeyGenerator): A private constructor.
(WebCore::createKey):
A helper for formKey(). This makes strings like "<action URL> #<index>".
(WebCore::FormKeyGenerator::formKey):
Returns a formKey for the specified HTMLFormElement*.
(WebCore::FormKeyGenerator::willDeleteForm):
Unregister HTMLFormElement*. This function is necessary because form
restore feature works during parsing and a script might delete form
elements.
(WebCore::formStateSignature): Bump the version.
(WebCore::FormController::formElementsState):
Records a formKey string for each of control state.
(WebCore::FormController::setStateForNewFormElements):
Loads formKeys from stateVector, and uses them for FormElementKey.
(WebCore::FormController::takeStateForFormElement):
- Construct and destruct FormKeyGenerator if needed.
- Passing a formKey for the specified form control to FormElementKey.
(WebCore::FormController::willDeleteForm):
Delegate to FormKeyGenerator::willDeleteForm.

(WebCore::FormElementKey::FormElementKey): Add formKey argument and member.
(WebCore::FormElementKey::operator=): ditto.
(WebCore::FormElementKey::ref): ditto.
(WebCore::FormElementKey::deref): ditto.
* html/FormController.h:
(FormElementKey): Add formKey argument and member.
(FormController): Add a FormKeyGenerator member which is used during restoring.

* html/HTMLFormElement.cpp:
(WebCore::HTMLFormElement::~HTMLFormElement): Notify the death to FormController.

LayoutTests:

* fast/forms/resources/state-restore-per-form-back.html: Added.
* fast/forms/state-restore-per-form-expected.txt:
Added. This contains some FAIL lines. They are expected and will
be fixed in webkit.org/b/89962.
* fast/forms/state-restore-per-form.html: Added.
* fast/forms/state-restore-broken-state-expected.txt:
Updated for the serialization format change.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (121419 => 121420)


--- trunk/LayoutTests/ChangeLog	2012-06-28 08:44:50 UTC (rev 121419)
+++ trunk/LayoutTests/ChangeLog	2012-06-28 08:48:20 UTC (rev 121420)
@@ -1,5 +1,20 @@
 2012-06-28  Kent Tamura  <[email protected]>
 
+        Classify form control states by their owner forms
+        https://bugs.webkit.org/show_bug.cgi?id=89950
+
+        Reviewed by Hajime Morita.
+
+        * fast/forms/resources/state-restore-per-form-back.html: Added.
+        * fast/forms/state-restore-per-form-expected.txt:
+        Added. This contains some FAIL lines. They are expected and will
+        be fixed in webkit.org/b/89962.
+        * fast/forms/state-restore-per-form.html: Added.
+        * fast/forms/state-restore-broken-state-expected.txt:
+        Updated for the serialization format change.
+
+2012-06-28  Kent Tamura  <[email protected]>
+
         [Chromium] Test expectation update
 
         * platform/chromium/TestExpectations:

Added: trunk/LayoutTests/fast/forms/resources/state-restore-per-form-back.html (0 => 121420)


--- trunk/LayoutTests/fast/forms/resources/state-restore-per-form-back.html	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/resources/state-restore-per-form-back.html	2012-06-28 08:48:20 UTC (rev 121420)
@@ -0,0 +1,16 @@
+<script>
+if (window.internals) {
+    buffer = 'Form state vector:';
+    var states = internals.formControlStateOfPreviousHistoryItem();
+    for (var i = 1; i < states.length; ++i) {
+        if (i % 5 == 1) {
+            console.log(buffer);
+            buffer = '';
+        }
+        buffer += states[i] + ', ';
+    }
+    console.log(buffer);
+    console.log('');
+}
+history.back();
+</script>

Modified: trunk/LayoutTests/fast/forms/state-restore-broken-state-expected.txt (121419 => 121420)


--- trunk/LayoutTests/fast/forms/state-restore-broken-state-expected.txt	2012-06-28 08:44:50 UTC (rev 121419)
+++ trunk/LayoutTests/fast/forms/state-restore-broken-state-expected.txt	2012-06-28 08:48:20 UTC (rev 121420)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 5: Generated state: [name1,text,1,modified]
+CONSOLE MESSAGE: line 5: Generated state: [name1,text,state-restore-broken-state-2.html #0,1,modified]
 The value was modified in the first load of state-restore-broken-state-1.html, but it should not be restored because the state-restore-broken-state-2.html breaks the state.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".

Added: trunk/LayoutTests/fast/forms/state-restore-per-form-expected.txt (0 => 121420)


--- trunk/LayoutTests/fast/forms/state-restore-per-form-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/state-restore-per-form-expected.txt	2012-06-28 08:48:20 UTC (rev 121420)
@@ -0,0 +1,36 @@
+CONSOLE MESSAGE: line 7: Form state vector:
+CONSOLE MESSAGE: line 7: , text, No owner, 1, visited, 
+CONSOLE MESSAGE: line 7: before, text, No owner, 1, form3-outer1-modified, 
+CONSOLE MESSAGE: line 7: before, text, No owner, 1, noowner1-modified, 
+CONSOLE MESSAGE: line 7: before, text, No owner, 1, form2-outer1-modified, 
+CONSOLE MESSAGE: line 7: common-name1, text, state-restore-per-form-back.html #0, 0, common-name1, 
+CONSOLE MESSAGE: line 7: text, state-restore-per-form-back.html #0, 1, form1-control2-modified, common-name1, 
+CONSOLE MESSAGE: line 7: text, http://example.com/foo.cgi#bar #0, 1, query-changed-control1-modified, username, 
+CONSOLE MESSAGE: line 7: text, http://example.com/foo.cgi#bar #1, 1, username-modified, common-name1, 
+CONSOLE MESSAGE: line 7: text, http://example.com/foo.cgi#bar #1, 1, form3-control2-modified, after, 
+CONSOLE MESSAGE: line 7: text, No owner, 1, form3-outer2-modified, after, 
+CONSOLE MESSAGE: line 12: text, No owner, 1, form2-outer2-modified, 
+CONSOLE MESSAGE: line 13: 
+Confirm we can restore correctly even if the order of forms are changed:
+PASS $("form1-control1").value is "initial"
+PASS $("form1-control2").value is "form1-control2-modified"
+PASS $("form3-control2").value is "form3-control2-modified"
+
+Confirm we ignore the query part of action URLs:
+PASS $("form2-control1").value is "query-changed-control1-modified"
+
+Confirm an additional control in the previous form doesn't take a state for the next form:
+PASS $("form3-control1").value is "username-modified"
+PASS $("form2-added").value is "initial"
+
+Associated controls with form attributes are correctly handled:
+PASS $("form3-outer1").value is "form3-outer1-modified"
+FAIL $("form2-outer1").value should be form2-outer1-modified. Was noowner1-modified.
+FAIL $("noowner2").value should be initial. Was form3-outer2-modified.
+FAIL $("form3-outer2").value should be form3-outer2-modified. Was form2-outer2-modified.
+FAIL $("form2-outer2").value should be form2-outer2-modified. Was initial.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+

Added: trunk/LayoutTests/fast/forms/state-restore-per-form.html (0 => 121420)


--- trunk/LayoutTests/fast/forms/state-restore-per-form.html	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/state-restore-per-form.html	2012-06-28 08:48:20 UTC (rev 121420)
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<div id="console"></div>
+
+<input id=emptyOnFirstVisit>
+
+<script>
+jsTestIsAsync = true;
+
+function makeForms(stage) {
+    var beforeForms = '<div id=parent>' +
+        '<input value=initial id=form3-outer1 name=before form=form3>' +
+        (stage == 1 ? '<input value=initial name=before id=noowner1>' : '') +
+        '<input value=initial id=form2-outer1 name=before form=form2>';
+
+    var backForm = '<form action="" id=form1>' +
+        '<input value=initial id=form1-control1 name=common-name1>' +
+        '<input value=initial id=form1-control2 name=common-name1>' +
+        '</form>';
+
+    var query = stage == 1 ? "?session=0123456" : "?session=7654321111";
+    var additionalControl = stage == 1 ? '' : '<input name=username id=form2-added value=initial>';
+    var sameActionForm1 = '<form action="" + query + '#bar" id=form2>' +
+        '<input value=initial id=form2-control1 name=common-name1>' +
+        additionalControl +
+        '</form>';
+
+    var sameActionForm2 = '<form action="" id=form3>' +
+        '<input value=initial id=form3-control1 name=username>' +
+        '<input value=initial id=form3-control2 name=common-name1>' +
+        '</form>';
+
+    var afterForms = (stage == 1 ? '' : '<input value=initial id=noowner2 name=after>') +
+        '<input value=initial id=form3-outer2 name=after form=form3>' +
+        '<input value=initial id=form2-outer2 name=after form=form2>' +
+        '</div>';
+
+    document.write(beforeForms +
+                   (stage == 1 ? backForm + sameActionForm1 : sameActionForm1 + backForm) +
+                   sameActionForm2 +
+                   afterForms);
+}
+
+function runTest()
+{
+    var state = $('emptyOnFirstVisit');
+    if (!state.value) {
+        // First visit.
+        state.value = 'visited';
+        makeForms(1);
+    
+        setTimeout(function() {
+            $('form1-control2').value = 'form1-control2-modified';
+            $('form2-control1').value = 'query-changed-control1-modified';
+            $('form3-control1').value = 'username-modified';
+            $('form3-control2').value = 'form3-control2-modified';
+            $('noowner1').value = 'noowner1-modified';
+            $('form2-outer1').value = 'form2-outer1-modified';
+            $('form3-outer1').value = 'form3-outer1-modified';
+            $('form2-outer2').value = 'form2-outer2-modified';
+            $('form3-outer2').value = 'form3-outer2-modified';
+            $('form1').submit();
+        }, 0);
+    } else {
+        // Second visit.
+        makeForms(2);
+    
+        debug('Confirm we can restore correctly even if the order of forms are changed:');
+        shouldBeEqualToString('$("form1-control1").value', 'initial');
+        shouldBeEqualToString('$("form1-control2").value', 'form1-control2-modified');
+        shouldBeEqualToString('$("form3-control2").value', 'form3-control2-modified');
+
+        debug('\nConfirm we ignore the query part of action URLs:');
+        shouldBeEqualToString('$("form2-control1").value', 'query-changed-control1-modified');
+
+        debug('\nConfirm an additional control in the previous form doesn\'t take a state for the next form:');
+        shouldBeEqualToString('$("form3-control1").value', 'username-modified');
+        shouldBeEqualToString('$("form2-added").value', 'initial');
+
+        debug('\nAssociated controls with form attributes are correctly handled:');
+        // Some of the followings fail. They will be resolved in webkit.org/b/89962.
+        shouldBeEqualToString('$("form3-outer1").value', 'form3-outer1-modified');
+        shouldBeEqualToString('$("form2-outer1").value', 'form2-outer1-modified');
+
+        shouldBeEqualToString('$("noowner2").value', 'initial');
+        shouldBeEqualToString('$("form3-outer2").value', 'form3-outer2-modified');
+        shouldBeEqualToString('$("form2-outer2").value', 'form2-outer2-modified');
+    
+        $('parent').innerHTML = '';
+        setTimeout(function() { finishJSTest(); }, 0);
+    }
+}
+
+runTest();
+</script>
+<script src=""
+</body>

Modified: trunk/Source/_javascript_Core/ChangeLog (121419 => 121420)


--- trunk/Source/_javascript_Core/ChangeLog	2012-06-28 08:44:50 UTC (rev 121419)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-06-28 08:48:20 UTC (rev 121420)
@@ -1,3 +1,13 @@
+2012-06-28  Kent Tamura  <[email protected]>
+
+        Classify form control states by their owner forms
+        https://bugs.webkit.org/show_bug.cgi?id=89950
+
+        Reviewed by Hajime Morita.
+
+        * _javascript_Core.vcproj/_javascript_Core/_javascript_Core.def:
+        Expose WTF::StringBuilder::canShrink()
+
 2012-06-27  Michael Saboff  <[email protected]>
 
         [Win] jscore-tests flakey

Modified: trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def (121419 => 121420)


--- trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def	2012-06-28 08:44:50 UTC (rev 121419)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def	2012-06-28 08:48:20 UTC (rev 121420)
@@ -85,6 +85,7 @@
     ?callHostFunctionAsConstructor@JSC@@YI_JPAVExecState@1@@Z
     ?callOnMainThread@WTF@@YAXP6AXPAX@Z0@Z
     ?callOnMainThreadAndWait@WTF@@YAXP6AXPAX@Z0@Z
+    ?canShrink@StringBuilder@WTF@@QBE_NXZ
     ?cancelCallOnMainThread@WTF@@YAXP6AXPAX@Z0@Z
     ?capacity@Heap@JSC@@QAEIXZ
     ?changePrototypeTransition@Structure@JSC@@SAPAV12@AAVJSGlobalData@2@PAV12@VJSValue@2@@Z

Modified: trunk/Source/WebCore/ChangeLog (121419 => 121420)


--- trunk/Source/WebCore/ChangeLog	2012-06-28 08:44:50 UTC (rev 121419)
+++ trunk/Source/WebCore/ChangeLog	2012-06-28 08:48:20 UTC (rev 121420)
@@ -1,3 +1,56 @@
+2012-06-28  Kent Tamura  <[email protected]>
+
+        Classify form control states by their owner forms
+        https://bugs.webkit.org/show_bug.cgi?id=89950
+
+        Reviewed by Hajime Morita.
+
+        To improve robustness of the form state restore feature, we classify
+        form control states by their owner forms. Owner forms are identified by
+        their action URLs and index numbers in forms with the same action URLs.
+
+        Implementation approach:
+        Extend FormElementKey class to have "formKey" string, which is a
+        combination of the action URL and an index number, or a fixed string for
+        no form owner.
+        FormKeyGenerator class is responsible to generate the "formKey" strings
+
+        Test: fast/forms/state-restore-per-form.html
+
+        * html/FormController.cpp:
+        (FormKeyGenerator):
+        (WebCore::FormKeyGenerator::create): A factory function.
+        (WebCore::FormKeyGenerator::FormKeyGenerator): A private constructor.
+        (WebCore::createKey):
+        A helper for formKey(). This makes strings like "<action URL> #<index>".
+        (WebCore::FormKeyGenerator::formKey):
+        Returns a formKey for the specified HTMLFormElement*.
+        (WebCore::FormKeyGenerator::willDeleteForm):
+        Unregister HTMLFormElement*. This function is necessary because form
+        restore feature works during parsing and a script might delete form
+        elements.
+        (WebCore::formStateSignature): Bump the version.
+        (WebCore::FormController::formElementsState):
+        Records a formKey string for each of control state.
+        (WebCore::FormController::setStateForNewFormElements):
+        Loads formKeys from stateVector, and uses them for FormElementKey.
+        (WebCore::FormController::takeStateForFormElement):
+        - Construct and destruct FormKeyGenerator if needed.
+        - Passing a formKey for the specified form control to FormElementKey.
+        (WebCore::FormController::willDeleteForm):
+        Delegate to FormKeyGenerator::willDeleteForm.
+
+        (WebCore::FormElementKey::FormElementKey): Add formKey argument and member.
+        (WebCore::FormElementKey::operator=): ditto.
+        (WebCore::FormElementKey::ref): ditto.
+        (WebCore::FormElementKey::deref): ditto.
+        * html/FormController.h:
+        (FormElementKey): Add formKey argument and member.
+        (FormController): Add a FormKeyGenerator member which is used during restoring.
+
+        * html/HTMLFormElement.cpp:
+        (WebCore::HTMLFormElement::~HTMLFormElement): Notify the death to FormController.
+
 2012-06-28  Sheriff Bot  <[email protected]>
 
         Unreviewed, rolling out r121395.

Modified: trunk/Source/WebCore/html/FormController.cpp (121419 => 121420)


--- trunk/Source/WebCore/html/FormController.cpp	2012-06-28 08:44:50 UTC (rev 121419)
+++ trunk/Source/WebCore/html/FormController.cpp	2012-06-28 08:48:20 UTC (rev 121420)
@@ -22,6 +22,8 @@
 #include "FormController.h"
 
 #include "HTMLFormControlElementWithState.h"
+#include "HTMLFormElement.h"
+#include <wtf/text/StringBuilder.h>
 
 namespace WebCore {
 
@@ -67,7 +69,75 @@
 
 // ----------------------------------------------------------------------------
 
+class FormKeyGenerator {
+    WTF_MAKE_NONCOPYABLE(FormKeyGenerator);
+    WTF_MAKE_FAST_ALLOCATED;
 
+public:
+    static PassOwnPtr<FormKeyGenerator> create() { return adoptPtr(new FormKeyGenerator); }
+    AtomicString formKey(const HTMLFormControlElementWithState&);
+    void willDeleteForm(HTMLFormElement*);
+
+private:
+    FormKeyGenerator() { }
+
+    typedef HashMap<HTMLFormElement*, AtomicString> FormToKeyMap;
+    FormToKeyMap m_formToKeyMap;
+    HashSet<AtomicString> m_existingKeys;
+};
+
+static inline AtomicString createKey(HTMLFormElement* form, unsigned index)
+{
+    ASSERT(form);
+    KURL actionURL = form->getURLAttribute(actionAttr);
+    // Remove the query part because it might contain volatile parameters such
+    // as a session key.
+    actionURL.setQuery(String());
+    StringBuilder builder;
+    if (!actionURL.isEmpty())
+        builder.append(actionURL.string());
+    builder.append(" #");
+    builder.append(String::number(index));
+    return builder.toAtomicString();
+}
+
+AtomicString FormKeyGenerator::formKey(const HTMLFormControlElementWithState& control)
+{
+    // Assume contorl with form attribute have no owners because we restores
+    // state during parsing and form owners of such controls might be
+    // indeterminate.
+    HTMLFormElement* form = control.fastHasAttribute(formAttr) ? 0 : control.form();
+    if (!form) {
+        DEFINE_STATIC_LOCAL(AtomicString, formKeyForNoOwner, ("No owner"));
+        return formKeyForNoOwner;
+    }
+    FormToKeyMap::const_iterator it = m_formToKeyMap.find(form);
+    if (it != m_formToKeyMap.end())
+        return it->second;
+
+    AtomicString candidateKey;
+    unsigned index = 0;
+    do {
+        candidateKey = createKey(form, index++);
+    } while (!m_existingKeys.add(candidateKey).isNewEntry);
+    m_formToKeyMap.add(form, candidateKey);
+    return candidateKey;
+}
+
+void FormKeyGenerator::willDeleteForm(HTMLFormElement* form)
+{
+    ASSERT(form);
+    if (m_formToKeyMap.isEmpty())
+        return;
+    FormToKeyMap::iterator it = m_formToKeyMap.find(form);
+    if (it == m_formToKeyMap.end())
+        return;
+    m_existingKeys.remove(it->second);
+    m_formToKeyMap.remove(it);
+}
+
+// ----------------------------------------------------------------------------
+
 FormController::FormController()
 {
 }
@@ -81,14 +151,15 @@
     // 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 3 \n\r=&"));
+    DEFINE_STATIC_LOCAL(String, signature, ("\n\r?% WebKit serialized form state version 5 \n\r=&"));
     return signature;
 }
 
 Vector<String> FormController::formElementsState() const
 {
+    OwnPtr<FormKeyGenerator> keyGenerator = FormKeyGenerator::create();
     Vector<String> stateVector;
-    stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 4 + 1);
+    stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 5 + 1);
     stateVector.append(formStateSignature());
     typedef FormElementListHashSet::const_iterator Iterator;
     Iterator end = m_formElementsWithState.end();
@@ -98,6 +169,7 @@
             continue;
         stateVector.append(elementWithState->name().string());
         stateVector.append(elementWithState->formControlType().string());
+        stateVector.append(keyGenerator->formKey(*elementWithState).string());
         elementWithState->saveFormControlState().serializeTo(stateVector);
     }
     return stateVector;
@@ -120,11 +192,12 @@
     while (i + 2 < stateVector.size()) {
         AtomicString name = stateVector[i++];
         AtomicString type = stateVector[i++];
+        AtomicString formKey = 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());
+        FormElementKey key(name.impl(), type.impl(), formKey.impl());
         Iterator it = m_stateForNewFormElements.find(key);
         if (it != m_stateForNewFormElements.end())
             it->second.append(state);
@@ -142,17 +215,28 @@
 {
     if (m_stateForNewFormElements.isEmpty())
         return FormControlState();
+    if (!m_formKeyGenerator)
+        m_formKeyGenerator = FormKeyGenerator::create();
     typedef FormElementStateMap::iterator Iterator;
-    Iterator it = m_stateForNewFormElements.find(FormElementKey(control.name().impl(), control.type().impl()));
+    Iterator it = m_stateForNewFormElements.find(FormElementKey(control.name().impl(), control.type().impl(), m_formKeyGenerator->formKey(control).impl()));
     if (it == m_stateForNewFormElements.end())
         return FormControlState();
     ASSERT(it->second.size());
     FormControlState state = it->second.takeFirst();
-    if (!it->second.size())
+    if (!it->second.size()) {
         m_stateForNewFormElements.remove(it);
+        if (m_stateForNewFormElements.isEmpty())
+            m_formKeyGenerator.clear();
+    }
     return state;
 }
 
+void FormController::willDeleteForm(HTMLFormElement* form)
+{
+    if (m_formKeyGenerator)
+        m_formKeyGenerator->willDeleteForm(form);
+}
+
 void FormController::registerFormElementWithFormAttribute(FormAssociatedElement* element)
 {
     ASSERT(toHTMLElement(element)->fastHasAttribute(formAttr));
@@ -172,8 +256,10 @@
         (*it)->resetFormOwner();
 }
 
-FormElementKey::FormElementKey(AtomicStringImpl* name, AtomicStringImpl* type)
-    : m_name(name), m_type(type)
+FormElementKey::FormElementKey(AtomicStringImpl* name, AtomicStringImpl* type, AtomicStringImpl* formKey)
+    : m_name(name)
+    , m_type(type)
+    , m_formKey(formKey)
 {
     ref();
 }
@@ -184,7 +270,9 @@
 }
 
 FormElementKey::FormElementKey(const FormElementKey& other)
-    : m_name(other.name()), m_type(other.type())
+    : m_name(other.name())
+    , m_type(other.type())
+    , m_formKey(other.formKey())
 {
     ref();
 }
@@ -195,6 +283,7 @@
     deref();
     m_name = other.name();
     m_type = other.type();
+    m_formKey = other.formKey();
     return *this;
 }
 
@@ -204,6 +293,8 @@
         name()->ref();
     if (type())
         type()->ref();
+    if (formKey())
+        formKey()->ref();
 }
 
 void FormElementKey::deref() const
@@ -212,6 +303,8 @@
         name()->deref();
     if (type())
         type()->deref();
+    if (formKey())
+        formKey()->deref();
 }
 
 unsigned FormElementKeyHash::hash(const FormElementKey& key)

Modified: trunk/Source/WebCore/html/FormController.h (121419 => 121420)


--- trunk/Source/WebCore/html/FormController.h	2012-06-28 08:44:50 UTC (rev 121419)
+++ trunk/Source/WebCore/html/FormController.h	2012-06-28 08:48:20 UTC (rev 121420)
@@ -32,17 +32,20 @@
 namespace WebCore {
 
 class FormAssociatedElement;
+class FormKeyGenerator;
 class HTMLFormControlElementWithState;
+class HTMLFormElement;
 
 class FormElementKey {
 public:
-    FormElementKey(AtomicStringImpl* = 0, AtomicStringImpl* = 0);
+    FormElementKey(AtomicStringImpl* = 0, AtomicStringImpl* = 0, AtomicStringImpl* = 0);
     ~FormElementKey();
     FormElementKey(const FormElementKey&);
     FormElementKey& operator=(const FormElementKey&);
 
     AtomicStringImpl* name() const { return m_name; }
     AtomicStringImpl* type() const { return m_type; }
+    AtomicStringImpl* formKey() const { return m_formKey; }
 
     // Hash table deleted values, which are only constructed and never copied or destroyed.
     FormElementKey(WTF::HashTableDeletedValueType) : m_name(hashTableDeletedValue()) { }
@@ -56,11 +59,12 @@
 
     AtomicStringImpl* m_name;
     AtomicStringImpl* m_type;
+    AtomicStringImpl* m_formKey;
 };
 
 inline bool operator==(const FormElementKey& a, const FormElementKey& b)
 {
-    return a.name() == b.name() && a.type() == b.type();
+    return a.name() == b.name() && a.type() == b.type() && a.formKey() == b.formKey();
 }
 
 struct FormElementKeyHash {
@@ -126,6 +130,7 @@
     // This should be callled only by Document::setStateForNewFormElements().
     void setStateForNewFormElements(const Vector<String>&);
     FormControlState takeStateForFormElement(const HTMLFormControlElementWithState&);
+    void willDeleteForm(HTMLFormElement*);
 
     void registerFormElementWithFormAttribute(FormAssociatedElement*);
     void unregisterFormElementWithFormAttribute(FormAssociatedElement*);
@@ -143,7 +148,7 @@
 
     typedef HashMap<FormElementKey, Deque<FormControlState>, FormElementKeyHash, FormElementKeyHashTraits> FormElementStateMap;
     FormElementStateMap m_stateForNewFormElements;
-    
+    OwnPtr<FormKeyGenerator> m_formKeyGenerator;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/html/HTMLFormElement.cpp (121419 => 121420)


--- trunk/Source/WebCore/html/HTMLFormElement.cpp	2012-06-28 08:44:50 UTC (rev 121419)
+++ trunk/Source/WebCore/html/HTMLFormElement.cpp	2012-06-28 08:48:20 UTC (rev 121420)
@@ -92,6 +92,7 @@
 
 HTMLFormElement::~HTMLFormElement()
 {
+    document()->formController()->willDeleteForm(this);
     if (!shouldAutocomplete())
         document()->unregisterForPageCacheSuspensionCallbacks(this);
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to