WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-39083-20100603163504.patch (text/plain), 74.99 KB, created by
Kinuko Yasuda
on 2010-06-03 16:35:05 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Kinuko Yasuda
Created:
2010-06-03 16:35:05 PDT
Size:
74.99 KB
patch
obsolete
>diff --git a/WebCore/CMakeLists.txt b/WebCore/CMakeLists.txt >index 1adcadec10eb293a773ce99a04f1cb5ea1691012..e477e27084cbd5ffdbbb9e668e42974f2aabd61a 100644 >--- a/WebCore/CMakeLists.txt >+++ b/WebCore/CMakeLists.txt >@@ -1122,6 +1122,7 @@ SET(WebCore_SOURCES > page/animation/KeyframeAnimation.cpp > > platform/Arena.cpp >+ platform/BlobItem.cpp > platform/ContentType.cpp > platform/ContextMenu.cpp > platform/CrossThreadCopier.cpp >diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog >index ec40737724d7058628d22afc6c99bf06cf29db9c..f5ea979e76fa25ae8f2242053db63e5817592dfa 100644 >--- a/WebCore/ChangeLog >+++ b/WebCore/ChangeLog >@@ -1,3 +1,91 @@ >+2010-06-03 Kinuko Yasuda <kinuko@chromium.org> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Refactor FormData and Blob for better support of Blobs synthesized by BlobBuilder. >+ https://bugs.webkit.org/show_bug.cgi?id=39083 >+ >+ - Introduces a new class BlobItem as a basic component of Blob and >+ FormData and makes Blob as a collection of BlobItems. >+ - File would become a special type of Blob that contains only one >+ FileBlobItem. >+ - Makes FormDataElement a wrapper of BlobItem (as a transient >+ solution). >+ - Fix the dependency violation in FormData so that the files under >+ platform/ do not include any html/ files. >+ >+ The patch doesn't support the latest File API changes (e.g. type, >+ url and slice's type parameters) and should not change any of its >+ existing behaviors. >+ >+ The existing tests should be able to be used for regression. >+ >+ * CMakeLists.txt: >+ * GNUmakefile.am: >+ * WebCore.gypi: >+ * WebCore.pro: >+ * WebCore.vcproj/WebCore.vcproj: >+ * WebCore.xcodeproj/project.pbxproj: >+ * html/Blob.cpp: >+ (WebCore::Blob::Blob): >+ (WebCore::Blob::size): >+ (WebCore::Blob::path): >+ (WebCore::Blob::append): >+ (WebCore::Blob::slice): >+ * html/Blob.h: >+ (WebCore::Blob::create): >+ (WebCore::Blob::type): >+ (WebCore::Blob::items): >+ (WebCore::Blob::Blob): >+ * html/File.cpp: >+ (WebCore::File::File): >+ (WebCore::File::name): >+ * html/File.h: >+ (WebCore::File::fileName): >+ * html/FileReader.cpp: >+ (WebCore::FileReader::readAsBinaryString): >+ (WebCore::FileReader::readAsText): >+ * html/FileStream.cpp: >+ (WebCore::FileStream::openForRead): >+ * html/FormDataList.cpp: >+ (WebCore::FormDataList::appendString): >+ (WebCore::FormDataList::appendBlob): >+ * html/FormDataList.h: >+ (WebCore::FormDataList::items): >+ * html/HTMLFormElement.cpp: >+ (WebCore::HTMLFormElement::createFormData): >+ * html/HTMLProgressElement.cpp: >+ * platform/BlobItem.cpp: Added. >+ * platform/BlobItem.h: Added. >+ * platform/network/FormData.cpp: >+ (WebCore::FormDataElement::FormDataElement): >+ (WebCore::FormData::create): >+ (WebCore::FormData::createMultiPart): >+ (WebCore::FormData::deepCopy): >+ (WebCore::FormData::appendData): >+ (WebCore::FormData::appendString): >+ (WebCore::FormData::appendFile): >+ (WebCore::FormData::appendFileRange): >+ (WebCore::FormData::appendItems): >+ (WebCore::FormData::appendKeyValuePairItems): >+ * platform/network/FormData.h: >+ (WebCore::FormDataElement::FormDataElement): >+ (WebCore::FormDataElement::item): >+ (WebCore::FormDataElement::BlobItemWrapper::BlobItemWrapper): >+ (WebCore::FormDataElement::BlobItemWrapper::size): >+ (WebCore::FormDataElement::BlobItemWrapper::data): >+ (WebCore::FormDataElement::BlobItemWrapper::releaseBuffer): >+ (WebCore::operator==): >+ (WebCore::operator!=): >+ * platform/network/mac/FormDataStreamMac.mm: >+ (WebCore::closeCurrentStream): >+ (WebCore::advanceCurrentStream): >+ (WebCore::formCreate): >+ (WebCore::formRead): >+ (WebCore::setHTTPBody): >+ * xml/XMLHttpRequest.cpp: >+ (WebCore::XMLHttpRequest::send): >+ > 2010-06-03 Pavel Feldman <pfeldman@chromium.org> > > Not reviewed. Rolling out aggressive cache part of the r60391 >diff --git a/WebCore/GNUmakefile.am b/WebCore/GNUmakefile.am >index 4dce62fdbc646d8692b6f547052ce78a1dd9636f..3fbf1d92586026585235551116b5b41468ac3eca 100644 >--- a/WebCore/GNUmakefile.am >+++ b/WebCore/GNUmakefile.am >@@ -1559,6 +1559,8 @@ webcore_sources += \ > WebCore/platform/Arena.cpp \ > WebCore/platform/Arena.h \ > WebCore/platform/AutodrainedPool.h \ >+ WebCore/platform/BlobItem.cpp \ >+ WebCore/platform/BlobItem.h \ > WebCore/platform/ContentType.cpp \ > WebCore/platform/ContentType.h \ > WebCore/platform/ContextMenu.cpp \ >diff --git a/WebCore/WebCore.gypi b/WebCore/WebCore.gypi >index 293f78580cb1627dece78adf6e8e237eb6109c35..d2b7de825c20dc096696242afba3af161abee6a2 100644 >--- a/WebCore/WebCore.gypi >+++ b/WebCore/WebCore.gypi >@@ -2880,6 +2880,8 @@ > 'platform/Arena.cpp', > 'platform/Arena.h', > 'platform/AutodrainedPool.h', >+ 'platform/BlobItem.cpp', >+ 'platform/BlobItem.h', > 'platform/ContentType.cpp', > 'platform/ContentType.h', > 'platform/ContextMenu.cpp', >diff --git a/WebCore/WebCore.pro b/WebCore/WebCore.pro >index 11a3dcbc3a744d4a47559618b747131d2a425f55..7d280e15dc66fad2560861ccc6b59f04ebfea176 100644 >--- a/WebCore/WebCore.pro >+++ b/WebCore/WebCore.pro >@@ -815,6 +815,7 @@ SOURCES += \ > platform/animation/Animation.cpp \ > platform/animation/AnimationList.cpp \ > platform/Arena.cpp \ >+ platform/BlobItem.cpp \ > platform/text/Base64.cpp \ > platform/text/BidiContext.cpp \ > platform/ContentType.cpp \ >@@ -1564,6 +1565,7 @@ HEADERS += \ > platform/animation/Animation.h \ > platform/animation/AnimationList.h \ > platform/Arena.h \ >+ platform/BlobItem.h \ > platform/ContentType.h \ > platform/ContextMenu.h \ > platform/CrossThreadCopier.h \ >diff --git a/WebCore/WebCore.vcproj/WebCore.vcproj b/WebCore/WebCore.vcproj/WebCore.vcproj >index ecdad46c5ed2c0a9b65af96f8971f4e8c219928a..3f08ff17654aa3bf9788f98df109205ea4fdb60d 100644 >--- a/WebCore/WebCore.vcproj/WebCore.vcproj >+++ b/WebCore/WebCore.vcproj/WebCore.vcproj >@@ -22369,6 +22369,14 @@ > > > </File> > <File >+ RelativePath="..\platform\BlobItem.cpp" >+ > >+ </File> >+ <File >+ RelativePath="..\platform\BlobItem.h" >+ > >+ </File> >+ <File > RelativePath="..\platform\ContentType.cpp" > > > </File> >diff --git a/WebCore/WebCore.xcodeproj/project.pbxproj b/WebCore/WebCore.xcodeproj/project.pbxproj >index 4dd6d853712bf25f6f607b0832422cded4b0b4de..e99d3f89cf215b828a061289fe5e107bef896c44 100644 >--- a/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -2279,6 +2279,8 @@ > 895253DD116C4EF500CABF00 /* FileStreamProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 895253DB116C4EF500CABF00 /* FileStreamProxy.h */; }; > 895253DF116C4F0600CABF00 /* FileThreadTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 895253DE116C4F0600CABF00 /* FileThreadTask.h */; }; > 8FAC774D119872CB0015AE94 /* JSMainThreadExecState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8F934D841189F1EE00508D5D /* JSMainThreadExecState.cpp */; }; >+ 8988E10E11A3508B00DB732E /* BlobItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8988E10C11A3508B00DB732E /* BlobItem.cpp */; }; >+ 8988E10F11A3508B00DB732E /* BlobItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 8988E10D11A3508B00DB732E /* BlobItem.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 9302B0BD0D79F82900C7EE83 /* PageGroup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9302B0BC0D79F82900C7EE83 /* PageGroup.cpp */; }; > 9302B0BF0D79F82C00C7EE83 /* PageGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 9302B0BE0D79F82C00C7EE83 /* PageGroup.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 9305B24D098F1B6B00C28855 /* Timer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9305B24C098F1B6B00C28855 /* Timer.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -7885,6 +7887,8 @@ > 895253DE116C4F0600CABF00 /* FileThreadTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileThreadTask.h; sourceTree = "<group>"; }; > 8F934D831189F1EE00508D5D /* JSMainThreadExecState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSMainThreadExecState.h; sourceTree = "<group>"; }; > 8F934D841189F1EE00508D5D /* JSMainThreadExecState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMainThreadExecState.cpp; sourceTree = "<group>"; }; >+ 8988E10C11A3508B00DB732E /* BlobItem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BlobItem.cpp; sourceTree = "<group>"; }; >+ 8988E10D11A3508B00DB732E /* BlobItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlobItem.h; sourceTree = "<group>"; }; > 9302B0BC0D79F82900C7EE83 /* PageGroup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PageGroup.cpp; sourceTree = "<group>"; }; > 9302B0BE0D79F82C00C7EE83 /* PageGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageGroup.h; sourceTree = "<group>"; }; > 9305B24C098F1B6B00C28855 /* Timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Timer.h; sourceTree = "<group>"; }; >@@ -15856,6 +15860,8 @@ > BCFB2F74097A2E1A00BA703D /* Arena.cpp */, > BCFB2F75097A2E1A00BA703D /* Arena.h */, > 51E1ECB10C91C55600DC255B /* AutodrainedPool.h */, >+ 8988E10C11A3508B00DB732E /* BlobItem.cpp */, >+ 8988E10D11A3508B00DB732E /* BlobItem.h */, > BCC8CFCA0986CD2400140BF2 /* ColorData.gperf */, > 41D015C90F4B5C71004A662F /* ContentType.cpp */, > 41D015C80F4B5C71004A662F /* ContentType.h */, >@@ -16893,6 +16899,7 @@ > BC5EB9200E82040800B25965 /* BindingURI.h in Headers */, > A89943280B42338800D7C802 /* BitmapImage.h in Headers */, > 2EAFAF0F10E2AF2D007ED3D6 /* Blob.h in Headers */, >+ 8988E10F11A3508B00DB732E /* BlobItem.h in Headers */, > 93F199BE08245E59001E9ABC /* BlockExceptions.h in Headers */, > BC5EB5E10E81BE8700B25965 /* BorderData.h in Headers */, > BC5EB5DB0E81B7EA00B25965 /* BorderValue.h in Headers */, >@@ -19724,6 +19731,7 @@ > BC5EB91F0E82040800B25965 /* BindingURI.cpp in Sources */, > A89943290B42338800D7C802 /* BitmapImage.cpp in Sources */, > 2EAFAF0E10E2AF2D007ED3D6 /* Blob.cpp in Sources */, >+ 8988E10E11A3508B00DB732E /* BlobItem.cpp in Sources */, > 93F19AE108245E59001E9ABC /* BlockExceptions.mm in Sources */, > BCEA4854097D93020094C9E4 /* break_lines.cpp in Sources */, > 93309DDA099E64920056E581 /* BreakBlockquoteCommand.cpp in Sources */, >diff --git a/WebCore/html/Blob.cpp b/WebCore/html/Blob.cpp >index 83bbdc0c526484542688192621684b6282024bf4..0546f1c3c0882da2208a9e6a0a762db4359bee4a 100644 >--- a/WebCore/html/Blob.cpp >+++ b/WebCore/html/Blob.cpp >@@ -31,88 +31,65 @@ > #include "config.h" > #include "Blob.h" > >+#include "BlobItem.h" > #include "FileSystem.h" > > namespace WebCore { > >-#if ENABLE(BLOB_SLICE) >-const int Blob::toEndOfFile = -1; >-const double Blob::doNotCheckFileChange = 0; >-#endif >- > Blob::Blob(const String& path) >- : m_path(path) >-#if ENABLE(BLOB_SLICE) >- , m_start(0) >- , m_length(toEndOfFile) >- , m_snapshotCaptured(false) >- , m_snapshotSize(0) >- , m_snapshotModificationTime(doNotCheckFileChange) >-#endif >-{ >-} >- >-#if ENABLE(BLOB_SLICE) >-Blob::Blob(const String& path, long long start, long long length, long long snapshotSize, double snapshotModificationTime) >- : m_path(path) >- , m_start(start) >- , m_length(length) >- , m_snapshotCaptured(true) >- , m_snapshotSize(snapshotSize) >- , m_snapshotModificationTime(snapshotModificationTime) > { >- ASSERT(start >= 0 && length >= 0 && start + length <= snapshotSize && snapshotModificationTime); >+ // Note: this doesn't initialize the type unlike File(path). >+ append(FileBlobItem::create(path)); > } >-#endif > > unsigned long long Blob::size() const > { > // FIXME: JavaScript cannot represent sizes as large as unsigned long long, we need to > // come up with an exception to throw if file size is not represetable. >-#if ENABLE(BLOB_SLICE) >- if (m_snapshotCaptured) >- return m_length; >-#endif >- long long size; >- if (!getFileSize(m_path, size)) >- return 0; >- return static_cast<unsigned long long>(size); >+ unsigned long long size = 0; >+ for (size_t i = 0; i < m_items.size(); ++i) >+ size += m_items[i]->size(); >+ return size; >+} >+ >+const String& Blob::path() const >+{ >+ ASSERT(m_items.size() == 1 && m_items[0]->toFileBlobItem()); >+ return m_items[0]->toFileBlobItem()->path(); >+} >+ >+void Blob::append(PassRefPtr<BlobItem> item) >+{ >+ m_items.append(item); > } > > #if ENABLE(BLOB_SLICE) > PassRefPtr<Blob> Blob::slice(long long start, long long length) const > { >- // When we slice a file for the first time, we obtain a snapshot of the file by capturing its current size and modification time. >- // The modification time will be used to verify if the file has been changed or not, when the underlying data are accessed. >- long long snapshotSize; >- double snapshotModificationTime; >- if (m_snapshotCaptured) { >- snapshotSize = m_snapshotSize; >- snapshotModificationTime = m_snapshotModificationTime; >- } else { >- // If we fail to retrieve the size or modification time, probably due to that the file has been deleted, an empty blob will be returned. >- time_t modificationTime; >- if (!getFileSize(m_path, snapshotSize) || !getFileModificationTime(m_path, modificationTime)) { >- snapshotSize = 0; >- snapshotModificationTime = 0; >- } else >- snapshotModificationTime = modificationTime; >- } >- >- // Clamp the range if it exceeds the size limit. > if (start < 0) > start = 0; > if (length < 0) > length = 0; > >- if (start > snapshotSize) { >+ // Clamp the range if it exceeds the size limit. >+ unsigned long long totalSize = size(); >+ if (static_cast<unsigned long long>(start) > totalSize) { > start = 0; > length = 0; >- } else if (start + length > snapshotSize) >- length = snapshotSize - start; >+ } else if (static_cast<unsigned long long>(start + length) > totalSize) >+ length = totalSize - start; > >- return adoptRef(new Blob(m_path, m_start + start, length, snapshotSize, snapshotModificationTime)); >+ size_t i = 0; >+ RefPtr<Blob> blob = Blob::create(); >+ for (; i < m_items.size() && static_cast<unsigned long long>(start) >= m_items[i]->size(); ++i) >+ start -= m_items[i]->size(); >+ for (; length > 0 && i < m_items.size(); ++i) { >+ blob->m_items.append(m_items[i]->slice(start, length)); >+ length -= blob->m_items.last()->size(); >+ start = 0; >+ } >+ return blob.release(); > } >-#endif >+#endif // ENABLE(BLOB_SLICE) > > } // namespace WebCore >diff --git a/WebCore/html/Blob.h b/WebCore/html/Blob.h >index e8b5f3fdf069a2b4876ed16ab81b22f0ff038970..39177b51ee9d078683f202a651df58238f274957 100644 >--- a/WebCore/html/Blob.h >+++ b/WebCore/html/Blob.h >@@ -31,21 +31,24 @@ > #ifndef Blob_h > #define Blob_h > >-#include "ExceptionCode.h" >+#include "BlobItem.h" > #include "PlatformString.h" >-#include <time.h> > #include <wtf/PassRefPtr.h> > #include <wtf/RefCounted.h> >+#include <wtf/Vector.h> > > namespace WebCore { > > class Blob : public RefCounted<Blob> { > public: >-#if ENABLE(BLOB_SLICE) >- static const int toEndOfFile; >- static const double doNotCheckFileChange; >-#endif >+ static PassRefPtr<Blob> create() >+ { >+ return adoptRef(new Blob()); >+ } > >+ // FIXME: Deprecated method. This is called only from >+ // bindings/v8/SerializedScriptValue.cpp and the usage in it will become invalid once >+ // BlobBuilder is introduced. > static PassRefPtr<Blob> create(const String& path) > { > return adoptRef(new Blob(path)); >@@ -53,47 +56,28 @@ public: > > virtual ~Blob() { } > >+ unsigned long long size() const; >+ const String& type() const { return m_type; } > virtual bool isFile() const { return false; } > >-#if ENABLE(BLOB_SLICE) >- PassRefPtr<Blob> slice(long long start, long long length) const; >-#endif >- >- const String& path() const { return m_path; } >- unsigned long long size() const; >-#if ENABLE(BLOB_SLICE) >- long long start() const { return m_start; } >- long long length() const { return m_length; } >- double modificationTime() const { return m_snapshotModificationTime; } >-#endif >+ // FIXME: Deprecated method. >+ const String& path() const; > >-protected: >- Blob(const String& path); >+ void append(PassRefPtr<BlobItem>); >+ const BlobItemList& items() const { return m_items; } > >-private: > #if ENABLE(BLOB_SLICE) >- Blob(const String& path, long long start, long long length, long long snapshotSize, double snapshotModificationTime); >+ PassRefPtr<Blob> slice(long long start, long long length) const; > #endif > >- // The underlying path of the file-based blob. >- String m_path; >- >-#if ENABLE(BLOB_SLICE) >- // The starting position of the file-based blob. >- long long m_start; >- >- // The length of the file-based blob. The value of -1 means to the end of the file. >- long long m_length; >- >- // A flag to tell if a snapshot has been captured. >- bool m_snapshotCaptured; >+protected: >+ Blob() { } > >- // The size of the file when a snapshot is captured. It can be 0 if the file is empty. >- long long m_snapshotSize; >+ // FIXME: Deprecated constructor. See also the comment for Blob::create(path). >+ Blob(const String& path); > >- // The last modification time of the file when a snapshot is captured. The value of 0 also means that the snapshot is not captured. >- double m_snapshotModificationTime; >-#endif >+ BlobItemList m_items; >+ String m_type; > }; > > } // namespace WebCore >diff --git a/WebCore/html/File.cpp b/WebCore/html/File.cpp >index 97fdc4578d74b225e5946f4d6aef256525443ae4..2c9ce53b83cb0df79a859522dc916f255bd84cc3 100644 >--- a/WebCore/html/File.cpp >+++ b/WebCore/html/File.cpp >@@ -33,12 +33,17 @@ namespace WebCore { > > File::File(const String& path) > : Blob(path) >- , m_name(pathGetFileName(path)) > { > // We don't use MIMETypeRegistry::getMIMETypeForPath() because it returns "application/octet-stream" upon failure. >- int index = m_name.reverseFind('.'); >+ const String& fileName = name(); >+ int index = fileName.reverseFind('.'); > if (index != -1) >- m_type = MIMETypeRegistry::getMIMETypeForExtension(m_name.substring(index + 1)); >+ m_type = MIMETypeRegistry::getMIMETypeForExtension(fileName.substring(index + 1)); >+} >+ >+const String& File::name() const >+{ >+ return items().at(0)->toFileBlobItem()->name(); > } > > } // namespace WebCore >diff --git a/WebCore/html/File.h b/WebCore/html/File.h >index 065dd86a7b1ebf77fb40646f9c6e870469d7eb09..582db28503bfff2b958e3d5255ef7abe9a60569a 100644 >--- a/WebCore/html/File.h >+++ b/WebCore/html/File.h >@@ -41,18 +41,14 @@ public: > > virtual bool isFile() const { return true; } > >- const String& name() const { return m_name; } >- const String& type() const { return m_type; } >+ const String& name() const; > > // FIXME: obsolete attributes. To be removed. >- const String& fileName() const { return m_name; } >+ const String& fileName() const { return name(); } > unsigned long long fileSize() const { return size(); } > > private: > File(const String& path); >- >- String m_name; >- String m_type; > }; > > } // namespace WebCore >diff --git a/WebCore/html/FileReader.cpp b/WebCore/html/FileReader.cpp >index 34423422758127bed773872c4ff31fa01dfac4e4..2e020c113505ccb6f443a8d256b0e9a1bab08034 100644 >--- a/WebCore/html/FileReader.cpp >+++ b/WebCore/html/FileReader.cpp >@@ -85,6 +85,7 @@ void FileReader::stop() > > void FileReader::readAsBinaryString(Blob* fileBlob) > { >+ // FIXME: needs to handle non-file blobs. > LOG(FileAPI, "FileReader: reading as binary: %s\n", fileBlob->path().utf8().data()); > > readInternal(fileBlob, ReadFileAsBinaryString); >@@ -92,6 +93,7 @@ void FileReader::readAsBinaryString(Blob* fileBlob) > > void FileReader::readAsText(Blob* fileBlob, const String& encoding) > { >+ // FIXME: needs to handle non-file blobs. > LOG(FileAPI, "FileReader: reading as text: %s\n", fileBlob->path().utf8().data()); > > if (!encoding.isEmpty()) >diff --git a/WebCore/html/FileStream.cpp b/WebCore/html/FileStream.cpp >index 9a06eed9fd66f8e37f37f9dd50435b56e9cc6141..f859b63a1c1b34c36e74c09124fa0913f6af6704 100644 >--- a/WebCore/html/FileStream.cpp >+++ b/WebCore/html/FileStream.cpp >@@ -72,48 +72,53 @@ void FileStream::openForRead(Blob* blob) > if (isHandleValid(m_handle)) > return; > >+ // FIXME: Need to handle multiple items that may include non-file ones when BlobBuilder is introduced. >+ ASSERT(blob->items().size() >= 1); >+ const FileBlobItem* fileItem = blob->items().at(0)->toFileBlobItem(); >+ if (!fileItem) { >+ ASSERT(false); >+ m_client->didFail(NOT_READABLE_ERR); >+ return; >+ } >+ > // Check if the file exists by querying its modification time. We choose not to call fileExists() in order to save an > // extra file system call when the modification time is needed to check the validity of the sliced file blob. > // Per the spec, we need to return different error codes to differentiate between non-existent file and permission error. > // openFile() could not tell use the failure reason. > time_t currentModificationTime; >- if (!getFileModificationTime(blob->path(), currentModificationTime)) { >+ if (!getFileModificationTime(fileItem->path(), currentModificationTime)) { > m_client->didFail(NOT_FOUND_ERR); > return; > } > > // Open the file blob. >- m_handle = openFile(blob->path(), OpenForRead); >+ m_handle = openFile(fileItem->path(), OpenForRead); > if (!isHandleValid(m_handle)) { > m_client->didFail(NOT_READABLE_ERR); > return; > } > > #if ENABLE(BLOB_SLICE) >- // Check the modificationt time for the possible file change. >- if (blob->modificationTime() != Blob::doNotCheckFileChange && static_cast<time_t>(blob->modificationTime()) != currentModificationTime) { >- m_client->didFail(NOT_READABLE_ERR); >- return; >- } >- >- // Jump to the beginning position if the file has been sliced. >- if (blob->start() > 0) { >- if (!seekFile(m_handle, blob->start(), SeekFromBeginning)) { >+ const FileRangeBlobItem* fileRangeItem = fileItem->toFileRangeBlobItem(); >+ if (fileRangeItem) { >+ // Check the modificationt time for the possible file change. >+ if (static_cast<time_t>(fileRangeItem->snapshotModificationTime()) != currentModificationTime) { > m_client->didFail(NOT_READABLE_ERR); > return; > } >+ >+ // Jump to the beginning position if the file has been sliced. >+ if (fileRangeItem->start() > 0) { >+ if (seekFile(m_handle, fileRangeItem->start(), SeekFromBeginning) < 0) { >+ m_client->didFail(NOT_READABLE_ERR); >+ return; >+ } >+ } > } > #endif > > // Get the size. >-#if ENABLE(BLOB_SLICE) >- m_totalBytesToRead = blob->length(); >- if (m_totalBytesToRead == Blob::toEndOfFile) >- m_totalBytesToRead = blob->size() - blob->start(); >-#else > m_totalBytesToRead = blob->size(); >-#endif >- > m_client->didGetSize(m_totalBytesToRead); > } > >diff --git a/WebCore/html/FormDataList.cpp b/WebCore/html/FormDataList.cpp >index 281c9fe418e1c4833bb87f82f74f1cc4d722d57c..0f62595ed41c2319bdb79b57bbd7ca94622b82aa 100644 >--- a/WebCore/html/FormDataList.cpp >+++ b/WebCore/html/FormDataList.cpp >@@ -28,64 +28,22 @@ FormDataList::FormDataList(const TextEncoding& c) > { > } > >-void FormDataList::appendString(const CString& s) >+void FormDataList::appendString(const String& s) > { >- m_list.append(s); >+ m_items.append(StringBlobItem::create(s, EndingCRLF, m_encoding)); > } > >-// Change plain CR and plain LF to CRLF pairs. >-static CString fixLineBreaks(const CString& s) >+void FormDataList::appendString(const CString& s) > { >- // Compute the length. >- unsigned newLen = 0; >- const char* p = s.data(); >- while (char c = *p++) { >- if (c == '\r') { >- // Safe to look ahead because of trailing '\0'. >- if (*p != '\n') { >- // Turn CR into CRLF. >- newLen += 2; >- } >- } else if (c == '\n') { >- // Turn LF into CRLF. >- newLen += 2; >- } else { >- // Leave other characters alone. >- newLen += 1; >- } >- } >- if (newLen == s.length()) { >- return s; >- } >- >- // Make a copy of the string. >- p = s.data(); >- char* q; >- CString result = CString::newUninitialized(newLen, q); >- while (char c = *p++) { >- if (c == '\r') { >- // Safe to look ahead because of trailing '\0'. >- if (*p != '\n') { >- // Turn CR into CRLF. >- *q++ = '\r'; >- *q++ = '\n'; >- } >- } else if (c == '\n') { >- // Turn LF into CRLF. >- *q++ = '\r'; >- *q++ = '\n'; >- } else { >- // Leave other characters alone. >- *q++ = c; >- } >- } >- return result; >+ m_items.append(StringBlobItem::create(s)); > } > >-void FormDataList::appendString(const String& s) >+void FormDataList::appendBlob(const String& key, PassRefPtr<Blob> blob) > { >- CString cstr = fixLineBreaks(m_encoding.encode(s.characters(), s.length(), EntitiesForUnencodables)); >- m_list.append(cstr); >+ appendString(key); >+ const BlobItemList& items = blob->items(); >+ for (size_t i = 0; i < items.size(); ++i) >+ m_items.append(items.at(i)); > } > > } // namespace >diff --git a/WebCore/html/FormDataList.h b/WebCore/html/FormDataList.h >index 8ecf64ee93ad524f47921f1d822f9a08ba013d7c..f4bb905150fad78b01ae5a9683fad9984390e6be 100644 >--- a/WebCore/html/FormDataList.h >+++ b/WebCore/html/FormDataList.h >@@ -46,27 +46,9 @@ public: > appendString(key); > appendString(String::number(value)); > } >- void appendBlob(const String& key, PassRefPtr<Blob> blob) >- { >- appendString(key); >- m_list.append(blob); >- } >- >- class Item { >- public: >- Item() { } >- Item(const WTF::CString& data) : m_data(data) { } >- Item(PassRefPtr<Blob> blob) : m_blob(blob) { } >- >- const WTF::CString& data() const { return m_data; } >- Blob* blob() const { return m_blob.get(); } >- >- private: >- WTF::CString m_data; >- RefPtr<Blob> m_blob; >- }; >+ void appendBlob(const String& key, PassRefPtr<Blob>); > >- const Vector<Item>& list() const { return m_list; } >+ const BlobItemList& items() const { return m_items; } > const TextEncoding& encoding() const { return m_encoding; } > > private: >@@ -74,7 +56,7 @@ private: > void appendString(const String&); > > TextEncoding m_encoding; >- Vector<Item> m_list; >+ BlobItemList m_items; > }; > > } // namespace WebCore >diff --git a/WebCore/html/HTMLFormElement.cpp b/WebCore/html/HTMLFormElement.cpp >index c19933adb4833cc40f16e0e9b658d57c8e6b0f50..8b606f590211293686669f536c75472b95272f5f 100644 >--- a/WebCore/html/HTMLFormElement.cpp >+++ b/WebCore/html/HTMLFormElement.cpp >@@ -209,7 +209,7 @@ PassRefPtr<FormData> HTMLFormElement::createFormData() > control->appendFormData(*domFormData, m_formDataBuilder.isMultiPartForm()); > } > >- RefPtr<FormData> result = (m_formDataBuilder.isMultiPartForm()) ? FormData::createMultiPart(*domFormData, document()) : FormData::create(*domFormData); >+ RefPtr<FormData> result = (m_formDataBuilder.isMultiPartForm()) ? FormData::createMultiPart(domFormData->items(), domFormData->encoding(), document()) : FormData::create(domFormData->items(), domFormData->encoding()); > > result->setIdentifier(generateFormDataIdentifier()); > return result; >diff --git a/WebCore/html/HTMLMeterElement.cpp b/WebCore/html/HTMLMeterElement.cpp >index a1b74b2d0ab0c75ceda3d6328981154c48c72418..03162670c63b779df6073b956054e6baead35238 100644 >--- a/WebCore/html/HTMLMeterElement.cpp >+++ b/WebCore/html/HTMLMeterElement.cpp >@@ -24,6 +24,7 @@ > > #include "Attribute.h" > #include "EventNames.h" >+#include "ExceptionCode.h" > #include "FormDataList.h" > #include "HTMLFormElement.h" > #include "HTMLNames.h" >diff --git a/WebCore/html/HTMLProgressElement.cpp b/WebCore/html/HTMLProgressElement.cpp >index d275ebfcff8d97b916d59d24f2419da8c534af29..f7e86f3a9affecedebb93b935350dab852aea6c5 100644 >--- a/WebCore/html/HTMLProgressElement.cpp >+++ b/WebCore/html/HTMLProgressElement.cpp >@@ -24,6 +24,7 @@ > > #include "Attribute.h" > #include "EventNames.h" >+#include "ExceptionCode.h" > #include "FormDataList.h" > #include "HTMLFormElement.h" > #include "HTMLNames.h" >diff --git a/WebCore/platform/BlobItem.cpp b/WebCore/platform/BlobItem.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..90a818e0f6ca274e4dfec02ca654ea1a7b0f5ef6 >--- /dev/null >+++ b/WebCore/platform/BlobItem.cpp >@@ -0,0 +1,317 @@ >+/* >+ * 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 "BlobItem.h" >+ >+#include "FileSystem.h" >+#include "UUID.h" >+ >+namespace WebCore { >+ >+#if ENABLE(BLOB_SLICE) >+static const double invalidModificationTime = 0; >+ >+double getFileSnapshotModificationTime(const String& path) >+{ >+ // FIXME: synchronized file call >+ time_t modificationTime; >+ if (getFileModificationTime(path, modificationTime)) >+ return static_cast<double>(modificationTime); >+ return invalidModificationTime; >+} >+#endif // ENABLE(BLOB_SLICE) >+ >+// DataBlobItem ---------------------------------------------------------------- >+ >+char* DataBlobItem::copyBuffer() const >+{ >+ // FIXME: Reconsider if we still need it once we clean up the transient wrapper class FormDataElement::BlobItemWrapper and its releaseBuffer() method. It used to be a mere Vector and Vector::releaseBuffer, but now we keep the data ref-counted and need to make a copy to return the data with ownership. >+ Vector<char> v; >+ v.append(data(), static_cast<size_t>(size())); >+ return v.releaseBuffer(); >+} >+ >+bool DataBlobItem::equals(const BlobItem* item) const >+{ >+ const DataBlobItem* dataItem = item->toDataBlobItem(); >+ return dataItem && data() == dataItem->data() && size() == dataItem->size(); >+} >+ >+#if ENABLE(BLOB_SLICE) >+PassRefPtr<BlobItem> DataBlobItem::slice(long long start, long long length) >+{ >+ ASSERT(start >= 0 && length >= 0); >+ ASSERT(static_cast<unsigned long long>(start) < size()); >+ if (!start && size() <= static_cast<unsigned long long>(length)) >+ return this; >+ if (static_cast<unsigned long long>(start + length) > size()) >+ length = size() - start; >+ return DataRangeBlobItem::create(this, start, length); >+} >+#endif // ENABLE(BLOB_SLICE) >+ >+// FileBlobItem ---------------------------------------------------------------- >+ >+PassRefPtr<BlobItem> FileBlobItem::create(const String& path) >+{ >+ return adoptRef(static_cast<BlobItem*>(new FileBlobItem(path))); >+} >+ >+FileBlobItem::FileBlobItem(const String& path) >+ : m_path(path) >+ , m_fileName(pathGetFileName(m_path)) >+{ >+} >+ >+unsigned long long FileBlobItem::size() const >+{ >+ // FIXME: synchronized file call >+ long long size; >+ if (!getFileSize(m_path, size)) >+ return 0; >+ return static_cast<unsigned long long>(size); >+} >+ >+PassRefPtr<BlobItem> FileBlobItem::deepCopy() const >+{ >+ return FileBlobItem::create(m_path); >+} >+ >+bool FileBlobItem::equals(const BlobItem* item) const >+{ >+ const FileBlobItem* fileItem = item->toFileBlobItem(); >+ return fileItem && m_path == fileItem->m_path; >+} >+ >+#if ENABLE(BLOB_SLICE) >+PassRefPtr<BlobItem> FileBlobItem::slice(long long start, long long length) >+{ >+ ASSERT(start >= 0 && length >= 0); >+ ASSERT(static_cast<unsigned long long>(start) < size()); >+ if (!start && size() <= static_cast<unsigned long long>(length)) >+ return this; >+ const FileRangeBlobItem* fileRangeItem = toFileRangeBlobItem(); >+ double modificationTime = fileRangeItem ? fileRangeItem->snapshotModificationTime() : getFileSnapshotModificationTime(path()); >+ return FileRangeBlobItem::create(path(), start, length, modificationTime); >+} >+#endif // ENABLE(BLOB_SLICE) >+ >+// StringBlobItem -------------------------------------------------------------- >+ >+PassRefPtr<BlobItem> StringBlobItem::create(const String& text, LineEnding ending, TextEncoding encoding) >+{ >+ return adoptRef(static_cast<BlobItem*>(new StringBlobItem(text, ending, encoding))); >+} >+ >+PassRefPtr<BlobItem> StringBlobItem::create(const CString& text) >+{ >+ return adoptRef(static_cast<BlobItem*>(new StringBlobItem(text))); >+} >+ >+StringBlobItem::StringBlobItem(const String& text, LineEnding ending, TextEncoding encoding) >+ : m_data(StringBlobItem::convertToCString(text, ending, encoding)) >+{ >+} >+ >+StringBlobItem::StringBlobItem(const CString& text) >+ : m_data(text) >+{ >+} >+ >+PassRefPtr<BlobItem> StringBlobItem::deepCopy() const >+{ >+ return StringBlobItem::create(CString(m_data.data(), m_data.length())); >+} >+ >+bool StringBlobItem::equals(const BlobItem* item) const >+{ >+ if (!DataBlobItem::equals(item)) >+ return false; >+ const StringBlobItem* stringItem = item->toStringBlobItem(); >+ return stringItem && data() == stringItem->data() && size() == stringItem->size(); >+} >+ >+CString StringBlobItem::convertToCString(const String& text, LineEnding ending, TextEncoding encoding) >+{ >+ CString from = encoding.encode(text.characters(), text.length(), EntitiesForUnencodables); >+ CString result = from; >+ >+ if (ending == EndingTransparent) >+ return result; >+ >+ const char* endingChars = (ending == EndingCRLF) ? "\r\n" : ((ending == EndingCR) ? "\r" : "\n"); >+ >+ int endingLength = (ending == EndingCRLF) ? 2 : 1; >+ int needFix = 0; >+ >+ // Calculate the final length. >+ int calculatedLength = from.length(); >+ const char* p = from.data(); >+ while (char c = *p++) { >+ if (c == '\r') { >+ // Safe to look ahead because of trailing '\0'. >+ if (*p == '\n' && ending != EndingCRLF) { >+ calculatedLength += (endingLength - 2); >+ ++needFix; >+ } else if (ending != EndingCR) { >+ calculatedLength += (endingLength - 1); >+ ++needFix; >+ } >+ } else if (c == '\n' && ending != EndingLF) { >+ calculatedLength += (endingLength - 1); >+ ++needFix; >+ } >+ } >+ >+ if (!needFix) >+ return result; >+ >+ // Convert the endings and create a data buffer. >+ p = from.data(); >+ char* q; >+ result = CString::newUninitialized(calculatedLength, q); >+ while (char c = *p++) { >+ if (c == '\r') { >+ if (*p == '\n' && ending != EndingCRLF) { >+ memcpy(q, endingChars, endingLength); >+ q += endingLength; >+ } else if (*p != '\n' && ending != EndingCR) { >+ memcpy(q, endingChars, endingLength); >+ q += endingLength; >+ } >+ } else if (c == '\n' && ending != EndingLF) { >+ memcpy(q, endingChars, endingLength); >+ q += endingLength; >+ } else { >+ // Leave other characters alone. >+ *q++ = c; >+ } >+ } >+ return result; >+} >+ >+// ByteArrayBlobItem ---------------------------------------------------------- >+ >+PassRefPtr<BlobItem> ByteArrayBlobItem::create(const char* data, size_t size) >+{ >+ return adoptRef(static_cast<BlobItem*>(new ByteArrayBlobItem(data, size))); >+} >+ >+ByteArrayBlobItem::ByteArrayBlobItem(const char* data, size_t size) >+{ >+ m_bytesArray.append(data, size); >+} >+ >+PassRefPtr<BlobItem> ByteArrayBlobItem::deepCopy() const >+{ >+ return ByteArrayBlobItem::create(m_bytesArray.data(), m_bytesArray.size()); >+} >+ >+#if ENABLE(BLOB_SLICE) >+ >+// DataRangeBlobItem ----------------------------------------------------------- >+ >+PassRefPtr<BlobItem> DataRangeBlobItem::create(PassRefPtr<DataBlobItem> item, long long start, long long length) >+{ >+ return adoptRef(static_cast<BlobItem*>(new DataRangeBlobItem(item, start, length))); >+} >+ >+DataRangeBlobItem::DataRangeBlobItem(PassRefPtr<DataBlobItem> item, long long start, long long length) >+ : m_length(length) >+{ >+ const DataRangeBlobItem* rangeItem = m_item->toDataRangeBlobItem(); >+ if (rangeItem) { >+ m_item = rangeItem->m_item; >+ m_start = start + rangeItem->m_start; >+ ASSERT(!m_item->toDataRangeBlobItem()); >+ ASSERT(static_cast<unsigned long long>(m_start + m_length) <= m_item->size()); >+ } else { >+ m_item = item; >+ m_start = start; >+ } >+} >+ >+const char* DataRangeBlobItem::data() const >+{ >+ return m_item->data() + m_start; >+} >+ >+PassRefPtr<BlobItem> DataRangeBlobItem::deepCopy() const >+{ >+ return DataRangeBlobItem::create(static_pointer_cast<DataBlobItem>(m_item->deepCopy()), m_start, m_length); >+} >+ >+bool DataRangeBlobItem::equals(const BlobItem* item) const >+{ >+ const DataRangeBlobItem* rangeItem = item->toDataRangeBlobItem(); >+ return rangeItem && m_start == rangeItem->m_start && m_length == rangeItem->m_length && m_item->equals(rangeItem->m_item.get()); >+} >+ >+// FileRangeBlobItem ----------------------------------------------------------- >+ >+PassRefPtr<BlobItem> FileRangeBlobItem::create(const String& path, long long start, long long length, double snapshotModificationTime) >+{ >+ return adoptRef(static_cast<BlobItem*>(new FileRangeBlobItem(path, start, length, snapshotModificationTime))); >+} >+ >+FileRangeBlobItem::FileRangeBlobItem(const String& path, long long start, long long length, double modificationTime) >+ : FileBlobItem(path) >+ , m_start(start) >+ , m_length(length) >+ , m_snapshotModificationTime(modificationTime) >+{ >+ m_uniqueName = "Blob" + createCanonicalUUIDString(); >+ m_uniqueName.replace("-", ""); // For safty, remove '-' from the filename snce some servers may not like it. >+} >+ >+PassRefPtr<BlobItem> FileRangeBlobItem::deepCopy() const >+{ >+ return FileRangeBlobItem::create(path(), m_start, m_length, m_snapshotModificationTime); >+} >+ >+bool FileRangeBlobItem::equals(const BlobItem* item) const >+{ >+ if (!FileBlobItem::equals(item)) >+ return false; >+ const FileRangeBlobItem* rangeItem = item->toFileRangeBlobItem(); >+ return rangeItem && m_start == rangeItem->m_start && m_uniqueName == rangeItem->m_uniqueName && m_snapshotModificationTime == rangeItem->m_snapshotModificationTime; >+} >+ >+bool FileRangeBlobItem::isValid() const >+{ >+ if (m_snapshotModificationTime == invalidModificationTime) >+ return false; >+ return m_snapshotModificationTime == getFileSnapshotModificationTime(path()); >+} >+ >+#endif // ENABLE(BLOB_SLICE) >+ >+} // namespace WebCore >diff --git a/WebCore/platform/BlobItem.h b/WebCore/platform/BlobItem.h >new file mode 100644 >index 0000000000000000000000000000000000000000..2191c6c087d36b3394710eb3e2eaac4795fa5e2e >--- /dev/null >+++ b/WebCore/platform/BlobItem.h >@@ -0,0 +1,227 @@ >+/* >+ * 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 BlobItem_h >+#define BlobItem_h >+ >+#include "PlatformString.h" >+#include "TextEncoding.h" >+#include <wtf/OwnPtr.h> >+#include <wtf/PassRefPtr.h> >+#include <wtf/RefCounted.h> >+#include <wtf/Vector.h> >+#include <wtf/text/CString.h> >+ >+namespace WebCore { >+ >+// String ending types. >+enum LineEnding { >+ EndingTransparent = 0, >+ EndingLF, >+ EndingCR, >+ EndingCRLF, >+}; >+ >+class ByteArrayBlobItem; >+class DataBlobItem; >+class DataRangeBlobItem; >+class FileBlobItem; >+class FileRangeBlobItem; >+class StringBlobItem; >+ >+// A base interface for all arbitrary-data-object component items. >+// The BlobItem and its subclasses are structured like the following: >+// BlobItem >+// | >+// +-------> DataBlobItem >+// | | >+// | +---------> StringBlobItem >+// | +---------> ByteArrayBlobItem >+// | +---------> DataRangeBlobItem >+// | >+// +-------> FileBlobItem >+// | >+// +---------> FileRangeBlobItem >+// >+class BlobItem : public RefCounted<BlobItem> { >+public: >+ virtual ~BlobItem() { } >+ virtual unsigned long long size() const = 0; >+ >+ // Returns false if the data has become stale or invalid. >+ virtual bool isValid() const { return true; } >+ >+ virtual const DataBlobItem* toDataBlobItem() const { return 0; } >+ virtual const StringBlobItem* toStringBlobItem() const { return 0; } >+ virtual const ByteArrayBlobItem* toByteArrayBlobItem() const { return 0; } >+ virtual const FileBlobItem* toFileBlobItem() const { return 0; } >+#if ENABLE(BLOB_SLICE) >+ virtual const DataRangeBlobItem* toDataRangeBlobItem() const { return 0; } >+ virtual const FileRangeBlobItem* toFileRangeBlobItem() const { return 0; } >+ >+ // Note: no external methods except for Blob::slice should call this. >+ virtual PassRefPtr<BlobItem> slice(long long start, long long length) = 0; >+#endif // ENABLE(BLOB_SLICE) >+ >+ virtual PassRefPtr<BlobItem> deepCopy() const = 0; >+ virtual bool equals(const BlobItem*) const = 0; >+ >+protected: >+ BlobItem() { } >+}; >+ >+typedef Vector<RefPtr<BlobItem> > BlobItemList; >+ >+class DataBlobItem : public BlobItem { >+public: >+ virtual const char* data() const = 0; >+ char* copyBuffer() const; >+ >+ // BlobItem methods. >+ virtual const DataBlobItem* toDataBlobItem() const { return this; } >+ virtual bool equals(const BlobItem*) const; >+#if ENABLE(BLOB_SLICE) >+ virtual PassRefPtr<BlobItem> slice(long long start, long long length); >+#endif // ENABLE(BLOB_SLICE) >+}; >+ >+class FileBlobItem : public BlobItem { >+public: >+ static PassRefPtr<BlobItem> create(const String& path); >+ virtual const String& name() const { return m_fileName; } >+ virtual const String& path() const { return m_path; } >+ >+ // BlobItem methods. >+ virtual unsigned long long size() const; >+ virtual const FileBlobItem* toFileBlobItem() const { return this; } >+ virtual PassRefPtr<BlobItem> deepCopy() const; >+ virtual bool equals(const BlobItem*) const; >+#if ENABLE(BLOB_SLICE) >+ virtual PassRefPtr<BlobItem> slice(long long start, long long length); >+#endif // ENABLE(BLOB_SLICE) >+ >+protected: >+ FileBlobItem(const String& path); >+ String m_path; >+ String m_fileName; >+}; >+ >+class StringBlobItem : public DataBlobItem { >+public: >+ static PassRefPtr<BlobItem> create(const String&, LineEnding, TextEncoding); >+ static PassRefPtr<BlobItem> create(const CString&); >+ const CString& cstr() const { return m_data; } >+ >+ // BlobItem methods. >+ virtual unsigned long long size() const { return m_data.length(); } >+ virtual const StringBlobItem* toStringBlobItem() const { return this; } >+ virtual PassRefPtr<BlobItem> deepCopy() const; >+ virtual bool equals(const BlobItem*) const; >+ >+ // DataBlobItem methods. >+ virtual const char* data() const { return m_data.data(); } >+ >+private: >+ StringBlobItem(const String&, LineEnding, TextEncoding); >+ StringBlobItem(const CString&); >+ static CString convertToCString(const String&, LineEnding, TextEncoding); >+ CString m_data; >+}; >+ >+class ByteArrayBlobItem : public DataBlobItem { >+public: >+ static PassRefPtr<BlobItem> create(const char* data, size_t size); >+ >+ // BlobItem methods. >+ virtual unsigned long long size() const { return m_bytesArray.size(); } >+ virtual const ByteArrayBlobItem* toByteArrayBlobItem() const { return this; } >+ virtual PassRefPtr<BlobItem> deepCopy() const; >+ >+ // DataBlobItem methods. >+ virtual const char* data() const { return m_bytesArray.data(); } >+ >+private: >+ ByteArrayBlobItem(const char* data, size_t size); >+ Vector<char> m_bytesArray; >+}; >+ >+#if ENABLE(BLOB_SLICE) >+ >+// BlobItem class for sliced data (string or bytes-array). >+class DataRangeBlobItem : public DataBlobItem { >+public: >+ static PassRefPtr<BlobItem> create(PassRefPtr<DataBlobItem>, long long start, long long length); >+ >+ // BlobItem methods. >+ virtual unsigned long long size() const { return m_length; } >+ virtual const DataRangeBlobItem* toDataRangeBlobItem() const { return this; } >+ virtual PassRefPtr<BlobItem> deepCopy() const; >+ virtual bool equals(const BlobItem*) const; >+ >+ // DataBlobItem methods. >+ virtual const char* data() const; >+ >+private: >+ DataRangeBlobItem(PassRefPtr<DataBlobItem>, long long start, long long length); >+ RefPtr<DataBlobItem> m_item; >+ long long m_start; >+ long long m_length; >+}; >+ >+class FileRangeBlobItem : public FileBlobItem { >+public: >+ static PassRefPtr<BlobItem> create(const String& path, long long start, long long length, double snapshotModificationTime); >+ long long start() const { return m_start; } >+ double snapshotModificationTime() const { return m_snapshotModificationTime; } >+ >+ // BlobItem methods. >+ virtual unsigned long long size() const { return m_length; } >+ virtual const FileRangeBlobItem* toFileRangeBlobItem() const { return this; } >+ virtual bool isValid() const; >+ virtual PassRefPtr<BlobItem> deepCopy() const; >+ virtual bool equals(const BlobItem*) const; >+ >+ // FileBlobItem methods. >+ virtual const String& name() const { return m_uniqueName; } >+ >+private: >+ FileRangeBlobItem(const String& path, long long start, long long length, double snapshotModificationTime); >+ long long m_start; >+ long long m_length; >+ String m_uniqueName; >+ >+ double m_snapshotModificationTime; >+}; >+ >+#endif // ENABLE(BLOB_SLICE) >+ >+} // namespace WebCore >+ >+#endif // BlobItem_h >diff --git a/WebCore/platform/network/FormData.cpp b/WebCore/platform/network/FormData.cpp >index 918002aefd81a6891f9f19baf44d75591fdfa484..afccccaa425dcbf50a9c43c3f5f966088f44eb7e 100644 >--- a/WebCore/platform/network/FormData.cpp >+++ b/WebCore/platform/network/FormData.cpp >@@ -19,23 +19,46 @@ > */ > > #include "config.h" >+ > #include "FormData.h" > >-#include "Blob.h" >+#include "BlobItem.h" > #include "Chrome.h" > #include "ChromeClient.h" >-#include "DOMFormData.h" > #include "Document.h" >-#include "File.h" > #include "FileSystem.h" > #include "FormDataBuilder.h" > #include "MIMETypeRegistry.h" > #include "Page.h" > #include "TextEncoding.h" >-#include "UUID.h" > > namespace WebCore { > >+#if ENABLE(BLOB_SLICE) >+const long long FormDataElement::toEndOfFile = -1; >+#endif >+ >+FormDataElement::FormDataElement(PassRefPtr<BlobItem> blobItem, bool shouldGenerateFile) >+ : m_item(blobItem) >+ , m_type(m_item->toFileBlobItem() ? encodedFile : data) >+ , m_data(m_item->toDataBlobItem()) >+ , m_filename(m_item->toFileBlobItem() ? m_item->toFileBlobItem()->path() : String()) >+ , m_shouldGenerateFile(shouldGenerateFile) >+{ >+#if ENABLE(BLOB_SLICE) >+ const FileRangeBlobItem* fileRangeItem = m_item->toFileRangeBlobItem(); >+ if (fileRangeItem) { >+ m_fileStart = fileRangeItem->start(); >+ m_fileLength = fileRangeItem->size(); >+ m_expectedFileModificationTime = fileRangeItem->snapshotModificationTime(); >+ } else { >+ m_fileStart = 0; >+ m_fileLength = toEndOfFile; >+ m_expectedFileModificationTime = 0; >+ } >+#endif >+} >+ > inline FormData::FormData() > : m_identifier(0) > , m_hasGeneratedFiles(false) >@@ -85,7 +108,7 @@ PassRefPtr<FormData> FormData::create(const void* data, size_t size) > PassRefPtr<FormData> FormData::create(const CString& string) > { > RefPtr<FormData> result = create(); >- result->appendData(string.data(), string.length()); >+ result->appendString(string); > return result.release(); > } > >@@ -96,17 +119,17 @@ PassRefPtr<FormData> FormData::create(const Vector<char>& vector) > return result.release(); > } > >-PassRefPtr<FormData> FormData::create(const DOMFormData& domFormData) >+PassRefPtr<FormData> FormData::create(const BlobItemList& items, const TextEncoding& encoding) > { > RefPtr<FormData> result = create(); >- result->appendDOMFormData(domFormData, false, 0); >+ result->appendKeyValuePairItems(items, encoding, false, 0); > return result.release(); > } > >-PassRefPtr<FormData> FormData::createMultiPart(const DOMFormData& domFormData, Document* document) >+PassRefPtr<FormData> FormData::createMultiPart(const BlobItemList& items, const TextEncoding& encoding, Document* document) > { > RefPtr<FormData> result = create(); >- result->appendDOMFormData(domFormData, true, document); >+ result->appendKeyValuePairItems(items, encoding, true, document); > return result.release(); > } > >@@ -125,84 +148,69 @@ PassRefPtr<FormData> FormData::deepCopy() const > formData->m_elements.reserveInitialCapacity(n); > for (size_t i = 0; i < n; ++i) { > const FormDataElement& e = m_elements[i]; >- switch (e.m_type) { >- case FormDataElement::data: >- formData->m_elements.append(FormDataElement(e.m_data)); >- break; >- case FormDataElement::encodedFile: >-#if ENABLE(BLOB_SLICE) >- formData->m_elements.append(FormDataElement(e.m_filename, e.m_fileStart, e.m_fileLength, e.m_expectedFileModificationTime, e.m_shouldGenerateFile)); >-#else >- formData->m_elements.append(FormDataElement(e.m_filename, e.m_shouldGenerateFile)); >-#endif >- break; >- } >+ formData->m_elements.append(FormDataElement(e.item()->deepCopy(), e.m_shouldGenerateFile)); > } > return formData.release(); > } > > void FormData::appendData(const void* data, size_t size) > { >- if (m_elements.isEmpty() || m_elements.last().m_type != FormDataElement::data) >- m_elements.append(FormDataElement()); >- FormDataElement& e = m_elements.last(); >- size_t oldSize = e.m_data.size(); >- e.m_data.grow(oldSize + size); >- memcpy(e.m_data.data() + oldSize, data, size); >+ m_elements.append(FormDataElement(ByteArrayBlobItem::create(static_cast<const char*>(data), size))); >+} >+ >+void FormData::appendString(const CString& string) >+{ >+ m_elements.append(FormDataElement(StringBlobItem::create(string))); > } > > void FormData::appendFile(const String& filename, bool shouldGenerateFile) > { >-#if ENABLE(BLOB_SLICE) >- m_elements.append(FormDataElement(filename, 0, Blob::toEndOfFile, Blob::doNotCheckFileChange, shouldGenerateFile)); >-#else >- m_elements.append(FormDataElement(filename, shouldGenerateFile)); >-#endif >+ m_elements.append(FormDataElement(FileBlobItem::create(filename), shouldGenerateFile)); >+} >+ >+void FormData::appendItems(const BlobItemList& items) >+{ >+ for (BlobItemList::const_iterator iter(items.begin()); iter != items.end(); ++iter) >+ m_elements.append(*iter); > } > > #if ENABLE(BLOB_SLICE) > void FormData::appendFileRange(const String& filename, long long start, long long length, double expectedModificationTime, bool shouldGenerateFile) > { >- m_elements.append(FormDataElement(filename, start, length, expectedModificationTime, shouldGenerateFile)); >+ if (length == FormDataElement::toEndOfFile) { >+ ASSERT(!start); >+ ASSERT(!expectedModificationTime); >+ m_elements.append(FormDataElement(FileBlobItem::create(filename), shouldGenerateFile)); >+ } else >+ m_elements.append(FormDataElement(FileRangeBlobItem::create(filename, start, length, expectedModificationTime), shouldGenerateFile)); > } > #endif > >-void FormData::appendDOMFormData(const DOMFormData& domFormData, bool isMultiPartForm, Document* document) >+void FormData::appendKeyValuePairItems(const BlobItemList& items, const TextEncoding& encoding, 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(); >+ size_t formDataListSize = items.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]; >+ const StringBlobItem* key = items[i]->toStringBlobItem(); >+ const RefPtr<BlobItem> value = items[i + 1]; >+ ASSERT(key); >+ bool appendValue = true; > if (isMultiPartForm) { > Vector<char> header; >- formDataBuilder.beginMultiPartHeader(header, m_boundary.data(), key.data()); >+ formDataBuilder.beginMultiPartHeader(header, m_boundary.data(), key->cstr()); > > bool shouldGenerateFile = false; > // If the current type is FILE, then we also need to include the filename >- if (value.blob()) { >- const String& path = value.blob()->path(); >-#if ENABLE(BLOB_SLICE) >- String fileName; >- if (value.blob()->isFile()) >- fileName = static_cast<File*>(value.blob())->fileName(); >- else { >- // If a blob is sliced from a file, it does not have the filename. In this case, let's produce a unique filename. >- fileName = "Blob" + createCanonicalUUIDString(); >- fileName.replace("-", ""); // For safty, remove '-' from the filename snce some servers may not like it. >- } >-#else >- ASSERT(value.blob()->isFile()); >- String fileName = static_cast<File*>(value.blob())->fileName(); >-#endif >+ const FileBlobItem* fileItem = value->toFileBlobItem(); >+ if (fileItem) { >+ const String& path = fileItem->path(); >+ String fileName = fileItem->name(); > > // Let the application specify a filename if it's going to generate a replacement file for the upload. > if (!path.isEmpty()) { >@@ -212,14 +220,17 @@ void FormData::appendDOMFormData(const DOMFormData& domFormData, bool isMultiPar > if (shouldGenerateFile) > fileName = generatedFileName; > } >+ } else { >+ // If the path is empty do not add the file to the element list. >+ appendValue = false; > } > > // We have to include the filename=".." part in the header, even if the filename is empty > formDataBuilder.addFilenameToMultiPartHeader(header, encoding, fileName); > >- // If a blob is sliced from a file, do not add the content type. >+ // If the item is sliced from a file, do not add the content type. > #if ENABLE(BLOB_SLICE) >- if (!fileName.isEmpty() && value.blob()->isFile()) { >+ if (!fileName.isEmpty() && !value->toFileRangeBlobItem()) { > #else > if (!fileName.isEmpty()) { > #endif >@@ -237,25 +248,21 @@ void FormData::appendDOMFormData(const DOMFormData& domFormData, bool isMultiPar > > // Append body > appendData(header.data(), header.size()); >- if (size_t dataSize = value.data().length()) >- appendData(value.data().data(), dataSize); >- else if (value.blob() && !value.blob()->path().isEmpty()) >-#if ENABLE(BLOB_SLICE) >- appendFileRange(value.blob()->path(), value.blob()->start(), value.blob()->length(), value.blob()->modificationTime(), shouldGenerateFile); >-#else >- appendFile(value.blob()->path(), shouldGenerateFile); >-#endif >- >+ if (appendValue) >+ m_elements.append(FormDataElement(value, 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()); >+ const StringBlobItem* stringValue = value->toStringBlobItem(); >+ if (!stringValue) >+ continue; >+ if (encodedData.isEmpty() && key->cstr() == "isindex") >+ FormDataBuilder::encodeStringAsFormData(encodedData, stringValue->cstr()); > else >- formDataBuilder.addKeyValuePairAsFormData(encodedData, key.data(), value.data()); >+ formDataBuilder.addKeyValuePairAsFormData(encodedData, key->cstr(), stringValue->cstr()); > } >- } >+ } > > if (isMultiPartForm) > formDataBuilder.addBoundaryToMultiPartHeader(encodedData, m_boundary.data(), true); >@@ -270,12 +277,8 @@ void FormData::flatten(Vector<char>& data) const > size_t n = m_elements.size(); > for (size_t i = 0; i < n; ++i) { > const FormDataElement& e = m_elements[i]; >- if (e.m_type == FormDataElement::data) { >- size_t oldSize = data.size(); >- size_t delta = e.m_data.size(); >- data.grow(oldSize + delta); >- memcpy(data.data() + oldSize, e.m_data.data(), delta); >- } >+ if (e.m_type == FormDataElement::data) >+ data.append(e.m_data.data(), static_cast<size_t>(e.m_data.size())); > } > } > >@@ -289,10 +292,10 @@ String FormData::flattenToString() const > void FormData::generateFiles(Document* document) > { > ASSERT(!m_hasGeneratedFiles); >- >+ > if (m_hasGeneratedFiles) > return; >- >+ > Page* page = document->page(); > if (!page) > return; >@@ -302,7 +305,7 @@ void FormData::generateFiles(Document* document) > for (size_t i = 0; i < n; ++i) { > FormDataElement& e = m_elements[i]; > if (e.m_type == FormDataElement::encodedFile && e.m_shouldGenerateFile) { >- e.m_generatedFilename = client->generateReplacementFile(e.m_filename); >+ e.m_generatedFilename = client->generateReplacementFile(e.item()->toFileBlobItem()->path()); > m_hasGeneratedFiles = true; > } > } >@@ -312,7 +315,7 @@ void FormData::removeGeneratedFilesIfNeeded() > { > if (!m_hasGeneratedFiles) > return; >- >+ > size_t n = m_elements.size(); > for (size_t i = 0; i < n; ++i) { > FormDataElement& e = m_elements[i]; >diff --git a/WebCore/platform/network/FormData.h b/WebCore/platform/network/FormData.h >index a4390234796a0e2f14f5d349f5dd0effc0a4b7cd..483a849747d852df5b37723f24aa620adad0a3b5 100644 >--- a/WebCore/platform/network/FormData.h >+++ b/WebCore/platform/network/FormData.h >@@ -20,74 +20,90 @@ > #ifndef FormData_h > #define FormData_h > >+#include "BlobItem.h" > #include "PlatformString.h" > #include <wtf/RefCounted.h> > #include <wtf/Vector.h> > > namespace WebCore { > >-class DOMFormData; > class Document; >+class TextEncoding; > >+// A wrapper class of BlobItem for FormData. > class FormDataElement { > public: >- FormDataElement() : m_type(data) { } >- FormDataElement(const Vector<char>& array) : m_type(data), m_data(array) { } >-#if ENABLE(BLOB_SLICE) >- FormDataElement(const String& filename, long long fileStart, long long fileLength, double expectedFileModificationTime, bool shouldGenerateFile) : m_type(encodedFile), m_filename(filename), m_fileStart(fileStart), m_fileLength(fileLength), m_expectedFileModificationTime(expectedFileModificationTime), m_shouldGenerateFile(shouldGenerateFile) { } >-#else >- FormDataElement(const String& filename, bool shouldGenerateFile) : m_type(encodedFile), m_filename(filename), m_shouldGenerateFile(shouldGenerateFile) { } >-#endif >+ FormDataElement() : m_data(0) { } >+ FormDataElement(PassRefPtr<BlobItem> blobItem, bool shouldGenerateFile = false); >+ >+ const BlobItem* item() const { return m_item.get(); } >+ >+ RefPtr<BlobItem> m_item; > >+ // FIXME: clean me up. Code below are mostly kept for compatibility. > enum { data, encodedFile } m_type; >- Vector<char> m_data; >+ struct BlobItemWrapper { >+ BlobItemWrapper(const DataBlobItem* item) : m_item(item) { } >+ size_t size() const >+ { >+ if (!m_item) >+ return 0; >+ return static_cast<size_t>(m_item->size()); >+ } >+ const char* data() const >+ { >+ if (!m_item) >+ return 0; >+ return m_item->data(); >+ } >+ char* releaseBuffer() const >+ { >+ if (!m_item) >+ return 0; >+ // FIXME: releaseBuffer actually makes a copy here. >+ return m_item->copyBuffer(); >+ } >+ const DataBlobItem* m_item; >+ }; >+ const BlobItemWrapper m_data; > String m_filename; > #if ENABLE(BLOB_SLICE) > long long m_fileStart; > long long m_fileLength; > double m_expectedFileModificationTime; >+ >+ static const long long toEndOfFile; > #endif >+ > String m_generatedFilename; > bool m_shouldGenerateFile; > }; > > inline bool operator==(const FormDataElement& a, const FormDataElement& b) > { >- if (&a == &b) >- return true; >- >- if (a.m_type != b.m_type) >- return false; >- if (a.m_data != b.m_data) >- return false; >-#if ENABLE(BLOB_SLICE) >- if (a.m_filename != b.m_filename || a.m_fileStart != b.m_fileStart || a.m_fileLength != b.m_fileLength || a.m_expectedFileModificationTime != b.m_expectedFileModificationTime) >-#else >- if (a.m_filename != b.m_filename) >-#endif >- return false; >- >- return true; >+ return a.item()->equals(b.item()); > } >- >+ > inline bool operator!=(const FormDataElement& a, const FormDataElement& b) > { > return !(a == b); > } >- >+ > class FormData : public RefCounted<FormData> { > public: > static PassRefPtr<FormData> create(); > static PassRefPtr<FormData> create(const void*, size_t); > static PassRefPtr<FormData> create(const WTF::CString&); > static PassRefPtr<FormData> create(const Vector<char>&); >- static PassRefPtr<FormData> create(const DOMFormData&); >- static PassRefPtr<FormData> createMultiPart(const DOMFormData&, Document*); >+ static PassRefPtr<FormData> create(const BlobItemList&, const TextEncoding&); >+ static PassRefPtr<FormData> createMultiPart(const BlobItemList&, const TextEncoding&, Document*); > PassRefPtr<FormData> copy() const; > PassRefPtr<FormData> deepCopy() const; > ~FormData(); >- >+ > void appendData(const void* data, size_t); >+ void appendItems(const BlobItemList&); >+ void appendString(const CString&); > void appendFile(const String& filename, bool shouldGenerateFile = false); > #if ENABLE(BLOB_SLICE) > void appendFileRange(const String& filename, long long start, long long length, double expectedModificationTime, bool shouldGenerateFile = false); >@@ -115,9 +131,10 @@ private: > FormData(); > FormData(const FormData&); > >- void appendDOMFormData(const DOMFormData& domFormData, bool isMultiPartForm, Document* document); >+ void appendKeyValuePairItems(const BlobItemList&, const TextEncoding&, bool isMultiPartForm, Document*); > > Vector<FormDataElement> m_elements; >+ > int64_t m_identifier; > bool m_hasGeneratedFiles; > bool m_alwaysStream; >@@ -131,7 +148,7 @@ inline bool operator==(const FormData& a, const FormData& b) > > inline bool operator!=(const FormData& a, const FormData& b) > { >- return a.elements() != b.elements(); >+ return !(a == b); > } > > } // namespace WebCore >diff --git a/WebCore/platform/network/mac/FormDataStreamMac.mm b/WebCore/platform/network/mac/FormDataStreamMac.mm >index 27ecfd08ad5aaab8756fa596d996bd2f6ec5d03f..252ddf7f97d5d8bf6d0cdd1d87528af541e07378 100644 >--- a/WebCore/platform/network/mac/FormDataStreamMac.mm >+++ b/WebCore/platform/network/mac/FormDataStreamMac.mm >@@ -31,7 +31,6 @@ > #import "config.h" > #import "FormDataStreamMac.h" > >-#import "Blob.h" > #import "FileSystem.h" > #import "FormData.h" > #import "ResourceHandle.h" >@@ -142,7 +141,7 @@ static void closeCurrentStream(FormStreamFields *form) > CFRelease(form->currentStream); > form->currentStream = NULL; > #if ENABLE(BLOB_SLICE) >- form->currentStreamRangeLength = Blob::toEndOfFile; >+ form->currentStreamRangeLength = FormDataElement::toEndOfFile; > #endif > } > if (form->currentData) { >@@ -151,7 +150,7 @@ static void closeCurrentStream(FormStreamFields *form) > } > } > >-// Return false if we cannot advance the stream. Currently the only possible failure is that the underlying file has been changed since File.slice. >+// Return false if we cannot advance the stream. Currently the only possible failure is that the underlying file has been removed or changed since File.slice. > static bool advanceCurrentStream(FormStreamFields* form) > { > closeCurrentStream(form); >@@ -161,25 +160,25 @@ static bool advanceCurrentStream(FormStreamFields* form) > > // Create the new stream. > FormDataElement& nextInput = form->remainingElements.last(); >+ >+ // Check if the underlying data has become stale (e.g. the file has been changed since its snapshot has been taken) or not. >+ if (!nextInput.m_item->isValid()) >+ return false; >+ > if (nextInput.m_type == FormDataElement::data) { > size_t size = nextInput.m_data.size(); > char* data = nextInput.m_data.releaseBuffer(); > form->currentStream = CFReadStreamCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data), size, kCFAllocatorNull); > form->currentData = data; > } else { >-#if ENABLE(BLOB_SLICE) >- // Check if the file has been changed or not if required. >- if (nextInput.m_expectedFileModificationTime != Blob::doNotCheckFileChange) { >- time_t fileModificationTime; >- if (!getFileModificationTime(nextInput.m_filename, fileModificationTime) || fileModificationTime != static_cast<time_t>(nextInput.m_expectedFileModificationTime)) >- return false; >- } >-#endif >- > const String& path = nextInput.m_shouldGenerateFile ? nextInput.m_generatedFilename : nextInput.m_filename; > RetainPtr<CFStringRef> filename(AdoptCF, path.createCFString()); > RetainPtr<CFURLRef> fileURL(AdoptCF, CFURLCreateWithFileSystemPath(0, filename.get(), kCFURLPOSIXPathStyle, FALSE)); > form->currentStream = CFReadStreamCreateWithFile(0, fileURL.get()); >+ if (!form->currentStream) { >+ // The file must have been removed or become unreadable. >+ return false; >+ } > #if ENABLE(BLOB_SLICE) > if (nextInput.m_fileStart > 0) { > CFNumberRef position = CFNumberCreate(0, kCFNumberLongLongType, &nextInput.m_fileStart); >@@ -222,7 +221,7 @@ static void* formCreate(CFReadStreamRef stream, void* context) > FormStreamFields* newInfo = new FormStreamFields; > newInfo->currentStream = NULL; > #if ENABLE(BLOB_SLICE) >- newInfo->currentStreamRangeLength = Blob::toEndOfFile; >+ newInfo->currentStreamRangeLength = FormDataElement::toEndOfFile; > #endif > newInfo->currentData = 0; > newInfo->formStream = stream; // Don't retain. That would create a reference cycle. >@@ -270,7 +269,7 @@ static CFIndex formRead(CFReadStreamRef stream, UInt8* buffer, CFIndex bufferLen > while (form->currentStream) { > CFIndex bytesToRead = bufferLength; > #if ENABLE(BLOB_SLICE) >- if (form->currentStreamRangeLength != Blob::toEndOfFile && form->currentStreamRangeLength < bytesToRead) >+ if (form->currentStreamRangeLength != FormDataElement::toEndOfFile && form->currentStreamRangeLength < bytesToRead) > bytesToRead = static_cast<CFIndex>(form->currentStreamRangeLength); > #endif > CFIndex bytesRead = CFReadStreamRead(form->currentStream, buffer, bytesToRead); >@@ -283,7 +282,7 @@ static CFIndex formRead(CFReadStreamRef stream, UInt8* buffer, CFIndex bufferLen > *atEOF = FALSE; > form->bytesSent += bytesRead; > #if ENABLE(BLOB_SLICE) >- if (form->currentStreamRangeLength != Blob::toEndOfFile) >+ if (form->currentStreamRangeLength != FormDataElement::toEndOfFile) > form->currentStreamRangeLength -= bytesRead; > #endif > >@@ -400,7 +399,7 @@ void setHTTPBody(NSMutableURLRequest *request, PassRefPtr<FormData> formData) > else { > #if ENABLE(BLOB_SLICE) > // If we're sending the file range, use the existing range length for now. We will detect if the file has been changed right before we read the file and abort the operation if necessary. >- if (element.m_fileLength != Blob::toEndOfFile) { >+ if (element.m_fileLength != FormDataElement::toEndOfFile) { > length += element.m_fileLength; > continue; > } >diff --git a/WebCore/xml/XMLHttpRequest.cpp b/WebCore/xml/XMLHttpRequest.cpp >index 5cde24de29db44210001a3023244ca4ccd25cfbb..831ada9811213942a804864da57f0a39c4bcc28e 100644 >--- a/WebCore/xml/XMLHttpRequest.cpp >+++ b/WebCore/xml/XMLHttpRequest.cpp >@@ -478,11 +478,7 @@ void XMLHttpRequest::send(Blob* body, ExceptionCode& ec) > // FIXME: Should we set a Content-Type if one is not set. > // FIXME: add support for uploading bundles. > m_requestEntityBody = FormData::create(); >-#if ENABLE(BLOB_SLICE) >- m_requestEntityBody->appendFileRange(body->path(), body->start(), body->length(), body->modificationTime()); >-#else >- m_requestEntityBody->appendFile(body->path(), false); >-#endif >+ m_requestEntityBody->appendItems(body->items()); > } > > createRequest(ec); >@@ -494,7 +490,7 @@ void XMLHttpRequest::send(DOMFormData* body, ExceptionCode& ec) > return; > > if (m_method != "GET" && m_method != "HEAD" && m_url.protocolInHTTPFamily()) { >- m_requestEntityBody = FormData::createMultiPart(*body, document()); >+ m_requestEntityBody = FormData::createMultiPart(body->items(), body->encoding(), document()); > > // We need to ask the client to provide the generated file names if needed. When FormData fills the element > // for the file, it could set a flag to use the generated file name, i.e. a package file on Mac. >diff --git a/WebKit/chromium/ChangeLog b/WebKit/chromium/ChangeLog >index 65758fd93a1bfff9b692f997cf6a9daef7133b1e..bafb15100e973a447a26102546aba9e53460e6d8 100644 >--- a/WebKit/chromium/ChangeLog >+++ b/WebKit/chromium/ChangeLog >@@ -1,3 +1,16 @@ >+2010-06-03 Kinuko Yasuda <kinuko@chromium.org> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Refactor FormData and Blob for better support of Blobs synthesized by BlobBuilder. >+ https://bugs.webkit.org/show_bug.cgi?id=39083 >+ >+ Replace FormDataList::Item list with BlobItemList to get it compiled >+ with the refactoring in FormDataList. >+ >+ * src/WebSearchableFormData.cpp: >+ (WebCore::HasSuitableTextElement): >+ > 2010-06-02 Tony Chang <tony@chromium.org> > > Reviewed by Kent Tamura. >diff --git a/WebKit/chromium/src/WebSearchableFormData.cpp b/WebKit/chromium/src/WebSearchableFormData.cpp >index 601a497382d08fbc8f0d8516f0f3aab955021f19..4ecc2e42d55e1080415a2b6f49c4ec16497a6504 100644 >--- a/WebKit/chromium/src/WebSearchableFormData.cpp >+++ b/WebKit/chromium/src/WebSearchableFormData.cpp >@@ -187,8 +187,8 @@ bool HasSuitableTextElement(const HTMLFormElement* form, Vector<char>* encodedSt > if (!formElement->appendFormData(dataList, false)) > continue; > >- const Vector<FormDataList::Item>& itemList = dataList.list(); >- if (isTextElement && !itemList.isEmpty()) { >+ const BlobItemList& items = dataList.items(); >+ if (isTextElement && !items.isEmpty()) { > if (textElement) { > // The auto-complete bar only knows how to fill in one value. > // This form has multiple fields; don't treat it as searchable. >@@ -196,20 +196,23 @@ bool HasSuitableTextElement(const HTMLFormElement* form, Vector<char>* encodedSt > } > textElement = static_cast<HTMLInputElement*>(formElement); > } >- for (Vector<FormDataList::Item>::const_iterator j(itemList.begin()); j != itemList.end(); ++j) { >+ for (BlobItemList::const_iterator j(items.begin()); j != items.end(); ++j) { >+ const StringBlobItem* item = (*j)->toStringBlobItem(); >+ if (!item) >+ continue; > // Handle ISINDEX / <input name=isindex> specially, but only if it's > // the first entry. >- if (!encodedString->isEmpty() || j->data() != "isindex") { >+ if (!encodedString->isEmpty() || item->cstr() != "isindex") { > if (!encodedString->isEmpty()) > encodedString->append('&'); >- FormDataBuilder::encodeStringAsFormData(*encodedString, j->data()); >+ FormDataBuilder::encodeStringAsFormData(*encodedString, item->cstr()); > encodedString->append('='); > } > ++j; > if (formElement == textElement) > encodedString->append("{searchTerms}", 13); > else >- FormDataBuilder::encodeStringAsFormData(*encodedString, j->data()); >+ FormDataBuilder::encodeStringAsFormData(*encodedString, item->cstr()); > } > } >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 39083
:
56030
|
56034
|
56085
|
56283
|
56286
|
56304
|
56305
|
56524
|
56609
|
56610
|
56706
|
56709
|
56861
|
57016
|
57018
|
57069
|
57080
|
57831
|
57922
|
57930