[Forms] Move ValidityState methods implementation to another place
https://bugs.webkit.org/show_bug.cgi?id=86058

Patch by Yoshifumi Inoue <yosin@chromium.org> on 2012-05-11
Reviewed by Kent Tamura.

This patch changes ValidityState class for limiting scope of
number/range input type related methods for introducing decimal
arithmetic.

Methods related to validation are moved from ValidateState to
input, select and textarea elements with virtual method based
dispatching via FormAssociateElement instead of tag name
dispatching so far for code simplification.

No new tests. This patch doesn't change behavior.

* html/FormAssociatedElement.cpp:
(WebCore::FormAssociatedElement::customError): Added. Called from ValidateState. Returns custom error mssage in member variable.
(WebCore::FormAssociatedElement::patternMismatch): Added.  Called from ValidateState. This is default implementation.
(WebCore::FormAssociatedElement::rangeOverflow): Added.  Called from ValidateState. This is default implementation.
(WebCore::FormAssociatedElement::rangeUnderflow): Added.  Called from ValidateState. This is default implementation.
(WebCore::FormAssociatedElement::stepMismatch): Added.  Called from ValidateState. This is default implementation.
(WebCore::FormAssociatedElement::tooLong): Added.  Called from ValidateState. This is default implementation.
(WebCore::FormAssociatedElement::typeMismatch): Added.  Called from ValidateState. This is default implementation.
(WebCore::FormAssociatedElement::valid): Added.  Called from ValidateState. This is default implementation.
(WebCore::FormAssociatedElement::valueMissing): Added.  Called from ValidateState. This is default implementation.
(WebCore::FormAssociatedElement::customValidationMessage): Added.  Called from ValidateState. This is default implementation.
(WebCore::FormAssociatedElement::validationMessage): Added.  Called from ValidateState. This is default implementation.
(WebCore::FormAssociatedElement::setCustomValidity): Added.  set custom error message.
* html/FormAssociatedElement.h:
(FormAssociatedElement): Added new instance value m_customValidationMessage.
* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::setCustomValidity): Changed. Calls base class setCustomValidity.
* html/HTMLFormControlElement.h:
(HTMLFormControlElement):
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::isValidValue): Call m_inputType methods instead of HTMLInputElement's.
(WebCore::HTMLInputElement::tooLong): Call m_inputType methods instead of HTMLInputElement's.
(WebCore):
(WebCore::HTMLInputElement::typeMismatch): Move implementation to InputType.
(WebCore::HTMLInputElement::valueMissing):  Move implementation to InputType.
(WebCore::HTMLInputElement::patternMismatch): Move implementation to InputType.
(WebCore::HTMLInputElement::rangeUnderflow): Move implementation to InputType.
(WebCore::HTMLInputElement::rangeOverflow): Move implementation to InputType.
(WebCore::HTMLInputElement::validationMessage): Move implementation to InputType.
(WebCore::HTMLInputElement::stepMismatch): Move implementation to InputType.
(WebCore::HTMLInputElement::isInRange): Call m_inputType methods instead of HTMLInputElement's.
(WebCore::HTMLInputElement::isOutOfRange): Call m_inputType methods instead of HTMLInputElement's.
* html/HTMLInputElement.h:
(HTMLInputElement): Make tooLong method private.
* html/HTMLObjectElement.h: Add "virtual" and "OVERRIDE".
* html/HTMLSelectElement.cpp:
(WebCore::HTMLSelectElement::validationMessage): Added. Implementation for HTMLSelectElement.
(WebCore::HTMLSelectElement::valueMissing): Added. Implementation for HTMLSelectElement.
* html/HTMLSelectElement.h:
(HTMLSelectElement):  Added entries for newly added methods.
* html/HTMLTextAreaElement.cpp:
(WebCore::HTMLTextAreaElement::validationMessage): Added. Implementation for HTMLTextAreaElement.
(WebCore::HTMLTextAreaElement::valueMissing): Added. Implementation for HTMLTextAreaElement.
(WebCore::HTMLTextAreaElement::tooLong): Added. Implementation for HTMLTextAreaElement.
* html/HTMLTextAreaElement.h:
(HTMLTextAreaElement): Added entries for newly added methods. Change tooLong and valueMissing private.
* html/InputType.cpp:
(WebCore::InputType::stepMismatch): Change method signature.
(WebCore::InputType::alignValueForStep):  Changed for calling InputClass instead of HTMLINputElement.
(WebCore::InputType::stepUpFromRenderer):  Added. Moved from HTMLInputElement.
(WebCore::InputType::validationMessage): Added.  Moved from HTMLInputElement.
* html/InputType.h:
(InputType): Added entries for newly added methods and update methods signature.
* html/ValidityState.cpp: Move actual implementation to FormAssociatedElement and derived classes for localizing implementation change of elements and input types.
(WebCore::ValidityState::validationMessage): Changed to call FormAssociatedElement's method.
(WebCore::ValidityState::valueMissing): Changed to call FormAssociatedElement's method.
(WebCore::ValidityState::typeMismatch): Changed to call FormAssociatedElement's method.
(WebCore::ValidityState::patternMismatch): Changed to call FormAssociatedElement's method.
(WebCore::ValidityState::tooLong): Changed to call FormAssociatedElement's method.
(WebCore::ValidityState::rangeUnderflow): Changed to call FormAssociatedElement's method.
(WebCore::ValidityState::rangeOverflow): Changed to call FormAssociatedElement's method.
(WebCore::ValidityState::stepMismatch): Changed to call FormAssociatedElement's method.
(WebCore::ValidityState::customError): Changed to call FormAssociatedElement's method.
(WebCore::ValidityState::valid):
* html/ValidityState.h:
(ValidityState): Remove custom validation message related things.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@116752 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index a9d6605..68ab796 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,88 @@
+2012-05-11  Yoshifumi Inoue  <yosin@chromium.org>
+
+        [Forms] Move ValidityState methods implementation to another place
+        https://bugs.webkit.org/show_bug.cgi?id=86058
+
+        Reviewed by Kent Tamura.
+
+        This patch changes ValidityState class for limiting scope of
+        number/range input type related methods for introducing decimal
+        arithmetic.
+
+        Methods related to validation are moved from ValidateState to
+        input, select and textarea elements with virtual method based
+        dispatching via FormAssociateElement instead of tag name
+        dispatching so far for code simplification.
+
+        No new tests. This patch doesn't change behavior.
+
+        * html/FormAssociatedElement.cpp:
+        (WebCore::FormAssociatedElement::customError): Added. Called from ValidateState. Returns custom error mssage in member variable.
+        (WebCore::FormAssociatedElement::patternMismatch): Added.  Called from ValidateState. This is default implementation.
+        (WebCore::FormAssociatedElement::rangeOverflow): Added.  Called from ValidateState. This is default implementation.
+        (WebCore::FormAssociatedElement::rangeUnderflow): Added.  Called from ValidateState. This is default implementation.
+        (WebCore::FormAssociatedElement::stepMismatch): Added.  Called from ValidateState. This is default implementation.
+        (WebCore::FormAssociatedElement::tooLong): Added.  Called from ValidateState. This is default implementation.
+        (WebCore::FormAssociatedElement::typeMismatch): Added.  Called from ValidateState. This is default implementation.
+        (WebCore::FormAssociatedElement::valid): Added.  Called from ValidateState. This is default implementation.
+        (WebCore::FormAssociatedElement::valueMissing): Added.  Called from ValidateState. This is default implementation.
+        (WebCore::FormAssociatedElement::customValidationMessage): Added.  Called from ValidateState. This is default implementation.
+        (WebCore::FormAssociatedElement::validationMessage): Added.  Called from ValidateState. This is default implementation.
+        (WebCore::FormAssociatedElement::setCustomValidity): Added.  set custom error message.
+        * html/FormAssociatedElement.h:
+        (FormAssociatedElement): Added new instance value m_customValidationMessage.
+        * html/HTMLFormControlElement.cpp:
+        (WebCore::HTMLFormControlElement::setCustomValidity): Changed. Calls base class setCustomValidity.
+        * html/HTMLFormControlElement.h:
+        (HTMLFormControlElement):
+        * html/HTMLInputElement.cpp:
+        (WebCore::HTMLInputElement::isValidValue): Call m_inputType methods instead of HTMLInputElement's.
+        (WebCore::HTMLInputElement::tooLong): Call m_inputType methods instead of HTMLInputElement's.
+        (WebCore):
+        (WebCore::HTMLInputElement::typeMismatch): Move implementation to InputType.
+        (WebCore::HTMLInputElement::valueMissing):  Move implementation to InputType.
+        (WebCore::HTMLInputElement::patternMismatch): Move implementation to InputType.
+        (WebCore::HTMLInputElement::rangeUnderflow): Move implementation to InputType.
+        (WebCore::HTMLInputElement::rangeOverflow): Move implementation to InputType.
+        (WebCore::HTMLInputElement::validationMessage): Move implementation to InputType.
+        (WebCore::HTMLInputElement::stepMismatch): Move implementation to InputType.
+        (WebCore::HTMLInputElement::isInRange): Call m_inputType methods instead of HTMLInputElement's.
+        (WebCore::HTMLInputElement::isOutOfRange): Call m_inputType methods instead of HTMLInputElement's.
+        * html/HTMLInputElement.h:
+        (HTMLInputElement): Make tooLong method private.
+        * html/HTMLObjectElement.h: Add "virtual" and "OVERRIDE".
+        * html/HTMLSelectElement.cpp:
+        (WebCore::HTMLSelectElement::validationMessage): Added. Implementation for HTMLSelectElement.
+        (WebCore::HTMLSelectElement::valueMissing): Added. Implementation for HTMLSelectElement.
+        * html/HTMLSelectElement.h:
+        (HTMLSelectElement):  Added entries for newly added methods.
+        * html/HTMLTextAreaElement.cpp:
+        (WebCore::HTMLTextAreaElement::validationMessage): Added. Implementation for HTMLTextAreaElement.
+        (WebCore::HTMLTextAreaElement::valueMissing): Added. Implementation for HTMLTextAreaElement.
+        (WebCore::HTMLTextAreaElement::tooLong): Added. Implementation for HTMLTextAreaElement.
+        * html/HTMLTextAreaElement.h:
+        (HTMLTextAreaElement): Added entries for newly added methods. Change tooLong and valueMissing private.
+        * html/InputType.cpp:
+        (WebCore::InputType::stepMismatch): Change method signature.
+        (WebCore::InputType::alignValueForStep):  Changed for calling InputClass instead of HTMLINputElement.
+        (WebCore::InputType::stepUpFromRenderer):  Added. Moved from HTMLInputElement.
+        (WebCore::InputType::validationMessage): Added.  Moved from HTMLInputElement.
+        * html/InputType.h:
+        (InputType): Added entries for newly added methods and update methods signature.
+        * html/ValidityState.cpp: Move actual implementation to FormAssociatedElement and derived classes for localizing implementation change of elements and input types.
+        (WebCore::ValidityState::validationMessage): Changed to call FormAssociatedElement's method.
+        (WebCore::ValidityState::valueMissing): Changed to call FormAssociatedElement's method.
+        (WebCore::ValidityState::typeMismatch): Changed to call FormAssociatedElement's method.
+        (WebCore::ValidityState::patternMismatch): Changed to call FormAssociatedElement's method.
+        (WebCore::ValidityState::tooLong): Changed to call FormAssociatedElement's method.
+        (WebCore::ValidityState::rangeUnderflow): Changed to call FormAssociatedElement's method.
+        (WebCore::ValidityState::rangeOverflow): Changed to call FormAssociatedElement's method.
+        (WebCore::ValidityState::stepMismatch): Changed to call FormAssociatedElement's method.
+        (WebCore::ValidityState::customError): Changed to call FormAssociatedElement's method.
+        (WebCore::ValidityState::valid):
+        * html/ValidityState.h:
+        (ValidityState): Remove custom validation message related things.
+
 2012-05-11  Kent Tamura  <tkent@chromium.org>
 
         Fix a build error without SVG, introduced by tab-size support.
diff --git a/Source/WebCore/html/FormAssociatedElement.cpp b/Source/WebCore/html/FormAssociatedElement.cpp
index 665efa7..76dd0d1 100644
--- a/Source/WebCore/html/FormAssociatedElement.cpp
+++ b/Source/WebCore/html/FormAssociatedElement.cpp
@@ -157,6 +157,69 @@
         resetFormOwner();
 }
 
+bool FormAssociatedElement::customError() const
+{
+    const HTMLElement* element = toHTMLElement(this);
+    return element->willValidate() && !m_customValidationMessage.isEmpty();
+}
+
+bool FormAssociatedElement::patternMismatch() const
+{
+    return false;
+}
+
+bool FormAssociatedElement::rangeOverflow() const
+{
+    return false;
+}
+
+bool FormAssociatedElement::rangeUnderflow() const
+{
+    return false;
+}
+
+bool FormAssociatedElement::stepMismatch() const
+{
+    return false;
+}
+
+bool FormAssociatedElement::tooLong() const
+{
+    return false;
+}
+
+bool FormAssociatedElement::typeMismatch() const
+{
+    return false;
+}
+
+bool FormAssociatedElement::valid() const
+{
+    bool someError = typeMismatch() || stepMismatch() || rangeUnderflow() || rangeOverflow()
+        || tooLong() || patternMismatch() || valueMissing() || customError();
+    return !someError;
+}
+
+bool FormAssociatedElement::valueMissing() const
+{
+    return false;
+}
+
+String FormAssociatedElement::customValidationMessage() const
+{
+    return m_customValidationMessage;
+}
+
+String FormAssociatedElement::validationMessage() const
+{
+    return customError() ? m_customValidationMessage : String();
+}
+
+void FormAssociatedElement::setCustomValidity(const String& error)
+{
+    m_customValidationMessage = error;
+}
+
 const HTMLElement* toHTMLElement(const FormAssociatedElement* associatedElement)
 {
     if (associatedElement->isFormControlElement())
diff --git a/Source/WebCore/html/FormAssociatedElement.h b/Source/WebCore/html/FormAssociatedElement.h
index 284e298..92eb8d7 100644
--- a/Source/WebCore/html/FormAssociatedElement.h
+++ b/Source/WebCore/html/FormAssociatedElement.h
@@ -60,6 +60,22 @@
 
     void formRemovedFromTree(const Node* formRoot);
 
+    // ValidityState attribute implementations
+    bool customError() const;
+
+    // Override functions for patterMismatch, rangeOverflow, rangerUnderflow,
+    // stepMismatch, tooLong and valueMissing must call willValidate method.
+    virtual bool patternMismatch() const;
+    virtual bool rangeOverflow() const;
+    virtual bool rangeUnderflow() const;
+    virtual bool stepMismatch() const;
+    virtual bool tooLong() const;
+    virtual bool typeMismatch() const;
+    virtual bool valueMissing() const;
+    virtual String validationMessage() const;
+    bool valid() const;
+    virtual void setCustomValidity(const String&);
+
 protected:
     FormAssociatedElement();
 
@@ -76,6 +92,8 @@
     virtual void willChangeForm();
     virtual void didChangeForm();
 
+    String customValidationMessage() const;
+
 private:
     virtual const AtomicString& formControlName() const = 0;
 
@@ -84,6 +102,7 @@
 
     HTMLFormElement* m_form;
     OwnPtr<ValidityState> m_validityState;
+    String m_customValidationMessage;
 };
 
 HTMLElement* toHTMLElement(FormAssociatedElement*);
diff --git a/Source/WebCore/html/HTMLFormControlElement.cpp b/Source/WebCore/html/HTMLFormControlElement.cpp
index 2f9f225..7021753 100644
--- a/Source/WebCore/html/HTMLFormControlElement.cpp
+++ b/Source/WebCore/html/HTMLFormControlElement.cpp
@@ -484,7 +484,8 @@
 
 void HTMLFormControlElement::setCustomValidity(const String& error)
 {
-    validity()->setCustomErrorMessage(error);
+    FormAssociatedElement::setCustomValidity(error);
+    setNeedsValidityCheck();
 }
 
 void HTMLFormControlElement::dispatchBlurEvent(PassRefPtr<Node> newFocusedNode)
diff --git a/Source/WebCore/html/HTMLFormControlElement.h b/Source/WebCore/html/HTMLFormControlElement.h
index 608411f..cafbf52 100644
--- a/Source/WebCore/html/HTMLFormControlElement.h
+++ b/Source/WebCore/html/HTMLFormControlElement.h
@@ -101,7 +101,7 @@
     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&);
+    virtual void setCustomValidity(const String&) OVERRIDE;
 
     bool readOnly() const { return m_readOnly; }
 
diff --git a/Source/WebCore/html/HTMLInputElement.cpp b/Source/WebCore/html/HTMLInputElement.cpp
index 778ed25..d6cecc8 100644
--- a/Source/WebCore/html/HTMLInputElement.cpp
+++ b/Source/WebCore/html/HTMLInputElement.cpp
@@ -191,27 +191,32 @@
         return false;
     }
     return !m_inputType->typeMismatchFor(value)
-        && !stepMismatch(value)
-        && !rangeUnderflow(value)
-        && !rangeOverflow(value)
+        && !m_inputType->stepMismatch(value)
+        && !m_inputType->rangeUnderflow(value)
+        && !m_inputType->rangeOverflow(value)
         && !tooLong(value, IgnoreDirtyFlag)
-        && !patternMismatch(value)
-        && !valueMissing(value);
+        && !m_inputType->patternMismatch(value)
+        && !m_inputType->valueMissing(value);
+}
+
+bool HTMLInputElement::tooLong() const
+{
+    return willValidate() && tooLong(value(), CheckDirtyFlag);
 }
 
 bool HTMLInputElement::typeMismatch() const
 {
-    return m_inputType->typeMismatch();
+    return willValidate() && m_inputType->typeMismatch();
 }
 
-bool HTMLInputElement::valueMissing(const String& value) const
+bool HTMLInputElement::valueMissing() const
 {
-    return m_inputType->valueMissing(value);
+    return willValidate() && m_inputType->valueMissing(value());
 }
 
-bool HTMLInputElement::patternMismatch(const String& value) const
+bool HTMLInputElement::patternMismatch() const
 {
-    return m_inputType->patternMismatch(value);
+    return willValidate() && m_inputType->patternMismatch(value());
 }
 
 bool HTMLInputElement::tooLong(const String& value, NeedsToCheckDirtyFlag check) const
@@ -232,14 +237,25 @@
     return numGraphemeClusters(value) > static_cast<unsigned>(max);
 }
 
-bool HTMLInputElement::rangeUnderflow(const String& value) const
+bool HTMLInputElement::rangeUnderflow() const
 {
-    return m_inputType->rangeUnderflow(value);
+    return willValidate() && m_inputType->rangeUnderflow(value());
 }
 
-bool HTMLInputElement::rangeOverflow(const String& value) const
+bool HTMLInputElement::rangeOverflow() const
 {
-    return m_inputType->rangeOverflow(value);
+    return willValidate() && m_inputType->rangeOverflow(value());
+}
+
+String HTMLInputElement::validationMessage() const
+{
+    if (!willValidate())
+        return String();
+
+    if (customError())
+        return customValidationMessage();
+
+    return m_inputType->validationMessage();
 }
 
 double HTMLInputElement::minimum() const
@@ -252,48 +268,9 @@
     return m_inputType->maximum();
 }
 
-bool HTMLInputElement::stepMismatch(const String& value) const
+bool HTMLInputElement::stepMismatch() const
 {
-    double step;
-    if (!getAllowedValueStep(&step))
-        return false;
-    return m_inputType->stepMismatch(value, step);
-}
-
-String HTMLInputElement::minimumString() const
-{
-    return m_inputType->serialize(minimum());
-}
-
-String HTMLInputElement::maximumString() const
-{
-    return m_inputType->serialize(maximum());
-}
-
-String HTMLInputElement::stepBaseString() const
-{
-    return m_inputType->serialize(m_inputType->stepBase());
-}
-
-String HTMLInputElement::stepString() const
-{
-    double step;
-    if (!getAllowedValueStep(&step)) {
-        // stepString() should be called only if stepMismatch() can be true.
-        ASSERT_NOT_REACHED();
-        return String();
-    }
-    return serializeForNumberType(step / m_inputType->stepScaleFactor());
-}
-
-String HTMLInputElement::typeMismatchText() const
-{
-    return m_inputType->typeMismatchText();
-}
-
-String HTMLInputElement::valueMissingText() const
-{
-    return m_inputType->valueMissingText();
+    return willValidate() && m_inputType->stepMismatch(value());
 }
 
 bool HTMLInputElement::getAllowedValueStep(double* step) const
@@ -1275,12 +1252,12 @@
 
 bool HTMLInputElement::isInRange() const
 {
-    return m_inputType->supportsRangeLimitation() && !rangeUnderflow(value()) && !rangeOverflow(value());
+    return m_inputType->supportsRangeLimitation() && !m_inputType->rangeUnderflow(value()) && !m_inputType->rangeOverflow(value());
 }
 
 bool HTMLInputElement::isOutOfRange() const
 {
-    return m_inputType->supportsRangeLimitation() && (rangeUnderflow(value()) || rangeOverflow(value()));
+    return m_inputType->supportsRangeLimitation() && (m_inputType->rangeUnderflow(value()) || m_inputType->rangeOverflow(value()));
 }
 
 bool HTMLInputElement::needsSuspensionCallback()
diff --git a/Source/WebCore/html/HTMLInputElement.h b/Source/WebCore/html/HTMLInputElement.h
index e34a03e..5c2e812 100644
--- a/Source/WebCore/html/HTMLInputElement.h
+++ b/Source/WebCore/html/HTMLInputElement.h
@@ -48,13 +48,15 @@
     virtual bool shouldAutocomplete() const;
 
     // For ValidityState
-    bool typeMismatch() const;
-    // valueMissing() ignores the specified string value for CHECKBOX and RADIO.
-    bool valueMissing(const String&) const;
-    bool patternMismatch(const String&) const;
-    bool tooLong(const String&, NeedsToCheckDirtyFlag) const;
-    bool rangeUnderflow(const String&) const;
-    bool rangeOverflow(const String&) const;
+    virtual bool patternMismatch() const OVERRIDE;
+    virtual bool rangeUnderflow() const OVERRIDE;
+    virtual bool rangeOverflow() const;
+    virtual bool stepMismatch() const OVERRIDE;
+    virtual bool tooLong() const OVERRIDE;
+    virtual bool typeMismatch() const OVERRIDE;
+    virtual bool valueMissing() const OVERRIDE;
+    virtual String validationMessage() const OVERRIDE;
+
     // Returns the minimum value for type=date, number, or range.  Don't call this for other types.
     double minimum() const;
     // Returns the maximum value for type=date, number, or range.  Don't call this for other types.
@@ -64,15 +66,6 @@
     // Returns false if there is no "allowed value step."
     bool getAllowedValueStep(double*) const;
 
-    // For ValidityState.
-    bool stepMismatch(const String&) const;
-    String minimumString() const;
-    String maximumString() const;
-    String stepBaseString() const;
-    String stepString() const;
-    String typeMismatchText() const;
-    String valueMissingText() const;
-
     // Implementations of HTMLInputElement::stepUp() and stepDown().
     void stepUp(int, ExceptionCode&);
     void stepDown(int, ExceptionCode&);
@@ -325,6 +318,7 @@
 
     bool supportsMaxLength() const { return isTextType(); }
     bool isTextType() const;
+    bool tooLong(const String&, NeedsToCheckDirtyFlag) const;
 
     virtual bool supportsPlaceholder() const;
     virtual bool isPlaceholderEmpty() const OVERRIDE;
diff --git a/Source/WebCore/html/HTMLObjectElement.h b/Source/WebCore/html/HTMLObjectElement.h
index a0e6637..313893b 100644
--- a/Source/WebCore/html/HTMLObjectElement.h
+++ b/Source/WebCore/html/HTMLObjectElement.h
@@ -56,7 +56,7 @@
     // Note that the object elements are always barred from constraint validation.
     String validationMessage() { return String(); }
     bool checkValidity() { return true; }
-    void setCustomValidity(const String&) { }
+    virtual void setCustomValidity(const String&) OVERRIDE { }
 
     using TreeShared<ContainerNode>::ref;
     using TreeShared<ContainerNode>::deref;
diff --git a/Source/WebCore/html/HTMLSelectElement.cpp b/Source/WebCore/html/HTMLSelectElement.cpp
index 58a9a73..ee57dae 100644
--- a/Source/WebCore/html/HTMLSelectElement.cpp
+++ b/Source/WebCore/html/HTMLSelectElement.cpp
@@ -41,6 +41,7 @@
 #include "HTMLOptionElement.h"
 #include "HTMLOptionsCollection.h"
 #include "KeyboardEvent.h"
+#include "LocalizedStrings.h"
 #include "MouseEvent.h"
 #include "NodeRenderingContext.h"
 #include "Page.h"
@@ -145,8 +146,22 @@
     return !listIndex && option->value().isEmpty();
 }
 
+String HTMLSelectElement::validationMessage() const
+{
+    if (!willValidate())
+        return String();
+
+    if (customError())
+        return customValidationMessage();
+
+    return valueMissing() ? validationMessageValueMissingForSelectText() : String();
+}
+
 bool HTMLSelectElement::valueMissing() const
 {
+    if (!willValidate())
+        return false;
+
     if (!isRequiredFormControl())
         return false;
 
diff --git a/Source/WebCore/html/HTMLSelectElement.h b/Source/WebCore/html/HTMLSelectElement.h
index 52665e1..82b7273 100644
--- a/Source/WebCore/html/HTMLSelectElement.h
+++ b/Source/WebCore/html/HTMLSelectElement.h
@@ -46,7 +46,8 @@
     void optionSelectedByUser(int index, bool dispatchChangeEvent, bool allowMultipleSelection = false);
 
     // For ValidityState
-    bool valueMissing() const;
+    virtual String validationMessage() const OVERRIDE;
+    virtual bool valueMissing() const OVERRIDE;
 
     unsigned length() const;
 
diff --git a/Source/WebCore/html/HTMLTextAreaElement.cpp b/Source/WebCore/html/HTMLTextAreaElement.cpp
index 8257d0f..3fc8151 100644
--- a/Source/WebCore/html/HTMLTextAreaElement.cpp
+++ b/Source/WebCore/html/HTMLTextAreaElement.cpp
@@ -37,6 +37,7 @@
 #include "FormDataList.h"
 #include "Frame.h"
 #include "HTMLNames.h"
+#include "LocalizedStrings.h"
 #include "RenderTextControlMultiLine.h"
 #include "ShadowRoot.h"
 #include "Text.h"
@@ -423,6 +424,33 @@
         setAttribute(maxlengthAttr, String::number(newValue));
 }
 
+String HTMLTextAreaElement::validationMessage() const
+{
+    if (!willValidate())
+        return String();
+
+    if (customError())
+        return customValidationMessage();
+
+    if (valueMissing())
+        return validationMessageValueMissingText();
+
+    if (tooLong())
+        return validationMessageTooLongText(numGraphemeClusters(value()), maxLength());
+
+    return String();
+}
+
+bool HTMLTextAreaElement::valueMissing() const
+{
+    return willValidate() && valueMissing(value());
+}
+
+bool HTMLTextAreaElement::tooLong() const
+{
+    return willValidate() && tooLong(value(), CheckDirtyFlag);
+}
+
 bool HTMLTextAreaElement::tooLong(const String& value, NeedsToCheckDirtyFlag check) const
 {
     // Return false for the default value or value set by script even if it is
diff --git a/Source/WebCore/html/HTMLTextAreaElement.h b/Source/WebCore/html/HTMLTextAreaElement.h
index a19a471..d755d88 100644
--- a/Source/WebCore/html/HTMLTextAreaElement.h
+++ b/Source/WebCore/html/HTMLTextAreaElement.h
@@ -47,8 +47,10 @@
     int textLength() const { return value().length(); }
     virtual int maxLength() const;
     void setMaxLength(int, ExceptionCode&);
-    bool valueMissing(const String& value) const { return isRequiredFormControl() && !disabled() && !readOnly() && value.isEmpty(); }
-    bool tooLong(const String&, NeedsToCheckDirtyFlag) const;
+    // For ValidityState
+    virtual String validationMessage() const OVERRIDE;
+    virtual bool valueMissing() const OVERRIDE;
+    virtual bool tooLong() const OVERRIDE;
     bool isValidValue(const String&) const;
     
     virtual HTMLElement* innerTextElement() const;
@@ -108,6 +110,9 @@
 
     virtual bool shouldUseInputMethod();
 
+    bool valueMissing(const String& value) const { return isRequiredFormControl() && !disabled() && !readOnly() && value.isEmpty(); }
+    bool tooLong(const String&, NeedsToCheckDirtyFlag) const;
+
     int m_rows;
     int m_cols;
     WrapMethod m_wrap;
diff --git a/Source/WebCore/html/InputType.cpp b/Source/WebCore/html/InputType.cpp
index cf125c9..146d918 100644
--- a/Source/WebCore/html/InputType.cpp
+++ b/Source/WebCore/html/InputType.cpp
@@ -283,6 +283,14 @@
     return false;
 }
 
+bool InputType::stepMismatch(const String& value) const
+{
+    double step;
+    if (!getAllowedValueStep(&step))
+        return false;
+    return stepMismatch(value, step);
+}
+
 bool InputType::stepMismatch(const String&, double) const
 {
     // Non-supported types should be rejected by HTMLInputElement::getAllowedValueStep().
@@ -338,6 +346,41 @@
     return validationMessageValueMissingText();
 }
 
+String InputType::validationMessage() const
+{
+    const String value = element()->value();
+
+    // 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(value))
+        return valueMissingText();
+
+    if (typeMismatch())
+        return typeMismatchText();
+
+    if (patternMismatch(value))
+        return validationMessagePatternMismatchText();
+
+    if (element()->tooLong())
+        return validationMessageTooLongText(numGraphemeClusters(value), element()->maxLength());
+
+    if (rangeUnderflow(value))
+        return validationMessageRangeUnderflowText(serialize(minimum()));
+
+    if (rangeOverflow(value))
+        return validationMessageRangeOverflowText(serialize(maximum()));
+
+    if (stepMismatch(value)) {
+        String stepString;
+        double step;
+        if (getAllowedValueStep(&step))
+            stepString = serializeForNumberType(step / stepScaleFactor());
+        return validationMessageStepMismatchText(serialize(stepBase()), stepString);
+    }
+
+    return String();
+}
+
 void InputType::handleClickEvent(MouseEvent*)
 {
 }
@@ -870,7 +913,7 @@
     unsigned baseDecimalPlaces;
     double base = stepBaseWithDecimalPlaces(&baseDecimalPlaces);
     baseDecimalPlaces = min(baseDecimalPlaces, 16u);
-    if (element()->stepMismatch(element()->value())) {
+    if (stepMismatch(element()->value())) {
         double scale = pow(10.0, static_cast<double>(max(stepDecimalPlaces, currentDecimalPlaces)));
         newValue = round(newValue * scale) / scale;
     } else {
@@ -1023,7 +1066,7 @@
         element()->setValue(serialize(sign > 0 ? minimum() : maximum()), DispatchInputAndChangeEvent);
     else {
         ExceptionCode ec;
-        if (element()->stepMismatch(element()->value())) {
+        if (stepMismatch(element()->value())) {
             ASSERT(step);
             double newValue;
             double scale = pow(10.0, static_cast<double>(max(stepDecimalPlaces, baseDecimalPlaces)));
diff --git a/Source/WebCore/html/InputType.h b/Source/WebCore/html/InputType.h
index 1c86cb0..b00826b 100644
--- a/Source/WebCore/html/InputType.h
+++ b/Source/WebCore/html/InputType.h
@@ -140,7 +140,7 @@
     virtual void setValueAsNumber(double, TextFieldEventBehavior, ExceptionCode&) const;
 
     // Validation functions
-
+    virtual String validationMessage() const;
     virtual bool supportsValidation() const;
     virtual bool typeMismatchFor(const String&) const;
     // Type check for the current input value. We do nothing for some types
@@ -157,6 +157,7 @@
     virtual double minimum() const;
     virtual double maximum() const;
     virtual bool sizeShouldIncludeDecoration(int defaultSize, int& preferredSize) const;
+    bool stepMismatch(const String&) const;
     virtual bool stepMismatch(const String&, double step) const;
     virtual double stepBase() const;
     virtual double stepBaseWithDecimalPlaces(unsigned*) const;
diff --git a/Source/WebCore/html/ValidityState.cpp b/Source/WebCore/html/ValidityState.cpp
index fe7312c..649765d 100644
--- a/Source/WebCore/html/ValidityState.cpp
+++ b/Source/WebCore/html/ValidityState.cpp
@@ -38,177 +38,52 @@
 
 String ValidityState::validationMessage() const
 {
-    if (!toHTMLElement(m_control)->willValidate())
-        return String();
-
-    if (customError())
-        return m_customErrorMessage;
-    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 (element->hasTagName(selectTag))
-            return validationMessageValueMissingForSelectText();
-        if (isInputElement)
-            return static_cast<HTMLInputElement*>(element)->valueMissingText();
-        return validationMessageValueMissingText();
-    }
-    if (typeMismatch()) {
-        if (isInputElement)
-            return static_cast<HTMLInputElement*>(element)->typeMismatchText();
-        return validationMessageTypeMismatchText();
-    }
-    if (patternMismatch())
-        return validationMessagePatternMismatchText();
-    if (tooLong()) {
-        if (!isInputElement && !isTextAreaElement) {
-            ASSERT_NOT_REACHED();
-            return String();
-        }
-        HTMLTextFormControlElement* text = static_cast<HTMLTextFormControlElement*>(element);
-        return validationMessageTooLongText(numGraphemeClusters(text->value()), text->maxLength());
-    }
-    if (rangeUnderflow()) {
-        if (!isInputElement) {
-            ASSERT_NOT_REACHED();
-            return String();
-        }
-        return validationMessageRangeUnderflowText(static_cast<HTMLInputElement*>(element)->minimumString());
-    }
-    if (rangeOverflow()) {
-        if (!isInputElement) {
-            ASSERT_NOT_REACHED();
-            return String();
-        }
-        return validationMessageRangeOverflowText(static_cast<HTMLInputElement*>(element)->maximumString());
-    }
-    if (stepMismatch()) {
-        if (!isInputElement) {
-            ASSERT_NOT_REACHED();
-            return String();
-        }
-        HTMLInputElement* input = static_cast<HTMLInputElement*>(element);
-        return validationMessageStepMismatchText(input->stepBaseString(), input->stepString());
-    }
-
-    return String();
-}
-
-void ValidityState::setCustomErrorMessage(const String& message)
-{
-    m_customErrorMessage = message;
-    if (m_control->isFormControlElement())
-        static_cast<HTMLFormControlElement*>(m_control)->setNeedsValidityCheck();
+    return m_control->validationMessage();
 }
 
 bool ValidityState::valueMissing() const
 {
-    HTMLElement* element = toHTMLElement(m_control);
-    if (!element->willValidate())
-        return false;
-
-    if (element->hasTagName(inputTag)) {
-        HTMLInputElement* input = static_cast<HTMLInputElement*>(element);
-        return input->valueMissing(input->value());
-    }
-    if (element->hasTagName(textareaTag)) {
-        HTMLTextAreaElement* textArea = static_cast<HTMLTextAreaElement*>(element);
-        return textArea->valueMissing(textArea->value());
-    }
-    if (element->hasTagName(selectTag))
-        return toHTMLSelectElement(element)->valueMissing();
-    return false;
+    return m_control->valueMissing();
 }
 
 bool ValidityState::typeMismatch() const
 {
-    HTMLElement* element = toHTMLElement(m_control);
-    if (!element->willValidate())
-        return false;
-
-    if (!element->hasTagName(inputTag))
-        return false;
-    return static_cast<HTMLInputElement*>(element)->typeMismatch();
+    return m_control->typeMismatch();
 }
 
 bool ValidityState::patternMismatch() const
 {
-    HTMLElement* element = toHTMLElement(m_control);
-    if (!element->willValidate())
-        return false;
-
-    if (!element->hasTagName(inputTag))
-        return false;
-    HTMLInputElement* input = static_cast<HTMLInputElement*>(element);
-    return input->patternMismatch(input->value());
+    return m_control->patternMismatch();
 }
 
 bool ValidityState::tooLong() const
 {
-    HTMLElement* element = toHTMLElement(m_control);
-    if (!element->willValidate())
-        return false;
-
-    if (element->hasTagName(inputTag)) {
-        HTMLInputElement* input = static_cast<HTMLInputElement*>(element);
-        return input->tooLong(input->value(), HTMLTextFormControlElement::CheckDirtyFlag);
-    }
-    if (element->hasTagName(textareaTag)) {
-        HTMLTextAreaElement* textArea = static_cast<HTMLTextAreaElement*>(element);
-        return textArea->tooLong(textArea->value(), HTMLTextFormControlElement::CheckDirtyFlag);
-    }
-    return false;
+    return m_control->tooLong();
 }
 
 bool ValidityState::rangeUnderflow() const
 {
-    HTMLElement* element = toHTMLElement(m_control);
-    if (!element->willValidate())
-        return false;
-
-    if (!element->hasTagName(inputTag))
-        return false;
-    HTMLInputElement* input = static_cast<HTMLInputElement*>(element);
-    return input->rangeUnderflow(input->value());
+    return m_control->rangeUnderflow();
 }
 
 bool ValidityState::rangeOverflow() const
 {
-    HTMLElement* element = toHTMLElement(m_control);
-    if (!element->willValidate())
-        return false;
-
-    if (!element->hasTagName(inputTag))
-        return false;
-    HTMLInputElement* input = static_cast<HTMLInputElement*>(element);
-    return input->rangeOverflow(input->value());
+    return m_control->rangeOverflow();
 }
 
 bool ValidityState::stepMismatch() const
 {
-    HTMLElement* element = toHTMLElement(m_control);
-    if (!element->willValidate())
-        return false;
-
-    if (!element->hasTagName(inputTag))
-        return false;
-    HTMLInputElement* input = static_cast<HTMLInputElement*>(element);
-    return input->stepMismatch(input->value());
+    return m_control->stepMismatch();
 }
 
 bool ValidityState::customError() const
 {
-    HTMLElement* element = toHTMLElement(m_control);
-    return element->willValidate() && !m_customErrorMessage.isEmpty();
+    return m_control->customError();
 }
 
 bool ValidityState::valid() const
 {
-    bool someError = typeMismatch() || stepMismatch() || rangeUnderflow() || rangeOverflow()
-        || tooLong() || patternMismatch() || valueMissing() || customError();
-    return !someError;
+    return m_control->valid();
 }
 
 } // namespace
diff --git a/Source/WebCore/html/ValidityState.h b/Source/WebCore/html/ValidityState.h
index 4a96488..17e94c9 100644
--- a/Source/WebCore/html/ValidityState.h
+++ b/Source/WebCore/html/ValidityState.h
@@ -57,11 +57,7 @@
 private:
     ValidityState(FormAssociatedElement* control) : m_control(control) { }
 
-    static bool isValidColorString(const String&);
-    static bool isValidEmailAddress(const String&);
-
     FormAssociatedElement* m_control;
-    String m_customErrorMessage;
 };
 
 } // namespace WebCore