diff options
Diffstat (limited to 'WebCore/fileapi')
42 files changed, 805 insertions, 493 deletions
diff --git a/WebCore/fileapi/AsyncFileWriterClient.h b/WebCore/fileapi/AsyncFileWriterClient.h index 327b19c..929f523 100644 --- a/WebCore/fileapi/AsyncFileWriterClient.h +++ b/WebCore/fileapi/AsyncFileWriterClient.h @@ -33,7 +33,7 @@ #if ENABLE(FILE_SYSTEM) -#include "ExceptionCode.h" +#include "FileError.h" namespace WebCore { @@ -43,7 +43,7 @@ public: virtual void didWrite(long long bytes, bool complete) = 0; virtual void didTruncate() = 0; - virtual void didFail(ExceptionCode) = 0; + virtual void didFail(FileError::ErrorCode) = 0; }; } // namespace diff --git a/WebCore/fileapi/BlobBuilder.cpp b/WebCore/fileapi/BlobBuilder.cpp index 69443a5..9406899 100644 --- a/WebCore/fileapi/BlobBuilder.cpp +++ b/WebCore/fileapi/BlobBuilder.cpp @@ -32,12 +32,16 @@ #include "BlobBuilder.h" +#include "ArrayBuffer.h" #include "Blob.h" #include "ExceptionCode.h" #include "File.h" #include "LineEnding.h" #include "TextEncoding.h" +#include <wtf/PassRefPtr.h> +#include <wtf/Vector.h> #include <wtf/text/AtomicString.h> +#include <wtf/text/CString.h> namespace WebCore { @@ -46,46 +50,57 @@ BlobBuilder::BlobBuilder() { } -bool BlobBuilder::append(const String& text, const String& endingType, ExceptionCode& ec) +Vector<char>& BlobBuilder::getBuffer() +{ + // If the last item is not a data item, create one. Otherwise, we simply append the new string to the last data item. + if (m_items.isEmpty() || m_items[m_items.size() - 1].type != BlobDataItem::Data) + m_items.append(BlobDataItem(RawData::create())); + + return *m_items[m_items.size() - 1].data->mutableData(); +} + +void BlobBuilder::append(const String& text, const String& endingType, ExceptionCode& ec) { bool isEndingTypeTransparent = endingType == "transparent"; bool isEndingTypeNative = endingType == "native"; if (!endingType.isEmpty() && !isEndingTypeTransparent && !isEndingTypeNative) { ec = SYNTAX_ERR; - return 0; + return; } CString utf8Text = UTF8Encoding().encode(text.characters(), text.length(), EntitiesForUnencodables); - // If the last item is not a data item, create one. Otherwise, we simply append the new string to the last data item. - if (m_items.isEmpty() || m_items[m_items.size() - 1].type != BlobDataItem::Data) - m_items.append(BlobDataItem(RawData::create())); - - if (!utf8Text.isNull()) { - Vector<char>& buffer = *m_items[m_items.size() - 1].data->mutableData(); - size_t oldSize = buffer.size(); + Vector<char>& buffer = getBuffer(); + size_t oldSize = buffer.size(); - if (isEndingTypeNative) - normalizeLineEndingsToNative(utf8Text, buffer); - else - buffer.append(utf8Text.data(), utf8Text.length()); - m_size += buffer.size() - oldSize; - } + if (isEndingTypeNative) + normalizeLineEndingsToNative(utf8Text, buffer); + else + buffer.append(utf8Text.data(), utf8Text.length()); + m_size += buffer.size() - oldSize; +} - return true; +void BlobBuilder::append(const String& text, ExceptionCode& ec) +{ + append(text, String(), ec); } -bool BlobBuilder::append(const String& text, ExceptionCode& ec) +#if ENABLE(BLOB) +void BlobBuilder::append(ArrayBuffer* arrayBuffer) { - return append(text, String(), ec); + Vector<char>& buffer = getBuffer(); + size_t oldSize = buffer.size(); + buffer.append(static_cast<const char*>(arrayBuffer->data()), arrayBuffer->byteLength()); + m_size += buffer.size() - oldSize; } +#endif -bool BlobBuilder::append(PassRefPtr<Blob> blob) +void BlobBuilder::append(Blob* blob) { if (blob->isFile()) { // If the blob is file that is not snapshoted, capture the snapshot now. // FIXME: This involves synchronous file operation. We need to figure out how to make it asynchronous. - File* file = static_cast<File*>(blob.get()); + File* file = static_cast<File*>(blob); long long snapshotSize; double snapshotModificationTime; file->captureSnapshot(snapshotSize, snapshotModificationTime); @@ -97,7 +112,6 @@ bool BlobBuilder::append(PassRefPtr<Blob> blob) m_size += blobSize; m_items.append(BlobDataItem(blob->url(), 0, blobSize)); } - return true; } PassRefPtr<Blob> BlobBuilder::getBlob(const String& contentType) diff --git a/WebCore/fileapi/BlobBuilder.h b/WebCore/fileapi/BlobBuilder.h index a981e31..db46591 100644 --- a/WebCore/fileapi/BlobBuilder.h +++ b/WebCore/fileapi/BlobBuilder.h @@ -32,14 +32,12 @@ #define BlobBuilder_h #include "BlobData.h" -#include "PlatformString.h" -#include <wtf/PassRefPtr.h> +#include <wtf/Forward.h> #include <wtf/RefCounted.h> -#include <wtf/Vector.h> -#include <wtf/text/CString.h> namespace WebCore { +class ArrayBuffer; class Blob; class TextEncoding; @@ -49,15 +47,20 @@ class BlobBuilder : public RefCounted<BlobBuilder> { public: static PassRefPtr<BlobBuilder> create() { return adoptRef(new BlobBuilder()); } - bool append(PassRefPtr<Blob>); - bool append(const String& text, ExceptionCode&); - bool append(const String& text, const String& ending, ExceptionCode&); + void append(Blob*); + void append(const String& text, ExceptionCode&); + void append(const String& text, const String& ending, ExceptionCode&); +#if ENABLE(BLOB) + void append(ArrayBuffer*); +#endif PassRefPtr<Blob> getBlob(const String& contentType = String()); private: BlobBuilder(); + Vector<char>& getBuffer(); + long long m_size; BlobDataItemList m_items; }; diff --git a/WebCore/fileapi/BlobBuilder.idl b/WebCore/fileapi/BlobBuilder.idl index 0da9314..8f5049f 100644 --- a/WebCore/fileapi/BlobBuilder.idl +++ b/WebCore/fileapi/BlobBuilder.idl @@ -38,6 +38,9 @@ module html { Blob getBlob(in [Optional, ConvertUndefinedOrNullToNullString] DOMString contentType); #endif void append(in Blob blob); +#if defined(ENABLE_BLOB) && ENABLE_BLOB + void append(in ArrayBuffer arrayBuffer); +#endif void append(in DOMString value, in [Optional, ConvertUndefinedOrNullToNullString] DOMString endings) raises (DOMException); }; diff --git a/WebCore/fileapi/DOMFileSystemBase.cpp b/WebCore/fileapi/DOMFileSystemBase.cpp index fefe99f..c462c3c 100644 --- a/WebCore/fileapi/DOMFileSystemBase.cpp +++ b/WebCore/fileapi/DOMFileSystemBase.cpp @@ -35,6 +35,7 @@ #include "DOMFilePath.h" #include "DirectoryEntry.h" +#include "DirectoryReaderBase.h" #include "EntriesCallback.h" #include "EntryArray.h" #include "EntryBase.h" @@ -190,7 +191,7 @@ bool DOMFileSystemBase::getDirectory(const EntryBase* base, const String& path, return true; } -bool DOMFileSystemBase::readDirectory(DirectoryReaderBase* reader, const String& path, PassRefPtr<EntriesCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback) +bool DOMFileSystemBase::readDirectory(PassRefPtr<DirectoryReaderBase> reader, const String& path, PassRefPtr<EntriesCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback) { ASSERT(DOMFilePath::isAbsolute(path)); String platformPath = m_asyncFileSystem->virtualToPlatformPath(path); diff --git a/WebCore/fileapi/DOMFileSystemBase.h b/WebCore/fileapi/DOMFileSystemBase.h index 36e35b4..66f1331 100644 --- a/WebCore/fileapi/DOMFileSystemBase.h +++ b/WebCore/fileapi/DOMFileSystemBase.h @@ -72,7 +72,7 @@ public: bool getParent(const EntryBase*, PassRefPtr<EntryCallback>, PassRefPtr<ErrorCallback>); bool getFile(const EntryBase*, const String& path, PassRefPtr<Flags>, PassRefPtr<EntryCallback>, PassRefPtr<ErrorCallback>); bool getDirectory(const EntryBase*, const String& path, PassRefPtr<Flags>, PassRefPtr<EntryCallback>, PassRefPtr<ErrorCallback>); - bool readDirectory(DirectoryReaderBase*, const String& path, PassRefPtr<EntriesCallback>, PassRefPtr<ErrorCallback>); + bool readDirectory(PassRefPtr<DirectoryReaderBase>, const String& path, PassRefPtr<EntriesCallback>, PassRefPtr<ErrorCallback>); protected: DOMFileSystemBase(const String& name, PassOwnPtr<AsyncFileSystem>); diff --git a/WebCore/fileapi/DirectoryEntry.cpp b/WebCore/fileapi/DirectoryEntry.cpp index 765fcd5..7bc0af8 100644 --- a/WebCore/fileapi/DirectoryEntry.cpp +++ b/WebCore/fileapi/DirectoryEntry.cpp @@ -41,7 +41,7 @@ namespace WebCore { -DirectoryEntry::DirectoryEntry(DOMFileSystemBase* fileSystem, const String& fullPath) +DirectoryEntry::DirectoryEntry(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) : Entry(fileSystem, fullPath) { } @@ -55,21 +55,21 @@ void DirectoryEntry::getFile(const String& path, PassRefPtr<Flags> flags, PassRe { RefPtr<ErrorCallback> errorCallback(errorCallbackRef); if (!m_fileSystem->getFile(this, path, flags, successCallback, errorCallback)) - filesystem()->scheduleCallback(errorCallback.release(), FileError::create(INVALID_MODIFICATION_ERR)); + filesystem()->scheduleCallback(errorCallback.release(), FileError::create(FileError::INVALID_MODIFICATION_ERR)); } void DirectoryEntry::getDirectory(const String& path, PassRefPtr<Flags> flags, PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallbackRef) { RefPtr<ErrorCallback> errorCallback(errorCallbackRef); if (!m_fileSystem->getDirectory(this, path, flags, successCallback, errorCallback)) - filesystem()->scheduleCallback(errorCallback.release(), FileError::create(INVALID_MODIFICATION_ERR)); + filesystem()->scheduleCallback(errorCallback.release(), FileError::create(FileError::INVALID_MODIFICATION_ERR)); } void DirectoryEntry::removeRecursively(PassRefPtr<VoidCallback> successCallback, PassRefPtr<ErrorCallback> errorCallbackRef) const { RefPtr<ErrorCallback> errorCallback(errorCallbackRef); if (!m_fileSystem->removeRecursively(this, successCallback, errorCallback)) - filesystem()->scheduleCallback(errorCallback.release(), FileError::create(INVALID_MODIFICATION_ERR)); + filesystem()->scheduleCallback(errorCallback.release(), FileError::create(FileError::INVALID_MODIFICATION_ERR)); } } diff --git a/WebCore/fileapi/DirectoryEntry.h b/WebCore/fileapi/DirectoryEntry.h index dd0159e..da903da 100644 --- a/WebCore/fileapi/DirectoryEntry.h +++ b/WebCore/fileapi/DirectoryEntry.h @@ -49,7 +49,7 @@ class VoidCallback; class DirectoryEntry : public Entry { public: - static PassRefPtr<DirectoryEntry> create(DOMFileSystemBase* fileSystem, const String& fullPath) + static PassRefPtr<DirectoryEntry> create(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) { return adoptRef(new DirectoryEntry(fileSystem, fullPath)); } @@ -61,7 +61,7 @@ public: void removeRecursively(PassRefPtr<VoidCallback> successCallback = 0, PassRefPtr<ErrorCallback> = 0) const; private: - DirectoryEntry(DOMFileSystemBase*, const String& fullPath); + DirectoryEntry(PassRefPtr<DOMFileSystemBase>, const String& fullPath); }; } // namespace diff --git a/WebCore/fileapi/DirectoryEntrySync.cpp b/WebCore/fileapi/DirectoryEntrySync.cpp index d8d22c2..e68f7be 100644 --- a/WebCore/fileapi/DirectoryEntrySync.cpp +++ b/WebCore/fileapi/DirectoryEntrySync.cpp @@ -36,11 +36,12 @@ #include "DirectoryReaderSync.h" #include "EntrySync.h" #include "FileEntrySync.h" +#include "FileException.h" #include "SyncCallbackHelper.h" namespace WebCore { -DirectoryEntrySync::DirectoryEntrySync(DOMFileSystemBase* fileSystem, const String& fullPath) +DirectoryEntrySync::DirectoryEntrySync(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) : EntrySync(fileSystem, fullPath) { } @@ -55,7 +56,7 @@ PassRefPtr<FileEntrySync> DirectoryEntrySync::getFile(const String& path, PassRe ec = 0; EntrySyncCallbackHelper helper(m_fileSystem->asyncFileSystem()); if (!m_fileSystem->getFile(this, path, flags, helper.successCallback(), helper.errorCallback())) { - ec = INVALID_MODIFICATION_ERR; + ec = FileException::INVALID_MODIFICATION_ERR; return 0; } return static_pointer_cast<FileEntrySync>(helper.getResult(ec)); @@ -66,7 +67,7 @@ PassRefPtr<DirectoryEntrySync> DirectoryEntrySync::getDirectory(const String& pa ec = 0; EntrySyncCallbackHelper helper(m_fileSystem->asyncFileSystem()); if (!m_fileSystem->getDirectory(this, path, flags, helper.successCallback(), helper.errorCallback())) { - ec = INVALID_MODIFICATION_ERR; + ec = FileException::INVALID_MODIFICATION_ERR; return 0; } return static_pointer_cast<DirectoryEntrySync>(helper.getResult(ec)); @@ -77,7 +78,7 @@ void DirectoryEntrySync::removeRecursively(ExceptionCode& ec) ec = 0; VoidSyncCallbackHelper helper(m_fileSystem->asyncFileSystem()); if (!m_fileSystem->removeRecursively(this, helper.successCallback(), helper.errorCallback())) { - ec = INVALID_MODIFICATION_ERR; + ec = FileException::INVALID_MODIFICATION_ERR; return; } helper.getResult(ec); diff --git a/WebCore/fileapi/DirectoryEntrySync.h b/WebCore/fileapi/DirectoryEntrySync.h index 9a3e0df..eb412bb 100644 --- a/WebCore/fileapi/DirectoryEntrySync.h +++ b/WebCore/fileapi/DirectoryEntrySync.h @@ -46,7 +46,7 @@ class FileEntrySync; class DirectoryEntrySync : public EntrySync { public: - static PassRefPtr<DirectoryEntrySync> create(DOMFileSystemBase* fileSystem, const String& fullPath) + static PassRefPtr<DirectoryEntrySync> create(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) { return adoptRef(new DirectoryEntrySync(fileSystem, fullPath)); } @@ -59,7 +59,7 @@ public: private: friend class EntrySync; - DirectoryEntrySync(DOMFileSystemBase*, const String& fullPath); + DirectoryEntrySync(PassRefPtr<DOMFileSystemBase>, const String& fullPath); }; } diff --git a/WebCore/fileapi/DirectoryReader.cpp b/WebCore/fileapi/DirectoryReader.cpp index 3437675..fe2d99f 100644 --- a/WebCore/fileapi/DirectoryReader.cpp +++ b/WebCore/fileapi/DirectoryReader.cpp @@ -40,7 +40,7 @@ namespace WebCore { -DirectoryReader::DirectoryReader(DOMFileSystemBase* fileSystem, const String& fullPath) +DirectoryReader::DirectoryReader(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) : DirectoryReaderBase(fileSystem, fullPath) { } diff --git a/WebCore/fileapi/DirectoryReader.h b/WebCore/fileapi/DirectoryReader.h index 806fdf1..bc89858 100644 --- a/WebCore/fileapi/DirectoryReader.h +++ b/WebCore/fileapi/DirectoryReader.h @@ -47,17 +47,17 @@ class ErrorCallback; class DirectoryReader : public DirectoryReaderBase { public: - static PassRefPtr<DirectoryReader> create(DOMFileSystemBase* fileSystem, const String& fullPath) + static PassRefPtr<DirectoryReader> create(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) { return adoptRef(new DirectoryReader(fileSystem, fullPath)); } void readEntries(PassRefPtr<EntriesCallback>, PassRefPtr<ErrorCallback> = 0); - DOMFileSystem* filesystem() const { return static_cast<DOMFileSystem*>(m_fileSystem); } + DOMFileSystem* filesystem() const { return static_cast<DOMFileSystem*>(m_fileSystem.get()); } private: - DirectoryReader(DOMFileSystemBase*, const String& fullPath); + DirectoryReader(PassRefPtr<DOMFileSystemBase>, const String& fullPath); }; } diff --git a/WebCore/fileapi/DirectoryReaderBase.h b/WebCore/fileapi/DirectoryReaderBase.h index 5a2c048..4096fe8 100644 --- a/WebCore/fileapi/DirectoryReaderBase.h +++ b/WebCore/fileapi/DirectoryReaderBase.h @@ -42,18 +42,18 @@ namespace WebCore { class DirectoryReaderBase : public RefCounted<DirectoryReaderBase> { public: - DOMFileSystemBase* filesystem() const { return m_fileSystem; } + DOMFileSystemBase* filesystem() const { return m_fileSystem.get(); } void setHasMoreEntries(bool hasMoreEntries) { m_hasMoreEntries = hasMoreEntries; } protected: - DirectoryReaderBase(DOMFileSystemBase* fileSystem, const String& fullPath) + DirectoryReaderBase(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) : m_fileSystem(fileSystem) , m_fullPath(fullPath) , m_hasMoreEntries(true) { } - DOMFileSystemBase* m_fileSystem; + RefPtr<DOMFileSystemBase> m_fileSystem; // This is a virtual path. String m_fullPath; diff --git a/WebCore/fileapi/DirectoryReaderSync.cpp b/WebCore/fileapi/DirectoryReaderSync.cpp index 6c66a15..15cdaa8 100644 --- a/WebCore/fileapi/DirectoryReaderSync.cpp +++ b/WebCore/fileapi/DirectoryReaderSync.cpp @@ -39,12 +39,12 @@ #include "EntrySync.h" #include "ExceptionCode.h" #include "FileEntrySync.h" -#include "FileError.h" +#include "FileException.h" #include "SyncCallbackHelper.h" namespace WebCore { -DirectoryReaderSync::DirectoryReaderSync(DOMFileSystemBase* fileSystem, const String& fullPath) +DirectoryReaderSync::DirectoryReaderSync(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) : DirectoryReaderBase(fileSystem, fullPath) { } @@ -57,7 +57,7 @@ PassRefPtr<EntryArraySync> DirectoryReaderSync::readEntries(ExceptionCode& ec) EntriesSyncCallbackHelper helper(m_fileSystem->asyncFileSystem()); if (!m_fileSystem->readDirectory(this, m_fullPath, helper.successCallback(), helper.errorCallback())) { - ec = INVALID_MODIFICATION_ERR; + ec = FileException::INVALID_MODIFICATION_ERR; setHasMoreEntries(false); return 0; } diff --git a/WebCore/fileapi/DirectoryReaderSync.h b/WebCore/fileapi/DirectoryReaderSync.h index 39119b7..5e3d61b 100644 --- a/WebCore/fileapi/DirectoryReaderSync.h +++ b/WebCore/fileapi/DirectoryReaderSync.h @@ -43,7 +43,7 @@ namespace WebCore { class DirectoryReaderSync : public DirectoryReaderBase { public: - static PassRefPtr<DirectoryReaderSync> create(DOMFileSystemBase* fileSystem, const String& fullPath) + static PassRefPtr<DirectoryReaderSync> create(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) { return adoptRef(new DirectoryReaderSync(fileSystem, fullPath)); } @@ -51,7 +51,7 @@ public: PassRefPtr<EntryArraySync> readEntries(ExceptionCode&); private: - DirectoryReaderSync(DOMFileSystemBase*, const String& fullPath); + DirectoryReaderSync(PassRefPtr<DOMFileSystemBase>, const String& fullPath); }; } // namespace diff --git a/WebCore/fileapi/Entry.cpp b/WebCore/fileapi/Entry.cpp index 2183b33..9c3fa4e 100644 --- a/WebCore/fileapi/Entry.cpp +++ b/WebCore/fileapi/Entry.cpp @@ -42,7 +42,7 @@ namespace WebCore { -Entry::Entry(DOMFileSystemBase* fileSystem, const String& fullPath) +Entry::Entry(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) : EntryBase(fileSystem, fullPath) { } @@ -51,35 +51,35 @@ void Entry::getMetadata(PassRefPtr<MetadataCallback> successCallback, PassRefPtr { RefPtr<ErrorCallback> errorCallback(errorCallbackRef); if (!m_fileSystem->getMetadata(this, successCallback, errorCallback)) - filesystem()->scheduleCallback(errorCallback.release(), FileError::create(INVALID_MODIFICATION_ERR)); + filesystem()->scheduleCallback(errorCallback.release(), FileError::create(FileError::INVALID_MODIFICATION_ERR)); } void Entry::moveTo(PassRefPtr<DirectoryEntry> parent, const String& name, PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallbackRef) const { RefPtr<ErrorCallback> errorCallback(errorCallbackRef); if (!m_fileSystem->move(this, parent.get(), name, successCallback, errorCallback)) - filesystem()->scheduleCallback(errorCallback.release(), FileError::create(INVALID_MODIFICATION_ERR)); + filesystem()->scheduleCallback(errorCallback.release(), FileError::create(FileError::INVALID_MODIFICATION_ERR)); } void Entry::copyTo(PassRefPtr<DirectoryEntry> parent, const String& name, PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallbackRef) const { RefPtr<ErrorCallback> errorCallback(errorCallbackRef); if (!m_fileSystem->copy(this, parent.get(), name, successCallback, errorCallback)) - filesystem()->scheduleCallback(errorCallback.release(), FileError::create(INVALID_MODIFICATION_ERR)); + filesystem()->scheduleCallback(errorCallback.release(), FileError::create(FileError::INVALID_MODIFICATION_ERR)); } void Entry::remove(PassRefPtr<VoidCallback> successCallback, PassRefPtr<ErrorCallback> errorCallbackRef) const { RefPtr<ErrorCallback> errorCallback(errorCallbackRef); if (!m_fileSystem->remove(this, successCallback, errorCallback)) - filesystem()->scheduleCallback(errorCallback.release(), FileError::create(INVALID_MODIFICATION_ERR)); + filesystem()->scheduleCallback(errorCallback.release(), FileError::create(FileError::INVALID_MODIFICATION_ERR)); } void Entry::getParent(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallbackRef) const { RefPtr<ErrorCallback> errorCallback(errorCallbackRef); if (!m_fileSystem->getParent(this, successCallback, errorCallback)) - filesystem()->scheduleCallback(errorCallback.release(), FileError::create(INVALID_MODIFICATION_ERR)); + filesystem()->scheduleCallback(errorCallback.release(), FileError::create(FileError::INVALID_MODIFICATION_ERR)); } String Entry::toURI(const String&) diff --git a/WebCore/fileapi/Entry.h b/WebCore/fileapi/Entry.h index 36f85eb..9367f4f 100644 --- a/WebCore/fileapi/Entry.h +++ b/WebCore/fileapi/Entry.h @@ -49,7 +49,7 @@ class VoidCallback; class Entry : public EntryBase { public: - DOMFileSystem* filesystem() const { return static_cast<DOMFileSystem*>(m_fileSystem); } + DOMFileSystem* filesystem() const { return static_cast<DOMFileSystem*>(m_fileSystem.get()); } void getMetadata(PassRefPtr<MetadataCallback> successCallback = 0, PassRefPtr<ErrorCallback> errorCallback = 0); void moveTo(PassRefPtr<DirectoryEntry> parent, const String& name = String(), PassRefPtr<EntryCallback> successCallback = 0, PassRefPtr<ErrorCallback> errorCallback = 0) const; @@ -60,7 +60,7 @@ public: String toURI(const String& mimeType = String()); protected: - Entry(DOMFileSystemBase*, const String& fullPath); + Entry(PassRefPtr<DOMFileSystemBase>, const String& fullPath); }; } // namespace WebCore diff --git a/WebCore/fileapi/EntryBase.h b/WebCore/fileapi/EntryBase.h index 2aaeba8..16f93ba 100644 --- a/WebCore/fileapi/EntryBase.h +++ b/WebCore/fileapi/EntryBase.h @@ -48,7 +48,7 @@ class EntryBase : public RefCounted<EntryBase> { public: virtual ~EntryBase() { } - DOMFileSystemBase* filesystem() const { return m_fileSystem; } + DOMFileSystemBase* filesystem() const { return m_fileSystem.get(); } virtual bool isFile() const { return false; } virtual bool isDirectory() const { return false; } @@ -57,7 +57,7 @@ public: const String& name() const { return m_name; } protected: - EntryBase(DOMFileSystemBase* fileSystem, const String& fullPath) + EntryBase(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) : m_fileSystem(fileSystem) , m_fullPath(fullPath) , m_name(DOMFilePath::getName(fullPath)) @@ -66,7 +66,7 @@ protected: friend class EntrySync; - DOMFileSystemBase* m_fileSystem; + RefPtr<DOMFileSystemBase> m_fileSystem; // This is a virtual path. String m_fullPath; diff --git a/WebCore/fileapi/EntrySync.cpp b/WebCore/fileapi/EntrySync.cpp index ad007db..299aeda 100644 --- a/WebCore/fileapi/EntrySync.cpp +++ b/WebCore/fileapi/EntrySync.cpp @@ -38,6 +38,7 @@ #include "DirectoryEntry.h" #include "DirectoryEntrySync.h" #include "FileEntrySync.h" +#include "FileException.h" #include "Metadata.h" #include "SyncCallbackHelper.h" @@ -55,7 +56,7 @@ PassRefPtr<Metadata> EntrySync::getMetadata(ExceptionCode& ec) ec = 0; MetadataSyncCallbackHelper helper(m_fileSystem->asyncFileSystem()); if (!m_fileSystem->getMetadata(this, helper.successCallback(), helper.errorCallback())) { - ec = INVALID_MODIFICATION_ERR; + ec = FileException::INVALID_MODIFICATION_ERR; return 0; } return helper.getResult(ec); @@ -66,7 +67,7 @@ PassRefPtr<EntrySync> EntrySync::moveTo(PassRefPtr<DirectoryEntrySync> parent, c ec = 0; EntrySyncCallbackHelper helper(m_fileSystem->asyncFileSystem()); if (!m_fileSystem->move(this, parent.get(), name, helper.successCallback(), helper.errorCallback())) { - ec = INVALID_MODIFICATION_ERR; + ec = FileException::INVALID_MODIFICATION_ERR; return 0; } return helper.getResult(ec); @@ -77,7 +78,7 @@ PassRefPtr<EntrySync> EntrySync::copyTo(PassRefPtr<DirectoryEntrySync> parent, c ec = 0; EntrySyncCallbackHelper helper(m_fileSystem->asyncFileSystem()); if (!m_fileSystem->copy(this, parent.get(), name, helper.successCallback(), helper.errorCallback())) { - ec = INVALID_MODIFICATION_ERR; + ec = FileException::INVALID_MODIFICATION_ERR; return 0; } return helper.getResult(ec); @@ -88,7 +89,7 @@ void EntrySync::remove(ExceptionCode& ec) const ec = 0; VoidSyncCallbackHelper helper(m_fileSystem->asyncFileSystem()); if (!m_fileSystem->remove(this, helper.successCallback(), helper.errorCallback())) { - ec = INVALID_MODIFICATION_ERR; + ec = FileException::INVALID_MODIFICATION_ERR; return; } helper.getResult(ec); @@ -101,7 +102,7 @@ PassRefPtr<EntrySync> EntrySync::getParent() const return DirectoryEntrySync::create(m_fileSystem, parentPath); } -EntrySync::EntrySync(DOMFileSystemBase* fileSystem, const String& fullPath) +EntrySync::EntrySync(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) : EntryBase(fileSystem, fullPath) { } diff --git a/WebCore/fileapi/EntrySync.h b/WebCore/fileapi/EntrySync.h index 24a0101..175d591 100644 --- a/WebCore/fileapi/EntrySync.h +++ b/WebCore/fileapi/EntrySync.h @@ -49,7 +49,7 @@ class EntrySync : public EntryBase { public: static PassRefPtr<EntrySync> create(EntryBase*); - DOMFileSystemSync* filesystem() const { return static_cast<DOMFileSystemSync*>(m_fileSystem); } + DOMFileSystemSync* filesystem() const { return static_cast<DOMFileSystemSync*>(m_fileSystem.get()); } PassRefPtr<Metadata> getMetadata(ExceptionCode&); PassRefPtr<EntrySync> moveTo(PassRefPtr<DirectoryEntrySync> parent, const String& name, ExceptionCode&) const; @@ -58,7 +58,7 @@ public: PassRefPtr<EntrySync> getParent() const; protected: - EntrySync(DOMFileSystemBase*, const String& fullPath); + EntrySync(PassRefPtr<DOMFileSystemBase>, const String& fullPath); }; } diff --git a/WebCore/fileapi/FileEntry.cpp b/WebCore/fileapi/FileEntry.cpp index 29cbd33..a5ecff5 100644 --- a/WebCore/fileapi/FileEntry.cpp +++ b/WebCore/fileapi/FileEntry.cpp @@ -41,7 +41,7 @@ namespace WebCore { -FileEntry::FileEntry(DOMFileSystemBase* fileSystem, const String& fullPath) +FileEntry::FileEntry(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) : Entry(fileSystem, fullPath) { } diff --git a/WebCore/fileapi/FileEntry.h b/WebCore/fileapi/FileEntry.h index 216cca2..2fa4394 100644 --- a/WebCore/fileapi/FileEntry.h +++ b/WebCore/fileapi/FileEntry.h @@ -43,7 +43,7 @@ class DOMFileSystemBase; class FileEntry : public Entry { public: - static PassRefPtr<FileEntry> create(DOMFileSystemBase* fileSystem, const String& fullPath) + static PassRefPtr<FileEntry> create(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) { return adoptRef(new FileEntry(fileSystem, fullPath)); } @@ -54,7 +54,7 @@ public: virtual bool isFile() const { return true; } private: - FileEntry(DOMFileSystemBase* fileSystem, const String& fullPath); + FileEntry(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath); }; } // namespace diff --git a/WebCore/fileapi/FileEntrySync.cpp b/WebCore/fileapi/FileEntrySync.cpp index 8fc5a77..36ec735 100644 --- a/WebCore/fileapi/FileEntrySync.cpp +++ b/WebCore/fileapi/FileEntrySync.cpp @@ -37,7 +37,7 @@ namespace WebCore { -FileEntrySync::FileEntrySync(DOMFileSystemBase* fileSystem, const String& fullPath) +FileEntrySync::FileEntrySync(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) : EntrySync(fileSystem, fullPath) { } diff --git a/WebCore/fileapi/FileEntrySync.h b/WebCore/fileapi/FileEntrySync.h index d027f63..be12e21 100644 --- a/WebCore/fileapi/FileEntrySync.h +++ b/WebCore/fileapi/FileEntrySync.h @@ -44,7 +44,7 @@ class File; class FileEntrySync : public EntrySync { public: - static PassRefPtr<FileEntrySync> create(DOMFileSystemBase* fileSystem, const String& fullPath) + static PassRefPtr<FileEntrySync> create(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) { return adoptRef(new FileEntrySync(fileSystem, fullPath)); } @@ -55,7 +55,7 @@ public: private: friend class EntrySync; - FileEntrySync(DOMFileSystemBase*, const String& fullPath); + FileEntrySync(PassRefPtr<DOMFileSystemBase>, const String& fullPath); }; } diff --git a/WebCore/fileapi/FileError.h b/WebCore/fileapi/FileError.h index 3528109..27ad397 100644 --- a/WebCore/fileapi/FileError.h +++ b/WebCore/fileapi/FileError.h @@ -33,7 +33,6 @@ #if ENABLE(BLOB) || ENABLE(FILE_SYSTEM) -#include "ExceptionCode.h" #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> @@ -41,16 +40,31 @@ namespace WebCore { class FileError : public RefCounted<FileError> { public: - static PassRefPtr<FileError> create(ExceptionCode code) { return adoptRef(new FileError(code)); } + enum ErrorCode { + NOT_FOUND_ERR = 1, + SECURITY_ERR = 2, + ABORT_ERR = 3, + NOT_READABLE_ERR = 4, + ENCODING_ERR = 5, + NO_MODIFICATION_ALLOWED_ERR = 6, + INVALID_STATE_ERR = 7, + SYNTAX_ERR = 8, + INVALID_MODIFICATION_ERR = 9, + QUOTA_EXCEEDED_ERR = 10, + TYPE_MISMATCH_ERR = 11, + PATH_EXISTS_ERR = 12, + }; - ExceptionCode code() const { return m_code; } + static PassRefPtr<FileError> create(ErrorCode code) { return adoptRef(new FileError(code)); } + + ErrorCode code() const { return m_code; } private: - FileError(ExceptionCode code) + FileError(ErrorCode code) : m_code(code) { } - ExceptionCode m_code; + ErrorCode m_code; }; } // namespace WebCore diff --git a/WebCore/fileapi/FileError.idl b/WebCore/fileapi/FileError.idl index c5dedbe..bab815a 100644 --- a/WebCore/fileapi/FileError.idl +++ b/WebCore/fileapi/FileError.idl @@ -31,21 +31,23 @@ module html { interface [ Conditional=BLOB|FILE_SYSTEM, - DontCheckEnums, NoStaticTables ] FileError { #if !defined(LANGUAGE_OBJECTIVE_C) - const unsigned short NO_MODIFICATION_ALLOWED_ERR = 7; - const unsigned short NOT_FOUND_ERR = 8; - const unsigned short INVALID_STATE_ERR = 11; - const unsigned short SYNTAX_ERR = 12; - const unsigned short INVALID_MODIFICATION_ERR = 13; + // FIXME: Some of constant names are already defined in DOMException.h for Objective-C binding and we cannot have the same names here (they are translated into a enum in the same namespace). + const unsigned short NOT_FOUND_ERR = 1; + const unsigned short SECURITY_ERR = 2; + const unsigned short ABORT_ERR = 3; + const unsigned short NOT_READABLE_ERR = 4; + const unsigned short ENCODING_ERR = 5; + const unsigned short NO_MODIFICATION_ALLOWED_ERR = 6; + const unsigned short INVALID_STATE_ERR = 7; + const unsigned short SYNTAX_ERR = 8; + const unsigned short INVALID_MODIFICATION_ERR = 9; + const unsigned short QUOTA_EXCEEDED_ERR = 10; + const unsigned short TYPE_MISMATCH_ERR = 11; + const unsigned short PATH_EXISTS_ERR = 12; #endif - const unsigned short SECURITY_ERR = 18; - const unsigned short ABORT_ERR = 20; - const unsigned short QUOTA_EXCEEDED_ERR = 22; - const unsigned short NOT_READABLE_ERR = 24; - const unsigned short ENCODING_ERR = 26; readonly attribute unsigned short code; }; } diff --git a/WebCore/fileapi/FileException.h b/WebCore/fileapi/FileException.h index e90ab90..c3cc638 100644 --- a/WebCore/fileapi/FileException.h +++ b/WebCore/fileapi/FileException.h @@ -44,13 +44,31 @@ public: return adoptRef(new FileException(description)); } - static const int FileExceptionOffset = 100; - static const int FileExceptionMax = 199; + static const int FileExceptionOffset = 1100; + static const int FileExceptionMax = 1199; - enum EventExceptionCode { - UNSPECIFIED_EVENT_TYPE_ERR = FileExceptionOffset + enum FileExceptionCode { + NOT_FOUND_ERR = FileExceptionOffset + 1, + SECURITY_ERR = FileExceptionOffset + 2, + ABORT_ERR = FileExceptionOffset + 3, + NOT_READABLE_ERR = FileExceptionOffset + 4, + ENCODING_ERR = FileExceptionOffset + 5, + NO_MODIFICATION_ALLOWED_ERR = FileExceptionOffset + 6, + INVALID_STATE_ERR = FileExceptionOffset + 7, + SYNTAX_ERR = FileExceptionOffset + 8, + INVALID_MODIFICATION_ERR = FileExceptionOffset + 9, + QUOTA_EXCEEDED_ERR = FileExceptionOffset + 10, + TYPE_MISMATCH_ERR = FileExceptionOffset + 11, + PATH_EXISTS_ERR = FileExceptionOffset + 12, }; + static int ErrorCodeToExceptionCode(int errorCode) + { + if (!errorCode) + return 0; + return errorCode + FileExceptionOffset; + } + private: FileException(const ExceptionCodeDescription& description) : ExceptionBase(description) @@ -63,4 +81,3 @@ private: #endif // ENABLE(BLOB) || ENABLE(FILE_SYSTEM) #endif // FileException_h - diff --git a/WebCore/fileapi/FileException.idl b/WebCore/fileapi/FileException.idl index 0b2ab9c..10bd151 100644 --- a/WebCore/fileapi/FileException.idl +++ b/WebCore/fileapi/FileException.idl @@ -45,15 +45,17 @@ module html { #endif // FileExceptionCode - const unsigned short NO_MODIFICATION_ALLOWED_ERR = 7; - const unsigned short NOT_FOUND_ERR = 8; - const unsigned short INVALID_STATE_ERR = 11; - const unsigned short SYNTAX_ERR = 12; - const unsigned short INVALID_MODIFICATION_ERR = 13; - const unsigned short SECURITY_ERR = 18; - const unsigned short ABORT_ERR = 20; - const unsigned short QUOTA_EXCEEDED_ERR = 22; - const unsigned short NOT_READABLE_ERR = 24; - const unsigned short ENCODING_ERR = 26; + const unsigned short NOT_FOUND_ERR = 1; + const unsigned short SECURITY_ERR = 2; + const unsigned short ABORT_ERR = 3; + const unsigned short NOT_READABLE_ERR = 4; + const unsigned short ENCODING_ERR = 5; + const unsigned short NO_MODIFICATION_ALLOWED_ERR = 6; + const unsigned short INVALID_STATE_ERR = 7; + const unsigned short SYNTAX_ERR = 8; + const unsigned short INVALID_MODIFICATION_ERR = 9; + const unsigned short QUOTA_EXCEEDED_ERR = 10; + const unsigned short TYPE_MISMATCH_ERR = 11; + const unsigned short PATH_EXISTS_ERR = 12; }; } diff --git a/WebCore/fileapi/FileReader.cpp b/WebCore/fileapi/FileReader.cpp index 0b7b46d..a54a337 100644 --- a/WebCore/fileapi/FileReader.cpp +++ b/WebCore/fileapi/FileReader.cpp @@ -34,21 +34,17 @@ #include "FileReader.h" -#include "Base64.h" +#include "ArrayBuffer.h" #include "Blob.h" -#include "BlobURL.h" #include "CrossThreadTask.h" #include "File.h" #include "Logging.h" #include "ProgressEvent.h" -#include "ResourceError.h" -#include "ResourceRequest.h" -#include "ResourceResponse.h" #include "ScriptExecutionContext.h" -#include "TextResourceDecoder.h" -#include "ThreadableBlobRegistry.h" -#include "ThreadableLoader.h" #include <wtf/CurrentTime.h> +#include <wtf/OwnPtr.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> namespace WebCore { @@ -57,10 +53,7 @@ const double progressNotificationIntervalMS = 50; FileReader::FileReader(ScriptExecutionContext* context) : ActiveDOMObject(context, this) , m_state(None) - , m_readType(ReadFileAsBinaryString) - , m_isRawDataConverted(false) - , m_bytesLoaded(0) - , m_totalBytes(0) + , m_readType(FileReaderLoader::ReadAsBinaryString) , m_lastProgressNotificationTimeMS(0) { } @@ -86,6 +79,16 @@ void FileReader::stop() terminate(); } +void FileReader::readAsArrayBuffer(Blob* blob) +{ + if (!blob) + return; + + LOG(FileAPI, "FileReader: reading as array buffer: %s %s\n", blob->url().string().utf8().data(), blob->isFile() ? static_cast<File*>(blob)->path().utf8().data() : ""); + + readInternal(blob, FileReaderLoader::ReadAsArrayBuffer); +} + void FileReader::readAsBinaryString(Blob* blob) { if (!blob) @@ -93,7 +96,7 @@ void FileReader::readAsBinaryString(Blob* blob) LOG(FileAPI, "FileReader: reading as binary: %s %s\n", blob->url().string().utf8().data(), blob->isFile() ? static_cast<File*>(blob)->path().utf8().data() : ""); - readInternal(blob, ReadFileAsBinaryString); + readInternal(blob, FileReaderLoader::ReadAsBinaryString); } void FileReader::readAsText(Blob* blob, const String& encoding) @@ -103,9 +106,8 @@ void FileReader::readAsText(Blob* blob, const String& encoding) LOG(FileAPI, "FileReader: reading as text: %s %s\n", blob->url().string().utf8().data(), blob->isFile() ? static_cast<File*>(blob)->path().utf8().data() : ""); - if (!encoding.isEmpty()) - m_encoding = TextEncoding(encoding); - readInternal(blob, ReadFileAsText); + m_encoding = encoding; + readInternal(blob, FileReaderLoader::ReadAsText); } void FileReader::readAsDataURL(Blob* blob) @@ -115,8 +117,7 @@ void FileReader::readAsDataURL(Blob* blob) LOG(FileAPI, "FileReader: reading as data URL: %s %s\n", blob->url().string().utf8().data(), blob->isFile() ? static_cast<File*>(blob)->path().utf8().data() : ""); - m_fileType = blob->type(); - readInternal(blob, ReadFileAsDataURL); + readInternal(blob, FileReaderLoader::ReadAsDataURL); } static void delayedStart(ScriptExecutionContext*, FileReader* reader) @@ -124,7 +125,7 @@ static void delayedStart(ScriptExecutionContext*, FileReader* reader) reader->start(); } -void FileReader::readInternal(Blob* blob, ReadType type) +void FileReader::readInternal(Blob* blob, FileReaderLoader::ReadType type) { // readAs*** methods() can be called multiple times. Only the last call before the actual reading happens is processed. if (m_state != None && m_state != Starting) @@ -138,14 +139,28 @@ void FileReader::readInternal(Blob* blob, ReadType type) m_state = Starting; } +static void delayedAbort(ScriptExecutionContext*, FileReader* reader) +{ + reader->doAbort(); +} + void FileReader::abort() { LOG(FileAPI, "FileReader: aborting\n"); + if (m_state == Aborting) + return; + m_state = Aborting; + + // Schedule to have the abort done later since abort() might be called from the event handler and we do not want the resource loading code to be in the stack. + scriptExecutionContext()->postTask(createCallbackTask(&delayedAbort, this)); +} + +void FileReader::doAbort() +{ terminate(); - m_builder.clear(); - m_error = FileError::create(ABORT_ERR); + m_error = FileError::create(FileError::ABORT_ERR); fireEvent(eventNames().errorEvent); fireEvent(eventNames().abortEvent); @@ -156,75 +171,29 @@ void FileReader::terminate() { if (m_loader) { m_loader->cancel(); - cleanup(); + m_loader = 0; } m_state = Completed; } -void FileReader::cleanup() -{ - m_loader = 0; - ThreadableBlobRegistry::unregisterBlobURL(m_urlForReading); - m_urlForReading = KURL(); -} - void FileReader::start() { m_state = Opening; - // The blob is read by routing through the request handling layer given a temporary public url. - m_urlForReading = BlobURL::createPublicURL(scriptExecutionContext()->securityOrigin()); - ThreadableBlobRegistry::registerBlobURL(m_urlForReading, m_blob->url()); - - ResourceRequest request(m_urlForReading); - request.setHTTPMethod("GET"); - - ThreadableLoaderOptions options; - options.sendLoadCallbacks = true; - options.sniffContent = false; - options.forcePreflight = false; - options.allowCredentials = true; - options.crossOriginRequestPolicy = DenyCrossOriginRequests; - - m_loader = ThreadableLoader::create(scriptExecutionContext(), this, request, options); + m_loader = adoptPtr(new FileReaderLoader(m_readType, this)); + m_loader->setEncoding(m_encoding); + m_loader->setDataType(m_blob->type()); + m_loader->start(scriptExecutionContext(), m_blob.get()); } -void FileReader::didReceiveResponse(const ResourceResponse& response) +void FileReader::didStartLoading() { - if (response.httpStatusCode() != 200) { - failed(response.httpStatusCode()); - return; - } - m_state = Reading; fireEvent(eventNames().loadstartEvent); - - m_totalBytes = response.expectedContentLength(); } -void FileReader::didReceiveData(const char* data, int lengthReceived) +void FileReader::didReceiveData() { - ASSERT(data && lengthReceived); - - // Bail out if we have aborted the reading. - if (m_state == Completed) - return; - - switch (m_readType) { - case ReadFileAsBinaryString: - m_builder.append(data, static_cast<unsigned>(lengthReceived)); - break; - case ReadFileAsText: - case ReadFileAsDataURL: - m_rawData.append(data, static_cast<unsigned>(lengthReceived)); - m_isRawDataConverted = false; - break; - default: - ASSERT_NOT_REACHED(); - } - - m_bytesLoaded += lengthReceived; - // Fire the progress event at least every 50ms. double now = WTF::currentTimeMS(); if (!m_lastProgressNotificationTimeMS) @@ -235,49 +204,33 @@ void FileReader::didReceiveData(const char* data, int lengthReceived) } } -void FileReader::didFinishLoading(unsigned long) +void FileReader::didFinishLoading() { m_state = Completed; fireEvent(eventNames().loadEvent); fireEvent(eventNames().loadendEvent); - - cleanup(); } -void FileReader::didFail(const ResourceError&) +void FileReader::didFail(int errorCode) { - // Treat as internal error. - failed(500); -} + // If we're aborting, do not proceed with normal error handling since it is covered in aborting code. + if (m_state == Aborting) + return; -void FileReader::failed(int httpStatusCode) -{ m_state = Completed; - m_error = FileError::create(httpStatusCodeToExceptionCode(httpStatusCode)); + m_error = FileError::create(static_cast<FileError::ErrorCode>(errorCode)); fireEvent(eventNames().errorEvent); fireEvent(eventNames().loadendEvent); - - cleanup(); -} - -ExceptionCode FileReader::httpStatusCodeToExceptionCode(int httpStatusCode) -{ - switch (httpStatusCode) { - case 403: - return SECURITY_ERR; - case 404: - return NOT_FOUND_ERR; - default: - return NOT_READABLE_ERR; - } } void FileReader::fireEvent(const AtomicString& type) { // FIXME: the current ProgressEvent uses "unsigned long" for total and loaded attributes. Need to talk with the spec writer to resolve the issue. - dispatchEvent(ProgressEvent::create(type, true, static_cast<unsigned>(m_bytesLoaded), static_cast<unsigned>(m_totalBytes))); + unsigned bytesLoaded = m_loader ? m_loader->bytesLoaded() : 0; + unsigned totalBytes = m_loader ? m_loader->totalBytes() : 0; + dispatchEvent(ProgressEvent::create(type, true, bytesLoaded, totalBytes)); } FileReader::ReadyState FileReader::readyState() const @@ -288,6 +241,7 @@ FileReader::ReadyState FileReader::readyState() const return EMPTY; case Opening: case Reading: + case Aborting: return LOADING; case Completed: return DONE; @@ -296,65 +250,14 @@ FileReader::ReadyState FileReader::readyState() const return EMPTY; } -String FileReader::result() -{ - // If reading as binary string, we can return the result immediately. - if (m_readType == ReadFileAsBinaryString) - return m_builder.toString(); - - // If we already convert the raw data received so far, we can return the result now. - if (m_isRawDataConverted) - return m_builder.toString(); - m_isRawDataConverted = true; - - if (m_readType == ReadFileAsText) - convertToText(); - // For data URL, we only do the coversion until we receive all the raw data. - else if (m_readType == ReadFileAsDataURL && m_state == Completed) - convertToDataURL(m_rawData, m_fileType, m_builder); - - return m_builder.toString(); -} - -void FileReader::convertToText() +PassRefPtr<ArrayBuffer> FileReader::arrayBufferResult() const { - if (!m_rawData.size()) { - m_builder.clear(); - return; - } - - // Decode the data. - // The File API spec says that we should use the supplied encoding if it is valid. However, we choose to ignore this - // requirement in order to be consistent with how WebKit decodes the web content: always has the BOM override the - // provided encoding. - // FIXME: consider supporting incremental decoding to improve the perf. - if (!m_decoder) - m_decoder = TextResourceDecoder::create("text/plain", m_encoding.isValid() ? m_encoding : UTF8Encoding()); - m_builder.clear(); - m_builder.append(m_decoder->decode(&m_rawData.at(0), m_rawData.size())); - - if (m_state == Completed && !m_error) - m_builder.append(m_decoder->flush()); + return m_loader ? m_loader->arrayBufferResult() : 0; } -void FileReader::convertToDataURL(const Vector<char>& rawData, const String& fileType, StringBuilder& builder) +String FileReader::stringResult() { - builder.clear(); - builder.append("data:"); - - if (!rawData.size()) - return; - - if (!fileType.isEmpty()) { - builder.append(fileType); - builder.append(";base64,"); - } else - builder.append("base64,"); - - Vector<char> out; - base64Encode(rawData, out); - out.append('\0'); - builder.append(out.data()); + return m_loader ? m_loader->stringResult() : ""; } } // namespace WebCore diff --git a/WebCore/fileapi/FileReader.h b/WebCore/fileapi/FileReader.h index f914dad..04513f3 100644 --- a/WebCore/fileapi/FileReader.h +++ b/WebCore/fileapi/FileReader.h @@ -36,24 +36,19 @@ #include "ActiveDOMObject.h" #include "EventTarget.h" #include "FileError.h" -#include "KURL.h" -#include "TextEncoding.h" -#include "ThreadableLoaderClient.h" -#include <wtf/PassRefPtr.h> +#include "FileReaderLoader.h" +#include "FileReaderLoaderClient.h" +#include <wtf/Forward.h> #include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> -#include <wtf/Vector.h> -#include <wtf/text/StringBuilder.h> #include <wtf/text/WTFString.h> namespace WebCore { +class ArrayBuffer; class Blob; class ScriptExecutionContext; -class TextResourceDecoder; -class ThreadableLoader; -class FileReader : public RefCounted<FileReader>, public ActiveDOMObject, public EventTarget, public ThreadableLoaderClient { +class FileReader : public RefCounted<FileReader>, public ActiveDOMObject, public EventTarget, public FileReaderLoaderClient { public: static PassRefPtr<FileReader> create(ScriptExecutionContext* context) { @@ -68,20 +63,20 @@ public: DONE = 2 }; + void readAsArrayBuffer(Blob*); void readAsBinaryString(Blob*); void readAsText(Blob*, const String& encoding = ""); void readAsDataURL(Blob*); void abort(); void start(); + void doAbort(); ReadyState readyState() const; PassRefPtr<FileError> error() { return m_error; } - String result(); - - // Helper methods, also used by FileReaderSync. - static ExceptionCode httpStatusCodeToExceptionCode(int httpStatusCode); - static void convertToDataURL(const Vector<char>& rawData, const String& fileType, StringBuilder&); + FileReaderLoader::ReadType readType() const { return m_readType; } + PassRefPtr<ArrayBuffer> arrayBufferResult() const; + String stringResult(); // ActiveDOMObject virtual bool canSuspend() const; @@ -92,11 +87,11 @@ public: virtual FileReader* toFileReader() { return this; } virtual ScriptExecutionContext* scriptExecutionContext() const { return ActiveDOMObject::scriptExecutionContext(); } - // ThreadableLoaderClient - virtual void didReceiveResponse(const ResourceResponse&); - virtual void didReceiveData(const char*, int); - virtual void didFinishLoading(unsigned long identifier); - virtual void didFail(const ResourceError&); + // FileReaderLoaderClient + virtual void didStartLoading(); + virtual void didReceiveData(); + virtual void didFinishLoading(); + virtual void didFail(int errorCode); using RefCounted<FileReader>::ref; using RefCounted<FileReader>::deref; @@ -109,16 +104,12 @@ public: DEFINE_ATTRIBUTE_EVENT_LISTENER(loadend); private: - enum ReadType { - ReadFileAsBinaryString, - ReadFileAsText, - ReadFileAsDataURL - }; enum InternalState { None, Starting, Opening, Reading, + Aborting, Completed }; @@ -131,38 +122,19 @@ private: virtual EventTargetData* ensureEventTargetData() { return &m_eventTargetData; } void terminate(); - void cleanup(); - void readInternal(Blob*, ReadType); - void failed(int httpStatusCode); + void readInternal(Blob*, FileReaderLoader::ReadType); void fireErrorEvent(int httpStatusCode); void fireEvent(const AtomicString& type); - void convertToText(); - void convertToDataURL(); InternalState m_state; EventTargetData m_eventTargetData; RefPtr<Blob> m_blob; - KURL m_urlForReading; - ReadType m_readType; - TextEncoding m_encoding; - - StringBuilder m_builder; - - // The raw data. We have to keep track of all the raw data for it to be converted to text or data URL data. - Vector<char> m_rawData; - bool m_isRawDataConverted; - - // The decoder used to decode the text data. - RefPtr<TextResourceDecoder> m_decoder; - - // Needed to create data URL. - String m_fileType; + FileReaderLoader::ReadType m_readType; + String m_encoding; - RefPtr<ThreadableLoader> m_loader; + OwnPtr<FileReaderLoader> m_loader; RefPtr<FileError> m_error; - long long m_bytesLoaded; - long long m_totalBytes; double m_lastProgressNotificationTimeMS; }; diff --git a/WebCore/fileapi/FileReader.idl b/WebCore/fileapi/FileReader.idl index febb231..ebc6ffd 100644 --- a/WebCore/fileapi/FileReader.idl +++ b/WebCore/fileapi/FileReader.idl @@ -44,6 +44,7 @@ module html { readonly attribute unsigned short readyState; // async read methods + void readAsArrayBuffer(in Blob blob); void readAsBinaryString(in Blob blob); void readAsText(in Blob blob, in [Optional] DOMString encoding); void readAsDataURL(in Blob blob); @@ -51,7 +52,7 @@ module html { void abort(); // file data - readonly attribute [ConvertScriptString] DOMString result; + readonly attribute [Custom] DOMObject result; readonly attribute FileError error; diff --git a/WebCore/fileapi/FileReaderLoader.cpp b/WebCore/fileapi/FileReaderLoader.cpp new file mode 100644 index 0000000..dcd5860 --- /dev/null +++ b/WebCore/fileapi/FileReaderLoader.cpp @@ -0,0 +1,302 @@ +/* + * 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" + +#if ENABLE(BLOB) + +#include "FileReaderLoader.h" + +#include "ArrayBuffer.h" +#include "Base64.h" +#include "Blob.h" +#include "BlobURL.h" +#include "FileReaderLoaderClient.h" +#include "ResourceRequest.h" +#include "ResourceResponse.h" +#include "ScriptExecutionContext.h" +#include "TextResourceDecoder.h" +#include "ThreadableBlobRegistry.h" +#include "ThreadableLoader.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> +#include <wtf/Vector.h> +#include <wtf/text/StringBuilder.h> + +namespace WebCore { + +FileReaderLoader::FileReaderLoader(ReadType readType, FileReaderLoaderClient* client) + : m_readType(readType) + , m_client(client) + , m_isRawDataConverted(false) + , m_stringResult("") + , m_bytesLoaded(0) + , m_totalBytes(0) + , m_errorCode(0) +{ +} + +FileReaderLoader::~FileReaderLoader() +{ + terminate(); + ThreadableBlobRegistry::unregisterBlobURL(m_urlForReading); +} + +void FileReaderLoader::start(ScriptExecutionContext* scriptExecutionContext, Blob* blob) +{ + // The blob is read by routing through the request handling layer given a temporary public url. + m_urlForReading = BlobURL::createPublicURL(scriptExecutionContext->securityOrigin()); + ThreadableBlobRegistry::registerBlobURL(m_urlForReading, blob->url()); + + // Construct and load the request. + ResourceRequest request(m_urlForReading); + request.setHTTPMethod("GET"); + + ThreadableLoaderOptions options; + options.sendLoadCallbacks = true; + options.sniffContent = false; + options.forcePreflight = false; + options.allowCredentials = true; + options.crossOriginRequestPolicy = DenyCrossOriginRequests; + + if (m_client) + m_loader = ThreadableLoader::create(scriptExecutionContext, this, request, options); + else + ThreadableLoader::loadResourceSynchronously(scriptExecutionContext, request, *this, options); +} + +void FileReaderLoader::cancel() +{ + m_errorCode = FileError::ABORT_ERR; + terminate(); +} + +void FileReaderLoader::terminate() +{ + if (m_loader) { + m_loader->cancel(); + cleanup(); + } +} + +void FileReaderLoader::cleanup() +{ + m_loader = 0; + + // If we get any error, we do not need to keep a buffer around. + if (m_errorCode) { + m_rawData = 0; + m_stringResult = ""; + } +} + +void FileReaderLoader::didReceiveResponse(const ResourceResponse& response) +{ + if (response.httpStatusCode() != 200) { + failed(httpStatusCodeToErrorCode(response.httpStatusCode())); + return; + } + + // FIXME: Support reading more than the current size limit of ArrayBuffer. + if (static_cast<unsigned long long>(response.expectedContentLength()) > std::numeric_limits<unsigned>::max()) { + failed(FileError::NOT_READABLE_ERR); + return; + } + m_totalBytes = static_cast<unsigned>(response.expectedContentLength()); + + ASSERT(!m_rawData); + m_rawData = ArrayBuffer::create(static_cast<unsigned>(m_totalBytes), 1); + + if (m_client) + m_client->didStartLoading(); +} + +void FileReaderLoader::didReceiveData(const char* data, int lengthReceived) +{ + ASSERT(data && lengthReceived > 0); + + // Bail out if we encounter an error. + if (m_errorCode) + return; + + memcpy(static_cast<char*>(m_rawData->data()) + static_cast<unsigned>(m_bytesLoaded), data, static_cast<unsigned>(lengthReceived)); + m_bytesLoaded += static_cast<unsigned>(lengthReceived); + + m_isRawDataConverted = false; + + if (m_client) + m_client->didReceiveData(); +} + +void FileReaderLoader::didFinishLoading(unsigned long) +{ + cleanup(); + if (m_client) + m_client->didFinishLoading(); +} + +void FileReaderLoader::didFail(const ResourceError&) +{ + // If we're aborting, do not proceed with normal error handling since it is covered in aborting code. + if (m_errorCode == FileError::ABORT_ERR) + return; + + failed(FileError::NOT_READABLE_ERR); +} + +void FileReaderLoader::failed(int errorCode) +{ + m_errorCode = errorCode; + cleanup(); + if (m_client) + m_client->didFail(m_errorCode); +} + +FileError::ErrorCode FileReaderLoader::httpStatusCodeToErrorCode(int httpStatusCode) +{ + switch (httpStatusCode) { + case 403: + return FileError::SECURITY_ERR; + case 404: + return FileError::NOT_FOUND_ERR; + default: + return FileError::NOT_READABLE_ERR; + } +} + +PassRefPtr<ArrayBuffer> FileReaderLoader::arrayBufferResult() const +{ + ASSERT(m_readType == ReadAsArrayBuffer); + + // If the loading is not started or an error occurs, return an empty result. + if (!m_rawData || m_errorCode) + return 0; + + // If completed, we can simply return our buffer. + if (isCompleted()) + return m_rawData; + + // Otherwise, return a copy. + return ArrayBuffer::create(m_rawData.get()); +} + +String FileReaderLoader::stringResult() +{ + ASSERT(m_readType != ReadAsArrayBuffer); + + // If the loading is not started or an error occurs, return an empty result. + if (!m_rawData || m_errorCode) + return m_stringResult; + + // If already converted from the raw data, return the result now. + if (m_isRawDataConverted) + return m_stringResult; + + switch (m_readType) { + case ReadAsArrayBuffer: + // No conversion is needed. + break; + case ReadAsBinaryString: + m_stringResult = String(static_cast<const char*>(m_rawData->data()), m_bytesLoaded); + break; + case ReadAsText: + convertToText(); + break; + case ReadAsDataURL: + // Partial data is not supported when reading as data URL. + if (isCompleted()) + convertToDataURL(); + break; + default: + ASSERT_NOT_REACHED(); + } + + return m_stringResult; +} + +void FileReaderLoader::convertToText() +{ + if (!m_bytesLoaded) + return; + + // Decode the data. + // The File API spec says that we should use the supplied encoding if it is valid. However, we choose to ignore this + // requirement in order to be consistent with how WebKit decodes the web content: always has the BOM override the + // provided encoding. + // FIXME: consider supporting incremental decoding to improve the perf. + StringBuilder builder; + if (!m_decoder) + m_decoder = TextResourceDecoder::create("text/plain", m_encoding.isValid() ? m_encoding : UTF8Encoding()); + builder.append(m_decoder->decode(static_cast<const char*>(m_rawData->data()), m_bytesLoaded)); + + if (isCompleted()) + builder.append(m_decoder->flush()); + + m_stringResult = builder.toString(); +} + +void FileReaderLoader::convertToDataURL() +{ + StringBuilder builder; + builder.append("data:"); + + if (!m_bytesLoaded) { + m_stringResult = builder.toString(); + return; + } + + if (!m_dataType.isEmpty()) { + builder.append(m_dataType); + builder.append(";base64,"); + } else + builder.append("base64,"); + + Vector<char> out; + base64Encode(static_cast<const char*>(m_rawData->data()), m_bytesLoaded, out); + out.append('\0'); + builder.append(out.data()); + + m_stringResult = builder.toString(); +} + +bool FileReaderLoader::isCompleted() const +{ + return m_bytesLoaded == m_totalBytes; +} + +void FileReaderLoader::setEncoding(const String& encoding) +{ + if (!encoding.isEmpty()) + m_encoding = TextEncoding(encoding); +} + +} // namespace WebCore + +#endif // ENABLE(BLOB) diff --git a/WebCore/fileapi/FileReaderLoader.h b/WebCore/fileapi/FileReaderLoader.h new file mode 100644 index 0000000..a15ee01 --- /dev/null +++ b/WebCore/fileapi/FileReaderLoader.h @@ -0,0 +1,119 @@ +/* + * 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 FileReaderLoader_h +#define FileReaderLoader_h + +#if ENABLE(BLOB) + +#include "FileError.h" +#include "KURL.h" +#include "TextEncoding.h" +#include "ThreadableLoaderClient.h" +#include <wtf/Forward.h> +#include <wtf/text/WTFString.h> + +namespace WebCore { + +class ArrayBuffer; +class Blob; +class FileReaderLoaderClient; +class ScriptExecutionContext; +class TextResourceDecoder; +class ThreadableLoader; + +class FileReaderLoader : public ThreadableLoaderClient { +public: + enum ReadType { + ReadAsArrayBuffer, + ReadAsBinaryString, + ReadAsText, + ReadAsDataURL + }; + + // If client is given, do the loading asynchronously. Otherwise, load synchronously. + FileReaderLoader(ReadType, FileReaderLoaderClient*); + ~FileReaderLoader(); + + void start(ScriptExecutionContext*, Blob*); + void cancel(); + + // ThreadableLoaderClient + virtual void didReceiveResponse(const ResourceResponse&); + virtual void didReceiveData(const char*, int); + virtual void didFinishLoading(unsigned long identifier); + virtual void didFail(const ResourceError&); + + String stringResult(); + PassRefPtr<ArrayBuffer> arrayBufferResult() const; + unsigned bytesLoaded() const { return m_bytesLoaded; } + unsigned totalBytes() const { return m_totalBytes; } + int errorCode() const { return m_errorCode; } + + void setEncoding(const String&); + void setDataType(const String& dataType) { m_dataType = dataType; } + +private: + void terminate(); + void cleanup(); + void failed(int errorCode); + void convertToText(); + void convertToDataURL(); + + bool isCompleted() const; + + static FileError::ErrorCode httpStatusCodeToErrorCode(int); + + ReadType m_readType; + FileReaderLoaderClient* m_client; + TextEncoding m_encoding; + String m_dataType; + + KURL m_urlForReading; + RefPtr<ThreadableLoader> m_loader; + + RefPtr<ArrayBuffer> m_rawData; + bool m_isRawDataConverted; + + String m_stringResult; + + // The decoder used to decode the text data. + RefPtr<TextResourceDecoder> m_decoder; + + unsigned m_bytesLoaded; + unsigned m_totalBytes; + int m_errorCode; +}; + +} // namespace WebCore + +#endif // ENABLE(BLOB) + +#endif // FileReaderLoader_h diff --git a/WebCore/fileapi/FileReaderLoaderClient.h b/WebCore/fileapi/FileReaderLoaderClient.h new file mode 100644 index 0000000..4acb8ad --- /dev/null +++ b/WebCore/fileapi/FileReaderLoaderClient.h @@ -0,0 +1,52 @@ +/* + * 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 FileReaderLoaderClient_h +#define FileReaderLoaderClient_h + +#if ENABLE(BLOB) + +namespace WebCore { + +class FileReaderLoaderClient { +public: + virtual ~FileReaderLoaderClient() {} + + virtual void didStartLoading() = 0; + virtual void didReceiveData() = 0; + virtual void didFinishLoading() = 0; + virtual void didFail(int errorCode) = 0; +}; + +} // namespace WebCore + +#endif // ENABLE(BLOB) + +#endif // FileReaderLoaderClient_h diff --git a/WebCore/fileapi/FileReaderSync.cpp b/WebCore/fileapi/FileReaderSync.cpp index 6425bcf..85e7f52 100644 --- a/WebCore/fileapi/FileReaderSync.cpp +++ b/WebCore/fileapi/FileReaderSync.cpp @@ -34,161 +34,66 @@ #include "FileReaderSync.h" -#include "Base64.h" +#include "ArrayBuffer.h" #include "Blob.h" #include "BlobURL.h" -#include "FileReader.h" -#include "ResourceRequest.h" -#include "ResourceResponse.h" -#include "ScriptExecutionContext.h" -#include "TextEncoding.h" -#include "TextResourceDecoder.h" -#include "ThreadableBlobRegistry.h" -#include "ThreadableLoader.h" +#include "FileException.h" +#include "FileReaderLoader.h" +#include <wtf/PassRefPtr.h> namespace WebCore { -class FileReaderSyncLoader : public ThreadableLoaderClient { -public: - // If the output result is provided, use it. Otherwise, save it as the raw data. - FileReaderSyncLoader(StringBuilder*); - - // Returns the http status code. - void start(ScriptExecutionContext*, const ResourceRequest&, ExceptionCode&); - - // ThreadableLoaderClient - virtual void didReceiveResponse(const ResourceResponse&); - virtual void didReceiveData(const char*, int); - virtual void didFinishLoading(unsigned long identifier); - virtual void didFail(const ResourceError&); - - const Vector<char>& rawData() const { return m_rawData; } - -private: - // The output result. The caller provides this in order to load the binary data directly. - StringBuilder* m_builder; - - // The raw data. The caller does not provide the above output result and we need to save it here. - Vector<char> m_rawData; - - int m_httpStatusCode; -}; - -FileReaderSyncLoader::FileReaderSyncLoader(StringBuilder* builder) - : m_builder(builder) - , m_httpStatusCode(0) -{ -} - -void FileReaderSyncLoader::start(ScriptExecutionContext* scriptExecutionContext, const ResourceRequest& request, ExceptionCode& ec) +FileReaderSync::FileReaderSync() { - ThreadableLoaderOptions options; - options.sendLoadCallbacks = true; - options.sniffContent = false; - options.forcePreflight = false; - options.allowCredentials = true; - options.crossOriginRequestPolicy = DenyCrossOriginRequests; - - ThreadableLoader::loadResourceSynchronously(scriptExecutionContext, request, *this, options); - - ec = (m_httpStatusCode == 200) ? 0 : FileReader::httpStatusCodeToExceptionCode(m_httpStatusCode); } -void FileReaderSyncLoader::didReceiveResponse(const ResourceResponse& response) +PassRefPtr<ArrayBuffer> FileReaderSync::readAsArrayBuffer(ScriptExecutionContext* scriptExecutionContext, Blob* blob, ExceptionCode& ec) { - m_httpStatusCode = response.httpStatusCode(); -} + if (!blob) + return 0; -void FileReaderSyncLoader::didReceiveData(const char* data, int lengthReceived) -{ - if (m_builder) - m_builder->append(data, static_cast<unsigned>(lengthReceived)); - else - m_rawData.append(data, static_cast<unsigned>(lengthReceived)); -} + FileReaderLoader loader(FileReaderLoader::ReadAsArrayBuffer, 0); + startLoading(scriptExecutionContext, loader, blob, ec); -void FileReaderSyncLoader::didFinishLoading(unsigned long) -{ -} - -void FileReaderSyncLoader::didFail(const ResourceError&) -{ - // Treat as internal error. - m_httpStatusCode = 500; + return loader.arrayBufferResult(); } String FileReaderSync::readAsBinaryString(ScriptExecutionContext* scriptExecutionContext, Blob* blob, ExceptionCode& ec) { if (!blob) - return m_builder.toString(); + return String(); - read(scriptExecutionContext, blob, ReadAsBinaryString, ec); - return m_builder.toString(); + FileReaderLoader loader(FileReaderLoader::ReadAsBinaryString, 0); + startLoading(scriptExecutionContext, loader, blob, ec); + return loader.stringResult(); } String FileReaderSync::readAsText(ScriptExecutionContext* scriptExecutionContext, Blob* blob, const String& encoding, ExceptionCode& ec) { if (!blob) - return m_builder.toString(); + return String(); - m_encoding = encoding; - read(scriptExecutionContext, blob, ReadAsText, ec); - return m_builder.toString(); + FileReaderLoader loader(FileReaderLoader::ReadAsText, 0); + loader.setEncoding(encoding); + startLoading(scriptExecutionContext, loader, blob, ec); + return loader.stringResult(); } String FileReaderSync::readAsDataURL(ScriptExecutionContext* scriptExecutionContext, Blob* blob, ExceptionCode& ec) { if (!blob) - return m_builder.toString(); + return String(); - read(scriptExecutionContext, blob, ReadAsDataURL, ec); - return m_builder.toString(); -} - -void FileReaderSync::read(ScriptExecutionContext* scriptExecutionContext, Blob* blob, ReadType readType, ExceptionCode& ec) -{ - // The blob is read by routing through the request handling layer given the temporary public url. - KURL urlForReading = BlobURL::createPublicURL(scriptExecutionContext->securityOrigin()); - ThreadableBlobRegistry::registerBlobURL(urlForReading, blob->url()); - - ResourceRequest request(urlForReading); - request.setHTTPMethod("GET"); - - FileReaderSyncLoader loader((readType == ReadAsBinaryString) ? &m_builder : 0); - loader.start(scriptExecutionContext, request, ec); - ThreadableBlobRegistry::unregisterBlobURL(urlForReading); - if (ec) - return; - - switch (readType) { - case ReadAsBinaryString: - // Nothing to do since we need no conversion. - return; - case ReadAsText: - convertToText(loader.rawData().data(), loader.rawData().size(), m_builder); - return; - case ReadAsDataURL: - FileReader::convertToDataURL(loader.rawData(), blob->type(), m_builder); - return; - } - - ASSERT_NOT_REACHED(); + FileReaderLoader loader(FileReaderLoader::ReadAsDataURL, 0); + loader.setDataType(blob->type()); + startLoading(scriptExecutionContext, loader, blob, ec); + return loader.stringResult(); } -void FileReaderSync::convertToText(const char* data, int size, StringBuilder& builder) +void FileReaderSync::startLoading(ScriptExecutionContext* scriptExecutionContext, FileReaderLoader& loader, Blob* blob, ExceptionCode& ec) { - if (!size) - return; - - // Decode the data. - // The File API spec says that we should use the supplied encoding if it is valid. However, we choose to ignore this - // requirement in order to be consistent with how WebKit decodes the web content: always have the BOM override the - // provided encoding. - // FIXME: consider supporting incremental decoding to improve the perf. - RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/plain", m_encoding.isEmpty() ? UTF8Encoding() : TextEncoding(m_encoding)); - builder.clear(); - builder.append(decoder->decode(data, size)); - builder.append(decoder->flush()); + loader.start(scriptExecutionContext, blob); + ec = FileException::ErrorCodeToExceptionCode(loader.errorCode()); } } // namespace WebCore diff --git a/WebCore/fileapi/FileReaderSync.h b/WebCore/fileapi/FileReaderSync.h index cb0e00d..79b637f 100644 --- a/WebCore/fileapi/FileReaderSync.h +++ b/WebCore/fileapi/FileReaderSync.h @@ -34,13 +34,15 @@ #if ENABLE(BLOB) #include "ExceptionCode.h" -#include <wtf/PassRefPtr.h> +#include <wtf/Forward.h> #include <wtf/RefCounted.h> -#include <wtf/text/StringBuilder.h> +#include <wtf/text/WTFString.h> namespace WebCore { +class ArrayBuffer; class Blob; +class FileReaderLoader; class ScriptExecutionContext; class FileReaderSync : public RefCounted<FileReaderSync> { @@ -52,6 +54,7 @@ public: virtual ~FileReaderSync() { } + PassRefPtr<ArrayBuffer> readAsArrayBuffer(ScriptExecutionContext*, Blob*, ExceptionCode&); String readAsBinaryString(ScriptExecutionContext*, Blob*, ExceptionCode&); String readAsText(ScriptExecutionContext* scriptExecutionContext, Blob* blob, ExceptionCode& ec) { @@ -61,20 +64,9 @@ public: String readAsDataURL(ScriptExecutionContext*, Blob*, ExceptionCode&); private: - enum ReadType { - ReadAsBinaryString, - ReadAsText, - ReadAsDataURL - }; + FileReaderSync(); - FileReaderSync() { } - - void read(ScriptExecutionContext*, Blob*, ReadType, ExceptionCode&); - void convertToText(const char* data, int size, StringBuilder&); - - StringBuilder m_builder; - - String m_encoding; + void startLoading(ScriptExecutionContext*, FileReaderLoader&, Blob*, ExceptionCode&); }; } // namespace WebCore diff --git a/WebCore/fileapi/FileReaderSync.idl b/WebCore/fileapi/FileReaderSync.idl index 72818b1..381d483 100644 --- a/WebCore/fileapi/FileReaderSync.idl +++ b/WebCore/fileapi/FileReaderSync.idl @@ -34,6 +34,8 @@ module html { CanBeConstructed, NoStaticTables ] FileReaderSync { + [CallWith=ScriptExecutionContext] ArrayBuffer readAsArrayBuffer(in Blob blob) + raises(FileException); [CallWith=ScriptExecutionContext, ConvertScriptString] DOMString readAsBinaryString(in Blob blob) raises(FileException); [CallWith=ScriptExecutionContext, ConvertScriptString] DOMString readAsText(in Blob blob, in [Optional] DOMString encoding) diff --git a/WebCore/fileapi/FileSystemCallbacks.cpp b/WebCore/fileapi/FileSystemCallbacks.cpp index e5f404e..6644589 100644 --- a/WebCore/fileapi/FileSystemCallbacks.cpp +++ b/WebCore/fileapi/FileSystemCallbacks.cpp @@ -43,9 +43,9 @@ #include "EntryArray.h" #include "EntryCallback.h" #include "ErrorCallback.h" -#include "ExceptionCode.h" #include "FileEntry.h" #include "FileError.h" +#include "FileMetadata.h" #include "FileSystemCallback.h" #include "FileWriter.h" #include "FileWriterCallback.h" @@ -77,7 +77,7 @@ void FileSystemCallbacksBase::didOpenFileSystem(const String&, PassOwnPtr<AsyncF ASSERT_NOT_REACHED(); } -void FileSystemCallbacksBase::didReadMetadata(double) +void FileSystemCallbacksBase::didReadMetadata(const FileMetadata&) { // Each subclass must implement an appropriate one. ASSERT_NOT_REACHED(); @@ -104,19 +104,19 @@ void FileSystemCallbacksBase::didCreateFileWriter(PassOwnPtr<AsyncFileWriter>, l void FileSystemCallbacksBase::didFail(int code) { if (m_errorCallback) { - m_errorCallback->handleEvent(FileError::create(code).get()); + m_errorCallback->handleEvent(FileError::create(static_cast<FileError::ErrorCode>(code)).get()); m_errorCallback.clear(); } } // EntryCallbacks ------------------------------------------------------------- -PassOwnPtr<EntryCallbacks> EntryCallbacks::create(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, DOMFileSystemBase* fileSystem, const String& expectedPath, bool isDirectory) +PassOwnPtr<EntryCallbacks> EntryCallbacks::create(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DOMFileSystemBase> fileSystem, const String& expectedPath, bool isDirectory) { return adoptPtr(new EntryCallbacks(successCallback, errorCallback, fileSystem, expectedPath, isDirectory)); } -EntryCallbacks::EntryCallbacks(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, DOMFileSystemBase* fileSystem, const String& expectedPath, bool isDirectory) +EntryCallbacks::EntryCallbacks(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DOMFileSystemBase> fileSystem, const String& expectedPath, bool isDirectory) : FileSystemCallbacksBase(errorCallback) , m_successCallback(successCallback) , m_fileSystem(fileSystem) @@ -138,12 +138,12 @@ void EntryCallbacks::didSucceed() // EntriesCallbacks ----------------------------------------------------------- -PassOwnPtr<EntriesCallbacks> EntriesCallbacks::create(PassRefPtr<EntriesCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, DirectoryReaderBase* directoryReader, const String& basePath) +PassOwnPtr<EntriesCallbacks> EntriesCallbacks::create(PassRefPtr<EntriesCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DirectoryReaderBase> directoryReader, const String& basePath) { return adoptPtr(new EntriesCallbacks(successCallback, errorCallback, directoryReader, basePath)); } -EntriesCallbacks::EntriesCallbacks(PassRefPtr<EntriesCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, DirectoryReaderBase* directoryReader, const String& basePath) +EntriesCallbacks::EntriesCallbacks(PassRefPtr<EntriesCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DirectoryReaderBase> directoryReader, const String& basePath) : FileSystemCallbacksBase(errorCallback) , m_successCallback(successCallback) , m_directoryReader(directoryReader) @@ -205,10 +205,10 @@ MetadataCallbacks::MetadataCallbacks(PassRefPtr<MetadataCallback> successCallbac { } -void MetadataCallbacks::didReadMetadata(double modificationTime) +void MetadataCallbacks::didReadMetadata(const FileMetadata& metadata) { if (m_successCallback) - m_successCallback->handleEvent(Metadata::create(modificationTime).get()); + m_successCallback->handleEvent(Metadata::create(metadata.modificationTime).get()); m_successCallback.clear(); } diff --git a/WebCore/fileapi/FileSystemCallbacks.h b/WebCore/fileapi/FileSystemCallbacks.h index c600a76..100fd0c 100644 --- a/WebCore/fileapi/FileSystemCallbacks.h +++ b/WebCore/fileapi/FileSystemCallbacks.h @@ -47,6 +47,7 @@ class ErrorCallback; class EntriesCallback; class EntryArray; class EntryCallback; +struct FileMetadata; class FileSystemCallback; class FileWriter; class FileWriterCallback; @@ -65,7 +66,7 @@ public: virtual void didOpenFileSystem(const String& name, PassOwnPtr<AsyncFileSystem>); // For MetadataCallbacks. - virtual void didReadMetadata(double modificationTime); + virtual void didReadMetadata(const FileMetadata&); // For EntriesCallbacks. didReadDirectoryEntry is called each time the API reads an entry, and didReadDirectoryDone is called when a chunk of entries have been read (i.e. good time to call back to the application). If hasMore is true there can be more chunks. virtual void didReadDirectoryEntry(const String& name, bool isDirectory); @@ -86,27 +87,27 @@ protected: class EntryCallbacks : public FileSystemCallbacksBase { public: - static PassOwnPtr<EntryCallbacks> create(PassRefPtr<EntryCallback>, PassRefPtr<ErrorCallback>, DOMFileSystemBase*, const String& expectedPath, bool isDirectory); + static PassOwnPtr<EntryCallbacks> create(PassRefPtr<EntryCallback>, PassRefPtr<ErrorCallback>, PassRefPtr<DOMFileSystemBase>, const String& expectedPath, bool isDirectory); virtual void didSucceed(); private: - EntryCallbacks(PassRefPtr<EntryCallback>, PassRefPtr<ErrorCallback>, DOMFileSystemBase*, const String& expectedPath, bool isDirectory); + EntryCallbacks(PassRefPtr<EntryCallback>, PassRefPtr<ErrorCallback>, PassRefPtr<DOMFileSystemBase>, const String& expectedPath, bool isDirectory); RefPtr<EntryCallback> m_successCallback; - DOMFileSystemBase* m_fileSystem; + RefPtr<DOMFileSystemBase> m_fileSystem; String m_expectedPath; bool m_isDirectory; }; class EntriesCallbacks : public FileSystemCallbacksBase { public: - static PassOwnPtr<EntriesCallbacks> create(PassRefPtr<EntriesCallback>, PassRefPtr<ErrorCallback>, DirectoryReaderBase*, const String& basePath); + static PassOwnPtr<EntriesCallbacks> create(PassRefPtr<EntriesCallback>, PassRefPtr<ErrorCallback>, PassRefPtr<DirectoryReaderBase>, const String& basePath); virtual void didReadDirectoryEntry(const String& name, bool isDirectory); virtual void didReadDirectoryEntries(bool hasMore); private: - EntriesCallbacks(PassRefPtr<EntriesCallback>, PassRefPtr<ErrorCallback>, DirectoryReaderBase*, const String& basePath); + EntriesCallbacks(PassRefPtr<EntriesCallback>, PassRefPtr<ErrorCallback>, PassRefPtr<DirectoryReaderBase>, const String& basePath); RefPtr<EntriesCallback> m_successCallback; - DirectoryReaderBase* m_directoryReader; + RefPtr<DirectoryReaderBase> m_directoryReader; String m_basePath; RefPtr<EntryArray> m_entries; }; @@ -125,7 +126,7 @@ private: class MetadataCallbacks : public FileSystemCallbacksBase { public: static PassOwnPtr<MetadataCallbacks> create(PassRefPtr<MetadataCallback>, PassRefPtr<ErrorCallback>); - virtual void didReadMetadata(double modificationTime); + virtual void didReadMetadata(const FileMetadata&); private: MetadataCallbacks(PassRefPtr<MetadataCallback>, PassRefPtr<ErrorCallback>); diff --git a/WebCore/fileapi/FileWriter.cpp b/WebCore/fileapi/FileWriter.cpp index bc76984..7775709 100644 --- a/WebCore/fileapi/FileWriter.cpp +++ b/WebCore/fileapi/FileWriter.cpp @@ -38,6 +38,7 @@ #include "Blob.h" #include "ExceptionCode.h" #include "FileError.h" +#include "FileException.h" #include "ProgressEvent.h" namespace WebCore { @@ -90,13 +91,11 @@ void FileWriter::write(Blob* data, ExceptionCode& ec) { ASSERT(m_writer); if (m_readyState == WRITING) { - ec = INVALID_STATE_ERR; - m_error = FileError::create(ec); + setError(FileError::INVALID_STATE_ERR, ec); return; } if (!data) { - ec = TYPE_MISMATCH_ERR; - m_error = FileError::create(ec); + setError(FileError::TYPE_MISMATCH_ERR, ec); return; } @@ -112,8 +111,7 @@ void FileWriter::seek(long long position, ExceptionCode& ec) { ASSERT(m_writer); if (m_readyState == WRITING) { - ec = INVALID_STATE_ERR; - m_error = FileError::create(ec); + setError(FileError::INVALID_STATE_ERR, ec); return; } @@ -132,8 +130,7 @@ void FileWriter::truncate(long long position, ExceptionCode& ec) { ASSERT(m_writer); if (m_readyState == WRITING || position < 0) { - ec = INVALID_STATE_ERR; - m_error = FileError::create(ec); + setError(FileError::INVALID_STATE_ERR, ec); return; } m_readyState = WRITING; @@ -147,12 +144,11 @@ void FileWriter::abort(ExceptionCode& ec) { ASSERT(m_writer); if (m_readyState != WRITING) { - ec = INVALID_STATE_ERR; - m_error = FileError::create(ec); + setError(FileError::INVALID_STATE_ERR, ec); return; } - - m_error = FileError::create(ABORT_ERR); + + m_error = FileError::create(FileError::ABORT_ERR); m_writer->abort(); } @@ -191,11 +187,11 @@ void FileWriter::didTruncate() fireEvent(eventNames().writeendEvent); } -void FileWriter::didFail(ExceptionCode ec) +void FileWriter::didFail(FileError::ErrorCode code) { - m_error = FileError::create(ec); + m_error = FileError::create(code); fireEvent(eventNames().errorEvent); - if (ABORT_ERR == ec) + if (FileError::ABORT_ERR == code) fireEvent(eventNames().abortEvent); fireEvent(eventNames().errorEvent); m_blobBeingWritten.clear(); @@ -209,6 +205,12 @@ void FileWriter::fireEvent(const AtomicString& type) dispatchEvent(ProgressEvent::create(type, true, static_cast<unsigned>(m_bytesWritten), static_cast<unsigned>(m_bytesToWrite))); } +void FileWriter::setError(FileError::ErrorCode errorCode, ExceptionCode& ec) +{ + ec = FileException::ErrorCodeToExceptionCode(errorCode); + m_error = FileError::create(errorCode); +} + } // namespace WebCore - + #endif // ENABLE(FILE_SYSTEM) diff --git a/WebCore/fileapi/FileWriter.h b/WebCore/fileapi/FileWriter.h index 454081c..0e884ea 100644 --- a/WebCore/fileapi/FileWriter.h +++ b/WebCore/fileapi/FileWriter.h @@ -77,7 +77,7 @@ public: // AsyncFileWriterClient void didWrite(long long bytes, bool complete); void didTruncate(); - void didFail(ExceptionCode ec); + void didFail(FileError::ErrorCode); // ActiveDOMObject virtual bool canSuspend() const; @@ -97,7 +97,7 @@ public: DEFINE_ATTRIBUTE_EVENT_LISTENER(abort); DEFINE_ATTRIBUTE_EVENT_LISTENER(error); DEFINE_ATTRIBUTE_EVENT_LISTENER(writeend); - + private: FileWriter(ScriptExecutionContext*); @@ -113,6 +113,8 @@ private: void fireEvent(const AtomicString& type); + void setError(FileError::ErrorCode, ExceptionCode&); + RefPtr<FileError> m_error; EventTargetData m_eventTargetData; OwnPtr<AsyncFileWriter> m_writer; diff --git a/WebCore/fileapi/SyncCallbackHelper.h b/WebCore/fileapi/SyncCallbackHelper.h index 1612e93..25e6739 100644 --- a/WebCore/fileapi/SyncCallbackHelper.h +++ b/WebCore/fileapi/SyncCallbackHelper.h @@ -41,6 +41,7 @@ #include "ExceptionCode.h" #include "FileEntry.h" #include "FileError.h" +#include "FileException.h" #include "FileSystemCallback.h" #include "MetadataCallback.h" #include "VoidCallback.h" @@ -64,7 +65,7 @@ public: : m_observer(observer) , m_successCallback(SuccessCallbackImpl::create(this)) , m_errorCallback(ErrorCallbackImpl::create(this)) - , m_error(0) + , m_exceptionCode(0) , m_completed(false) { } @@ -74,12 +75,12 @@ public: if (m_observer) { while (!m_completed) { if (!m_observer->waitForOperationToComplete()) { - m_error = ABORT_ERR; + m_exceptionCode = FileException::ABORT_ERR; break; } } } - ec = m_error; + ec = m_exceptionCode; return m_result.release(); } @@ -138,9 +139,9 @@ private: friend class SuccessCallbackImpl; friend class ErrorCallbackImpl; - void setError(ExceptionCode ec) + void setError(int code) { - m_error = ec; + m_exceptionCode = FileException::ErrorCodeToExceptionCode(code); m_completed = true; } @@ -154,7 +155,7 @@ private: RefPtr<SuccessCallbackImpl> m_successCallback; RefPtr<ErrorCallbackImpl> m_errorCallback; RefPtr<ResultType> m_result; - ExceptionCode m_error; + ExceptionCode m_exceptionCode; bool m_completed; }; |