summaryrefslogtreecommitdiff
path: root/Source/WebCore/fileapi
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2016-05-24 08:28:08 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2016-05-24 08:28:08 +0000
commita4e969f4965059196ca948db781e52f7cfebf19e (patch)
tree6ca352808c8fdc52006a0f33f6ae3c593b23867d /Source/WebCore/fileapi
parent41386e9cb918eed93b3f13648cbef387e371e451 (diff)
downloadWebKitGtk-tarball-a4e969f4965059196ca948db781e52f7cfebf19e.tar.gz
webkitgtk-2.12.3webkitgtk-2.12.3
Diffstat (limited to 'Source/WebCore/fileapi')
-rw-r--r--Source/WebCore/fileapi/AsyncFileStream.cpp266
-rw-r--r--Source/WebCore/fileapi/AsyncFileStream.h41
-rw-r--r--Source/WebCore/fileapi/Blob.cpp173
-rw-r--r--Source/WebCore/fileapi/Blob.h49
-rw-r--r--Source/WebCore/fileapi/Blob.idl3
-rw-r--r--Source/WebCore/fileapi/BlobURL.cpp2
-rw-r--r--Source/WebCore/fileapi/BlobURL.h2
-rw-r--r--Source/WebCore/fileapi/File.cpp104
-rw-r--r--Source/WebCore/fileapi/File.h79
-rw-r--r--Source/WebCore/fileapi/File.idl2
-rw-r--r--Source/WebCore/fileapi/FileError.h8
-rw-r--r--Source/WebCore/fileapi/FileError.idl2
-rw-r--r--Source/WebCore/fileapi/FileException.cpp9
-rw-r--r--Source/WebCore/fileapi/FileException.h8
-rw-r--r--Source/WebCore/fileapi/FileException.idl2
-rw-r--r--Source/WebCore/fileapi/FileList.h21
-rw-r--r--Source/WebCore/fileapi/FileList.idl1
-rw-r--r--Source/WebCore/fileapi/FileReader.cpp63
-rw-r--r--Source/WebCore/fileapi/FileReader.h24
-rw-r--r--Source/WebCore/fileapi/FileReader.idl26
-rw-r--r--Source/WebCore/fileapi/FileReaderLoader.cpp65
-rw-r--r--Source/WebCore/fileapi/FileReaderLoader.h6
-rw-r--r--Source/WebCore/fileapi/FileReaderLoaderClient.h4
-rw-r--r--Source/WebCore/fileapi/FileReaderSync.cpp9
-rw-r--r--Source/WebCore/fileapi/FileReaderSync.h10
-rw-r--r--Source/WebCore/fileapi/FileReaderSync.idl2
-rw-r--r--Source/WebCore/fileapi/FileThread.cpp117
-rw-r--r--Source/WebCore/fileapi/FileThread.h88
-rw-r--r--Source/WebCore/fileapi/FileThreadTask.h206
-rw-r--r--Source/WebCore/fileapi/ThreadableBlobRegistry.cpp143
-rw-r--r--Source/WebCore/fileapi/ThreadableBlobRegistry.h13
-rw-r--r--Source/WebCore/fileapi/WebKitBlobBuilder.cpp81
-rw-r--r--Source/WebCore/fileapi/WebKitBlobBuilder.h22
33 files changed, 502 insertions, 1149 deletions
diff --git a/Source/WebCore/fileapi/AsyncFileStream.cpp b/Source/WebCore/fileapi/AsyncFileStream.cpp
index 374fac0e3..0fb9124e1 100644
--- a/Source/WebCore/fileapi/AsyncFileStream.cpp
+++ b/Source/WebCore/fileapi/AsyncFileStream.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Google Inc. All rights reserved.
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -30,211 +30,185 @@
*/
#include "config.h"
-
-#if ENABLE(BLOB)
-
#include "AsyncFileStream.h"
-#include "Blob.h"
#include "FileStream.h"
#include "FileStreamClient.h"
-#include "FileThread.h"
-#include "FileThreadTask.h"
-#include "MainThreadTask.h"
+#include "URL.h"
+#include <wtf/AutodrainedPool.h>
#include <wtf/MainThread.h>
-#include <wtf/text/WTFString.h>
-
-#if PLATFORM(IOS)
-#include "WebCoreThread.h"
-#endif
+#include <wtf/MessageQueue.h>
+#include <wtf/NeverDestroyed.h>
namespace WebCore {
-static PassRefPtr<FileThread> createFileThread()
-{
- RefPtr<FileThread> thread = FileThread::create();
- if (!thread->start())
- return 0;
- return thread.release();
-}
+struct AsyncFileStream::Internals {
+ explicit Internals(FileStreamClient&);
+
+ FileStream stream;
+ FileStreamClient& client;
+#if !COMPILER(MSVC)
+ std::atomic_bool destroyed { false };
+#else
+ std::atomic_bool destroyed;
+#endif
+};
-static FileThread* fileThread()
+inline AsyncFileStream::Internals::Internals(FileStreamClient& client)
+ : client(client)
{
- ASSERT(isMainThread());
- static FileThread* thread = createFileThread().leakRef();
- return thread;
+#if COMPILER(MSVC)
+ // Work around a bug that prevents the default value above from compiling.
+ atomic_init(&destroyed, false);
+#endif
}
-inline AsyncFileStream::AsyncFileStream(FileStreamClient* client)
- : m_stream(FileStream::create())
- , m_client(client)
+static void callOnFileThread(std::function<void()>&& function)
{
ASSERT(isMainThread());
-}
+ ASSERT(function);
-PassRefPtr<AsyncFileStream> AsyncFileStream::create(FileStreamClient* client)
-{
- RefPtr<AsyncFileStream> proxy = adoptRef(new AsyncFileStream(client));
+ static NeverDestroyed<MessageQueue<std::function<void()>>> queue;
- // Hold a reference so that the instance will not get deleted while there are tasks on the file thread.
- // This is balanced by the deref in derefProxyOnContext below.
- proxy->ref();
+ static std::once_flag createFileThreadOnce;
+ std::call_once(createFileThreadOnce, [] {
+ createThread("WebCore: AsyncFileStream", [] {
+ for (;;) {
+ AutodrainedPool pool;
- fileThread()->postTask(createFileThreadTask(proxy.get(), &AsyncFileStream::startOnFileThread));
+ auto function = queue.get().waitForMessage();
- return proxy.release();
-}
+ // This can never be null because we never kill the MessageQueue.
+ ASSERT(function);
-AsyncFileStream::~AsyncFileStream()
-{
-}
+ // This can bever be null because we never queue a function that is null.
+ ASSERT(*function);
-static void didStart(AsyncFileStream* proxy)
-{
- if (proxy->client())
- proxy->client()->didStart();
-}
+ (*function)();
+ }
+ });
+ });
-void AsyncFileStream::startOnFileThread()
-{
- // FIXME: It is not correct to check m_client from a secondary thread - stop() could be racing with this check.
- if (!m_client)
- return;
- m_stream->start();
- callOnMainThread(didStart, AllowCrossThreadAccess(this));
+ queue.get().append(std::make_unique<std::function<void()>>(WTFMove(function)));
}
-void AsyncFileStream::stop()
+AsyncFileStream::AsyncFileStream(FileStreamClient& client)
+ : m_internals(std::make_unique<Internals>(client))
{
- // Clear the client so that we won't be invoking callbacks on the client.
- setClient(0);
-
- fileThread()->unscheduleTasks(m_stream.get());
- fileThread()->postTask(createFileThreadTask(this, &AsyncFileStream::stopOnFileThread));
+ ASSERT(isMainThread());
}
-static void derefProxyOnMainThread(AsyncFileStream* proxy)
+AsyncFileStream::~AsyncFileStream()
{
- ASSERT(proxy->hasOneRef());
- proxy->deref();
-}
+ ASSERT(isMainThread());
-void AsyncFileStream::stopOnFileThread()
-{
- m_stream->stop();
- callOnMainThread(derefProxyOnMainThread, AllowCrossThreadAccess(this));
-}
+ // Release so that we can control the timing of deletion below.
+ auto& internals = *m_internals.release();
-static void didGetSize(AsyncFileStream* proxy, long long size)
-{
- if (proxy->client())
- proxy->client()->didGetSize(size);
-}
+ // Set flag to prevent client callbacks and also prevent queued operations from starting.
+ internals.destroyed = true;
-void AsyncFileStream::getSize(const String& path, double expectedModificationTime)
-{
- fileThread()->postTask(createFileThreadTask(this, &AsyncFileStream::getSizeOnFileThread, path, expectedModificationTime));
+ // Call through file thread and back to main thread to make sure deletion happens
+ // after all file thread functions and all main thread functions called from them.
+ callOnFileThread([&internals] {
+ callOnMainThread([&internals] {
+ delete &internals;
+ });
+ });
}
-void AsyncFileStream::getSizeOnFileThread(const String& path, double expectedModificationTime)
+void AsyncFileStream::perform(std::function<std::function<void(FileStreamClient&)>(FileStream&)> operation)
{
- long long size = m_stream->getSize(path, expectedModificationTime);
- callOnMainThread(didGetSize, AllowCrossThreadAccess(this), size);
+ auto& internals = *m_internals;
+ callOnFileThread([&internals, operation] {
+ // Don't do the operation if stop was already called on the main thread. Note that there is
+ // a race here, but since skipping the operation is an optimization it's OK that we can't
+ // guarantee exactly which operations are skipped. Note that this is also the only reason
+ // we use an atomic_bool rather than just a bool for destroyed.
+ if (internals.destroyed)
+ return;
+ auto mainThreadWork = operation(internals.stream);
+ callOnMainThread([&internals, mainThreadWork] {
+ if (internals.destroyed)
+ return;
+ mainThreadWork(internals.client);
+ });
+ });
}
-static void didOpen(AsyncFileStream* proxy, bool success)
+void AsyncFileStream::getSize(const String& path, double expectedModificationTime)
{
- if (proxy->client())
- proxy->client()->didOpen(success);
+ StringCapture capturedPath(path);
+ // FIXME: Explicit return type here and in all the other cases like this below is a workaround for a deficiency
+ // in the Windows compiler at the time of this writing. Could remove it if that is resolved.
+ perform([capturedPath, expectedModificationTime](FileStream& stream) -> std::function<void(FileStreamClient&)> {
+ long long size = stream.getSize(capturedPath.string(), expectedModificationTime);
+ return [size](FileStreamClient& client) {
+ client.didGetSize(size);
+ };
+ });
}
void AsyncFileStream::openForRead(const String& path, long long offset, long long length)
{
- fileThread()->postTask(createFileThreadTask(this, &AsyncFileStream::openForReadOnFileThread, path, offset, length));
-}
-
-void AsyncFileStream::openForReadOnFileThread(const String& path, long long offset, long long length)
-{
- bool success = m_stream->openForRead(path, offset, length);
- callOnMainThread(didOpen, AllowCrossThreadAccess(this), success);
+ StringCapture capturedPath(path);
+ // FIXME: Explicit return type here is a workaround for a deficiency in the Windows compiler at the time of this writing.
+ perform([capturedPath, offset, length](FileStream& stream) -> std::function<void(FileStreamClient&)> {
+ bool success = stream.openForRead(capturedPath.string(), offset, length);
+ return [success](FileStreamClient& client) {
+ client.didOpen(success);
+ };
+ });
}
void AsyncFileStream::openForWrite(const String& path)
{
- fileThread()->postTask(
- createFileThreadTask(this,
- &AsyncFileStream::openForWriteOnFileThread, path));
-}
-
-void AsyncFileStream::openForWriteOnFileThread(const String& path)
-{
- bool success = m_stream->openForWrite(path);
- callOnMainThread(didOpen, AllowCrossThreadAccess(this), success);
+ StringCapture capturedPath(path);
+ perform([capturedPath](FileStream& stream) -> std::function<void(FileStreamClient&)> {
+ bool success = stream.openForWrite(capturedPath.string());
+ return [success](FileStreamClient& client) {
+ client.didOpen(success);
+ };
+ });
}
void AsyncFileStream::close()
{
- fileThread()->postTask(createFileThreadTask(this, &AsyncFileStream::closeOnFileThread));
-}
-
-void AsyncFileStream::closeOnFileThread()
-{
- m_stream->close();
-}
-
-static void didRead(AsyncFileStream* proxy, int bytesRead)
-{
- if (proxy->client())
- proxy->client()->didRead(bytesRead);
+ auto& internals = *m_internals;
+ callOnFileThread([&internals] {
+ internals.stream.close();
+ });
}
void AsyncFileStream::read(char* buffer, int length)
{
- fileThread()->postTask(
- createFileThreadTask(this, &AsyncFileStream::readOnFileThread,
- AllowCrossThreadAccess(buffer), length));
-}
-
-void AsyncFileStream::readOnFileThread(char* buffer, int length)
-{
- int bytesRead = m_stream->read(buffer, length);
- callOnMainThread(didRead, AllowCrossThreadAccess(this), bytesRead);
-}
-
-static void didWrite(AsyncFileStream* proxy, int bytesWritten)
-{
- if (proxy->client())
- proxy->client()->didWrite(bytesWritten);
+ perform([buffer, length](FileStream& stream) -> std::function<void(FileStreamClient&)> {
+ int bytesRead = stream.read(buffer, length);
+ return [bytesRead](FileStreamClient& client) {
+ client.didRead(bytesRead);
+ };
+ });
}
void AsyncFileStream::write(const URL& blobURL, long long position, int length)
{
- fileThread()->postTask(createFileThreadTask(this, &AsyncFileStream::writeOnFileThread, blobURL, position, length));
-}
-
-void AsyncFileStream::writeOnFileThread(const URL& blobURL, long long position, int length)
-{
- int bytesWritten = m_stream->write(blobURL, position, length);
- callOnMainThread(didWrite, AllowCrossThreadAccess(this), bytesWritten);
-}
-
-static void didTruncate(AsyncFileStream* proxy, bool success)
-{
- if (proxy->client())
- proxy->client()->didTruncate(success);
+ URLCapture capturedURL(blobURL);
+ perform([capturedURL, position, length](FileStream& stream) -> std::function<void(FileStreamClient&)> {
+ int bytesWritten = stream.write(capturedURL.url(), position, length);
+ return [bytesWritten](FileStreamClient& client) {
+ client.didWrite(bytesWritten);
+ };
+ });
}
void AsyncFileStream::truncate(long long position)
{
- fileThread()->postTask(createFileThreadTask(this, &AsyncFileStream::truncateOnFileThread, position));
-}
-
-void AsyncFileStream::truncateOnFileThread(long long position)
-{
- bool success = m_stream->truncate(position);
- callOnMainThread(didTruncate, AllowCrossThreadAccess(this), success);
+ perform([position](FileStream& stream) -> std::function<void(FileStreamClient&)> {
+ bool success = stream.truncate(position);
+ return [success](FileStreamClient& client) {
+ client.didTruncate(success);
+ };
+ });
}
} // namespace WebCore
-
-#endif // ENABLE(BLOB)
diff --git a/Source/WebCore/fileapi/AsyncFileStream.h b/Source/WebCore/fileapi/AsyncFileStream.h
index 849ea2bc9..428f730ee 100644
--- a/Source/WebCore/fileapi/AsyncFileStream.h
+++ b/Source/WebCore/fileapi/AsyncFileStream.h
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- * Copyright (C) 2010, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2010, 2012, 2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -32,11 +32,8 @@
#ifndef AsyncFileStream_h
#define AsyncFileStream_h
-#if ENABLE(BLOB)
-
+#include <functional>
#include <wtf/Forward.h>
-#include <wtf/RefCounted.h>
-#include <wtf/RefPtr.h>
namespace WebCore {
@@ -44,9 +41,9 @@ class FileStreamClient;
class FileStream;
class URL;
-class AsyncFileStream : public RefCounted<AsyncFileStream> {
+class AsyncFileStream {
public:
- static PassRefPtr<AsyncFileStream> create(FileStreamClient*);
+ explicit AsyncFileStream(FileStreamClient&);
~AsyncFileStream();
void getSize(const String& path, double expectedModificationTime);
@@ -57,34 +54,14 @@ public:
void write(const URL& blobURL, long long position, int length);
void truncate(long long position);
- // Stops the proxy and schedules it to be destructed. All the pending tasks will be aborted and the file stream will be closed.
- // Note: the caller should deref the instance immediately after calling stop().
- void stop();
-
- FileStreamClient* client() const { return m_client; }
- void setClient(FileStreamClient* client) { m_client = client; }
-
private:
- AsyncFileStream(FileStreamClient*);
+ void start();
+ void perform(std::function<std::function<void(FileStreamClient&)>(FileStream&)>);
- // Called on File thread.
- void startOnFileThread();
- void stopOnFileThread();
- void getSizeOnFileThread(const String& path, double expectedModificationTime);
- void openForReadOnFileThread(const String& path, long long offset, long long length);
- void openForWriteOnFileThread(const String& path);
- void closeOnFileThread();
- void readOnFileThread(char* buffer, int length);
- void writeOnFileThread(const URL& blobURL, long long position, int length);
- void truncateOnFileThread(long long position);
-
- RefPtr<FileStream> m_stream;
-
- FileStreamClient* m_client;
+ struct Internals;
+ std::unique_ptr<Internals> m_internals;
};
} // namespace WebCore
-#endif // ENABLE(BLOB)
-
#endif // AsyncFileStream_h
diff --git a/Source/WebCore/fileapi/Blob.cpp b/Source/WebCore/fileapi/Blob.cpp
index 6726bf470..4607c1af3 100644
--- a/Source/WebCore/fileapi/Blob.cpp
+++ b/Source/WebCore/fileapi/Blob.cpp
@@ -33,25 +33,13 @@
#include "BlobURL.h"
#include "File.h"
-#include "HistogramSupport.h"
-#include "ScriptCallStack.h"
#include "ScriptExecutionContext.h"
#include "ThreadableBlobRegistry.h"
+#include <wtf/NeverDestroyed.h>
#include <wtf/text/CString.h>
namespace WebCore {
-namespace {
-
-// Used in histograms to see when we can actually deprecate the prefixed slice.
-enum SliceHistogramEnum {
- SliceWithoutPrefix,
- SliceWithPrefix,
- SliceHistogramEnumMax,
-};
-
-} // namespace
-
class BlobURLRegistry final : public URLRegistry {
public:
virtual void registerURL(SecurityOrigin*, const URL&, URLRegistrable*) override;
@@ -74,39 +62,53 @@ void BlobURLRegistry::unregisterURL(const URL& url)
URLRegistry& BlobURLRegistry::registry()
{
- DEFINE_STATIC_LOCAL(BlobURLRegistry, instance, ());
+ static NeverDestroyed<BlobURLRegistry> instance;
return instance;
}
+Blob::Blob(UninitializedContructor)
+{
+}
Blob::Blob()
: m_size(0)
{
- auto blobData = std::make_unique<BlobData>();
-
- // Create a new internal URL and register it with the provided blob data.
m_internalURL = BlobURL::createInternalURL();
- ThreadableBlobRegistry::registerBlobURL(m_internalURL, std::move(blobData));
+ ThreadableBlobRegistry::registerBlobURL(m_internalURL, Vector<BlobPart>(), String());
}
-Blob::Blob(std::unique_ptr<BlobData> blobData, long long size)
- : m_type(blobData->contentType())
- , m_size(size)
+Blob::Blob(Vector<uint8_t> data, const String& contentType)
+ : m_type(contentType)
+ , m_size(data.size())
{
- ASSERT(blobData);
+ Vector<BlobPart> blobParts;
+ blobParts.append(BlobPart(WTFMove(data)));
+ m_internalURL = BlobURL::createInternalURL();
+ ThreadableBlobRegistry::registerBlobURL(m_internalURL, WTFMove(blobParts), contentType);
+}
- // Create a new internal URL and register it with the provided blob data.
+Blob::Blob(Vector<BlobPart> blobParts, const String& contentType)
+ : m_type(contentType)
+ , m_size(-1)
+{
m_internalURL = BlobURL::createInternalURL();
- ThreadableBlobRegistry::registerBlobURL(m_internalURL, std::move(blobData));
+ ThreadableBlobRegistry::registerBlobURL(m_internalURL, WTFMove(blobParts), contentType);
}
-Blob::Blob(const URL& srcURL, const String& type, long long size)
- : m_type(Blob::normalizedContentType(type))
+Blob::Blob(DeserializationContructor, const URL& srcURL, const String& type, long long size)
+ : m_type(normalizedContentType(type))
, m_size(size)
{
- // Create a new internal URL and register it with the same blob data as the source URL.
m_internalURL = BlobURL::createInternalURL();
- ThreadableBlobRegistry::registerBlobURL(0, m_internalURL, srcURL);
+ ThreadableBlobRegistry::registerBlobURL(nullptr, m_internalURL, srcURL);
+}
+
+Blob::Blob(const URL& srcURL, long long start, long long end, const String& type)
+ : m_type(normalizedContentType(type))
+ , m_size(-1) // size is not necessarily equal to end - start.
+{
+ m_internalURL = BlobURL::createInternalURL();
+ ThreadableBlobRegistry::registerBlobURLForSlice(m_internalURL, srcURL, start, end);
}
Blob::~Blob()
@@ -114,118 +116,63 @@ Blob::~Blob()
ThreadableBlobRegistry::unregisterBlobURL(m_internalURL);
}
-bool Blob::isValidContentType(const String& contentType)
+unsigned long long Blob::size() const
{
- if (contentType.isNull())
- return true;
+ if (m_size < 0) {
+ // 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 representable.
+ unsigned long long actualSize = ThreadableBlobRegistry::blobSize(m_internalURL);
+ m_size = WTF::isInBounds<long long>(actualSize) ? static_cast<long long>(actualSize) : 0;
+ }
- size_t length = contentType.length();
- if (contentType.is8Bit()) {
- const LChar* characters = contentType.characters8();
- for (size_t i = 0; i < length; ++i) {
- if (characters[i] < 0x20 || characters[i] > 0x7e)
- return false;
- }
- } else {
- const UChar* characters = contentType.characters16();
- for (size_t i = 0; i < length; ++i) {
- if (characters[i] < 0x20 || characters[i] > 0x7e)
- return false;
- }
+ return static_cast<unsigned long long>(m_size);
+}
+
+bool Blob::isValidContentType(const String& contentType)
+{
+ // FIXME: Do we really want to treat the empty string and null string as valid content types?
+ unsigned length = contentType.length();
+ for (unsigned i = 0; i < length; ++i) {
+ if (contentType[i] < 0x20 || contentType[i] > 0x7e)
+ return false;
}
return true;
}
String Blob::normalizedContentType(const String& contentType)
{
- if (Blob::isValidContentType(contentType))
- return contentType.lower();
- return emptyString();
+ if (!isValidContentType(contentType))
+ return emptyString();
+ return contentType.convertToASCIILowercase();
}
+#if !ASSERT_DISABLED
bool Blob::isNormalizedContentType(const String& contentType)
{
- if (contentType.isNull())
- return true;
-
- size_t length = contentType.length();
- if (contentType.is8Bit()) {
- const LChar* characters = contentType.characters8();
- for (size_t i = 0; i < length; ++i) {
- if (characters[i] < 0x20 || characters[i] > 0x7e)
- return false;
- if (characters[i] >= 'A' && characters[i] <= 'Z')
- return false;
- }
- } else {
- const UChar* characters = contentType.characters16();
- for (size_t i = 0; i < length; ++i) {
- if (characters[i] < 0x20 || characters[i] > 0x7e)
- return false;
- if (characters[i] >= 'A' && characters[i] <= 'Z')
- return false;
- }
+ // FIXME: Do we really want to treat the empty string and null string as valid content types?
+ unsigned length = contentType.length();
+ for (size_t i = 0; i < length; ++i) {
+ if (contentType[i] < 0x20 || contentType[i] > 0x7e)
+ return false;
+ if (isASCIIUpper(contentType[i]))
+ return false;
}
return true;
}
bool Blob::isNormalizedContentType(const CString& contentType)
{
+ // FIXME: Do we really want to treat the empty string and null string as valid content types?
size_t length = contentType.length();
const char* characters = contentType.data();
for (size_t i = 0; i < length; ++i) {
if (characters[i] < 0x20 || characters[i] > 0x7e)
return false;
- if (characters[i] >= 'A' && characters[i] <= 'Z')
+ if (isASCIIUpper(characters[i]))
return false;
}
return true;
}
-
-#if ENABLE(BLOB)
-PassRefPtr<Blob> Blob::slice(long long start, long long end, const String& contentType) 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 size;
- double modificationTime;
- if (isFile()) {
- // FIXME: This involves synchronous file operation. We need to figure out how to make it asynchronous.
- toFile(this)->captureSnapshot(size, modificationTime);
- } else {
- ASSERT(m_size != -1);
- size = m_size;
- }
-
- // Convert the negative value that is used to select from the end.
- if (start < 0)
- start = start + size;
- if (end < 0)
- end = end + size;
-
- // Clamp the range if it exceeds the size limit.
- if (start < 0)
- start = 0;
- if (end < 0)
- end = 0;
- if (start >= size) {
- start = 0;
- end = 0;
- } else if (end < start)
- end = start;
- else if (end > size)
- end = size;
-
- long long length = end - start;
- auto blobData = std::make_unique<BlobData>();
- blobData->setContentType(Blob::normalizedContentType(contentType));
- if (isFile())
- blobData->appendFile(toFile(this)->path(), start, length, modificationTime);
- else
- blobData->appendBlob(m_internalURL, start, length);
-
- return Blob::create(std::move(blobData), length);
-}
#endif
URLRegistry& Blob::registry() const
diff --git a/Source/WebCore/fileapi/Blob.h b/Source/WebCore/fileapi/Blob.h
index 3e1e2ad9f..28abfc096 100644
--- a/Source/WebCore/fileapi/Blob.h
+++ b/Source/WebCore/fileapi/Blob.h
@@ -31,11 +31,9 @@
#ifndef Blob_h
#define Blob_h
-#include "BlobData.h"
-#include "URL.h"
+#include "BlobPart.h"
#include "ScriptWrappable.h"
#include "URLRegistry.h"
-#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
#include <wtf/text/WTFString.h>
@@ -45,21 +43,25 @@ class ScriptExecutionContext;
class Blob : public ScriptWrappable, public URLRegistrable, public RefCounted<Blob> {
public:
- static PassRefPtr<Blob> create()
+ static Ref<Blob> create()
{
- return adoptRef(new Blob);
+ return adoptRef(*new Blob);
}
- static PassRefPtr<Blob> create(std::unique_ptr<BlobData> blobData, long long size)
+ static Ref<Blob> create(Vector<uint8_t> data, const String& contentType)
{
- return adoptRef(new Blob(std::move(blobData), size));
+ return adoptRef(*new Blob(WTFMove(data), contentType));
}
- // For deserialization.
- static PassRefPtr<Blob> create(const URL& srcURL, const String& type, long long size)
+ static Ref<Blob> create(Vector<BlobPart> blobParts, const String& contentType)
+ {
+ return adoptRef(*new Blob(WTFMove(blobParts), contentType));
+ }
+
+ static Ref<Blob> deserialize(const URL& srcURL, const String& type, long long size)
{
ASSERT(Blob::isNormalizedContentType(type));
- return adoptRef(new Blob(srcURL, type, size));
+ return adoptRef(*new Blob(deserializationContructor, srcURL, type, size));
}
virtual ~Blob();
@@ -67,30 +69,39 @@ public:
const URL& url() const { return m_internalURL; }
const String& type() const { return m_type; }
- virtual unsigned long long size() const { return static_cast<unsigned long long>(m_size); }
+ unsigned long long size() const;
virtual bool isFile() const { return false; }
// The checks described in the File API spec.
static bool isValidContentType(const String&);
// The normalization procedure described in the File API spec.
static String normalizedContentType(const String&);
- // Intended for use in ASSERT statements.
+#if !ASSERT_DISABLED
static bool isNormalizedContentType(const String&);
static bool isNormalizedContentType(const CString&);
+#endif
// URLRegistrable
virtual URLRegistry& registry() const override;
-#if ENABLE(BLOB)
- PassRefPtr<Blob> slice(long long start = 0, long long end = std::numeric_limits<long long>::max(), const String& contentType = String()) const;
-#endif
+ Ref<Blob> slice(long long start = 0, long long end = std::numeric_limits<long long>::max(), const String& contentType = String()) const
+ {
+ return adoptRef(*new Blob(m_internalURL, start, end, contentType));
+ }
protected:
Blob();
- Blob(std::unique_ptr<BlobData>, long long size);
+ Blob(Vector<uint8_t>, const String& contentType);
+ Blob(Vector<BlobPart>, const String& contentType);
+
+ enum UninitializedContructor { uninitializedContructor };
+ Blob(UninitializedContructor);
+
+ enum DeserializationContructor { deserializationContructor };
+ Blob(DeserializationContructor, const URL& srcURL, const String& type, long long size);
- // For deserialization.
- Blob(const URL& srcURL, const String& type, long long size);
+ // For slicing.
+ Blob(const URL& srcURL, long long start, long long end, const String& contentType);
// This is an internal URL referring to the blob data associated with this object. It serves
// as an identifier for this blob. The internal URL is never used to source the blob's content
@@ -98,7 +109,7 @@ protected:
URL m_internalURL;
String m_type;
- long long m_size;
+ mutable long long m_size;
};
} // namespace WebCore
diff --git a/Source/WebCore/fileapi/Blob.idl b/Source/WebCore/fileapi/Blob.idl
index ca2dd343b..7078c3233 100644
--- a/Source/WebCore/fileapi/Blob.idl
+++ b/Source/WebCore/fileapi/Blob.idl
@@ -32,7 +32,6 @@
GlobalContext=DOMWindow&WorkerGlobalScope,
GenerateIsReachable=Impl,
CustomToJSObject,
- JSNoStaticTables,
CustomConstructor,
CustomConstructor(sequence<any> blobParts, optional BlobPropertyBag options),
] interface Blob {
@@ -40,9 +39,7 @@
readonly attribute DOMString type;
#if !defined(LANGUAGE_OBJECTIVE_C)
-#if defined(ENABLE_BLOB) && ENABLE_BLOB
Blob slice(optional long long start, optional long long end, [TreatNullAs=NullString, TreatUndefinedAs=NullString] optional DOMString contentType);
#endif
-#endif
};
diff --git a/Source/WebCore/fileapi/BlobURL.cpp b/Source/WebCore/fileapi/BlobURL.cpp
index 3debf3831..847ea493b 100644
--- a/Source/WebCore/fileapi/BlobURL.cpp
+++ b/Source/WebCore/fileapi/BlobURL.cpp
@@ -39,7 +39,7 @@
namespace WebCore {
-const char BlobURL::kBlobProtocol[] = "blob";
+const char* kBlobProtocol = "blob";
URL BlobURL::createPublicURL(SecurityOrigin* securityOrigin)
{
diff --git a/Source/WebCore/fileapi/BlobURL.h b/Source/WebCore/fileapi/BlobURL.h
index c7fa4fe74..f837c9196 100644
--- a/Source/WebCore/fileapi/BlobURL.h
+++ b/Source/WebCore/fileapi/BlobURL.h
@@ -52,11 +52,9 @@ public:
static URL createInternalURL();
static String getOrigin(const URL&);
static String getIdentifier(const URL&);
- static const char* blobProtocol() { return kBlobProtocol; }
private:
static URL createBlobURL(const String& originString);
- static const char kBlobProtocol[];
BlobURL() { }
};
diff --git a/Source/WebCore/fileapi/File.cpp b/Source/WebCore/fileapi/File.cpp
index 6f6dd0e61..94b228823 100644
--- a/Source/WebCore/fileapi/File.cpp
+++ b/Source/WebCore/fileapi/File.cpp
@@ -26,77 +26,39 @@
#include "config.h"
#include "File.h"
+#include "BlobURL.h"
#include "FileMetadata.h"
#include "FileSystem.h"
#include "MIMETypeRegistry.h"
+#include "ThreadableBlobRegistry.h"
#include <wtf/CurrentTime.h>
#include <wtf/DateMath.h>
#include <wtf/text/WTFString.h>
namespace WebCore {
-static String getContentTypeFromFileName(const String& name, File::ContentTypeLookupPolicy policy)
-{
- String type;
- int index = name.reverseFind('.');
- if (index != -1) {
- if (policy == File::WellKnownContentTypes)
- type = MIMETypeRegistry::getWellKnownMIMETypeForExtension(name.substring(index + 1));
- else {
- ASSERT(policy == File::AllContentTypes);
- type = MIMETypeRegistry::getMIMETypeForExtension(name.substring(index + 1));
- }
- }
- return type;
-}
-
-static std::unique_ptr<BlobData> createBlobDataForFileWithType(const String& path, const String& contentType)
-{
- auto blobData = std::make_unique<BlobData>();
- ASSERT(Blob::isNormalizedContentType(contentType));
- blobData->setContentType(contentType);
- blobData->appendFile(path);
- return blobData;
-}
-
-static std::unique_ptr<BlobData> createBlobDataForFile(const String& path, File::ContentTypeLookupPolicy policy)
-{
- return createBlobDataForFileWithType(path, getContentTypeFromFileName(path, policy));
-}
-
-static std::unique_ptr<BlobData> createBlobDataForFileWithName(const String& path, const String& fileSystemName, File::ContentTypeLookupPolicy policy)
-{
- return createBlobDataForFileWithType(path, getContentTypeFromFileName(fileSystemName, policy));
-}
-
-#if ENABLE(DIRECTORY_UPLOAD)
-PassRefPtr<File> File::createWithRelativePath(const String& path, const String& relativePath)
-{
- RefPtr<File> file = adoptRef(new File(path, AllContentTypes));
- file->m_relativePath = relativePath;
- return file.release();
-}
-#endif
-
-File::File(const String& path, ContentTypeLookupPolicy policy)
- : Blob(createBlobDataForFile(path, policy), -1)
+File::File(const String& path)
+ : Blob(uninitializedContructor)
, m_path(path)
- , m_name(pathGetFileName(path))
{
+ m_internalURL = BlobURL::createInternalURL();
+ m_size = -1;
+ computeNameAndContentType(m_path, String(), m_name, m_type);
+ ThreadableBlobRegistry::registerFileBlobURL(m_internalURL, path, m_type);
}
-File::File(const String& path, const URL& url, const String& type)
- : Blob(url, type, -1)
+File::File(const String& path, const String& nameOverride)
+ : Blob(uninitializedContructor)
, m_path(path)
{
- m_name = pathGetFileName(path);
- // FIXME: File object serialization/deserialization does not include
- // newer file object data members: m_name and m_relativePath.
- // See SerializedScriptValue.cpp
+ m_internalURL = BlobURL::createInternalURL();
+ m_size = -1;
+ computeNameAndContentType(m_path, nameOverride, m_name, m_type);
+ ThreadableBlobRegistry::registerFileBlobURL(m_internalURL, path, m_type);
}
-File::File(const String& path, const String& name, ContentTypeLookupPolicy policy)
- : Blob(createBlobDataForFileWithName(path, name, policy), -1)
+File::File(DeserializationContructor, const String& path, const URL& url, const String& type, const String& name)
+ : Blob(deserializationContructor, url, type, -1)
, m_path(path)
, m_name(name)
{
@@ -111,29 +73,27 @@ double File::lastModifiedDate() const
return currentTime() * msPerSecond;
}
-unsigned long long File::size() const
+void File::computeNameAndContentType(const String& path, const String& nameOverride, String& effectiveName, String& effectiveContentType)
{
- // 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 representable.
- long long size;
- if (!getFileSize(m_path, size))
- return 0;
- return static_cast<unsigned long long>(size);
+#if ENABLE(FILE_REPLACEMENT)
+ if (shouldReplaceFile(path)) {
+ computeNameAndContentTypeForReplacedFile(path, nameOverride, effectiveName, effectiveContentType);
+ return;
+ }
+#endif
+ effectiveName = nameOverride.isNull() ? pathGetFileName(path) : nameOverride;
+ size_t index = effectiveName.reverseFind('.');
+ if (index != notFound)
+ effectiveContentType = MIMETypeRegistry::getMIMETypeForExtension(effectiveName.substring(index + 1));
}
-void File::captureSnapshot(long long& snapshotSize, double& snapshotModificationTime) const
+String File::contentTypeForFile(const String& path)
{
- // Obtains a snapshot of the file by capturing its current size and modification time. This is used when we slice a file for the first time.
- // If we fail to retrieve the size or modification time, probably due to that the file has been deleted, 0 size is returned.
- FileMetadata metadata;
- if (!getFileMetadata(m_path, metadata)) {
- snapshotSize = 0;
- snapshotModificationTime = invalidFileTime();
- return;
- }
+ String name;
+ String type;
+ computeNameAndContentType(path, String(), name, type);
- snapshotSize = metadata.length;
- snapshotModificationTime = metadata.modificationTime;
+ return type;
}
} // namespace WebCore
diff --git a/Source/WebCore/fileapi/File.h b/Source/WebCore/fileapi/File.h
index edf485582..683d20d00 100644
--- a/Source/WebCore/fileapi/File.h
+++ b/Source/WebCore/fileapi/File.h
@@ -27,90 +27,67 @@
#define File_h
#include "Blob.h"
-#include <wtf/PassRefPtr.h>
+#include <wtf/Ref.h>
+#include <wtf/TypeCasts.h>
#include <wtf/text/WTFString.h>
namespace WebCore {
-struct FileMetadata;
class URL;
-class File : public Blob {
+class File final : public Blob {
public:
- // AllContentTypes should only be used when the full path/name are trusted; otherwise, it could
- // allow arbitrary pages to determine what applications an user has installed.
- enum ContentTypeLookupPolicy {
- WellKnownContentTypes,
- AllContentTypes,
- };
-
- static PassRefPtr<File> create(const String& path, ContentTypeLookupPolicy policy = WellKnownContentTypes)
+ static Ref<File> create(const String& path)
{
- return adoptRef(new File(path, policy));
+ return adoptRef(*new File(path));
}
- // For deserialization.
- static PassRefPtr<File> create(const String& path, const URL& srcURL, const String& type)
+ static Ref<File> deserialize(const String& path, const URL& srcURL, const String& type, const String& name)
{
- return adoptRef(new File(path, srcURL, type));
+ return adoptRef(*new File(deserializationContructor, path, srcURL, type, name));
}
-#if ENABLE(DIRECTORY_UPLOAD)
- static PassRefPtr<File> createWithRelativePath(const String& path, const String& relativePath);
-#endif
-
// Create a file with a name exposed to the author (via File.name and associated DOM properties) that differs from the one provided in the path.
- static PassRefPtr<File> createWithName(const String& path, const String& name, ContentTypeLookupPolicy policy = WellKnownContentTypes)
+ static Ref<File> createWithName(const String& path, const String& nameOverride)
{
- if (name.isEmpty())
- return adoptRef(new File(path, policy));
- return adoptRef(new File(path, name, policy));
+ if (nameOverride.isEmpty())
+ return adoptRef(*new File(path));
+ return adoptRef(*new File(path, nameOverride));
}
- virtual unsigned long long size() const override;
virtual bool isFile() const override { return true; }
const String& path() const { return m_path; }
const String& name() const { return m_name; }
- // This returns the current date and time if the file's last modifiecation date is not known (per spec: http://www.w3.org/TR/FileAPI/#dfn-lastModifiedDate).
+ // This returns the current date and time if the file's last modification date is not known (per spec: http://www.w3.org/TR/FileAPI/#dfn-lastModifiedDate).
double lastModifiedDate() const;
-#if ENABLE(DIRECTORY_UPLOAD)
- // Returns the relative path of this file in the context of a directory selection.
- const String& webkitRelativePath() const { return m_relativePath; }
-#endif
+ static String contentTypeForFile(const String& path);
- // Note that this involves synchronous file operation. Think twice before calling this function.
- void captureSnapshot(long long& snapshotSize, double& snapshotModificationTime) const;
+#if ENABLE(FILE_REPLACEMENT)
+ static bool shouldReplaceFile(const String& path);
+#endif
private:
- File(const String& path, ContentTypeLookupPolicy);
+ WEBCORE_EXPORT explicit File(const String& path);
+ File(const String& path, const String& nameOverride);
+
+ File(DeserializationContructor, const String& path, const URL& srcURL, const String& type, const String& name);
- // For deserialization.
- File(const String& path, const URL& srcURL, const String& type);
- File(const String& path, const String& name, ContentTypeLookupPolicy);
+ static void computeNameAndContentType(const String& path, const String& nameOverride, String& effectiveName, String& effectiveContentType);
+#if ENABLE(FILE_REPLACEMENT)
+ static void computeNameAndContentTypeForReplacedFile(const String& path, const String& nameOverride, String& effectiveName, String& effectiveContentType);
+#endif
String m_path;
String m_name;
-
-#if ENABLE(DIRECTORY_UPLOAD)
- String m_relativePath;
-#endif
};
-inline File* toFile(Blob* blob)
-{
- ASSERT_WITH_SECURITY_IMPLICATION(!blob || blob->isFile());
- return static_cast<File*>(blob);
-}
-
-inline const File* toFile(const Blob* blob)
-{
- ASSERT_WITH_SECURITY_IMPLICATION(!blob || blob->isFile());
- return static_cast<const File*>(blob);
-}
-
} // namespace WebCore
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::File)
+ static bool isType(const WebCore::Blob& blob) { return blob.isFile(); }
+SPECIALIZE_TYPE_TRAITS_END()
+
#endif // File_h
diff --git a/Source/WebCore/fileapi/File.idl b/Source/WebCore/fileapi/File.idl
index 1d9dc51fc..8e0989394 100644
--- a/Source/WebCore/fileapi/File.idl
+++ b/Source/WebCore/fileapi/File.idl
@@ -26,12 +26,10 @@
[
JSGenerateToNativeObject,
JSGenerateToJSObject,
- JSNoStaticTables
] interface File : Blob {
readonly attribute DOMString name;
#if !defined(LANGUAGE_GOBJECT) || !LANGUAGE_GOBJECT
readonly attribute Date lastModifiedDate;
#endif
- [Conditional=DIRECTORY_UPLOAD] readonly attribute DOMString webkitRelativePath;
};
diff --git a/Source/WebCore/fileapi/FileError.h b/Source/WebCore/fileapi/FileError.h
index 7678a5154..1db58c53e 100644
--- a/Source/WebCore/fileapi/FileError.h
+++ b/Source/WebCore/fileapi/FileError.h
@@ -31,9 +31,7 @@
#ifndef FileError_h
#define FileError_h
-#if ENABLE(BLOB)
-
-#include <wtf/PassRefPtr.h>
+#include <wtf/Ref.h>
#include <wtf/RefCounted.h>
namespace WebCore {
@@ -56,7 +54,7 @@ public:
PATH_EXISTS_ERR = 12,
};
- static PassRefPtr<FileError> create(ErrorCode code) { return adoptRef(new FileError(code)); }
+ static Ref<FileError> create(ErrorCode code) { return adoptRef(*new FileError(code)); }
ErrorCode code() const { return m_code; }
@@ -70,6 +68,4 @@ private:
} // namespace WebCore
-#endif // ENABLE(BLOB)
-
#endif // FileError_h
diff --git a/Source/WebCore/fileapi/FileError.idl b/Source/WebCore/fileapi/FileError.idl
index 866ce9274..a4db08173 100644
--- a/Source/WebCore/fileapi/FileError.idl
+++ b/Source/WebCore/fileapi/FileError.idl
@@ -29,8 +29,6 @@
*/
[
- Conditional=BLOB,
- JSNoStaticTables,
ImplementationLacksVTable
] interface FileError {
#if !defined(LANGUAGE_OBJECTIVE_C)
diff --git a/Source/WebCore/fileapi/FileException.cpp b/Source/WebCore/fileapi/FileException.cpp
index 357fb495d..975d1c708 100644
--- a/Source/WebCore/fileapi/FileException.cpp
+++ b/Source/WebCore/fileapi/FileException.cpp
@@ -10,7 +10,7 @@
* 2. 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.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -27,11 +27,10 @@
*/
#include "config.h"
-
-#if ENABLE(BLOB)
-
#include "FileException.h"
+#include "ExceptionCodeDescription.h"
+
namespace WebCore {
static struct FileExceptionNameDescription {
@@ -71,5 +70,3 @@ bool FileException::initializeDescription(ExceptionCode ec, ExceptionCodeDescrip
}
} // namespace WebCore
-
-#endif // ENABLE(BLOB)
diff --git a/Source/WebCore/fileapi/FileException.h b/Source/WebCore/fileapi/FileException.h
index ccf7982df..e53ba30b9 100644
--- a/Source/WebCore/fileapi/FileException.h
+++ b/Source/WebCore/fileapi/FileException.h
@@ -31,17 +31,15 @@
#ifndef FileException_h
#define FileException_h
-#if ENABLE(BLOB)
-
#include "ExceptionBase.h"
namespace WebCore {
class FileException : public ExceptionBase {
public:
- static PassRefPtr<FileException> create(const ExceptionCodeDescription& description)
+ static Ref<FileException> create(const ExceptionCodeDescription& description)
{
- return adoptRef(new FileException(description));
+ return adoptRef(*new FileException(description));
}
static const int FileExceptionOffset = 1100;
@@ -80,6 +78,4 @@ private:
} // namespace WebCore
-#endif // ENABLE(BLOB)
-
#endif // FileException_h
diff --git a/Source/WebCore/fileapi/FileException.idl b/Source/WebCore/fileapi/FileException.idl
index 8ff47c524..77a5a366b 100644
--- a/Source/WebCore/fileapi/FileException.idl
+++ b/Source/WebCore/fileapi/FileException.idl
@@ -30,9 +30,7 @@
[
NoInterfaceObject,
- Conditional=BLOB,
DoNotCheckConstants,
- JSNoStaticTables,
ImplementationLacksVTable,
] exception FileException {
diff --git a/Source/WebCore/fileapi/FileList.h b/Source/WebCore/fileapi/FileList.h
index 1e982ee77..939013fef 100644
--- a/Source/WebCore/fileapi/FileList.h
+++ b/Source/WebCore/fileapi/FileList.h
@@ -28,7 +28,6 @@
#include "File.h"
#include "ScriptWrappable.h"
-#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
#include <wtf/Vector.h>
@@ -37,21 +36,33 @@ namespace WebCore {
class FileList : public ScriptWrappable, public RefCounted<FileList> {
public:
- static PassRefPtr<FileList> create()
+ static Ref<FileList> create()
{
- return adoptRef(new FileList);
+ return adoptRef(*new FileList);
+ }
+
+ static Ref<FileList> create(Vector<RefPtr<File>>&& files)
+ {
+ return adoptRef(*new FileList(WTFMove(files)));
}
unsigned length() const { return m_files.size(); }
File* item(unsigned index) const;
bool isEmpty() const { return m_files.isEmpty(); }
- void clear() { m_files.clear(); }
- void append(PassRefPtr<File> file) { m_files.append(file); }
Vector<String> paths() const;
private:
FileList();
+ FileList(Vector<RefPtr<File>>&& files)
+ : m_files(WTFMove(files))
+ { }
+
+ // FileLists can only be changed by their owners.
+ friend class DataTransfer;
+ friend class FileInputType;
+ void append(RefPtr<File>&& file) { m_files.append(WTFMove(file)); }
+ void clear() { m_files.clear(); }
Vector<RefPtr<File>> m_files;
};
diff --git a/Source/WebCore/fileapi/FileList.idl b/Source/WebCore/fileapi/FileList.idl
index 258f9ccb6..42d553814 100644
--- a/Source/WebCore/fileapi/FileList.idl
+++ b/Source/WebCore/fileapi/FileList.idl
@@ -24,7 +24,6 @@
*/
[
- JSNoStaticTables,
ImplementationLacksVTable,
] interface FileList {
readonly attribute unsigned long length;
diff --git a/Source/WebCore/fileapi/FileReader.cpp b/Source/WebCore/fileapi/FileReader.cpp
index 0025bc045..1d9a09584 100644
--- a/Source/WebCore/fileapi/FileReader.cpp
+++ b/Source/WebCore/fileapi/FileReader.cpp
@@ -30,11 +30,8 @@
#include "config.h"
-#if ENABLE(BLOB)
-
#include "FileReader.h"
-#include "CrossThreadTask.h"
#include "ExceptionCode.h"
#include "File.h"
#include "Logging.h"
@@ -48,11 +45,11 @@ namespace WebCore {
static const auto progressNotificationInterval = std::chrono::milliseconds(50);
-PassRefPtr<FileReader> FileReader::create(ScriptExecutionContext& context)
+Ref<FileReader> FileReader::create(ScriptExecutionContext& context)
{
- RefPtr<FileReader> fileReader(adoptRef(new FileReader(context)));
+ Ref<FileReader> fileReader = adoptRef(*new FileReader(context));
fileReader->suspendIfNeeded();
- return fileReader.release();
+ return fileReader;
}
FileReader::FileReader(ScriptExecutionContext& context)
@@ -68,12 +65,17 @@ FileReader::~FileReader()
terminate();
}
-bool FileReader::canSuspend() const
+bool FileReader::canSuspendForDocumentSuspension() const
{
// FIXME: It is not currently possible to suspend a FileReader, so pages with FileReader can not go into page cache.
return false;
}
+const char* FileReader::activeDOMObjectName() const
+{
+ return "FileReader";
+}
+
void FileReader::stop()
{
terminate();
@@ -84,7 +86,7 @@ void FileReader::readAsArrayBuffer(Blob* blob, ExceptionCode& ec)
if (!blob)
return;
- LOG(FileAPI, "FileReader: reading as array buffer: %s %s\n", blob->url().string().utf8().data(), blob->isFile() ? toFile(blob)->path().utf8().data() : "");
+ LOG(FileAPI, "FileReader: reading as array buffer: %s %s\n", blob->url().string().utf8().data(), is<File>(*blob) ? downcast<File>(*blob).path().utf8().data() : "");
readInternal(blob, FileReaderLoader::ReadAsArrayBuffer, ec);
}
@@ -94,7 +96,7 @@ void FileReader::readAsBinaryString(Blob* blob, ExceptionCode& ec)
if (!blob)
return;
- LOG(FileAPI, "FileReader: reading as binary: %s %s\n", blob->url().string().utf8().data(), blob->isFile() ? toFile(blob)->path().utf8().data() : "");
+ LOG(FileAPI, "FileReader: reading as binary: %s %s\n", blob->url().string().utf8().data(), is<File>(*blob) ? downcast<File>(*blob).path().utf8().data() : "");
readInternal(blob, FileReaderLoader::ReadAsBinaryString, ec);
}
@@ -104,7 +106,7 @@ void FileReader::readAsText(Blob* blob, const String& encoding, ExceptionCode& e
if (!blob)
return;
- LOG(FileAPI, "FileReader: reading as text: %s %s\n", blob->url().string().utf8().data(), blob->isFile() ? toFile(blob)->path().utf8().data() : "");
+ LOG(FileAPI, "FileReader: reading as text: %s %s\n", blob->url().string().utf8().data(), is<File>(*blob) ? downcast<File>(*blob).path().utf8().data() : "");
m_encoding = encoding;
readInternal(blob, FileReaderLoader::ReadAsText, ec);
@@ -120,7 +122,7 @@ void FileReader::readAsDataURL(Blob* blob, ExceptionCode& ec)
if (!blob)
return;
- LOG(FileAPI, "FileReader: reading as data URL: %s %s\n", blob->url().string().utf8().data(), blob->isFile() ? toFile(blob)->path().utf8().data() : "");
+ LOG(FileAPI, "FileReader: reading as data URL: %s %s\n", blob->url().string().utf8().data(), is<File>(*blob) ? downcast<File>(*blob).path().utf8().data() : "");
readInternal(blob, FileReaderLoader::ReadAsDataURL, ec);
}
@@ -138,7 +140,7 @@ void FileReader::readInternal(Blob* blob, FileReaderLoader::ReadType type, Excep
m_blob = blob;
m_readType = type;
m_state = LOADING;
- m_error = 0;
+ m_error = nullptr;
m_loader = std::make_unique<FileReaderLoader>(m_readType, this);
m_loader->setEncoding(m_encoding);
@@ -146,11 +148,6 @@ void FileReader::readInternal(Blob* blob, FileReaderLoader::ReadType type, Excep
m_loader->start(scriptExecutionContext(), m_blob.get());
}
-static void delayedAbort(ScriptExecutionContext*, FileReader* reader)
-{
- reader->doAbort();
-}
-
void FileReader::abort()
{
LOG(FileAPI, "FileReader: aborting\n");
@@ -160,25 +157,21 @@ void FileReader::abort()
m_aborting = true;
// 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, AllowAccessLater(this)));
-}
+ scriptExecutionContext()->postTask([this] (ScriptExecutionContext&) {
+ ASSERT(m_state != DONE);
-void FileReader::doAbort()
-{
- ASSERT(m_state != DONE);
-
- terminate();
- m_aborting = false;
+ terminate();
+ m_aborting = false;
- m_error = FileError::create(FileError::ABORT_ERR);
+ m_error = FileError::create(FileError::ABORT_ERR);
- fireEvent(eventNames().errorEvent);
- fireEvent(eventNames().abortEvent);
- fireEvent(eventNames().loadendEvent);
+ fireEvent(eventNames().errorEvent);
+ fireEvent(eventNames().abortEvent);
+ fireEvent(eventNames().loadendEvent);
- // All possible events have fired and we're done, no more pending activity.
- unsetPendingActivity(this);
+ // All possible events have fired and we're done, no more pending activity.
+ unsetPendingActivity(this);
+ });
}
void FileReader::terminate()
@@ -248,10 +241,10 @@ void FileReader::fireEvent(const AtomicString& type)
dispatchEvent(ProgressEvent::create(type, true, m_loader ? m_loader->bytesLoaded() : 0, m_loader ? m_loader->totalBytes() : 0));
}
-PassRefPtr<ArrayBuffer> FileReader::arrayBufferResult() const
+RefPtr<ArrayBuffer> FileReader::arrayBufferResult() const
{
if (!m_loader || m_error)
- return 0;
+ return nullptr;
return m_loader->arrayBufferResult();
}
@@ -263,5 +256,3 @@ String FileReader::stringResult()
}
} // namespace WebCore
-
-#endif // ENABLE(BLOB)
diff --git a/Source/WebCore/fileapi/FileReader.h b/Source/WebCore/fileapi/FileReader.h
index 789701635..27f4b6112 100644
--- a/Source/WebCore/fileapi/FileReader.h
+++ b/Source/WebCore/fileapi/FileReader.h
@@ -31,8 +31,6 @@
#ifndef FileReader_h
#define FileReader_h
-#if ENABLE(BLOB)
-
#include "ActiveDOMObject.h"
#include "EventTarget.h"
#include "FileError.h"
@@ -56,7 +54,7 @@ typedef int ExceptionCode;
class FileReader final : public RefCounted<FileReader>, public ActiveDOMObject, public EventTargetWithInlineData, public FileReaderLoaderClient {
public:
- static PassRefPtr<FileReader> create(ScriptExecutionContext&);
+ static Ref<FileReader> create(ScriptExecutionContext&);
virtual ~FileReader();
@@ -76,9 +74,9 @@ public:
void doAbort();
ReadyState readyState() const { return m_state; }
- PassRefPtr<FileError> error() { return m_error; }
+ RefPtr<FileError> error() { return m_error; }
FileReaderLoader::ReadType readType() const { return m_readType; }
- PassRefPtr<JSC::ArrayBuffer> arrayBufferResult() const;
+ RefPtr<JSC::ArrayBuffer> arrayBufferResult() const;
String stringResult();
// EventTarget
@@ -94,19 +92,13 @@ public:
using RefCounted<FileReader>::ref;
using RefCounted<FileReader>::deref;
- DEFINE_ATTRIBUTE_EVENT_LISTENER(loadstart);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(progress);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(load);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(error);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(loadend);
-
private:
explicit FileReader(ScriptExecutionContext&);
- // ActiveDOMObject
- virtual bool canSuspend() const override;
- virtual void stop() override;
+ // ActiveDOMObject API.
+ const char* activeDOMObjectName() const override;
+ bool canSuspendForDocumentSuspension() const override;
+ void stop() override;
// EventTarget
virtual void refEventTarget() override { ref(); }
@@ -129,6 +121,4 @@ private:
} // namespace WebCore
-#endif // ENABLE(BLOB)
-
#endif // FileReader_h
diff --git a/Source/WebCore/fileapi/FileReader.idl b/Source/WebCore/fileapi/FileReader.idl
index 6ad56e323..81ff25596 100644
--- a/Source/WebCore/fileapi/FileReader.idl
+++ b/Source/WebCore/fileapi/FileReader.idl
@@ -31,13 +31,10 @@
[
GlobalContext=DOMWindow&WorkerGlobalScope,
- Conditional=BLOB,
ActiveDOMObject,
Constructor,
ConstructorCallWith=ScriptExecutionContext,
- EventTarget,
- JSNoStaticTables,
-] interface FileReader {
+] interface FileReader : EventTarget {
// ready states
const unsigned short EMPTY = 0;
const unsigned short LOADING = 1;
@@ -57,19 +54,10 @@
readonly attribute FileError error;
- // EventTarget interface
- void addEventListener(DOMString type,
- EventListener listener,
- optional boolean useCapture);
- void removeEventListener(DOMString type,
- EventListener listener,
- optional boolean useCapture);
- [RaisesException] boolean dispatchEvent(Event evt);
-
- attribute EventListener onloadstart;
- attribute EventListener onprogress;
- attribute EventListener onload;
- attribute EventListener onabort;
- attribute EventListener onerror;
- attribute EventListener onloadend;
+ attribute EventHandler onloadstart;
+ attribute EventHandler onprogress;
+ attribute EventHandler onload;
+ attribute EventHandler onabort;
+ attribute EventHandler onerror;
+ attribute EventHandler onloadend;
};
diff --git a/Source/WebCore/fileapi/FileReaderLoader.cpp b/Source/WebCore/fileapi/FileReaderLoader.cpp
index 007ff70a9..a80a2ab12 100644
--- a/Source/WebCore/fileapi/FileReaderLoader.cpp
+++ b/Source/WebCore/fileapi/FileReaderLoader.cpp
@@ -30,13 +30,12 @@
#include "config.h"
-#if ENABLE(BLOB)
-
#include "FileReaderLoader.h"
#include "Blob.h"
#include "BlobURL.h"
#include "FileReaderLoaderClient.h"
+#include "HTTPHeaderNames.h"
#include "ResourceRequest.h"
#include "ResourceResponse.h"
#include "ScriptExecutionContext.h"
@@ -44,7 +43,6 @@
#include "ThreadableBlobRegistry.h"
#include "ThreadableLoader.h"
#include <runtime/ArrayBuffer.h>
-#include <wtf/PassRefPtr.h>
#include <wtf/RefPtr.h>
#include <wtf/Vector.h>
#include <wtf/text/Base64.h>
@@ -90,14 +88,16 @@ void FileReaderLoader::start(ScriptExecutionContext* scriptExecutionContext, Blo
ResourceRequest request(m_urlForReading);
request.setHTTPMethod("GET");
if (m_hasRange)
- request.setHTTPHeaderField("Range", String::format("bytes=%d-%d", m_rangeStart, m_rangeEnd));
+ request.setHTTPHeaderField(HTTPHeaderName::Range, String::format("bytes=%d-%d", m_rangeStart, m_rangeEnd));
ThreadableLoaderOptions options;
- options.sendLoadCallbacks = SendCallbacks;
- options.sniffContent = DoNotSniffContent;
+ options.setSendLoadCallbacks(SendCallbacks);
+ options.setSniffContent(DoNotSniffContent);
+ options.setDataBufferingPolicy(DoNotBufferData);
options.preflightPolicy = ConsiderPreflight;
- options.allowCredentials = AllowStoredCredentials;
+ options.setAllowCredentials(AllowStoredCredentials);
options.crossOriginRequestPolicy = DenyCrossOriginRequests;
+ options.contentSecurityPolicyEnforcement = ContentSecurityPolicyEnforcement::DoNotEnforce;
if (m_client)
m_loader = ThreadableLoader::create(scriptExecutionContext, this, request, options);
@@ -121,11 +121,11 @@ void FileReaderLoader::terminate()
void FileReaderLoader::cleanup()
{
- m_loader = 0;
+ m_loader = nullptr;
// If we get any error, we do not need to keep a buffer around.
if (m_errorCode) {
- m_rawData = 0;
+ m_rawData = nullptr;
m_stringResult = "";
}
}
@@ -137,11 +137,10 @@ void FileReaderLoader::didReceiveResponse(unsigned long, const ResourceResponse&
return;
}
- unsigned long long length = response.expectedContentLength();
+ long long length = response.expectedContentLength();
- // A value larger than INT_MAX means that the content length wasn't
- // specified, so the buffer will need to be dynamically grown.
- if (length > INT_MAX) {
+ // A negative value means that the content length wasn't specified, so the buffer will need to be dynamically grown.
+ if (length < 0) {
m_variableLength = true;
if (m_hasRange)
length = 1 + m_rangeEnd - m_rangeStart;
@@ -189,17 +188,26 @@ void FileReaderLoader::didReceiveData(const char* data, int dataLength)
return;
}
if (m_variableLength) {
- unsigned long long newLength = m_totalBytes * 2;
- if (newLength > std::numeric_limits<unsigned>::max())
- newLength = std::numeric_limits<unsigned>::max();
- RefPtr<ArrayBuffer> newData =
- ArrayBuffer::create(static_cast<unsigned>(newLength), 1);
+ unsigned newLength = m_totalBytes + static_cast<unsigned>(dataLength);
+ if (newLength < m_totalBytes) {
+ failed(FileError::NOT_READABLE_ERR);
+ return;
+ }
+ newLength = std::max(newLength, m_totalBytes + m_totalBytes / 4 + 1);
+ RefPtr<ArrayBuffer> newData = ArrayBuffer::create(newLength, 1);
+ if (!newData) {
+ // Not enough memory.
+ failed(FileError::NOT_READABLE_ERR);
+ return;
+ }
memcpy(static_cast<char*>(newData->data()), static_cast<char*>(m_rawData->data()), m_bytesLoaded);
m_rawData = newData;
m_totalBytes = static_cast<unsigned>(newLength);
- } else
+ } else {
+ // This can only happen if we get more data than indicated in expected content length (i.e. never, unless the networking layer is buggy).
length = remainingBufferSpace;
+ }
}
if (length <= 0)
@@ -256,13 +264,13 @@ FileError::ErrorCode FileReaderLoader::httpStatusCodeToErrorCode(int httpStatusC
}
}
-PassRefPtr<ArrayBuffer> FileReaderLoader::arrayBufferResult() const
+RefPtr<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;
+ return nullptr;
// If completed, we can simply return our buffer.
if (isCompleted())
@@ -316,21 +324,18 @@ void FileReaderLoader::convertToText()
// 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();
+ m_stringResult = m_decoder->decodeAndFlush(static_cast<const char*>(m_rawData->data()), m_bytesLoaded);
+ else
+ m_stringResult = m_decoder->decode(static_cast<const char*>(m_rawData->data()), m_bytesLoaded);
}
void FileReaderLoader::convertToDataURL()
{
StringBuilder builder;
- builder.append("data:");
+ builder.appendLiteral("data:");
if (!m_bytesLoaded) {
m_stringResult = builder.toString();
@@ -338,7 +343,7 @@ void FileReaderLoader::convertToDataURL()
}
builder.append(m_dataType);
- builder.append(";base64,");
+ builder.appendLiteral(";base64,");
Vector<char> out;
base64Encode(m_rawData->data(), m_bytesLoaded, out);
@@ -360,5 +365,3 @@ void FileReaderLoader::setEncoding(const String& encoding)
}
} // namespace WebCore
-
-#endif // ENABLE(BLOB)
diff --git a/Source/WebCore/fileapi/FileReaderLoader.h b/Source/WebCore/fileapi/FileReaderLoader.h
index 435662613..0bdf08c88 100644
--- a/Source/WebCore/fileapi/FileReaderLoader.h
+++ b/Source/WebCore/fileapi/FileReaderLoader.h
@@ -31,8 +31,6 @@
#ifndef FileReaderLoader_h
#define FileReaderLoader_h
-#if ENABLE(BLOB)
-
#include "FileError.h"
#include "URL.h"
#include "TextEncoding.h"
@@ -76,7 +74,7 @@ public:
virtual void didFail(const ResourceError&);
String stringResult();
- PassRefPtr<JSC::ArrayBuffer> arrayBufferResult() const;
+ RefPtr<JSC::ArrayBuffer> arrayBufferResult() const;
unsigned bytesLoaded() const { return m_bytesLoaded; }
unsigned totalBytes() const { return m_totalBytes; }
int errorCode() const { return m_errorCode; }
@@ -125,6 +123,4 @@ private:
} // namespace WebCore
-#endif // ENABLE(BLOB)
-
#endif // FileReaderLoader_h
diff --git a/Source/WebCore/fileapi/FileReaderLoaderClient.h b/Source/WebCore/fileapi/FileReaderLoaderClient.h
index 4acb8ad3a..fde658bbf 100644
--- a/Source/WebCore/fileapi/FileReaderLoaderClient.h
+++ b/Source/WebCore/fileapi/FileReaderLoaderClient.h
@@ -31,8 +31,6 @@
#ifndef FileReaderLoaderClient_h
#define FileReaderLoaderClient_h
-#if ENABLE(BLOB)
-
namespace WebCore {
class FileReaderLoaderClient {
@@ -47,6 +45,4 @@ public:
} // namespace WebCore
-#endif // ENABLE(BLOB)
-
#endif // FileReaderLoaderClient_h
diff --git a/Source/WebCore/fileapi/FileReaderSync.cpp b/Source/WebCore/fileapi/FileReaderSync.cpp
index 2d53afd1b..aec40f999 100644
--- a/Source/WebCore/fileapi/FileReaderSync.cpp
+++ b/Source/WebCore/fileapi/FileReaderSync.cpp
@@ -30,8 +30,6 @@
#include "config.h"
-#if ENABLE(BLOB)
-
#include "FileReaderSync.h"
#include "Blob.h"
@@ -39,7 +37,6 @@
#include "FileException.h"
#include "FileReaderLoader.h"
#include <runtime/ArrayBuffer.h>
-#include <wtf/PassRefPtr.h>
namespace WebCore {
@@ -47,11 +44,11 @@ FileReaderSync::FileReaderSync()
{
}
-PassRefPtr<ArrayBuffer> FileReaderSync::readAsArrayBuffer(ScriptExecutionContext* scriptExecutionContext, Blob* blob, ExceptionCode& ec)
+RefPtr<ArrayBuffer> FileReaderSync::readAsArrayBuffer(ScriptExecutionContext* scriptExecutionContext, Blob* blob, ExceptionCode& ec)
{
if (!blob) {
ec = NOT_FOUND_ERR;
- return 0;
+ return nullptr;
}
FileReaderLoader loader(FileReaderLoader::ReadAsArrayBuffer, 0);
@@ -105,5 +102,3 @@ void FileReaderSync::startLoading(ScriptExecutionContext* scriptExecutionContext
}
} // namespace WebCore
-
-#endif // ENABLE(BLOB)
diff --git a/Source/WebCore/fileapi/FileReaderSync.h b/Source/WebCore/fileapi/FileReaderSync.h
index 50140efcd..ba35e6910 100644
--- a/Source/WebCore/fileapi/FileReaderSync.h
+++ b/Source/WebCore/fileapi/FileReaderSync.h
@@ -31,8 +31,6 @@
#ifndef FileReaderSync_h
#define FileReaderSync_h
-#if ENABLE(BLOB)
-
#include <wtf/Forward.h>
#include <wtf/RefCounted.h>
#include <wtf/text/WTFString.h>
@@ -51,14 +49,14 @@ typedef int ExceptionCode;
class FileReaderSync : public RefCounted<FileReaderSync> {
public:
- static PassRefPtr<FileReaderSync> create()
+ static Ref<FileReaderSync> create()
{
- return adoptRef(new FileReaderSync());
+ return adoptRef(*new FileReaderSync);
}
virtual ~FileReaderSync() { }
- PassRefPtr<JSC::ArrayBuffer> readAsArrayBuffer(ScriptExecutionContext*, Blob*, ExceptionCode&);
+ RefPtr<JSC::ArrayBuffer> readAsArrayBuffer(ScriptExecutionContext*, Blob*, ExceptionCode&);
String readAsBinaryString(ScriptExecutionContext*, Blob*, ExceptionCode&);
String readAsText(ScriptExecutionContext* scriptExecutionContext, Blob* blob, ExceptionCode& ec)
{
@@ -75,6 +73,4 @@ private:
} // namespace WebCore
-#endif // ENABLE(BLOB)
-
#endif // FileReaderSync_h
diff --git a/Source/WebCore/fileapi/FileReaderSync.idl b/Source/WebCore/fileapi/FileReaderSync.idl
index 184f32200..5a028240c 100644
--- a/Source/WebCore/fileapi/FileReaderSync.idl
+++ b/Source/WebCore/fileapi/FileReaderSync.idl
@@ -30,9 +30,7 @@
[
GlobalContext=WorkerGlobalScope,
- Conditional=BLOB,
Constructor,
- JSNoStaticTables,
] interface FileReaderSync {
[CallWith=ScriptExecutionContext, RaisesException] ArrayBuffer readAsArrayBuffer(Blob blob);
[CallWith=ScriptExecutionContext, RaisesException] DOMString readAsBinaryString(Blob blob);
diff --git a/Source/WebCore/fileapi/FileThread.cpp b/Source/WebCore/fileapi/FileThread.cpp
deleted file mode 100644
index e43f0e72d..000000000
--- a/Source/WebCore/fileapi/FileThread.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(BLOB)
-
-#include "FileThread.h"
-
-#include "Logging.h"
-#include <wtf/AutodrainedPool.h>
-
-namespace WebCore {
-
-FileThread::FileThread()
- : m_threadID(0)
-{
- m_selfRef = this;
-}
-
-FileThread::~FileThread()
-{
- ASSERT(m_queue.killed());
-}
-
-bool FileThread::start()
-{
- MutexLocker lock(m_threadCreationMutex);
- if (m_threadID)
- return true;
- m_threadID = createThread(FileThread::fileThreadStart, this, "WebCore: File");
- return m_threadID;
-}
-
-void FileThread::stop()
-{
- m_queue.kill();
-}
-
-void FileThread::postTask(std::unique_ptr<Task> task)
-{
- m_queue.append(std::move(task));
-}
-
-class SameInstancePredicate {
-public:
- SameInstancePredicate(const void* instance) : m_instance(instance) { }
- bool operator()(FileThread::Task& task) const { return task.instance() == m_instance; }
-private:
- const void* m_instance;
-};
-
-void FileThread::unscheduleTasks(const void* instance)
-{
- SameInstancePredicate predicate(instance);
- m_queue.removeIf(predicate);
-}
-
-void FileThread::fileThreadStart(void* arg)
-{
- FileThread* fileThread = static_cast<FileThread*>(arg);
- fileThread->runLoop();
-}
-
-void FileThread::runLoop()
-{
- {
- // Wait for FileThread::start() to complete to have m_threadID
- // established before starting the main loop.
- MutexLocker lock(m_threadCreationMutex);
- LOG(FileAPI, "Started FileThread %p", this);
- }
-
- while (auto task = m_queue.waitForMessage()) {
- AutodrainedPool pool;
-
- task->performTask();
- }
-
- LOG(FileAPI, "About to detach thread %i and clear the ref to FileThread %p, which currently has %i ref(s)", m_threadID, this, refCount());
-
- detachThread(m_threadID);
-
- // Clear the self refptr, possibly resulting in deletion
- m_selfRef = 0;
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(BLOB)
diff --git a/Source/WebCore/fileapi/FileThread.h b/Source/WebCore/fileapi/FileThread.h
deleted file mode 100644
index 4b9739e4f..000000000
--- a/Source/WebCore/fileapi/FileThread.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FileThread_h
-#define FileThread_h
-
-#if ENABLE(BLOB)
-
-#include <wtf/MessageQueue.h>
-#include <wtf/PassRefPtr.h>
-#include <wtf/Threading.h>
-
-namespace WebCore {
-
-class FileStream;
-
-class FileThread : public ThreadSafeRefCounted<FileThread> {
-public:
- static PassRefPtr<FileThread> create()
- {
- return adoptRef(new FileThread());
- }
-
- ~FileThread();
-
- bool start();
- void stop();
-
- class Task {
- WTF_MAKE_NONCOPYABLE(Task);
- public:
- virtual ~Task() { }
- virtual void performTask() = 0;
- void* instance() const { return m_instance; }
- protected:
- Task(void* instance) : m_instance(instance) { }
- void* m_instance;
- };
-
- void postTask(std::unique_ptr<Task>);
-
- void unscheduleTasks(const void* instance);
-
-private:
- FileThread();
-
- static void fileThreadStart(void*);
- void runLoop();
-
- ThreadIdentifier m_threadID;
- RefPtr<FileThread> m_selfRef;
- MessageQueue<Task> m_queue;
-
- Mutex m_threadCreationMutex;
-};
-
-} // namespace WebCore
-
-#endif // ENABLE(BLOB)
-
-#endif // FileThread_h
diff --git a/Source/WebCore/fileapi/FileThreadTask.h b/Source/WebCore/fileapi/FileThreadTask.h
deleted file mode 100644
index a0541dff9..000000000
--- a/Source/WebCore/fileapi/FileThreadTask.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FileThreadTask_h
-#define FileThreadTask_h
-
-#include "CrossThreadCopier.h"
-#include "CrossThreadTask.h"
-#include "FileThread.h"
-#include <wtf/PassRefPtr.h>
-
-namespace WebCore {
-
-template<typename T>
-class FileThreadTask0 : public FileThread::Task {
-public:
- typedef void (T::*Method)();
- typedef FileThreadTask0<T> FileThreadTaskImpl;
-
- FileThreadTask0(T* instance, Method method)
- : FileThread::Task(instance)
- , m_method(method)
- {
- }
-
-private:
- virtual void performTask() override
- {
- (*static_cast<T*>(instance()).*m_method)();
- }
-
-private:
- Method m_method;
-};
-
-template<typename T, typename P1, typename MP1>
-class FileThreadTask1 : public FileThread::Task {
-public:
- typedef void (T::*Method)(MP1);
- typedef FileThreadTask1<T, P1, MP1> FileThreadTaskImpl;
- typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
-
- FileThreadTask1(T* instance, Method method, Param1 parameter1)
- : FileThread::Task(instance)
- , m_method(method)
- , m_parameter1(parameter1)
- {
- }
-
-private:
- virtual void performTask() override
- {
- (*static_cast<T*>(instance()).*m_method)(m_parameter1);
- }
-
-private:
- Method m_method;
- P1 m_parameter1;
-};
-
-template<typename T, typename P1, typename MP1, typename P2, typename MP2>
-class FileThreadTask2 : public FileThread::Task {
-public:
- typedef void (T::*Method)(MP1, MP2);
- typedef FileThreadTask2<T, P1, MP1, P2, MP2> FileThreadTaskImpl;
- typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
- typedef typename CrossThreadTaskTraits<P2>::ParamType Param2;
-
- FileThreadTask2(T* instance, Method method, Param1 parameter1, Param2 parameter2)
- : FileThread::Task(instance)
- , m_method(method)
- , m_parameter1(parameter1)
- , m_parameter2(parameter2)
- {
- }
-
-private:
- virtual void performTask() override
- {
- (*static_cast<T*>(instance()).*m_method)(m_parameter1, m_parameter2);
- }
-
-private:
- Method m_method;
- P1 m_parameter1;
- P2 m_parameter2;
-};
-
-template<typename T, typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3>
-class FileThreadTask3 : public FileThread::Task {
-public:
- typedef void (T::*Method)(MP1, MP2, MP3);
- typedef FileThreadTask3<T, P1, MP1, P2, MP2, P3, MP3> FileThreadTaskImpl;
- typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
- typedef typename CrossThreadTaskTraits<P2>::ParamType Param2;
- typedef typename CrossThreadTaskTraits<P3>::ParamType Param3;
-
- FileThreadTask3(T* instance, Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3)
- : FileThread::Task(instance)
- , m_method(method)
- , m_parameter1(parameter1)
- , m_parameter2(parameter2)
- , m_parameter3(parameter3)
- {
- }
-
-private:
- virtual void performTask() override
- {
- (*static_cast<T*>(instance()).*m_method)(m_parameter1, m_parameter2, m_parameter3);
- }
-
-private:
- Method m_method;
- P1 m_parameter1;
- P2 m_parameter2;
- P3 m_parameter3;
-};
-
-template<typename T>
-std::unique_ptr<FileThread::Task> createFileThreadTask(
- T* const callee,
- void (T::*method)());
-
-template<typename T>
-std::unique_ptr<FileThread::Task> createFileThreadTask(
- T* const callee,
- void (T::*method)())
-{
- return std::make_unique<FileThreadTask0<T>>(
- callee,
- method);
-}
-
-template<typename T, typename P1, typename MP1>
-std::unique_ptr<FileThread::Task> createFileThreadTask(
- T* const callee,
- void (T::*method)(MP1),
- const P1& parameter1)
-{
- return std::make_unique<FileThreadTask1<T, typename CrossThreadCopier<P1>::Type, MP1>>(
- callee,
- method,
- CrossThreadCopier<P1>::copy(parameter1));
-}
-
-template<typename T, typename P1, typename MP1, typename P2, typename MP2>
-std::unique_ptr<FileThread::Task> createFileThreadTask(
- T* const callee,
- void (T::*method)(MP1, MP2),
- const P1& parameter1,
- const P2& parameter2)
-{
- return std::make_unique<FileThreadTask2<T, typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2>>(
- callee,
- method,
- CrossThreadCopier<P1>::copy(parameter1),
- CrossThreadCopier<P2>::copy(parameter2));
-}
-
-template<typename T, typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3>
-std::unique_ptr<FileThread::Task> createFileThreadTask(
- T* const callee,
- void (T::*method)(MP1, MP2, MP3),
- const P1& parameter1,
- const P2& parameter2,
- const P3& parameter3)
-{
- return std::make_unique<FileThreadTask3<T, typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3>>(
- callee,
- method,
- CrossThreadCopier<P1>::copy(parameter1),
- CrossThreadCopier<P2>::copy(parameter2),
- CrossThreadCopier<P3>::copy(parameter3));
-}
-
-} // namespace WebCore
-
-#endif // FileThreadTask_h
diff --git a/Source/WebCore/fileapi/ThreadableBlobRegistry.cpp b/Source/WebCore/fileapi/ThreadableBlobRegistry.cpp
index 19844412e..71880cabe 100644
--- a/Source/WebCore/fileapi/ThreadableBlobRegistry.cpp
+++ b/Source/WebCore/fileapi/ThreadableBlobRegistry.cpp
@@ -31,7 +31,8 @@
#include "config.h"
#include "ThreadableBlobRegistry.h"
-#include "BlobData.h"
+#include "BlobDataFileReference.h"
+#include "BlobPart.h"
#include "BlobRegistry.h"
#include "BlobURL.h"
#include "SecurityOrigin.h"
@@ -41,6 +42,7 @@
#include <wtf/RefPtr.h>
#include <wtf/ThreadSpecific.h>
#include <wtf/text/StringHash.h>
+#include <wtf/threads/BinarySemaphore.h>
using WTF::ThreadSpecific;
@@ -49,31 +51,40 @@ namespace WebCore {
struct BlobRegistryContext {
WTF_MAKE_FAST_ALLOCATED;
public:
- BlobRegistryContext(const URL& url, std::unique_ptr<BlobData> blobData)
- : url(url.copy())
- , blobData(std::move(blobData))
+ BlobRegistryContext(const URL& url, Vector<BlobPart> blobParts, const String& contentType)
+ : url(url.isolatedCopy())
+ , contentType(contentType.isolatedCopy())
+ , blobParts(WTFMove(blobParts))
{
- this->blobData->detachFromCurrentThread();
+ for (BlobPart& part : blobParts)
+ part.detachFromCurrentThread();
}
BlobRegistryContext(const URL& url, const URL& srcURL)
- : url(url.copy())
- , srcURL(srcURL.copy())
+ : url(url.isolatedCopy())
+ , srcURL(srcURL.isolatedCopy())
{
}
BlobRegistryContext(const URL& url)
- : url(url.copy())
+ : url(url.isolatedCopy())
+ {
+ }
+
+ BlobRegistryContext(const URL& url, const String& path, const String& contentType)
+ : url(url.isolatedCopy())
+ , path(path.isolatedCopy())
+ , contentType(contentType.isolatedCopy())
{
}
URL url;
URL srcURL;
- std::unique_ptr<BlobData> blobData;
+ String path;
+ String contentType;
+ Vector<BlobPart> blobParts;
};
-#if ENABLE(BLOB)
-
typedef HashMap<String, RefPtr<SecurityOrigin>> BlobUrlOriginMap;
static ThreadSpecific<BlobUrlOriginMap>& originMap()
@@ -87,24 +98,32 @@ static ThreadSpecific<BlobUrlOriginMap>& originMap()
return *map;
}
-static void registerBlobURLTask(void* context)
-{
- std::unique_ptr<BlobRegistryContext> blobRegistryContext(static_cast<BlobRegistryContext*>(context));
- blobRegistry().registerBlobURL(blobRegistryContext->url, std::move(blobRegistryContext->blobData));
-}
-
-void ThreadableBlobRegistry::registerBlobURL(const URL& url, std::unique_ptr<BlobData> blobData)
+void ThreadableBlobRegistry::registerFileBlobURL(const URL& url, const String& path, const String& contentType)
{
if (isMainThread())
- blobRegistry().registerBlobURL(url, std::move(blobData));
- else
- callOnMainThread(&registerBlobURLTask, new BlobRegistryContext(url, std::move(blobData)));
+ blobRegistry().registerFileBlobURL(url, BlobDataFileReference::create(path), contentType);
+ else {
+ // BlobRegistryContext performs an isolated copy of data.
+ BlobRegistryContext* context = new BlobRegistryContext(url, path, contentType);
+ callOnMainThread([context] {
+ std::unique_ptr<BlobRegistryContext> blobRegistryContext(context);
+ blobRegistry().registerFileBlobURL(blobRegistryContext->url, BlobDataFileReference::create(blobRegistryContext->path), blobRegistryContext->contentType);
+ });
+ }
}
-static void registerBlobURLFromTask(void* context)
+void ThreadableBlobRegistry::registerBlobURL(const URL& url, Vector<BlobPart> blobParts, const String& contentType)
{
- std::unique_ptr<BlobRegistryContext> blobRegistryContext(static_cast<BlobRegistryContext*>(context));
- blobRegistry().registerBlobURL(blobRegistryContext->url, blobRegistryContext->srcURL);
+ if (isMainThread())
+ blobRegistry().registerBlobURL(url, WTFMove(blobParts), contentType);
+ else {
+ // BlobRegistryContext performs an isolated copy of data.
+ BlobRegistryContext* context = new BlobRegistryContext(url, WTFMove(blobParts), contentType);
+ callOnMainThread([context] {
+ std::unique_ptr<BlobRegistryContext> blobRegistryContext(context);
+ blobRegistry().registerBlobURL(blobRegistryContext->url, WTFMove(blobRegistryContext->blobParts), blobRegistryContext->contentType);
+ });
+ }
}
void ThreadableBlobRegistry::registerBlobURL(SecurityOrigin* origin, const URL& url, const URL& srcURL)
@@ -115,14 +134,47 @@ void ThreadableBlobRegistry::registerBlobURL(SecurityOrigin* origin, const URL&
if (isMainThread())
blobRegistry().registerBlobURL(url, srcURL);
- else
- callOnMainThread(&registerBlobURLFromTask, new BlobRegistryContext(url, srcURL));
+ else {
+ // BlobRegistryContext performs an isolated copy of data.
+ BlobRegistryContext* context = new BlobRegistryContext(url, srcURL);
+ callOnMainThread([context] {
+ std::unique_ptr<BlobRegistryContext> blobRegistryContext(context);
+ blobRegistry().registerBlobURL(blobRegistryContext->url, blobRegistryContext->srcURL);
+ });
+ }
}
-static void unregisterBlobURLTask(void* context)
+void ThreadableBlobRegistry::registerBlobURLForSlice(const URL& newURL, const URL& srcURL, long long start, long long end)
{
- std::unique_ptr<BlobRegistryContext> blobRegistryContext(static_cast<BlobRegistryContext*>(context));
- blobRegistry().unregisterBlobURL(blobRegistryContext->url);
+ if (isMainThread())
+ blobRegistry().registerBlobURLForSlice(newURL, srcURL, start, end);
+ else {
+ // BlobRegistryContext performs an isolated copy of data.
+ BlobRegistryContext* context = new BlobRegistryContext(newURL, srcURL);
+ callOnMainThread([context, start, end] {
+ std::unique_ptr<BlobRegistryContext> blobRegistryContext(context);
+ blobRegistry().registerBlobURLForSlice(blobRegistryContext->url, blobRegistryContext->srcURL, start, end);
+ });
+ }
+}
+
+unsigned long long ThreadableBlobRegistry::blobSize(const URL& url)
+{
+ unsigned long long resultSize;
+ if (isMainThread())
+ resultSize = blobRegistry().blobSize(url);
+ else {
+ // BlobRegistryContext performs an isolated copy of data.
+ BlobRegistryContext* context = new BlobRegistryContext(url);
+ BinarySemaphore semaphore;
+ callOnMainThread([context, &semaphore, &resultSize] {
+ std::unique_ptr<BlobRegistryContext> blobRegistryContext(context);
+ resultSize = blobRegistry().blobSize(blobRegistryContext->url);
+ semaphore.signal();
+ });
+ semaphore.wait(std::numeric_limits<double>::max());
+ }
+ return resultSize;
}
void ThreadableBlobRegistry::unregisterBlobURL(const URL& url)
@@ -132,34 +184,19 @@ void ThreadableBlobRegistry::unregisterBlobURL(const URL& url)
if (isMainThread())
blobRegistry().unregisterBlobURL(url);
- else
- callOnMainThread(&unregisterBlobURLTask, new BlobRegistryContext(url));
+ else {
+ // BlobRegistryContext performs an isolated copy of data.
+ BlobRegistryContext* context = new BlobRegistryContext(url);
+ callOnMainThread([context] {
+ std::unique_ptr<BlobRegistryContext> blobRegistryContext(context);
+ blobRegistry().unregisterBlobURL(blobRegistryContext->url);
+ });
+ }
}
-PassRefPtr<SecurityOrigin> ThreadableBlobRegistry::getCachedOrigin(const URL& url)
+RefPtr<SecurityOrigin> ThreadableBlobRegistry::getCachedOrigin(const URL& url)
{
return originMap()->get(url.string());
}
-#else
-
-void ThreadableBlobRegistry::registerBlobURL(const URL&, std::unique_ptr<BlobData>)
-{
-}
-
-void ThreadableBlobRegistry::registerBlobURL(SecurityOrigin*, const URL&, const URL&)
-{
-}
-
-void ThreadableBlobRegistry::unregisterBlobURL(const URL&)
-{
-}
-
-PassRefPtr<SecurityOrigin> ThreadableBlobRegistry::getCachedOrigin(const URL&)
-{
- return 0;
-}
-
-#endif // ENABL(BLOB)
-
} // namespace WebCore
diff --git a/Source/WebCore/fileapi/ThreadableBlobRegistry.h b/Source/WebCore/fileapi/ThreadableBlobRegistry.h
index e2e5c694b..8ec9764ca 100644
--- a/Source/WebCore/fileapi/ThreadableBlobRegistry.h
+++ b/Source/WebCore/fileapi/ThreadableBlobRegistry.h
@@ -31,23 +31,28 @@
#ifndef ThreadableBlobRegistry_h
#define ThreadableBlobRegistry_h
-#include <wtf/PassRefPtr.h>
+#include <wtf/Forward.h>
+#include <wtf/Vector.h>
namespace WebCore {
-class BlobData;
+class BlobPart;
class URL;
class SecurityOrigin;
class ThreadableBlobRegistry {
public:
- static void registerBlobURL(const URL&, std::unique_ptr<BlobData>);
+ static void registerFileBlobURL(const URL&, const String& path, const String& contentType);
+ static void registerBlobURL(const URL&, Vector<BlobPart> blobParts, const String& contentType);
static void registerBlobURL(SecurityOrigin*, const URL&, const URL& srcURL);
+ static void registerBlobURLForSlice(const URL& newURL, const URL& srcURL, long long start, long long end);
static void unregisterBlobURL(const URL&);
+ static unsigned long long blobSize(const URL&);
+
// Returns the origin for the given blob URL. This is because we are not able to embed the unique security origin or the origin of file URL
// in the blob URL.
- static PassRefPtr<SecurityOrigin> getCachedOrigin(const URL&);
+ static RefPtr<SecurityOrigin> getCachedOrigin(const URL&);
};
} // namespace WebCore
diff --git a/Source/WebCore/fileapi/WebKitBlobBuilder.cpp b/Source/WebCore/fileapi/WebKitBlobBuilder.cpp
index c47eb1f51..86608c695 100644
--- a/Source/WebCore/fileapi/WebKitBlobBuilder.cpp
+++ b/Source/WebCore/fileapi/WebKitBlobBuilder.cpp
@@ -29,28 +29,23 @@
*/
#include "config.h"
-
#include "WebKitBlobBuilder.h"
#include "Blob.h"
#include "Document.h"
#include "ExceptionCode.h"
#include "File.h"
-#include "HistogramSupport.h"
#include "LineEnding.h"
-#include "ScriptCallStack.h"
#include "TextEncoding.h"
#include <runtime/ArrayBuffer.h>
#include <runtime/ArrayBufferView.h>
-#include <wtf/PassRefPtr.h>
#include <wtf/Vector.h>
#include <wtf/text/AtomicString.h>
#include <wtf/text/CString.h>
+#include <wtf/text/StringView.h>
namespace WebCore {
-// FIXME: Move this file to BlobBuilder.cpp
-
enum BlobConstructorArrayBufferOrView {
BlobConstructorArrayBuffer,
BlobConstructorArrayBufferView,
@@ -58,99 +53,51 @@ enum BlobConstructorArrayBufferOrView {
};
BlobBuilder::BlobBuilder()
- : m_size(0)
{
}
-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)
{
- CString utf8Text = UTF8Encoding().encode(text.deprecatedCharacters(), text.length(), EntitiesForUnencodables);
-
- Vector<char>& buffer = getBuffer();
- size_t oldSize = buffer.size();
+ CString utf8Text = UTF8Encoding().encode(text, EntitiesForUnencodables);
if (endingType == "native")
- normalizeLineEndingsToNative(utf8Text, buffer);
+ normalizeLineEndingsToNative(utf8Text, m_appendableData);
else {
ASSERT(endingType == "transparent");
- buffer.append(utf8Text.data(), utf8Text.length());
+ m_appendableData.append(utf8Text.data(), utf8Text.length());
}
- m_size += buffer.size() - oldSize;
}
-#if ENABLE(BLOB)
void BlobBuilder::append(ArrayBuffer* arrayBuffer)
{
- HistogramSupport::histogramEnumeration("WebCore.Blob.constructor.ArrayBufferOrView", BlobConstructorArrayBuffer, BlobConstructorArrayBufferOrViewMax);
-
if (!arrayBuffer)
return;
- appendBytesData(arrayBuffer->data(), arrayBuffer->byteLength());
+ m_appendableData.append(static_cast<const char*>(arrayBuffer->data()), arrayBuffer->byteLength());
}
-void BlobBuilder::append(PassRefPtr<ArrayBufferView> arrayBufferView)
+void BlobBuilder::append(RefPtr<ArrayBufferView>&& arrayBufferView)
{
- HistogramSupport::histogramEnumeration("WebCore.Blob.constructor.ArrayBufferOrView", BlobConstructorArrayBufferView, BlobConstructorArrayBufferOrViewMax);
-
if (!arrayBufferView)
return;
- appendBytesData(arrayBufferView->baseAddress(), arrayBufferView->byteLength());
+ m_appendableData.append(static_cast<const char*>(arrayBufferView->baseAddress()), arrayBufferView->byteLength());
}
-#endif
void BlobBuilder::append(Blob* blob)
{
if (!blob)
return;
- if (blob->isFile()) {
- File* file = toFile(blob);
- // 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.
- long long snapshotSize;
- double snapshotModificationTime;
- file->captureSnapshot(snapshotSize, snapshotModificationTime);
-
- m_size += snapshotSize;
- m_items.append(BlobDataItem(file->path(), 0, snapshotSize, snapshotModificationTime));
- } else {
- long long blobSize = static_cast<long long>(blob->size());
- m_size += blobSize;
- m_items.append(BlobDataItem(blob->url(), 0, blobSize));
- }
-}
-
-void BlobBuilder::appendBytesData(const void* data, size_t length)
-{
- Vector<char>& buffer = getBuffer();
- size_t oldSize = buffer.size();
- buffer.append(static_cast<const char*>(data), length);
- m_size += buffer.size() - oldSize;
+ if (!m_appendableData.isEmpty())
+ m_items.append(BlobPart(WTFMove(m_appendableData)));
+ m_items.append(BlobPart(blob->url()));
}
-PassRefPtr<Blob> BlobBuilder::getBlob(const String& contentType)
+Vector<BlobPart> BlobBuilder::finalize()
{
- auto blobData = std::make_unique<BlobData>();
- blobData->setContentType(Blob::normalizedContentType(contentType));
- blobData->swapItems(m_items);
-
- RefPtr<Blob> blob = Blob::create(std::move(blobData), m_size);
-
- // After creating a blob from the current blob data, we do not need to keep the data around any more. Instead, we only
- // need to keep a reference to the URL of the blob just created.
- m_items.append(BlobDataItem(blob->url(), 0, m_size));
-
- return blob;
+ if (!m_appendableData.isEmpty())
+ m_items.append(BlobPart(WTFMove(m_appendableData)));
+ return WTFMove(m_items);
}
} // namespace WebCore
diff --git a/Source/WebCore/fileapi/WebKitBlobBuilder.h b/Source/WebCore/fileapi/WebKitBlobBuilder.h
index bd2bbdfd9..ba87b3dfe 100644
--- a/Source/WebCore/fileapi/WebKitBlobBuilder.h
+++ b/Source/WebCore/fileapi/WebKitBlobBuilder.h
@@ -31,8 +31,7 @@
#ifndef WebKitBlobBuilder_h
#define WebKitBlobBuilder_h
-#include "BlobData.h"
-#include <wtf/Forward.h>
+#include "BlobPart.h"
namespace JSC {
class ArrayBuffer;
@@ -41,12 +40,7 @@ class ArrayBufferView;
namespace WebCore {
-// FIXME: Move this file to BlobBuilder.h
-
class Blob;
-class TextEncoding;
-
-typedef int ExceptionCode;
class BlobBuilder {
public:
@@ -54,20 +48,14 @@ public:
void append(Blob*);
void append(const String& text, const String& ending);
-#if ENABLE(BLOB)
void append(JSC::ArrayBuffer*);
- void append(PassRefPtr<JSC::ArrayBufferView>);
-#endif
+ void append(RefPtr<JSC::ArrayBufferView>&&);
- PassRefPtr<Blob> getBlob(const String& contentType);
+ Vector<BlobPart> finalize();
private:
- void appendBytesData(const void*, size_t);
-
- Vector<char>& getBuffer();
-
- long long m_size;
- BlobDataItemList m_items;
+ Vector<BlobPart> m_items;
+ Vector<uint8_t> m_appendableData;
};
} // namespace WebCore