summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/fileapi
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-05-15 10:20:33 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-05-15 10:28:57 +0000
commitd17ea114e5ef69ad5d5d7413280a13e6428098aa (patch)
tree2c01a75df69f30d27b1432467cfe7c1467a498da /chromium/third_party/blink/renderer/core/fileapi
parent8c5c43c7b138c9b4b0bf56d946e61d3bbc111bec (diff)
downloadqtwebengine-chromium-d17ea114e5ef69ad5d5d7413280a13e6428098aa.tar.gz
BASELINE: Update Chromium to 67.0.3396.47
Change-Id: Idcb1341782e417561a2473eeecc82642dafda5b7 Reviewed-by: Michal Klocek <michal.klocek@qt.io>
Diffstat (limited to 'chromium/third_party/blink/renderer/core/fileapi')
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/BUILD.gn51
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/OWNERS6
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/blob.cc217
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/blob.h144
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/blob.idl45
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/blob_property_bag.idl12
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file.cc382
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file.h255
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file.idl40
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_error.cc186
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_error.h78
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_list.cc57
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_list.h61
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_list.idl33
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_list_test.cc64
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_property_bag.idl9
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_reader.cc480
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_reader.h140
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_reader.idl68
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.cc431
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.h172
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_reader_loader_client.h59
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_reader_sync.cc123
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_reader_sync.h70
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_reader_sync.idl43
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_test.cc97
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/public_url_manager.cc209
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/public_url_manager.h94
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/public_url_manager_test.cc174
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/url_file_api.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/url_file_api.h27
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/url_file_api.idl11
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/url_registry.h72
33 files changed, 3950 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/core/fileapi/BUILD.gn b/chromium/third_party/blink/renderer/core/fileapi/BUILD.gn
new file mode 100644
index 00000000000..d6b3ff11937
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/BUILD.gn
@@ -0,0 +1,51 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/blink/renderer/core/core.gni")
+
+blink_core_sources("fileapi") {
+ sources = [
+ "blob.cc",
+ "blob.h",
+ "file.cc",
+ "file.h",
+ "file_error.cc",
+ "file_error.h",
+ "file_list.cc",
+ "file_list.h",
+ "file_reader.cc",
+ "file_reader.h",
+ "file_reader_loader.cc",
+ "file_reader_loader.h",
+ "file_reader_loader_client.h",
+ "file_reader_sync.cc",
+ "file_reader_sync.h",
+ "public_url_manager.cc",
+ "public_url_manager.h",
+ "url_file_api.cc",
+ "url_file_api.h",
+ "url_registry.h",
+ ]
+}
+
+jumbo_source_set("unit_tests") {
+ testonly = true
+ sources = [
+ "file_list_test.cc",
+ "file_test.cc",
+ "public_url_manager_test.cc",
+ ]
+
+ configs += [
+ "//third_party/blink/renderer/core:blink_core_pch",
+ "//third_party/blink/renderer:config",
+ "//third_party/blink/renderer:inside_blink",
+ ]
+
+ deps = [
+ "//testing/gmock",
+ "//testing/gtest",
+ "//third_party/blink/renderer/core",
+ ]
+}
diff --git a/chromium/third_party/blink/renderer/core/fileapi/OWNERS b/chromium/third_party/blink/renderer/core/fileapi/OWNERS
new file mode 100644
index 00000000000..75048f422da
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/OWNERS
@@ -0,0 +1,6 @@
+jsbell@chromium.org
+mek@chromium.org
+pwnall@chromium.org
+
+# TEAM: storage-dev@chromium.org
+# COMPONENT: Blink>FileAPI
diff --git a/chromium/third_party/blink/renderer/core/fileapi/blob.cc b/chromium/third_party/blink/renderer/core/fileapi/blob.cc
new file mode 100644
index 00000000000..5839473349f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/blob.cc
@@ -0,0 +1,217 @@
+/*
+ * 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 "third_party/blink/renderer/core/fileapi/blob.h"
+
+#include <memory>
+#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/fileapi/blob_property_bag.h"
+#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/core/url/dom_url.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/blob/blob_registry.h"
+#include "third_party/blink/renderer/platform/blob/blob_url.h"
+
+namespace blink {
+
+class BlobURLRegistry final : public URLRegistry {
+ public:
+ // SecurityOrigin is passed together with KURL so that the registry can
+ // save it for entries from whose KURL the origin is not recoverable by
+ // using BlobURL::getOrigin().
+ void RegisterURL(SecurityOrigin*, const KURL&, URLRegistrable*) override;
+ void UnregisterURL(const KURL&) override;
+
+ static URLRegistry& Registry();
+};
+
+void BlobURLRegistry::RegisterURL(SecurityOrigin* origin,
+ const KURL& public_url,
+ URLRegistrable* registrable_object) {
+ DCHECK_EQ(&registrable_object->Registry(), this);
+ Blob* blob = static_cast<Blob*>(registrable_object);
+ BlobRegistry::RegisterPublicBlobURL(origin, public_url,
+ blob->GetBlobDataHandle());
+}
+
+void BlobURLRegistry::UnregisterURL(const KURL& public_url) {
+ BlobRegistry::RevokePublicBlobURL(public_url);
+}
+
+URLRegistry& BlobURLRegistry::Registry() {
+ // This is called on multiple threads.
+ // (This code assumes it is safe to register or unregister URLs on
+ // BlobURLRegistry (that is implemented by the embedder) on
+ // multiple threads.)
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(BlobURLRegistry, instance, ());
+ return instance;
+}
+
+Blob::Blob(scoped_refptr<BlobDataHandle> data_handle)
+ : blob_data_handle_(std::move(data_handle)) {}
+
+Blob::~Blob() = default;
+
+// static
+Blob* Blob::Create(
+ ExecutionContext* context,
+ const HeapVector<ArrayBufferOrArrayBufferViewOrBlobOrUSVString>& blob_parts,
+ const BlobPropertyBag& options,
+ ExceptionState& exception_state) {
+ DCHECK(options.hasType());
+
+ DCHECK(options.hasEndings());
+ bool normalize_line_endings_to_native = options.endings() == "native";
+ if (normalize_line_endings_to_native)
+ UseCounter::Count(context, WebFeature::kFileAPINativeLineEndings);
+
+ std::unique_ptr<BlobData> blob_data = BlobData::Create();
+ blob_data->SetContentType(NormalizeType(options.type()));
+
+ PopulateBlobData(blob_data.get(), blob_parts,
+ normalize_line_endings_to_native);
+
+ long long blob_size = blob_data->length();
+ return new Blob(BlobDataHandle::Create(std::move(blob_data), blob_size));
+}
+
+Blob* Blob::Create(const unsigned char* data,
+ size_t bytes,
+ const String& content_type) {
+ DCHECK(data);
+
+ std::unique_ptr<BlobData> blob_data = BlobData::Create();
+ blob_data->SetContentType(content_type);
+ blob_data->AppendBytes(data, bytes);
+ long long blob_size = blob_data->length();
+
+ return new Blob(BlobDataHandle::Create(std::move(blob_data), blob_size));
+}
+
+// static
+void Blob::PopulateBlobData(
+ BlobData* blob_data,
+ const HeapVector<ArrayBufferOrArrayBufferViewOrBlobOrUSVString>& parts,
+ bool normalize_line_endings_to_native) {
+ for (const auto& item : parts) {
+ if (item.IsArrayBuffer()) {
+ DOMArrayBuffer* array_buffer = item.GetAsArrayBuffer();
+ blob_data->AppendBytes(array_buffer->Data(), array_buffer->ByteLength());
+ } else if (item.IsArrayBufferView()) {
+ DOMArrayBufferView* array_buffer_view =
+ item.GetAsArrayBufferView().View();
+ blob_data->AppendBytes(array_buffer_view->BaseAddress(),
+ array_buffer_view->byteLength());
+ } else if (item.IsBlob()) {
+ item.GetAsBlob()->AppendTo(*blob_data);
+ } else if (item.IsUSVString()) {
+ blob_data->AppendText(item.GetAsUSVString(),
+ normalize_line_endings_to_native);
+ } else {
+ NOTREACHED();
+ }
+ }
+}
+
+// static
+void Blob::ClampSliceOffsets(long long size, long long& start, long long& end) {
+ DCHECK_NE(size, -1);
+
+ // 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;
+ }
+}
+
+Blob* Blob::slice(long long start,
+ long long end,
+ const String& content_type,
+ ExceptionState& exception_state) const {
+ long long size = this->size();
+ ClampSliceOffsets(size, start, end);
+
+ long long length = end - start;
+ std::unique_ptr<BlobData> blob_data = BlobData::Create();
+ blob_data->SetContentType(NormalizeType(content_type));
+ blob_data->AppendBlob(blob_data_handle_, start, length);
+ return Blob::Create(BlobDataHandle::Create(std::move(blob_data), length));
+}
+
+void Blob::AppendTo(BlobData& blob_data) const {
+ blob_data.AppendBlob(blob_data_handle_, 0, blob_data_handle_->size());
+}
+
+URLRegistry& Blob::Registry() const {
+ return BlobURLRegistry::Registry();
+}
+
+mojom::blink::BlobPtr Blob::AsMojoBlob() {
+ return blob_data_handle_->CloneBlobPtr();
+}
+
+// static
+String Blob::NormalizeType(const String& type) {
+ if (type.IsNull())
+ return g_empty_string;
+ const size_t length = type.length();
+ if (type.Is8Bit()) {
+ const LChar* chars = type.Characters8();
+ for (size_t i = 0; i < length; ++i) {
+ if (chars[i] < 0x20 || chars[i] > 0x7e)
+ return g_empty_string;
+ }
+ } else {
+ const UChar* chars = type.Characters16();
+ for (size_t i = 0; i < length; ++i) {
+ if (chars[i] < 0x0020 || chars[i] > 0x007e)
+ return g_empty_string;
+ }
+ }
+ return type.DeprecatedLower();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fileapi/blob.h b/chromium/third_party/blink/renderer/core/fileapi/blob.h
new file mode 100644
index 00000000000..2173f64c1f5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/blob.h
@@ -0,0 +1,144 @@
+/*
+ * 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 THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_BLOB_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_BLOB_H_
+
+#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view_or_blob_or_usv_string.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/fileapi/url_registry.h"
+#include "third_party/blink/renderer/core/imagebitmap/image_bitmap_source.h"
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/blob/blob_data.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class BlobPropertyBag;
+class ExceptionState;
+class ExecutionContext;
+
+class CORE_EXPORT Blob : public ScriptWrappable,
+ public URLRegistrable,
+ public ImageBitmapSource {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static Blob* Create(ExecutionContext*, ExceptionState&) {
+ return new Blob(BlobDataHandle::Create());
+ }
+
+ static Blob* Create(
+ ExecutionContext*,
+ const HeapVector<ArrayBufferOrArrayBufferViewOrBlobOrUSVString>&,
+ const BlobPropertyBag&,
+ ExceptionState&);
+
+ static Blob* Create(scoped_refptr<BlobDataHandle> blob_data_handle) {
+ return new Blob(std::move(blob_data_handle));
+ }
+
+ static Blob* Create(const unsigned char* data,
+ size_t bytes,
+ const String& content_type);
+
+ ~Blob() override;
+
+ virtual unsigned long long size() const { return blob_data_handle_->size(); }
+ virtual Blob* slice(long long start,
+ long long end,
+ const String& content_type,
+ ExceptionState&) const;
+
+ // To allow ExceptionState to be passed in last, manually enumerate the
+ // optional argument overloads.
+ Blob* slice(ExceptionState& exception_state) const {
+ return slice(0, std::numeric_limits<long long>::max(), String(),
+ exception_state);
+ }
+ Blob* slice(long long start, ExceptionState& exception_state) const {
+ return slice(start, std::numeric_limits<long long>::max(), String(),
+ exception_state);
+ }
+ Blob* slice(long long start,
+ long long end,
+ ExceptionState& exception_state) const {
+ return slice(start, end, String(), exception_state);
+ }
+
+ String type() const { return blob_data_handle_->GetType(); }
+ String Uuid() const { return blob_data_handle_->Uuid(); }
+ scoped_refptr<BlobDataHandle> GetBlobDataHandle() const {
+ return blob_data_handle_;
+ }
+ // True for all File instances, including the user-built ones.
+ virtual bool IsFile() const { return false; }
+ // Only true for File instances that are backed by platform files.
+ virtual bool HasBackingFile() const { return false; }
+
+ // Used by the JavaScript Blob and File constructors.
+ virtual void AppendTo(BlobData&) const;
+
+ // URLRegistrable to support PublicURLs.
+ URLRegistry& Registry() const final;
+ mojom::blink::BlobPtr AsMojoBlob() final;
+
+ // ImageBitmapSource implementation
+ bool IsBlob() const override { return true; }
+
+ protected:
+ explicit Blob(scoped_refptr<BlobDataHandle>);
+
+ static void PopulateBlobData(
+ BlobData*,
+ const HeapVector<ArrayBufferOrArrayBufferViewOrBlobOrUSVString>& parts,
+ bool normalize_line_endings_to_native);
+ static void ClampSliceOffsets(long long size,
+ long long& start,
+ long long& end);
+
+ // Called by the Blob and File constructors when processing the 'type'
+ // option per the FileAPI standard. Returns "" if |type| contains any
+ // character outside U+0020...U+007E, or |type| ASCII-lowercased otherwise.
+ static String NormalizeType(const String& type);
+
+ private:
+ Blob() = delete;
+
+ scoped_refptr<BlobDataHandle> blob_data_handle_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_BLOB_H_
diff --git a/chromium/third_party/blink/renderer/core/fileapi/blob.idl b/chromium/third_party/blink/renderer/core/fileapi/blob.idl
new file mode 100644
index 00000000000..fa0d2500180
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/blob.idl
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+// https://w3c.github.io/FileAPI/#blob
+
+typedef (ArrayBuffer or ArrayBufferView or Blob or USVString) BlobPart;
+[
+ Constructor(optional sequence<BlobPart> blobParts, optional BlobPropertyBag options),
+ ConstructorCallWith=ExecutionContext,
+ RaisesException=Constructor,
+ Exposed=(Window,Worker)
+] interface Blob {
+ readonly attribute unsigned long long size;
+ readonly attribute DOMString type;
+
+ // TODO(jsbell): start and end arguments should be [Clamp]
+ [RaisesException] Blob slice(optional long long start, optional long long end, optional DOMString contentType);
+};
diff --git a/chromium/third_party/blink/renderer/core/fileapi/blob_property_bag.idl b/chromium/third_party/blink/renderer/core/fileapi/blob_property_bag.idl
new file mode 100644
index 00000000000..009bbd1e83c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/blob_property_bag.idl
@@ -0,0 +1,12 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://w3c.github.io/FileAPI/#dfn-BlobPropertyBag
+
+enum EndingType { "transparent", "native" };
+
+dictionary BlobPropertyBag {
+ DOMString type = "";
+ EndingType endings = "transparent";
+};
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file.cc b/chromium/third_party/blink/renderer/core/fileapi/file.cc
new file mode 100644
index 00000000000..d028cd0c66c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/file.cc
@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) 2008 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 met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 "third_party/blink/renderer/core/fileapi/file.h"
+
+#include <memory>
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_file_utilities.h"
+#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/core/fileapi/file_property_bag.h"
+#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/blob/blob_data.h"
+#include "third_party/blink/renderer/platform/file_metadata.h"
+#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
+#include "third_party/blink/renderer/platform/wtf/date_math.h"
+#include "third_party/blink/renderer/platform/wtf/time.h"
+
+namespace blink {
+
+static String GetContentTypeFromFileName(const String& name,
+ File::ContentTypeLookupPolicy policy) {
+ String type;
+ int index = name.ReverseFind('.');
+ if (index != -1) {
+ if (policy == File::kWellKnownContentTypes) {
+ type = MIMETypeRegistry::GetWellKnownMIMETypeForExtension(
+ name.Substring(index + 1));
+ } else {
+ DCHECK_EQ(policy, File::kAllContentTypes);
+ type =
+ MIMETypeRegistry::GetMIMETypeForExtension(name.Substring(index + 1));
+ }
+ }
+ return type;
+}
+
+static std::unique_ptr<BlobData> CreateBlobDataForFileWithType(
+ const String& path,
+ const String& content_type) {
+ std::unique_ptr<BlobData> blob_data =
+ BlobData::CreateForFileWithUnknownSize(path);
+ blob_data->SetContentType(content_type);
+ return blob_data;
+}
+
+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& file_system_name,
+ File::ContentTypeLookupPolicy policy) {
+ return CreateBlobDataForFileWithType(
+ path, GetContentTypeFromFileName(file_system_name, policy));
+}
+
+static std::unique_ptr<BlobData> CreateBlobDataForFileWithMetadata(
+ const String& file_system_name,
+ const FileMetadata& metadata) {
+ std::unique_ptr<BlobData> blob_data;
+ if (metadata.length == BlobData::kToEndOfFile) {
+ blob_data = BlobData::CreateForFileWithUnknownSize(
+ metadata.platform_path, metadata.modification_time / kMsPerSecond);
+ } else {
+ blob_data = BlobData::Create();
+ blob_data->AppendFile(metadata.platform_path, 0, metadata.length,
+ metadata.modification_time / kMsPerSecond);
+ }
+ blob_data->SetContentType(GetContentTypeFromFileName(
+ file_system_name, File::kWellKnownContentTypes));
+ return blob_data;
+}
+
+static std::unique_ptr<BlobData> CreateBlobDataForFileSystemURL(
+ const KURL& file_system_url,
+ const FileMetadata& metadata) {
+ std::unique_ptr<BlobData> blob_data;
+ if (metadata.length == BlobData::kToEndOfFile) {
+ blob_data = BlobData::CreateForFileSystemURLWithUnknownSize(
+ file_system_url, metadata.modification_time / kMsPerSecond);
+ } else {
+ blob_data = BlobData::Create();
+ blob_data->AppendFileSystemURL(file_system_url, 0, metadata.length,
+ metadata.modification_time / kMsPerSecond);
+ }
+ blob_data->SetContentType(GetContentTypeFromFileName(
+ file_system_url.GetPath(), File::kWellKnownContentTypes));
+ return blob_data;
+}
+
+// static
+File* File::Create(
+ ExecutionContext* context,
+ const HeapVector<ArrayBufferOrArrayBufferViewOrBlobOrUSVString>& file_bits,
+ const String& file_name,
+ const FilePropertyBag& options,
+ ExceptionState& exception_state) {
+ DCHECK(options.hasType());
+
+ double last_modified;
+ if (options.hasLastModified())
+ last_modified = static_cast<double>(options.lastModified());
+ else
+ last_modified = CurrentTimeMS();
+ DCHECK(options.hasEndings());
+ bool normalize_line_endings_to_native = options.endings() == "native";
+ if (normalize_line_endings_to_native)
+ UseCounter::Count(context, WebFeature::kFileAPINativeLineEndings);
+
+ std::unique_ptr<BlobData> blob_data = BlobData::Create();
+ blob_data->SetContentType(NormalizeType(options.type()));
+ PopulateBlobData(blob_data.get(), file_bits,
+ normalize_line_endings_to_native);
+
+ long long file_size = blob_data->length();
+ return File::Create(file_name, last_modified,
+ BlobDataHandle::Create(std::move(blob_data), file_size));
+}
+
+File* File::CreateWithRelativePath(const String& path,
+ const String& relative_path) {
+ File* file = new File(path, File::kAllContentTypes, File::kIsUserVisible);
+ file->relative_path_ = relative_path;
+ return file;
+}
+
+File::File(const String& path,
+ ContentTypeLookupPolicy policy,
+ UserVisibility user_visibility)
+ : Blob(BlobDataHandle::Create(CreateBlobDataForFile(path, policy), -1)),
+ has_backing_file_(true),
+ user_visibility_(user_visibility),
+ path_(path),
+ name_(Platform::Current()->GetFileUtilities()->BaseName(path)),
+ snapshot_size_(-1),
+ snapshot_modification_time_ms_(InvalidFileTime()) {}
+
+File::File(const String& path,
+ const String& name,
+ ContentTypeLookupPolicy policy,
+ UserVisibility user_visibility)
+ : Blob(BlobDataHandle::Create(
+ CreateBlobDataForFileWithName(path, name, policy),
+ -1)),
+ has_backing_file_(true),
+ user_visibility_(user_visibility),
+ path_(path),
+ name_(name),
+ snapshot_size_(-1),
+ snapshot_modification_time_ms_(InvalidFileTime()) {}
+
+File::File(const String& path,
+ const String& name,
+ const String& relative_path,
+ UserVisibility user_visibility,
+ bool has_snapshot_data,
+ uint64_t size,
+ double last_modified,
+ scoped_refptr<BlobDataHandle> blob_data_handle)
+ : Blob(std::move(blob_data_handle)),
+ has_backing_file_(!path.IsEmpty() || !relative_path.IsEmpty()),
+ user_visibility_(user_visibility),
+ path_(path),
+ name_(name),
+ snapshot_size_(has_snapshot_data ? static_cast<long long>(size) : -1),
+ snapshot_modification_time_ms_(has_snapshot_data ? last_modified
+ : InvalidFileTime()),
+ relative_path_(relative_path) {}
+
+File::File(const String& name,
+ double modification_time_ms,
+ scoped_refptr<BlobDataHandle> blob_data_handle)
+ : Blob(std::move(blob_data_handle)),
+ has_backing_file_(false),
+ user_visibility_(File::kIsNotUserVisible),
+ name_(name),
+ snapshot_size_(Blob::size()),
+ snapshot_modification_time_ms_(modification_time_ms) {}
+
+File::File(const String& name,
+ const FileMetadata& metadata,
+ UserVisibility user_visibility)
+ : Blob(BlobDataHandle::Create(
+ CreateBlobDataForFileWithMetadata(name, metadata),
+ metadata.length)),
+ has_backing_file_(true),
+ user_visibility_(user_visibility),
+ path_(metadata.platform_path),
+ name_(name),
+ snapshot_size_(metadata.length),
+ snapshot_modification_time_ms_(metadata.modification_time) {}
+
+File::File(const KURL& file_system_url,
+ const FileMetadata& metadata,
+ UserVisibility user_visibility)
+ : Blob(BlobDataHandle::Create(
+ CreateBlobDataForFileSystemURL(file_system_url, metadata),
+ metadata.length)),
+ has_backing_file_(false),
+ user_visibility_(user_visibility),
+ name_(DecodeURLEscapeSequences(file_system_url.LastPathComponent())),
+ file_system_url_(file_system_url),
+ snapshot_size_(metadata.length),
+ snapshot_modification_time_ms_(metadata.modification_time) {}
+
+File::File(const File& other)
+ : Blob(other.GetBlobDataHandle()),
+ has_backing_file_(other.has_backing_file_),
+ user_visibility_(other.user_visibility_),
+ path_(other.path_),
+ name_(other.name_),
+ file_system_url_(other.file_system_url_),
+ snapshot_size_(other.snapshot_size_),
+ snapshot_modification_time_ms_(other.snapshot_modification_time_ms_),
+ relative_path_(other.relative_path_) {}
+
+File* File::Clone(const String& name) const {
+ File* file = new File(*this);
+ if (!name.IsNull())
+ file->name_ = name;
+ return file;
+}
+
+double File::LastModifiedMS() const {
+ if (HasValidSnapshotMetadata() &&
+ IsValidFileTime(snapshot_modification_time_ms_))
+ return snapshot_modification_time_ms_;
+
+ double modification_time_ms;
+ if (HasBackingFile() &&
+ GetFileModificationTime(path_, modification_time_ms) &&
+ IsValidFileTime(modification_time_ms))
+ return modification_time_ms;
+
+ return CurrentTimeMS();
+}
+
+long long File::lastModified() const {
+ double modified_date = LastModifiedMS();
+
+ // The getter should return the current time when the last modification time
+ // isn't known.
+ if (!IsValidFileTime(modified_date))
+ modified_date = CurrentTimeMS();
+
+ // lastModified returns a number, not a Date instance,
+ // http://dev.w3.org/2006/webapi/FileAPI/#file-attrs
+ return floor(modified_date);
+}
+
+double File::lastModifiedDate() const {
+ double modified_date = LastModifiedMS();
+
+ // The getter should return the current time when the last modification time
+ // isn't known.
+ if (!IsValidFileTime(modified_date))
+ modified_date = CurrentTimeMS();
+
+ // lastModifiedDate returns a Date instance,
+ // http://www.w3.org/TR/FileAPI/#dfn-lastModifiedDate
+ return modified_date;
+}
+
+unsigned long long File::size() const {
+ if (HasValidSnapshotMetadata())
+ return snapshot_size_;
+
+ // 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 (!HasBackingFile() || !GetFileSize(path_, size))
+ return 0;
+ return static_cast<unsigned long long>(size);
+}
+
+Blob* File::slice(long long start,
+ long long end,
+ const String& content_type,
+ ExceptionState& exception_state) const {
+ if (!has_backing_file_)
+ return Blob::slice(start, end, content_type, exception_state);
+
+ // FIXME: This involves synchronous file operation. We need to figure out how
+ // to make it asynchronous.
+ long long size;
+ double modification_time_ms;
+ CaptureSnapshot(size, modification_time_ms);
+ ClampSliceOffsets(size, start, end);
+
+ long long length = end - start;
+ std::unique_ptr<BlobData> blob_data = BlobData::Create();
+ blob_data->SetContentType(NormalizeType(content_type));
+ DCHECK(!path_.IsEmpty());
+ blob_data->AppendFile(path_, start, length,
+ modification_time_ms / kMsPerSecond);
+ return Blob::Create(BlobDataHandle::Create(std::move(blob_data), length));
+}
+
+void File::CaptureSnapshot(long long& snapshot_size,
+ double& snapshot_modification_time_ms) const {
+ if (HasValidSnapshotMetadata()) {
+ snapshot_size = snapshot_size_;
+ snapshot_modification_time_ms = snapshot_modification_time_ms_;
+ return;
+ }
+
+ // 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 (!HasBackingFile() || !GetFileMetadata(path_, metadata)) {
+ snapshot_size = 0;
+ snapshot_modification_time_ms = InvalidFileTime();
+ return;
+ }
+
+ snapshot_size = metadata.length;
+ snapshot_modification_time_ms = metadata.modification_time;
+}
+
+void File::AppendTo(BlobData& blob_data) const {
+ if (!has_backing_file_) {
+ Blob::AppendTo(blob_data);
+ return;
+ }
+
+ // FIXME: This involves synchronous file operation. We need to figure out how
+ // to make it asynchronous.
+ long long size;
+ double modification_time_ms;
+ CaptureSnapshot(size, modification_time_ms);
+ DCHECK(!path_.IsEmpty());
+ blob_data.AppendFile(path_, 0, size, modification_time_ms / kMsPerSecond);
+}
+
+bool File::HasSameSource(const File& other) const {
+ if (has_backing_file_ != other.has_backing_file_)
+ return false;
+
+ if (has_backing_file_)
+ return path_ == other.path_;
+
+ if (file_system_url_.IsEmpty() != other.file_system_url_.IsEmpty())
+ return false;
+
+ if (!file_system_url_.IsEmpty())
+ return file_system_url_ == other.file_system_url_;
+
+ return Uuid() == other.Uuid();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file.h b/chromium/third_party/blink/renderer/core/fileapi/file.h
new file mode 100644
index 00000000000..39831f1902c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/file.h
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2008 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 met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_H_
+
+#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view_or_blob_or_usv_string.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/fileapi/blob.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class ExceptionState;
+class ExecutionContext;
+class FilePropertyBag;
+class FileMetadata;
+class KURL;
+
+class CORE_EXPORT File final : public Blob {
+ DEFINE_WRAPPERTYPEINFO();
+
+ 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 {
+ kWellKnownContentTypes,
+ kAllContentTypes,
+ };
+
+ // The user should not be able to browse to some files, such as the ones
+ // generated by the Filesystem API.
+ enum UserVisibility { kIsUserVisible, kIsNotUserVisible };
+
+ // Constructor in File.idl
+ static File* Create(
+ ExecutionContext*,
+ const HeapVector<ArrayBufferOrArrayBufferViewOrBlobOrUSVString>&,
+ const String& file_name,
+ const FilePropertyBag&,
+ ExceptionState&);
+
+ static File* Create(const String& path,
+ ContentTypeLookupPolicy policy = kWellKnownContentTypes) {
+ return new File(path, policy, File::kIsUserVisible);
+ }
+
+ static File* Create(const String& name,
+ double modification_time,
+ scoped_refptr<BlobDataHandle> blob_data_handle) {
+ return new File(name, modification_time, std::move(blob_data_handle));
+ }
+
+ // For deserialization.
+ static File* CreateFromSerialization(
+ const String& path,
+ const String& name,
+ const String& relative_path,
+ UserVisibility user_visibility,
+ bool has_snapshot_data,
+ uint64_t size,
+ double last_modified,
+ scoped_refptr<BlobDataHandle> blob_data_handle) {
+ return new File(path, name, relative_path, user_visibility,
+ has_snapshot_data, size, last_modified,
+ std::move(blob_data_handle));
+ }
+ static File* CreateFromIndexedSerialization(
+ const String& path,
+ const String& name,
+ uint64_t size,
+ double last_modified,
+ scoped_refptr<BlobDataHandle> blob_data_handle) {
+ return new File(path, name, String(), kIsNotUserVisible, true, size,
+ last_modified, std::move(blob_data_handle));
+ }
+
+ static File* CreateWithRelativePath(const String& path,
+ const String& relative_path);
+
+ // If filesystem files live in the remote filesystem, the port might pass the
+ // valid metadata (whose length field is non-negative) and cache in the File
+ // object.
+ //
+ // Otherwise calling size(), lastModifiedTime() and slice() will synchronously
+ // query the file metadata.
+ static File* CreateForFileSystemFile(const String& name,
+ const FileMetadata& metadata,
+ UserVisibility user_visibility) {
+ return new File(name, metadata, user_visibility);
+ }
+
+ static File* CreateForFileSystemFile(const KURL& url,
+ const FileMetadata& metadata,
+ UserVisibility user_visibility) {
+ return new File(url, metadata, user_visibility);
+ }
+
+ KURL FileSystemURL() const {
+#if DCHECK_IS_ON()
+ DCHECK(HasValidFileSystemURL());
+#endif
+ return file_system_url_;
+ }
+
+ // 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 File* CreateForUserProvidedFile(const String& path,
+ const String& display_name) {
+ if (display_name.IsEmpty())
+ return new File(path, File::kAllContentTypes, File::kIsUserVisible);
+ return new File(path, display_name, File::kAllContentTypes,
+ File::kIsUserVisible);
+ }
+
+ static File* CreateForFileSystemFile(
+ const String& path,
+ const String& name,
+ ContentTypeLookupPolicy policy = kWellKnownContentTypes) {
+ if (name.IsEmpty())
+ return new File(path, policy, File::kIsNotUserVisible);
+ return new File(path, name, policy, File::kIsNotUserVisible);
+ }
+
+ File* Clone(const String& name = String()) const;
+
+ unsigned long long size() const override;
+ Blob* slice(long long start,
+ long long end,
+ const String& content_type,
+ ExceptionState&) const override;
+
+ bool IsFile() const override { return true; }
+ bool HasBackingFile() const override { return has_backing_file_; }
+
+ void AppendTo(BlobData&) const override;
+
+ const String& GetPath() const {
+#if DCHECK_IS_ON()
+ DCHECK(HasValidFilePath());
+#endif
+ return path_;
+ }
+ const String& name() const { return name_; }
+
+ // Getter for the lastModified IDL attribute,
+ // http://dev.w3.org/2006/webapi/FileAPI/#file-attrs
+ long long lastModified() const;
+
+ // Getter for the lastModifiedDate IDL attribute,
+ // http://www.w3.org/TR/FileAPI/#dfn-lastModifiedDate
+ double lastModifiedDate() const;
+
+ UserVisibility GetUserVisibility() const { return user_visibility_; }
+
+ // Returns the relative path of this file in the context of a directory
+ // selection.
+ const String& webkitRelativePath() const { return relative_path_; }
+
+ // Note that this involves synchronous file operation. Think twice before
+ // calling this function.
+ void CaptureSnapshot(long long& snapshot_size,
+ double& snapshot_modification_time_ms) const;
+
+ // Returns true if this has a valid snapshot metadata
+ // (i.e. m_snapshotSize >= 0).
+ bool HasValidSnapshotMetadata() const { return snapshot_size_ >= 0; }
+
+ // Returns true if the sources (file path, file system URL, or blob handler)
+ // of the file objects are same or not.
+ bool HasSameSource(const File& other) const;
+
+ private:
+ File(const String& path, ContentTypeLookupPolicy, UserVisibility);
+ File(const String& path,
+ const String& name,
+ ContentTypeLookupPolicy,
+ UserVisibility);
+ File(const String& path,
+ const String& name,
+ const String& relative_path,
+ UserVisibility,
+ bool has_snapshot_data,
+ uint64_t size,
+ double last_modified,
+ scoped_refptr<BlobDataHandle>);
+ File(const String& name,
+ double modification_time,
+ scoped_refptr<BlobDataHandle>);
+ File(const String& name, const FileMetadata&, UserVisibility);
+ File(const KURL& file_system_url, const FileMetadata&, UserVisibility);
+ File(const File&);
+
+ void InvalidateSnapshotMetadata() { snapshot_size_ = -1; }
+
+ // Returns File's last modified time (in MS since Epoch.)
+ // If the modification time isn't known, the current time is returned.
+ double LastModifiedMS() const;
+
+#if DCHECK_IS_ON()
+ // Instances backed by a file must have an empty file system URL.
+ bool HasValidFileSystemURL() const {
+ return !HasBackingFile() || file_system_url_.IsEmpty();
+ }
+ // Instances not backed by a file must have an empty path set.
+ bool HasValidFilePath() const { return HasBackingFile() || path_.IsEmpty(); }
+#endif
+
+ bool has_backing_file_;
+ UserVisibility user_visibility_;
+ String path_;
+ String name_;
+
+ KURL file_system_url_;
+
+ // If m_snapshotSize is negative (initialized to -1 by default), the snapshot
+ // metadata is invalid and we retrieve the latest metadata synchronously in
+ // size(), lastModifiedTime() and slice().
+ // Otherwise, the snapshot metadata are used directly in those methods.
+ long long snapshot_size_;
+ const double snapshot_modification_time_ms_;
+
+ String relative_path_;
+};
+
+DEFINE_TYPE_CASTS(File, Blob, blob, blob->IsFile(), blob.IsFile());
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_H_
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file.idl b/chromium/third_party/blink/renderer/core/fileapi/file.idl
new file mode 100644
index 00000000000..a74beceda3e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/file.idl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2008 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 met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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.
+ */
+
+// https://w3c.github.io/FileAPI/#file
+
+[
+ Constructor(sequence<BlobPart> fileBits, USVString fileName, optional FilePropertyBag options),
+ ConstructorCallWith=ExecutionContext,
+ RaisesException=Constructor,
+ Exposed=(Window,Worker)
+] interface File : Blob {
+ readonly attribute DOMString name;
+ readonly attribute long long lastModified;
+
+ // Non-standard APIs
+ [MeasureAs=FileGetLastModifiedDate] readonly attribute Date lastModifiedDate;
+ [MeasureAs=PrefixedFileRelativePath] readonly attribute DOMString webkitRelativePath;
+};
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_error.cc b/chromium/third_party/blink/renderer/core/fileapi/file_error.cc
new file mode 100644
index 00000000000..1dd5f239998
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_error.cc
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2013 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 "third_party/blink/renderer/core/fileapi/file_error.h"
+
+#include "third_party/blink/public/platform/web_file_error.h"
+#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/platform/wtf/assertions.h"
+
+namespace blink {
+
+namespace FileError {
+
+const char kAbortErrorMessage[] =
+ "An ongoing operation was aborted, typically with a call to abort().";
+const char kEncodingErrorMessage[] =
+ "A URI supplied to the API was malformed, or the resulting Data URL has "
+ "exceeded the URL length limitations for Data URLs.";
+const char kInvalidStateErrorMessage[] =
+ "An operation that depends on state cached in an interface object was made "
+ "but the state had changed since it was read from disk.";
+const char kNoModificationAllowedErrorMessage[] =
+ "An attempt was made to write to a file or directory which could not be "
+ "modified due to the state of the underlying filesystem.";
+const char kNotFoundErrorMessage[] =
+ "A requested file or directory could not be found at the time an operation "
+ "was processed.";
+const char kNotReadableErrorMessage[] =
+ "The requested file could not be read, typically due to permission "
+ "problems that have occurred after a reference to a file was acquired.";
+const char kPathExistsErrorMessage[] =
+ "An attempt was made to create a file or directory where an element "
+ "already exists.";
+const char kQuotaExceededErrorMessage[] =
+ "The operation failed because it would cause the application to exceed its "
+ "storage quota.";
+const char kSecurityErrorMessage[] =
+ "It was determined that certain files are unsafe for access within a Web "
+ "application, or that too many calls are being made on file resources.";
+const char kSyntaxErrorMessage[] =
+ "An invalid or unsupported argument was given, like an invalid line ending "
+ "specifier.";
+const char kTypeMismatchErrorMessage[] =
+ "The path supplied exists, but was not an entry of requested type.";
+
+namespace {
+
+ExceptionCode ErrorCodeToExceptionCode(ErrorCode code) {
+ switch (code) {
+ case kOK:
+ return 0;
+ case kNotFoundErr:
+ return kNotFoundError;
+ case kSecurityErr:
+ return kSecurityError;
+ case kAbortErr:
+ return kAbortError;
+ case kNotReadableErr:
+ return kNotReadableError;
+ case kEncodingErr:
+ return kEncodingError;
+ case kNoModificationAllowedErr:
+ return kNoModificationAllowedError;
+ case kInvalidStateErr:
+ return kInvalidStateError;
+ case kSyntaxErr:
+ return kSyntaxError;
+ case kInvalidModificationErr:
+ return kInvalidModificationError;
+ case kQuotaExceededErr:
+ return kQuotaExceededError;
+ case kTypeMismatchErr:
+ return kTypeMismatchError;
+ case kPathExistsErr:
+ return kPathExistsError;
+ default:
+ NOTREACHED();
+ return code;
+ }
+}
+
+const char* ErrorCodeToMessage(ErrorCode code) {
+ // Note that some of these do not set message. If message is 0 then the
+ // default message is used.
+ switch (code) {
+ case kOK:
+ return nullptr;
+ case kSecurityErr:
+ return kSecurityErrorMessage;
+ case kNotFoundErr:
+ return kNotFoundErrorMessage;
+ case kAbortErr:
+ return kAbortErrorMessage;
+ case kNotReadableErr:
+ return kNotReadableErrorMessage;
+ case kEncodingErr:
+ return kEncodingErrorMessage;
+ case kNoModificationAllowedErr:
+ return kNoModificationAllowedErrorMessage;
+ case kInvalidStateErr:
+ return kInvalidStateErrorMessage;
+ case kSyntaxErr:
+ return kSyntaxErrorMessage;
+ case kInvalidModificationErr:
+ return nullptr;
+ case kQuotaExceededErr:
+ return kQuotaExceededErrorMessage;
+ case kTypeMismatchErr:
+ return nullptr;
+ case kPathExistsErr:
+ return kPathExistsErrorMessage;
+ default:
+ NOTREACHED();
+ return nullptr;
+ }
+}
+
+} // namespace
+
+void ThrowDOMException(ExceptionState& exception_state, ErrorCode code) {
+ if (code == kOK)
+ return;
+
+ // SecurityError is special-cased, as we want to route those exceptions
+ // through ExceptionState::throwSecurityError.
+ if (code == kSecurityErr) {
+ exception_state.ThrowSecurityError(kSecurityErrorMessage);
+ return;
+ }
+
+ exception_state.ThrowDOMException(ErrorCodeToExceptionCode(code),
+ ErrorCodeToMessage(code));
+}
+
+DOMException* CreateDOMException(ErrorCode code) {
+ DCHECK_NE(code, kOK);
+ return DOMException::Create(ErrorCodeToExceptionCode(code),
+ ErrorCodeToMessage(code));
+}
+
+STATIC_ASSERT_ENUM(kWebFileErrorNotFound, kNotFoundErr);
+STATIC_ASSERT_ENUM(kWebFileErrorSecurity, kSecurityErr);
+STATIC_ASSERT_ENUM(kWebFileErrorAbort, kAbortErr);
+STATIC_ASSERT_ENUM(kWebFileErrorNotReadable, kNotReadableErr);
+STATIC_ASSERT_ENUM(kWebFileErrorEncoding, kEncodingErr);
+STATIC_ASSERT_ENUM(kWebFileErrorNoModificationAllowed,
+ kNoModificationAllowedErr);
+STATIC_ASSERT_ENUM(kWebFileErrorInvalidState, kInvalidStateErr);
+STATIC_ASSERT_ENUM(kWebFileErrorSyntax, kSyntaxErr);
+STATIC_ASSERT_ENUM(kWebFileErrorInvalidModification, kInvalidModificationErr);
+STATIC_ASSERT_ENUM(kWebFileErrorQuotaExceeded, kQuotaExceededErr);
+STATIC_ASSERT_ENUM(kWebFileErrorTypeMismatch, kTypeMismatchErr);
+STATIC_ASSERT_ENUM(kWebFileErrorPathExists, kPathExistsErr);
+
+} // namespace FileError
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_error.h b/chromium/third_party/blink/renderer/core/fileapi/file_error.h
new file mode 100644
index 00000000000..55f11174804
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_error.h
@@ -0,0 +1,78 @@
+/*
+ * 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 THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_ERROR_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_ERROR_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+
+namespace blink {
+
+class DOMException;
+class ExceptionState;
+
+namespace FileError {
+
+enum ErrorCode {
+ kOK = 0,
+ kNotFoundErr = 1,
+ kSecurityErr = 2,
+ kAbortErr = 3,
+ kNotReadableErr = 4,
+ kEncodingErr = 5,
+ kNoModificationAllowedErr = 6,
+ kInvalidStateErr = 7,
+ kSyntaxErr = 8,
+ kInvalidModificationErr = 9,
+ kQuotaExceededErr = 10,
+ kTypeMismatchErr = 11,
+ kPathExistsErr = 12,
+};
+
+CORE_EXPORT extern const char kAbortErrorMessage[];
+CORE_EXPORT extern const char kEncodingErrorMessage[];
+CORE_EXPORT extern const char kInvalidStateErrorMessage[];
+CORE_EXPORT extern const char kNoModificationAllowedErrorMessage[];
+CORE_EXPORT extern const char kNotFoundErrorMessage[];
+CORE_EXPORT extern const char kNotReadableErrorMessage[];
+CORE_EXPORT extern const char kPathExistsErrorMessage[];
+CORE_EXPORT extern const char kQuotaExceededErrorMessage[];
+CORE_EXPORT extern const char kSecurityErrorMessage[];
+CORE_EXPORT extern const char kSyntaxErrorMessage[];
+CORE_EXPORT extern const char kTypeMismatchErrorMessage[];
+
+CORE_EXPORT void ThrowDOMException(ExceptionState&, ErrorCode);
+CORE_EXPORT DOMException* CreateDOMException(ErrorCode);
+
+} // namespace FileError
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_ERROR_H_
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_list.cc b/chromium/third_party/blink/renderer/core/fileapi/file_list.cc
new file mode 100644
index 00000000000..720371ecba0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_list.cc
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2008 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 met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 "third_party/blink/renderer/core/fileapi/file_list.h"
+
+namespace blink {
+
+FileList::FileList() = default;
+
+File* FileList::item(unsigned index) const {
+ if (index >= files_.size())
+ return nullptr;
+ return files_[index].Get();
+}
+
+Vector<String> FileList::PathsForUserVisibleFiles() const {
+ Vector<String> paths;
+ for (unsigned i = 0; i < files_.size(); ++i) {
+ if (files_[i]->GetUserVisibility() == File::kIsUserVisible) {
+ if (files_[i]->HasBackingFile())
+ paths.push_back(files_[i]->GetPath());
+ else
+ paths.push_back(files_[i]->name());
+ }
+ }
+
+ return paths;
+}
+
+void FileList::Trace(blink::Visitor* visitor) {
+ visitor->Trace(files_);
+ ScriptWrappable::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_list.h b/chromium/third_party/blink/renderer/core/fileapi/file_list.h
new file mode 100644
index 00000000000..550a03406c3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_list.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2008 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 met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_LIST_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_LIST_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/fileapi/file.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+class CORE_EXPORT FileList final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static FileList* Create() { return new FileList; }
+
+ unsigned length() const { return files_.size(); }
+ File* item(unsigned index) const;
+
+ bool IsEmpty() const { return files_.IsEmpty(); }
+ void clear() { files_.clear(); }
+ void Append(File* file) { files_.push_back(file); }
+ Vector<String> PathsForUserVisibleFiles() const;
+
+ void Trace(blink::Visitor*);
+
+ private:
+ FileList();
+
+ HeapVector<Member<File>> files_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_LIST_H_
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_list.idl b/chromium/third_party/blink/renderer/core/fileapi/file_list.idl
new file mode 100644
index 00000000000..25db9a0ba23
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_list.idl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008 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 met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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.
+ */
+
+// https://w3c.github.io/FileAPI/#filelist-section
+
+[
+ Exposed=(Window,Worker)
+] interface FileList {
+ getter File? item(unsigned long index);
+ readonly attribute unsigned long length;
+};
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_list_test.cc b/chromium/third_party/blink/renderer/core/fileapi/file_list_test.cc
new file mode 100644
index 00000000000..ef6ffcadab4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_list_test.cc
@@ -0,0 +1,64 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/fileapi/file_list.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+TEST(FileListTest, pathsForUserVisibleFiles) {
+ FileList* const file_list = FileList::Create();
+
+ // Native file.
+ file_list->Append(File::Create("/native/path"));
+
+ // Blob file.
+ const scoped_refptr<BlobDataHandle> blob_data_handle =
+ BlobDataHandle::Create();
+ file_list->Append(File::Create("name", 0.0, blob_data_handle));
+
+ // User visible snapshot file.
+ {
+ FileMetadata metadata;
+ metadata.platform_path = "/native/visible/snapshot";
+ file_list->Append(
+ File::CreateForFileSystemFile("name", metadata, File::kIsUserVisible));
+ }
+
+ // Not user visible snapshot file.
+ {
+ FileMetadata metadata;
+ metadata.platform_path = "/native/not-visible/snapshot";
+ file_list->Append(File::CreateForFileSystemFile("name", metadata,
+ File::kIsNotUserVisible));
+ }
+
+ // User visible file system URL file.
+ {
+ KURL url(
+ "filesystem:http://example.com/isolated/hash/visible-non-native-file");
+ file_list->Append(File::CreateForFileSystemFile(url, FileMetadata(),
+ File::kIsUserVisible));
+ }
+
+ // Not user visible file system URL file.
+ {
+ KURL url(
+ "filesystem:http://example.com/isolated/hash/"
+ "not-visible-non-native-file");
+ file_list->Append(File::CreateForFileSystemFile(url, FileMetadata(),
+ File::kIsNotUserVisible));
+ }
+
+ Vector<String> paths = file_list->PathsForUserVisibleFiles();
+
+ ASSERT_EQ(3u, paths.size());
+ EXPECT_EQ("/native/path", paths[0]);
+ EXPECT_EQ("/native/visible/snapshot", paths[1]);
+ EXPECT_EQ("visible-non-native-file", paths[2])
+ << "Files not backed by a native file should return name.";
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_property_bag.idl b/chromium/third_party/blink/renderer/core/fileapi/file_property_bag.idl
new file mode 100644
index 00000000000..692b13853ee
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_property_bag.idl
@@ -0,0 +1,9 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://w3c.github.io/FileAPI/#file
+
+dictionary FilePropertyBag : BlobPropertyBag {
+ long long lastModified;
+};
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_reader.cc b/chromium/third_party/blink/renderer/core/fileapi/file_reader.cc
new file mode 100644
index 00000000000..71d893dd055
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_reader.cc
@@ -0,0 +1,480 @@
+/*
+ * 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 "third_party/blink/renderer/core/fileapi/file_reader.h"
+
+#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/bindings/core/v8/string_or_array_buffer.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/core/events/progress_event.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/fileapi/file.h"
+#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/core/probe/core_probes.h"
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+#include "third_party/blink/renderer/platform/wtf/auto_reset.h"
+#include "third_party/blink/renderer/platform/wtf/deque.h"
+#include "third_party/blink/renderer/platform/wtf/hash_set.h"
+#include "third_party/blink/renderer/platform/wtf/text/cstring.h"
+#include "third_party/blink/renderer/platform/wtf/time.h"
+
+namespace blink {
+
+namespace {
+
+const CString Utf8BlobUUID(Blob* blob) {
+ return blob->Uuid().Utf8();
+}
+
+const CString Utf8FilePath(Blob* blob) {
+ return blob->HasBackingFile() ? ToFile(blob)->GetPath().Utf8() : "";
+}
+
+} // namespace
+
+// Embedders like chromium limit the number of simultaneous requests to avoid
+// excessive IPC congestion. We limit this to 100 per thread to throttle the
+// requests (the value is arbitrarily chosen).
+static const size_t kMaxOutstandingRequestsPerThread = 100;
+static const double kProgressNotificationIntervalMS = 50;
+
+class FileReader::ThrottlingController final
+ : public GarbageCollected<FileReader::ThrottlingController>,
+ public Supplement<ExecutionContext> {
+ USING_GARBAGE_COLLECTED_MIXIN(FileReader::ThrottlingController);
+
+ public:
+ static const char kSupplementName[];
+
+ static ThrottlingController* From(ExecutionContext* context) {
+ if (!context)
+ return nullptr;
+
+ ThrottlingController* controller =
+ Supplement<ExecutionContext>::From<ThrottlingController>(*context);
+ if (!controller) {
+ controller = new ThrottlingController(*context);
+ ProvideTo(*context, controller);
+ }
+ return controller;
+ }
+
+ enum FinishReaderType { kDoNotRunPendingReaders, kRunPendingReaders };
+
+ static void PushReader(ExecutionContext* context, FileReader* reader) {
+ ThrottlingController* controller = From(context);
+ if (!controller)
+ return;
+
+ probe::AsyncTaskScheduled(context, "FileReader", reader);
+ controller->PushReader(reader);
+ }
+
+ static FinishReaderType RemoveReader(ExecutionContext* context,
+ FileReader* reader) {
+ ThrottlingController* controller = From(context);
+ if (!controller)
+ return kDoNotRunPendingReaders;
+
+ return controller->RemoveReader(reader);
+ }
+
+ static void FinishReader(ExecutionContext* context,
+ FileReader* reader,
+ FinishReaderType next_step) {
+ ThrottlingController* controller = From(context);
+ if (!controller)
+ return;
+
+ controller->FinishReader(reader, next_step);
+ probe::AsyncTaskCanceled(context, reader);
+ }
+
+ void Trace(blink::Visitor* visitor) {
+ visitor->Trace(pending_readers_);
+ visitor->Trace(running_readers_);
+ Supplement<ExecutionContext>::Trace(visitor);
+ }
+
+ private:
+ explicit ThrottlingController(ExecutionContext& context)
+ : Supplement<ExecutionContext>(context),
+ max_running_readers_(kMaxOutstandingRequestsPerThread) {}
+
+ void PushReader(FileReader* reader) {
+ if (pending_readers_.IsEmpty() &&
+ running_readers_.size() < max_running_readers_) {
+ reader->ExecutePendingRead();
+ DCHECK(!running_readers_.Contains(reader));
+ running_readers_.insert(reader);
+ return;
+ }
+ pending_readers_.push_back(reader);
+ ExecuteReaders();
+ }
+
+ FinishReaderType RemoveReader(FileReader* reader) {
+ FileReaderHashSet::const_iterator hash_iter = running_readers_.find(reader);
+ if (hash_iter != running_readers_.end()) {
+ running_readers_.erase(hash_iter);
+ return kRunPendingReaders;
+ }
+ FileReaderDeque::const_iterator deque_end = pending_readers_.end();
+ for (FileReaderDeque::const_iterator it = pending_readers_.begin();
+ it != deque_end; ++it) {
+ if (*it == reader) {
+ pending_readers_.erase(it);
+ break;
+ }
+ }
+ return kDoNotRunPendingReaders;
+ }
+
+ void FinishReader(FileReader* reader, FinishReaderType next_step) {
+ if (next_step == kRunPendingReaders)
+ ExecuteReaders();
+ }
+
+ void ExecuteReaders() {
+ while (running_readers_.size() < max_running_readers_) {
+ if (pending_readers_.IsEmpty())
+ return;
+ FileReader* reader = pending_readers_.TakeFirst();
+ reader->ExecutePendingRead();
+ running_readers_.insert(reader);
+ }
+ }
+
+ const size_t max_running_readers_;
+
+ using FileReaderDeque = HeapDeque<Member<FileReader>>;
+ using FileReaderHashSet = HeapHashSet<Member<FileReader>>;
+
+ FileReaderDeque pending_readers_;
+ FileReaderHashSet running_readers_;
+};
+
+// static
+const char FileReader::ThrottlingController::kSupplementName[] =
+ "FileReaderThrottlingController";
+
+FileReader* FileReader::Create(ExecutionContext* context) {
+ return new FileReader(context);
+}
+
+FileReader::FileReader(ExecutionContext* context)
+ : ContextLifecycleObserver(context),
+ state_(kEmpty),
+ loading_state_(kLoadingStateNone),
+ still_firing_events_(false),
+ read_type_(FileReaderLoader::kReadAsBinaryString),
+ last_progress_notification_time_ms_(0) {}
+
+FileReader::~FileReader() {
+ Terminate();
+}
+
+const AtomicString& FileReader::InterfaceName() const {
+ return EventTargetNames::FileReader;
+}
+
+void FileReader::ContextDestroyed(ExecutionContext* destroyed_context) {
+ // The delayed abort task tidies up and advances to the DONE state.
+ if (loading_state_ == kLoadingStateAborted)
+ return;
+
+ if (HasPendingActivity()) {
+ ThrottlingController::FinishReader(
+ destroyed_context, this,
+ ThrottlingController::RemoveReader(destroyed_context, this));
+ }
+ Terminate();
+}
+
+bool FileReader::HasPendingActivity() const {
+ return state_ == kLoading || still_firing_events_;
+}
+
+void FileReader::readAsArrayBuffer(Blob* blob,
+ ExceptionState& exception_state) {
+ DCHECK(blob);
+ DVLOG(1) << "reading as array buffer: " << Utf8BlobUUID(blob).data() << " "
+ << Utf8FilePath(blob).data();
+
+ ReadInternal(blob, FileReaderLoader::kReadAsArrayBuffer, exception_state);
+}
+
+void FileReader::readAsBinaryString(Blob* blob,
+ ExceptionState& exception_state) {
+ DCHECK(blob);
+ DVLOG(1) << "reading as binary: " << Utf8BlobUUID(blob).data() << " "
+ << Utf8FilePath(blob).data();
+
+ ReadInternal(blob, FileReaderLoader::kReadAsBinaryString, exception_state);
+}
+
+void FileReader::readAsText(Blob* blob,
+ const String& encoding,
+ ExceptionState& exception_state) {
+ DCHECK(blob);
+ DVLOG(1) << "reading as text: " << Utf8BlobUUID(blob).data() << " "
+ << Utf8FilePath(blob).data();
+
+ encoding_ = encoding;
+ ReadInternal(blob, FileReaderLoader::kReadAsText, exception_state);
+}
+
+void FileReader::readAsText(Blob* blob, ExceptionState& exception_state) {
+ readAsText(blob, String(), exception_state);
+}
+
+void FileReader::readAsDataURL(Blob* blob, ExceptionState& exception_state) {
+ DCHECK(blob);
+ DVLOG(1) << "reading as data URL: " << Utf8BlobUUID(blob).data() << " "
+ << Utf8FilePath(blob).data();
+
+ ReadInternal(blob, FileReaderLoader::kReadAsDataURL, exception_state);
+}
+
+void FileReader::ReadInternal(Blob* blob,
+ FileReaderLoader::ReadType type,
+ ExceptionState& exception_state) {
+ // If multiple concurrent read methods are called on the same FileReader,
+ // InvalidStateError should be thrown when the state is kLoading.
+ if (state_ == kLoading) {
+ exception_state.ThrowDOMException(
+ kInvalidStateError, "The object is already busy reading Blobs.");
+ return;
+ }
+
+ ExecutionContext* context = GetExecutionContext();
+ if (!context) {
+ exception_state.ThrowDOMException(
+ kAbortError, "Reading from a detached FileReader is not supported.");
+ return;
+ }
+
+ // A document loader will not load new resources once the Document has
+ // detached from its frame.
+ if (context->IsDocument() && !ToDocument(context)->GetFrame()) {
+ exception_state.ThrowDOMException(
+ kAbortError,
+ "Reading from a Document-detached FileReader is not supported.");
+ return;
+ }
+
+ // "Snapshot" the Blob data rather than the Blob itself as ongoing
+ // read operations should not be affected if close() is called on
+ // the Blob being read.
+ blob_data_handle_ = blob->GetBlobDataHandle();
+ blob_type_ = blob->type();
+ read_type_ = type;
+ state_ = kLoading;
+ loading_state_ = kLoadingStatePending;
+ error_ = nullptr;
+ DCHECK(ThrottlingController::From(context));
+ ThrottlingController::PushReader(context, this);
+}
+
+void FileReader::ExecutePendingRead() {
+ DCHECK_EQ(loading_state_, kLoadingStatePending);
+ loading_state_ = kLoadingStateLoading;
+
+ loader_ = FileReaderLoader::Create(read_type_, this);
+ loader_->SetEncoding(encoding_);
+ loader_->SetDataType(blob_type_);
+ loader_->Start(blob_data_handle_);
+ blob_data_handle_ = nullptr;
+}
+
+void FileReader::abort() {
+ DVLOG(1) << "aborting";
+
+ if (loading_state_ != kLoadingStateLoading &&
+ loading_state_ != kLoadingStatePending) {
+ return;
+ }
+ loading_state_ = kLoadingStateAborted;
+
+ DCHECK_NE(kDone, state_);
+ state_ = kDone;
+
+ AutoReset<bool> firing_events(&still_firing_events_, true);
+
+ // Setting error implicitly makes |result| return null.
+ error_ = FileError::CreateDOMException(FileError::kAbortErr);
+
+ // Unregister the reader.
+ ThrottlingController::FinishReaderType final_step =
+ ThrottlingController::RemoveReader(GetExecutionContext(), this);
+
+ FireEvent(EventTypeNames::abort);
+ FireEvent(EventTypeNames::loadend);
+
+ // All possible events have fired and we're done, no more pending activity.
+ ThrottlingController::FinishReader(GetExecutionContext(), this, final_step);
+
+ // ..but perform the loader cancellation asynchronously as abort() could be
+ // called from the event handler and we do not want the resource loading code
+ // to be on the stack when doing so. The persistent reference keeps the
+ // reader alive until the task has completed.
+ GetExecutionContext()
+ ->GetTaskRunner(TaskType::kFileReading)
+ ->PostTask(FROM_HERE,
+ WTF::Bind(&FileReader::Terminate, WrapPersistent(this)));
+}
+
+void FileReader::result(ScriptState* state,
+ StringOrArrayBuffer& result_attribute) const {
+ if (error_ || !loader_)
+ return;
+
+ if (!loader_->HasFinishedLoading()) {
+ UseCounter::Count(ExecutionContext::From(state),
+ WebFeature::kFileReaderResultBeforeCompletion);
+ }
+
+ if (read_type_ == FileReaderLoader::kReadAsArrayBuffer)
+ result_attribute.SetArrayBuffer(loader_->ArrayBufferResult());
+ else
+ result_attribute.SetString(loader_->StringResult());
+}
+
+void FileReader::Terminate() {
+ if (loader_) {
+ loader_->Cancel();
+ loader_ = nullptr;
+ }
+ state_ = kDone;
+ loading_state_ = kLoadingStateNone;
+}
+
+void FileReader::DidStartLoading() {
+ AutoReset<bool> firing_events(&still_firing_events_, true);
+ FireEvent(EventTypeNames::loadstart);
+}
+
+void FileReader::DidReceiveData() {
+ // Fire the progress event at least every 50ms.
+ double now = CurrentTimeMS();
+ if (!last_progress_notification_time_ms_) {
+ last_progress_notification_time_ms_ = now;
+ } else if (now - last_progress_notification_time_ms_ >
+ kProgressNotificationIntervalMS) {
+ AutoReset<bool> firing_events(&still_firing_events_, true);
+ FireEvent(EventTypeNames::progress);
+ last_progress_notification_time_ms_ = now;
+ }
+}
+
+void FileReader::DidFinishLoading() {
+ if (loading_state_ == kLoadingStateAborted)
+ return;
+ DCHECK_EQ(loading_state_, kLoadingStateLoading);
+
+ // TODO(jochen): When we set m_state to DONE below, we still need to fire
+ // the load and loadend events. To avoid GC to collect this FileReader, we
+ // use this separate variable to keep the wrapper of this FileReader alive.
+ // An alternative would be to keep any ActiveScriptWrappables alive that is on
+ // the stack.
+ AutoReset<bool> firing_events(&still_firing_events_, true);
+
+ // It's important that we change m_loadingState before firing any events
+ // since any of the events could call abort(), which internally checks
+ // if we're still loading (therefore we need abort process) or not.
+ loading_state_ = kLoadingStateNone;
+
+ FireEvent(EventTypeNames::progress);
+
+ DCHECK_NE(kDone, state_);
+ state_ = kDone;
+
+ // Unregister the reader.
+ ThrottlingController::FinishReaderType final_step =
+ ThrottlingController::RemoveReader(GetExecutionContext(), this);
+
+ FireEvent(EventTypeNames::load);
+ FireEvent(EventTypeNames::loadend);
+
+ // All possible events have fired and we're done, no more pending activity.
+ ThrottlingController::FinishReader(GetExecutionContext(), this, final_step);
+}
+
+void FileReader::DidFail(FileError::ErrorCode error_code) {
+ if (loading_state_ == kLoadingStateAborted)
+ return;
+
+ AutoReset<bool> firing_events(&still_firing_events_, true);
+
+ DCHECK_EQ(kLoadingStateLoading, loading_state_);
+ loading_state_ = kLoadingStateNone;
+
+ DCHECK_NE(kDone, state_);
+ state_ = kDone;
+
+ error_ = FileError::CreateDOMException(error_code);
+
+ // Unregister the reader.
+ ThrottlingController::FinishReaderType final_step =
+ ThrottlingController::RemoveReader(GetExecutionContext(), this);
+
+ FireEvent(EventTypeNames::error);
+ FireEvent(EventTypeNames::loadend);
+
+ // All possible events have fired and we're done, no more pending activity.
+ ThrottlingController::FinishReader(GetExecutionContext(), this, final_step);
+}
+
+void FileReader::FireEvent(const AtomicString& type) {
+ probe::AsyncTask async_task(GetExecutionContext(), this, "event");
+ if (!loader_) {
+ DispatchEvent(ProgressEvent::Create(type, false, 0, 0));
+ return;
+ }
+
+ if (loader_->TotalBytes()) {
+ DispatchEvent(ProgressEvent::Create(type, true, loader_->BytesLoaded(),
+ *loader_->TotalBytes()));
+ } else {
+ DispatchEvent(
+ ProgressEvent::Create(type, false, loader_->BytesLoaded(), 0));
+ }
+}
+
+void FileReader::Trace(blink::Visitor* visitor) {
+ visitor->Trace(error_);
+ EventTargetWithInlineData::Trace(visitor);
+ ContextLifecycleObserver::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_reader.h b/chromium/third_party/blink/renderer/core/fileapi/file_reader.h
new file mode 100644
index 00000000000..c891c4f514a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_reader.h
@@ -0,0 +1,140 @@
+/*
+ * 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 THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_READER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_READER_H_
+
+#include <memory>
+#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/core/dom/events/event_target.h"
+#include "third_party/blink/renderer/core/fileapi/file_error.h"
+#include "third_party/blink/renderer/core/fileapi/file_reader_loader.h"
+#include "third_party/blink/renderer/core/fileapi/file_reader_loader_client.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace blink {
+
+class Blob;
+class ExceptionState;
+class ExecutionContext;
+class StringOrArrayBuffer;
+
+class CORE_EXPORT FileReader final : public EventTargetWithInlineData,
+ public ActiveScriptWrappable<FileReader>,
+ public ContextLifecycleObserver,
+ public FileReaderLoaderClient {
+ DEFINE_WRAPPERTYPEINFO();
+ USING_GARBAGE_COLLECTED_MIXIN(FileReader);
+
+ public:
+ static FileReader* Create(ExecutionContext*);
+
+ ~FileReader() override;
+
+ enum ReadyState { kEmpty = 0, kLoading = 1, kDone = 2 };
+
+ void readAsArrayBuffer(Blob*, ExceptionState&);
+ void readAsBinaryString(Blob*, ExceptionState&);
+ void readAsText(Blob*, const String& encoding, ExceptionState&);
+ void readAsText(Blob*, ExceptionState&);
+ void readAsDataURL(Blob*, ExceptionState&);
+ void abort();
+
+ ReadyState getReadyState() const { return state_; }
+ DOMException* error() { return error_; }
+ void result(ScriptState*, StringOrArrayBuffer& result_attribute) const;
+
+ // ContextLifecycleObserver
+ void ContextDestroyed(ExecutionContext*) override;
+
+ // ScriptWrappable
+ bool HasPendingActivity() const final;
+
+ // EventTarget
+ const AtomicString& InterfaceName() const override;
+ ExecutionContext* GetExecutionContext() const override {
+ return ContextLifecycleObserver::GetExecutionContext();
+ }
+
+ // FileReaderLoaderClient
+ void DidStartLoading() override;
+ void DidReceiveData() override;
+ void DidFinishLoading() override;
+ void DidFail(FileError::ErrorCode) override;
+
+ 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);
+
+ virtual void Trace(blink::Visitor*);
+
+ private:
+ class ThrottlingController;
+
+ explicit FileReader(ExecutionContext*);
+
+ void Terminate();
+ void ReadInternal(Blob*, FileReaderLoader::ReadType, ExceptionState&);
+ void FireEvent(const AtomicString& type);
+
+ void ExecutePendingRead();
+
+ ReadyState state_;
+
+ // Internal loading state, which could differ from ReadyState as it's
+ // for script-visible state while this one's for internal state.
+ enum LoadingState {
+ kLoadingStateNone,
+ kLoadingStatePending,
+ kLoadingStateLoading,
+ kLoadingStateAborted
+ };
+ LoadingState loading_state_;
+ bool still_firing_events_;
+
+ String blob_type_;
+ scoped_refptr<BlobDataHandle> blob_data_handle_;
+ FileReaderLoader::ReadType read_type_;
+ String encoding_;
+
+ std::unique_ptr<FileReaderLoader> loader_;
+ Member<DOMException> error_;
+ double last_progress_notification_time_ms_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_READER_H_
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_reader.idl b/chromium/third_party/blink/renderer/core/fileapi/file_reader.idl
new file mode 100644
index 00000000000..ab2c692417e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_reader.idl
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2011 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
+ * 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.
+ */
+
+// https://w3c.github.io/FileAPI/#APIASynch
+
+[
+ ActiveScriptWrappable,
+ Constructor,
+ ConstructorCallWith=ExecutionContext,
+ Exposed=(Window,Worker)
+] interface FileReader : EventTarget {
+ // async read methods
+ [RaisesException] void readAsArrayBuffer(Blob blob);
+ [RaisesException] void readAsBinaryString(Blob blob);
+ [RaisesException] void readAsText(Blob blob, optional DOMString label);
+ [RaisesException] void readAsDataURL(Blob blob);
+
+ void abort();
+
+ // states
+ const unsigned short EMPTY = 0;
+ const unsigned short LOADING = 1;
+ const unsigned short DONE = 2;
+
+ [ImplementedAs=getReadyState] readonly attribute unsigned short readyState;
+
+ // File or Blob data
+ [CallWith=ScriptState]
+ readonly attribute (DOMString or ArrayBuffer)? result;
+
+ readonly attribute DOMException? error;
+
+ // event handler attributes
+ attribute EventHandler onloadstart;
+ attribute EventHandler onprogress;
+ attribute EventHandler onload;
+ attribute EventHandler onabort;
+ attribute EventHandler onerror;
+ attribute EventHandler onloadend;
+};
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.cc b/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.cc
new file mode 100644
index 00000000000..5543f63bc48
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.cc
@@ -0,0 +1,431 @@
+/*
+ * 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 "third_party/blink/renderer/core/fileapi/file_reader_loader.h"
+
+#include <limits>
+#include <memory>
+#include <utility>
+
+#include "base/memory/scoped_refptr.h"
+#include "mojo/public/cpp/system/wait.h"
+#include "third_party/blink/public/platform/web_url_request.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/fileapi/blob.h"
+#include "third_party/blink/renderer/core/fileapi/file_reader_loader_client.h"
+#include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
+#include "third_party/blink/renderer/core/loader/threadable_loader.h"
+#include "third_party/blink/renderer/core/loader/threadable_loader_client.h"
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
+#include "third_party/blink/renderer/platform/blob/blob_registry.h"
+#include "third_party/blink/renderer/platform/blob/blob_url.h"
+#include "third_party/blink/renderer/platform/histogram.h"
+#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
+#include "third_party/blink/renderer/platform/loader/fetch/text_resource_decoder_options.h"
+#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
+#include "third_party/blink/renderer/platform/wtf/text/base64.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+// static
+std::unique_ptr<FileReaderLoader> FileReaderLoader::Create(
+ ReadType read_type,
+ FileReaderLoaderClient* client) {
+ return std::make_unique<FileReaderLoader>(read_type, client);
+}
+
+FileReaderLoader::FileReaderLoader(ReadType read_type,
+ FileReaderLoaderClient* client)
+ : read_type_(read_type),
+ client_(client),
+ // TODO(hajimehoshi): Pass an appropriate task runner to SimpleWatcher
+ // constructor.
+ handle_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC),
+ binding_(this),
+ weak_factory_(this) {}
+
+FileReaderLoader::~FileReaderLoader() {
+ Cleanup();
+ UnadjustReportedMemoryUsageToV8();
+}
+
+void FileReaderLoader::Start(scoped_refptr<BlobDataHandle> blob_data) {
+#if DCHECK_IS_ON()
+ DCHECK(!started_loading_) << "FileReaderLoader can only be used once";
+ started_loading_ = true;
+#endif // DCHECK_IS_ON()
+
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ MojoResult result =
+ CreateDataPipe(nullptr, &producer_handle, &consumer_handle_);
+ if (result != MOJO_RESULT_OK) {
+ Failed(FileError::kNotReadableErr);
+ return;
+ }
+
+ mojom::blink::BlobReaderClientPtr client_ptr;
+ binding_.Bind(MakeRequest(&client_ptr));
+ blob_data->ReadAll(std::move(producer_handle), std::move(client_ptr));
+
+ if (IsSyncLoad()) {
+ // Wait for OnCalculatedSize, which will also synchronously drain the data
+ // pipe.
+ binding_.WaitForIncomingMethodCall();
+ if (received_on_complete_)
+ return;
+ if (!received_all_data_) {
+ Failed(FileError::kNotReadableErr);
+ return;
+ }
+
+ // Wait for OnComplete
+ binding_.WaitForIncomingMethodCall();
+ if (!received_on_complete_)
+ Failed(FileError::kNotReadableErr);
+ }
+}
+
+void FileReaderLoader::Cancel() {
+ error_code_ = FileError::kAbortErr;
+ Cleanup();
+}
+
+DOMArrayBuffer* FileReaderLoader::ArrayBufferResult() {
+ DCHECK_EQ(read_type_, kReadAsArrayBuffer);
+ if (array_buffer_result_)
+ return array_buffer_result_;
+
+ // If the loading is not started or an error occurs, return an empty result.
+ if (!raw_data_ || error_code_)
+ return nullptr;
+
+ DOMArrayBuffer* result = DOMArrayBuffer::Create(raw_data_->ToArrayBuffer());
+ if (finished_loading_) {
+ array_buffer_result_ = result;
+ AdjustReportedMemoryUsageToV8(
+ -1 * static_cast<int64_t>(raw_data_->ByteLength()));
+ raw_data_.reset();
+ }
+ return result;
+}
+
+String FileReaderLoader::StringResult() {
+ DCHECK_NE(read_type_, kReadAsArrayBuffer);
+ DCHECK_NE(read_type_, kReadByClient);
+
+ if (!raw_data_ || error_code_ || is_raw_data_converted_)
+ return string_result_;
+
+ switch (read_type_) {
+ case kReadAsArrayBuffer:
+ // No conversion is needed.
+ return string_result_;
+ case kReadAsBinaryString:
+ SetStringResult(raw_data_->ToString());
+ break;
+ case kReadAsText:
+ SetStringResult(ConvertToText());
+ break;
+ case kReadAsDataURL:
+ // Partial data is not supported when reading as data URL.
+ if (finished_loading_)
+ SetStringResult(ConvertToDataURL());
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ if (finished_loading_) {
+ DCHECK(is_raw_data_converted_);
+ AdjustReportedMemoryUsageToV8(
+ -1 * static_cast<int64_t>(raw_data_->ByteLength()));
+ raw_data_.reset();
+ }
+ return string_result_;
+}
+
+void FileReaderLoader::SetEncoding(const String& encoding) {
+ if (!encoding.IsEmpty())
+ encoding_ = WTF::TextEncoding(encoding);
+}
+
+void FileReaderLoader::Cleanup() {
+ handle_watcher_.Cancel();
+ consumer_handle_.reset();
+
+ // If we get any error, we do not need to keep a buffer around.
+ if (error_code_) {
+ raw_data_.reset();
+ string_result_ = "";
+ is_raw_data_converted_ = true;
+ decoder_.reset();
+ array_buffer_result_ = nullptr;
+ UnadjustReportedMemoryUsageToV8();
+ }
+}
+
+void FileReaderLoader::Failed(FileError::ErrorCode error_code) {
+ // If an error was already reported, don't report this error again.
+ if (error_code_ != FileError::kOK)
+ return;
+ error_code_ = error_code;
+ Cleanup();
+ if (client_)
+ client_->DidFail(error_code_);
+}
+
+void FileReaderLoader::OnStartLoading(uint64_t total_bytes) {
+ total_bytes_ = total_bytes;
+
+ DCHECK(!raw_data_);
+
+ if (read_type_ != kReadByClient) {
+ // Check that we can cast to unsigned since we have to do
+ // so to call ArrayBuffer's create function.
+ // FIXME: Support reading more than the current size limit of ArrayBuffer.
+ if (total_bytes > std::numeric_limits<unsigned>::max()) {
+ Failed(FileError::kNotReadableErr);
+ return;
+ }
+
+ raw_data_ = std::make_unique<ArrayBufferBuilder>(total_bytes);
+ if (!raw_data_->IsValid()) {
+ Failed(FileError::kNotReadableErr);
+ return;
+ }
+ raw_data_->SetVariableCapacity(false);
+ }
+
+ if (client_)
+ client_->DidStartLoading();
+}
+
+void FileReaderLoader::OnReceivedData(const char* data, unsigned data_length) {
+ DCHECK(data);
+
+ // Bail out if we already encountered an error.
+ if (error_code_)
+ return;
+
+ if (read_type_ == kReadByClient) {
+ bytes_loaded_ += data_length;
+
+ if (client_)
+ client_->DidReceiveDataForClient(data, data_length);
+ return;
+ }
+
+ unsigned bytes_appended = raw_data_->Append(data, data_length);
+ if (!bytes_appended) {
+ raw_data_.reset();
+ bytes_loaded_ = 0;
+ Failed(FileError::kNotReadableErr);
+ return;
+ }
+ bytes_loaded_ += bytes_appended;
+ is_raw_data_converted_ = false;
+ AdjustReportedMemoryUsageToV8(bytes_appended);
+
+ if (client_)
+ client_->DidReceiveData();
+}
+
+void FileReaderLoader::OnFinishLoading() {
+ if (read_type_ != kReadByClient && raw_data_) {
+ raw_data_->ShrinkToFit();
+ is_raw_data_converted_ = false;
+ }
+
+ finished_loading_ = true;
+
+ Cleanup();
+ if (client_)
+ client_->DidFinishLoading();
+}
+
+void FileReaderLoader::OnCalculatedSize(uint64_t total_size,
+ uint64_t expected_content_size) {
+ auto weak_this = weak_factory_.GetWeakPtr();
+ OnStartLoading(expected_content_size);
+ // OnStartLoading calls out to our client, which could delete |this|, so bail
+ // out if that happened.
+ if (!weak_this)
+ return;
+
+ if (expected_content_size == 0) {
+ received_all_data_ = true;
+ return;
+ }
+
+ if (IsSyncLoad()) {
+ OnDataPipeReadable(MOJO_RESULT_OK);
+ } else {
+ handle_watcher_.Watch(
+ consumer_handle_.get(), MOJO_HANDLE_SIGNAL_READABLE,
+ WTF::BindRepeating(&FileReaderLoader::OnDataPipeReadable,
+ WTF::Unretained(this)));
+ }
+}
+
+void FileReaderLoader::OnComplete(int32_t status, uint64_t data_length) {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(SparseHistogram,
+ file_reader_loader_read_errors_histogram,
+ ("Storage.Blob.FileReaderLoader.ReadError"));
+ if (status != net::OK || data_length != total_bytes_) {
+ net_error_ = status;
+ if (net_error_ != net::OK)
+ file_reader_loader_read_errors_histogram.Sample(std::max(0, -net_error_));
+ Failed(status == net::ERR_FILE_NOT_FOUND ? FileError::kNotFoundErr
+ : FileError::kNotReadableErr);
+ return;
+ }
+
+ received_on_complete_ = true;
+ if (received_all_data_)
+ OnFinishLoading();
+}
+
+void FileReaderLoader::OnDataPipeReadable(MojoResult result) {
+ if (result != MOJO_RESULT_OK) {
+ if (!received_all_data_)
+ Failed(FileError::kNotReadableErr);
+ return;
+ }
+
+ while (true) {
+ uint32_t num_bytes;
+ const void* buffer;
+ MojoResult result = consumer_handle_->BeginReadData(
+ &buffer, &num_bytes, MOJO_READ_DATA_FLAG_NONE);
+ if (result == MOJO_RESULT_SHOULD_WAIT) {
+ if (!IsSyncLoad())
+ return;
+
+ result = mojo::Wait(consumer_handle_.get(), MOJO_HANDLE_SIGNAL_READABLE);
+ if (result == MOJO_RESULT_OK)
+ continue;
+ }
+ if (result == MOJO_RESULT_FAILED_PRECONDITION) {
+ // Pipe closed.
+ if (!received_all_data_)
+ Failed(FileError::kNotReadableErr);
+ return;
+ }
+ if (result != MOJO_RESULT_OK) {
+ Failed(FileError::kNotReadableErr);
+ return;
+ }
+ OnReceivedData(static_cast<const char*>(buffer), num_bytes);
+ consumer_handle_->EndReadData(num_bytes);
+ if (BytesLoaded() >= total_bytes_) {
+ received_all_data_ = true;
+ if (received_on_complete_)
+ OnFinishLoading();
+ return;
+ }
+ }
+}
+
+void FileReaderLoader::AdjustReportedMemoryUsageToV8(int64_t usage) {
+ if (!usage)
+ return;
+ memory_usage_reported_to_v8_ += usage;
+ v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(usage);
+ DCHECK_GE(memory_usage_reported_to_v8_, 0);
+}
+
+void FileReaderLoader::UnadjustReportedMemoryUsageToV8() {
+ if (!memory_usage_reported_to_v8_)
+ return;
+ v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(
+ -memory_usage_reported_to_v8_);
+ memory_usage_reported_to_v8_ = 0;
+}
+
+String FileReaderLoader::ConvertToText() {
+ if (!bytes_loaded_)
+ return "";
+
+ // Decode the data.
+ // The File API spec says that we should use the supplied encoding if it is
+ // valid. However, we choose to ignore this requirement in order to be
+ // consistent with how WebKit decodes the web content: always has the BOM
+ // override the provided encoding.
+ // FIXME: consider supporting incremental decoding to improve the perf.
+ StringBuilder builder;
+ if (!decoder_) {
+ decoder_ = TextResourceDecoder::Create(TextResourceDecoderOptions(
+ TextResourceDecoderOptions::kPlainTextContent,
+ encoding_.IsValid() ? encoding_ : UTF8Encoding()));
+ }
+ builder.Append(decoder_->Decode(static_cast<const char*>(raw_data_->Data()),
+ raw_data_->ByteLength()));
+
+ if (finished_loading_)
+ builder.Append(decoder_->Flush());
+
+ return builder.ToString();
+}
+
+String FileReaderLoader::ConvertToDataURL() {
+ StringBuilder builder;
+ builder.Append("data:");
+
+ if (!bytes_loaded_)
+ return builder.ToString();
+
+ builder.Append(data_type_);
+ builder.Append(";base64,");
+
+ Vector<char> out;
+ Base64Encode(static_cast<const char*>(raw_data_->Data()),
+ raw_data_->ByteLength(), out);
+ out.push_back('\0');
+ builder.Append(out.data());
+
+ return builder.ToString();
+}
+
+void FileReaderLoader::SetStringResult(const String& result) {
+ AdjustReportedMemoryUsageToV8(
+ -1 * static_cast<int64_t>(string_result_.CharactersSizeInBytes()));
+ is_raw_data_converted_ = true;
+ string_result_ = result;
+ AdjustReportedMemoryUsageToV8(string_result_.CharactersSizeInBytes());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.h b/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.h
new file mode 100644
index 00000000000..d8fdaa8b743
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.h
@@ -0,0 +1,172 @@
+/*
+ * 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 THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_READER_LOADER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_READER_LOADER_H_
+
+#include <memory>
+
+#include "base/memory/weak_ptr.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/fileapi/file_error.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "third_party/blink/renderer/platform/wtf/optional.h"
+#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_builder.h"
+
+namespace blink {
+
+class BlobDataHandle;
+class DOMArrayBuffer;
+class FileReaderLoaderClient;
+class TextResourceDecoder;
+
+// Reads a Blob's content into memory.
+//
+// Blobs are typically stored on disk, and should be read asynchronously
+// whenever possible. Synchronous loading is implemented to support Web Platform
+// features that we cannot (yet) remove, such as FileReaderSync and synchronous
+// XMLHttpRequest.
+//
+// Each FileReaderLoader instance is only good for reading one Blob, and will
+// leak resources if used multiple times.
+class CORE_EXPORT FileReaderLoader : public mojom::blink::BlobReaderClient {
+ USING_FAST_MALLOC(FileReaderLoader);
+
+ public:
+ enum ReadType {
+ kReadAsArrayBuffer,
+ kReadAsBinaryString,
+ kReadAsText,
+ kReadAsDataURL,
+ kReadByClient
+ };
+
+ // If client is given, do the loading asynchronously. Otherwise, load
+ // synchronously.
+ static std::unique_ptr<FileReaderLoader> Create(ReadType,
+ FileReaderLoaderClient*);
+ FileReaderLoader(ReadType, FileReaderLoaderClient*);
+ ~FileReaderLoader() override;
+
+ void Start(scoped_refptr<BlobDataHandle>);
+ void Cancel();
+
+ DOMArrayBuffer* ArrayBufferResult();
+ String StringResult();
+
+ // Returns the total bytes received. Bytes ignored by m_rawData won't be
+ // counted.
+ //
+ // This value doesn't grow more than numeric_limits<unsigned> when
+ // m_readType is not set to ReadByClient.
+ uint64_t BytesLoaded() const { return bytes_loaded_; }
+
+ // Before OnCalculatedSize() is called: Returns nullopt.
+ // After OnCalculatedSize() is called: Returns the size of the resource.
+ Optional<uint64_t> TotalBytes() const { return total_bytes_; }
+
+ FileError::ErrorCode GetErrorCode() const { return error_code_; }
+
+ int32_t GetNetError() const { return net_error_; }
+
+ void SetEncoding(const String&);
+ void SetDataType(const String& data_type) { data_type_ = data_type; }
+
+ bool HasFinishedLoading() const { return finished_loading_; }
+
+ private:
+ void Cleanup();
+ void Failed(FileError::ErrorCode);
+
+ void OnStartLoading(uint64_t total_bytes);
+ void OnReceivedData(const char* data, unsigned data_length);
+ void OnFinishLoading();
+
+ bool IsSyncLoad() const { return !client_; }
+
+ // BlobReaderClient:
+ void OnCalculatedSize(uint64_t total_size,
+ uint64_t expected_content_size) override;
+ void OnComplete(int32_t status, uint64_t data_length) override;
+ void OnDataPipeReadable(MojoResult);
+
+ void AdjustReportedMemoryUsageToV8(int64_t usage);
+ void UnadjustReportedMemoryUsageToV8();
+
+ String ConvertToText();
+ String ConvertToDataURL();
+ void SetStringResult(const String&);
+
+ ReadType read_type_;
+ FileReaderLoaderClient* client_;
+ WTF::TextEncoding encoding_;
+ String data_type_;
+
+ std::unique_ptr<ArrayBufferBuilder> raw_data_;
+ bool is_raw_data_converted_ = false;
+
+ Persistent<DOMArrayBuffer> array_buffer_result_;
+ String string_result_;
+
+ // The decoder used to decode the text data.
+ std::unique_ptr<TextResourceDecoder> decoder_;
+
+ bool finished_loading_ = false;
+ uint64_t bytes_loaded_ = 0;
+ // total_bytes_ is set to the total size of the blob being loaded as soon as
+ // it is known, and the buffer for receiving data of total_bytes_ is
+ // allocated and never grow even when extra data is appended.
+ Optional<uint64_t> total_bytes_;
+ int64_t memory_usage_reported_to_v8_ = 0;
+
+ int32_t net_error_ = 0; // net::OK
+ FileError::ErrorCode error_code_ = FileError::kOK;
+
+ mojo::ScopedDataPipeConsumerHandle consumer_handle_;
+ mojo::SimpleWatcher handle_watcher_;
+ mojo::Binding<mojom::blink::BlobReaderClient> binding_;
+ bool received_all_data_ = false;
+ bool received_on_complete_ = false;
+#if DCHECK_IS_ON()
+ bool started_loading_ = false;
+#endif // DCHECK_IS_ON()
+
+ base::WeakPtrFactory<FileReaderLoader> weak_factory_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_READER_LOADER_H_
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader_client.h b/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader_client.h
new file mode 100644
index 00000000000..d52508fbbd3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader_client.h
@@ -0,0 +1,59 @@
+/*
+ * 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 THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_READER_LOADER_CLIENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_READER_LOADER_CLIENT_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/fileapi/file_error.h"
+#include "third_party/blink/renderer/platform/wtf/assertions.h"
+
+namespace blink {
+
+class CORE_EXPORT FileReaderLoaderClient {
+ public:
+ virtual ~FileReaderLoaderClient() = default;
+
+ virtual void DidStartLoading() = 0;
+ // Clients must implement this method if they are using any ReadType except
+ // ReadByClient.
+ virtual void DidReceiveData() { NOTREACHED(); }
+ // Clients must implement this method if they are using the ReadByClient
+ // ReadType.
+ virtual void DidReceiveDataForClient(const char* data, unsigned data_length) {
+ NOTREACHED();
+ }
+ virtual void DidFinishLoading() = 0;
+ virtual void DidFail(FileError::ErrorCode) = 0;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_READER_LOADER_CLIENT_H_
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_reader_sync.cc b/chromium/third_party/blink/renderer/core/fileapi/file_reader_sync.cc
new file mode 100644
index 00000000000..94d3943339b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_reader_sync.cc
@@ -0,0 +1,123 @@
+/*
+ * 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 "third_party/blink/renderer/core/fileapi/file_reader_sync.h"
+
+#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/fileapi/blob.h"
+#include "third_party/blink/renderer/core/fileapi/file_error.h"
+#include "third_party/blink/renderer/core/fileapi/file_reader_loader.h"
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/histogram.h"
+
+namespace blink {
+
+namespace {
+// These values are written to logs. New enum values can be added, but existing
+// enums must never be renumbered or deleted and reused.
+enum class WorkerType {
+ OTHER = 0,
+ DEDICATED_WORKER = 1,
+ SHARED_WORKER = 2,
+ SERVICE_WORKER = 3,
+ MAX
+};
+} // namespace
+
+FileReaderSync::FileReaderSync(ExecutionContext* context) {
+ WorkerType type = WorkerType::OTHER;
+ if (context->IsDedicatedWorkerGlobalScope())
+ type = WorkerType::DEDICATED_WORKER;
+ else if (context->IsSharedWorkerGlobalScope())
+ type = WorkerType::SHARED_WORKER;
+ else if (context->IsServiceWorkerGlobalScope())
+ type = WorkerType::SERVICE_WORKER;
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ EnumerationHistogram, worker_type_histogram,
+ ("FileReaderSync.WorkerType", static_cast<int>(WorkerType::MAX)));
+ worker_type_histogram.Count(static_cast<int>(type));
+}
+
+DOMArrayBuffer* FileReaderSync::readAsArrayBuffer(
+ Blob* blob,
+ ExceptionState& exception_state) {
+ DCHECK(blob);
+
+ std::unique_ptr<FileReaderLoader> loader =
+ FileReaderLoader::Create(FileReaderLoader::kReadAsArrayBuffer, nullptr);
+ StartLoading(*loader, *blob, exception_state);
+
+ return loader->ArrayBufferResult();
+}
+
+String FileReaderSync::readAsBinaryString(Blob* blob,
+ ExceptionState& exception_state) {
+ DCHECK(blob);
+
+ std::unique_ptr<FileReaderLoader> loader =
+ FileReaderLoader::Create(FileReaderLoader::kReadAsBinaryString, nullptr);
+ StartLoading(*loader, *blob, exception_state);
+ return loader->StringResult();
+}
+
+String FileReaderSync::readAsText(Blob* blob,
+ const String& encoding,
+ ExceptionState& exception_state) {
+ DCHECK(blob);
+
+ std::unique_ptr<FileReaderLoader> loader =
+ FileReaderLoader::Create(FileReaderLoader::kReadAsText, nullptr);
+ loader->SetEncoding(encoding);
+ StartLoading(*loader, *blob, exception_state);
+ return loader->StringResult();
+}
+
+String FileReaderSync::readAsDataURL(Blob* blob,
+ ExceptionState& exception_state) {
+ DCHECK(blob);
+
+ std::unique_ptr<FileReaderLoader> loader =
+ FileReaderLoader::Create(FileReaderLoader::kReadAsDataURL, nullptr);
+ loader->SetDataType(blob->type());
+ StartLoading(*loader, *blob, exception_state);
+ return loader->StringResult();
+}
+
+void FileReaderSync::StartLoading(FileReaderLoader& loader,
+ const Blob& blob,
+ ExceptionState& exception_state) {
+ loader.Start(blob.GetBlobDataHandle());
+ if (loader.GetErrorCode())
+ FileError::ThrowDOMException(exception_state, loader.GetErrorCode());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_reader_sync.h b/chromium/third_party/blink/renderer/core/fileapi/file_reader_sync.h
new file mode 100644
index 00000000000..d5db3fca225
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_reader_sync.h
@@ -0,0 +1,70 @@
+/*
+ * 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 THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_READER_SYNC_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_READER_SYNC_H_
+
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class Blob;
+class DOMArrayBuffer;
+class ExceptionState;
+class ExecutionContext;
+class FileReaderLoader;
+
+class FileReaderSync final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static FileReaderSync* Create(ExecutionContext* context) {
+ return new FileReaderSync(context);
+ }
+
+ DOMArrayBuffer* readAsArrayBuffer(Blob*, ExceptionState&);
+ String readAsBinaryString(Blob*, ExceptionState&);
+ String readAsText(Blob* blob, ExceptionState& ec) {
+ return readAsText(blob, "", ec);
+ }
+ String readAsText(Blob*, const String& encoding, ExceptionState&);
+ String readAsDataURL(Blob*, ExceptionState&);
+
+ private:
+ explicit FileReaderSync(ExecutionContext*);
+
+ void StartLoading(FileReaderLoader&, const Blob&, ExceptionState&);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_READER_SYNC_H_
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_reader_sync.idl b/chromium/third_party/blink/renderer/core/fileapi/file_reader_sync.idl
new file mode 100644
index 00000000000..2f8ef263c0c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_reader_sync.idl
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+// https://w3c.github.io/FileAPI/#FileReaderSync
+
+[
+ Exposed=(DedicatedWorker,SharedWorker),
+ Constructor,
+ ConstructorCallWith=ExecutionContext,
+ Measure
+] interface FileReaderSync {
+ [RaisesException] ArrayBuffer readAsArrayBuffer(Blob blob);
+ [RaisesException] DOMString readAsBinaryString(Blob blob);
+ [RaisesException] DOMString readAsText(Blob blob, optional DOMString label);
+ [RaisesException] DOMString readAsDataURL(Blob blob);
+};
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_test.cc b/chromium/third_party/blink/renderer/core/fileapi/file_test.cc
new file mode 100644
index 00000000000..d09de6af79b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_test.cc
@@ -0,0 +1,97 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/fileapi/file.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/file_metadata.h"
+
+namespace blink {
+
+TEST(FileTest, nativeFile) {
+ File* const file = File::Create("/native/path");
+ EXPECT_TRUE(file->HasBackingFile());
+ EXPECT_EQ("/native/path", file->GetPath());
+ EXPECT_TRUE(file->FileSystemURL().IsEmpty());
+}
+
+TEST(FileTest, blobBackingFile) {
+ const scoped_refptr<BlobDataHandle> blob_data_handle =
+ BlobDataHandle::Create();
+ File* const file = File::Create("name", 0.0, blob_data_handle);
+ EXPECT_FALSE(file->HasBackingFile());
+ EXPECT_TRUE(file->GetPath().IsEmpty());
+ EXPECT_TRUE(file->FileSystemURL().IsEmpty());
+}
+
+TEST(FileTest, fileSystemFileWithNativeSnapshot) {
+ FileMetadata metadata;
+ metadata.platform_path = "/native/snapshot";
+ File* const file =
+ File::CreateForFileSystemFile("name", metadata, File::kIsUserVisible);
+ EXPECT_TRUE(file->HasBackingFile());
+ EXPECT_EQ("/native/snapshot", file->GetPath());
+ EXPECT_TRUE(file->FileSystemURL().IsEmpty());
+}
+
+TEST(FileTest, fileSystemFileWithNativeSnapshotAndSize) {
+ FileMetadata metadata;
+ metadata.length = 1024ll;
+ metadata.platform_path = "/native/snapshot";
+ File* const file =
+ File::CreateForFileSystemFile("name", metadata, File::kIsUserVisible);
+ EXPECT_TRUE(file->HasBackingFile());
+ EXPECT_EQ("/native/snapshot", file->GetPath());
+ EXPECT_TRUE(file->FileSystemURL().IsEmpty());
+}
+
+TEST(FileTest, fileSystemFileWithoutNativeSnapshot) {
+ KURL url("filesystem:http://example.com/isolated/hash/non-native-file");
+ FileMetadata metadata;
+ File* const file =
+ File::CreateForFileSystemFile(url, metadata, File::kIsUserVisible);
+ EXPECT_FALSE(file->HasBackingFile());
+ EXPECT_TRUE(file->GetPath().IsEmpty());
+ EXPECT_EQ(url, file->FileSystemURL());
+}
+
+TEST(FileTest, hsaSameSource) {
+ File* const native_file_a1 = File::Create("/native/pathA");
+ File* const native_file_a2 = File::Create("/native/pathA");
+ File* const native_file_b = File::Create("/native/pathB");
+
+ const scoped_refptr<BlobDataHandle> blob_data_a = BlobDataHandle::Create();
+ const scoped_refptr<BlobDataHandle> blob_data_b = BlobDataHandle::Create();
+ File* const blob_file_a1 = File::Create("name", 0.0, blob_data_a);
+ File* const blob_file_a2 = File::Create("name", 0.0, blob_data_a);
+ File* const blob_file_b = File::Create("name", 0.0, blob_data_b);
+
+ KURL url_a("filesystem:http://example.com/isolated/hash/non-native-file-A");
+ KURL url_b("filesystem:http://example.com/isolated/hash/non-native-file-B");
+ FileMetadata metadata;
+ File* const file_system_file_a1 =
+ File::CreateForFileSystemFile(url_a, metadata, File::kIsUserVisible);
+ File* const file_system_file_a2 =
+ File::CreateForFileSystemFile(url_a, metadata, File::kIsUserVisible);
+ File* const file_system_file_b =
+ File::CreateForFileSystemFile(url_b, metadata, File::kIsUserVisible);
+
+ EXPECT_FALSE(native_file_a1->HasSameSource(*blob_file_a1));
+ EXPECT_FALSE(blob_file_a1->HasSameSource(*file_system_file_a1));
+ EXPECT_FALSE(file_system_file_a1->HasSameSource(*native_file_a1));
+
+ EXPECT_TRUE(native_file_a1->HasSameSource(*native_file_a1));
+ EXPECT_TRUE(native_file_a1->HasSameSource(*native_file_a2));
+ EXPECT_FALSE(native_file_a1->HasSameSource(*native_file_b));
+
+ EXPECT_TRUE(blob_file_a1->HasSameSource(*blob_file_a1));
+ EXPECT_TRUE(blob_file_a1->HasSameSource(*blob_file_a2));
+ EXPECT_FALSE(blob_file_a1->HasSameSource(*blob_file_b));
+
+ EXPECT_TRUE(file_system_file_a1->HasSameSource(*file_system_file_a1));
+ EXPECT_TRUE(file_system_file_a1->HasSameSource(*file_system_file_a2));
+ EXPECT_FALSE(file_system_file_a1->HasSameSource(*file_system_file_b));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fileapi/public_url_manager.cc b/chromium/third_party/blink/renderer/core/fileapi/public_url_manager.cc
new file mode 100644
index 00000000000..19faf5d2f96
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/public_url_manager.cc
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2012 Motorola Mobility Inc.
+ * Copyright (C) 2013 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:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS 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 APPLE OR ITS 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 "third_party/blink/renderer/core/fileapi/public_url_manager.h"
+
+#include "third_party/blink/public/mojom/blob/blob_registry.mojom-blink.h"
+#include "third_party/blink/renderer/core/fileapi/url_registry.h"
+#include "third_party/blink/renderer/platform/blob/blob_data.h"
+#include "third_party/blink/renderer/platform/blob/blob_url.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+#include "third_party/blink/renderer/platform/weborigin/url_security_origin_map.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
+#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+namespace {
+
+// When a blob URL is created in a unique origin the origin is serialized into
+// the URL as "null". Since that makes it impossible to parse the origin back
+// out and compare it against a context's origin (to check if a context is
+// allowed to dereference the URL) we store a map of blob URL to SecurityOrigin
+// instance for blob URLs with unique origins.
+
+class BlobOriginMap : public URLSecurityOriginMap {
+ public:
+ BlobOriginMap();
+ SecurityOrigin* GetOrigin(const KURL&) override;
+};
+
+typedef HashMap<String, scoped_refptr<SecurityOrigin>> BlobURLOriginMap;
+static ThreadSpecific<BlobURLOriginMap>& OriginMap() {
+ // We want to create the BlobOriginMap exactly once because it is shared by
+ // all the threads.
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(BlobOriginMap, cache, ());
+ (void)cache; // BlobOriginMap's constructor does the interesting work.
+
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<BlobURLOriginMap>, map, ());
+ return map;
+}
+
+static void SaveToOriginMap(SecurityOrigin* origin, const KURL& url) {
+ // If the blob URL contains null origin, as in the context with unique
+ // security origin or file URL, save the mapping between url and origin so
+ // that the origin can be retrieved when doing security origin check.
+ //
+ // See the definition of the origin of a Blob URL in the File API spec.
+ DCHECK(!url.HasFragmentIdentifier());
+ if (origin && BlobURL::GetOrigin(url) == "null")
+ OriginMap()->insert(url.GetString(), origin);
+}
+
+static void RemoveFromOriginMap(const KURL& url) {
+ if (BlobURL::GetOrigin(url) == "null")
+ OriginMap()->erase(url.GetString());
+}
+
+BlobOriginMap::BlobOriginMap() {
+ SecurityOrigin::SetMap(this);
+}
+
+SecurityOrigin* BlobOriginMap::GetOrigin(const KURL& url) {
+ if (url.ProtocolIs("blob")) {
+ KURL url_without_fragment = url;
+ url_without_fragment.RemoveFragmentIdentifier();
+ return OriginMap()->at(url_without_fragment.GetString());
+ }
+ return nullptr;
+}
+
+} // namespace
+
+PublicURLManager* PublicURLManager::Create(ExecutionContext* context) {
+ return new PublicURLManager(context);
+}
+
+PublicURLManager::PublicURLManager(ExecutionContext* context)
+ : ContextLifecycleObserver(context), is_stopped_(false) {}
+
+String PublicURLManager::RegisterURL(URLRegistrable* registrable) {
+ if (is_stopped_)
+ return String();
+
+ SecurityOrigin* origin = GetExecutionContext()->GetMutableSecurityOrigin();
+ const KURL& url = BlobURL::CreatePublicURL(origin);
+ DCHECK(!url.IsEmpty());
+ const String& url_string = url.GetString();
+
+ mojom::blink::BlobPtr blob;
+ if (RuntimeEnabledFeatures::MojoBlobURLsEnabled())
+ blob = registrable->AsMojoBlob();
+ if (blob) {
+ if (!url_store_) {
+ BlobDataHandle::GetBlobRegistry()->URLStoreForOrigin(
+ origin, MakeRequest(&url_store_));
+ }
+ url_store_->Register(std::move(blob), url);
+ mojo_urls_.insert(url_string);
+ } else {
+ URLRegistry* registry = &registrable->Registry();
+ registry->RegisterURL(origin, url, registrable);
+ url_to_registry_.insert(url_string, registry);
+ }
+ SaveToOriginMap(origin, url);
+
+ return url_string;
+}
+
+void PublicURLManager::Revoke(const KURL& url) {
+ if (is_stopped_)
+ return;
+ // Don't bother trying to revoke URLs that can't have been registered anyway.
+ if (!url.ProtocolIs("blob") || url.HasFragmentIdentifier())
+ return;
+ // Don't support revoking cross-origin blob URLs.
+ if (!SecurityOrigin::Create(url)->IsSameSchemeHostPort(
+ GetExecutionContext()->GetSecurityOrigin()))
+ return;
+
+ if (RuntimeEnabledFeatures::MojoBlobURLsEnabled()) {
+ if (!url_store_) {
+ BlobDataHandle::GetBlobRegistry()->URLStoreForOrigin(
+ GetExecutionContext()->GetSecurityOrigin(), MakeRequest(&url_store_));
+ }
+ url_store_->Revoke(url);
+ mojo_urls_.erase(url.GetString());
+ }
+ RemoveFromOriginMap(url);
+ auto it = url_to_registry_.find(url.GetString());
+ if (it == url_to_registry_.end())
+ return;
+ it->value->UnregisterURL(url);
+ url_to_registry_.erase(it);
+}
+
+void PublicURLManager::Resolve(
+ const KURL& url,
+ network::mojom::blink::URLLoaderFactoryRequest factory_request) {
+ DCHECK(RuntimeEnabledFeatures::MojoBlobURLsEnabled());
+ DCHECK(url.ProtocolIs("blob"));
+ if (!url_store_) {
+ BlobDataHandle::GetBlobRegistry()->URLStoreForOrigin(
+ GetExecutionContext()->GetSecurityOrigin(), MakeRequest(&url_store_));
+ }
+ url_store_->ResolveAsURLLoaderFactory(url, std::move(factory_request));
+}
+
+void PublicURLManager::Resolve(
+ const KURL& url,
+ mojom::blink::BlobURLTokenRequest token_request) {
+ DCHECK(RuntimeEnabledFeatures::MojoBlobURLsEnabled());
+ DCHECK(url.ProtocolIs("blob"));
+ if (!url_store_) {
+ BlobDataHandle::GetBlobRegistry()->URLStoreForOrigin(
+ GetExecutionContext()->GetSecurityOrigin(), MakeRequest(&url_store_));
+ }
+ url_store_->ResolveForNavigation(url, std::move(token_request));
+}
+
+void PublicURLManager::ContextDestroyed(ExecutionContext*) {
+ if (is_stopped_)
+ return;
+
+ is_stopped_ = true;
+ for (auto& url_registry : url_to_registry_) {
+ url_registry.value->UnregisterURL(KURL(url_registry.key));
+ RemoveFromOriginMap(KURL(url_registry.key));
+ }
+ for (const auto& url : mojo_urls_)
+ RemoveFromOriginMap(KURL(url));
+
+ url_to_registry_.clear();
+ mojo_urls_.clear();
+
+ url_store_.reset();
+}
+
+void PublicURLManager::Trace(blink::Visitor* visitor) {
+ ContextLifecycleObserver::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fileapi/public_url_manager.h b/chromium/third_party/blink/renderer/core/fileapi/public_url_manager.h
new file mode 100644
index 00000000000..9d5e9454f5c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/public_url_manager.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2012 Motorola Mobility Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS 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 APPLE OR ITS 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 THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_PUBLIC_URL_MANAGER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_PUBLIC_URL_MANAGER_H_
+
+#include "services/network/public/mojom/url_loader_factory.mojom-blink.h"
+#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/hash_set.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class KURL;
+class ExecutionContext;
+class URLRegistry;
+class URLRegistrable;
+
+class CORE_EXPORT PublicURLManager final
+ : public GarbageCollectedFinalized<PublicURLManager>,
+ public ContextLifecycleObserver {
+ USING_GARBAGE_COLLECTED_MIXIN(PublicURLManager);
+
+ public:
+ static PublicURLManager* Create(ExecutionContext*);
+
+ // Generates a new Blob URL and registers the URLRegistrable to the
+ // corresponding URLRegistry with the Blob URL. Returns the serialization
+ // of the Blob URL.
+ String RegisterURL(URLRegistrable*);
+ // Revokes the given URL.
+ void Revoke(const KURL&);
+ // When mojo Blob URLs are enabled this resolves the provided URL to a
+ // factory capable of creating loaders for the specific URL.
+ void Resolve(const KURL&, network::mojom::blink::URLLoaderFactoryRequest);
+ // When mojo Blob URLs are enabled this resolves the provided URL to a mojom
+ // BlobURLToken. This token can be used by the browser process to securely
+ // lookup what blob a URL used to refer to, even after the URL is revoked.
+ // If the URL fails to resolve the request will simply be disconnected.
+ void Resolve(const KURL&, mojom::blink::BlobURLTokenRequest);
+
+ // ContextLifecycleObserver interface.
+ void ContextDestroyed(ExecutionContext*) override;
+
+ virtual void Trace(blink::Visitor*);
+
+ void SetURLStoreForTesting(
+ mojom::blink::BlobURLStoreAssociatedPtr url_store) {
+ url_store_ = std::move(url_store);
+ }
+
+ private:
+ explicit PublicURLManager(ExecutionContext*);
+
+ typedef String URLString;
+ // Map from URLs to the URLRegistry they are registered with.
+ typedef HashMap<URLString, URLRegistry*> URLToRegistryMap;
+ URLToRegistryMap url_to_registry_;
+ HashSet<URLString> mojo_urls_;
+
+ bool is_stopped_;
+
+ mojom::blink::BlobURLStoreAssociatedPtr url_store_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_PUBLIC_URL_MANAGER_H_
diff --git a/chromium/third_party/blink/renderer/core/fileapi/public_url_manager_test.cc b/chromium/third_party/blink/renderer/core/fileapi/public_url_manager_test.cc
new file mode 100644
index 00000000000..7e2a27d1284
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/public_url_manager_test.cc
@@ -0,0 +1,174 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/fileapi/public_url_manager.h"
+
+#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/fileapi/url_registry.h"
+#include "third_party/blink/renderer/core/testing/null_execution_context.h"
+#include "third_party/blink/renderer/platform/blob/testing/fake_blob.h"
+#include "third_party/blink/renderer/platform/blob/testing/fake_blob_url_store.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+
+namespace blink {
+namespace {
+
+using mojom::blink::Blob;
+using mojom::blink::BlobPtr;
+using mojom::blink::BlobRequest;
+using mojom::blink::BlobURLStore;
+using mojom::blink::BlobURLStoreAssociatedPtr;
+
+class TestURLRegistrable : public URLRegistrable {
+ public:
+ TestURLRegistrable(URLRegistry* registry, BlobPtr blob = nullptr)
+ : registry_(registry), blob_(std::move(blob)) {}
+
+ URLRegistry& Registry() const override { return *registry_; }
+
+ BlobPtr AsMojoBlob() override {
+ if (!blob_)
+ return nullptr;
+ BlobPtr result;
+ blob_->Clone(MakeRequest(&result));
+ return result;
+ }
+
+ private:
+ URLRegistry* const registry_;
+ BlobPtr blob_;
+};
+
+class FakeURLRegistry : public URLRegistry {
+ public:
+ void RegisterURL(SecurityOrigin* origin,
+ const KURL& url,
+ URLRegistrable* registrable) override {
+ registrations.push_back(Registration{origin, url, registrable});
+ }
+ void UnregisterURL(const KURL&) override {}
+
+ struct Registration {
+ SecurityOrigin* origin;
+ KURL url;
+ URLRegistrable* registrable;
+ };
+ Vector<Registration> registrations;
+};
+
+} // namespace
+
+class PublicURLManagerTest : public testing::Test {
+ public:
+ PublicURLManagerTest() : url_store_binding_(&url_store_) {}
+
+ void SetUp() override {
+ execution_context_ = new NullExecutionContext;
+ // By default this creates a unique origin, which is exactly what this test
+ // wants.
+ execution_context_->SetUpSecurityContext();
+
+ BlobURLStoreAssociatedPtr url_store_ptr;
+ url_store_binding_.Bind(
+ MakeRequestAssociatedWithDedicatedPipe(&url_store_ptr));
+ url_manager().SetURLStoreForTesting(std::move(url_store_ptr));
+ }
+
+ PublicURLManager& url_manager() {
+ return execution_context_->GetPublicURLManager();
+ }
+
+ BlobPtr CreateMojoBlob(const String& uuid) {
+ BlobPtr result;
+ mojo::MakeStrongBinding(std::make_unique<FakeBlob>(uuid),
+ MakeRequest(&result));
+ return result;
+ }
+
+ protected:
+ ScopedMojoBlobURLsForTest mojo_blob_urls_ = true;
+ Persistent<NullExecutionContext> execution_context_;
+
+ FakeBlobURLStore url_store_;
+ mojo::AssociatedBinding<BlobURLStore> url_store_binding_;
+};
+
+TEST_F(PublicURLManagerTest, RegisterNonMojoBlob) {
+ FakeURLRegistry registry;
+ TestURLRegistrable registrable(&registry);
+ String url = url_manager().RegisterURL(&registrable);
+ ASSERT_EQ(1u, registry.registrations.size());
+ EXPECT_EQ(0u, url_store_.registrations.size());
+ EXPECT_EQ(execution_context_->GetSecurityOrigin(),
+ registry.registrations[0].origin);
+ EXPECT_EQ(url, registry.registrations[0].url);
+ EXPECT_EQ(&registrable, registry.registrations[0].registrable);
+
+ EXPECT_TRUE(SecurityOrigin::CreateFromString(url)->IsSameSchemeHostPort(
+ execution_context_->GetSecurityOrigin()));
+ EXPECT_EQ(execution_context_->GetSecurityOrigin(),
+ SecurityOrigin::CreateFromString(url));
+
+ url_manager().Revoke(KURL(url));
+ EXPECT_FALSE(SecurityOrigin::CreateFromString(url)->IsSameSchemeHostPort(
+ execution_context_->GetSecurityOrigin()));
+ url_store_binding_.FlushForTesting();
+ // Even though this was not a mojo blob, the PublicURLManager might not know
+ // that, so still expect a revocation on the mojo interface.
+ ASSERT_EQ(1u, url_store_.revocations.size());
+ EXPECT_EQ(url, url_store_.revocations[0]);
+}
+
+TEST_F(PublicURLManagerTest, RegisterMojoBlob) {
+ FakeURLRegistry registry;
+ TestURLRegistrable registrable(&registry, CreateMojoBlob("id"));
+ String url = url_manager().RegisterURL(&registrable);
+
+ EXPECT_EQ(0u, registry.registrations.size());
+ ASSERT_EQ(1u, url_store_.registrations.size());
+ EXPECT_EQ(url, url_store_.registrations.begin()->key);
+
+ EXPECT_TRUE(SecurityOrigin::CreateFromString(url)->IsSameSchemeHostPort(
+ execution_context_->GetSecurityOrigin()));
+ EXPECT_EQ(execution_context_->GetSecurityOrigin(),
+ SecurityOrigin::CreateFromString(url));
+
+ url_manager().Revoke(KURL(url));
+ EXPECT_FALSE(SecurityOrigin::CreateFromString(url)->IsSameSchemeHostPort(
+ execution_context_->GetSecurityOrigin()));
+ url_store_binding_.FlushForTesting();
+ ASSERT_EQ(1u, url_store_.revocations.size());
+ EXPECT_EQ(url, url_store_.revocations[0]);
+}
+
+TEST_F(PublicURLManagerTest, RevokeValidNonRegisteredURL) {
+ execution_context_->SetURL(KURL("http://example.com/foo/bar"));
+ execution_context_->SetUpSecurityContext();
+
+ KURL url = KURL("blob:http://example.com/id");
+ url_manager().Revoke(url);
+ url_store_binding_.FlushForTesting();
+ ASSERT_EQ(1u, url_store_.revocations.size());
+ EXPECT_EQ(url, url_store_.revocations[0]);
+}
+
+TEST_F(PublicURLManagerTest, RevokeInvalidURL) {
+ execution_context_->SetURL(KURL("http://example.com/foo/bar"));
+ execution_context_->SetUpSecurityContext();
+
+ KURL invalid_scheme_url = KURL("blb:http://example.com/id");
+ KURL fragment_url = KURL("blob:http://example.com/id#fragment");
+ KURL invalid_origin_url = KURL("blob:http://foobar.com/id");
+ url_manager().Revoke(invalid_scheme_url);
+ url_manager().Revoke(fragment_url);
+ url_manager().Revoke(invalid_origin_url);
+ url_store_binding_.FlushForTesting();
+ // Both should have been silently ignored.
+ EXPECT_TRUE(url_store_.revocations.IsEmpty());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fileapi/url_file_api.cc b/chromium/third_party/blink/renderer/core/fileapi/url_file_api.cc
new file mode 100644
index 00000000000..dc29bc939df
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/url_file_api.cc
@@ -0,0 +1,40 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/fileapi/url_file_api.h"
+
+#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/fileapi/blob.h"
+#include "third_party/blink/renderer/core/fileapi/public_url_manager.h"
+#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/core/url/dom_url.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+
+namespace blink {
+
+// static
+String URLFileAPI::createObjectURL(ScriptState* script_state,
+ Blob* blob,
+ ExceptionState& exception_state) {
+ DCHECK(blob);
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+ DCHECK(execution_context);
+
+ UseCounter::Count(execution_context, WebFeature::kCreateObjectURLBlob);
+ return DOMURL::CreatePublicURL(execution_context, blob);
+}
+
+// static
+void URLFileAPI::revokeObjectURL(ScriptState* script_state,
+ const String& url_string) {
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+ DCHECK(execution_context);
+
+ KURL url(NullURL(), url_string);
+ execution_context->RemoveURLFromMemoryCache(url);
+ execution_context->GetPublicURLManager().Revoke(url);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fileapi/url_file_api.h b/chromium/third_party/blink/renderer/core/fileapi/url_file_api.h
new file mode 100644
index 00000000000..dcab4f27217
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/url_file_api.h
@@ -0,0 +1,27 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_URL_FILE_API_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_URL_FILE_API_H_
+
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace blink {
+
+class ExceptionState;
+class ScriptState;
+class Blob;
+
+class URLFileAPI {
+ STATIC_ONLY(URLFileAPI);
+
+ public:
+ static String createObjectURL(ScriptState*, Blob*, ExceptionState&);
+ static void revokeObjectURL(ScriptState*, const String&);
+};
+
+} // namespace blink
+
+#endif
diff --git a/chromium/third_party/blink/renderer/core/fileapi/url_file_api.idl b/chromium/third_party/blink/renderer/core/fileapi/url_file_api.idl
new file mode 100644
index 00000000000..da2b186b2bb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/url_file_api.idl
@@ -0,0 +1,11 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://w3c.github.io/FileAPI/#creating-revoking
+[
+ ImplementedAs=URLFileAPI
+] partial interface URL {
+ [Exposed=(Window,DedicatedWorker,SharedWorker), CallWith=ScriptState, RaisesException] static DOMString createObjectURL(Blob blob);
+ [Exposed=(Window,DedicatedWorker,SharedWorker), CallWith=ScriptState] static void revokeObjectURL(DOMString url);
+};
diff --git a/chromium/third_party/blink/renderer/core/fileapi/url_registry.h b/chromium/third_party/blink/renderer/core/fileapi/url_registry.h
new file mode 100644
index 00000000000..e68d8ae63cd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fileapi/url_registry.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2013 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 THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_URL_REGISTRY_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_URL_REGISTRY_H_
+
+#include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class KURL;
+class SecurityOrigin;
+class URLRegistry;
+
+class CORE_EXPORT URLRegistrable {
+ public:
+ virtual ~URLRegistrable() = default;
+ virtual URLRegistry& Registry() const = 0;
+ virtual mojom::blink::BlobPtr AsMojoBlob() { return nullptr; }
+};
+
+class CORE_EXPORT URLRegistry {
+ USING_FAST_MALLOC(URLRegistry);
+
+ public:
+ virtual ~URLRegistry() = default;
+ virtual void RegisterURL(SecurityOrigin*, const KURL&, URLRegistrable*) = 0;
+ virtual void UnregisterURL(const KURL&) = 0;
+
+ // These are optional APIs
+ virtual URLRegistrable* Lookup(const String&) {
+ NOTREACHED();
+ return nullptr;
+ }
+ virtual bool Contains(const String&) {
+ NOTREACHED();
+ return false;
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_URL_REGISTRY_H_