2010-12-07 Kenichi Ishibashi <bashi@google.com>
authortkent@chromium.org <tkent@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 7 Dec 2010 09:40:23 +0000 (09:40 +0000)
committertkent@chromium.org <tkent@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 7 Dec 2010 09:40:23 +0000 (09:40 +0000)
        Reviewed by Kent Tamura.

        Let HTMLObjectElement be a form associated element
        https://bugs.webkit.org/show_bug.cgi?id=48821

        Introduces FormAssociatedElement class which would be a super class
        of form assocated elements. Some of member functions and variables of
        HTMLFormControlElement are migrated into this class.
        Following the HTML5 spec, HTMLFormControlElement class and
        HTMLObjectElement class are subclasses of it for now.

        Test: fast/forms/form-collection-elements-order.html

        * Android.mk: Added FormAssociatedElement.cpp
        * CMakeLists.txt: Ditto.
        * GNUmakefile.am: Added FormAssociatedElement.{cpp,h}
        * WebCore.exp.in: Added the symbol for toHTMLElement(FormAssociatedElement*)
        * WebCore.gypi: Added FormAssociatedElement.{cpp,h}
        * WebCore.pro: Ditto.
        * WebCore.vcproj/WebCore.vcproj: Ditto.
        * WebCore.xcodeproj/project.pbxproj: Ditto.
        * dom/CheckedRadioButtons.h: Fixed class forward declaration order.
        * dom/Document.cpp:
        (WebCore::Document::registerFormElementWithFormAttribute): Modified to
        use FormAssociatedElement instead of HTMLFormControlElement
        (WebCore::Document::unregisterFormElementWithFormAttribute): Ditto.
        (WebCore::Document::resetFormElementsOwner):
        * dom/Document.h: Ditto.
        * html/DOMFormData.cpp: Ditto.
        (WebCore::DOMFormData::DOMFormData):
        * html/FormAssociatedElement.cpp: Copied and renamed from WebCore/html/HTMLFormControlElement.cpp.
        (WebCore::FormAssociatedElement::FormAssociatedElement):
        (WebCore::FormAssociatedElement::~FormAssociatedElement):
        (WebCore::FormAssociatedElement::validity):
        (WebCore::FormAssociatedElement::insertedIntoTree):
        (WebCore::FormAssociatedElement::removedFromTree):
        (WebCore::FormAssociatedElement::removeFromForm):
        (WebCore::FormAssociatedElement::resetFormOwner):
        (WebCore::FormAssociatedElement::formAttributeChanged):
        (WebCore::toHTMLElement):
        * html/FormAssociatedElement.h: Ditto.
        (WebCore::FormAssociatedElement::ref):
        (WebCore::FormAssociatedElement::deref):
        (WebCore::FormAssociatedElement::formDestroyed):
        (WebCore::FormAssociatedElement::setForm):
        * html/HTMLElement.h: Changed the access level of findFormAncestor().
        * html/HTMLFormCollection.cpp:
        (WebCore::HTMLFormCollection::item): Modified to use FormAssociatedElement
        instead of HTMLFormControlElement.
        (WebCore::HTMLFormCollection::getNamedFormItem): Ditto.
        (WebCore::HTMLFormCollection::updateNameCache): Ditto.
        * html/HTMLFormControlElement.cpp: Modified regarding with the change of class
        hierarchy.
        (WebCore::HTMLFormControlElement::HTMLFormControlElement):
        (WebCore::HTMLFormControlElement::~HTMLFormControlElement):
        (WebCore::HTMLFormControlElement::insertedIntoTree):
        (WebCore::HTMLFormControlElement::removedFromTree):
        (WebCore::HTMLFormControlElement::supportsFocus):
        (WebCore::HTMLFormControlElement::checkValidity):
        (WebCore::HTMLFormControlElement::virtualForm):
        (WebCore::HTMLFormControlElement::isDefaultButtonForForm):
        (WebCore::HTMLFormControlElement::attributeChanged):
        * html/HTMLFormControlElement.h: Ditto.
        (WebCore::HTMLFormControlElement::form):
        (WebCore::HTMLFormControlElement::disabled):
        (WebCore::HTMLFormControlElement::type):
        (WebCore::HTMLFormControlElement::refFormAssociatedElement):
        (WebCore::HTMLFormControlElement::derefFormAssociatedElement):
        * html/HTMLFormElement.cpp: Modified to use FormAssociatedElement
        instead of HTMLFormControlElement.
        (WebCore::HTMLFormElement::submitImplicitly):
        (WebCore::HTMLFormElement::validateInteractively):
        (WebCore::HTMLFormElement::submit):
        (WebCore::HTMLFormElement::reset):
        (WebCore::HTMLFormElement::formElementIndexWithFormAttribute):
        (WebCore::HTMLFormElement::formElementIndex):
        (WebCore::HTMLFormElement::registerFormElement):
        (WebCore::HTMLFormElement::removeFormElement):
        (WebCore::HTMLFormElement::defaultButton):
        (WebCore::HTMLFormElement::checkValidity):
        (WebCore::HTMLFormElement::collectUnhandledInvalidControls):
        (WebCore::HTMLFormElement::documentDidBecomeActive):
        * html/HTMLFormElement.h: Ditto.
        (WebCore::HTMLFormElement::associatedElements):
        * html/HTMLInputElement.cpp: Ditto.
        (WebCore::HTMLInputElement::updateCheckedRadioButtons):
        * html/HTMLObjectElement.cpp: Modified regarding with the change of class
        hierarchy.
        (WebCore::HTMLObjectElement::HTMLObjectElement):
        (WebCore::HTMLObjectElement::~HTMLObjectElement):
        (WebCore::HTMLObjectElement::create):
        (WebCore::HTMLObjectElement::attributeChanged):
        (WebCore::HTMLObjectElement::insertedIntoTree):
        (WebCore::HTMLObjectElement::removedFromTree):
        (WebCore::HTMLObjectElement::appendFormData):
        (WebCore::HTMLObjectElement::formControlName):
        * html/HTMLObjectElement.h: Ditto.
        (WebCore::HTMLObjectElement::form):
        (WebCore::HTMLObjectElement::isFormControlElement):
        (WebCore::HTMLObjectElement::isEnumeratable):
        (WebCore::HTMLObjectElement::refFormAssociatedElement):
        (WebCore::HTMLObjectElement::derefFormAssociatedElement):
        * html/HTMLTagNames.in: Added constructorNeedsFormElement to object tag.
        * html/ValidationMessage.cpp: Modified to use FormAssociatedElement
        instead of HTMLFormControlElement.
        (WebCore::ValidationMessage::ValidationMessage):
        (WebCore::ValidationMessage::create):
        * html/ValidationMessage.h: Ditto.
        * html/ValidityState.cpp: Ditto.
        (WebCore::ValidityState::validationMessage):
        (WebCore::ValidityState::setCustomErrorMessage):
        (WebCore::ValidityState::valueMissing):
        (WebCore::ValidityState::typeMismatch):
        (WebCore::ValidityState::patternMismatch):
        (WebCore::ValidityState::tooLong):
        (WebCore::ValidityState::rangeUnderflow):
        (WebCore::ValidityState::rangeOverflow):
        (WebCore::ValidityState::stepMismatch):
        * html/ValidityState.h: Ditto.
        (WebCore::ValidityState::create):
        (WebCore::ValidityState::ValidityState):
        * loader/FormSubmission.cpp: Ditto.
        (WebCore::FormSubmission::create):

2010-12-07  Kenichi Ishibashi  <bashi@google.com>

        Reviewed by Kent Tamura.

        Let HTMLObjectElement be a form associated element
        https://bugs.webkit.org/show_bug.cgi?id=48821

        Modified to use FormAssociatedElement instead of HTMLFormControlElement.

        * src/WebFormElement.cpp:
        (WebKit::WebFormElement::getFormControlElements): Modified to use
        FormAssociatedElement instead of HTMLFormControlElement.
        * src/WebPasswordFormUtils.cpp:
        (WebKit::findPasswordFormFields): Ditto.
        * src/WebSearchableFormData.cpp:
        (WebCore::GetButtonToActivate): Ditto.
        (WebCore::HasSuitableTextElement): Ditto.

2010-12-07  Kenichi Ishibashi  <bashi@google.com>

        Reviewed by Kent Tamura.

        Let HTMLObjectElement be a form associated element
        https://bugs.webkit.org/show_bug.cgi?id=48821

        Modified to use FormAssociatedElement instead of HTMLFormControlElement.

        * WebFrame.cpp:
        (WebFrame::elementWithName): Modified to use FormAssociatedElement
        instead of HTMLFormControlElement.
        (WebFrame::controlsInForm): Ditto.

2010-12-07  Kenichi Ishibashi  <bashi@google.com>

        Reviewed by Kent Tamura.

        Let HTMLObjectElement be a form associated element
        https://bugs.webkit.org/show_bug.cgi?id=48821

        Modified to use FormAssociatedElement instead of HTMLFormControlElement.

        * WebView/WebHTMLRepresentation.mm:
        (-[WebHTMLRepresentation elementWithName:inForm:]): Modified to use
        FormAssociatedElement instead of HTMLFormControlElement.
        (-[WebHTMLRepresentation controlsInForm:]): Ditto.

2010-12-07  Kenichi Ishibashi  <bashi@google.com>

        Reviewed by Kent Tamura.

        Let HTMLObjectElement be a form associated element
        https://bugs.webkit.org/show_bug.cgi?id=48821

        Adds a test to ensure the order of form.elements attribute.
        Updates two tests to check whether object elements are handled
        correctly in form.elements attribute.

        * fast/forms/form-attribute-expected.txt: Updated.
        * fast/forms/form-collection-elements-order-expected.txt: Added.
        * fast/forms/form-collection-elements-order.html: Added.
        * fast/forms/script-tests/form-attribute.js: Updated.
        * fast/forms/script-tests/form-collection-elements-order.js: Added.
        (checkOrder):
        * fast/forms/script-tests/form-collection-elements.js: Updated.

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

46 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/forms/form-attribute-expected.txt
LayoutTests/fast/forms/form-collection-elements-expected.txt
LayoutTests/fast/forms/form-collection-elements-order-expected.txt [new file with mode: 0644]
LayoutTests/fast/forms/form-collection-elements-order.html [new file with mode: 0644]
LayoutTests/fast/forms/script-tests/form-attribute.js
LayoutTests/fast/forms/script-tests/form-collection-elements-order.js [new file with mode: 0644]
LayoutTests/fast/forms/script-tests/form-collection-elements.js
WebCore/Android.mk
WebCore/CMakeLists.txt
WebCore/ChangeLog
WebCore/GNUmakefile.am
WebCore/WebCore.exp.in
WebCore/WebCore.gypi
WebCore/WebCore.pro
WebCore/WebCore.vcproj/WebCore.vcproj
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/dom/CheckedRadioButtons.h
WebCore/dom/Document.cpp
WebCore/dom/Document.h
WebCore/html/DOMFormData.cpp
WebCore/html/FormAssociatedElement.cpp [new file with mode: 0644]
WebCore/html/FormAssociatedElement.h [new file with mode: 0644]
WebCore/html/HTMLElement.h
WebCore/html/HTMLFormCollection.cpp
WebCore/html/HTMLFormControlElement.cpp
WebCore/html/HTMLFormControlElement.h
WebCore/html/HTMLFormElement.cpp
WebCore/html/HTMLFormElement.h
WebCore/html/HTMLInputElement.cpp
WebCore/html/HTMLObjectElement.cpp
WebCore/html/HTMLObjectElement.h
WebCore/html/HTMLTagNames.in
WebCore/html/ValidationMessage.cpp
WebCore/html/ValidationMessage.h
WebCore/html/ValidityState.cpp
WebCore/html/ValidityState.h
WebCore/loader/FormSubmission.cpp
WebKit/chromium/ChangeLog
WebKit/chromium/src/WebFormElement.cpp
WebKit/chromium/src/WebPasswordFormUtils.cpp
WebKit/chromium/src/WebSearchableFormData.cpp
WebKit/mac/ChangeLog
WebKit/mac/WebView/WebHTMLRepresentation.mm
WebKit/win/ChangeLog
WebKit/win/WebFrame.cpp

index b53454b..fc7ae81 100644 (file)
@@ -1,3 +1,22 @@
+2010-12-07  Kenichi Ishibashi  <bashi@google.com>
+
+        Reviewed by Kent Tamura.
+
+        Let HTMLObjectElement be a form associated element
+        https://bugs.webkit.org/show_bug.cgi?id=48821
+
+        Adds a test to ensure the order of form.elements attribute.
+        Updates two tests to check whether object elements are handled
+        correctly in form.elements attribute.
+
+        * fast/forms/form-attribute-expected.txt: Updated.
+        * fast/forms/form-collection-elements-order-expected.txt: Added.
+        * fast/forms/form-collection-elements-order.html: Added.
+        * fast/forms/script-tests/form-attribute.js: Updated.
+        * fast/forms/script-tests/form-collection-elements-order.js: Added.
+        (checkOrder):
+        * fast/forms/script-tests/form-collection-elements.js: Updated.
+
 2010-12-06  Yuta Kitamura  <yutak@chromium.org>
 
         Unreviewed.
index 7f20967..52cb252 100644 (file)
@@ -4,14 +4,14 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 - Checks the existence of the form attribute for each form-associated elements.
-FIXME: <label> and <object> don't support the form attribute for now.
+FIXME: <label> doesn't support the form attribute for now.
 PASS document.getElementsByTagName("button")[0].form is owner
 PASS document.getElementsByTagName("fieldset")[0].form is owner
 PASS document.getElementsByTagName("input")[0].form is owner
 PASS document.getElementsByTagName("keygen")[0].form is owner
 FAIL document.getElementsByTagName("label")[0].form should be [object HTMLFormElement]. Was null.
 PASS document.getElementsByTagName("meter")[0].form is owner
-FAIL document.getElementsByTagName("object")[0].form should be [object HTMLFormElement]. Was null.
+PASS document.getElementsByTagName("object")[0].form is owner
 PASS document.getElementsByTagName("output")[0].form is owner
 PASS document.getElementsByTagName("progress")[0].form is owner
 PASS document.getElementsByTagName("select")[0].form is owner
index 9577a44..c0c49a6 100644 (file)
@@ -4,7 +4,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 This test does not add object element as a listed element. Separate test will cover that.
-PASS owner.elements.length is 22
+PASS owner.elements.length is 23
 PASS owner.elements[0].id is 'button1'
 PASS owner.elements[1].id is 'fieldset1'
 PASS owner.elements[2].id is 'inputhidden'
@@ -24,9 +24,10 @@ PASS owner.elements[15].id is 'inputsubmit'
 PASS owner.elements[16].id is 'inputreset'
 PASS owner.elements[17].id is 'inputbutton'
 PASS owner.elements[18].id is 'keygen1'
-PASS owner.elements[19].id is 'output1'
-PASS owner.elements[20].id is 'select1'
-PASS owner.elements[21].id is 'textarea1'
+PASS owner.elements[19].id is 'object1'
+PASS owner.elements[20].id is 'output1'
+PASS owner.elements[21].id is 'select1'
+PASS owner.elements[22].id is 'textarea1'
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/LayoutTests/fast/forms/form-collection-elements-order-expected.txt b/LayoutTests/fast/forms/form-collection-elements-order-expected.txt
new file mode 100644 (file)
index 0000000..4187ac7
--- /dev/null
@@ -0,0 +1,31 @@
+This test examines the order of form associated elements which are classified as 'listed'.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+- Checks the order of form associated elements.
+PASS checkOrder([button, fieldset, input, keygen, object, output, select, textarea]) is "OK"
+
+- Checks the order after some elements removed/inserted.
+PASS checkOrder([button, fieldset, input, keygen, output, select, textarea]) is "OK"
+PASS checkOrder([fieldset, input, keygen, output, select, textarea]) is "OK"
+PASS checkOrder([object, fieldset, input, keygen, output, select, textarea]) is "OK"
+PASS checkOrder([object, fieldset, input, keygen, output, select, textarea, button]) is "OK"
+
+- Checks the order of form associated elements with form attribute.
+PASS checkOrder([button, fieldset, input, keygen, object, output, select, textarea]) is "OK"
+
+- Checks the order after some elements removed/inserted with form attribute.
+PASS checkOrder([button, fieldset, input, keygen, output, select, textarea]) is "OK"
+PASS checkOrder([fieldset, input, keygen, output, select, textarea]) is "OK"
+PASS checkOrder([fieldset, input, keygen, output, select]) is "OK"
+PASS checkOrder([fieldset, input, keygen, object, output, select]) is "OK"
+PASS checkOrder([textarea, fieldset, input, keygen, object, output, select]) is "OK"
+PASS checkOrder([textarea, fieldset, input, keygen, object, output, select, button]) is "OK"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+Test
+
+
+
diff --git a/LayoutTests/fast/forms/form-collection-elements-order.html b/LayoutTests/fast/forms/form-collection-elements-order.html
new file mode 100644 (file)
index 0000000..9975c62
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/form-collection-elements-order.js"></script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
index 082afe6..e34ec46 100644 (file)
@@ -4,7 +4,7 @@ var container = document.createElement('div');
 document.body.appendChild(container);
 
 debug('- Checks the existence of the form attribute for each form-associated elements.');
-debug('FIXME: &lt;label&gt; and &lt;object&gt; don\'t support the form attribute for now.');
+debug('FIXME: &lt;label&gt; doesn\'t support the form attribute for now.');
 container.innerHTML = '<form id=owner></form>' +
     '<button name=victim form=owner />' +
     '<fieldset name=victim form=owner />' +
diff --git a/LayoutTests/fast/forms/script-tests/form-collection-elements-order.js b/LayoutTests/fast/forms/script-tests/form-collection-elements-order.js
new file mode 100644 (file)
index 0000000..195e461
--- /dev/null
@@ -0,0 +1,100 @@
+description("This test examines the order of form associated elements which are classified as 'listed'.");
+
+var container = document.createElement('div');
+document.body.appendChild(container);
+var owner;
+
+function checkOrder(victims) {
+    if (owner.elements.length != victims.length)
+        return 'length mismatch, elements.length = ' + owner.elements.length +
+               ', expected length = ' + victims.length;
+    for (var i = 0; i < victims.length; ++i)
+        if (owner.elements[i] != victims[i])
+            return 'element mismatch at index ' + i;
+    return 'OK';
+}
+
+debug('- Checks the order of form associated elements.');
+container.innerHTML = '<form id=owner>' +
+    '<button name=victim></button>' +
+    '<fieldset name=victim>Test</fieldset>' +
+    '<input name=victim/>' +
+    '<keygen name=victim></keygen>' +
+    '<label name=victim></label>' +
+    '<meter name=victim></meter>' +
+    '<object name=victim></object>' +
+    '<output name=victim></output>' +
+    '<progress name=victim></progress>' +
+    '<select name=victim></select>' +
+    '<textarea name=victim></textarea>'+
+    '</form>';
+owner = document.getElementById('owner');
+var button = document.getElementsByTagName('button')[0];
+var fieldset = document.getElementsByTagName('fieldset')[0];
+var input = document.getElementsByTagName('input')[0];
+var keygen = document.getElementsByTagName('keygen')[0];
+var label = document.getElementsByTagName('label')[0];
+var meter = document.getElementsByTagName('meter')[0];
+var object = document.getElementsByTagName('object')[0];
+var output = document.getElementsByTagName('output')[0];
+var progress = document.getElementsByTagName('progress')[0];
+var select = document.getElementsByTagName('select')[0];
+var textarea = document.getElementsByTagName('textarea')[0];
+shouldBe('checkOrder([button, fieldset, input, keygen, object, output, select, textarea])', '"OK"');
+
+debug('');
+debug('- Checks the order after some elements removed/inserted.');
+owner.removeChild(object);
+shouldBe('checkOrder([button, fieldset, input, keygen, output, select, textarea])', '"OK"');
+owner.removeChild(button);
+shouldBe('checkOrder([fieldset, input, keygen, output, select, textarea])', '"OK"');
+owner.insertBefore(object, fieldset);
+shouldBe('checkOrder([object, fieldset, input, keygen, output, select, textarea])', '"OK"');
+owner.appendChild(button);
+shouldBe('checkOrder([object, fieldset, input, keygen, output, select, textarea, button])', '"OK"');
+
+debug('');
+debug('- Checks the order of form associated elements with form attribute.');
+container.innerHTML = '<button name=victim form=owner></button>' +
+    '<fieldset name=victim form=owner>Test</fieldset>' +
+    '<input name=victim form=owner/>' +
+    '<keygen name=victim form=owner></keygen>' +
+    '<form id=owner>' +
+    '<label name=victim></label>' +
+    '<meter name=victim></meter>' +
+    '<object name=victim></object>' +
+    '</form>' +
+    '<output name=victim form=owner></output>' +
+    '<progress name=victim form=owner></progress>' +
+    '<select name=victim form=owner></select>' +
+    '<textarea name=victim form=owner></textarea>';
+owner = document.getElementById('owner');
+button = document.getElementsByTagName('button')[0];
+fieldset = document.getElementsByTagName('fieldset')[0];
+input = document.getElementsByTagName('input')[0];
+keygen = document.getElementsByTagName('keygen')[0];
+label = document.getElementsByTagName('label')[0];
+meter = document.getElementsByTagName('meter')[0];
+object = document.getElementsByTagName('object')[0];
+output = document.getElementsByTagName('output')[0];
+progress = document.getElementsByTagName('progress')[0];
+select = document.getElementsByTagName('select')[0];
+textarea = document.getElementsByTagName('textarea')[0];
+shouldBe('checkOrder([button, fieldset, input, keygen, object, output, select, textarea])', '"OK"');
+
+debug('');
+debug('- Checks the order after some elements removed/inserted with form attribute.');
+owner.removeChild(object);
+shouldBe('checkOrder([button, fieldset, input, keygen, output, select, textarea])', '"OK"');
+container.removeChild(button);
+shouldBe('checkOrder([fieldset, input, keygen, output, select, textarea])', '"OK"');
+container.removeChild(textarea);
+shouldBe('checkOrder([fieldset, input, keygen, output, select])', '"OK"');
+owner.appendChild(object);
+shouldBe('checkOrder([fieldset, input, keygen, object, output, select])', '"OK"');
+container.insertBefore(textarea, fieldset);
+shouldBe('checkOrder([textarea, fieldset, input, keygen, object, output, select])', '"OK"');
+container.appendChild(button);
+shouldBe('checkOrder([textarea, fieldset, input, keygen, object, output, select, button])', '"OK"');
+
+var successfullyParsed = true;
index 3b7eb69..7fb9ab8 100644 (file)
@@ -27,6 +27,7 @@ container.innerHTML = '<form id="form1">' +
     '<keygen id=keygen1></keygen>' +
     '<label id=label1></label>' +
     '<meter id=meter1></meter>' +
+    '<object id=object1></object>' +
     '<output id=output1></output>' +
     '<progress id=progress1></progress>' +
     '<select id=select1>' +
@@ -38,7 +39,7 @@ container.innerHTML = '<form id="form1">' +
 
 var owner = document.getElementById('form1');
 
-shouldBe('owner.elements.length', '22');
+shouldBe('owner.elements.length', '23');
 shouldBe('owner.elements[0].id', "'button1'");
 shouldBe('owner.elements[1].id', "'fieldset1'");
 shouldBe('owner.elements[2].id', "'inputhidden'");
@@ -58,9 +59,10 @@ shouldBe('owner.elements[15].id', "'inputsubmit'");
 shouldBe('owner.elements[16].id', "'inputreset'");
 shouldBe('owner.elements[17].id', "'inputbutton'");
 shouldBe('owner.elements[18].id', "'keygen1'");
-shouldBe('owner.elements[19].id', "'output1'");
-shouldBe('owner.elements[20].id', "'select1'");
-shouldBe('owner.elements[21].id', "'textarea1'");
+shouldBe('owner.elements[19].id', "'object1'");
+shouldBe('owner.elements[20].id', "'output1'");
+shouldBe('owner.elements[21].id', "'select1'");
+shouldBe('owner.elements[22].id', "'textarea1'");
 
 
 var successfullyParsed = true;
index 1544679..0916edb 100644 (file)
@@ -277,6 +277,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
        html/DateTimeLocalInputType.cpp \
        html/EmailInputType.cpp \
        html/FileInputType.cpp \
+       html/FormAssociatedElement.cpp \
        html/FormDataList.cpp \
        html/HTMLAllCollection.cpp \
        html/HTMLCollection.cpp \
index 731661a..5db4c8a 100644 (file)
@@ -991,6 +991,7 @@ SET(WebCore_SOURCES
     html/EmailInputType.cpp
     html/FTPDirectoryDocument.cpp
     html/FileInputType.cpp
+    html/FormAssociatedElement.cpp
     html/FormDataList.cpp
     html/HTMLAllCollection.cpp
     html/HTMLAnchorElement.cpp
index d487f26..97b423b 100644 (file)
@@ -1,3 +1,129 @@
+2010-12-07  Kenichi Ishibashi  <bashi@google.com>
+
+        Reviewed by Kent Tamura.
+
+        Let HTMLObjectElement be a form associated element
+        https://bugs.webkit.org/show_bug.cgi?id=48821
+
+        Introduces FormAssociatedElement class which would be a super class
+        of form assocated elements. Some of member functions and variables of
+        HTMLFormControlElement are migrated into this class.
+        Following the HTML5 spec, HTMLFormControlElement class and
+        HTMLObjectElement class are subclasses of it for now.
+
+        Test: fast/forms/form-collection-elements-order.html
+
+        * Android.mk: Added FormAssociatedElement.cpp
+        * CMakeLists.txt: Ditto.
+        * GNUmakefile.am: Added FormAssociatedElement.{cpp,h}
+        * WebCore.exp.in: Added the symbol for toHTMLElement(FormAssociatedElement*)
+        * WebCore.gypi: Added FormAssociatedElement.{cpp,h}
+        * WebCore.pro: Ditto.
+        * WebCore.vcproj/WebCore.vcproj: Ditto.
+        * WebCore.xcodeproj/project.pbxproj: Ditto.
+        * dom/CheckedRadioButtons.h: Fixed class forward declaration order.
+        * dom/Document.cpp:
+        (WebCore::Document::registerFormElementWithFormAttribute): Modified to
+        use FormAssociatedElement instead of HTMLFormControlElement
+        (WebCore::Document::unregisterFormElementWithFormAttribute): Ditto.
+        (WebCore::Document::resetFormElementsOwner):
+        * dom/Document.h: Ditto.
+        * html/DOMFormData.cpp: Ditto.
+        (WebCore::DOMFormData::DOMFormData):
+        * html/FormAssociatedElement.cpp: Copied and renamed from WebCore/html/HTMLFormControlElement.cpp.
+        (WebCore::FormAssociatedElement::FormAssociatedElement):
+        (WebCore::FormAssociatedElement::~FormAssociatedElement):
+        (WebCore::FormAssociatedElement::validity):
+        (WebCore::FormAssociatedElement::insertedIntoTree):
+        (WebCore::FormAssociatedElement::removedFromTree):
+        (WebCore::FormAssociatedElement::removeFromForm):
+        (WebCore::FormAssociatedElement::resetFormOwner):
+        (WebCore::FormAssociatedElement::formAttributeChanged):
+        (WebCore::toHTMLElement):
+        * html/FormAssociatedElement.h: Ditto.
+        (WebCore::FormAssociatedElement::ref):
+        (WebCore::FormAssociatedElement::deref):
+        (WebCore::FormAssociatedElement::formDestroyed):
+        (WebCore::FormAssociatedElement::setForm):
+        * html/HTMLElement.h: Changed the access level of findFormAncestor().
+        * html/HTMLFormCollection.cpp:
+        (WebCore::HTMLFormCollection::item): Modified to use FormAssociatedElement
+        instead of HTMLFormControlElement.
+        (WebCore::HTMLFormCollection::getNamedFormItem): Ditto.
+        (WebCore::HTMLFormCollection::updateNameCache): Ditto.
+        * html/HTMLFormControlElement.cpp: Modified regarding with the change of class
+        hierarchy.
+        (WebCore::HTMLFormControlElement::HTMLFormControlElement):
+        (WebCore::HTMLFormControlElement::~HTMLFormControlElement):
+        (WebCore::HTMLFormControlElement::insertedIntoTree):
+        (WebCore::HTMLFormControlElement::removedFromTree):
+        (WebCore::HTMLFormControlElement::supportsFocus):
+        (WebCore::HTMLFormControlElement::checkValidity):
+        (WebCore::HTMLFormControlElement::virtualForm):
+        (WebCore::HTMLFormControlElement::isDefaultButtonForForm):
+        (WebCore::HTMLFormControlElement::attributeChanged):
+        * html/HTMLFormControlElement.h: Ditto.
+        (WebCore::HTMLFormControlElement::form):
+        (WebCore::HTMLFormControlElement::disabled):
+        (WebCore::HTMLFormControlElement::type):
+        (WebCore::HTMLFormControlElement::refFormAssociatedElement):
+        (WebCore::HTMLFormControlElement::derefFormAssociatedElement):
+        * html/HTMLFormElement.cpp: Modified to use FormAssociatedElement
+        instead of HTMLFormControlElement.
+        (WebCore::HTMLFormElement::submitImplicitly):
+        (WebCore::HTMLFormElement::validateInteractively):
+        (WebCore::HTMLFormElement::submit):
+        (WebCore::HTMLFormElement::reset):
+        (WebCore::HTMLFormElement::formElementIndexWithFormAttribute):
+        (WebCore::HTMLFormElement::formElementIndex):
+        (WebCore::HTMLFormElement::registerFormElement):
+        (WebCore::HTMLFormElement::removeFormElement):
+        (WebCore::HTMLFormElement::defaultButton):
+        (WebCore::HTMLFormElement::checkValidity):
+        (WebCore::HTMLFormElement::collectUnhandledInvalidControls):
+        (WebCore::HTMLFormElement::documentDidBecomeActive):
+        * html/HTMLFormElement.h: Ditto.
+        (WebCore::HTMLFormElement::associatedElements):
+        * html/HTMLInputElement.cpp: Ditto.
+        (WebCore::HTMLInputElement::updateCheckedRadioButtons):
+        * html/HTMLObjectElement.cpp: Modified regarding with the change of class
+        hierarchy.
+        (WebCore::HTMLObjectElement::HTMLObjectElement):
+        (WebCore::HTMLObjectElement::~HTMLObjectElement):
+        (WebCore::HTMLObjectElement::create):
+        (WebCore::HTMLObjectElement::attributeChanged):
+        (WebCore::HTMLObjectElement::insertedIntoTree):
+        (WebCore::HTMLObjectElement::removedFromTree):
+        (WebCore::HTMLObjectElement::appendFormData):
+        (WebCore::HTMLObjectElement::formControlName):
+        * html/HTMLObjectElement.h: Ditto.
+        (WebCore::HTMLObjectElement::form):
+        (WebCore::HTMLObjectElement::isFormControlElement):
+        (WebCore::HTMLObjectElement::isEnumeratable):
+        (WebCore::HTMLObjectElement::refFormAssociatedElement):
+        (WebCore::HTMLObjectElement::derefFormAssociatedElement):
+        * html/HTMLTagNames.in: Added constructorNeedsFormElement to object tag.
+        * html/ValidationMessage.cpp: Modified to use FormAssociatedElement
+        instead of HTMLFormControlElement.
+        (WebCore::ValidationMessage::ValidationMessage):
+        (WebCore::ValidationMessage::create):
+        * html/ValidationMessage.h: Ditto.
+        * html/ValidityState.cpp: Ditto.
+        (WebCore::ValidityState::validationMessage):
+        (WebCore::ValidityState::setCustomErrorMessage):
+        (WebCore::ValidityState::valueMissing):
+        (WebCore::ValidityState::typeMismatch):
+        (WebCore::ValidityState::patternMismatch):
+        (WebCore::ValidityState::tooLong):
+        (WebCore::ValidityState::rangeUnderflow):
+        (WebCore::ValidityState::rangeOverflow):
+        (WebCore::ValidityState::stepMismatch):
+        * html/ValidityState.h: Ditto.
+        (WebCore::ValidityState::create):
+        (WebCore::ValidityState::ValidityState):
+        * loader/FormSubmission.cpp: Ditto.
+        (WebCore::FormSubmission::create):
+
 2010-12-06  Pavel Feldman  <pfeldman@chromium.org>
 
         Not reviewed. Rolling out r72988 for breaking iframes.
index 6b26464..34038d7 100644 (file)
@@ -1585,6 +1585,8 @@ webcore_sources += \
        WebCore/html/EmailInputType.h \
        WebCore/html/FileInputType.cpp \
        WebCore/html/FileInputType.h \
+       WebCore/html/FormAssociatedElement.cpp \
+       WebCore/html/FormAssociatedElement.h \
        WebCore/html/FormDataList.cpp \
        WebCore/html/FormDataList.h \
        WebCore/html/FTPDirectoryDocument.cpp \
index 2f37c4c..f229e87 100644 (file)
@@ -296,6 +296,7 @@ __ZN7WebCore13KeyboardEventC1ERKN3WTF12AtomicStringEbbPNS_9DOMWindowERKNS1_6Stri
 __ZN7WebCore13TypingCommand39insertParagraphSeparatorInQuotedContentEPNS_8DocumentE
 __ZN7WebCore13createWrapperEPN3JSC9ExecStateEPNS_17JSDOMGlobalObjectEPNS_4NodeE
 __ZN7WebCore13toDeviceSpaceERKNS_9FloatRectEP8NSWindow
+__ZN7WebCore13toHTMLElementEPNS_21FormAssociatedElementE
 __ZN7WebCore13toJSDOMWindowEN3JSC7JSValueE
 __ZN7WebCore14CachedResource12removeClientEPNS_20CachedResourceClientE
 __ZN7WebCore14CachedResource9addClientEPNS_20CachedResourceClientE
index 01c5c89..bb4eb1c 100644 (file)
             'html/FTPDirectoryDocument.h',
             'html/FileInputType.cpp',
             'html/FileInputType.h',
+            'html/FormAssociatedElement.cpp',
+            'html/FormAssociatedElement.h',
             'html/FormDataList.cpp',
             'html/FormDataList.h',
             'html/HTMLAllCollection.cpp',
index a2eee7e..40a016c 100644 (file)
@@ -882,6 +882,7 @@ SOURCES += \
     html/EmailInputType.cpp \
     html/FTPDirectoryDocument.cpp \
     html/FileInputType.cpp \
+    html/FormAssociatedElement.cpp \
     html/FormDataList.cpp \
     html/HTMLAllCollection.cpp \
     html/HTMLAnchorElement.cpp \
@@ -1795,6 +1796,7 @@ HEADERS += \
     html/DOMFormData.h \
     html/DOMSettableTokenList.h \
     html/DOMTokenList.h \
+    html/FormAssociatedElement.h \
     html/FormDataList.h \
     html/FTPDirectoryDocument.h \
     html/HTMLAllCollection.h \
index 3a04bac..df77e40 100755 (executable)
                                >
                        </File>
                        <File
+                               RelativePath="..\html\FormAssociatedElement.cpp"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\html\FormAssociatedElement.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\html\FormDataList.cpp"
                                >
                        </File>
index 4f7ed78..4f1616c 100644 (file)
                49FFBF1D11C8550E006A7118 /* GraphicsContext3DMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49FFBF1C11C8550E006A7118 /* GraphicsContext3DMac.mm */; };
                49FFBF3F11C93EE3006A7118 /* WebGLLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 49FFBF3D11C93EE3006A7118 /* WebGLLayer.h */; };
                49FFBF4011C93EE3006A7118 /* WebGLLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49FFBF3E11C93EE3006A7118 /* WebGLLayer.mm */; };
+               4A0DA2FE129B241900AB61E1 /* FormAssociatedElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A0DA2FC129B241900AB61E1 /* FormAssociatedElement.cpp */; };
+               4A0DA2FF129B241900AB61E1 /* FormAssociatedElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A0DA2FD129B241900AB61E1 /* FormAssociatedElement.h */; settings = {ATTRIBUTES = (Private, ); }; };
                4A8C96EB0BE69032004EEFF0 /* SelectionControllerMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A8C96EA0BE69032004EEFF0 /* SelectionControllerMac.mm */; };
                4ACBC0BE12713CBD0094F9B2 /* ClassList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4ACBC0BC12713CBD0094F9B2 /* ClassList.cpp */; };
                4ACBC0BF12713CBD0094F9B2 /* ClassList.h in Headers */ = {isa = PBXBuildFile; fileRef = 4ACBC0BD12713CBD0094F9B2 /* ClassList.h */; };
                49FFBF1C11C8550E006A7118 /* GraphicsContext3DMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = GraphicsContext3DMac.mm; sourceTree = "<group>"; };
                49FFBF3D11C93EE3006A7118 /* WebGLLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebGLLayer.h; sourceTree = "<group>"; };
                49FFBF3E11C93EE3006A7118 /* WebGLLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebGLLayer.mm; sourceTree = "<group>"; };
+               4A0DA2FC129B241900AB61E1 /* FormAssociatedElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FormAssociatedElement.cpp; sourceTree = "<group>"; };
+               4A0DA2FD129B241900AB61E1 /* FormAssociatedElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormAssociatedElement.h; sourceTree = "<group>"; };
                4A8C96EA0BE69032004EEFF0 /* SelectionControllerMac.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = SelectionControllerMac.mm; path = mac/SelectionControllerMac.mm; sourceTree = "<group>"; };
                4ACBC0BC12713CBD0094F9B2 /* ClassList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClassList.cpp; sourceTree = "<group>"; };
                4ACBC0BD12713CBD0094F9B2 /* ClassList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClassList.h; sourceTree = "<group>"; };
                                F55B3D881251F12D003EF269 /* EmailInputType.h */,
                                F55B3D891251F12D003EF269 /* FileInputType.cpp */,
                                F55B3D8A1251F12D003EF269 /* FileInputType.h */,
+                               4A0DA2FC129B241900AB61E1 /* FormAssociatedElement.cpp */,
+                               4A0DA2FD129B241900AB61E1 /* FormAssociatedElement.h */,
                                A8136D370973A8E700D74463 /* FormDataList.cpp */,
                                A8136D360973A8E700D74463 /* FormDataList.h */,
                                97205AAD123928CA00B17380 /* FTPDirectoryDocument.cpp */,
                                3784C34B0E11AA34007D8D48 /* FontTraitsMask.h in Headers */,
                                B734B183119B991D006587BD /* FontTranscoder.h in Headers */,
                                A80E6CED0A1989CA007FB8C5 /* FontValue.h in Headers */,
+                               4A0DA2FF129B241900AB61E1 /* FormAssociatedElement.h in Headers */,
                                D05CED2A0A40BB2C00C5AF38 /* FormatBlockCommand.h in Headers */,
                                514C76700CE923A1007EF3CD /* FormData.h in Headers */,
                                085B92BB0EFDE73D00E6123C /* FormDataBuilder.h in Headers */,
                                B5320D6C122A24E9002D1440 /* FontPlatformDataCocoa.mm in Sources */,
                                B734B181119B9911006587BD /* FontTranscoder.cpp in Sources */,
                                A80E6CF10A1989CA007FB8C5 /* FontValue.cpp in Sources */,
+                               4A0DA2FE129B241900AB61E1 /* FormAssociatedElement.cpp in Sources */,
                                D05CED290A40BB2C00C5AF38 /* FormatBlockCommand.cpp in Sources */,
                                514C766F0CE923A1007EF3CD /* FormData.cpp in Sources */,
                                085B92BA0EFDE73D00E6123C /* FormDataBuilder.cpp in Sources */,
index de7b712..0fa457a 100644 (file)
@@ -27,8 +27,8 @@
 
 namespace WebCore {
 
-class HTMLInputElement;
 class HTMLFormControlElement;
+class HTMLInputElement;
 
 class CheckedRadioButtons {
 public:
index e182214..75d8b9b 100644 (file)
@@ -61,6 +61,7 @@
 #include "EventNames.h"
 #include "ExceptionCode.h"
 #include "FocusController.h"
+#include "FormAssociatedElement.h"
 #include "Frame.h"
 #include "FrameLoader.h"
 #include "FrameLoaderClient.h"
@@ -4388,23 +4389,23 @@ void Document::setIconURL(const String& iconURL, const String& type)
         f->loader()->setIconURL(m_iconURL);
 }
 
-void Document::registerFormElementWithFormAttribute(Element* control)
+void Document::registerFormElementWithFormAttribute(FormAssociatedElement* element)
 {
-    ASSERT(control->fastHasAttribute(formAttr));
-    m_formElementsWithFormAttribute.add(control);
+    ASSERT(toHTMLElement(element)->fastHasAttribute(formAttr));
+    m_formElementsWithFormAttribute.add(element);
 }
 
-void Document::unregisterFormElementWithFormAttribute(Element* control)
+void Document::unregisterFormElementWithFormAttribute(FormAssociatedElement* element)
 {
-    m_formElementsWithFormAttribute.remove(control);
+    m_formElementsWithFormAttribute.remove(element);
 }
 
 void Document::resetFormElementsOwner(HTMLFormElement* form)
 {
-    typedef FormElementListHashSet::iterator Iterator;
+    typedef FormAssociatedElementListHashSet::iterator Iterator;
     Iterator end = m_formElementsWithFormAttribute.end();
     for (Iterator it = m_formElementsWithFormAttribute.begin(); it != end; ++it)
-        static_cast<HTMLFormControlElement*>(*it)->resetFormOwner(form);
+        (*it)->resetFormOwner(form);
 }
 
 void Document::setUseSecureKeyboardEntryWhenActive(bool usesSecureKeyboard)
index bc06883..5a4f5ca 100644 (file)
@@ -77,6 +77,7 @@ class Element;
 class EntityReference;
 class Event;
 class EventListener;
+class FormAssociatedElement;
 class Frame;
 class FrameView;
 class HTMLCanvasElement;
@@ -491,8 +492,8 @@ public:
     bool hasStateForNewFormElements() const;
     bool takeStateForFormElement(AtomicStringImpl* name, AtomicStringImpl* type, String& state);
 
-    void registerFormElementWithFormAttribute(Element*);
-    void unregisterFormElementWithFormAttribute(Element*);
+    void registerFormElementWithFormAttribute(FormAssociatedElement*);
+    void unregisterFormElementWithFormAttribute(FormAssociatedElement*);
     void resetFormElementsOwner(HTMLFormElement*);
 
     FrameView* view() const; // can be NULL
@@ -1216,7 +1217,8 @@ private:
 
     typedef ListHashSet<Element*, 64> FormElementListHashSet;
     FormElementListHashSet m_formElementsWithState;
-    FormElementListHashSet m_formElementsWithFormAttribute;
+    typedef ListHashSet<FormAssociatedElement*, 32> FormAssociatedElementListHashSet;
+    FormAssociatedElementListHashSet m_formElementsWithFormAttribute;
 
     typedef HashMap<FormElementKey, Vector<String>, FormElementKeyHash, FormElementKeyHashTraits> FormElementStateMap;
     FormElementStateMap m_stateForNewFormElements;
index 0ece637..bd20155 100644 (file)
@@ -51,9 +51,9 @@ DOMFormData::DOMFormData(HTMLFormElement* form)
         return;
 
     for (unsigned i = 0; i < form->associatedElements().size(); ++i) {
-        HTMLFormControlElement* control = form->associatedElements()[i];
-        if (!control->disabled())
-            control->appendFormData(*this, true);
+        FormAssociatedElement* element = form->associatedElements()[i];
+        if (!toHTMLElement(element)->disabled())
+            element->appendFormData(*this, true);
     }
 }
 
diff --git a/WebCore/html/FormAssociatedElement.cpp b/WebCore/html/FormAssociatedElement.cpp
new file mode 100644 (file)
index 0000000..a97c0e2
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "FormAssociatedElement.h"
+
+#include "HTMLFormControlElement.h"
+#include "HTMLFormElement.h"
+#include "HTMLNames.h"
+#include "HTMLObjectElement.h"
+#include "ValidityState.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+FormAssociatedElement::FormAssociatedElement(HTMLFormElement* form)
+    : m_form(form)
+{
+}
+
+FormAssociatedElement::~FormAssociatedElement()
+{
+}
+
+ValidityState* FormAssociatedElement::validity()
+{
+    if (!m_validityState)
+        m_validityState = ValidityState::create(this);
+
+    return m_validityState.get();
+}
+
+void FormAssociatedElement::insertedIntoTree()
+{
+    HTMLElement* element = toHTMLElement(this);
+    if (element->fastHasAttribute(formAttr)) {
+        element->document()->registerFormElementWithFormAttribute(this);
+        Element* formElement = element->document()->getElementById(element->fastGetAttribute(formAttr));
+        if (formElement && formElement->hasTagName(formTag)) {
+            if (m_form)
+                m_form->removeFormElement(this);
+            m_form = static_cast<HTMLFormElement*>(formElement);
+            m_form->registerFormElement(this);
+        }
+    }
+    if (!m_form) {
+        // This handles the case of a new form element being created by
+        // JavaScript and inserted inside a form.  In the case of the parser
+        // setting a form, we will already have a non-null value for m_form,
+        // and so we don't need to do anything.
+        m_form = element->findFormAncestor();
+        if (m_form)
+            m_form->registerFormElement(this);
+    }
+}
+
+static inline Node* findRoot(Node* n)
+{
+    Node* root = n;
+    for (; n; n = n->parentNode())
+        root = n;
+    return root;
+}
+
+void FormAssociatedElement::removedFromTree()
+{
+    HTMLElement* element = toHTMLElement(this);
+    if (element->fastHasAttribute(formAttr))
+        element->document()->unregisterFormElementWithFormAttribute(this);
+
+    // If the form and element are both in the same tree, preserve the connection to the form.
+    // Otherwise, null out our form and remove ourselves from the form's list of elements.
+    if (m_form && findRoot(element) != findRoot(m_form))
+        removeFromForm();
+}
+
+void FormAssociatedElement::removeFromForm()
+{
+    if (!m_form)
+        return;
+    m_form->removeFormElement(this);
+    m_form = 0;
+}
+
+void FormAssociatedElement::resetFormOwner(HTMLFormElement* form)
+{
+    HTMLElement* element = toHTMLElement(this);
+    const AtomicString& formId(element->fastGetAttribute(formAttr));
+    if (m_form) {
+        if (formId.isNull())
+            return;
+        m_form->removeFormElement(this);
+    }
+    m_form = 0;
+    if (!formId.isNull()) {
+        // The HTML5 spec says that the element should be associated with
+        // the first element in the document to have an ID that equal to
+        // the value of form attribute, so we put the result of
+        // document()->getElementById() over the given element.
+        Element* firstElement = element->document()->getElementById(formId);
+        if (firstElement && firstElement->hasTagName(formTag))
+            m_form = static_cast<HTMLFormElement*>(firstElement);
+        else
+            m_form = form;
+    } else
+        m_form = element->findFormAncestor();
+    if (m_form)
+        m_form->registerFormElement(this);
+}
+
+void FormAssociatedElement::formAttributeChanged()
+{
+    HTMLElement* element = toHTMLElement(this);
+    if (!element->fastHasAttribute(formAttr)) {
+        // The form attribute removed. We need to reset form owner here.
+        if (m_form)
+            m_form->removeFormElement(this);
+        m_form = element->findFormAncestor();
+        if (m_form)
+            form()->registerFormElement(this);
+    } else
+        resetFormOwner(0);
+}
+
+const HTMLElement* toHTMLElement(const FormAssociatedElement* associatedElement)
+{
+    if (associatedElement->isFormControlElement())
+        return static_cast<const HTMLFormControlElement*>(associatedElement);
+    // Assumes the element is an HTMLObjectElement
+    const HTMLElement* element = static_cast<const HTMLObjectElement*>(associatedElement);
+    ASSERT(element->hasTagName(objectTag));
+    return element;
+}
+
+HTMLElement* toHTMLElement(FormAssociatedElement* associatedElement)
+{
+    return const_cast<HTMLElement*>(toHTMLElement(static_cast<const FormAssociatedElement*>(associatedElement)));
+}
+
+} // namespace Webcore
diff --git a/WebCore/html/FormAssociatedElement.h b/WebCore/html/FormAssociatedElement.h
new file mode 100644 (file)
index 0000000..3c8c6e1
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef FormAssociatedElement_h
+#define FormAssociatedElement_h
+
+#include "HTMLElement.h"
+
+namespace WebCore {
+
+class FormDataList;
+class HTMLFormElement;
+class ValidationMessage;
+class ValidityState;
+class VisibleSelection;
+
+class FormAssociatedElement {
+public:
+    virtual ~FormAssociatedElement();
+
+    void ref() { refFormAssociatedElement(); }
+    void deref() { derefFormAssociatedElement(); }
+
+    HTMLFormElement* form() const { return m_form; }
+    ValidityState* validity();
+
+    virtual bool isFormControlElement() const = 0;
+    virtual bool isEnumeratable() const = 0;
+
+    const AtomicString& name() const { return formControlName(); }
+
+    // Override in derived classes to get the encoded name=value pair for submitting.
+    // Return true for a successful control (see HTML4-17.13.2).
+    virtual bool appendFormData(FormDataList&, bool) { return false; }
+
+    virtual void formDestroyed() { m_form = 0; }
+
+    void resetFormOwner(HTMLFormElement*);
+
+protected:
+    FormAssociatedElement(HTMLFormElement*);
+
+    void insertedIntoTree();
+    void removedFromTree();
+
+    void setForm(HTMLFormElement* form) { m_form = form; }
+    void removeFromForm();
+    void formAttributeChanged();
+
+private:
+    virtual const AtomicString& formControlName() const = 0;
+
+    virtual void refFormAssociatedElement() = 0;
+    virtual void derefFormAssociatedElement() = 0;
+
+    HTMLFormElement* m_form;
+    OwnPtr<ValidityState> m_validityState;
+};
+
+HTMLElement* toHTMLElement(FormAssociatedElement*);
+const HTMLElement* toHTMLElement(const FormAssociatedElement*);
+
+} // namespace
+
+#endif // FormAssociatedElement_h
index 1660e2a..63ce110 100644 (file)
@@ -82,6 +82,8 @@ public:
 
     static void addHTMLAlignmentToStyledElement(StyledElement*, Attribute*);
 
+    HTMLFormElement* findFormAncestor() const;
+
 protected:
     HTMLElement(const QualifiedName& tagName, Document*);
 
@@ -90,8 +92,6 @@ protected:
     virtual bool mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const;
     virtual void parseMappedAttribute(Attribute*);
 
-    HTMLFormElement* findFormAncestor() const;
-
 private:
     virtual String nodeName() const;
 
index 4147f29..4f52b9d 100644 (file)
@@ -78,12 +78,12 @@ Node* HTMLFormCollection::item(unsigned index) const
         info()->elementsArrayPosition = 0;
     }
 
-    Vector<HTMLFormControlElement*>& elementsArray = static_cast<HTMLFormElement*>(base())->m_associatedElements;
+    Vector<FormAssociatedElement*>& elementsArray = static_cast<HTMLFormElement*>(base())->m_associatedElements;
     unsigned currentIndex = info()->position;
     
     for (unsigned i = info()->elementsArrayPosition; i < elementsArray.size(); i++) {
-        HTMLFormControlElement* element = elementsArray[i];
-        if (element->isEnumeratable()) {
+        if (elementsArray[i]->isEnumeratable()) {
+            HTMLElement* element = toHTMLElement(elementsArray[i]);
             if (index == currentIndex) {
                 info()->position = index;
                 info()->current = element;
@@ -110,21 +110,22 @@ Element* HTMLFormCollection::getNamedFormItem(const QualifiedName& attrName, con
 
     bool foundInputElements = false;
     for (unsigned i = 0; i < form->m_associatedElements.size(); ++i) {
-        HTMLFormControlElement* e = form->m_associatedElements[i];
-        if (e->isEnumeratable() && e->getAttribute(attrName) == name) {
+        FormAssociatedElement* associatedElement = form->m_associatedElements[i];
+        HTMLElement* element = toHTMLElement(associatedElement);
+        if (associatedElement->isEnumeratable() && element->getAttribute(attrName) == name) {
             foundInputElements = true;
             if (!duplicateNumber)
-                return e;
+                return element;
             --duplicateNumber;
         }
     }
 
     if (!foundInputElements) {
         for (unsigned i = 0; i < form->m_imageElements.size(); ++i) {
-            HTMLImageElement* e = form->m_imageElements[i];
-            if (e->getAttribute(attrName) == name) {
+            HTMLImageElement* element = form->m_imageElements[i];
+            if (element->getAttribute(attrName) == name) {
                 if (!duplicateNumber)
-                    return e;
+                    return element;
                 --duplicateNumber;
             }
         }
@@ -191,10 +192,11 @@ void HTMLFormCollection::updateNameCache() const
     HTMLFormElement* f = static_cast<HTMLFormElement*>(base());
 
     for (unsigned i = 0; i < f->m_associatedElements.size(); ++i) {
-        HTMLFormControlElement* e = f->m_associatedElements[i];
-        if (e->isEnumeratable()) {
-            const AtomicString& idAttrVal = e->getIdAttribute();
-            const AtomicString& nameAttrVal = e->getAttribute(nameAttr);
+        FormAssociatedElement* associatedElement = f->m_associatedElements[i];
+        if (associatedElement->isEnumeratable()) {
+            HTMLElement* element = toHTMLElement(associatedElement);
+            const AtomicString& idAttrVal = element->getIdAttribute();
+            const AtomicString& nameAttrVal = element->getAttribute(nameAttr);
             if (!idAttrVal.isEmpty()) {
                 // add to id cache
                 Vector<Element*>* idVector = info()->idCache.get(idAttrVal.impl());
@@ -202,7 +204,7 @@ void HTMLFormCollection::updateNameCache() const
                     idVector = new Vector<Element*>;
                     info()->idCache.add(idAttrVal.impl(), idVector);
                 }
-                idVector->append(e);
+                idVector->append(element);
                 foundInputElements.add(idAttrVal.impl());
             }
             if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal) {
@@ -212,16 +214,16 @@ void HTMLFormCollection::updateNameCache() const
                     nameVector = new Vector<Element*>;
                     info()->nameCache.add(nameAttrVal.impl(), nameVector);
                 }
-                nameVector->append(e);
+                nameVector->append(element);
                 foundInputElements.add(nameAttrVal.impl());
             }
         }
     }
 
     for (unsigned i = 0; i < f->m_imageElements.size(); ++i) {
-        HTMLImageElement* e = f->m_imageElements[i];
-        const AtomicString& idAttrVal = e->getIdAttribute();
-        const AtomicString& nameAttrVal = e->getAttribute(nameAttr);
+        HTMLImageElement* element = f->m_imageElements[i];
+        const AtomicString& idAttrVal = element->getIdAttribute();
+        const AtomicString& nameAttrVal = element->getAttribute(nameAttr);
         if (!idAttrVal.isEmpty() && !foundInputElements.contains(idAttrVal.impl())) {
             // add to id cache
             Vector<Element*>* idVector = info()->idCache.get(idAttrVal.impl());
@@ -229,7 +231,7 @@ void HTMLFormCollection::updateNameCache() const
                 idVector = new Vector<Element*>;
                 info()->idCache.add(idAttrVal.impl(), idVector);
             }
-            idVector->append(e);
+            idVector->append(element);
         }
         if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && !foundInputElements.contains(nameAttrVal.impl())) {
             // add to name cache
@@ -238,7 +240,7 @@ void HTMLFormCollection::updateNameCache() const
                 nameVector = new Vector<Element*>;
                 info()->nameCache.add(nameAttrVal.impl(), nameVector);
             }
-            nameVector->append(e);
+            nameVector->append(element);
         }
     }
 
index 2f5d414..7015fa2 100644 (file)
@@ -57,7 +57,7 @@ using namespace std;
 
 HTMLFormControlElement::HTMLFormControlElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
     : HTMLElement(tagName, document)
-    , m_form(form)
+    , FormAssociatedElement(form)
     , m_disabled(false)
     , m_readOnly(false)
     , m_required(false)
@@ -66,16 +66,16 @@ HTMLFormControlElement::HTMLFormControlElement(const QualifiedName& tagName, Doc
     , m_willValidate(true)
     , m_isValid(true)
 {
-    if (!m_form)
-        m_form = findFormAncestor();
-    if (m_form)
-        m_form->registerFormElement(this);
+    if (!this->form())
+        setForm(findFormAncestor());
+    if (this->form())
+        this->form()->registerFormElement(this);
 }
 
 HTMLFormControlElement::~HTMLFormControlElement()
 {
-    if (m_form)
-        m_form->removeFormElement(this);
+    if (form())
+        form()->removeFormElement(this);
 }
 
 void HTMLFormControlElement::detach()
@@ -89,14 +89,6 @@ bool HTMLFormControlElement::formNoValidate() const
     return !getAttribute(formnovalidateAttr).isNull();
 }
 
-ValidityState* HTMLFormControlElement::validity()
-{
-    if (!m_validityState)
-        m_validityState = ValidityState::create(this);
-
-    return m_validityState.get();
-}
-
 void HTMLFormControlElement::parseMappedAttribute(Attribute* attr)
 {
     if (attr->name() == disabledAttr) {
@@ -154,51 +146,16 @@ void HTMLFormControlElement::attach()
 
 void HTMLFormControlElement::insertedIntoTree(bool deep)
 {
-    if (fastHasAttribute(formAttr)) {
-        document()->registerFormElementWithFormAttribute(this);
-        Element* element = document()->getElementById(fastGetAttribute(formAttr));
-        if (element && element->hasTagName(formTag)) {
-            if (m_form)
-                m_form->removeFormElement(this);
-            m_form = static_cast<HTMLFormElement*>(element);
-            m_form->registerFormElement(this);
-        }
-    }
-    if (!m_form) {
-        // This handles the case of a new form element being created by
-        // JavaScript and inserted inside a form.  In the case of the parser
-        // setting a form, we will already have a non-null value for m_form, 
-        // and so we don't need to do anything.
-        m_form = findFormAncestor();
-        if (m_form)
-            m_form->registerFormElement(this);
-        else
-            document()->checkedRadioButtons().addButton(this);
-    }
+    FormAssociatedElement::insertedIntoTree();
+    if (!form())
+        document()->checkedRadioButtons().addButton(this);
 
     HTMLElement::insertedIntoTree(deep);
 }
 
-static inline Node* findRoot(Node* n)
-{
-    Node* root = n;
-    for (; n; n = n->parentNode())
-        root = n;
-    return root;
-}
-
 void HTMLFormControlElement::removedFromTree(bool deep)
 {
-    if (fastHasAttribute(formAttr))
-        document()->unregisterFormElementWithFormAttribute(this);
-
-    // If the form and element are both in the same tree, preserve the connection to the form.
-    // Otherwise, null out our form and remove ourselves from the form's list of elements.
-    if (m_form && findRoot(this) != findRoot(m_form)) {
-        m_form->removeFormElement(this);
-        m_form = 0;
-    }
-
+    FormAssociatedElement::removedFromTree();
     HTMLElement::removedFromTree(deep);
 }
 
@@ -254,7 +211,7 @@ void HTMLFormControlElement::recalcStyle(StyleChange change)
 
 bool HTMLFormControlElement::supportsFocus() const
 {
-    return !disabled();
+    return !m_disabled;
 }
 
 bool HTMLFormControlElement::isFocusable() const
@@ -366,7 +323,7 @@ String HTMLFormControlElement::visibleValidationMessage() const
     return m_validationMessage ? m_validationMessage->message() : String();
 }
 
-bool HTMLFormControlElement::checkValidity(Vector<RefPtr<HTMLFormControlElement> >* unhandledInvalidControls)
+bool HTMLFormControlElement::checkValidity(Vector<RefPtr<FormAssociatedElement> >* unhandledInvalidControls)
 {
     if (!willValidate() || isValidFormControlElement())
         return true;
@@ -408,7 +365,7 @@ void HTMLFormControlElement::setCustomValidity(const String& error)
 {
     validity()->setCustomErrorMessage(error);
 }
-    
+
 void HTMLFormControlElement::dispatchFocusEvent()
 {
     if (document()->page())
@@ -428,64 +385,22 @@ void HTMLFormControlElement::dispatchBlurEvent()
 
 HTMLFormElement* HTMLFormControlElement::virtualForm() const
 {
-    return m_form;
+    return FormAssociatedElement::form();
 }
 
 bool HTMLFormControlElement::isDefaultButtonForForm() const
 {
-    return isSuccessfulSubmitButton() && m_form && m_form->defaultButton() == this;
-}
-
-void HTMLFormControlElement::removeFromForm()
-{
-    if (!m_form)
-        return;
-    m_form->removeFormElement(this);
-    m_form = 0;
-}
-
-void HTMLFormControlElement::resetFormOwner(HTMLFormElement* form)
-{
-    if (m_form) {
-        if (!fastHasAttribute(formAttr))
-            return;
-        m_form->removeFormElement(this);
-    }
-    m_form = 0;
-    if (fastHasAttribute(formAttr)) {
-        // The HTML5 spec says that the element should be associated with
-        // the first element in the document to have an ID that equal to
-        // the value of form attribute, so we put the result of
-        // document()->getElementById() over the given element.
-        Element* firstElement = document()->getElementById(fastGetAttribute(formAttr));
-        if (firstElement && firstElement->hasTagName(formTag))
-            m_form = static_cast<HTMLFormElement*>(firstElement);
-        else
-            m_form = form;
-    } else
-        m_form = findFormAncestor();
-    if (m_form)
-        m_form->registerFormElement(this);
-    else
-        document()->checkedRadioButtons().addButton(this);
+    return isSuccessfulSubmitButton() && form() && form()->defaultButton() == this;
 }
 
 void HTMLFormControlElement::attributeChanged(Attribute* attr, bool preserveDecls)
 {
     if (attr->name() == formAttr) {
-        if (!fastHasAttribute(formAttr)) {
-            // The form attribute removed. We need to reset form owner here.
-            if (m_form)
-                m_form->removeFormElement(this);
-            m_form = findFormAncestor();
-            if (m_form)
-                m_form->registerFormElement(this);
-            else
-                document()->checkedRadioButtons().addButton(this);
-        } else
-            resetFormOwner(0);
-    }
-    HTMLElement::attributeChanged(attr, preserveDecls);
+        formAttributeChanged();
+        if (!form())
+            document()->checkedRadioButtons().addButton(this);
+    } else
+        HTMLElement::attributeChanged(attr, preserveDecls);
 }
 
 bool HTMLFormControlElement::isLabelable() const
@@ -516,7 +431,7 @@ PassRefPtr<NodeList> HTMLFormControlElement::labels()
     
     return LabelsNodeList::create(this);
 }
-    
+
 HTMLFormControlElementWithState::HTMLFormControlElementWithState(const QualifiedName& tagName, Document* doc, HTMLFormElement* f)
     : HTMLFormControlElement(tagName, doc, f)
 {
index 568f63e..e5d741b 100644 (file)
@@ -24,6 +24,7 @@
 #ifndef HTMLFormControlElement_h
 #define HTMLFormControlElement_h
 
+#include "FormAssociatedElement.h"
 #include "HTMLElement.h"
 
 namespace WebCore {
@@ -35,14 +36,14 @@ class ValidationMessage;
 class ValidityState;
 class VisibleSelection;
 
-// FIXME: The HTML5 specification calls these form-associated elements.
-// So consider renaming this to HTMLFormAssociatedElement.
-class HTMLFormControlElement : public HTMLElement {
+// HTMLFormControlElement is the default implementation of FormAssociatedElement,
+// and form-associated element implementations should use HTMLFormControlElement
+// unless there is a special reason.
+class HTMLFormControlElement : public HTMLElement, public FormAssociatedElement {
 public:
     virtual ~HTMLFormControlElement();
 
-    HTMLFormElement* form() const { return m_form; }
-    ValidityState* validity();
+    HTMLFormElement* form() const { return FormAssociatedElement::form(); }
 
     bool formNoValidate() const;
 
@@ -53,7 +54,7 @@ public:
 
     virtual void dispatchFormControlChangeEvent();
 
-    bool disabled() const { return m_disabled; }
+    virtual bool disabled() const { return m_disabled; }
     void setDisabled(bool);
 
     virtual bool isFocusable() const;
@@ -65,7 +66,6 @@ public:
     bool required() const;
 
     const AtomicString& type() const { return formControlType(); }
-    const AtomicString& name() const { return formControlName(); }
 
     void setName(const AtomicString& name);
 
@@ -87,21 +87,21 @@ public:
     String validationMessage();
     void updateVisibleValidationMessage();
     void hideVisibleValidationMessage();
-    bool checkValidity(Vector<RefPtr<HTMLFormControlElement> >* unhandledInvalidControls = 0);
+    bool checkValidity(Vector<RefPtr<FormAssociatedElement> >* unhandledInvalidControls = 0);
     // This must be called when a validation constraint or control value is changed.
     void setNeedsValidityCheck();
     void setCustomValidity(const String&);
 
-    void formDestroyed() { m_form = 0; }
-
     bool isLabelable() const;
     PassRefPtr<NodeList> labels();
-    
+
     bool readOnly() const { return m_readOnly; }
 
-    void resetFormOwner(HTMLFormElement*);
     virtual void attributeChanged(Attribute*, bool preserveDecls = false);
 
+    using TreeShared<ContainerNode>::ref;
+    using TreeShared<ContainerNode>::deref;
+
 protected:
     HTMLFormControlElement(const QualifiedName& tagName, Document*, HTMLFormElement*);
 
@@ -119,8 +119,6 @@ protected:
     virtual void dispatchBlurEvent();
     virtual void detach();
 
-    void removeFromForm();
-
     // This must be called any time the result of willValidate() has changed.
     void setNeedsWillValidateCheck();
     virtual bool recalcWillValidate() const;
@@ -129,6 +127,9 @@ private:
     virtual const AtomicString& formControlName() const;
     virtual const AtomicString& formControlType() const = 0;
 
+    virtual void refFormAssociatedElement() { ref(); }
+    virtual void derefFormAssociatedElement() { deref(); }
+
     virtual bool isFormControlElement() const { return true; }
 
     virtual bool supportsFocus() const;
@@ -140,8 +141,6 @@ private:
     virtual bool isValidFormControlElement();
     String visibleValidationMessage() const;
 
-    HTMLFormElement* m_form;
-    OwnPtr<ValidityState> m_validityState;
     OwnPtr<ValidationMessage> m_validationMessage;
     bool m_disabled : 1;
     bool m_readOnly : 1;
index 1aeb360..79d622f 100644 (file)
@@ -179,7 +179,10 @@ void HTMLFormElement::submitImplicitly(Event* event, bool fromImplicitSubmission
 {
     int submissionTriggerCount = 0;
     for (unsigned i = 0; i < m_associatedElements.size(); ++i) {
-        HTMLFormControlElement* formElement = m_associatedElements[i];
+        FormAssociatedElement* formAssociatedElement = m_associatedElements[i];
+        if (!formAssociatedElement->isFormControlElement())
+            continue;
+        HTMLFormControlElement* formElement = static_cast<HTMLFormControlElement*>(formAssociatedElement);
         if (formElement->isSuccessfulSubmitButton()) {
             if (formElement->renderer()) {
                 formElement->dispatchSimulatedClick(event);
@@ -213,10 +216,12 @@ bool HTMLFormElement::validateInteractively(Event* event)
     if (submitElement && submitElement->formNoValidate())
         return true;
 
-    for (unsigned i = 0; i < m_associatedElements.size(); ++i)
-        m_associatedElements[i]->hideVisibleValidationMessage();
+    for (unsigned i = 0; i < m_associatedElements.size(); ++i) {
+        if (m_associatedElements[i]->isFormControlElement())
+            static_cast<HTMLFormControlElement*>(m_associatedElements[i])->hideVisibleValidationMessage();
+    }
 
-    Vector<RefPtr<HTMLFormControlElement> > unhandledInvalidControls;
+    Vector<RefPtr<FormAssociatedElement> > unhandledInvalidControls;
     collectUnhandledInvalidControls(unhandledInvalidControls);
     if (unhandledInvalidControls.isEmpty())
         return true;
@@ -225,7 +230,8 @@ bool HTMLFormElement::validateInteractively(Event* event)
     RefPtr<HTMLFormElement> protector(this);
     // Focus on the first focusable control and show a validation message.
     for (unsigned i = 0; i < unhandledInvalidControls.size(); ++i) {
-        HTMLFormControlElement* unhandled = unhandledInvalidControls[i].get();
+        FormAssociatedElement* unhandledAssociatedElement = unhandledInvalidControls[i].get();
+        HTMLElement* unhandled = toHTMLElement(unhandledAssociatedElement);
         if (unhandled->isFocusable() && unhandled->inDocument()) {
             RefPtr<Document> originalDocument(unhandled->document());
             unhandled->scrollIntoViewIfNeeded(false);
@@ -234,7 +240,8 @@ bool HTMLFormElement::validateInteractively(Event* event)
             // moved to another document.
             if (unhandled->isFocusable() && unhandled->inDocument() && originalDocument == unhandled->document()) {
                 unhandled->focus();
-                unhandled->updateVisibleValidationMessage();
+                if (unhandled->isFormControlElement())
+                    static_cast<HTMLFormControlElement*>(unhandled)->updateVisibleValidationMessage();
                 break;
             }
         }
@@ -242,11 +249,12 @@ bool HTMLFormElement::validateInteractively(Event* event)
     // Warn about all of unfocusable controls.
     if (Frame* frame = document()->frame()) {
         for (unsigned i = 0; i < unhandledInvalidControls.size(); ++i) {
-            HTMLFormControlElement* unhandled = unhandledInvalidControls[i].get();
+            FormAssociatedElement* unhandledAssociatedElement = unhandledInvalidControls[i].get();
+            HTMLElement* unhandled = toHTMLElement(unhandledAssociatedElement);
             if (unhandled->isFocusable() && unhandled->inDocument())
                 continue;
             String message("An invalid form control with name='%name' is not focusable.");
-            message.replace("%name", unhandled->name());
+            message.replace("%name", unhandledAssociatedElement->name());
             frame->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, ErrorMessageLevel, message, 0, document()->url().string());
         }
     }
@@ -307,8 +315,11 @@ void HTMLFormElement::submit(Event* event, bool activateSubmitButton, bool proce
     bool needButtonActivation = activateSubmitButton; // do we need to activate a submit button?
 
     for (unsigned i = 0; i < m_associatedElements.size(); ++i) {
-        HTMLFormControlElement* control = m_associatedElements[i];
+        FormAssociatedElement* associatedElement = m_associatedElements[i];
+        if (!associatedElement->isFormControlElement())
+            continue;
         if (needButtonActivation) {
+            HTMLFormControlElement* control = static_cast<HTMLFormControlElement*>(associatedElement);
             if (control->isActivatedSubmit())
                 needButtonActivation = false;
             else if (firstSuccessfulSubmitButton == 0 && control->isSuccessfulSubmitButton())
@@ -342,8 +353,10 @@ void HTMLFormElement::reset()
         return;
     }
 
-    for (unsigned i = 0; i < m_associatedElements.size(); ++i)
-        m_associatedElements[i]->reset();
+    for (unsigned i = 0; i < m_associatedElements.size(); ++i) {
+        if (m_associatedElements[i]->isFormControlElement())
+            static_cast<HTMLFormControlElement*>(m_associatedElements[i])->reset();
+    }
 
     m_inreset = false;
 }
@@ -396,7 +409,7 @@ template<class T, size_t n> static void removeFromVector(Vector<T*, n> & vec, T*
         }
 }
 
-unsigned HTMLFormElement::formElementIndexWithFormAttribute(HTMLFormControlElement* element)
+unsigned HTMLFormElement::formElementIndexWithFormAttribute(Element* element)
 {
     // Compares the position of the form element and the inserted element.
     // Updates the indeces in order to the relation of the position:
@@ -416,57 +429,64 @@ unsigned HTMLFormElement::formElementIndexWithFormAttribute(HTMLFormControlEleme
     unsigned left = 0, right = m_associatedElements.size() - 1;
     while (left != right) {
         unsigned middle = left + ((right - left) / 2);
-        position = element->compareDocumentPosition(m_associatedElements[middle]);
+        position = element->compareDocumentPosition(toHTMLElement(m_associatedElements[middle]));
         if (position & DOCUMENT_POSITION_FOLLOWING)
             right = middle;
         else
             left = middle + 1;
     }
 
-    position = element->compareDocumentPosition(m_associatedElements[left]);
+    position = element->compareDocumentPosition(toHTMLElement(m_associatedElements[left]));
     if (position & DOCUMENT_POSITION_FOLLOWING)
         return left;
     return left + 1;
 }
 
-unsigned HTMLFormElement::formElementIndex(HTMLFormControlElement* e)
+unsigned HTMLFormElement::formElementIndex(FormAssociatedElement* associatedElement)
 {
+    HTMLElement* element = toHTMLElement(associatedElement);
     // Treats separately the case where this element has the form attribute
     // for performance consideration.
-    if (e->fastHasAttribute(formAttr))
-        return formElementIndexWithFormAttribute(e);
+    if (element->fastHasAttribute(formAttr))
+        return formElementIndexWithFormAttribute(element);
 
     // Check for the special case where this element is the very last thing in
     // the form's tree of children; we don't want to walk the entire tree in that
     // common case that occurs during parsing; instead we'll just return a value
     // that says "add this form element to the end of the array".
-    if (e->traverseNextNode(this)) {
+    if (element->traverseNextNode(this)) {
         unsigned i = m_associatedElementsBeforeIndex;
         for (Node* node = this; node; node = node->traverseNextNode(this)) {
-            if (node == e) {
+            if (node == element) {
                 ++m_associatedElementsAfterIndex;
                 return i;
             }
             if (node->isHTMLElement()
-                    && static_cast<Element*>(node)->isFormControlElement()
-                    && static_cast<HTMLFormControlElement*>(node)->form() == this)
+                    && (static_cast<Element*>(node)->isFormControlElement()
+                        || node->hasTagName(objectTag))
+                    && static_cast<HTMLElement*>(node)->form() == this)
                 ++i;
         }
     }
     return m_associatedElementsAfterIndex++;
 }
 
-void HTMLFormElement::registerFormElement(HTMLFormControlElement* e)
+void HTMLFormElement::registerFormElement(FormAssociatedElement* e)
 {
-    document()->checkedRadioButtons().removeButton(e);
-    m_checkedRadioButtons.addButton(e);
+    if (e->isFormControlElement()) {
+        HTMLFormControlElement* element = static_cast<HTMLFormControlElement*>(e);
+        document()->checkedRadioButtons().removeButton(element);
+        m_checkedRadioButtons.addButton(element);
+    }
     m_associatedElements.insert(formElementIndex(e), e);
 }
 
-void HTMLFormElement::removeFormElement(HTMLFormControlElement* e)
+void HTMLFormElement::removeFormElement(FormAssociatedElement* e)
 {
-    m_checkedRadioButtons.removeButton(e);
-    if (e->fastHasAttribute(formAttr)) {
+    if (e->isFormControlElement())
+        m_checkedRadioButtons.removeButton(static_cast<HTMLFormControlElement*>(e));
+    HTMLElement* element = toHTMLElement(e);
+    if (element->fastHasAttribute(formAttr)) {
         unsigned index;
         for (index = 0; index < m_associatedElements.size(); ++index)
             if (m_associatedElements[index] == e)
@@ -554,7 +574,9 @@ bool HTMLFormElement::wasUserSubmitted() const
 HTMLFormControlElement* HTMLFormElement::defaultButton() const
 {
     for (unsigned i = 0; i < m_associatedElements.size(); ++i) {
-        HTMLFormControlElement* control = m_associatedElements[i];
+        if (!m_associatedElements[i]->isFormControlElement())
+            continue;
+        HTMLFormControlElement* control = static_cast<HTMLFormControlElement*>(m_associatedElements[i]);
         if (control->isSuccessfulSubmitButton())
             return control;
     }
@@ -564,23 +586,23 @@ HTMLFormControlElement* HTMLFormElement::defaultButton() const
 
 bool HTMLFormElement::checkValidity()
 {
-    Vector<RefPtr<HTMLFormControlElement> > controls;
+    Vector<RefPtr<FormAssociatedElement> > controls;
     collectUnhandledInvalidControls(controls);
     return controls.isEmpty();
 }
 
-void HTMLFormElement::collectUnhandledInvalidControls(Vector<RefPtr<HTMLFormControlElement> >& unhandledInvalidControls)
+void HTMLFormElement::collectUnhandledInvalidControls(Vector<RefPtr<FormAssociatedElement> >& unhandledInvalidControls)
 {
     RefPtr<HTMLFormElement> protector(this);
     // Copy m_associatedElements because event handlers called from
     // HTMLFormControlElement::checkValidity() might change m_associatedElements.
-    Vector<RefPtr<HTMLFormControlElement> > elements;
+    Vector<RefPtr<FormAssociatedElement> > elements;
     elements.reserveCapacity(m_associatedElements.size());
     for (unsigned i = 0; i < m_associatedElements.size(); ++i)
         elements.append(m_associatedElements[i]);
     for (unsigned i = 0; i < elements.size(); ++i) {
-        if (elements[i]->form() == this)
-            elements[i]->checkValidity(&unhandledInvalidControls);
+        if (elements[i]->form() == this && elements[i]->isFormControlElement())
+            static_cast<HTMLFormControlElement*>(elements[i].get())->checkValidity(&unhandledInvalidControls);
     }
 }
 
@@ -627,8 +649,10 @@ void HTMLFormElement::documentDidBecomeActive()
 {
     ASSERT(!m_autocomplete);
 
-    for (unsigned i = 0; i < m_associatedElements.size(); ++i)
-        m_associatedElements[i]->reset();
+    for (unsigned i = 0; i < m_associatedElements.size(); ++i) {
+        if (m_associatedElements[i]->isFormControlElement())
+            static_cast<HTMLFormControlElement*>(m_associatedElements[i])->reset();
+    }
 }
 
 void HTMLFormElement::willMoveToNewOwnerDocument()
index 4e06bec..e18b524 100644 (file)
@@ -33,6 +33,7 @@
 namespace WebCore {
 
 class Event;
+class FormAssociatedElement;
 class FormData;
 class HTMLFormControlElement;
 class HTMLImageElement;
@@ -64,8 +65,8 @@ public:
 
     // FIXME: Should rename these two functions to say "form control"
     // or "form-associated element" instead of "form element".
-    void registerFormElement(HTMLFormControlElement*);
-    void removeFormElement(HTMLFormControlElement*);
+    void registerFormElement(FormAssociatedElement*);
+    void removeFormElement(FormAssociatedElement*);
     void registerImgElement(HTMLImageElement*);
     void removeImgElement(HTMLImageElement*);
 
@@ -109,7 +110,7 @@ public:
 
     CheckedRadioButtons& checkedRadioButtons() { return m_checkedRadioButtons; }
 
-    const Vector<HTMLFormControlElement*>& associatedElements() const { return m_associatedElements; }
+    const Vector<FormAssociatedElement*>& associatedElements() const { return m_associatedElements; }
 
 private:
     HTMLFormElement(const QualifiedName&, Document*);
@@ -131,13 +132,13 @@ private:
 
     void submit(Event*, bool activateSubmitButton, bool processingUserGesture, FormSubmissionTrigger);
 
-    unsigned formElementIndexWithFormAttribute(HTMLFormControlElement*);
-    unsigned formElementIndex(HTMLFormControlElement*);
+    unsigned formElementIndexWithFormAttribute(Element*);
+    unsigned formElementIndex(FormAssociatedElement*);
     // Returns true if the submission should be proceeded.
     bool validateInteractively(Event*);
     // Validates each of the controls, and stores controls of which 'invalid'
     // event was not canceled to the specified vector.
-    void collectUnhandledInvalidControls(Vector<RefPtr<HTMLFormControlElement> >&);
+    void collectUnhandledInvalidControls(Vector<RefPtr<FormAssociatedElement> >&);
 
     friend class HTMLFormCollection;
 
@@ -151,7 +152,7 @@ private:
 
     unsigned m_associatedElementsBeforeIndex;
     unsigned m_associatedElementsAfterIndex;
-    Vector<HTMLFormControlElement*> m_associatedElements;
+    Vector<FormAssociatedElement*> m_associatedElements;
     Vector<HTMLImageElement*> m_imageElements;
 
     bool m_wasUserSubmitted;
index 4f9339d..f1f32ee 100644 (file)
@@ -139,9 +139,11 @@ void HTMLInputElement::updateCheckedRadioButtons()
         checkedRadioButtons().addButton(this);
 
     if (form()) {
-        const Vector<HTMLFormControlElement*>& controls = form()->associatedElements();
+        const Vector<FormAssociatedElement*>& controls = form()->associatedElements();
         for (unsigned i = 0; i < controls.size(); ++i) {
-            HTMLFormControlElement* control = controls[i];
+            if (!controls[i]->isFormControlElement())
+                continue;
+            HTMLFormControlElement* control = static_cast<HTMLFormControlElement*>(controls[i]);
             if (control->name() != name())
                 continue;
             if (control->type() != type())
index 69974a8..c80d374 100644 (file)
@@ -46,17 +46,28 @@ namespace WebCore {
 
 using namespace HTMLNames;
 
-inline HTMLObjectElement::HTMLObjectElement(const QualifiedName& tagName, Document* document, bool createdByParser) 
+inline HTMLObjectElement::HTMLObjectElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form, bool createdByParser) 
     : HTMLPlugInImageElement(tagName, document, createdByParser)
+    , FormAssociatedElement(form)
     , m_docNamedItem(true)
     , m_useFallbackContent(false)
 {
     ASSERT(hasTagName(objectTag));
+    if (!this->form())
+        setForm(findFormAncestor());
+    if (this->form())
+        this->form()->registerFormElement(this);
 }
 
-PassRefPtr<HTMLObjectElement> HTMLObjectElement::create(const QualifiedName& tagName, Document* document, bool createdByParser)
+inline HTMLObjectElement::~HTMLObjectElement()
 {
-    return adoptRef(new HTMLObjectElement(tagName, document, createdByParser));
+    if (form())
+        form()->removeFormElement(this);
+}
+
+PassRefPtr<HTMLObjectElement> HTMLObjectElement::create(const QualifiedName& tagName, Document* document, HTMLFormElement* form, bool createdByParser)
+{
+    return adoptRef(new HTMLObjectElement(tagName, document, form, createdByParser));
 }
 
 RenderWidget* HTMLObjectElement::renderWidgetForJSBindings() const
@@ -313,6 +324,14 @@ void HTMLObjectElement::removedFromDocument()
     HTMLPlugInImageElement::removedFromDocument();
 }
 
+void HTMLObjectElement::attributeChanged(Attribute* attr, bool preserveDecls)
+{
+    if (attr->name() == formAttr)
+        formAttributeChanged();
+    else
+        HTMLPlugInImageElement::attributeChanged(attr, preserveDecls);
+}
+
 void HTMLObjectElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
 {
     updateDocNamedItem();
@@ -453,4 +472,27 @@ void HTMLObjectElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) con
         addSubresourceURL(urls, document()->completeURL(useMap));
 }
 
+void HTMLObjectElement::insertedIntoTree(bool deep)
+{
+    FormAssociatedElement::insertedIntoTree();
+    HTMLPlugInImageElement::insertedIntoTree(deep);
+}
+
+void HTMLObjectElement::removedFromTree(bool deep)
+{
+    FormAssociatedElement::removedFromTree();
+    HTMLPlugInImageElement::removedFromTree(deep);
+}
+
+bool HTMLObjectElement::appendFormData(FormDataList&, bool)
+{
+    // FIXME: Implements this function.
+    return false;
+}
+
+const AtomicString& HTMLObjectElement::formControlName() const
+{
+    return m_name.isNull() ? emptyAtom : m_name;
+}
+
 }
index a4609cb..e420628 100644 (file)
 #ifndef HTMLObjectElement_h
 #define HTMLObjectElement_h
 
+#include "FormAssociatedElement.h"
 #include "HTMLPlugInImageElement.h"
 
 namespace WebCore {
 
-class HTMLObjectElement : public HTMLPlugInImageElement {
+class HTMLFormElement;
+
+class HTMLObjectElement : public HTMLPlugInImageElement, public FormAssociatedElement {
 public:
-    static PassRefPtr<HTMLObjectElement> create(const QualifiedName&, Document*, bool createdByParser);
+    static PassRefPtr<HTMLObjectElement> create(const QualifiedName&, Document*, HTMLFormElement*, bool createdByParser);
+    virtual ~HTMLObjectElement();
 
     bool isDocNamedItem() const { return m_docNamedItem; }
 
@@ -40,10 +44,25 @@ public:
     virtual bool useFallbackContent() const { return m_useFallbackContent; }
     void renderFallbackContent();
 
+    // Implementations of FormAssociatedElement
+    HTMLFormElement* form() const { return FormAssociatedElement::form(); }
+
+    virtual bool isFormControlElement() const { return false; }
+
+    virtual bool isEnumeratable() const { return true; }
+    virtual bool appendFormData(FormDataList&, bool);
+
+    virtual void attributeChanged(Attribute*, bool preserveDecls = false);
+
+    using TreeShared<ContainerNode>::ref;
+    using TreeShared<ContainerNode>::deref;
+
 private:
-    HTMLObjectElement(const QualifiedName&, Document*, bool createdByParser);
+    HTMLObjectElement(const QualifiedName&, Document*, HTMLFormElement*, bool createdByParser);
 
     virtual void parseMappedAttribute(Attribute*);
+    virtual void insertedIntoTree(bool deep);
+    virtual void removedFromTree(bool deep);
 
     virtual bool rendererIsNeeded(RenderStyle*);
     virtual void insertedIntoDocument();
@@ -69,6 +88,11 @@ private:
     
     bool hasValidClassId();
 
+    virtual void refFormAssociatedElement() { ref(); }
+    virtual void derefFormAssociatedElement() { deref(); }
+
+    virtual const AtomicString& formControlName() const;
+
     AtomicString m_id;
     String m_classId;
     bool m_docNamedItem : 1;
index 9e2156c..4153f5c 100644 (file)
@@ -89,7 +89,7 @@ nobr interfaceName=HTMLElement
 noembed interfaceName=HTMLElement
 noframes interfaceName=HTMLElement
 nolayer interfaceName=HTMLElement
-object constructorNeedsCreatedByParser
+object constructorNeedsFormElement, constructorNeedsCreatedByParser
 ol interfaceName=HTMLOListElement
 optgroup interfaceName=HTMLOptGroupElement, constructorNeedsFormElement
 option constructorNeedsFormElement
index d32917e..4418235 100644 (file)
@@ -35,7 +35,7 @@
 
 namespace WebCore {
 
-ALWAYS_INLINE ValidationMessage::ValidationMessage(HTMLFormControlElement* element)
+ALWAYS_INLINE ValidationMessage::ValidationMessage(FormAssociatedElement* element)
     : m_element(element)
 {
 }
@@ -45,7 +45,7 @@ ValidationMessage::~ValidationMessage()
     hideMessage();
 }
 
-PassOwnPtr<ValidationMessage> ValidationMessage::create(HTMLFormControlElement* element)
+PassOwnPtr<ValidationMessage> ValidationMessage::create(FormAssociatedElement* element)
 {
     return adoptPtr(new ValidationMessage(element));
 }
index fe18b6b..d78e3f3 100644 (file)
 
 namespace WebCore {
 
-class HTMLFormControlElement;
+class FormAssociatedElement;
 
 class ValidationMessage : public Noncopyable {
 public:
-    static PassOwnPtr<ValidationMessage> create(HTMLFormControlElement*);
+    static PassOwnPtr<ValidationMessage> create(FormAssociatedElement*);
     ~ValidationMessage();
     String message() const { return m_message; }
     void setMessage(const String&);
 
 private:
-    ValidationMessage(HTMLFormControlElement*);
+    ValidationMessage(FormAssociatedElement*);
     void hideMessage(Timer<ValidationMessage>* = 0);
 
-    HTMLFormControlElement* m_element;
+    FormAssociatedElement* m_element;
     String m_message;
     OwnPtr<Timer<ValidationMessage> > m_timer;
 };
index ef3de66..2fb1e2c 100644 (file)
@@ -37,25 +37,26 @@ using namespace HTMLNames;
 
 String ValidityState::validationMessage() const
 {
-    if (!m_control->willValidate())
+    if (!toHTMLElement(m_control)->willValidate())
         return String();
 
     if (customError())
         return m_customErrorMessage;
-    bool isInputElement = m_control->hasTagName(inputTag);
-    bool isTextAreaElement = m_control->hasTagName(textareaTag);
+    HTMLElement* element = toHTMLElement(m_control);
+    bool isInputElement = element->isFormControlElement() && element->hasTagName(inputTag);
+    bool isTextAreaElement = element->isFormControlElement() && element->hasTagName(textareaTag);
     // The order of the following checks is meaningful. e.g. We'd like to show the
     // valueMissing message even if the control has other validation errors.
     if (valueMissing()) {
-        if (m_control->hasTagName(selectTag))
+        if (element->hasTagName(selectTag))
             return validationMessageValueMissingForSelectText();
         if (isInputElement)
-            return static_cast<HTMLInputElement*>(m_control)->valueMissingText();
+            return static_cast<HTMLInputElement*>(element)->valueMissingText();
         return validationMessageValueMissingText();
     }
     if (typeMismatch()) {
         if (isInputElement)
-            return static_cast<HTMLInputElement*>(m_control)->typeMismatchText();
+            return static_cast<HTMLInputElement*>(element)->typeMismatchText();
         return validationMessageTypeMismatchText();
     }
     if (patternMismatch())
@@ -65,7 +66,7 @@ String ValidityState::validationMessage() const
             ASSERT_NOT_REACHED();
             return String();
         }
-        HTMLTextFormControlElement* text = static_cast<HTMLTextFormControlElement*>(m_control);
+        HTMLTextFormControlElement* text = static_cast<HTMLTextFormControlElement*>(element);
         return validationMessageTooLongText(numGraphemeClusters(text->value()), text->maxLength());
     }
     if (rangeUnderflow()) {
@@ -73,21 +74,21 @@ String ValidityState::validationMessage() const
             ASSERT_NOT_REACHED();
             return String();
         }
-        return validationMessageRangeUnderflowText(static_cast<HTMLInputElement*>(m_control)->minimumString());
+        return validationMessageRangeUnderflowText(static_cast<HTMLInputElement*>(element)->minimumString());
     }
     if (rangeOverflow()) {
         if (!isInputElement) {
             ASSERT_NOT_REACHED();
             return String();
         }
-        return validationMessageRangeOverflowText(static_cast<HTMLInputElement*>(m_control)->maximumString());
+        return validationMessageRangeOverflowText(static_cast<HTMLInputElement*>(element)->maximumString());
     }
     if (stepMismatch()) {
         if (!isInputElement) {
             ASSERT_NOT_REACHED();
             return String();
         }
-        HTMLInputElement* input = static_cast<HTMLInputElement*>(m_control);
+        HTMLInputElement* input = static_cast<HTMLInputElement*>(element);
         return validationMessageStepMismatchText(input->stepBaseString(), input->stepString());
     }
 
@@ -97,17 +98,19 @@ String ValidityState::validationMessage() const
 void ValidityState::setCustomErrorMessage(const String& message)
 {
     m_customErrorMessage = message;
-    m_control->setNeedsValidityCheck();
+    if (m_control->isFormControlElement())
+        static_cast<HTMLFormControlElement*>(m_control)->setNeedsValidityCheck();
 }
 
 bool ValidityState::valueMissing() const
 {
-    if (m_control->hasTagName(inputTag)) {
-        HTMLInputElement* input = static_cast<HTMLInputElement*>(m_control);
+    HTMLElement* element = toHTMLElement(m_control);
+    if (element->hasTagName(inputTag)) {
+        HTMLInputElement* input = static_cast<HTMLInputElement*>(element);
         return input->valueMissing(input->value());
     }
-    if (m_control->hasTagName(textareaTag)) {
-        HTMLTextAreaElement* textArea = static_cast<HTMLTextAreaElement*>(m_control);
+    if (element->hasTagName(textareaTag)) {
+        HTMLTextAreaElement* textArea = static_cast<HTMLTextAreaElement*>(element);
         return textArea->valueMissing(textArea->value());
     }
     return false;
@@ -115,14 +118,14 @@ bool ValidityState::valueMissing() const
 
 bool ValidityState::typeMismatch() const
 {
-    if (!m_control->hasTagName(inputTag))
+    if (!toHTMLElement(m_control)->hasTagName(inputTag))
         return false;
     return static_cast<HTMLInputElement*>(m_control)->typeMismatch();
 }
 
 bool ValidityState::patternMismatch() const
 {
-    if (!m_control->hasTagName(inputTag))
+    if (!toHTMLElement(m_control)->hasTagName(inputTag))
         return false;
     HTMLInputElement* input = static_cast<HTMLInputElement*>(m_control);
     return input->patternMismatch(input->value());
@@ -130,11 +133,11 @@ bool ValidityState::patternMismatch() const
 
 bool ValidityState::tooLong() const
 {
-    if (m_control->hasTagName(inputTag)) {
+    if (toHTMLElement(m_control)->hasTagName(inputTag)) {
         HTMLInputElement* input = static_cast<HTMLInputElement*>(m_control);
         return input->tooLong(input->value(), HTMLTextFormControlElement::CheckDirtyFlag);
     }
-    if (m_control->hasTagName(textareaTag)) {
+    if (toHTMLElement(m_control)->hasTagName(textareaTag)) {
         HTMLTextAreaElement* textArea = static_cast<HTMLTextAreaElement*>(m_control);
         return textArea->tooLong(textArea->value(), HTMLTextFormControlElement::CheckDirtyFlag);
     }
@@ -143,7 +146,7 @@ bool ValidityState::tooLong() const
 
 bool ValidityState::rangeUnderflow() const
 {
-    if (!m_control->hasTagName(inputTag))
+    if (!toHTMLElement(m_control)->hasTagName(inputTag))
         return false;
     HTMLInputElement* input = static_cast<HTMLInputElement*>(m_control);
     return input->rangeUnderflow(input->value());
@@ -151,7 +154,7 @@ bool ValidityState::rangeUnderflow() const
 
 bool ValidityState::rangeOverflow() const
 {
-    if (!m_control->hasTagName(inputTag))
+    if (!toHTMLElement(m_control)->hasTagName(inputTag))
         return false;
     HTMLInputElement* input = static_cast<HTMLInputElement*>(m_control);
     return input->rangeOverflow(input->value());
@@ -159,7 +162,7 @@ bool ValidityState::rangeOverflow() const
 
 bool ValidityState::stepMismatch() const
 {
-    if (!m_control->hasTagName(inputTag))
+    if (!toHTMLElement(m_control)->hasTagName(inputTag))
         return false;
     HTMLInputElement* input = static_cast<HTMLInputElement*>(m_control);
     return input->stepMismatch(input->value());
index 532ddb2..01c26d1 100644 (file)
 #ifndef ValidityState_h
 #define ValidityState_h
 
-#include "HTMLFormControlElement.h"
+#include "FormAssociatedElement.h"
 #include <wtf/PassOwnPtr.h>
 
 namespace WebCore {
 
 class ValidityState : public Noncopyable {
 public:
-    static PassOwnPtr<ValidityState> create(HTMLFormControlElement* control)
+    static PassOwnPtr<ValidityState> create(FormAssociatedElement* control)
     {
         return adoptPtr(new ValidityState(control));
     }
@@ -54,12 +54,12 @@ public:
     bool valid() const;
 
 private:
-    ValidityState(HTMLFormControlElement* control) : m_control(control) { }
+    ValidityState(FormAssociatedElement* control) : m_control(control) { }
 
     static bool isValidColorString(const String&);
     static bool isValidEmailAddress(const String&);
 
-    HTMLFormControlElement* m_control;
+    FormAssociatedElement* m_control;
     String m_customErrorMessage;
 };
 
index a9f2680..44f9ff1 100644 (file)
@@ -175,10 +175,11 @@ PassRefPtr<FormSubmission> FormSubmission::create(HTMLFormElement* form, const A
     Vector<pair<String, String> > formValues;
 
     for (unsigned i = 0; i < form->associatedElements().size(); ++i) {
-        HTMLFormControlElement* control = form->associatedElements()[i];
-        if (!control->disabled())
+        FormAssociatedElement* control = form->associatedElements()[i];
+        HTMLElement* element = toHTMLElement(control);
+        if (!element->disabled())
             control->appendFormData(*domFormData, isMultiPartForm);
-        if (control->hasLocalName(inputTag)) {
+        if (element->hasLocalName(inputTag)) {
             HTMLInputElement* input = static_cast<HTMLInputElement*>(control);
             if (input->isTextField()) {
                 formValues.append(pair<String, String>(input->name(), input->value()));
index 5892a26..7cfd885 100644 (file)
@@ -1,3 +1,21 @@
+2010-12-07  Kenichi Ishibashi  <bashi@google.com>
+
+        Reviewed by Kent Tamura.
+
+        Let HTMLObjectElement be a form associated element
+        https://bugs.webkit.org/show_bug.cgi?id=48821
+
+        Modified to use FormAssociatedElement instead of HTMLFormControlElement.
+
+        * src/WebFormElement.cpp: 
+        (WebKit::WebFormElement::getFormControlElements): Modified to use
+        FormAssociatedElement instead of HTMLFormControlElement.
+        * src/WebPasswordFormUtils.cpp:
+        (WebKit::findPasswordFormFields): Ditto.
+        * src/WebSearchableFormData.cpp:
+        (WebCore::GetButtonToActivate): Ditto.
+        (WebCore::HasSuitableTextElement): Ditto.
+
 2010-12-06  Nate Chapin  <japhet@chromium.org>
 
         Reviewed by Adam Barth.
index 7a01053..6b6e9be 100644 (file)
@@ -92,9 +92,12 @@ void WebFormElement::getFormControlElements(WebVector<WebFormControlElement>& re
     // re-evaluating size each time. Also, consider refactoring this code so that
     // we don't call form->associatedElements() multiple times.
     for (size_t i = 0; i < form->associatedElements().size(); i++) {
-        if (form->associatedElements()[i]->hasLocalName(HTMLNames::inputTag)
-            || form->associatedElements()[i]->hasLocalName(HTMLNames::selectTag))
-            tempVector.append(form->associatedElements()[i]);
+        if (!form->associatedElements()[i]->isFormControlElement())
+            continue;
+        HTMLFormControlElement* element = static_cast<HTMLFormControlElement*>(form->associatedElements()[i]);
+        if (element->hasLocalName(HTMLNames::inputTag)
+            || element->hasLocalName(HTMLNames::selectTag))
+            tempVector.append(element);
     }
     result.assign(tempVector);
 }
index b4997e5..5f8a1ec 100644 (file)
@@ -65,9 +65,11 @@ void findPasswordFormFields(HTMLFormElement* form, PasswordFormFields* fields)
 
     int firstPasswordIndex = 0;
     // First, find the password fields and activated submit button
-    const Vector<HTMLFormControlElement*>& formElements = form->associatedElements();
+    const Vector<FormAssociatedElement*>& formElements = form->associatedElements();
     for (size_t i = 0; i < formElements.size(); i++) {
-        HTMLFormControlElement* formElement = formElements[i];
+        if (!formElements[i]->isFormControlElement())
+            continue;
+        HTMLFormControlElement* formElement = static_cast<HTMLFormControlElement*>(formElements[i]);
         if (formElement->isActivatedSubmit())
             fields->submit = formElement;
 
@@ -90,7 +92,9 @@ void findPasswordFormFields(HTMLFormElement* form, PasswordFormFields* fields)
     if (!fields->passwords.isEmpty()) {
         // Then, search backwards for the username field
         for (int i = firstPasswordIndex - 1; i >= 0; i--) {
-            HTMLFormControlElement* formElement = formElements[i];
+            if (!formElements[i]->isFormControlElement())
+                continue;
+            HTMLFormControlElement* formElement = static_cast<HTMLFormControlElement*>(formElements[i]);
             if (!formElement->hasLocalName(HTMLNames::inputTag))
                 continue;
 
index d9a2133..55c0adf 100644 (file)
@@ -77,8 +77,10 @@ HTMLFormControlElement* GetButtonToActivate(HTMLFormElement* form)
 {
     HTMLFormControlElement* firstSubmitButton = 0;
     // FIXME: Consider refactoring this code so that we don't call form->associatedElements() twice.
-    for (Vector<HTMLFormControlElement*>::const_iterator i(form->associatedElements().begin()); i != form->associatedElements().end(); ++i) {
-      HTMLFormControlElement* formElement = *i;
+    for (Vector<FormAssociatedElement*>::const_iterator i(form->associatedElements().begin()); i != form->associatedElements().end(); ++i) {
+      if (!(*i)->isFormControlElement())
+          continue;
+      HTMLFormControlElement* formElement = static_cast<HTMLFormControlElement*>(*i);
       if (formElement->isActivatedSubmit())
           // There's a button that is already activated for submit, return 0.
           return 0;
@@ -155,8 +157,10 @@ bool HasSuitableTextElement(const HTMLFormElement* form, Vector<char>* encodedSt
 
     HTMLInputElement* textElement = 0;
     // FIXME: Consider refactoring this code so that we don't call form->associatedElements() twice.
-    for (Vector<HTMLFormControlElement*>::const_iterator i(form->associatedElements().begin()); i != form->associatedElements().end(); ++i) {
-        HTMLFormControlElement* formElement = *i;
+    for (Vector<FormAssociatedElement*>::const_iterator i(form->associatedElements().begin()); i != form->associatedElements().end(); ++i) {
+        if (!(*i)->isFormControlElement())
+            continue;
+        HTMLFormControlElement* formElement = static_cast<HTMLFormControlElement*>(*i);
         if (formElement->disabled() || formElement->name().isNull())
             continue;
 
index 2fd7057..581cb03 100644 (file)
@@ -1,3 +1,17 @@
+2010-12-07  Kenichi Ishibashi  <bashi@google.com>
+
+        Reviewed by Kent Tamura.
+
+        Let HTMLObjectElement be a form associated element
+        https://bugs.webkit.org/show_bug.cgi?id=48821
+
+        Modified to use FormAssociatedElement instead of HTMLFormControlElement.
+
+        * WebView/WebHTMLRepresentation.mm:
+        (-[WebHTMLRepresentation elementWithName:inForm:]): Modified to use
+        FormAssociatedElement instead of HTMLFormControlElement.
+        (-[WebHTMLRepresentation controlsInForm:]): Ditto.
+
 2010-12-06  Nate Chapin  <japhet@chromium.org>
 
         Reviewed by Adam Barth.
index 2699472..fad0a4a 100644 (file)
@@ -285,12 +285,12 @@ static HTMLFormElement* formElementFromDOMElement(DOMElement *element)
     HTMLFormElement* formElement = formElementFromDOMElement(form);
     if (!formElement)
         return nil;
-    const Vector<HTMLFormControlElement*>& elements = formElement->associatedElements();
+    const Vector<FormAssociatedElement*>& elements = formElement->associatedElements();
     AtomicString targetName = name;
     for (unsigned i = 0; i < elements.size(); i++) {
-        HTMLFormControlElement* elt = elements[i];
+        FormAssociatedElement* elt = elements[i];
         if (elt->name() == targetName)
-            return kit(elt);
+            return kit(toHTMLElement(elt));
     }
     return nil;
 }
@@ -333,10 +333,10 @@ static HTMLInputElement* inputElementFromDOMElement(DOMElement* element)
     if (!formElement)
         return nil;
     NSMutableArray *results = nil;
-    const Vector<HTMLFormControlElement*>& elements = formElement->associatedElements();
+    const Vector<FormAssociatedElement*>& elements = formElement->associatedElements();
     for (unsigned i = 0; i < elements.size(); i++) {
         if (elements[i]->isEnumeratable()) { // Skip option elements, other duds
-            DOMElement* de = kit(elements[i]);
+            DOMElement* de = kit(toHTMLElement(elements[i]));
             if (!results)
                 results = [NSMutableArray arrayWithObject:de];
             else
index 51be76a..c0e22d0 100644 (file)
@@ -1,3 +1,17 @@
+2010-12-07  Kenichi Ishibashi  <bashi@google.com>
+
+        Reviewed by Kent Tamura.
+
+        Let HTMLObjectElement be a form associated element
+        https://bugs.webkit.org/show_bug.cgi?id=48821
+
+        Modified to use FormAssociatedElement instead of HTMLFormControlElement.
+
+        * WebFrame.cpp:
+        (WebFrame::elementWithName): Modified to use FormAssociatedElement
+        instead of HTMLFormControlElement.
+        (WebFrame::controlsInForm): Ditto.
+
 2010-12-05  Adam Roben  <aroben@apple.com>
 
         Windows production build fix
index 60be4d5..e91a9e2 100644 (file)
@@ -1134,12 +1134,14 @@ HRESULT WebFrame::elementWithName(BSTR name, IDOMElement* form, IDOMElement** el
     if (!form)
         return E_INVALIDARG;
 
-    HTMLFormElement *formElement = formElementFromDOMElement(form);
+    HTMLFormElementformElement = formElementFromDOMElement(form);
     if (formElement) {
-        const Vector<HTMLFormControlElement*>& elements = formElement->associatedElements();
+        const Vector<FormAssociatedElement*>& elements = formElement->associatedElements();
         AtomicString targetName((UChar*)name, SysStringLen(name));
         for (unsigned int i = 0; i < elements.size(); i++) {
-            HTMLFormControlElement *elt = elements[i];
+            if (!elements[i]->isFormControlElement())
+                continue;
+            HTMLFormControlElement* elt = static_cast<HTMLFormControlElement*>(elements[i]);
             // Skip option elements, other duds
             if (elt->name() == targetName) {
                 *element = DOMElement::createInstance(elt);
@@ -1349,7 +1351,7 @@ HRESULT WebFrame::controlsInForm(IDOMElement* form, IDOMElement** controls, int*
     if (!form)
         return E_INVALIDARG;
 
-    HTMLFormElement *formElement = formElementFromDOMElement(form);
+    HTMLFormElementformElement = formElementFromDOMElement(form);
     if (!formElement)
         return E_FAIL;
 
@@ -1362,10 +1364,10 @@ HRESULT WebFrame::controlsInForm(IDOMElement* form, IDOMElement** controls, int*
         return E_FAIL;
 
     *cControls = 0;
-    const Vector<HTMLFormControlElement*>& elements = formElement->associatedElements();
+    const Vector<FormAssociatedElement*>& elements = formElement->associatedElements();
     for (int i = 0; i < count; i++) {
         if (elements.at(i)->isEnumeratable()) { // Skip option elements, other duds
-            controls[*cControls] = DOMElement::createInstance(elements.at(i));
+            controls[*cControls] = DOMElement::createInstance(toHTMLElement(elements.at(i)));
             (*cControls)++;
         }
     }