diff options
author | Steve Block <steveblock@google.com> | 2011-05-06 11:45:16 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-05-12 13:44:10 +0100 |
commit | cad810f21b803229eb11403f9209855525a25d57 (patch) | |
tree | 29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/fileapi/FileReader.cpp | |
parent | 121b0cf4517156d0ac5111caf9830c51b69bae8f (diff) | |
download | external_webkit-cad810f21b803229eb11403f9209855525a25d57.zip external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2 |
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/fileapi/FileReader.cpp')
-rw-r--r-- | Source/WebCore/fileapi/FileReader.cpp | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/Source/WebCore/fileapi/FileReader.cpp b/Source/WebCore/fileapi/FileReader.cpp new file mode 100644 index 0000000..fd2e263 --- /dev/null +++ b/Source/WebCore/fileapi/FileReader.cpp @@ -0,0 +1,259 @@ +/* + * 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 "FileReader.h" + +#include "ArrayBuffer.h" +#include "CrossThreadTask.h" +#include "File.h" +#include "Logging.h" +#include "ProgressEvent.h" +#include "ScriptExecutionContext.h" +#include <wtf/CurrentTime.h> +#include <wtf/text/CString.h> + +namespace WebCore { + +static const double progressNotificationIntervalMS = 50; + +FileReader::FileReader(ScriptExecutionContext* context) + : ActiveDOMObject(context, this) + , m_state(None) + , m_readType(FileReaderLoader::ReadAsBinaryString) + , m_lastProgressNotificationTimeMS(0) +{ +} + +FileReader::~FileReader() +{ + terminate(); +} + +bool FileReader::hasPendingActivity() const +{ + return (m_state != None && m_state != Completed) || ActiveDOMObject::hasPendingActivity(); +} + +bool FileReader::canSuspend() const +{ + // FIXME: It is not currently possible to suspend a FileReader, so pages with FileReader can not go into page cache. + return false; +} + +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) + return; + + 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, FileReaderLoader::ReadAsBinaryString); +} + +void FileReader::readAsText(Blob* blob, const String& encoding) +{ + if (!blob) + return; + + LOG(FileAPI, "FileReader: reading as text: %s %s\n", blob->url().string().utf8().data(), blob->isFile() ? static_cast<File*>(blob)->path().utf8().data() : ""); + + m_encoding = encoding; + readInternal(blob, FileReaderLoader::ReadAsText); +} + +void FileReader::readAsDataURL(Blob* blob) +{ + if (!blob) + return; + + LOG(FileAPI, "FileReader: reading as data URL: %s %s\n", blob->url().string().utf8().data(), blob->isFile() ? static_cast<File*>(blob)->path().utf8().data() : ""); + + readInternal(blob, FileReaderLoader::ReadAsDataURL); +} + +static void delayedStart(ScriptExecutionContext*, FileReader* reader) +{ + reader->start(); +} + +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) + return; + + if (m_state == None) + scriptExecutionContext()->postTask(createCallbackTask(&delayedStart, this)); + + m_blob = blob; + m_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_error = FileError::create(FileError::ABORT_ERR); + + fireEvent(eventNames().errorEvent); + fireEvent(eventNames().abortEvent); + fireEvent(eventNames().loadendEvent); +} + +void FileReader::terminate() +{ + if (m_loader) { + m_loader->cancel(); + m_loader = 0; + } + m_state = Completed; +} + +void FileReader::start() +{ + m_state = Opening; + + 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::didStartLoading() +{ + m_state = Reading; + fireEvent(eventNames().loadstartEvent); +} + +void FileReader::didReceiveData() +{ + // Fire the progress event at least every 50ms. + double now = currentTimeMS(); + if (!m_lastProgressNotificationTimeMS) + m_lastProgressNotificationTimeMS = now; + else if (now - m_lastProgressNotificationTimeMS > progressNotificationIntervalMS) { + fireEvent(eventNames().progressEvent); + m_lastProgressNotificationTimeMS = now; + } +} + +void FileReader::didFinishLoading() +{ + m_state = Completed; + + fireEvent(eventNames().loadEvent); + fireEvent(eventNames().loadendEvent); +} + +void FileReader::didFail(int errorCode) +{ + // If we're aborting, do not proceed with normal error handling since it is covered in aborting code. + if (m_state == Aborting) + return; + + m_state = Completed; + + m_error = FileError::create(static_cast<FileError::ErrorCode>(errorCode)); + fireEvent(eventNames().errorEvent); + fireEvent(eventNames().loadendEvent); +} + +void FileReader::fireEvent(const AtomicString& type) +{ + dispatchEvent(ProgressEvent::create(type, true, m_loader ? m_loader->bytesLoaded() : 0, m_loader ? m_loader->totalBytes() : 0)); +} + +FileReader::ReadyState FileReader::readyState() const +{ + switch (m_state) { + case None: + case Starting: + return EMPTY; + case Opening: + case Reading: + case Aborting: + return LOADING; + case Completed: + return DONE; + } + ASSERT_NOT_REACHED(); + return EMPTY; +} + +PassRefPtr<ArrayBuffer> FileReader::arrayBufferResult() const +{ + return m_loader ? m_loader->arrayBufferResult() : 0; +} + +String FileReader::stringResult() +{ + return m_loader ? m_loader->stringResult() : ""; +} + +} // namespace WebCore + +#endif // ENABLE(BLOB) |