Move form-related functions of Document to FormController
authortkent@chromium.org <tkent@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 8 Jun 2012 09:53:52 +0000 (09:53 +0000)
committertkent@chromium.org <tkent@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 8 Jun 2012 09:53:52 +0000 (09:53 +0000)
https://bugs.webkit.org/show_bug.cgi?id=88497

Reviewed by Hajime Morita.

A lot of files depend on Document.h. We had to build many files when we
touched form-related features in Document.h or
CheckedRadioButtons.h. This patch reduces such pain.

No new tests. Just a refactoring.

* CMakeLists.txt: Add FormController.cpp and/or FormController.h.
* GNUmakefile.list.am: ditto.
* Target.pri: ditto.
* WebCore.gypi: ditto.
* WebCore.vcproj/WebCore.vcproj: ditto.
* WebCore.xcodeproj/project.pbxproj: ditto.

* dom/Document.cpp: Removed form-releated features except the followings.
(WebCore::Document::formController): Accessor for a FormController.
(WebCore::Document::formElementsState):
Just returns FormController::formElementsState().
We don't create new FormController.
(WebCore::Document::setStateForNewFormElements):
Just returns FormController::setStateForNewFormElements().
We don't create new FormController if the specified vector is empty.
* dom/Document.h:
Moved form-related functions to FormController.

* html/FormController.cpp: Added. Moved from Document.cpp.
* html/FormController.h: Added. Moved from Document.h

* html/FormAssociatedElement.cpp: Use Document::formController().
(WebCore::FormAssociatedElement::didMoveToNewDocument):
(WebCore::FormAssociatedElement::insertedInto):
(WebCore::FormAssociatedElement::removedFrom):
(WebCore::FormAssociatedElement::formAttributeChanged):
* html/HTMLFormControlElementWithState.cpp: Use Document::formController().
(WebCore::HTMLFormControlElementWithState::HTMLFormControlElementWithState):
(WebCore::HTMLFormControlElementWithState::~HTMLFormControlElementWithState):
(WebCore::HTMLFormControlElementWithState::didMoveToNewDocument):
(WebCore::HTMLFormControlElementWithState::finishParsingChildren):
* html/HTMLFormElement.cpp: Use Document::formController().
(WebCore::HTMLFormElement::didNotifyDescendantInsertions):
(WebCore::HTMLFormElement::removedFrom):
* html/HTMLInputElement.cpp: Use Document::formController().
(WebCore::HTMLInputElement::~HTMLInputElement):
(WebCore::HTMLInputElement::didMoveToNewDocument):
(WebCore::HTMLInputElement::checkedRadioButtons):
* html/HTMLInputElement.h:
Declare CheckedRadioButtons. It was provided by Document.h.
* html/parser/HTMLConstructionSite.h:
Declare HTMLFormElement. It was provided by Document.h

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

17 files changed:
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/Target.pri
Source/WebCore/WebCore.gypi
Source/WebCore/WebCore.vcproj/WebCore.vcproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/html/FormAssociatedElement.cpp
Source/WebCore/html/FormController.cpp [new file with mode: 0644]
Source/WebCore/html/FormController.h [new file with mode: 0644]
Source/WebCore/html/HTMLFormControlElementWithState.cpp
Source/WebCore/html/HTMLFormElement.cpp
Source/WebCore/html/HTMLInputElement.cpp
Source/WebCore/html/HTMLInputElement.h
Source/WebCore/html/parser/HTMLConstructionSite.h

index 7b97783..436e1c0 100644 (file)
@@ -764,6 +764,7 @@ SET(WebCore_SOURCES
     html/FTPDirectoryDocument.cpp
     html/FileInputType.cpp
     html/FormAssociatedElement.cpp
+    html/FormController.cpp
     html/FormDataList.cpp
     html/HTMLAllCollection.cpp
     html/HTMLAnchorElement.cpp
index 32e3f10..7fd120e 100644 (file)
@@ -1,3 +1,59 @@
+2012-06-08  Kent Tamura  <tkent@chromium.org>
+
+        Move form-related functions of Document to FormController
+        https://bugs.webkit.org/show_bug.cgi?id=88497
+
+        Reviewed by Hajime Morita.
+
+        A lot of files depend on Document.h. We had to build many files when we
+        touched form-related features in Document.h or
+        CheckedRadioButtons.h. This patch reduces such pain.
+
+        No new tests. Just a refactoring.
+
+        * CMakeLists.txt: Add FormController.cpp and/or FormController.h.
+        * GNUmakefile.list.am: ditto.
+        * Target.pri: ditto.
+        * WebCore.gypi: ditto.
+        * WebCore.vcproj/WebCore.vcproj: ditto.
+        * WebCore.xcodeproj/project.pbxproj: ditto.
+
+        * dom/Document.cpp: Removed form-releated features except the followings.
+        (WebCore::Document::formController): Accessor for a FormController.
+        (WebCore::Document::formElementsState):
+        Just returns FormController::formElementsState().
+        We don't create new FormController.
+        (WebCore::Document::setStateForNewFormElements):
+        Just returns FormController::setStateForNewFormElements().
+        We don't create new FormController if the specified vector is empty.
+        * dom/Document.h:
+        Moved form-related functions to FormController.
+
+        * html/FormController.cpp: Added. Moved from Document.cpp.
+        * html/FormController.h: Added. Moved from Document.h
+
+        * html/FormAssociatedElement.cpp: Use Document::formController().
+        (WebCore::FormAssociatedElement::didMoveToNewDocument):
+        (WebCore::FormAssociatedElement::insertedInto):
+        (WebCore::FormAssociatedElement::removedFrom):
+        (WebCore::FormAssociatedElement::formAttributeChanged):
+        * html/HTMLFormControlElementWithState.cpp: Use Document::formController().
+        (WebCore::HTMLFormControlElementWithState::HTMLFormControlElementWithState):
+        (WebCore::HTMLFormControlElementWithState::~HTMLFormControlElementWithState):
+        (WebCore::HTMLFormControlElementWithState::didMoveToNewDocument):
+        (WebCore::HTMLFormControlElementWithState::finishParsingChildren):
+        * html/HTMLFormElement.cpp: Use Document::formController().
+        (WebCore::HTMLFormElement::didNotifyDescendantInsertions):
+        (WebCore::HTMLFormElement::removedFrom):
+        * html/HTMLInputElement.cpp: Use Document::formController().
+        (WebCore::HTMLInputElement::~HTMLInputElement):
+        (WebCore::HTMLInputElement::didMoveToNewDocument):
+        (WebCore::HTMLInputElement::checkedRadioButtons):
+        * html/HTMLInputElement.h:
+        Declare CheckedRadioButtons. It was provided by Document.h.
+        * html/parser/HTMLConstructionSite.h:
+        Declare HTMLFormElement. It was provided by Document.h
+
 2012-06-08  Taiju Tsuiki  <tzik@chromium.org>
 
         Add FileSystem item to storage tree.
index a9c75e2..3da5891 100644 (file)
@@ -2262,6 +2262,8 @@ webcore_sources += \
        Source/WebCore/html/FileInputType.h \
        Source/WebCore/html/FormAssociatedElement.cpp \
        Source/WebCore/html/FormAssociatedElement.h \
+       Source/WebCore/html/FormController.cpp \
+       Source/WebCore/html/FormController.h \
        Source/WebCore/html/FormDataList.cpp \
        Source/WebCore/html/FormDataList.h \
        Source/WebCore/html/FTPDirectoryDocument.cpp \
index 153f139..c28de3f 100644 (file)
@@ -735,6 +735,7 @@ SOURCES += \
     html/FTPDirectoryDocument.cpp \
     html/FileInputType.cpp \
     html/FormAssociatedElement.cpp \
+    html/FormController.cpp \
     html/FormDataList.cpp \
     html/HTMLAllCollection.cpp \
     html/HTMLAnchorElement.cpp \
@@ -1890,6 +1891,7 @@ HEADERS += \
     html/DOMTokenList.h \
     html/DOMURL.h \
     html/FormAssociatedElement.h \
+    html/FormController.h \
     html/FormDataList.h \
     html/FTPDirectoryDocument.h \
     html/HTMLAllCollection.h \
index 5ab288c..0b57191 100644 (file)
             'html/FileInputType.cpp',
             'html/FileInputType.h',
             'html/FormAssociatedElement.cpp',
+            'html/FormController.cpp',
+            'html/FormController.h',
             'html/FormDataList.cpp',
             'html/FormDataList.h',
             'html/HTMLAllCollection.cpp',
index 627e7ae..f91097e 100755 (executable)
                                >
                        </File>
                        <File
+                               RelativePath="..\html\FormController.cpp"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\html\FormController.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\html\FormDataList.cpp"
                                >
                        </File>
index b1d0cfb..e7a1e7b 100644 (file)
                F3F68DA6143CAC5A00C2F887 /* InspectorStateClient.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F68DA5143CAC5A00C2F887 /* InspectorStateClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
                F4EAF4AE10C742B1009100D3 /* OpenTypeSanitizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4EAF4AC10C742B1009100D3 /* OpenTypeSanitizer.cpp */; };
                F4EAF4AF10C742B1009100D3 /* OpenTypeSanitizer.h in Headers */ = {isa = PBXBuildFile; fileRef = F4EAF4AD10C742B1009100D3 /* OpenTypeSanitizer.h */; };
+               F50664F7157F52DC00AC226F /* FormController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F50664F5157F52DC00AC226F /* FormController.cpp */; };
+               F50664F8157F52DC00AC226F /* FormController.h in Headers */ = {isa = PBXBuildFile; fileRef = F50664F6157F52DC00AC226F /* FormController.h */; };
                F5142C69123F12B000F5BD4C /* LocalizedNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = F5142C68123F12B000F5BD4C /* LocalizedNumber.h */; };
                F52AD5E41534245F0059FBE6 /* EmptyClients.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F52AD5E31534245F0059FBE6 /* EmptyClients.cpp */; };
                F55B3DAD1251F12D003EF269 /* BaseTextInputType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F55B3D791251F12D003EF269 /* BaseTextInputType.cpp */; };
                F3F68DA5143CAC5A00C2F887 /* InspectorStateClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorStateClient.h; sourceTree = "<group>"; };
                F4EAF4AC10C742B1009100D3 /* OpenTypeSanitizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OpenTypeSanitizer.cpp; path = opentype/OpenTypeSanitizer.cpp; sourceTree = "<group>"; };
                F4EAF4AD10C742B1009100D3 /* OpenTypeSanitizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenTypeSanitizer.h; path = opentype/OpenTypeSanitizer.h; sourceTree = "<group>"; };
+               F50664F5157F52DC00AC226F /* FormController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FormController.cpp; sourceTree = "<group>"; };
+               F50664F6157F52DC00AC226F /* FormController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormController.h; sourceTree = "<group>"; };
                F5142C68123F12B000F5BD4C /* LocalizedNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalizedNumber.h; sourceTree = "<group>"; };
                F523D23B02DE4396018635CA /* HTMLDocument.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLDocument.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                F523D23C02DE4396018635CA /* HTMLDocument.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = HTMLDocument.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                                F55B3D8A1251F12D003EF269 /* FileInputType.h */,
                                4A0DA2FC129B241900AB61E1 /* FormAssociatedElement.cpp */,
                                4A0DA2FD129B241900AB61E1 /* FormAssociatedElement.h */,
+                               F50664F5157F52DC00AC226F /* FormController.cpp */,
+                               F50664F6157F52DC00AC226F /* FormController.h */,
                                A8136D370973A8E700D74463 /* FormDataList.cpp */,
                                A8136D360973A8E700D74463 /* FormDataList.h */,
                                97205AAD123928CA00B17380 /* FTPDirectoryDocument.cpp */,
                                BCE4413612F7490B009B84B8 /* FontWidthVariant.h in Headers */,
                                4A0DA2FF129B241900AB61E1 /* FormAssociatedElement.h in Headers */,
                                D05CED2A0A40BB2C00C5AF38 /* FormatBlockCommand.h in Headers */,
+                               F50664F8157F52DC00AC226F /* FormController.h in Headers */,
                                514C76700CE923A1007EF3CD /* FormData.h in Headers */,
                                085B92BB0EFDE73D00E6123C /* FormDataBuilder.h in Headers */,
                                A8136D380973A8E700D74463 /* FormDataList.h in Headers */,
                                A80E6CF10A1989CA007FB8C5 /* FontValue.cpp in Sources */,
                                4A0DA2FE129B241900AB61E1 /* FormAssociatedElement.cpp in Sources */,
                                D05CED290A40BB2C00C5AF38 /* FormatBlockCommand.cpp in Sources */,
+                               F50664F7157F52DC00AC226F /* FormController.cpp in Sources */,
                                514C766F0CE923A1007EF3CD /* FormData.cpp in Sources */,
                                085B92BA0EFDE73D00E6123C /* FormDataBuilder.cpp in Sources */,
                                A8136D390973A8E700D74463 /* FormDataList.cpp in Sources */,
index 4228d63..dfb4329 100644 (file)
@@ -71,7 +71,7 @@
 #include "ExceptionCode.h"
 #include "FlowThreadController.h"
 #include "FocusController.h"
-#include "FormAssociatedElement.h"
+#include "FormController.h"
 #include "Frame.h"
 #include "FrameLoader.h"
 #include "FrameLoaderClient.h"
@@ -92,7 +92,6 @@
 #include "HTMLFrameOwnerElement.h"
 #include "HTMLHeadElement.h"
 #include "HTMLIFrameElement.h"
-#include "HTMLInputElement.h"
 #include "HTMLLinkElement.h"
 #include "HTMLMapElement.h"
 #include "HTMLNameCollection.h"
@@ -1626,6 +1625,27 @@ Node::NodeType Document::nodeType() const
     return DOCUMENT_NODE;
 }
 
+FormController* Document::formController()
+{
+    if (!m_formController)
+        m_formController = FormController::create();
+    return m_formController.get();
+}
+
+Vector<String> Document::formElementsState() const
+{
+    if (!m_formController)
+        return Vector<String>();
+    return m_formController->formElementsState();
+}
+
+void Document::setStateForNewFormElements(const Vector<String>& stateVector)
+{
+    if (!stateVector.size() && !m_formController)
+        return;
+    formController()->setStateForNewFormElements(stateVector);
+}
+
 FrameView* Document::view() const
 {
     return m_frame ? m_frame->view() : 0;
@@ -4747,26 +4767,6 @@ void Document::finishedParsing()
     }
 }
 
-Vector<String> Document::formElementsState() const
-{
-    Vector<String> stateVector;
-    stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 3);
-    typedef FormElementListHashSet::const_iterator Iterator;
-    Iterator end = m_formElementsWithState.end();
-    for (Iterator it = m_formElementsWithState.begin(); it != end; ++it) {
-        HTMLFormControlElementWithState* elementWithState = *it;
-        if (!elementWithState->shouldSaveAndRestoreFormControlState())
-            continue;
-        String value;
-        if (!elementWithState->saveFormControlState(value))
-            continue;
-        stateVector.append(elementWithState->formControlName().string());
-        stateVector.append(elementWithState->formControlType().string());
-        stateVector.append(value);
-    }
-    return stateVector;
-}
-
 PassRefPtr<XPathExpression> Document::createExpression(const String& expression,
                                                        XPathNSResolver* resolver,
                                                        ExceptionCode& ec)
@@ -4795,96 +4795,6 @@ PassRefPtr<XPathResult> Document::evaluate(const String& expression,
     return m_xpathEvaluator->evaluate(expression, contextNode, resolver, type, result, ec);
 }
 
-void Document::setStateForNewFormElements(const Vector<String>& stateVector)
-{
-    // Walk the state vector backwards so that the value to use for each
-    // name/type pair first is the one at the end of each individual vector
-    // in the FormElementStateMap. We're using them like stacks.
-    typedef FormElementStateMap::iterator Iterator;
-    m_formElementsWithState.clear();
-    for (size_t i = stateVector.size() / 3 * 3; i; i -= 3) {
-        AtomicString a = stateVector[i - 3];
-        AtomicString b = stateVector[i - 2];
-        const String& c = stateVector[i - 1];
-        FormElementKey key(a.impl(), b.impl());
-        Iterator it = m_stateForNewFormElements.find(key);
-        if (it != m_stateForNewFormElements.end())
-            it->second.append(c);
-        else {
-            Vector<String> v(1);
-            v[0] = c;
-            m_stateForNewFormElements.set(key, v);
-        }
-    }
-}
-
-bool Document::hasStateForNewFormElements() const
-{
-    return !m_stateForNewFormElements.isEmpty();
-}
-
-bool Document::takeStateForFormElement(AtomicStringImpl* name, AtomicStringImpl* type, String& state)
-{
-    typedef FormElementStateMap::iterator Iterator;
-    Iterator it = m_stateForNewFormElements.find(FormElementKey(name, type));
-    if (it == m_stateForNewFormElements.end())
-        return false;
-    ASSERT(it->second.size());
-    state = it->second.last();
-    if (it->second.size() > 1)
-        it->second.removeLast();
-    else
-        m_stateForNewFormElements.remove(it);
-    return true;
-}
-
-FormElementKey::FormElementKey(AtomicStringImpl* name, AtomicStringImpl* type)
-    : m_name(name), m_type(type)
-{
-    ref();
-}
-
-FormElementKey::~FormElementKey()
-{
-    deref();
-}
-
-FormElementKey::FormElementKey(const FormElementKey& other)
-    : m_name(other.name()), m_type(other.type())
-{
-    ref();
-}
-
-FormElementKey& FormElementKey::operator=(const FormElementKey& other)
-{
-    other.ref();
-    deref();
-    m_name = other.name();
-    m_type = other.type();
-    return *this;
-}
-
-void FormElementKey::ref() const
-{
-    if (name())
-        name()->ref();
-    if (type())
-        type()->ref();
-}
-
-void FormElementKey::deref() const
-{
-    if (name())
-        name()->deref();
-    if (type())
-        type()->deref();
-}
-
-unsigned FormElementKeyHash::hash(const FormElementKey& key)
-{
-    return StringHasher::hashMemory<sizeof(FormElementKey)>(&key);
-}
-
 const Vector<IconURL>& Document::iconURLs() const
 {
     return m_iconURLs;
@@ -4906,25 +4816,6 @@ void Document::addIconURL(const String& url, const String& mimeType, const Strin
     }
 }
 
-void Document::registerFormElementWithFormAttribute(FormAssociatedElement* element)
-{
-    ASSERT(toHTMLElement(element)->fastHasAttribute(formAttr));
-    m_formElementsWithFormAttribute.add(element);
-}
-
-void Document::unregisterFormElementWithFormAttribute(FormAssociatedElement* element)
-{
-    m_formElementsWithFormAttribute.remove(element);
-}
-
-void Document::resetFormElementsOwner()
-{
-    typedef FormAssociatedElementListHashSet::iterator Iterator;
-    Iterator end = m_formElementsWithFormAttribute.end();
-    for (Iterator it = m_formElementsWithFormAttribute.begin(); it != end; ++it)
-        (*it)->resetFormOwner();
-}
-
 void Document::setUseSecureKeyboardEntryWhenActive(bool usesSecureKeyboard)
 {
     if (m_useSecureKeyboardEntryWhenActive == usesSecureKeyboard)
index e19c593..d7b70e8 100644 (file)
@@ -28,7 +28,6 @@
 #ifndef Document_h
 #define Document_h
 
-#include "CheckedRadioButtons.h"
 #include "CollectionType.h"
 #include "Color.h"
 #include "ContainerNode.h"
@@ -86,7 +85,7 @@ class EventListener;
 class FloatRect;
 class FloatQuad;
 class FontData;
-class FormAssociatedElement;
+class FormController;
 class Frame;
 class FrameView;
 class HTMLCanvasElement;
@@ -94,11 +93,8 @@ class HTMLCollection;
 class HTMLAllCollection;
 class HTMLDocument;
 class HTMLElement;
-class HTMLFormControlElementWithState;
-class HTMLFormElement;
 class HTMLFrameOwnerElement;
 class HTMLHeadElement;
-class HTMLInputElement;
 class HTMLIFrameElement;
 class HTMLMapElement;
 class HTMLNameCollection;
@@ -176,46 +172,6 @@ class Prerenderer;
 
 typedef int ExceptionCode;
 
-class FormElementKey {
-public:
-    FormElementKey(AtomicStringImpl* = 0, AtomicStringImpl* = 0);
-    ~FormElementKey();
-    FormElementKey(const FormElementKey&);
-    FormElementKey& operator=(const FormElementKey&);
-
-    AtomicStringImpl* name() const { return m_name; }
-    AtomicStringImpl* type() const { return m_type; }
-
-    // Hash table deleted values, which are only constructed and never copied or destroyed.
-    FormElementKey(WTF::HashTableDeletedValueType) : m_name(hashTableDeletedValue()) { }
-    bool isHashTableDeletedValue() const { return m_name == hashTableDeletedValue(); }
-
-private:
-    void ref() const;
-    void deref() const;
-
-    static AtomicStringImpl* hashTableDeletedValue() { return reinterpret_cast<AtomicStringImpl*>(-1); }
-
-    AtomicStringImpl* m_name;
-    AtomicStringImpl* m_type;
-};
-
-inline bool operator==(const FormElementKey& a, const FormElementKey& b)
-{
-    return a.name() == b.name() && a.type() == b.type();
-}
-
-struct FormElementKeyHash {
-    static unsigned hash(const FormElementKey&);
-    static bool equal(const FormElementKey& a, const FormElementKey& b) { return a == b; }
-    static const bool safeToCompareToEmptyOrDeleted = true;
-};
-
-struct FormElementKeyHashTraits : WTF::GenericHashTraits<FormElementKey> {
-    static void constructDeletedValue(FormElementKey& slot) { new (NotNull, &slot) FormElementKey(WTF::HashTableDeletedValue); }
-    static bool isDeletedValue(const FormElementKey& value) { return value.isHashTableDeletedValue(); }
-};
-
 enum PageshowEventPersistence {
     PageshowEventNotPersisted = 0,
     PageshowEventPersisted = 1
@@ -540,17 +496,10 @@ public:
     bool usesLinkRules() const { return linkColor() != visitedLinkColor() || m_usesLinkRules; }
     void setUsesLinkRules(bool b) { m_usesLinkRules = b; }
 
-    // Machinery for saving and restoring state when you leave and then go back to a page.
-    void registerFormElementWithState(HTMLFormControlElementWithState* control) { m_formElementsWithState.add(control); }
-    void unregisterFormElementWithState(HTMLFormControlElementWithState* control) { m_formElementsWithState.remove(control); }
+    // Never returns 0.
+    FormController* formController();
     Vector<String> formElementsState() const;
     void setStateForNewFormElements(const Vector<String>&);
-    bool hasStateForNewFormElements() const;
-    bool takeStateForFormElement(AtomicStringImpl* name, AtomicStringImpl* type, String& state);
-
-    void registerFormElementWithFormAttribute(FormAssociatedElement*);
-    void unregisterFormElementWithFormAttribute(FormAssociatedElement*);
-    void resetFormElementsOwner();
 
     FrameView* view() const; // can be NULL
     Frame* frame() const { return m_frame; } // can be NULL
@@ -1045,8 +994,6 @@ public:
 
     virtual void removeAllEventListeners();
 
-    CheckedRadioButtons& checkedRadioButtons() { return m_checkedRadioButtons; }
-    
 #if ENABLE(SVG)
     const SVGDocumentExtensions* svgExtensions();
     SVGDocumentExtensions* accessSVGExtensions();
@@ -1338,14 +1285,8 @@ private:
     typedef ListHashSet<Node*, 32> StyleSheetCandidateListHashSet;
     StyleSheetCandidateListHashSet m_styleSheetCandidateNodes; // All of the nodes that could potentially provide stylesheets to the document (<link>, <style>, <?xml-stylesheet>)
 
-    typedef ListHashSet<HTMLFormControlElementWithState*, 64> FormElementListHashSet;
-    FormElementListHashSet m_formElementsWithState;
-    typedef ListHashSet<RefPtr<FormAssociatedElement>, 32> FormAssociatedElementListHashSet;
-    FormAssociatedElementListHashSet m_formElementsWithFormAttribute;
+    OwnPtr<FormController> m_formController;
 
-    typedef HashMap<FormElementKey, Vector<String>, FormElementKeyHash, FormElementKeyHashTraits> FormElementStateMap;
-    FormElementStateMap m_stateForNewFormElements;
-    
     Color m_linkColor;
     Color m_visitedLinkColor;
     Color m_activeLinkColor;
@@ -1428,8 +1369,6 @@ private:
 
     InheritedBool m_designMode;
     
-    CheckedRadioButtons m_checkedRadioButtons;
-
     OwnPtr<HTMLCollection> m_collections[NumUnnamedDocumentCachedTypes];
     OwnPtr<HTMLAllCollection> m_allCollection;
 
index 390c149..39fe71d 100644 (file)
@@ -25,6 +25,7 @@
 #include "config.h"
 #include "FormAssociatedElement.h"
 
+#include "FormController.h"
 #include "HTMLFormControlElement.h"
 #include "HTMLFormElement.h"
 #include "HTMLNames.h"
@@ -57,7 +58,7 @@ void FormAssociatedElement::didMoveToNewDocument(Document* oldDocument)
 {
     HTMLElement* element = toHTMLElement(this);
     if (oldDocument && element->fastHasAttribute(formAttr))
-        oldDocument->unregisterFormElementWithFormAttribute(this);
+        oldDocument->formController()->unregisterFormElementWithFormAttribute(this);
 }
 
 void FormAssociatedElement::insertedInto(ContainerNode* insertionPoint)
@@ -68,14 +69,14 @@ void FormAssociatedElement::insertedInto(ContainerNode* insertionPoint)
 
     HTMLElement* element = toHTMLElement(this);
     if (element->fastHasAttribute(formAttr))
-        element->document()->registerFormElementWithFormAttribute(this);
+        element->document()->formController()->registerFormElementWithFormAttribute(this);
 }
 
 void FormAssociatedElement::removedFrom(ContainerNode* insertionPoint)
 {
     HTMLElement* element = toHTMLElement(this);
     if (insertionPoint->inDocument() && element->fastHasAttribute(formAttr))
-        element->document()->unregisterFormElementWithFormAttribute(this);
+        element->document()->formController()->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 && element->highestAncestor() != m_form->highestAncestor())
@@ -152,7 +153,7 @@ void FormAssociatedElement::formAttributeChanged()
     if (!element->fastHasAttribute(formAttr)) {
         // The form attribute removed. We need to reset form owner here.
         setForm(element->findFormAncestor());
-        element->document()->unregisterFormElementWithFormAttribute(this);
+        element->document()->formController()->unregisterFormElementWithFormAttribute(this);
     } else
         resetFormOwner();
 }
diff --git a/Source/WebCore/html/FormController.cpp b/Source/WebCore/html/FormController.cpp
new file mode 100644 (file)
index 0000000..69b931f
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2006, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010, 2011, 2012 Google 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.
+ */
+
+#include "config.h"
+#include "FormController.h"
+
+#include "HTMLFormControlElementWithState.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+FormController::FormController()
+{
+}
+
+FormController::~FormController()
+{
+}
+
+Vector<String> FormController::formElementsState() const
+{
+    Vector<String> stateVector;
+    stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 3);
+    typedef FormElementListHashSet::const_iterator Iterator;
+    Iterator end = m_formElementsWithState.end();
+    for (Iterator it = m_formElementsWithState.begin(); it != end; ++it) {
+        HTMLFormControlElementWithState* elementWithState = *it;
+        if (!elementWithState->shouldSaveAndRestoreFormControlState())
+            continue;
+        String value;
+        if (!elementWithState->saveFormControlState(value))
+            continue;
+        stateVector.append(elementWithState->formControlName().string());
+        stateVector.append(elementWithState->formControlType().string());
+        stateVector.append(value);
+    }
+    return stateVector;
+}
+
+void FormController::setStateForNewFormElements(const Vector<String>& stateVector)
+{
+    // Walk the state vector backwards so that the value to use for each
+    // name/type pair first is the one at the end of each individual vector
+    // in the FormElementStateMap. We're using them like stacks.
+    typedef FormElementStateMap::iterator Iterator;
+    m_formElementsWithState.clear();
+    for (size_t i = stateVector.size() / 3 * 3; i; i -= 3) {
+        AtomicString a = stateVector[i - 3];
+        AtomicString b = stateVector[i - 2];
+        const String& c = stateVector[i - 1];
+        FormElementKey key(a.impl(), b.impl());
+        Iterator it = m_stateForNewFormElements.find(key);
+        if (it != m_stateForNewFormElements.end())
+            it->second.append(c);
+        else {
+            Vector<String> v(1);
+            v[0] = c;
+            m_stateForNewFormElements.set(key, v);
+        }
+    }
+}
+
+bool FormController::hasStateForNewFormElements() const
+{
+    return !m_stateForNewFormElements.isEmpty();
+}
+
+bool FormController::takeStateForFormElement(AtomicStringImpl* name, AtomicStringImpl* type, String& state)
+{
+    typedef FormElementStateMap::iterator Iterator;
+    Iterator it = m_stateForNewFormElements.find(FormElementKey(name, type));
+    if (it == m_stateForNewFormElements.end())
+        return false;
+    ASSERT(it->second.size());
+    state = it->second.last();
+    if (it->second.size() > 1)
+        it->second.removeLast();
+    else
+        m_stateForNewFormElements.remove(it);
+    return true;
+}
+
+void FormController::registerFormElementWithFormAttribute(FormAssociatedElement* element)
+{
+    ASSERT(toHTMLElement(element)->fastHasAttribute(formAttr));
+    m_formElementsWithFormAttribute.add(element);
+}
+
+void FormController::unregisterFormElementWithFormAttribute(FormAssociatedElement* element)
+{
+    m_formElementsWithFormAttribute.remove(element);
+}
+
+void FormController::resetFormElementsOwner()
+{
+    typedef FormAssociatedElementListHashSet::iterator Iterator;
+    Iterator end = m_formElementsWithFormAttribute.end();
+    for (Iterator it = m_formElementsWithFormAttribute.begin(); it != end; ++it)
+        (*it)->resetFormOwner();
+}
+
+FormElementKey::FormElementKey(AtomicStringImpl* name, AtomicStringImpl* type)
+    : m_name(name), m_type(type)
+{
+    ref();
+}
+
+FormElementKey::~FormElementKey()
+{
+    deref();
+}
+
+FormElementKey::FormElementKey(const FormElementKey& other)
+    : m_name(other.name()), m_type(other.type())
+{
+    ref();
+}
+
+FormElementKey& FormElementKey::operator=(const FormElementKey& other)
+{
+    other.ref();
+    deref();
+    m_name = other.name();
+    m_type = other.type();
+    return *this;
+}
+
+void FormElementKey::ref() const
+{
+    if (name())
+        name()->ref();
+    if (type())
+        type()->ref();
+}
+
+void FormElementKey::deref() const
+{
+    if (name())
+        name()->deref();
+    if (type())
+        type()->deref();
+}
+
+unsigned FormElementKeyHash::hash(const FormElementKey& key)
+{
+    return StringHasher::hashMemory<sizeof(FormElementKey)>(&key);
+}
+
+} // namespace WebCore
+
diff --git a/Source/WebCore/html/FormController.h b/Source/WebCore/html/FormController.h
new file mode 100644 (file)
index 0000000..991d35d
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2010, 2011, 2012 Google 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 FormController_h
+#define FormController_h
+
+#include "CheckedRadioButtons.h"
+#include <wtf/Forward.h>
+#include <wtf/ListHashSet.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class FormAssociatedElement;
+class HTMLFormControlElementWithState;
+
+class FormElementKey {
+public:
+    FormElementKey(AtomicStringImpl* = 0, AtomicStringImpl* = 0);
+    ~FormElementKey();
+    FormElementKey(const FormElementKey&);
+    FormElementKey& operator=(const FormElementKey&);
+
+    AtomicStringImpl* name() const { return m_name; }
+    AtomicStringImpl* type() const { return m_type; }
+
+    // Hash table deleted values, which are only constructed and never copied or destroyed.
+    FormElementKey(WTF::HashTableDeletedValueType) : m_name(hashTableDeletedValue()) { }
+    bool isHashTableDeletedValue() const { return m_name == hashTableDeletedValue(); }
+
+private:
+    void ref() const;
+    void deref() const;
+
+    static AtomicStringImpl* hashTableDeletedValue() { return reinterpret_cast<AtomicStringImpl*>(-1); }
+
+    AtomicStringImpl* m_name;
+    AtomicStringImpl* m_type;
+};
+
+inline bool operator==(const FormElementKey& a, const FormElementKey& b)
+{
+    return a.name() == b.name() && a.type() == b.type();
+}
+
+struct FormElementKeyHash {
+    static unsigned hash(const FormElementKey&);
+    static bool equal(const FormElementKey& a, const FormElementKey& b) { return a == b; }
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+struct FormElementKeyHashTraits : WTF::GenericHashTraits<FormElementKey> {
+    static void constructDeletedValue(FormElementKey& slot) { new (NotNull, &slot) FormElementKey(WTF::HashTableDeletedValue); }
+    static bool isDeletedValue(const FormElementKey& value) { return value.isHashTableDeletedValue(); }
+};
+
+class FormController {
+public:
+    static PassOwnPtr<FormController> create()
+    {
+        return adoptPtr(new FormController);
+    }
+    ~FormController();
+
+    CheckedRadioButtons& checkedRadioButtons() { return m_checkedRadioButtons; }
+    
+    void registerFormElementWithState(HTMLFormControlElementWithState* control) { m_formElementsWithState.add(control); }
+    void unregisterFormElementWithState(HTMLFormControlElementWithState* control) { m_formElementsWithState.remove(control); }
+    // This should be callled only by Document::formElementsState().
+    Vector<String> formElementsState() const;
+    // This should be callled only by Document::setStateForNewFormElements().
+    void setStateForNewFormElements(const Vector<String>&);
+    bool hasStateForNewFormElements() const;
+    bool takeStateForFormElement(AtomicStringImpl* name, AtomicStringImpl* type, String& state);
+
+    void registerFormElementWithFormAttribute(FormAssociatedElement*);
+    void unregisterFormElementWithFormAttribute(FormAssociatedElement*);
+    void resetFormElementsOwner();
+
+private:
+    FormController();
+
+    CheckedRadioButtons m_checkedRadioButtons;
+
+    typedef ListHashSet<HTMLFormControlElementWithState*, 64> FormElementListHashSet;
+    FormElementListHashSet m_formElementsWithState;
+    typedef ListHashSet<RefPtr<FormAssociatedElement>, 32> FormAssociatedElementListHashSet;
+    FormAssociatedElementListHashSet m_formElementsWithFormAttribute;
+
+    typedef HashMap<FormElementKey, Vector<String>, FormElementKeyHash, FormElementKeyHashTraits> FormElementStateMap;
+    FormElementStateMap m_stateForNewFormElements;
+    
+};
+
+} // namespace WebCore
+#endif
index bf94c54..94aead4 100644 (file)
@@ -25,6 +25,7 @@
 #include "config.h"
 #include "HTMLFormControlElementWithState.h"
 
+#include "FormController.h"
 #include "HTMLFormElement.h"
 
 namespace WebCore {
@@ -32,19 +33,19 @@ namespace WebCore {
 HTMLFormControlElementWithState::HTMLFormControlElementWithState(const QualifiedName& tagName, Document* doc, HTMLFormElement* f)
     : HTMLFormControlElement(tagName, doc, f)
 {
-    document()->registerFormElementWithState(this);
+    document()->formController()->registerFormElementWithState(this);
 }
 
 HTMLFormControlElementWithState::~HTMLFormControlElementWithState()
 {
-    document()->unregisterFormElementWithState(this);
+    document()->formController()->unregisterFormElementWithState(this);
 }
 
 void HTMLFormControlElementWithState::didMoveToNewDocument(Document* oldDocument)
 {
     if (oldDocument)
-        oldDocument->unregisterFormElementWithState(this);
-    document()->registerFormElementWithState(this);
+        oldDocument->formController()->unregisterFormElementWithState(this);
+    document()->formController()->registerFormElementWithState(this);
     HTMLFormControlElement::didMoveToNewDocument(oldDocument);
 }
 
@@ -72,9 +73,9 @@ void HTMLFormControlElementWithState::finishParsingChildren()
         return;
 
     Document* doc = document();
-    if (doc->hasStateForNewFormElements()) {
+    if (doc->formController()->hasStateForNewFormElements()) {
         String state;
-        if (doc->takeStateForFormElement(name().impl(), type().impl(), state))
+        if (doc->formController()->takeStateForFormElement(name().impl(), type().impl(), state))
             restoreFormControlState(state);
     }
 }
index ea54b93..719b46e 100644 (file)
@@ -34,6 +34,7 @@
 #include "EventNames.h"
 #include "FileList.h"
 #include "FileSystem.h"
+#include "FormController.h"
 #include "FormData.h"
 #include "FormDataList.h"
 #include "FormState.h"
@@ -144,7 +145,7 @@ void HTMLFormElement::didNotifyDescendantInsertions(ContainerNode* insertionPoin
     ASSERT(insertionPoint->inDocument());
     HTMLElement::didNotifyDescendantInsertions(insertionPoint);
     if (hasID())
-        document()->resetFormElementsOwner();
+        document()->formController()->resetFormElementsOwner();
 }
 
 static inline Node* findRoot(Node* n)
@@ -163,7 +164,7 @@ void HTMLFormElement::removedFrom(ContainerNode* insertionPoint)
         associatedElements[i]->formRemovedFromTree(root);
     HTMLElement::removedFrom(insertionPoint);
     if (insertionPoint->inDocument() && hasID())
-        document()->resetFormElementsOwner();
+        document()->formController()->resetFormElementsOwner();
 }
 
 void HTMLFormElement::handleLocalEvents(Event* event)
index 231142e..c6cf1f4 100644 (file)
@@ -37,6 +37,7 @@
 #include "EventNames.h"
 #include "ExceptionCode.h"
 #include "FileList.h"
+#include "FormController.h"
 #include "Frame.h"
 #include "HTMLCollection.h"
 #include "HTMLDataListElement.h"
@@ -127,7 +128,7 @@ HTMLInputElement::~HTMLInputElement()
     // setForm(0) may register this to a document-level radio button group.
     // We should unregister it to avoid accessing a deleted object.
     if (isRadioButton())
-        document()->checkedRadioButtons().removeButton(this);
+        document()->formController()->checkedRadioButtons().removeButton(this);
 }
 
 const AtomicString& HTMLInputElement::formControlName() const
@@ -1374,7 +1375,7 @@ void HTMLInputElement::didMoveToNewDocument(Document* oldDocument)
         if (needsSuspensionCallback)
             oldDocument->unregisterForPageCacheSuspensionCallbacks(this);
         if (isRadioButton())
-            oldDocument->checkedRadioButtons().removeButton(this);
+            oldDocument->formController()->checkedRadioButtons().removeButton(this);
     }
 
     if (needsSuspensionCallback)
@@ -1672,7 +1673,7 @@ CheckedRadioButtons* HTMLInputElement::checkedRadioButtons() const
     if (HTMLFormElement* formElement = form())
         return &formElement->checkedRadioButtons();
     if (inDocument())
-        return &document()->checkedRadioButtons();
+        return &document()->formController()->checkedRadioButtons();
     return 0;
 }
 
index 105deb7..a5c1998 100644 (file)
@@ -30,6 +30,7 @@
 
 namespace WebCore {
 
+class CheckedRadioButtons;
 class FileList;
 class HTMLDataListElement;
 class HTMLOptionElement;
index 2790664..367c0fe 100644 (file)
@@ -75,6 +75,7 @@ enum WhitespaceMode {
 class AtomicHTMLToken;
 class Document;
 class Element;
+class HTMLFormElement;
 
 class HTMLConstructionSite {
     WTF_MAKE_NONCOPYABLE(HTMLConstructionSite);