Commit fd3fc61f authored by jianli@chromium.org's avatar jianli@chromium.org

Implementing DOMFormData class.

https://bugs.webkit.org/show_bug.cgi?id=35707

Reviewed by Dmitry Titov.

This patch only addresses the implementation of DOMFormData class and
moves the FormData construction logic from HTMLFormElement::createFormData
to FormData::create() so that it can be used by both HTMLFormElement
and XMLHttpRequest.

The DOMFormData IDL interface will be exposed in another patch and the
test will be added then.

* Android.mk:
* GNUmakefile.am:
* WebCore.gypi:
* WebCore.pro:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* html/DOMFormData.cpp: Added.
* html/DOMFormData.h: Added.
* html/FormDataList.h:
(WebCore::FormDataList::encoding):
* html/HTMLFormElement.cpp:
(WebCore::HTMLFormElement::createFormData):
(WebCore::HTMLFormElement::submit):
* html/HTMLFormElement.h:
* platform/network/FormData.cpp:
(WebCore::FormData::create):
(WebCore::FormData::createMultiPart):
(WebCore::FormData::appendDOMFormData):
* platform/network/FormData.h:
(WebCore::FormData::boundary):
* xml/XMLHttpRequest.cpp:
(WebCore::XMLHttpRequest::send):
* xml/XMLHttpRequest.h:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@55821 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 1478d70e
......@@ -239,6 +239,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
\
html/Blob.cpp \
html/CollectionCache.cpp \
html/DOMFormData.cpp \
html/File.cpp \
html/FileList.cpp \
html/FormDataList.cpp \
......
2010-03-10 Jian Li <jianli@chromium.org>
Reviewed by Dmitry Titov.
Implementing DOMFormData class.
https://bugs.webkit.org/show_bug.cgi?id=35707
This patch only addresses the implementation of DOMFormData class and
moves the FormData construction logic from HTMLFormElement::createFormData
to FormData::create() so that it can be used by both HTMLFormElement
and XMLHttpRequest.
The DOMFormData IDL interface will be exposed in another patch and the
test will be added then.
* Android.mk:
* GNUmakefile.am:
* WebCore.gypi:
* WebCore.pro:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* html/DOMFormData.cpp: Added.
* html/DOMFormData.h: Added.
* html/FormDataList.h:
(WebCore::FormDataList::encoding):
* html/HTMLFormElement.cpp:
(WebCore::HTMLFormElement::createFormData):
(WebCore::HTMLFormElement::submit):
* html/HTMLFormElement.h:
* platform/network/FormData.cpp:
(WebCore::FormData::create):
(WebCore::FormData::createMultiPart):
(WebCore::FormData::appendDOMFormData):
* platform/network/FormData.h:
(WebCore::FormData::boundary):
* xml/XMLHttpRequest.cpp:
(WebCore::XMLHttpRequest::send):
* xml/XMLHttpRequest.h:
2010-03-10 Chris Fleizach <cfleizach@apple.com>
Reviewed by Beth Dakin.
......
......@@ -1008,6 +1008,8 @@ webcore_sources += \
WebCore/html/DateComponents.h \
WebCore/html/DOMDataGridDataSource.cpp \
WebCore/html/DOMDataGridDataSource.h \
WebCore/html/DOMFormData.cpp \
WebCore/html/DOMFormData.h \
WebCore/html/File.cpp \
WebCore/html/File.h \
WebCore/html/FileList.cpp \
......
......@@ -1412,6 +1412,8 @@
'html/DataGridColumn.h',
'html/DOMDataGridDataSource.cpp',
'html/DOMDataGridDataSource.h',
'html/DOMFormData.cpp',
'html/DOMFormData.h',
'html/DataGridColumnList.cpp',
'html/DataGridColumnList.h',
'html/DateComponents.cpp',
......
......@@ -598,6 +598,7 @@ SOURCES += \
html/DataGridColumnList.cpp \
html/DateComponents.cpp \
html/DOMDataGridDataSource.cpp \
html/DOMFormData.cpp \
html/File.cpp \
html/FileList.cpp \
html/FormDataList.cpp \
......@@ -1295,6 +1296,7 @@ HEADERS += \
html/DataGridColumnList.h \
html/DateComponents.h \
html/DOMDataGridDataSource.h \
html/DOMFormData.h \
html/File.h \
html/FileList.h \
html/FormDataList.h \
......
......@@ -29972,6 +29972,14 @@
RelativePath="..\html\DOMDataGridDataSource.h"
>
</File>
<File
RelativePath="..\html\DOMFormData.cpp"
>
</File>
<File
RelativePath="..\html\DOMFormData.h"
>
</File>
<File
RelativePath="..\html\File.cpp"
>
......
......@@ -625,6 +625,8 @@
2ECF7ADD10162B3800427DE7 /* JSErrorEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ECF7ADB10162B3800427DE7 /* JSErrorEvent.h */; };
2ECF7AE110162B5800427DE7 /* ErrorEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ECF7ADE10162B5800427DE7 /* ErrorEvent.cpp */; };
2ECF7AE210162B5800427DE7 /* ErrorEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ECF7ADF10162B5800427DE7 /* ErrorEvent.h */; };
2ED609BC1145B07100C8684E /* DOMFormData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ED609BA1145B07100C8684E /* DOMFormData.cpp */; };
2ED609BD1145B07100C8684E /* DOMFormData.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ED609BB1145B07100C8684E /* DOMFormData.h */; };
31288E720E3005D6003619AE /* WebKitCSSKeyframeRule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 31288E6E0E3005D6003619AE /* WebKitCSSKeyframeRule.cpp */; };
31288E730E3005D6003619AE /* WebKitCSSKeyframeRule.h in Headers */ = {isa = PBXBuildFile; fileRef = 31288E6F0E3005D6003619AE /* WebKitCSSKeyframeRule.h */; };
31288E740E3005D6003619AE /* WebKitCSSKeyframesRule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 31288E700E3005D6003619AE /* WebKitCSSKeyframesRule.cpp */; };
......@@ -5990,6 +5992,8 @@
2ECF7ADE10162B5800427DE7 /* ErrorEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErrorEvent.cpp; sourceTree = "<group>"; };
2ECF7ADF10162B5800427DE7 /* ErrorEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ErrorEvent.h; sourceTree = "<group>"; };
2ECF7AE010162B5800427DE7 /* ErrorEvent.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ErrorEvent.idl; sourceTree = "<group>"; };
2ED609BA1145B07100C8684E /* DOMFormData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMFormData.cpp; sourceTree = "<group>"; };
2ED609BB1145B07100C8684E /* DOMFormData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMFormData.h; sourceTree = "<group>"; };
31288E6E0E3005D6003619AE /* WebKitCSSKeyframeRule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebKitCSSKeyframeRule.cpp; sourceTree = "<group>"; };
31288E6F0E3005D6003619AE /* WebKitCSSKeyframeRule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebKitCSSKeyframeRule.h; sourceTree = "<group>"; };
31288E700E3005D6003619AE /* WebKitCSSKeyframesRule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebKitCSSKeyframesRule.cpp; sourceTree = "<group>"; };
......@@ -12874,6 +12878,8 @@
F5D3A57B106B83B300545297 /* DateComponents.h */,
BC7DAAEC0FF9615D00CE0138 /* DOMDataGridDataSource.cpp */,
BC7DAAED0FF9615D00CE0138 /* DOMDataGridDataSource.h */,
2ED609BA1145B07100C8684E /* DOMFormData.cpp */,
2ED609BB1145B07100C8684E /* DOMFormData.h */,
BCDBB8CC0E08958400C60FF6 /* File.cpp */,
BCDBB8CB0E08958400C60FF6 /* File.h */,
BC1881D90E08C4ED00048C13 /* File.idl */,
......@@ -18668,6 +18674,7 @@
BC53DA2E1143121E000D817E /* DOMWrapperWorld.h in Headers */,
BC53DA601143141A000D817E /* DOMObjectHashTableMap.h in Headers */,
BC53DAC211432EEE000D817E /* JSDebugWrapperSet.h in Headers */,
2ED609BD1145B07100C8684E /* DOMFormData.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -20867,6 +20874,7 @@
BC53DA62114314BD000D817E /* DOMObjectHashTableMap.cpp in Sources */,
BC53DAC511432FD9000D817E /* JSDebugWrapperSet.cpp in Sources */,
BC53DAC711433064000D817E /* JSDOMWrapper.cpp in Sources */,
2ED609BC1145B07100C8684E /* DOMFormData.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/*
* Copyright (C) 2010 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "DOMFormData.h"
#include "Blob.h"
#include "PlatformString.h"
#include "TextEncoding.h"
namespace WebCore {
DOMFormData::DOMFormData(const TextEncoding& encoding)
: FormDataList(encoding)
{
}
void DOMFormData::append(const String& name, const String& value)
{
if (!name.isEmpty())
appendData(name, value);
}
void DOMFormData::append(const String& name, Blob* blob)
{
// FIXME: Need to support sliced file when Blob.slice support is landed.
if (!name.isEmpty() && !blob->path().isEmpty()) {
RefPtr<File> file = static_cast<File*>(blob);
appendFile(name, file.release());
}
}
} // namespace WebCore
/*
* Copyright (C) 2010 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DOMFormData_h
#define DOMFormData_h
#include "FormDataList.h"
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
namespace WebCore {
class Blob;
class String;
class TextEncoding;
class DOMFormData : public FormDataList, public RefCounted<DOMFormData> {
public:
static PassRefPtr<DOMFormData> create() { return adoptRef(new DOMFormData(UTF8Encoding())); }
static PassRefPtr<DOMFormData> create(const TextEncoding& encoding) { return adoptRef(new DOMFormData(encoding)); }
void append(const String& name, const String& value);
void append(const String& name, Blob*);
private:
DOMFormData(const TextEncoding&);
};
} // namespace WebCore
#endif // DOMFormData_h
......@@ -55,6 +55,7 @@ public:
};
const Vector<Item>& list() const { return m_list; }
const TextEncoding& encoding() const { return m_encoding; }
private:
void appendString(const CString&);
......
......@@ -26,8 +26,7 @@
#include "HTMLFormElement.h"
#include "CSSHelper.h"
#include "Chrome.h"
#include "ChromeClient.h"
#include "DOMFormData.h"
#include "Document.h"
#include "Event.h"
#include "EventNames.h"
......@@ -46,7 +45,6 @@
#include "ScriptEventListener.h"
#include "MIMETypeRegistry.h"
#include "MappedAttribute.h"
#include "Page.h"
#include "RenderTextControl.h"
#include "ValidityState.h"
#include <limits>
......@@ -201,83 +199,16 @@ TextEncoding HTMLFormElement::dataEncoding() const
return m_formDataBuilder.dataEncoding(document());
}
PassRefPtr<FormData> HTMLFormElement::createFormData(const CString& boundary)
PassRefPtr<FormData> HTMLFormElement::createFormData()
{
Vector<char> encodedData;
TextEncoding encoding = dataEncoding().encodingForFormSubmission();
RefPtr<FormData> result = FormData::create();
RefPtr<DOMFormData> domFormData = DOMFormData::create(dataEncoding().encodingForFormSubmission());
for (unsigned i = 0; i < formElements.size(); ++i) {
HTMLFormControlElement* control = formElements[i];
FormDataList list(encoding);
if (!control->disabled() && control->appendFormData(list, m_formDataBuilder.isMultiPartForm())) {
size_t formDataListSize = list.list().size();
ASSERT(formDataListSize % 2 == 0);
for (size_t j = 0; j < formDataListSize; j += 2) {
const FormDataList::Item& key = list.list()[j];
const FormDataList::Item& value = list.list()[j + 1];
if (!m_formDataBuilder.isMultiPartForm()) {
// Omit the name "isindex" if it's the first form data element.
// FIXME: Why is this a good rule? Is this obsolete now?
if (encodedData.isEmpty() && key.data() == "isindex")
FormDataBuilder::encodeStringAsFormData(encodedData, value.data());
else
m_formDataBuilder.addKeyValuePairAsFormData(encodedData, key.data(), value.data());
} else {
Vector<char> header;
m_formDataBuilder.beginMultiPartHeader(header, boundary, key.data());
bool shouldGenerateFile = false;
// if the current type is FILE, then we also need to include the filename
if (value.file()) {
const String& path = value.file()->path();
String fileName = value.file()->fileName();
// Let the application specify a filename if it's going to generate a replacement file for the upload.
if (!path.isEmpty()) {
if (Page* page = document()->page()) {
String generatedFileName;
shouldGenerateFile = page->chrome()->client()->shouldReplaceWithGeneratedFileForUpload(path, generatedFileName);
if (shouldGenerateFile)
fileName = generatedFileName;
}
}
// We have to include the filename=".." part in the header, even if the filename is empty
m_formDataBuilder.addFilenameToMultiPartHeader(header, encoding, fileName);
if (!fileName.isEmpty()) {
// FIXME: The MIMETypeRegistry function's name makes it sound like it takes a path,
// not just a basename. But filename is not the path. But note that it's not safe to
// just use path instead since in the generated-file case it will not reflect the
// MIME type of the generated file.
String mimeType = MIMETypeRegistry::getMIMETypeForPath(fileName);
if (!mimeType.isEmpty())
m_formDataBuilder.addContentTypeToMultiPartHeader(header, mimeType.latin1());
}
}
m_formDataBuilder.finishMultiPartHeader(header);
// Append body
result->appendData(header.data(), header.size());
if (size_t dataSize = value.data().length())
result->appendData(value.data().data(), dataSize);
else if (value.file() && !value.file()->path().isEmpty())
result->appendFile(value.file()->path(), shouldGenerateFile);
result->appendData("\r\n", 2);
}
}
}
if (!control->disabled())
control->appendFormData(*domFormData, m_formDataBuilder.isMultiPartForm());
}
if (m_formDataBuilder.isMultiPartForm())
m_formDataBuilder.addBoundaryToMultiPartHeader(encodedData, boundary, true);
result->appendData(encodedData.data(), encodedData.size());
RefPtr<FormData> result = (m_formDataBuilder.isMultiPartForm()) ? FormData::createMultiPart(*domFormData, document()) : FormData::create(*domFormData);
result->setIdentifier(generateFormDataIdentifier());
return result;
......@@ -389,8 +320,8 @@ void HTMLFormElement::submit(Event* event, bool activateSubmitButton, bool lockH
ASSERT(!m_formDataBuilder.isMultiPartForm());
}
RefPtr<FormData> data = createFormData();
if (!m_formDataBuilder.isMultiPartForm()) {
RefPtr<FormData> data = createFormData(CString());
if (isMailtoForm()) {
// Convert the form data into a string that we put into the URL.
......@@ -400,13 +331,11 @@ void HTMLFormElement::submit(Event* event, bool activateSubmitButton, bool lockH
}
frame->loader()->submitForm("POST", m_url, data.release(), m_target, m_formDataBuilder.encodingType(), String(), lockHistory, event, formState.release());
} else {
Vector<char> boundary = m_formDataBuilder.generateUniqueBoundaryString();
frame->loader()->submitForm("POST", m_url, createFormData(boundary.data()), m_target, m_formDataBuilder.encodingType(), boundary.data(), lockHistory, event, formState.release());
}
} else
frame->loader()->submitForm("POST", m_url, data.get(), m_target, m_formDataBuilder.encodingType(), data->boundary().data(), lockHistory, event, formState.release());
} else {
m_formDataBuilder.setIsMultiPartForm(false);
frame->loader()->submitForm("GET", m_url, createFormData(CString()), m_target, String(), String(), lockHistory, event, formState.release());
frame->loader()->submitForm("GET", m_url, createFormData(), m_target, String(), String(), lockHistory, event, formState.release());
}
if (needButtonActivation && firstSuccessfulSubmitButton)
......
......@@ -135,7 +135,7 @@ private:
bool isMailtoForm() const;
TextEncoding dataEncoding() const;
PassRefPtr<FormData> createFormData(const CString& boundary);
PassRefPtr<FormData> createFormData();
unsigned formElementIndex(HTMLFormControlElement*);
friend class HTMLFormCollection;
......
......@@ -23,8 +23,14 @@
#include "Blob.h"
#include "CString.h"
#include "Chrome.h"
#include "ChromeClient.h"
#include "DOMFormData.h"
#include "Document.h"
#include "FileSystem.h"
#include "FormDataBuilder.h"
#include "MIMETypeRegistry.h"
#include "Page.h"
#include "TextEncoding.h"
namespace WebCore {
......@@ -89,6 +95,20 @@ PassRefPtr<FormData> FormData::create(const Vector<char>& vector)
return result.release();
}
PassRefPtr<FormData> FormData::create(const DOMFormData& domFormData)
{
RefPtr<FormData> result = create();
result->appendDOMFormData(domFormData, false, 0);
return result.release();
}
PassRefPtr<FormData> FormData::createMultiPart(const DOMFormData& domFormData, Document* document)
{
RefPtr<FormData> result = create();
result->appendDOMFormData(domFormData, true, document);
return result.release();
}
PassRefPtr<FormData> FormData::copy() const
{
return adoptRef(new FormData(*this));
......@@ -146,6 +166,81 @@ void FormData::appendFileRange(const String& filename, long long start, long lon
}
#endif
void FormData::appendDOMFormData(const DOMFormData& domFormData, bool isMultiPartForm, Document* document)
{
FormDataBuilder formDataBuilder;
if (isMultiPartForm)
m_boundary = formDataBuilder.generateUniqueBoundaryString();
Vector<char> encodedData;
TextEncoding encoding = domFormData.encoding();
const Vector<FormDataList::Item>& list = domFormData.list();
size_t formDataListSize = list.size();
ASSERT(!(formDataListSize % 2));
for (size_t i = 0; i < formDataListSize; i += 2) {
const FormDataList::Item& key = list[i];
const FormDataList::Item& value = list[i + 1];
if (isMultiPartForm) {
Vector<char> header;
formDataBuilder.beginMultiPartHeader(header, m_boundary.data(), key.data());
bool shouldGenerateFile = false;
// If the current type is FILE, then we also need to include the filename
if (value.file()) {
const String& path = value.file()->path();
String fileName = value.file()->fileName();
// Let the application specify a filename if it's going to generate a replacement file for the upload.
if (!path.isEmpty()) {
if (Page* page = document->page()) {
String generatedFileName;
shouldGenerateFile = page->chrome()->client()->shouldReplaceWithGeneratedFileForUpload(path, generatedFileName);
if (shouldGenerateFile)
fileName = generatedFileName;
}
}
// We have to include the filename=".." part in the header, even if the filename is empty
formDataBuilder.addFilenameToMultiPartHeader(header, encoding, fileName);
if (!fileName.isEmpty()) {
// FIXME: The MIMETypeRegistry function's name makes it sound like it takes a path,
// not just a basename. But filename is not the path. But note that it's not safe to
// just use path instead since in the generated-file case it will not reflect the
// MIME type of the generated file.
String mimeType = MIMETypeRegistry::getMIMETypeForPath(fileName);
if (!mimeType.isEmpty())
formDataBuilder.addContentTypeToMultiPartHeader(header, mimeType.latin1());
}
}
formDataBuilder.finishMultiPartHeader(header);
// Append body
appendData(header.data(), header.size());
if (size_t dataSize = value.data().length())
appendData(value.data().data(), dataSize);
else if (value.file() && !value.file()->path().isEmpty())
appendFile(value.file()->path(), shouldGenerateFile);
appendData("\r\n", 2);
} else {
// Omit the name "isindex" if it's the first form data element.
// FIXME: Why is this a good rule? Is this obsolete now?
if (encodedData.isEmpty() && key.data() == "isindex")
FormDataBuilder::encodeStringAsFormData(encodedData, value.data());
else
formDataBuilder.addKeyValuePairAsFormData(encodedData, key.data(), value.data());
}
}
if (isMultiPartForm)
formDataBuilder.addBoundaryToMultiPartHeader(encodedData, m_boundary.data(), true);
appendData(encodedData.data(), encodedData.size());
}
void FormData::flatten(Vector<char>& data) const
{
// Concatenate all the byte arrays, but omit any files.
......
......@@ -27,6 +27,8 @@
namespace WebCore {
class ChromeClient;
class DOMFormData;
class Document;
class FormDataElement {
public:
......@@ -80,6 +82,8 @@ public:
static PassRefPtr<FormData> create(const void*, size_t);
static PassRefPtr<FormData> create(const CString&);
static PassRefPtr<FormData> create(const Vector<char>&);
static PassRefPtr<FormData> create(const DOMFormData&);
static PassRefPtr<FormData> createMultiPart(const DOMFormData&, Document*);
PassRefPtr<FormData> copy() const;
PassRefPtr<FormData> deepCopy() const;
~FormData();
......@@ -95,6 +99,7 @@ public:
bool isEmpty() const { return m_elements.isEmpty(); }
const Vector<FormDataElement>& elements() const { return m_elements; }
const Vector<char>& boundary() const { return m_boundary; }
void generateFiles(ChromeClient*);
void removeGeneratedFilesIfNeeded();
......@@ -111,10 +116,13 @@ private:
FormData();
FormData(const FormData&);
void appendDOMFormData(const DOMFormData& domFormData, bool isMultiPartForm, Document* document);
Vector<FormDataElement> m_elements;
int64_t m_identifier;
bool m_hasGeneratedFiles;
bool m_alwaysStream;
Vector<char> m_boundary;
};
inline bool operator==(const FormData& a, const FormData& b)
......
......@@ -26,6 +26,7 @@
#include "Cache.h"
#include "CString.h"
#include "CrossOriginAccessControl.h"
#include "DOMFormData.h"
#include "DOMImplementation.h"
#include "Document.h"
#include "Event.h"
......@@ -459,6 +460,25 @@ void XMLHttpRequest::send(Blob* body, ExceptionCode& ec)
createRequest(ec);
}
void XMLHttpRequest::send(DOMFormData* body, ExceptionCode& ec)
{
if (!initSend(ec))
return;
if (m_method != "GET" && m_method != "HEAD" && m_url.protocolInHTTPFamily()) {
m_requestEntityBody = FormData::createMultiPart(*body, document());
String contentType = getRequestHeader("Content-Type");
if (contentType.isEmpty()) {
contentType = "multipart/form-data; boundary=";
contentType += m_requestEntityBody->boundary().data();
setRequestHeaderInternal("Content-Type", contentType);
}
}
createRequest(ec);
}
void XMLHttpRequest::createRequest(ExceptionCode& ec)
{
// The presence of upload event listeners forces us to use preflighting because POSTing to an URL that does not
......
......@@ -35,6 +35,7 @@ namespace WebCore {
class Blob;
class Document;
class DOMFormData;
class ResourceRequest;
class TextResourceDecoder;
class ThreadableLoader;
......@@ -74,6 +75,7 @@ public:
void send(Document*, ExceptionCode&);
void send(const String&, ExceptionCode&);
void send(Blob*, ExceptionCode&);
void send(DOMFormData*, ExceptionCode&);
void abort();
void setRequestHeader(const AtomicString& name, const String& value, ExceptionCode&);
void overrideMimeType(const String& override);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment