2010-06-24 Dimitri Glazkov <dglazkov@chromium.org>
authordglazkov@chromium.org <dglazkov@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 23 Jul 2010 22:17:56 +0000 (22:17 +0000)
committerdglazkov@chromium.org <dglazkov@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 23 Jul 2010 22:17:56 +0000 (22:17 +0000)
        Reviewed by Kent Tamura.

        Move more form submission logic into FormSubmission.
        https://bugs.webkit.org/show_bug.cgi?id=41110

        Two major moves:
        * Fold HTMLFormElement::prepareFormSubmission into FormSubmission::create
        * Move non-static (non-FormData-building) methods of FormDataBuilder
            to FormSubmission::Attributes.

        Mechanical moving, no change in behavior, so no new tests.

        * WebCore.xcodeproj/project.pbxproj: Gave FormDataBuilder.h "project" and
            FormSubmission.h "private" visibility.
        * html/HTMLFormElement.cpp:
        (WebCore::HTMLFormElement::submit): Changed to use FormSubmission::create.
        (WebCore::HTMLFormElement::parseMappedAttribute): Changed to use m_attributes.
        * html/HTMLFormElement.h:
        (WebCore::HTMLFormElement::enctype): Ditto.
        (WebCore::HTMLFormElement::encoding): Ditto.
        (WebCore::HTMLFormElement::acceptCharset): Ditto.
        * loader/FormSubmission.cpp:
        (WebCore::generateFormDataIdentifier): Moved from HTMLFormElement.
        (WebCore::appendMailtoPostFormDataToURL): Ditto.
        (WebCore::FormSubmission::Attributes::parseAction): Moved from FormDataBuilder.
        (WebCore::FormSubmission::Attributes::parseEncodingType): Ditto.
        (WebCore::FormSubmission::Attributes::parseMethodType): Ditto.
        (WebCore::FormSubmission::FormSubmission): Made inline.
        (WebCore::FormSubmission::create): Added logic that used to be in
            HTMLFormElement::prepareFormSubmission.
        * loader/FormSubmission.h:
        (WebCore::FormSubmission::):
        (WebCore::FormSubmission::Attributes::Attributes): Added new class.
        (WebCore::FormSubmission::Attributes::method): Moved from FormDataBuilder.
        (WebCore::FormSubmission::Attributes::isMultiPartForm): Ditto.
        (WebCore::FormSubmission::Attributes::action): Ditto.
        (WebCore::FormSubmission::Attributes::target): Ditto.
        (WebCore::FormSubmission::Attributes::setTarget): Ditto.
        (WebCore::FormSubmission::Attributes::encodingType): Ditto.
        (WebCore::FormSubmission::Attributes::acceptCharset): Ditto.
        (WebCore::FormSubmission::Attributes::setAcceptCharset): Ditto.
        (WebCore::FormSubmission::target): Ditto.
        (WebCore::FormSubmission::contentType): Const-ified return type.
        (WebCore::FormSubmission::boundary): Ditto.
        * platform/network/FormDataBuilder.cpp:
        (WebCore::FormDataBuilder::encodingFromAcceptCharset): Renamed method for clarity,
            made it use param instead of a class member.
        * platform/network/FormDataBuilder.h:
        (WebCore::FormDataBuilder::FormDataBuilder): Made constructor private.
        * wml/WMLGoElement.cpp: Changed to use FormSubmision::Attributes.
        * wml/WMLGoElement.h: Ditto.

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

WebCore/ChangeLog
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/html/HTMLFormElement.cpp
WebCore/html/HTMLFormElement.h
WebCore/loader/FormSubmission.cpp
WebCore/loader/FormSubmission.h
WebCore/platform/network/FormDataBuilder.cpp
WebCore/platform/network/FormDataBuilder.h
WebCore/wml/WMLGoElement.cpp
WebCore/wml/WMLGoElement.h

index 35a1981..0b1f5ee 100644 (file)
@@ -1,3 +1,57 @@
+2010-06-24  Dimitri Glazkov  <dglazkov@chromium.org>
+
+        Reviewed by Kent Tamura.
+
+        Move more form submission logic into FormSubmission.
+        https://bugs.webkit.org/show_bug.cgi?id=41110
+
+        Two major moves:
+        * Fold HTMLFormElement::prepareFormSubmission into FormSubmission::create
+        * Move non-static (non-FormData-building) methods of FormDataBuilder
+            to FormSubmission::Attributes.
+
+        Mechanical moving, no change in behavior, so no new tests.
+
+        * WebCore.xcodeproj/project.pbxproj: Gave FormDataBuilder.h "project" and
+            FormSubmission.h "private" visibility.
+        * html/HTMLFormElement.cpp:
+        (WebCore::HTMLFormElement::submit): Changed to use FormSubmission::create.
+        (WebCore::HTMLFormElement::parseMappedAttribute): Changed to use m_attributes.
+        * html/HTMLFormElement.h:
+        (WebCore::HTMLFormElement::enctype): Ditto.
+        (WebCore::HTMLFormElement::encoding): Ditto.
+        (WebCore::HTMLFormElement::acceptCharset): Ditto.
+        * loader/FormSubmission.cpp:
+        (WebCore::generateFormDataIdentifier): Moved from HTMLFormElement.
+        (WebCore::appendMailtoPostFormDataToURL): Ditto.
+        (WebCore::FormSubmission::Attributes::parseAction): Moved from FormDataBuilder.
+        (WebCore::FormSubmission::Attributes::parseEncodingType): Ditto.
+        (WebCore::FormSubmission::Attributes::parseMethodType): Ditto.
+        (WebCore::FormSubmission::FormSubmission): Made inline.
+        (WebCore::FormSubmission::create): Added logic that used to be in
+            HTMLFormElement::prepareFormSubmission.
+        * loader/FormSubmission.h:
+        (WebCore::FormSubmission::):
+        (WebCore::FormSubmission::Attributes::Attributes): Added new class.
+        (WebCore::FormSubmission::Attributes::method): Moved from FormDataBuilder.
+        (WebCore::FormSubmission::Attributes::isMultiPartForm): Ditto.
+        (WebCore::FormSubmission::Attributes::action): Ditto.
+        (WebCore::FormSubmission::Attributes::target): Ditto.
+        (WebCore::FormSubmission::Attributes::setTarget): Ditto.
+        (WebCore::FormSubmission::Attributes::encodingType): Ditto.
+        (WebCore::FormSubmission::Attributes::acceptCharset): Ditto.
+        (WebCore::FormSubmission::Attributes::setAcceptCharset): Ditto.
+        (WebCore::FormSubmission::target): Ditto.
+        (WebCore::FormSubmission::contentType): Const-ified return type.
+        (WebCore::FormSubmission::boundary): Ditto.
+        * platform/network/FormDataBuilder.cpp:
+        (WebCore::FormDataBuilder::encodingFromAcceptCharset): Renamed method for clarity,
+            made it use param instead of a class member.
+        * platform/network/FormDataBuilder.h:
+        (WebCore::FormDataBuilder::FormDataBuilder): Made constructor private.
+        * wml/WMLGoElement.cpp: Changed to use FormSubmision::Attributes.
+        * wml/WMLGoElement.h: Ditto.
+
 2010-07-23  Adam Barth  <abarth@webkit.org>
 
         Reviewed by Eric Seidel.
index ae2db13..ab88da3 100644 (file)
                085AFDC80F2977350061F2B3 /* WMLFormControlElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 085AFDC60F2977350061F2B3 /* WMLFormControlElement.cpp */; };
                085AFDC90F2977350061F2B3 /* WMLFormControlElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 085AFDC70F2977350061F2B3 /* WMLFormControlElement.h */; settings = {ATTRIBUTES = (); }; };
                085B92BA0EFDE73D00E6123C /* FormDataBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 085B92B80EFDE73D00E6123C /* FormDataBuilder.cpp */; };
-               085B92BB0EFDE73D00E6123C /* FormDataBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 085B92B90EFDE73D00E6123C /* FormDataBuilder.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               085B92BB0EFDE73D00E6123C /* FormDataBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 085B92B90EFDE73D00E6123C /* FormDataBuilder.h */; settings = {ATTRIBUTES = (); }; };
                0865CCE60EDDF51B00DF9EC3 /* WMLNoopElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0865CCE40EDDF51B00DF9EC3 /* WMLNoopElement.cpp */; };
                0865CCE70EDDF51B00DF9EC3 /* WMLNoopElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 0865CCE50EDDF51B00DF9EC3 /* WMLNoopElement.h */; };
                08700BE70F086C5300919419 /* InputElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08700BE60F086C5300919419 /* InputElement.cpp */; };
                416E75CB0EDF90C700360E1D /* ScriptCallFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 416E75C90EDF90C700360E1D /* ScriptCallFrame.h */; };
                416E75CC0EDF90C700360E1D /* ScriptCallFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 416E75CA0EDF90C700360E1D /* ScriptCallFrame.cpp */; };
                416F45F00ED7B311008215B6 /* ScriptString.h in Headers */ = {isa = PBXBuildFile; fileRef = 416F45EF0ED7B311008215B6 /* ScriptString.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               41885B9311B6FDA6003383BB /* FormSubmission.h in Headers */ = {isa = PBXBuildFile; fileRef = 41885B9111B6FDA6003383BB /* FormSubmission.h */; };
+               41885B9311B6FDA6003383BB /* FormSubmission.h in Headers */ = {isa = PBXBuildFile; fileRef = 41885B9111B6FDA6003383BB /* FormSubmission.h */; settings = {ATTRIBUTES = (Private, ); }; };
                41885B9411B6FDA6003383BB /* FormSubmission.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41885B9211B6FDA6003383BB /* FormSubmission.cpp */; };
                418F88040FF957AE0080F045 /* JSAbstractWorker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 418F88020FF957AE0080F045 /* JSAbstractWorker.cpp */; };
                418F88050FF957AF0080F045 /* JSAbstractWorker.h in Headers */ = {isa = PBXBuildFile; fileRef = 418F88030FF957AE0080F045 /* JSAbstractWorker.h */; };
index 4d6b603..7afd434 100644 (file)
@@ -36,7 +36,6 @@
 #include "FormData.h"
 #include "FormDataList.h"
 #include "FormState.h"
-#include "FormSubmission.h"
 #include "Frame.h"
 #include "FrameLoader.h"
 #include "FrameLoaderClient.h"
@@ -50,8 +49,6 @@
 #include "ScriptEventListener.h"
 #include "ValidityState.h"
 #include <limits>
-#include <wtf/CurrentTime.h>
-#include <wtf/RandomNumber.h>
 
 #if PLATFORM(WX)
 #include <wx/defs.h>
@@ -64,14 +61,6 @@ namespace WebCore {
 
 using namespace HTMLNames;
 
-static int64_t generateFormDataIdentifier()
-{
-    // Initialize to the current time to reduce the likelihood of generating
-    // identifiers that overlap with those from past/future browser sessions.
-    static int64_t nextIdentifier = static_cast<int64_t>(currentTime() * 1000000.0);
-    return ++nextIdentifier;
-}
-
 HTMLFormElement::HTMLFormElement(const QualifiedName& tagName, Document* document)
     : HTMLElement(tagName, document)
     , m_submissionTrigger(NotSubmittedByJavaScript)
@@ -193,79 +182,6 @@ void HTMLFormElement::submitImplicitly(Event* event, bool fromImplicitSubmission
         prepareSubmit(event);
 }
 
-static void appendMailtoPostFormDataToURL(KURL& url, const FormData& data, const String& encodingType)
-{
-    String body = data.flattenToString();
-
-    if (equalIgnoringCase(encodingType, "text/plain")) {
-        // Convention seems to be to decode, and s/&/\r\n/. Also, spaces are encoded as %20.
-        body = decodeURLEscapeSequences(body.replace('&', "\r\n").replace('+', ' ') + "\r\n");
-    }
-
-    Vector<char> bodyData;
-    bodyData.append("body=", 5);
-    FormDataBuilder::encodeStringAsFormData(bodyData, body.utf8());
-    body = String(bodyData.data(), bodyData.size()).replace('+', "%20");
-
-    String query = url.query();
-    if (!query.isEmpty())
-        query.append('&');
-    query.append(body);
-    url.setQuery(query);
-}
-
-PassRefPtr<FormSubmission> HTMLFormElement::prepareFormSubmission(Event* event, bool lockHistory, FormSubmissionTrigger trigger)
-{
-    KURL actionURL = document()->completeURL(m_formDataBuilder.action().isEmpty() ? document()->url().string() : m_formDataBuilder.action());
-    bool isMailtoForm = actionURL.protocolIs("mailto");
-
-    if (m_formDataBuilder.isPostMethod()) {
-        if (m_formDataBuilder.isMultiPartForm() && isMailtoForm) {
-            m_formDataBuilder.parseEncodingType("application/x-www-form-urlencoded");
-            ASSERT(!m_formDataBuilder.isMultiPartForm());
-        }
-    } else
-        m_formDataBuilder.setIsMultiPartForm(false);
-
-    TextEncoding dataEncoding = isMailtoForm ? UTF8Encoding() : m_formDataBuilder.dataEncoding(document());
-    RefPtr<DOMFormData> domFormData = DOMFormData::create(dataEncoding.encodingForFormSubmission());
-    Vector<pair<String, String> > formValues;
-
-    for (unsigned i = 0; i < m_associatedElements.size(); ++i) {
-        HTMLFormControlElement* control = m_associatedElements[i];
-        if (!control->disabled())
-            control->appendFormData(*domFormData, m_formDataBuilder.isMultiPartForm());
-        if (control->hasLocalName(inputTag)) {
-            HTMLInputElement* input = static_cast<HTMLInputElement*>(control);
-            if (input->isTextField()) {
-                formValues.append(pair<String, String>(input->name(), input->value()));
-                if (input->isSearchField())
-                    input->addSearchResult();
-            }
-        }
-    }
-
-    RefPtr<FormData> formData;
-    String boundary;
-
-    if (m_formDataBuilder.isMultiPartForm()) {
-        formData = FormData::createMultiPart(domFormData->items(), domFormData->encoding(), document());
-        boundary = formData->boundary().data();
-    } else {
-        formData = FormData::create(domFormData->items(), domFormData->encoding());
-        if (m_formDataBuilder.isPostMethod() && isMailtoForm) {
-            // Convert the form data into a string that we put into the URL.
-            appendMailtoPostFormDataToURL(actionURL, *formData, m_formDataBuilder.encodingType());
-            formData = FormData::create();
-        }
-    }
-
-    formData->setIdentifier(generateFormDataIdentifier());
-    FormSubmission::Method method = m_formDataBuilder.isPostMethod() ? FormSubmission::PostMethod : FormSubmission::GetMethod;
-    String targetOrBaseTarget = m_formDataBuilder.target().isEmpty() ? document()->baseTarget() : m_formDataBuilder.target();
-    return FormSubmission::create(method, actionURL, targetOrBaseTarget, m_formDataBuilder.encodingType(), FormState::create(this, formValues, document()->frame(), trigger), formData.release(), boundary, lockHistory, event);
-}
-
 static inline HTMLFormControlElement* submitElementFromEvent(const Event* event)
 {
     Node* targetNode = event->target()->toNode();
@@ -389,7 +305,7 @@ void HTMLFormElement::submit(Event* event, bool activateSubmitButton, bool lockH
     if (needButtonActivation && firstSuccessfulSubmitButton)
         firstSuccessfulSubmitButton->setActivatedSubmit(true);
 
-    frame->loader()->submitForm(prepareFormSubmission(event, lockHistory, formSubmissionTrigger));
+    frame->loader()->submitForm(FormSubmission::create(this, m_attributes, event, lockHistory, formSubmissionTrigger));
 
     if (needButtonActivation && firstSuccessfulSubmitButton)
         firstSuccessfulSubmitButton->setActivatedSubmit(false);
@@ -421,17 +337,17 @@ void HTMLFormElement::reset()
 void HTMLFormElement::parseMappedAttribute(Attribute* attr)
 {
     if (attr->name() == actionAttr)
-        m_formDataBuilder.parseAction(attr->value());
+        m_attributes.parseAction(attr->value());
     else if (attr->name() == targetAttr)
-        m_formDataBuilder.setTarget(attr->value());
+        m_attributes.setTarget(attr->value());
     else if (attr->name() == methodAttr)
-        m_formDataBuilder.parseMethodType(attr->value());
+        m_attributes.parseMethodType(attr->value());
     else if (attr->name() == enctypeAttr)
-        m_formDataBuilder.parseEncodingType(attr->value());
+        m_attributes.parseEncodingType(attr->value());
     else if (attr->name() == accept_charsetAttr)
         // space separated list of charsets the server
         // accepts - see rfc2045
-        m_formDataBuilder.setAcceptCharset(attr->value());
+        m_attributes.setAcceptCharset(attr->value());
     else if (attr->name() == acceptAttr) {
         // ignore this one for the moment...
     } else if (attr->name() == autocompleteAttr) {
index 5aa9a5c..c9fb9ac 100644 (file)
@@ -25,8 +25,8 @@
 #define HTMLFormElement_h
 
 #include "CheckedRadioButtons.h"
-#include "FormDataBuilder.h"
 #include "FormState.h"
+#include "FormSubmission.h"
 #include "HTMLElement.h"
 #include <wtf/OwnPtr.h>
 
@@ -34,7 +34,6 @@ namespace WebCore {
 
 class Event;
 class FormData;
-class FormSubmission;
 class HTMLFormControlElement;
 class HTMLImageElement;
 class HTMLInputElement;
@@ -55,10 +54,10 @@ public:
     unsigned length() const;
     Node* item(unsigned index);
 
-    String enctype() const { return m_formDataBuilder.encodingType(); }
+    String enctype() const { return m_attributes.encodingType(); }
     void setEnctype(const String&);
 
-    String encoding() const { return m_formDataBuilder.encodingType(); }
+    String encoding() const { return m_attributes.encodingType(); }
     void setEncoding(const String& value) { setEnctype(value); }
 
     bool autoComplete() const { return m_autocomplete; }
@@ -88,7 +87,8 @@ public:
 
     bool noValidate() const;
 
-    String acceptCharset() const { return m_formDataBuilder.acceptCharset(); }
+    String acceptCharset() const { return m_attributes.acceptCharset(); }
+    void setAcceptCharset(const String&);
 
     String action() const;
     void setAction(const String&);
@@ -134,7 +134,6 @@ private:
 
     void submit(Event*, bool activateSubmitButton, bool lockHistory, FormSubmissionTrigger);
 
-    PassRefPtr<FormSubmission> prepareFormSubmission(Event*, bool lockHistory, FormSubmissionTrigger);
     unsigned formElementIndex(HTMLFormControlElement*);
     // Returns true if the submission should be proceeded.
     bool validateInteractively(Event*);
@@ -146,7 +145,7 @@ private:
 
     typedef HashMap<RefPtr<AtomicStringImpl>, RefPtr<HTMLFormControlElement> > AliasMap;
 
-    FormDataBuilder m_formDataBuilder;
+    FormSubmission::Attributes m_attributes;
     OwnPtr<AliasMap> m_elementAliases;
     OwnPtr<CollectionCache> m_collectionCache;
 
index 4d44174..f661273 100644 (file)
 #include "config.h"
 #include "FormSubmission.h"
 
+#include "CSSHelper.h"
+#include "DOMFormData.h"
+#include "Document.h"
 #include "Event.h"
 #include "FormData.h"
+#include "FormDataBuilder.h"
 #include "FormState.h"
 #include "Frame.h"
 #include "FrameLoadRequest.h"
 #include "FrameLoader.h"
+#include "HTMLFormControlElement.h"
 #include "HTMLFormElement.h"
-#include <wtf/PassRefPtr.h>
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
+#include "TextEncoding.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/RandomNumber.h>
 
 namespace WebCore {
 
-FormSubmission::FormSubmission(Method method, const KURL& action, const String& target, const String& contentType, PassRefPtr<FormState> state, PassRefPtr<FormData> data, const String& boundary, bool lockHistory, PassRefPtr<Event> event)
+using namespace HTMLNames;
+
+static int64_t generateFormDataIdentifier()
+{
+    // Initialize to the current time to reduce the likelihood of generating
+    // identifiers that overlap with those from past/future browser sessions.
+    static int64_t nextIdentifier = static_cast<int64_t>(currentTime() * 1000000.0);
+    return ++nextIdentifier;
+}
+
+static void appendMailtoPostFormDataToURL(KURL& url, const FormData& data, const String& encodingType)
+{
+    String body = data.flattenToString();
+
+    if (equalIgnoringCase(encodingType, "text/plain")) {
+        // Convention seems to be to decode, and s/&/\r\n/. Also, spaces are encoded as %20.
+        body = decodeURLEscapeSequences(body.replace('&', "\r\n").replace('+', ' ') + "\r\n");
+    }
+
+    Vector<char> bodyData;
+    bodyData.append("body=", 5);
+    FormDataBuilder::encodeStringAsFormData(bodyData, body.utf8());
+    body = String(bodyData.data(), bodyData.size()).replace('+', "%20");
+
+    String query = url.query();
+    if (!query.isEmpty())
+        query.append('&');
+    query.append(body);
+    url.setQuery(query);
+}
+
+void FormSubmission::Attributes::parseAction(const String& action)
+{
+    // FIXME: Can we parse into a KURL?
+    m_action = deprecatedParseURL(action);
+}
+
+void FormSubmission::Attributes::parseEncodingType(const String& type)
+{
+    if (type.contains("multipart", false) || type.contains("form-data", false)) {
+        m_encodingType = "multipart/form-data";
+        m_isMultiPartForm = true;
+    } else if (type.contains("text", false) || type.contains("plain", false)) {
+        m_encodingType = "text/plain";
+        m_isMultiPartForm = false;
+    } else {
+        m_encodingType = "application/x-www-form-urlencoded";
+        m_isMultiPartForm = false;
+    }
+}
+
+void FormSubmission::Attributes::parseMethodType(const String& type)
+{
+    if (equalIgnoringCase(type, "post"))
+        m_method = FormSubmission::PostMethod;
+    else if (equalIgnoringCase(type, "get"))
+        m_method = FormSubmission::GetMethod;
+}
+
+inline FormSubmission::FormSubmission(Method method, const KURL& action, const String& target, const String& contentType, PassRefPtr<FormState> state, PassRefPtr<FormData> data, const String& boundary, bool lockHistory, PassRefPtr<Event> event)
     : m_method(method)
     , m_action(action)
     , m_target(target)
@@ -55,9 +123,60 @@ FormSubmission::FormSubmission(Method method, const KURL& action, const String&
 {
 }
 
-PassRefPtr<FormSubmission> FormSubmission::create(Method method, const KURL& action, const String& target, const String& contentType, PassRefPtr<FormState> state, PassRefPtr<FormData> data, const String& boundary, bool lockHistory, PassRefPtr<Event> event)
+PassRefPtr<FormSubmission> FormSubmission::create(HTMLFormElement* form, const Attributes& attributes, PassRefPtr<Event> event, bool lockHistory, FormSubmissionTrigger trigger)
 {
-    return adoptRef(new FormSubmission(method, action, target, contentType, state, data, boundary, lockHistory, event));
+    ASSERT(form);
+    Document* document = form->document();
+    KURL actionURL = document->completeURL(attributes.action().isEmpty() ? document->url().string() : attributes.action());
+    bool isMailtoForm = actionURL.protocolIs("mailto");
+    bool isMultiPartForm = false;
+    String encodingType = attributes.encodingType();
+
+    if (attributes.method() == PostMethod) {
+        isMultiPartForm = attributes.isMultiPartForm();
+        if (isMultiPartForm && isMailtoForm) {
+            encodingType = "application/x-www-form-urlencoded";
+            isMultiPartForm = false;
+        }
+    }
+
+    TextEncoding dataEncoding = isMailtoForm ? UTF8Encoding() : FormDataBuilder::encodingFromAcceptCharset(attributes.acceptCharset(), document);
+    RefPtr<DOMFormData> domFormData = DOMFormData::create(dataEncoding.encodingForFormSubmission());
+    Vector<pair<String, String> > formValues;
+
+    for (unsigned i = 0; i < form->associatedElements().size(); ++i) {
+        HTMLFormControlElement* control = form->associatedElements()[i];
+        if (!control->disabled())
+            control->appendFormData(*domFormData, isMultiPartForm);
+        if (control->hasLocalName(inputTag)) {
+            HTMLInputElement* input = static_cast<HTMLInputElement*>(control);
+            if (input->isTextField()) {
+                formValues.append(pair<String, String>(input->name(), input->value()));
+                if (input->isSearchField())
+                    input->addSearchResult();
+            }
+        }
+    }
+
+    RefPtr<FormData> formData;
+    String boundary;
+
+    if (isMultiPartForm) {
+        formData = FormData::createMultiPart(domFormData->items(), domFormData->encoding(), document);
+        boundary = formData->boundary().data();
+    } else {
+        formData = FormData::create(domFormData->items(), domFormData->encoding());
+        if (attributes.method() == PostMethod && isMailtoForm) {
+            // Convert the form data into a string that we put into the URL.
+            appendMailtoPostFormDataToURL(actionURL, *formData, encodingType);
+            formData = FormData::create();
+        }
+    }
+
+    formData->setIdentifier(generateFormDataIdentifier());
+    String targetOrBaseTarget = attributes.target().isEmpty() ? document->baseTarget() : attributes.target();
+    RefPtr<FormState> formState = FormState::create(form, formValues, document->frame(), trigger);
+    return adoptRef(new FormSubmission(attributes.method(), actionURL, targetOrBaseTarget, encodingType, formState.release(), formData.release(), boundary, lockHistory, event));
 }
 
 void FormSubmission::populateFrameLoadRequest(FrameLoadRequest& frameRequest)
index 647c6c6..bee4e71 100644 (file)
 #ifndef FormSubmission_h
 #define FormSubmission_h
 
+#include "FormState.h"
 #include "KURL.h"
 
 namespace WebCore {
 
+class Document;
 class Event;
 class FormData;
-class FormState;
 struct FrameLoadRequest;
+class HTMLFormElement;
+class TextEncoding;
 
 class FormSubmission : public RefCounted<FormSubmission> {
 public:
-    enum Method {
-        GetMethod,
-        PostMethod
+    enum Method { GetMethod, PostMethod };
+
+    class Attributes : public Noncopyable {
+    public:
+        Attributes()
+            : m_method(GetMethod)
+            , m_isMultiPartForm(false)
+            , m_encodingType("application/x-www-form-urlencoded")
+        {
+        }
+
+        Method method() const { return m_method; }
+        void parseMethodType(const String&);
+
+        const String& action() const { return m_action; }
+        void parseAction(const String&);
+
+        const String& target() const { return m_target; }
+        void setTarget(const String& target) { m_target = target; }
+
+        const String& encodingType() const { return m_encodingType; }
+        void parseEncodingType(const String&);
+        bool isMultiPartForm() const { return m_isMultiPartForm; }
+
+        const String& acceptCharset() const { return m_acceptCharset; }
+        void setAcceptCharset(const String& value) { m_acceptCharset = value; }
+
+    private:
+        Method m_method;
+        bool m_isMultiPartForm;
+
+        String m_action;
+        String m_target;
+        String m_encodingType;
+        String m_acceptCharset;
     };
 
-    static PassRefPtr<FormSubmission> create(Method, const KURL& action, const String& target, const String& contentType, PassRefPtr<FormState>, PassRefPtr<FormData>, const String& boundary, bool lockHistory, PassRefPtr<Event>);
+    static PassRefPtr<FormSubmission> create(HTMLFormElement*, const Attributes&, PassRefPtr<Event> event, bool lockHistory, FormSubmissionTrigger);
 
     void populateFrameLoadRequest(FrameLoadRequest&);
 
     Method method() const { return m_method; }
     const KURL& action() const { return m_action; }
-    String target() const { return m_target; }
+    const String& target() const { return m_target; }
     void clearTarget() { m_target = String(); }
-    String contentType() const { return m_contentType; }
+    const String& contentType() const { return m_contentType; }
     FormState* state() const { return m_formState.get(); }
     FormData* data() const { return m_formData.get(); }
-    String boundary() const { return m_boundary; }
+    const String boundary() const { return m_boundary; }
     bool lockHistory() const { return m_lockHistory; }
     Event* event() const { return m_event.get(); }
 
@@ -70,6 +105,7 @@ public:
 private:
     FormSubmission(Method, const KURL& action, const String& target, const String& contentType, PassRefPtr<FormState>, PassRefPtr<FormData>, const String& boundary, bool lockHistory, PassRefPtr<Event>);
 
+    // FIXME: Hold an instance of Attributes instead of individual members.
     Method m_method;
     KURL m_action;
     String m_target;
index fb78b08..da28fc2 100644 (file)
@@ -25,7 +25,6 @@
 #include "config.h"
 #include "FormDataBuilder.h"
 
-#include "CSSHelper.h"
 #include "Document.h"
 #include "Frame.h"
 #include "FrameLoader.h"
 
 namespace WebCore {
 
-FormDataBuilder::FormDataBuilder()
-    : m_isPostMethod(false)
-    , m_isMultiPartForm(false)
-    , m_encodingType("application/x-www-form-urlencoded")
-{
-}
-
-FormDataBuilder::~FormDataBuilder()
-{
-}
-
-void FormDataBuilder::parseAction(const String& action)
-{
-    // FIXME: Can we parse into a KURL?
-    m_action = deprecatedParseURL(action);
-}
-
-void FormDataBuilder::parseEncodingType(const String& type)
-{
-    if (type.contains("multipart", false) || type.contains("form-data", false)) {
-        m_encodingType = "multipart/form-data";
-        m_isMultiPartForm = true;
-    } else if (type.contains("text", false) || type.contains("plain", false)) {
-        m_encodingType = "text/plain";
-        m_isMultiPartForm = false;
-    } else {
-        m_encodingType = "application/x-www-form-urlencoded";
-        m_isMultiPartForm = false;
-    }
-}
-
-void FormDataBuilder::parseMethodType(const String& type)
-{
-    if (equalIgnoringCase(type, "post"))
-        m_isPostMethod = true;
-    else if (equalIgnoringCase(type, "get"))
-        m_isPostMethod = false;
-}
-
-TextEncoding FormDataBuilder::dataEncoding(Document* document) const
-{
-    String acceptCharset = m_acceptCharset;
-    acceptCharset.replace(',', ' ');
-
-    Vector<String> charsets;
-    acceptCharset.split(' ', charsets);
-
-    TextEncoding encoding;
-
-    Vector<String>::const_iterator end = charsets.end();
-    for (Vector<String>::const_iterator it = charsets.begin(); it != end; ++it) {
-        if ((encoding = TextEncoding(*it)).isValid())
-            return encoding;
-    }
-
-    if (Frame* frame = document->frame())
-        return frame->loader()->writer()->encoding();
-
-    return Latin1Encoding();
-}
-
 // Helper functions
 static inline void append(Vector<char>& buffer, char string)
 {
@@ -140,6 +78,28 @@ static void appendQuotedString(Vector<char>& buffer, const CString& string)
     }
 }
 
+TextEncoding FormDataBuilder::encodingFromAcceptCharset(const String& acceptCharset, Document* document)
+{
+    String normalizedAcceptCharset = acceptCharset;
+    normalizedAcceptCharset.replace(',', ' ');
+
+    Vector<String> charsets;
+    normalizedAcceptCharset.split(' ', charsets);
+
+    TextEncoding encoding;
+
+    Vector<String>::const_iterator end = charsets.end();
+    for (Vector<String>::const_iterator it = charsets.begin(); it != end; ++it) {
+        if ((encoding = TextEncoding(*it)).isValid())
+            return encoding;
+    }
+
+    if (Frame* frame = document->frame())
+        return frame->loader()->writer()->encoding();
+
+    return Latin1Encoding();
+}
+
 Vector<char> FormDataBuilder::generateUniqueBoundaryString()
 {
     Vector<char> boundary;
index 559906e..26b90af 100644 (file)
@@ -36,31 +36,7 @@ class TextEncoding;
 
 class FormDataBuilder : public Noncopyable {
 public:
-    FormDataBuilder();
-    ~FormDataBuilder();
-
-    bool isPostMethod() const { return m_isPostMethod; }
-    void setIsPostMethod(bool value) { m_isPostMethod = value; }
-
-    bool isMultiPartForm() const { return m_isMultiPartForm; }
-    void setIsMultiPartForm(bool value) { m_isMultiPartForm = value; }
-
-    const String& action() const { return m_action; }
-
-    const String& target() const { return m_target; }
-    void setTarget(const String& target) { m_target = target; }
-
-    String encodingType() const { return m_encodingType; }
-    void setEncodingType(const String& value) { m_encodingType = value; }
-
-    String acceptCharset() const { return m_acceptCharset; }
-    void setAcceptCharset(const String& value) { m_acceptCharset = value; }
-
-    void parseAction(const String&);
-    void parseEncodingType(const String&);
-    void parseMethodType(const String&);
-
-    TextEncoding dataEncoding(Document*) const;
+    static TextEncoding encodingFromAcceptCharset(const String& acceptCharset, Document* document);
 
     // Helper functions used by HTMLFormElement/WMLGoElement for multi-part form data
     static Vector<char> generateUniqueBoundaryString();
@@ -75,13 +51,7 @@ public:
     static void encodeStringAsFormData(Vector<char>&, const WTF::CString&);
 
 private:
-    bool m_isPostMethod;
-    bool m_isMultiPartForm;
-
-    String m_action;
-    String m_target;
-    String m_encodingType;
-    String m_acceptCharset;
+    FormDataBuilder() {}
 };
 
 }
index db4880c..9b329d7 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "Attribute.h"
 #include "FormData.h"
+#include "FormSubmission.h"
 #include "Frame.h"
 #include "FrameLoader.h"
 #include "HTMLNames.h"
@@ -64,11 +65,11 @@ void WMLGoElement::deregisterPostfieldElement(WMLPostfieldElement* postfield)
 void WMLGoElement::parseMappedAttribute(Attribute* attr)
 {
     if (attr->name() == HTMLNames::methodAttr)
-        m_formDataBuilder.parseMethodType(attr->value());
+        m_formAttributes.parseMethodType(attr->value());
     else if (attr->name() == HTMLNames::enctypeAttr)
-        m_formDataBuilder.parseEncodingType(parseValueSubstitutingVariableReferences(attr->value()));
+        m_formAttributes.parseEncodingType(parseValueSubstitutingVariableReferences(attr->value()));
     else if (attr->name() == HTMLNames::accept_charsetAttr)
-        m_formDataBuilder.setAcceptCharset(parseValueForbiddingVariableReferences(attr->value()));
+        m_formAttributes.setAcceptCharset(parseValueForbiddingVariableReferences(attr->value()));
     else
         WMLTaskElement::parseMappedAttribute(attr);
 }
@@ -126,7 +127,7 @@ void WMLGoElement::executeTask()
 
     String cacheControl = getAttribute(cache_controlAttr);
 
-    if (m_formDataBuilder.isPostMethod())
+    if (m_formAttributes.method() == FormSubmission::PostMethod)
         preparePOSTRequest(request, inSameDeck, cacheControl);
     else
         prepareGETRequest(request, url);
@@ -153,14 +154,14 @@ void WMLGoElement::preparePOSTRequest(ResourceRequest& request, bool inSameDeck,
 
     RefPtr<FormData> data;
 
-    if (m_formDataBuilder.isMultiPartForm()) { // multipart/form-data
-        Vector<char> boundary = m_formDataBuilder.generateUniqueBoundaryString();
+    if (m_formAttributes.isMultiPartForm()) { // multipart/form-data
+        Vector<char> boundary = FormDataBuilder::generateUniqueBoundaryString();
         data = createFormData(boundary.data());
-        request.setHTTPContentType(m_formDataBuilder.encodingType() + "; boundary=" + boundary.data());
+        request.setHTTPContentType(m_formAttributes.encodingType() + "; boundary=" + boundary.data());
     } else {
         // text/plain or application/x-www-form-urlencoded
         data = createFormData(CString());
-        request.setHTTPContentType(m_formDataBuilder.encodingType());
+        request.setHTTPContentType(m_formAttributes.encodingType());
     }
 
     request.setHTTPBody(data.get());
@@ -171,7 +172,7 @@ void WMLGoElement::prepareGETRequest(ResourceRequest& request, const KURL& url)
     request.setHTTPMethod("GET");
 
     // Eventually display error message?
-    if (m_formDataBuilder.isMultiPartForm())
+    if (m_formAttributes.isMultiPartForm())
         return;
 
     RefPtr<FormData> data = createFormData(CString());
@@ -187,7 +188,7 @@ PassRefPtr<FormData> WMLGoElement::createFormData(const CString& boundary)
     CString value;
 
     Vector<char> encodedData;
-    TextEncoding encoding = m_formDataBuilder.dataEncoding(document()).encodingForFormSubmission();
+    TextEncoding encoding = FormDataBuilder::encodingFromAcceptCharset(m_formAttributes.acceptCharset(), document()).encodingForFormSubmission();
 
     Vector<WMLPostfieldElement*>::iterator it = m_postfieldElements.begin();
     Vector<WMLPostfieldElement*>::iterator end = m_postfieldElements.end();
@@ -196,10 +197,10 @@ PassRefPtr<FormData> WMLGoElement::createFormData(const CString& boundary)
     for (; it != end; ++it) {
         (*it)->encodeData(encoding, key, value);
 
-        if (m_formDataBuilder.isMultiPartForm()) {
+        if (m_formAttributes.isMultiPartForm()) {
             Vector<char> header;
-            m_formDataBuilder.beginMultiPartHeader(header, boundary, key);
-            m_formDataBuilder.finishMultiPartHeader(header);
+            FormDataBuilder::beginMultiPartHeader(header, boundary, key);
+            FormDataBuilder::finishMultiPartHeader(header);
             result->appendData(header.data(), header.size());
 
             if (size_t dataSize = value.length())
@@ -207,11 +208,11 @@ PassRefPtr<FormData> WMLGoElement::createFormData(const CString& boundary)
 
             result->appendData("\r\n", 2);
         } else
-            m_formDataBuilder.addKeyValuePairAsFormData(encodedData, key, value);
+            FormDataBuilder::addKeyValuePairAsFormData(encodedData, key, value);
     }
 
-    if (m_formDataBuilder.isMultiPartForm())
-        m_formDataBuilder.addBoundaryToMultiPartHeader(encodedData, boundary, true);
+    if (m_formAttributes.isMultiPartForm())
+        FormDataBuilder::addBoundaryToMultiPartHeader(encodedData, boundary, true);
 
     result->appendData(encodedData.data(), encodedData.size());
     return result;
index f602a39..d7f8991 100644 (file)
@@ -22,7 +22,7 @@
 #define WMLGoElement_h
 
 #if ENABLE(WML)
-#include "FormDataBuilder.h"
+#include "FormSubmission.h"
 #include "WMLTaskElement.h"
 
 namespace WebCore {
@@ -48,7 +48,7 @@ private:
     PassRefPtr<FormData> createFormData(const CString& boundary);
 
     Vector<WMLPostfieldElement*> m_postfieldElements;
-    FormDataBuilder m_formDataBuilder;
+    FormSubmission::Attributes m_formAttributes;
 };
 
 }