summaryrefslogtreecommitdiff
path: root/chromium/storage
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-11-18 16:35:47 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-11-18 15:45:54 +0000
commit32f5a1c56531e4210bc4cf8d8c7825d66e081888 (patch)
treeeeeec6822f4d738d8454525233fd0e2e3a659e6d /chromium/storage
parent99677208ff3b216fdfec551fbe548da5520cd6fb (diff)
downloadqtwebengine-chromium-32f5a1c56531e4210bc4cf8d8c7825d66e081888.tar.gz
BASELINE: Update Chromium to 87.0.4280.67
Change-Id: Ib157360be8c2ffb2c73125751a89f60e049c1d54 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/storage')
-rw-r--r--chromium/storage/browser/BUILD.gn7
-rw-r--r--chromium/storage/browser/blob/blob_builder_from_stream_unittest.cc3
-rw-r--r--chromium/storage/browser/blob/blob_data_builder.cc2
-rw-r--r--chromium/storage/browser/blob/blob_data_builder.h3
-rw-r--r--chromium/storage/browser/blob/blob_data_item.cc5
-rw-r--r--chromium/storage/browser/blob/blob_data_item.h11
-rw-r--r--chromium/storage/browser/blob/blob_reader.cc8
-rw-r--r--chromium/storage/browser/blob/blob_reader_unittest.cc16
-rw-r--r--chromium/storage/browser/blob/blob_registry_impl.cc80
-rw-r--r--chromium/storage/browser/blob/blob_registry_impl_unittest.cc4
-rw-r--r--chromium/storage/browser/blob/blob_storage_context_unittest.cc9
-rw-r--r--chromium/storage/browser/blob/blob_url_registry.cc12
-rw-r--r--chromium/storage/browser/blob/blob_url_registry.h8
-rw-r--r--chromium/storage/browser/blob/view_blob_internals_job.cc2
-rw-r--r--chromium/storage/browser/blob/write_blob_to_file.cc3
-rw-r--r--chromium/storage/browser/file_system/file_stream_reader.h24
-rw-r--r--chromium/storage/browser/file_system/file_stream_reader_test.cc12
-rw-r--r--chromium/storage/browser/file_system/file_stream_reader_test.h287
-rw-r--r--chromium/storage/browser/file_system/file_system_file_stream_reader_unittest.cc199
-rw-r--r--chromium/storage/browser/file_system/file_system_quota_client_unittest.cc52
-rw-r--r--chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader.cc245
-rw-r--r--chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader.h93
-rw-r--r--chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader_unittest.cc109
-rw-r--r--chromium/storage/browser/file_system/local_file_stream_reader.cc62
-rw-r--r--chromium/storage/browser/file_system/local_file_stream_reader.h7
-rw-r--r--chromium/storage/browser/file_system/local_file_stream_reader_unittest.cc237
-rw-r--r--chromium/storage/browser/file_system/local_file_stream_writer.cc31
-rw-r--r--chromium/storage/browser/file_system/local_file_stream_writer.h5
-rw-r--r--chromium/storage/browser/file_system/local_file_stream_writer_unittest.cc31
-rw-r--r--chromium/storage/browser/file_system/memory_file_stream_reader_unittest.cc231
-rw-r--r--chromium/storage/browser/file_system/memory_file_stream_writer.cc36
-rw-r--r--chromium/storage/browser/file_system/memory_file_stream_writer.h8
-rw-r--r--chromium/storage/browser/file_system/memory_file_stream_writer_unittest.cc26
-rw-r--r--chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc9
-rw-r--r--chromium/storage/browser/file_system/sandbox_file_stream_writer.cc2
-rw-r--r--chromium/storage/browser/quota/quota_database.cc28
-rw-r--r--chromium/storage/browser/quota/quota_database.h10
-rw-r--r--chromium/storage/browser/quota/quota_database_unittest.cc60
-rw-r--r--chromium/storage/browser/quota/quota_features.cc20
-rw-r--r--chromium/storage/browser/quota/quota_features.h8
-rw-r--r--chromium/storage/browser/quota/quota_manager.cc40
-rw-r--r--chromium/storage/browser/quota/quota_manager.h7
-rw-r--r--chromium/storage/browser/quota/quota_manager_proxy.cc10
-rw-r--r--chromium/storage/browser/quota/quota_manager_unittest.cc20
-rw-r--r--chromium/storage/browser/quota/quota_settings.cc12
-rw-r--r--chromium/storage/browser/quota/quota_settings_unittest.cc42
46 files changed, 1285 insertions, 851 deletions
diff --git a/chromium/storage/browser/BUILD.gn b/chromium/storage/browser/BUILD.gn
index 48be0d9f2bd..3ac459e3459 100644
--- a/chromium/storage/browser/BUILD.gn
+++ b/chromium/storage/browser/BUILD.gn
@@ -111,6 +111,8 @@ component("browser") {
"file_system/file_system_usage_cache.h",
"file_system/file_writer_delegate.cc",
"file_system/file_writer_delegate.h",
+ "file_system/filesystem_proxy_file_stream_reader.cc",
+ "file_system/filesystem_proxy_file_stream_reader.h",
"file_system/isolated_context.cc",
"file_system/isolated_context.h",
"file_system/isolated_file_system_backend.cc",
@@ -224,6 +226,7 @@ component("browser") {
"//base",
"//base:i18n",
"//base/third_party/dynamic_annotations",
+ "//components/services/storage/public/cpp/filesystem",
"//mojo/public/cpp/bindings",
"//net",
"//services/network:network_service",
@@ -275,6 +278,8 @@ source_set("unittests") {
"file_system/copy_or_move_operation_delegate_unittest.cc",
"file_system/dragged_file_util_unittest.cc",
"file_system/external_mount_points_unittest.cc",
+ "file_system/file_stream_reader_test.cc",
+ "file_system/file_stream_reader_test.h",
"file_system/file_stream_test_utils.cc",
"file_system/file_stream_test_utils.h",
"file_system/file_system_context_unittest.cc",
@@ -285,6 +290,7 @@ source_set("unittests") {
"file_system/file_system_url_unittest.cc",
"file_system/file_system_usage_cache_unittest.cc",
"file_system/file_writer_delegate_unittest.cc",
+ "file_system/filesystem_proxy_file_stream_reader_unittest.cc",
"file_system/isolated_context_unittest.cc",
"file_system/local_file_stream_reader_unittest.cc",
"file_system/local_file_stream_writer_unittest.cc",
@@ -318,6 +324,7 @@ source_set("unittests") {
":test_support",
"//base/test:test_support",
"//components/services/filesystem/public/mojom",
+ "//components/services/storage/public/cpp/filesystem",
"//mojo/public/cpp/system",
"//net:test_support",
"//services/network/public/cpp",
diff --git a/chromium/storage/browser/blob/blob_builder_from_stream_unittest.cc b/chromium/storage/browser/blob/blob_builder_from_stream_unittest.cc
index 184f335c802..3c27c863187 100644
--- a/chromium/storage/browser/blob/blob_builder_from_stream_unittest.cc
+++ b/chromium/storage/browser/blob/blob_builder_from_stream_unittest.cc
@@ -416,8 +416,7 @@ TEST_P(BlobBuilderFromStreamTest, ProgressEvents) {
mojo::AssociatedRemote<blink::mojom::ProgressClient> progress_client_remote;
mojo::AssociatedReceiver<blink::mojom::ProgressClient> progress_receiver(
&progress_client,
- progress_client_remote
- .BindNewEndpointAndPassDedicatedReceiverForTesting());
+ progress_client_remote.BindNewEndpointAndPassDedicatedReceiver());
mojo::DataPipe pipe;
base::RunLoop loop;
diff --git a/chromium/storage/browser/blob/blob_data_builder.cc b/chromium/storage/browser/blob/blob_data_builder.cc
index a429d7b8bc2..9414959e882 100644
--- a/chromium/storage/browser/blob/blob_data_builder.cc
+++ b/chromium/storage/browser/blob/blob_data_builder.cc
@@ -321,7 +321,7 @@ void BlobDataBuilder::AppendBlob(const std::string& uuid,
}
void BlobDataBuilder::AppendFileSystemFile(
- const GURL& url,
+ const FileSystemURL& url,
uint64_t offset,
uint64_t length,
const base::Time& expected_modification_time,
diff --git a/chromium/storage/browser/blob/blob_data_builder.h b/chromium/storage/browser/blob/blob_data_builder.h
index a40f4ef4854..a4ad251e5ca 100644
--- a/chromium/storage/browser/blob/blob_data_builder.h
+++ b/chromium/storage/browser/blob/blob_data_builder.h
@@ -28,6 +28,7 @@ namespace storage {
class BlobSliceTest;
class BlobStorageContext;
class BlobStorageRegistry;
+class FileSystemURL;
// This class is used to build blobs. It also facilitates the operation of
// 'pending' data, where the user knows the size and existence of a file or
@@ -136,7 +137,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobDataBuilder {
const BlobStorageRegistry& blob_registry);
void AppendFileSystemFile(
- const GURL& url,
+ const FileSystemURL& url,
uint64_t offset,
uint64_t length,
const base::Time& expected_modification_time,
diff --git a/chromium/storage/browser/blob/blob_data_item.cc b/chromium/storage/browser/blob/blob_data_item.cc
index f5e06824930..ef05067a1ad 100644
--- a/chromium/storage/browser/blob/blob_data_item.cc
+++ b/chromium/storage/browser/blob/blob_data_item.cc
@@ -116,7 +116,7 @@ scoped_refptr<BlobDataItem> BlobDataItem::CreateFutureFile(uint64_t offset,
// static
scoped_refptr<BlobDataItem> BlobDataItem::CreateFileFilesystem(
- const GURL& url,
+ const FileSystemURL& url,
uint64_t offset,
uint64_t length,
base::Time expected_modification_time,
@@ -193,6 +193,7 @@ void BlobDataItem::ShrinkBytes(size_t new_length) {
DCHECK_EQ(type_, Type::kBytes);
length_ = new_length;
bytes_.resize(length_);
+ bytes_.shrink_to_fit();
}
void BlobDataItem::PopulateFile(
@@ -251,7 +252,7 @@ void PrintTo(const BlobDataItem& x, ::std::ostream* os) {
<< ", expected_modification_time: " << x.expected_modification_time();
break;
case BlobDataItem::Type::kFileFilesystem:
- *os << "kFileFilesystem, url: " << x.filesystem_url();
+ *os << "kFileFilesystem, url: " << x.filesystem_url().DebugString();
break;
case BlobDataItem::Type::kReadableDataHandle:
*os << "kReadableDataHandle"
diff --git a/chromium/storage/browser/blob/blob_data_item.h b/chromium/storage/browser/blob/blob_data_item.h
index d40d1edf6c1..aa681aceb61 100644
--- a/chromium/storage/browser/blob/blob_data_item.h
+++ b/chromium/storage/browser/blob/blob_data_item.h
@@ -18,6 +18,7 @@
#include "components/services/storage/public/mojom/blob_storage_context.mojom.h"
#include "net/base/io_buffer.h"
#include "storage/browser/blob/shareable_file_reference.h"
+#include "storage/browser/file_system/file_system_url.h"
#include "url/gurl.h"
namespace storage {
@@ -92,7 +93,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobDataItem
uint64_t length,
uint64_t file_id);
static scoped_refptr<BlobDataItem> CreateFileFilesystem(
- const GURL& url,
+ const FileSystemURL& url,
uint64_t offset,
uint64_t length,
base::Time expected_modification_time,
@@ -118,7 +119,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobDataItem
return path_;
}
- const GURL& filesystem_url() const {
+ const FileSystemURL& filesystem_url() const {
DCHECK_EQ(type_, Type::kFileFilesystem);
return filesystem_url_;
}
@@ -182,9 +183,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobDataItem
uint64_t offset_;
uint64_t length_;
- std::vector<uint8_t> bytes_; // For Type::kBytes.
- base::FilePath path_; // For Type::kFile.
- GURL filesystem_url_; // For Type::kFileFilesystem.
+ std::vector<uint8_t> bytes_; // For Type::kBytes.
+ base::FilePath path_; // For Type::kFile.
+ FileSystemURL filesystem_url_; // For Type::kFileFilesystem.
base::Time
expected_modification_time_; // For Type::kFile and kFileFilesystem.
diff --git a/chromium/storage/browser/blob/blob_reader.cc b/chromium/storage/browser/blob/blob_reader.cc
index 8bed5a695b5..40e5c49b919 100644
--- a/chromium/storage/browser/blob/blob_reader.cc
+++ b/chromium/storage/browser/blob/blob_reader.cc
@@ -726,14 +726,12 @@ std::unique_ptr<FileStreamReader> BlobReader::CreateFileStreamReader(
: item.length() - additional_offset;
if (file_stream_provider_for_testing_) {
return file_stream_provider_for_testing_->CreateFileStreamReader(
- item.filesystem_url(), item.offset() + additional_offset,
+ item.filesystem_url().ToGURL(), item.offset() + additional_offset,
max_bytes_to_read, item.expected_modification_time());
}
return item.file_system_context()->CreateFileStreamReader(
- FileSystemURL(
- item.file_system_context()->CrackURL(item.filesystem_url())),
- item.offset() + additional_offset, max_bytes_to_read,
- item.expected_modification_time());
+ item.filesystem_url(), item.offset() + additional_offset,
+ max_bytes_to_read, item.expected_modification_time());
}
case BlobDataItem::Type::kBytes:
case BlobDataItem::Type::kBytesDescription:
diff --git a/chromium/storage/browser/blob/blob_reader_unittest.cc b/chromium/storage/browser/blob/blob_reader_unittest.cc
index 51b85c71632..bdba18feb7e 100644
--- a/chromium/storage/browser/blob/blob_reader_unittest.cc
+++ b/chromium/storage/browser/blob/blob_reader_unittest.cc
@@ -206,6 +206,11 @@ class BlobReaderTest : public ::testing::Test {
BlobReaderTest() = default;
~BlobReaderTest() override = default;
+ void SetUp() override {
+ file_system_context_ =
+ CreateFileSystemContextForTesting(nullptr, base::FilePath());
+ }
+
void TearDown() override {
reader_.reset();
blob_handle_.reset();
@@ -280,6 +285,7 @@ class BlobReaderTest : public ::testing::Test {
std::unique_ptr<BlobDataHandle> blob_handle_;
MockFileStreamReaderProvider* provider_ = nullptr;
std::unique_ptr<BlobReader> reader_;
+ scoped_refptr<FileSystemContext> file_system_context_;
private:
DISALLOW_COPY_AND_ASSIGN(BlobReaderTest);
@@ -347,10 +353,11 @@ TEST_F(BlobReaderTest, BasicFile) {
TEST_F(BlobReaderTest, BasicFileSystem) {
auto b = std::make_unique<BlobDataBuilder>("uuid");
- const GURL kURL("file://test_file/here.txt");
+ const GURL kURL("filesystem:http://example.com/temporary/test_file/here.txt");
const std::string kData = "FileData!!!";
const base::Time kTime = base::Time::Now();
- b->AppendFileSystemFile(kURL, 0, kData.size(), kTime, nullptr);
+ b->AppendFileSystemFile(file_system_context_->CrackURL(kURL), 0, kData.size(),
+ kTime, file_system_context_);
this->InitializeReader(std::move(b));
// Non-async reader.
ExpectFileSystemCall(kURL, 0, kData.size(), kTime,
@@ -609,10 +616,11 @@ TEST_F(BlobReaderTest, FileAsync) {
TEST_F(BlobReaderTest, FileSystemAsync) {
auto b = std::make_unique<BlobDataBuilder>("uuid");
- const GURL kURL("file://test_file/here.txt");
+ const GURL kURL("filesystem:http://example.com/temporary/test_file/here.txt");
const std::string kData = "FileData!!!";
const base::Time kTime = base::Time::Now();
- b->AppendFileSystemFile(kURL, 0, kData.size(), kTime, nullptr);
+ b->AppendFileSystemFile(file_system_context_->CrackURL(kURL), 0, kData.size(),
+ kTime, file_system_context_);
this->InitializeReader(std::move(b));
std::unique_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(kData));
diff --git a/chromium/storage/browser/blob/blob_registry_impl.cc b/chromium/storage/browser/blob/blob_registry_impl.cc
index 1902cca8345..34e736e80de 100644
--- a/chromium/storage/browser/blob/blob_registry_impl.cc
+++ b/chromium/storage/browser/blob/blob_registry_impl.cc
@@ -30,20 +30,43 @@ BlobRegistryImpl::URLStoreCreationHook* g_url_store_creation_hook = nullptr;
class BlobRegistryImpl::BlobUnderConstruction {
public:
+ // Holds onto a blink::mojom::DataElement struct and optionally a bound
+ // mojo::Remote<blink::mojom::BytesProvider> or
+ // mojo::Remote<blink::mojom::Blob>, if the element encapsulates a large byte
+ // array or a blob.
+ struct ElementEntry {
+ explicit ElementEntry(blink::mojom::DataElementPtr e)
+ : element(std::move(e)) {
+ if (element && element->is_bytes())
+ bytes_provider.Bind(std::move(element->get_bytes()->data));
+ else if (element && element->is_blob())
+ blob.Bind(std::move(element->get_blob()->blob));
+ }
+
+ ElementEntry(ElementEntry&& other) = default;
+ ~ElementEntry() = default;
+
+ ElementEntry& operator=(ElementEntry&& other) = default;
+
+ blink::mojom::DataElementPtr element;
+ FileSystemURL filesystem_url;
+ mojo::Remote<blink::mojom::BytesProvider> bytes_provider;
+ mojo::Remote<blink::mojom::Blob> blob;
+ };
+
BlobUnderConstruction(BlobRegistryImpl* blob_registry,
const std::string& uuid,
const std::string& content_type,
const std::string& content_disposition,
- std::vector<blink::mojom::DataElementPtr> elements,
+ std::vector<ElementEntry> elements,
mojo::ReportBadMessageCallback bad_message_callback)
: blob_registry_(blob_registry),
uuid_(uuid),
builder_(std::make_unique<BlobDataBuilder>(uuid)),
+ elements_(std::move(elements)),
bad_message_callback_(std::move(bad_message_callback)) {
builder_->set_content_type(content_type);
builder_->set_content_disposition(content_disposition);
- for (auto& element : elements)
- elements_.emplace_back(std::move(element));
}
// Call this after constructing to kick of fetching of UUIDs of blobs
@@ -57,29 +80,6 @@ class BlobRegistryImpl::BlobUnderConstruction {
const std::string& uuid() const { return uuid_; }
private:
- // Holds onto a blink::mojom::DataElement struct and optionally a bound
- // mojo::Remote<blink::mojom::BytesProvider> or
- // mojo::Remote<blink::mojom::Blob>, if the element encapsulates a large byte
- // array or a blob.
- struct ElementEntry {
- explicit ElementEntry(blink::mojom::DataElementPtr e)
- : element(std::move(e)) {
- if (element && element->is_bytes())
- bytes_provider.Bind(std::move(element->get_bytes()->data));
- else if (element && element->is_blob())
- blob.Bind(std::move(element->get_blob()->blob));
- }
-
- ElementEntry(ElementEntry&& other) = default;
- ~ElementEntry() = default;
-
- ElementEntry& operator=(ElementEntry&& other) = default;
-
- blink::mojom::DataElementPtr element;
- mojo::Remote<blink::mojom::BytesProvider> bytes_provider;
- mojo::Remote<blink::mojom::Blob> blob;
- };
-
BlobStorageContext* context() const { return blob_registry_->context_.get(); }
// Marks this blob as broken. If an optional |bad_message_reason| is provided,
@@ -382,9 +382,10 @@ void BlobRegistryImpl::BlobUnderConstruction::ResolvedAllBlobDependencies() {
f->path, f->offset, f->length,
f->expected_modification_time.value_or(base::Time()));
} else if (element->is_file_filesystem()) {
+ DCHECK(entry.filesystem_url.is_valid());
const auto& f = element->get_file_filesystem();
builder_->AppendFileSystemFile(
- f->url, f->offset, f->length,
+ entry.filesystem_url, f->offset, f->length,
f->expected_modification_time.value_or(base::Time()),
blob_registry_->file_system_context_);
} else if (element->is_blob()) {
@@ -533,9 +534,12 @@ void BlobRegistryImpl::Register(
Delegate* delegate = receivers_.current_context().get();
DCHECK(delegate);
- for (const auto& element : elements) {
- if (element->is_file()) {
- if (!delegate->CanReadFile(element->get_file()->path)) {
+ std::vector<BlobUnderConstruction::ElementEntry> element_entries;
+ element_entries.reserve(elements.size());
+ for (auto& element : elements) {
+ BlobUnderConstruction::ElementEntry entry(std::move(element));
+ if (entry.element->is_file()) {
+ if (!delegate->CanReadFile(entry.element->get_file()->path)) {
std::unique_ptr<BlobDataHandle> handle = context_->AddBrokenBlob(
uuid, content_type, content_disposition,
BlobStatus::ERR_REFERENCED_FILE_UNAVAILABLE);
@@ -543,12 +547,13 @@ void BlobRegistryImpl::Register(
std::move(callback).Run();
return;
}
- } else if (element->is_file_filesystem()) {
- FileSystemURL filesystem_url(
- file_system_context_->CrackURL(element->get_file_filesystem()->url));
- if (!filesystem_url.is_valid() ||
- !file_system_context_->GetFileSystemBackend(filesystem_url.type()) ||
- !delegate->CanReadFileSystemFile(filesystem_url)) {
+ } else if (entry.element->is_file_filesystem()) {
+ entry.filesystem_url = file_system_context_->CrackURL(
+ entry.element->get_file_filesystem()->url);
+ if (!entry.filesystem_url.is_valid() ||
+ !file_system_context_->GetFileSystemBackend(
+ entry.filesystem_url.type()) ||
+ !delegate->CanReadFileSystemFile(entry.filesystem_url)) {
std::unique_ptr<BlobDataHandle> handle = context_->AddBrokenBlob(
uuid, content_type, content_disposition,
BlobStatus::ERR_REFERENCED_FILE_UNAVAILABLE);
@@ -557,10 +562,11 @@ void BlobRegistryImpl::Register(
return;
}
}
+ element_entries.push_back(std::move(entry));
}
blobs_under_construction_[uuid] = std::make_unique<BlobUnderConstruction>(
- this, uuid, content_type, content_disposition, std::move(elements),
+ this, uuid, content_type, content_disposition, std::move(element_entries),
receivers_.GetBadMessageCallback());
std::unique_ptr<BlobDataHandle> handle = context_->AddFutureBlob(
diff --git a/chromium/storage/browser/blob/blob_registry_impl_unittest.cc b/chromium/storage/browser/blob/blob_registry_impl_unittest.cc
index a3207ff6b61..8f076e17c24 100644
--- a/chromium/storage/browser/blob/blob_registry_impl_unittest.cc
+++ b/chromium/storage/browser/blob/blob_registry_impl_unittest.cc
@@ -645,7 +645,9 @@ TEST_F(BlobRegistryImplTest, Register_FileSystemFile_Valid) {
ASSERT_EQ(BlobStatus::DONE, handle->GetBlobStatus());
BlobDataBuilder expected_blob_data(kId);
- expected_blob_data.AppendFileSystemFile(url, 0, 16, base::Time(), nullptr);
+ expected_blob_data.AppendFileSystemFile(file_system_context_->CrackURL(url),
+ 0, 16, base::Time(),
+ file_system_context_);
EXPECT_EQ(expected_blob_data, *handle->CreateSnapshot());
EXPECT_EQ(0u, BlobsUnderConstruction());
diff --git a/chromium/storage/browser/blob/blob_storage_context_unittest.cc b/chromium/storage/browser/blob/blob_storage_context_unittest.cc
index d09810799fc..42e7c34c7bb 100644
--- a/chromium/storage/browser/blob/blob_storage_context_unittest.cc
+++ b/chromium/storage/browser/blob/blob_storage_context_unittest.cc
@@ -32,9 +32,9 @@
#include "storage/browser/blob/blob_data_snapshot.h"
#include "storage/browser/blob/blob_impl.h"
#include "storage/browser/test/fake_blob_data_handle.h"
+#include "storage/browser/test/test_file_system_context.h"
#include "testing/gtest/include/gtest/gtest.h"
-
namespace storage {
namespace {
@@ -80,6 +80,8 @@ class BlobStorageContextTest : public testing::Test {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
base::ThreadRestrictions::SetIOAllowed(false);
context_ = std::make_unique<BlobStorageContext>();
+ file_system_context_ =
+ CreateFileSystemContextForTesting(nullptr, base::FilePath());
}
void TearDown() override {
@@ -138,6 +140,7 @@ class BlobStorageContextTest : public testing::Test {
std::vector<FileCreationInfo> files_;
base::ScopedTempDir temp_dir_;
scoped_refptr<TestSimpleTaskRunner> file_runner_ = new TestSimpleTaskRunner();
+ scoped_refptr<FileSystemContext> file_system_context_;
base::test::SingleThreadTaskEnvironment task_environment_;
std::unique_ptr<BlobStorageContext> context_;
@@ -453,8 +456,8 @@ TEST_F(BlobStorageContextTest, AddFinishedBlob_LargeOffset) {
const std::string kId2("id2");
auto builder1 = std::make_unique<BlobDataBuilder>(kId1);
- builder1->AppendFileSystemFile(GURL(), 0, kLargeSize, base::Time::Now(),
- nullptr);
+ builder1->AppendFileSystemFile(FileSystemURL(), 0, kLargeSize,
+ base::Time::Now(), file_system_context_);
std::unique_ptr<BlobDataHandle> blob_data_handle1 =
context_->AddFinishedBlob(std::move(builder1));
diff --git a/chromium/storage/browser/blob/blob_url_registry.cc b/chromium/storage/browser/blob/blob_url_registry.cc
index ddca7989597..c0cea83e1fc 100644
--- a/chromium/storage/browser/blob/blob_url_registry.cc
+++ b/chromium/storage/browser/blob/blob_url_registry.cc
@@ -10,7 +10,9 @@
namespace storage {
-BlobUrlRegistry::BlobUrlRegistry() = default;
+BlobUrlRegistry::BlobUrlRegistry(base::WeakPtr<BlobUrlRegistry> fallback)
+ : fallback_(std::move(fallback)) {}
+
BlobUrlRegistry::~BlobUrlRegistry() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
@@ -38,7 +40,11 @@ bool BlobUrlRegistry::RemoveUrlMapping(const GURL& blob_url) {
bool BlobUrlRegistry::IsUrlMapped(const GURL& blob_url) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return url_to_blob_.find(blob_url) != url_to_blob_.end();
+ if (url_to_blob_.find(blob_url) != url_to_blob_.end())
+ return true;
+ if (fallback_)
+ return fallback_->IsUrlMapped(blob_url);
+ return false;
}
mojo::PendingRemote<blink::mojom::Blob> BlobUrlRegistry::GetBlobFromUrl(
@@ -46,7 +52,7 @@ mojo::PendingRemote<blink::mojom::Blob> BlobUrlRegistry::GetBlobFromUrl(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto it = url_to_blob_.find(BlobUrlUtils::ClearUrlFragment(url));
if (it == url_to_blob_.end())
- return mojo::NullRemote();
+ return fallback_ ? fallback_->GetBlobFromUrl(url) : mojo::NullRemote();
mojo::Remote<blink::mojom::Blob> blob(std::move(it->second));
mojo::PendingRemote<blink::mojom::Blob> result;
blob->Clone(result.InitWithNewPipeAndPassReceiver());
diff --git a/chromium/storage/browser/blob/blob_url_registry.h b/chromium/storage/browser/blob/blob_url_registry.h
index a3e80fe514d..c74eb3f00c4 100644
--- a/chromium/storage/browser/blob/blob_url_registry.h
+++ b/chromium/storage/browser/blob/blob_url_registry.h
@@ -24,7 +24,7 @@ namespace storage {
// This class stores the mapping of blob Urls to blobs.
class COMPONENT_EXPORT(STORAGE_BROWSER) BlobUrlRegistry {
public:
- BlobUrlRegistry();
+ explicit BlobUrlRegistry(base::WeakPtr<BlobUrlRegistry> fallback = nullptr);
~BlobUrlRegistry();
// Creates a url mapping from blob to the given url. Returns false if
@@ -59,6 +59,12 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobUrlRegistry {
private:
SEQUENCE_CHECKER(sequence_checker_);
+ // Optional fallback BlobUrlRegistry. If lookups for URLs in this registry
+ // fail, they are retried in the fallback registry. This is used to allow
+ // "child" storage partitions to resolve URLs created by their "parent", while
+ // not allowing the reverse.
+ base::WeakPtr<BlobUrlRegistry> fallback_;
+
std::map<GURL, mojo::PendingRemote<blink::mojom::Blob>> url_to_blob_;
std::map<base::UnguessableToken,
std::pair<GURL, mojo::PendingRemote<blink::mojom::Blob>>>
diff --git a/chromium/storage/browser/blob/view_blob_internals_job.cc b/chromium/storage/browser/blob/view_blob_internals_job.cc
index a73d15d6f08..10c7ba69778 100644
--- a/chromium/storage/browser/blob/view_blob_internals_job.cc
+++ b/chromium/storage/browser/blob/view_blob_internals_job.cc
@@ -201,7 +201,7 @@ void ViewBlobInternalsJob::GenerateHTMLForBlobData(
break;
case BlobDataItem::Type::kFileFilesystem:
AddHTMLListItem(kType, "filesystem", out);
- AddHTMLListItem(kURL, item.filesystem_url().spec(), out);
+ AddHTMLListItem(kURL, item.filesystem_url().DebugString(), out);
if (!item.expected_modification_time().is_null()) {
AddHTMLListItem(kModificationTime, base::UTF16ToUTF8(
TimeFormatFriendlyDateAndTime(item.expected_modification_time())),
diff --git a/chromium/storage/browser/blob/write_blob_to_file.cc b/chromium/storage/browser/blob/write_blob_to_file.cc
index 4f270b0878f..b41269b38f8 100644
--- a/chromium/storage/browser/blob/write_blob_to_file.cc
+++ b/chromium/storage/browser/blob/write_blob_to_file.cc
@@ -97,7 +97,8 @@ bool CopyFileContentsWithOffsetAndSize(base::File* infile,
for (;;) {
size_t bytes_to_read =
- std::min(buffer.size(), base::saturated_cast<size_t>(max_size));
+ std::min(buffer.size(),
+ base::checked_cast<size_t>(checked_max_size.ValueOrDie()));
int bytes_read = infile->ReadAtCurrentPos(buffer.data(), bytes_to_read);
if (bytes_read < 0)
return false;
diff --git a/chromium/storage/browser/file_system/file_stream_reader.h b/chromium/storage/browser/file_system/file_stream_reader.h
index d9ac296c94a..4f6e30af5f6 100644
--- a/chromium/storage/browser/file_system/file_stream_reader.h
+++ b/chromium/storage/browser/file_system/file_stream_reader.h
@@ -13,6 +13,7 @@
#include "base/component_export.h"
#include "base/files/file.h"
#include "base/memory/weak_ptr.h"
+#include "components/services/storage/public/cpp/filesystem/filesystem_proxy.h"
#include "net/base/completion_once_callback.h"
namespace base {
@@ -44,8 +45,29 @@ class FileStreamReader {
// ERR_UPLOAD_FILE_CHANGED error.
COMPONENT_EXPORT(STORAGE_BROWSER)
static std::unique_ptr<FileStreamReader> CreateForLocalFile(
- base::TaskRunner* task_runner,
+ scoped_refptr<base::TaskRunner> task_runner,
+ const base::FilePath& file_path,
+ int64_t initial_offset,
+ const base::Time& expected_modification_time);
+
+ // Creates a new FileReader for a local file |file_path|, which is a
+ // relative path into |filesystem_proxy|. This function's behavior
+ // is otherwise identical to CreateForLocalFile other than all file operations
+ // going through |filesystem_proxy|.
+ COMPONENT_EXPORT(STORAGE_BROWSER)
+ static std::unique_ptr<FileStreamReader> CreateForFilesystemProxy(
+ scoped_refptr<base::TaskRunner> task_runner,
+ const base::FilePath& file_path,
+ std::unique_ptr<storage::FilesystemProxy> filesystem_proxy,
+ int64_t initial_offset,
+ const base::Time& expected_modification_time);
+
+ // The same as CreateForFilesystemProxy, but will emit diagnostic metrics.
+ COMPONENT_EXPORT(STORAGE_BROWSER)
+ static std::unique_ptr<FileStreamReader> CreateForIndexedDBDataItemReader(
+ scoped_refptr<base::TaskRunner> task_runner,
const base::FilePath& file_path,
+ std::unique_ptr<storage::FilesystemProxy> filesystem_proxy,
int64_t initial_offset,
const base::Time& expected_modification_time);
diff --git a/chromium/storage/browser/file_system/file_stream_reader_test.cc b/chromium/storage/browser/file_system/file_stream_reader_test.cc
new file mode 100644
index 00000000000..1ce59c61b7e
--- /dev/null
+++ b/chromium/storage/browser/file_system/file_stream_reader_test.cc
@@ -0,0 +1,12 @@
+// Copyright 2020 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 "storage/browser/file_system/file_stream_reader_test.h"
+
+namespace storage {
+
+const base::StringPiece FileStreamReaderTest::kTestFileName;
+const base::StringPiece FileStreamReaderTest::kTestData;
+
+} // namespace storage
diff --git a/chromium/storage/browser/file_system/file_stream_reader_test.h b/chromium/storage/browser/file_system/file_stream_reader_test.h
new file mode 100644
index 00000000000..f82e7cb00dd
--- /dev/null
+++ b/chromium/storage/browser/file_system/file_stream_reader_test.h
@@ -0,0 +1,287 @@
+// Copyright 2020 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 STORAGE_BROWSER_FILE_SYSTEM_FILE_STREAM_READER_TEST_H_
+#define STORAGE_BROWSER_FILE_SYSTEM_FILE_STREAM_READER_TEST_H_
+
+#include "base/bind_helpers.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/single_thread_task_runner.h"
+#include "base/test/task_environment.h"
+#include "base/threading/thread.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/base/test_completion_callback.h"
+#include "storage/browser/file_system/file_stream_reader.h"
+#include "storage/browser/file_system/file_stream_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace storage {
+
+// An interface for derived FileStreamReader to implement.
+// This allows multiple FileStreamReader implementations can share the
+// same test framework. Tests should implement CreateFileReader, WriteFile, and
+// TouchFile to manipulate files for their particular implementation.
+class FileStreamReaderTest : public testing::Test {
+ public:
+ static constexpr base::StringPiece kTestFileName = "test.dat";
+ static constexpr base::StringPiece kTestData = "0123456789";
+
+ virtual std::unique_ptr<FileStreamReader> CreateFileReader(
+ const std::string& file_name,
+ int64_t initial_offset,
+ const base::Time& expected_modification_time) = 0;
+ virtual void WriteFile(const std::string& file_name,
+ const char* buf,
+ size_t buf_size,
+ base::Time* modification_time) = 0;
+ // Adjust a file's last modified time by |delta|.
+ virtual void TouchFile(const std::string& file_name,
+ base::TimeDelta delta) = 0;
+ virtual void EnsureFileTaskFinished() {}
+
+ base::Time test_file_modification_time() const {
+ return test_file_modification_time_;
+ }
+
+ void WriteTestFile() {
+ WriteFile(std::string(kTestFileName), kTestData.data(), kTestData.size(),
+ &test_file_modification_time_);
+ }
+
+ static void NeverCalled(int unused) { ADD_FAILURE(); }
+
+ private:
+ base::test::SingleThreadTaskEnvironment task_environment_{
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
+ base::Time test_file_modification_time_;
+};
+
+template <class SubClass>
+class FileStreamReaderTypedTest : public SubClass {
+ public:
+ void SetUp() override {
+ SubClass::SetUp();
+ this->WriteTestFile();
+ }
+};
+
+TYPED_TEST_SUITE_P(FileStreamReaderTypedTest);
+
+TYPED_TEST_P(FileStreamReaderTypedTest, NonExistent) {
+ const char kFileName[] = "nonexistent";
+ std::unique_ptr<FileStreamReader> reader(
+ this->CreateFileReader(kFileName, 0, base::Time()));
+ int result = 0;
+ std::string data;
+ ReadFromReader(reader.get(), &data, 10, &result);
+ ASSERT_EQ(net::ERR_FILE_NOT_FOUND, result);
+ ASSERT_EQ(0U, data.size());
+}
+
+TYPED_TEST_P(FileStreamReaderTypedTest, Empty) {
+ const char kFileName[] = "empty";
+ this->WriteFile(kFileName, nullptr, 0, nullptr);
+
+ std::unique_ptr<FileStreamReader> reader(
+ this->CreateFileReader(kFileName, 0, base::Time()));
+ int result = 0;
+ std::string data;
+ ReadFromReader(reader.get(), &data, 10, &result);
+ ASSERT_EQ(net::OK, result);
+ ASSERT_EQ(0U, data.size());
+
+ net::TestInt64CompletionCallback callback;
+ int64_t length_result = reader->GetLength(callback.callback());
+ if (length_result == net::ERR_IO_PENDING)
+ length_result = callback.WaitForResult();
+ ASSERT_EQ(0, length_result);
+}
+
+TYPED_TEST_P(FileStreamReaderTypedTest, GetLengthNormal) {
+ std::unique_ptr<FileStreamReader> reader(
+ this->CreateFileReader(std::string(this->kTestFileName), 0,
+ this->test_file_modification_time()));
+ net::TestInt64CompletionCallback callback;
+ int64_t result = reader->GetLength(callback.callback());
+ if (result == net::ERR_IO_PENDING)
+ result = callback.WaitForResult();
+ ASSERT_EQ(static_cast<int64_t>(this->kTestData.size()), result);
+}
+
+TYPED_TEST_P(FileStreamReaderTypedTest, GetLengthAfterModified) {
+ this->TouchFile(std::string(this->kTestFileName),
+ base::TimeDelta::FromSeconds(10));
+
+ std::unique_ptr<FileStreamReader> reader(
+ this->CreateFileReader(std::string(this->kTestFileName), 0,
+ this->test_file_modification_time()));
+ net::TestInt64CompletionCallback callback1;
+ int64_t result = reader->GetLength(callback1.callback());
+ if (result == net::ERR_IO_PENDING)
+ result = callback1.WaitForResult();
+ ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result);
+
+ // With nullptr expected modification time this should work.
+ reader =
+ this->CreateFileReader(std::string(this->kTestFileName), 0, base::Time());
+ net::TestInt64CompletionCallback callback2;
+ result = reader->GetLength(callback2.callback());
+ if (result == net::ERR_IO_PENDING)
+ result = callback2.WaitForResult();
+ ASSERT_EQ(static_cast<int64_t>(this->kTestData.size()), result);
+}
+
+TYPED_TEST_P(FileStreamReaderTypedTest, GetLengthWithOffset) {
+ std::unique_ptr<FileStreamReader> reader(this->CreateFileReader(
+ std::string(this->kTestFileName), 3, base::Time()));
+ net::TestInt64CompletionCallback callback;
+ int64_t result = reader->GetLength(callback.callback());
+ if (result == net::ERR_IO_PENDING)
+ result = callback.WaitForResult();
+ // Initial offset does not affect the result of GetLength.
+ ASSERT_EQ(static_cast<int64_t>(this->kTestData.size()), result);
+}
+
+TYPED_TEST_P(FileStreamReaderTypedTest, ReadNormal) {
+ std::unique_ptr<FileStreamReader> reader(
+ this->CreateFileReader(std::string(this->kTestFileName), 0,
+ this->test_file_modification_time()));
+ int result = 0;
+ std::string data;
+ ReadFromReader(reader.get(), &data, this->kTestData.size(), &result);
+ ASSERT_EQ(net::OK, result);
+ ASSERT_EQ(this->kTestData, data);
+}
+
+TYPED_TEST_P(FileStreamReaderTypedTest, ReadAfterModified) {
+ // Touch file so that the file's modification time becomes different
+ // from what we expect. Note that the resolution on some filesystems
+ // is 1s so we can't test with deltas less than that.
+ this->TouchFile(std::string(this->kTestFileName),
+ base::TimeDelta::FromSeconds(-1));
+
+ std::unique_ptr<FileStreamReader> reader(
+ this->CreateFileReader(std::string(this->kTestFileName), 0,
+ this->test_file_modification_time()));
+ int result = 0;
+ std::string data;
+ ReadFromReader(reader.get(), &data, this->kTestData.size(), &result);
+ ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result);
+ ASSERT_EQ(0U, data.size());
+}
+
+TYPED_TEST_P(FileStreamReaderTypedTest, ReadAfterModifiedLessThanThreshold) {
+ // Due to precision loss converting int64_t->double->int64_t (e.g. through
+ // Blink) the expected/actual time may vary by microseconds. With
+ // modification time delta < 10us this should work.
+ this->TouchFile(std::string(this->kTestFileName),
+ base::TimeDelta::FromMicroseconds(1));
+ std::unique_ptr<FileStreamReader> reader(
+ this->CreateFileReader(std::string(this->kTestFileName), 0,
+ this->test_file_modification_time()));
+ int result = 0;
+ std::string data;
+
+ ReadFromReader(reader.get(), &data, this->kTestData.size(), &result);
+ ASSERT_EQ(net::OK, result);
+ ASSERT_EQ(this->kTestData, data);
+}
+
+TYPED_TEST_P(FileStreamReaderTypedTest, ReadAfterModifiedWithMatchingTimes) {
+ this->TouchFile(std::string(this->kTestFileName), base::TimeDelta());
+ std::unique_ptr<FileStreamReader> reader(
+ this->CreateFileReader(std::string(this->kTestFileName), 0,
+ this->test_file_modification_time()));
+ int result = 0;
+ std::string data;
+
+ ReadFromReader(reader.get(), &data, this->kTestData.size(), &result);
+ ASSERT_EQ(net::OK, result);
+ ASSERT_EQ(this->kTestData, data);
+}
+
+TYPED_TEST_P(FileStreamReaderTypedTest, ReadAfterModifiedWithoutExpectedTime) {
+ this->TouchFile(std::string(this->kTestFileName),
+ base::TimeDelta::FromSeconds(-1));
+ std::unique_ptr<FileStreamReader> reader(this->CreateFileReader(
+ std::string(this->kTestFileName), 0, base::Time()));
+ int result = 0;
+ std::string data;
+
+ ReadFromReader(reader.get(), &data, this->kTestData.size(), &result);
+ ASSERT_EQ(net::OK, result);
+ ASSERT_EQ(this->kTestData, data);
+}
+
+TYPED_TEST_P(FileStreamReaderTypedTest, ReadWithOffset) {
+ std::unique_ptr<FileStreamReader> reader(this->CreateFileReader(
+ std::string(this->kTestFileName), 3, base::Time()));
+ int result = 0;
+ std::string data;
+ ReadFromReader(reader.get(), &data, this->kTestData.size(), &result);
+ ASSERT_EQ(net::OK, result);
+
+ ASSERT_EQ(this->kTestData.substr(3), data);
+}
+
+TYPED_TEST_P(FileStreamReaderTypedTest, ReadWithNegativeOffset) {
+ std::unique_ptr<FileStreamReader> reader(this->CreateFileReader(
+ std::string(this->kTestFileName), -1, base::Time()));
+ int result = 0;
+ std::string data;
+ ReadFromReader(reader.get(), &data, 1, &result);
+ ASSERT_EQ(net::ERR_INVALID_ARGUMENT, result);
+ ASSERT_EQ(data.size(), 0u);
+}
+
+TYPED_TEST_P(FileStreamReaderTypedTest, ReadWithOffsetLargerThanFile) {
+ std::unique_ptr<FileStreamReader> reader(
+ this->CreateFileReader(std::string(this->kTestFileName),
+ this->kTestData.size() + 1, base::Time()));
+ int result = 0;
+ std::string data;
+ ReadFromReader(reader.get(), &data, 1, &result);
+ ASSERT_EQ(data.size(), 0u);
+ ASSERT_EQ(net::OK, result);
+}
+
+TYPED_TEST_P(FileStreamReaderTypedTest, DeleteWithUnfinishedRead) {
+ std::unique_ptr<FileStreamReader> reader(this->CreateFileReader(
+ std::string(this->kTestFileName), 0, base::Time()));
+
+ net::TestCompletionCallback callback;
+ scoped_refptr<net::IOBufferWithSize> buf =
+ base::MakeRefCounted<net::IOBufferWithSize>(this->kTestData.size());
+ int rv = reader->Read(buf.get(), buf->size(),
+ base::BindOnce(&FileStreamReaderTest::NeverCalled));
+ if (rv < 0)
+ ASSERT_EQ(rv, net::ERR_IO_PENDING);
+
+ // Delete immediately.
+ // Should not crash; nor should NeverCalled be callback.
+ reader = nullptr;
+ this->EnsureFileTaskFinished();
+}
+
+REGISTER_TYPED_TEST_SUITE_P(FileStreamReaderTypedTest,
+ NonExistent,
+ Empty,
+ GetLengthNormal,
+ GetLengthAfterModified,
+ GetLengthWithOffset,
+ ReadNormal,
+ ReadAfterModified,
+ ReadAfterModifiedLessThanThreshold,
+ ReadAfterModifiedWithMatchingTimes,
+ ReadAfterModifiedWithoutExpectedTime,
+ ReadWithOffset,
+ ReadWithNegativeOffset,
+ ReadWithOffsetLargerThanFile,
+ DeleteWithUnfinishedRead);
+
+} // namespace storage
+
+#endif // STORAGE_BROWSER_FILE_SYSTEM_FILE_STREAM_READER_TEST_H_
diff --git a/chromium/storage/browser/file_system/file_system_file_stream_reader_unittest.cc b/chromium/storage/browser/file_system/file_system_file_stream_reader_unittest.cc
index dc5f5999969..9dbc6661796 100644
--- a/chromium/storage/browser/file_system/file_system_file_stream_reader_unittest.cc
+++ b/chromium/storage/browser/file_system/file_system_file_stream_reader_unittest.cc
@@ -21,6 +21,8 @@
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "storage/browser/file_system/external_mount_points.h"
+
+#include "storage/browser/file_system/file_stream_reader_test.h"
#include "storage/browser/file_system/file_stream_test_utils.h"
#include "storage/browser/file_system/file_system_context.h"
#include "storage/browser/file_system/file_system_file_util.h"
@@ -33,58 +35,44 @@
namespace storage {
namespace {
-
const char kURLOrigin[] = "http://remote/";
-const char kTestFileName[] = "test.dat";
-const char kTestData[] = "0123456789";
-const int kTestDataSize = base::size(kTestData) - 1;
-
-void NeverCalled(int unused) {
- ADD_FAILURE();
-}
-
} // namespace
-class FileSystemFileStreamReaderTest : public testing::Test {
+class FileSystemFileStreamReaderTest : public FileStreamReaderTest {
public:
FileSystemFileStreamReaderTest() = default;
void SetUp() override {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ ASSERT_TRUE(dir_.CreateUniqueTempDir());
file_system_context_ =
- CreateFileSystemContextForTesting(nullptr, temp_dir_.GetPath());
+ CreateFileSystemContextForTesting(nullptr, dir_.GetPath());
- file_system_context_->OpenFileSystem(url::Origin::Create(GURL(kURLOrigin)),
- kFileSystemTypeTemporary,
- OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
- base::BindOnce(&OnOpenFileSystem));
+ file_system_context_->OpenFileSystem(
+ url::Origin::Create(GURL(kURLOrigin)), kFileSystemTypeTemporary,
+ OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::BindOnce([](const GURL& root_url, const std::string& name,
+ base::File::Error result) {
+ ASSERT_EQ(base::File::FILE_OK, result);
+ }));
base::RunLoop().RunUntilIdle();
-
- WriteFile(kTestFileName, kTestData, kTestDataSize,
- &test_file_modification_time_);
}
void TearDown() override { base::RunLoop().RunUntilIdle(); }
- protected:
- FileSystemFileStreamReader* CreateFileReader(
+ std::unique_ptr<FileStreamReader> CreateFileReader(
const std::string& file_name,
int64_t initial_offset,
- const base::Time& expected_modification_time) {
- return new FileSystemFileStreamReader(
+ const base::Time& expected_modification_time) override {
+ return FileStreamReader::CreateForFileSystemFile(
file_system_context_.get(), GetFileSystemURL(file_name), initial_offset,
expected_modification_time);
}
- base::Time test_file_modification_time() const {
- return test_file_modification_time_;
- }
-
void WriteFile(const std::string& file_name,
const char* buf,
- int buf_size,
- base::Time* modification_time) {
+ size_t buf_size,
+ base::Time* modification_time) override {
FileSystemURL url = GetFileSystemURL(file_name);
ASSERT_EQ(base::File::FILE_OK,
@@ -99,11 +87,17 @@ class FileSystemFileStreamReaderTest : public testing::Test {
*modification_time = file_info.last_modified;
}
- private:
- static void OnOpenFileSystem(const GURL& root_url,
- const std::string& name,
- base::File::Error result) {
- ASSERT_EQ(base::File::FILE_OK, result);
+ void TouchFile(const std::string& file_name, base::TimeDelta delta) override {
+ FileSystemURL url = GetFileSystemURL(file_name);
+
+ base::File::Info file_info;
+ ASSERT_EQ(base::File::FILE_OK,
+ AsyncFileTestHelper::GetMetadata(file_system_context_.get(), url,
+ &file_info));
+ ASSERT_EQ(base::File::FILE_OK,
+ AsyncFileTestHelper::TouchFile(file_system_context_.get(), url,
+ file_info.last_accessed,
+ file_info.last_modified + delta));
}
FileSystemURL GetFileSystemURL(const std::string& file_name) {
@@ -112,140 +106,13 @@ class FileSystemFileStreamReaderTest : public testing::Test {
base::FilePath().AppendASCII(file_name));
}
- base::test::SingleThreadTaskEnvironment task_environment_{
- base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
- base::ScopedTempDir temp_dir_;
+ private:
+ base::ScopedTempDir dir_;
scoped_refptr<FileSystemContext> file_system_context_;
- base::Time test_file_modification_time_;
};
-TEST_F(FileSystemFileStreamReaderTest, NonExistent) {
- const char kFileName[] = "nonexistent";
- std::unique_ptr<FileSystemFileStreamReader> reader(
- CreateFileReader(kFileName, 0, base::Time()));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, 10, &result);
- ASSERT_EQ(net::ERR_FILE_NOT_FOUND, result);
- ASSERT_EQ(0U, data.size());
-}
-
-TEST_F(FileSystemFileStreamReaderTest, Empty) {
- const char kFileName[] = "empty";
- WriteFile(kFileName, nullptr, 0, nullptr);
-
- std::unique_ptr<FileSystemFileStreamReader> reader(
- CreateFileReader(kFileName, 0, base::Time()));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, 10, &result);
- ASSERT_EQ(net::OK, result);
- ASSERT_EQ(0U, data.size());
-
- net::TestInt64CompletionCallback callback;
- int64_t length_result = reader->GetLength(callback.callback());
- if (length_result == net::ERR_IO_PENDING)
- length_result = callback.WaitForResult();
- ASSERT_EQ(0, length_result);
-}
-
-TEST_F(FileSystemFileStreamReaderTest, GetLengthNormal) {
- std::unique_ptr<FileSystemFileStreamReader> reader(
- CreateFileReader(kTestFileName, 0, test_file_modification_time()));
- net::TestInt64CompletionCallback callback;
- int64_t result = reader->GetLength(callback.callback());
- if (result == net::ERR_IO_PENDING)
- result = callback.WaitForResult();
- ASSERT_EQ(kTestDataSize, result);
-}
-
-TEST_F(FileSystemFileStreamReaderTest, GetLengthAfterModified) {
- // Pass a fake expected modifictaion time so that the expectation fails.
- base::Time fake_expected_modification_time =
- test_file_modification_time() - base::TimeDelta::FromSeconds(10);
-
- std::unique_ptr<FileSystemFileStreamReader> reader(
- CreateFileReader(kTestFileName, 0, fake_expected_modification_time));
- net::TestInt64CompletionCallback callback1;
- int64_t result = reader->GetLength(callback1.callback());
- if (result == net::ERR_IO_PENDING)
- result = callback1.WaitForResult();
- ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result);
-
- // With nullptr expected modification time this should work.
- reader.reset(CreateFileReader(kTestFileName, 0, base::Time()));
- net::TestInt64CompletionCallback callback2;
- result = reader->GetLength(callback2.callback());
- if (result == net::ERR_IO_PENDING)
- result = callback2.WaitForResult();
- ASSERT_EQ(kTestDataSize, result);
-}
-
-TEST_F(FileSystemFileStreamReaderTest, GetLengthWithOffset) {
- std::unique_ptr<FileSystemFileStreamReader> reader(
- CreateFileReader(kTestFileName, 3, base::Time()));
- net::TestInt64CompletionCallback callback;
- int64_t result = reader->GetLength(callback.callback());
- if (result == net::ERR_IO_PENDING)
- result = callback.WaitForResult();
- // Initial offset does not affect the result of GetLength.
- ASSERT_EQ(kTestDataSize, result);
-}
-
-TEST_F(FileSystemFileStreamReaderTest, ReadNormal) {
- std::unique_ptr<FileSystemFileStreamReader> reader(
- CreateFileReader(kTestFileName, 0, test_file_modification_time()));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, kTestDataSize, &result);
- ASSERT_EQ(net::OK, result);
- ASSERT_EQ(kTestData, data);
-}
-
-TEST_F(FileSystemFileStreamReaderTest, ReadAfterModified) {
- // Pass a fake expected modifictaion time so that the expectation fails.
- base::Time fake_expected_modification_time =
- test_file_modification_time() - base::TimeDelta::FromSeconds(10);
-
- std::unique_ptr<FileSystemFileStreamReader> reader(
- CreateFileReader(kTestFileName, 0, fake_expected_modification_time));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, kTestDataSize, &result);
- ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result);
- ASSERT_EQ(0U, data.size());
-
- // With nullptr expected modification time this should work.
- data.clear();
- reader.reset(CreateFileReader(kTestFileName, 0, base::Time()));
- ReadFromReader(reader.get(), &data, kTestDataSize, &result);
- ASSERT_EQ(net::OK, result);
- ASSERT_EQ(kTestData, data);
-}
-
-TEST_F(FileSystemFileStreamReaderTest, ReadWithOffset) {
- std::unique_ptr<FileSystemFileStreamReader> reader(
- CreateFileReader(kTestFileName, 3, base::Time()));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, kTestDataSize, &result);
- ASSERT_EQ(net::OK, result);
- ASSERT_EQ(&kTestData[3], data);
-}
-
-TEST_F(FileSystemFileStreamReaderTest, DeleteWithUnfinishedRead) {
- std::unique_ptr<FileSystemFileStreamReader> reader(
- CreateFileReader(kTestFileName, 0, base::Time()));
-
- net::TestCompletionCallback callback;
- scoped_refptr<net::IOBufferWithSize> buf =
- base::MakeRefCounted<net::IOBufferWithSize>(kTestDataSize);
- int rv = reader->Read(buf.get(), buf->size(), base::BindOnce(&NeverCalled));
- ASSERT_TRUE(rv == net::ERR_IO_PENDING || rv >= 0);
-
- // Delete immediately.
- // Should not crash; nor should NeverCalled be callback.
- reader.reset();
-}
+INSTANTIATE_TYPED_TEST_SUITE_P(FileSystem,
+ FileStreamReaderTypedTest,
+ FileSystemFileStreamReaderTest);
} // namespace storage
diff --git a/chromium/storage/browser/file_system/file_system_quota_client_unittest.cc b/chromium/storage/browser/file_system/file_system_quota_client_unittest.cc
index 51ffd3e3e57..dcba590fb00 100644
--- a/chromium/storage/browser/file_system/file_system_quota_client_unittest.cc
+++ b/chromium/storage/browser/file_system/file_system_quota_client_unittest.cc
@@ -248,7 +248,7 @@ TEST_F(FileSystemQuotaClientTest, NoFileSystemTest) {
TEST_F(FileSystemQuotaClientTest, NoFileTest) {
auto quota_client = NewQuotaClient();
const TestFile kFiles[] = {
- {true, nullptr, 0, kDummyURL1, kTemporary},
+ {true, "", 0, kDummyURL1, kTemporary},
};
InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles));
@@ -260,7 +260,7 @@ TEST_F(FileSystemQuotaClientTest, NoFileTest) {
TEST_F(FileSystemQuotaClientTest, OneFileTest) {
auto quota_client = NewQuotaClient();
const TestFile kFiles[] = {
- {true, nullptr, 0, kDummyURL1, kTemporary},
+ {true, "", 0, kDummyURL1, kTemporary},
{false, "foo", 4921, kDummyURL1, kTemporary},
};
InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles));
@@ -276,7 +276,7 @@ TEST_F(FileSystemQuotaClientTest, OneFileTest) {
TEST_F(FileSystemQuotaClientTest, TwoFilesTest) {
auto quota_client = NewQuotaClient();
const TestFile kFiles[] = {
- {true, nullptr, 0, kDummyURL1, kTemporary},
+ {true, "", 0, kDummyURL1, kTemporary},
{false, "foo", 10310, kDummyURL1, kTemporary},
{false, "bar", 41, kDummyURL1, kTemporary},
};
@@ -293,7 +293,7 @@ TEST_F(FileSystemQuotaClientTest, TwoFilesTest) {
TEST_F(FileSystemQuotaClientTest, EmptyFilesTest) {
auto quota_client = NewQuotaClient();
const TestFile kFiles[] = {
- {true, nullptr, 0, kDummyURL1, kTemporary},
+ {true, "", 0, kDummyURL1, kTemporary},
{false, "foo", 0, kDummyURL1, kTemporary},
{false, "bar", 0, kDummyURL1, kTemporary},
{false, "baz", 0, kDummyURL1, kTemporary},
@@ -311,7 +311,7 @@ TEST_F(FileSystemQuotaClientTest, EmptyFilesTest) {
TEST_F(FileSystemQuotaClientTest, SubDirectoryTest) {
auto quota_client = NewQuotaClient();
const TestFile kFiles[] = {
- {true, nullptr, 0, kDummyURL1, kTemporary},
+ {true, "", 0, kDummyURL1, kTemporary},
{true, "dirtest", 0, kDummyURL1, kTemporary},
{false, "dirtest/foo", 11921, kDummyURL1, kTemporary},
{false, "bar", 4814, kDummyURL1, kTemporary},
@@ -329,11 +329,11 @@ TEST_F(FileSystemQuotaClientTest, SubDirectoryTest) {
TEST_F(FileSystemQuotaClientTest, MultiTypeTest) {
auto quota_client = NewQuotaClient();
const TestFile kFiles[] = {
- {true, nullptr, 0, kDummyURL1, kTemporary},
+ {true, "", 0, kDummyURL1, kTemporary},
{true, "dirtest", 0, kDummyURL1, kTemporary},
{false, "dirtest/foo", 133, kDummyURL1, kTemporary},
{false, "bar", 14, kDummyURL1, kTemporary},
- {true, nullptr, 0, kDummyURL1, kPersistent},
+ {true, "", 0, kDummyURL1, kPersistent},
{true, "dirtest", 0, kDummyURL1, kPersistent},
{false, "dirtest/foo", 193, kDummyURL1, kPersistent},
{false, "bar", 9, kDummyURL1, kPersistent},
@@ -357,19 +357,19 @@ TEST_F(FileSystemQuotaClientTest, MultiTypeTest) {
TEST_F(FileSystemQuotaClientTest, MultiDomainTest) {
auto quota_client = NewQuotaClient();
const TestFile kFiles[] = {
- {true, nullptr, 0, kDummyURL1, kTemporary},
+ {true, "", 0, kDummyURL1, kTemporary},
{true, "dir1", 0, kDummyURL1, kTemporary},
{false, "dir1/foo", 1331, kDummyURL1, kTemporary},
{false, "bar", 134, kDummyURL1, kTemporary},
- {true, nullptr, 0, kDummyURL1, kPersistent},
+ {true, "", 0, kDummyURL1, kPersistent},
{true, "dir2", 0, kDummyURL1, kPersistent},
{false, "dir2/foo", 1903, kDummyURL1, kPersistent},
{false, "bar", 19, kDummyURL1, kPersistent},
- {true, nullptr, 0, kDummyURL2, kTemporary},
+ {true, "", 0, kDummyURL2, kTemporary},
{true, "dom", 0, kDummyURL2, kTemporary},
{false, "dom/fan", 1319, kDummyURL2, kTemporary},
{false, "bar", 113, kDummyURL2, kTemporary},
- {true, nullptr, 0, kDummyURL2, kPersistent},
+ {true, "", 0, kDummyURL2, kPersistent},
{true, "dom", 0, kDummyURL2, kPersistent},
{false, "dom/fan", 2013, kDummyURL2, kPersistent},
{false, "baz", 18, kDummyURL2, kPersistent},
@@ -403,7 +403,7 @@ TEST_F(FileSystemQuotaClientTest, MultiDomainTest) {
TEST_F(FileSystemQuotaClientTest, GetUsage_MultipleTasks) {
auto quota_client = NewQuotaClient();
const TestFile kFiles[] = {
- {true, nullptr, 0, kDummyURL1, kTemporary},
+ {true, "", 0, kDummyURL1, kTemporary},
{false, "foo", 11, kDummyURL1, kTemporary},
{false, "bar", 22, kDummyURL1, kTemporary},
};
@@ -433,9 +433,9 @@ TEST_F(FileSystemQuotaClientTest, GetUsage_MultipleTasks) {
TEST_F(FileSystemQuotaClientTest, GetOriginsForType) {
auto quota_client = NewQuotaClient();
const TestFile kFiles[] = {
- {true, nullptr, 0, kDummyURL1, kTemporary},
- {true, nullptr, 0, kDummyURL2, kTemporary},
- {true, nullptr, 0, kDummyURL3, kPersistent},
+ {true, "", 0, kDummyURL1, kTemporary},
+ {true, "", 0, kDummyURL2, kTemporary},
+ {true, "", 0, kDummyURL3, kPersistent},
};
InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles));
@@ -459,11 +459,9 @@ TEST_F(FileSystemQuotaClientTest, GetOriginsForHost) {
const char* kURL4 = "http://foo2.com/";
const char* kURL5 = "http://foo.com:2/";
const TestFile kFiles[] = {
- {true, nullptr, 0, kURL1, kTemporary},
- {true, nullptr, 0, kURL2, kTemporary},
- {true, nullptr, 0, kURL3, kTemporary},
- {true, nullptr, 0, kURL4, kTemporary},
- {true, nullptr, 0, kURL5, kPersistent},
+ {true, "", 0, kURL1, kTemporary}, {true, "", 0, kURL2, kTemporary},
+ {true, "", 0, kURL3, kTemporary}, {true, "", 0, kURL4, kTemporary},
+ {true, "", 0, kURL5, kPersistent},
};
InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles));
@@ -482,19 +480,19 @@ TEST_F(FileSystemQuotaClientTest, GetOriginsForHost) {
TEST_F(FileSystemQuotaClientTest, DeleteOriginTest) {
auto quota_client = NewQuotaClient();
const TestFile kFiles[] = {
- {true, nullptr, 0, "http://foo.com/", kTemporary},
+ {true, "", 0, "http://foo.com/", kTemporary},
{false, "a", 1, "http://foo.com/", kTemporary},
- {true, nullptr, 0, "https://foo.com/", kTemporary},
+ {true, "", 0, "https://foo.com/", kTemporary},
{false, "b", 2, "https://foo.com/", kTemporary},
- {true, nullptr, 0, "http://foo.com/", kPersistent},
+ {true, "", 0, "http://foo.com/", kPersistent},
{false, "c", 4, "http://foo.com/", kPersistent},
- {true, nullptr, 0, "http://bar.com/", kTemporary},
+ {true, "", 0, "http://bar.com/", kTemporary},
{false, "d", 8, "http://bar.com/", kTemporary},
- {true, nullptr, 0, "http://bar.com/", kPersistent},
+ {true, "", 0, "http://bar.com/", kPersistent},
{false, "e", 16, "http://bar.com/", kPersistent},
- {true, nullptr, 0, "https://bar.com/", kPersistent},
+ {true, "", 0, "https://bar.com/", kPersistent},
{false, "f", 32, "https://bar.com/", kPersistent},
- {true, nullptr, 0, "https://bar.com/", kTemporary},
+ {true, "", 0, "https://bar.com/", kTemporary},
{false, "g", 64, "https://bar.com/", kTemporary},
};
InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles));
diff --git a/chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader.cc b/chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader.cc
new file mode 100644
index 00000000000..e60c66db978
--- /dev/null
+++ b/chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader.cc
@@ -0,0 +1,245 @@
+// Copyright 2020 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 "storage/browser/file_system/filesystem_proxy_file_stream_reader.h"
+
+#include <stdint.h>
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/check_op.h"
+#include "base/files/file_util.h"
+#include "base/location.h"
+#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/task_runner.h"
+#include "base/task_runner_util.h"
+#include "net/base/file_stream.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+
+namespace storage {
+
+namespace {
+
+const int kOpenFlagsForRead =
+ base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_ASYNC;
+
+using GetFileInfoCallback =
+ base::OnceCallback<void(base::File::Error, const base::File::Info&)>;
+
+FileErrorOr<base::File::Info> DoGetFileInfo(
+ const base::FilePath& path,
+ scoped_refptr<FilesystemProxyFileStreamReader::SharedFilesystemProxy>
+ shared_filesystem_proxy) {
+ if (!shared_filesystem_proxy->data->PathExists(path)) {
+ return base::File::FILE_ERROR_NOT_FOUND;
+ }
+
+ base::Optional<base::File::Info> info =
+ shared_filesystem_proxy->data->GetFileInfo(path);
+ if (!info.has_value()) {
+ return base::File::FILE_ERROR_FAILED;
+ }
+
+ return std::move(*info);
+}
+
+FileErrorOr<base::File> DoOpenFile(
+ const base::FilePath& path,
+ scoped_refptr<FilesystemProxyFileStreamReader::SharedFilesystemProxy>
+ shared_filesystem_proxy) {
+ return shared_filesystem_proxy->data->OpenFile(path, kOpenFlagsForRead);
+}
+
+} // namespace
+
+std::unique_ptr<FileStreamReader> FileStreamReader::CreateForFilesystemProxy(
+ scoped_refptr<base::TaskRunner> task_runner,
+ const base::FilePath& file_path,
+ std::unique_ptr<storage::FilesystemProxy> filesystem_proxy,
+ int64_t initial_offset,
+ const base::Time& expected_modification_time) {
+ DCHECK(filesystem_proxy);
+ constexpr bool emit_metrics = false;
+ return base::WrapUnique(new FilesystemProxyFileStreamReader(
+ std::move(task_runner), file_path, std::move(filesystem_proxy),
+ initial_offset, expected_modification_time, emit_metrics));
+}
+
+std::unique_ptr<FileStreamReader>
+FileStreamReader::CreateForIndexedDBDataItemReader(
+ scoped_refptr<base::TaskRunner> task_runner,
+ const base::FilePath& file_path,
+ std::unique_ptr<storage::FilesystemProxy> filesystem_proxy,
+ int64_t initial_offset,
+ const base::Time& expected_modification_time) {
+ DCHECK(filesystem_proxy);
+ constexpr bool emit_metrics = true;
+ return base::WrapUnique(new FilesystemProxyFileStreamReader(
+ std::move(task_runner), file_path, std::move(filesystem_proxy),
+ initial_offset, expected_modification_time, emit_metrics));
+}
+
+FilesystemProxyFileStreamReader::~FilesystemProxyFileStreamReader() = default;
+
+int FilesystemProxyFileStreamReader::Read(
+ net::IOBuffer* buf,
+ int buf_len,
+ net::CompletionOnceCallback callback) {
+ DCHECK(!has_pending_open_);
+
+ if (stream_impl_)
+ return stream_impl_->Read(buf, buf_len, std::move(callback));
+
+ Open(base::BindOnce(&FilesystemProxyFileStreamReader::DidOpenForRead,
+ weak_factory_.GetWeakPtr(), base::RetainedRef(buf),
+ buf_len, std::move(callback)));
+
+ return net::ERR_IO_PENDING;
+}
+
+int64_t FilesystemProxyFileStreamReader::GetLength(
+ net::Int64CompletionOnceCallback callback) {
+ base::PostTaskAndReplyWithResult(
+ task_runner_.get(), FROM_HERE,
+ base::BindOnce(&DoGetFileInfo, file_path_, shared_filesystem_proxy_),
+ base::BindOnce(
+ &FilesystemProxyFileStreamReader::DidGetFileInfoForGetLength,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
+ return net::ERR_IO_PENDING;
+}
+
+FilesystemProxyFileStreamReader::FilesystemProxyFileStreamReader(
+ scoped_refptr<base::TaskRunner> task_runner,
+ const base::FilePath& file_path,
+ std::unique_ptr<storage::FilesystemProxy> filesystem_proxy,
+ int64_t initial_offset,
+ const base::Time& expected_modification_time,
+ bool emit_metrics)
+ : task_runner_(std::move(task_runner)),
+ shared_filesystem_proxy_(base::MakeRefCounted<SharedFilesystemProxy>(
+ std::move(filesystem_proxy))),
+ file_path_(file_path),
+ initial_offset_(initial_offset),
+ expected_modification_time_(expected_modification_time),
+ emit_metrics_(emit_metrics) {}
+
+void FilesystemProxyFileStreamReader::Open(
+ net::CompletionOnceCallback callback) {
+ DCHECK(!has_pending_open_);
+ DCHECK(!stream_impl_.get());
+ has_pending_open_ = true;
+
+ // Call GetLength first to make it perform last-modified-time verification,
+ // and then call DidVerifyForOpen to do the rest.
+ int64_t verify_result = GetLength(
+ base::BindOnce(&FilesystemProxyFileStreamReader::DidVerifyForOpen,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
+ DCHECK_EQ(verify_result, net::ERR_IO_PENDING);
+}
+
+void FilesystemProxyFileStreamReader::DidVerifyForOpen(
+ net::CompletionOnceCallback callback,
+ int64_t get_length_result) {
+ if (get_length_result < 0) {
+ std::move(callback).Run(static_cast<int>(get_length_result));
+ return;
+ }
+
+ callback_ = std::move(callback);
+ base::PostTaskAndReplyWithResult(
+ task_runner_.get(), FROM_HERE,
+ base::BindOnce(&DoOpenFile, file_path_, shared_filesystem_proxy_),
+ base::BindOnce(&FilesystemProxyFileStreamReader::DidOpenFile,
+ weak_factory_.GetWeakPtr()));
+}
+
+void FilesystemProxyFileStreamReader::DidOpenFile(
+ FileErrorOr<base::File> open_result) {
+ if (open_result.is_error()) {
+ std::move(callback_).Run(open_result.error());
+ return;
+ }
+
+ stream_impl_ = std::make_unique<net::FileStream>(
+ std::move(open_result.value()), task_runner_);
+ int seek_result = stream_impl_->Seek(
+ initial_offset_,
+ base::BindOnce(&FilesystemProxyFileStreamReader::DidSeekFileStream,
+ weak_factory_.GetWeakPtr()));
+ if (seek_result != net::ERR_IO_PENDING) {
+ std::move(callback_).Run(seek_result);
+ }
+}
+
+void FilesystemProxyFileStreamReader::DidSeekFileStream(int64_t seek_result) {
+ if (seek_result < 0) {
+ std::move(callback_).Run(static_cast<int>(seek_result));
+ return;
+ }
+ if (seek_result != initial_offset_) {
+ std::move(callback_).Run(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
+ return;
+ }
+ std::move(callback_).Run(net::OK);
+}
+
+void FilesystemProxyFileStreamReader::DidOpenForRead(
+ net::IOBuffer* buf,
+ int buf_len,
+ net::CompletionOnceCallback callback,
+ int open_result) {
+ DCHECK(has_pending_open_);
+ has_pending_open_ = false;
+ if (open_result != net::OK) {
+ stream_impl_.reset();
+ std::move(callback).Run(open_result);
+ return;
+ }
+ DCHECK(stream_impl_.get());
+
+ callback_ = std::move(callback);
+ const int read_result = stream_impl_->Read(
+ buf, buf_len,
+ base::BindOnce(&FilesystemProxyFileStreamReader::OnRead,
+ weak_factory_.GetWeakPtr()));
+ if (read_result != net::ERR_IO_PENDING)
+ std::move(callback_).Run(read_result);
+}
+
+void FilesystemProxyFileStreamReader::DidGetFileInfoForGetLength(
+ net::Int64CompletionOnceCallback callback,
+ FileErrorOr<base::File::Info> result) {
+ // TODO(enne): track rate of missing blobs for http://crbug.com/1131151
+ if (emit_metrics_) {
+ bool file_was_found = !result.is_error() ||
+ result.error() != base::File::FILE_ERROR_NOT_FOUND;
+ UMA_HISTOGRAM_BOOLEAN("WebCore.IndexedDB.FoundBlobFileForValue",
+ file_was_found);
+ }
+
+ if (result.is_error()) {
+ std::move(callback).Run(net::FileErrorToNetError(result.error()));
+ return;
+ }
+
+ const auto& file_info = result.value();
+ if (file_info.is_directory) {
+ std::move(callback).Run(net::ERR_FILE_NOT_FOUND);
+ return;
+ }
+ if (!VerifySnapshotTime(expected_modification_time_, file_info)) {
+ std::move(callback).Run(net::ERR_UPLOAD_FILE_CHANGED);
+ return;
+ }
+ std::move(callback).Run(file_info.size);
+}
+
+void FilesystemProxyFileStreamReader::OnRead(int read_result) {
+ std::move(callback_).Run(read_result);
+}
+
+} // namespace storage
diff --git a/chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader.h b/chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader.h
new file mode 100644
index 00000000000..10222e0d032
--- /dev/null
+++ b/chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader.h
@@ -0,0 +1,93 @@
+// Copyright 2020 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 STORAGE_BROWSER_FILE_SYSTEM_FILESYSTEM_PROXY_FILE_STREAM_READER_H_
+#define STORAGE_BROWSER_FILE_SYSTEM_FILESYSTEM_PROXY_FILE_STREAM_READER_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "base/compiler_specific.h"
+#include "base/component_export.h"
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "components/services/storage/public/cpp/filesystem/filesystem_proxy.h"
+#include "net/base/completion_once_callback.h"
+#include "storage/browser/file_system/file_stream_reader.h"
+
+namespace base {
+class TaskRunner;
+}
+
+namespace net {
+class FileStream;
+}
+
+namespace storage {
+
+// A thin wrapper of net::FileStream with range support for sliced file
+// handling.
+class COMPONENT_EXPORT(STORAGE_BROWSER) FilesystemProxyFileStreamReader
+ : public FileStreamReader {
+ public:
+ ~FilesystemProxyFileStreamReader() override;
+
+ // FileStreamReader overrides.
+ int Read(net::IOBuffer* buf,
+ int buf_len,
+ net::CompletionOnceCallback callback) override;
+ int64_t GetLength(net::Int64CompletionOnceCallback callback) override;
+
+ using SharedFilesystemProxy =
+ base::RefCountedData<std::unique_ptr<storage::FilesystemProxy>>;
+
+ private:
+ friend class FileStreamReader;
+
+ FilesystemProxyFileStreamReader(
+ scoped_refptr<base::TaskRunner> task_runner,
+ const base::FilePath& file_path,
+ std::unique_ptr<storage::FilesystemProxy> filesystem_proxy,
+ int64_t initial_offset,
+ const base::Time& expected_modification_time,
+ bool emit_metrics);
+ void Open(net::CompletionOnceCallback callback);
+
+ // Callbacks that are chained from Open for Read.
+ void DidVerifyForOpen(net::CompletionOnceCallback callback,
+ int64_t get_length_result);
+ void DidOpenFile(FileErrorOr<base::File> result);
+
+ void DidSeekFileStream(int64_t seek_result);
+ void DidOpenForRead(net::IOBuffer* buf,
+ int buf_len,
+ net::CompletionOnceCallback callback,
+ int open_result);
+ void OnRead(int read_result);
+
+ void DidGetFileInfoForGetLength(net::Int64CompletionOnceCallback callback,
+ FileErrorOr<base::File::Info> result);
+
+ net::CompletionOnceCallback callback_;
+ scoped_refptr<base::TaskRunner> task_runner_;
+ std::unique_ptr<net::FileStream> stream_impl_;
+ // FilesystemProxy is threadsafe, however all file operations must be
+ // run on |task_runner_|. Therefore, this refcounted-data preserves
+ // the lifetime of the filesystem proxy even if the FileStreamReader is
+ // destroyed during a callback.
+ scoped_refptr<SharedFilesystemProxy> shared_filesystem_proxy_;
+ const base::FilePath file_path_;
+ const int64_t initial_offset_;
+ const base::Time expected_modification_time_;
+ bool has_pending_open_ = false;
+ bool emit_metrics_ = false;
+ base::WeakPtrFactory<FilesystemProxyFileStreamReader> weak_factory_{this};
+};
+
+} // namespace storage
+
+#endif // STORAGE_BROWSER_FILE_SYSTEM_FILESYSTEM_PROXY_FILE_STREAM_READER_H_
diff --git a/chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader_unittest.cc b/chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader_unittest.cc
new file mode 100644
index 00000000000..0cfd7801075
--- /dev/null
+++ b/chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader_unittest.cc
@@ -0,0 +1,109 @@
+// Copyright 2020 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 "storage/browser/file_system/local_file_stream_reader.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/location.h"
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
+#include "base/test/task_environment.h"
+#include "base/threading/thread.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/base/test_completion_callback.h"
+#include "storage/browser/file_system/file_stream_reader_test.h"
+#include "storage/browser/file_system/file_stream_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace storage {
+
+class FilesystemProxyFileStreamReaderTest : public FileStreamReaderTest {
+ public:
+ FilesystemProxyFileStreamReaderTest() : file_thread_("TestFileThread") {}
+
+ void SetUp() override {
+ ASSERT_TRUE(dir_.CreateUniqueTempDir());
+ ASSERT_TRUE(file_thread_.Start());
+ }
+
+ void TearDown() override {
+ // Give another chance for deleted streams to perform Close.
+ base::RunLoop().RunUntilIdle();
+ file_thread_.Stop();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ std::unique_ptr<FileStreamReader> CreateFileReader(
+ const std::string& file_name,
+ int64_t initial_offset,
+ const base::Time& expected_modification_time) override {
+ return FileStreamReader::CreateForFilesystemProxy(
+ file_task_runner(), test_dir().AppendASCII(file_name),
+ CreateFilesystemProxy(), initial_offset, expected_modification_time);
+ }
+
+ void WriteFile(const std::string& file_name,
+ const char* buf,
+ size_t buf_size,
+ base::Time* modification_time) override {
+ base::FilePath path = test_dir().AppendASCII(file_name);
+ base::WriteFile(path, buf, buf_size);
+
+ base::File::Info file_info;
+ ASSERT_TRUE(base::GetFileInfo(path, &file_info));
+ if (modification_time)
+ *modification_time = file_info.last_modified;
+ }
+
+ void TouchFile(const std::string& file_name, base::TimeDelta delta) override {
+ base::FilePath path = test_dir().AppendASCII(file_name);
+ base::File::Info file_info;
+ ASSERT_TRUE(base::GetFileInfo(path, &file_info));
+ ASSERT_TRUE(base::TouchFile(path, file_info.last_accessed,
+ file_info.last_modified + delta));
+ }
+
+ void EnsureFileTaskFinished() override {
+ base::RunLoop run_loop;
+ file_task_runner()->PostTaskAndReply(FROM_HERE, base::DoNothing(),
+
+ run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ base::FilePath test_dir() const { return dir_.GetPath(); }
+
+ base::SingleThreadTaskRunner* file_task_runner() const {
+ return file_thread_.task_runner().get();
+ }
+
+ std::unique_ptr<FilesystemProxy> CreateFilesystemProxy() {
+ return std::make_unique<FilesystemProxy>(FilesystemProxy::UNRESTRICTED,
+ dir_.GetPath());
+ }
+
+ private:
+ base::ScopedTempDir dir_;
+ base::Thread file_thread_;
+};
+
+INSTANTIATE_TYPED_TEST_SUITE_P(FilesystemProxy,
+ FileStreamReaderTypedTest,
+ FilesystemProxyFileStreamReaderTest);
+
+} // namespace storage
diff --git a/chromium/storage/browser/file_system/local_file_stream_reader.cc b/chromium/storage/browser/file_system/local_file_stream_reader.cc
index 716b5806cff..efd958857eb 100644
--- a/chromium/storage/browser/file_system/local_file_stream_reader.cc
+++ b/chromium/storage/browser/file_system/local_file_stream_reader.cc
@@ -26,40 +26,27 @@ namespace {
const int kOpenFlagsForRead =
base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_ASYNC;
-struct GetFileInfoResults {
- base::File::Error error;
- base::File::Info info;
-};
-
-using GetFileInfoCallback =
- base::OnceCallback<void(base::File::Error, const base::File::Info&)>;
-
-GetFileInfoResults DoGetFileInfo(const base::FilePath& path) {
- GetFileInfoResults results;
- if (!base::PathExists(path)) {
- results.error = base::File::FILE_ERROR_NOT_FOUND;
- return results;
- }
- results.error = base::GetFileInfo(path, &results.info)
- ? base::File::FILE_OK
- : base::File::FILE_ERROR_FAILED;
- return results;
-}
+FileErrorOr<base::File::Info> DoGetFileInfo(const base::FilePath& path) {
+ if (!base::PathExists(path))
+ return base::File::FILE_ERROR_NOT_FOUND;
-void SendGetFileInfoResults(GetFileInfoCallback callback,
- const GetFileInfoResults& results) {
- std::move(callback).Run(results.error, results.info);
+ base::File::Info info;
+ bool success = base::GetFileInfo(path, &info);
+ if (!success)
+ return base::File::FILE_ERROR_FAILED;
+ return info;
}
} // namespace
std::unique_ptr<FileStreamReader> FileStreamReader::CreateForLocalFile(
- base::TaskRunner* task_runner,
+ scoped_refptr<base::TaskRunner> task_runner,
const base::FilePath& file_path,
int64_t initial_offset,
const base::Time& expected_modification_time) {
- return base::WrapUnique(new LocalFileStreamReader(
- task_runner, file_path, initial_offset, expected_modification_time));
+ return base::WrapUnique(
+ new LocalFileStreamReader(std::move(task_runner), file_path,
+ initial_offset, expected_modification_time));
}
LocalFileStreamReader::~LocalFileStreamReader() = default;
@@ -83,24 +70,21 @@ int64_t LocalFileStreamReader::GetLength(
net::Int64CompletionOnceCallback callback) {
bool posted = base::PostTaskAndReplyWithResult(
task_runner_.get(), FROM_HERE, base::BindOnce(&DoGetFileInfo, file_path_),
- base::BindOnce(
- &SendGetFileInfoResults,
- base::BindOnce(&LocalFileStreamReader::DidGetFileInfoForGetLength,
- weak_factory_.GetWeakPtr(), std::move(callback))));
+ base::BindOnce(&LocalFileStreamReader::DidGetFileInfoForGetLength,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
DCHECK(posted);
return net::ERR_IO_PENDING;
}
LocalFileStreamReader::LocalFileStreamReader(
- base::TaskRunner* task_runner,
+ scoped_refptr<base::TaskRunner> task_runner,
const base::FilePath& file_path,
int64_t initial_offset,
const base::Time& expected_modification_time)
- : task_runner_(task_runner),
+ : task_runner_(std::move(task_runner)),
file_path_(file_path),
initial_offset_(initial_offset),
- expected_modification_time_(expected_modification_time),
- has_pending_open_(false) {}
+ expected_modification_time_(expected_modification_time) {}
void LocalFileStreamReader::Open(net::CompletionOnceCallback callback) {
DCHECK(!has_pending_open_);
@@ -182,14 +166,14 @@ void LocalFileStreamReader::DidOpenForRead(net::IOBuffer* buf,
void LocalFileStreamReader::DidGetFileInfoForGetLength(
net::Int64CompletionOnceCallback callback,
- base::File::Error error,
- const base::File::Info& file_info) {
- if (file_info.is_directory) {
- std::move(callback).Run(net::ERR_FILE_NOT_FOUND);
+ FileErrorOr<base::File::Info> result) {
+ if (result.is_error()) {
+ std::move(callback).Run(net::FileErrorToNetError(result.error()));
return;
}
- if (error != base::File::FILE_OK) {
- std::move(callback).Run(net::FileErrorToNetError(error));
+ const auto& file_info = result.value();
+ if (file_info.is_directory) {
+ std::move(callback).Run(net::ERR_FILE_NOT_FOUND);
return;
}
if (!VerifySnapshotTime(expected_modification_time_, file_info)) {
diff --git a/chromium/storage/browser/file_system/local_file_stream_reader.h b/chromium/storage/browser/file_system/local_file_stream_reader.h
index f46c3956828..e9f5866f513 100644
--- a/chromium/storage/browser/file_system/local_file_stream_reader.h
+++ b/chromium/storage/browser/file_system/local_file_stream_reader.h
@@ -45,7 +45,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) LocalFileStreamReader
friend class FileStreamReader;
friend class LocalFileStreamReaderTest;
- LocalFileStreamReader(base::TaskRunner* task_runner,
+ LocalFileStreamReader(scoped_refptr<base::TaskRunner> task_runner,
const base::FilePath& file_path,
int64_t initial_offset,
const base::Time& expected_modification_time);
@@ -63,8 +63,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) LocalFileStreamReader
void OnRead(int read_result);
void DidGetFileInfoForGetLength(net::Int64CompletionOnceCallback callback,
- base::File::Error error,
- const base::File::Info& file_info);
+ FileErrorOr<base::File::Info> result);
net::CompletionOnceCallback callback_;
scoped_refptr<base::TaskRunner> task_runner_;
@@ -72,7 +71,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) LocalFileStreamReader
const base::FilePath file_path_;
const int64_t initial_offset_;
const base::Time expected_modification_time_;
- bool has_pending_open_;
+ bool has_pending_open_ = false;
base::WeakPtrFactory<LocalFileStreamReader> weak_factory_{this};
};
diff --git a/chromium/storage/browser/file_system/local_file_stream_reader_unittest.cc b/chromium/storage/browser/file_system/local_file_stream_reader_unittest.cc
index 7b7887d5214..d1f6bf8fe82 100644
--- a/chromium/storage/browser/file_system/local_file_stream_reader_unittest.cc
+++ b/chromium/storage/browser/file_system/local_file_stream_reader_unittest.cc
@@ -26,38 +26,19 @@
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
+#include "storage/browser/file_system/file_stream_reader_test.h"
#include "storage/browser/file_system/file_stream_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace storage {
-namespace {
-
-const char kTestData[] = "0123456789";
-const int kTestDataSize = base::size(kTestData) - 1;
-
-void NeverCalled(int) {
- ADD_FAILURE();
-}
-
-void QuitLoop() {
- base::RunLoop::QuitCurrentWhenIdleDeprecated();
-}
-
-} // namespace
-
-class LocalFileStreamReaderTest : public testing::Test {
+class LocalFileStreamReaderTest : public FileStreamReaderTest {
public:
LocalFileStreamReaderTest() : file_thread_("TestFileThread") {}
void SetUp() override {
- ASSERT_TRUE(file_thread_.Start());
ASSERT_TRUE(dir_.CreateUniqueTempDir());
-
- base::WriteFile(test_path(), kTestData);
- base::File::Info info;
- ASSERT_TRUE(base::GetFileInfo(test_path(), &info));
- test_file_modification_time_ = info.last_modified;
+ ASSERT_TRUE(file_thread_.Start());
}
void TearDown() override {
@@ -67,195 +48,57 @@ class LocalFileStreamReaderTest : public testing::Test {
base::RunLoop().RunUntilIdle();
}
- protected:
- LocalFileStreamReader* CreateFileReader(
- const base::FilePath& path,
+ std::unique_ptr<FileStreamReader> CreateFileReader(
+ const std::string& file_name,
int64_t initial_offset,
- const base::Time& expected_modification_time) {
- return new LocalFileStreamReader(file_task_runner(), path, initial_offset,
- expected_modification_time);
+ const base::Time& expected_modification_time) override {
+ return FileStreamReader::CreateForLocalFile(
+ file_task_runner(), test_dir().AppendASCII(file_name), initial_offset,
+ expected_modification_time);
}
- void TouchTestFile(base::TimeDelta delta) {
- base::Time new_modified_time = test_file_modification_time() + delta;
- ASSERT_TRUE(base::TouchFile(test_path(), test_file_modification_time(),
- new_modified_time));
+ void WriteFile(const std::string& file_name,
+ const char* buf,
+ size_t buf_size,
+ base::Time* modification_time) override {
+ base::FilePath path = test_dir().AppendASCII(file_name);
+ base::WriteFile(path, buf, buf_size);
+
+ base::File::Info file_info;
+ ASSERT_TRUE(base::GetFileInfo(path, &file_info));
+ if (modification_time)
+ *modification_time = file_info.last_modified;
}
- base::SingleThreadTaskRunner* file_task_runner() const {
- return file_thread_.task_runner().get();
+ void TouchFile(const std::string& file_name, base::TimeDelta delta) override {
+ base::FilePath path = test_dir().AppendASCII(file_name);
+ base::File::Info file_info;
+ ASSERT_TRUE(base::GetFileInfo(path, &file_info));
+ ASSERT_TRUE(base::TouchFile(path, file_info.last_accessed,
+ file_info.last_modified + delta));
}
- base::FilePath test_dir() const { return dir_.GetPath(); }
- base::FilePath test_path() const {
- return dir_.GetPath().AppendASCII("test");
- }
- base::Time test_file_modification_time() const {
- return test_file_modification_time_;
+ void EnsureFileTaskFinished() override {
+ base::RunLoop run_loop;
+ file_task_runner()->PostTaskAndReply(FROM_HERE, base::DoNothing(),
+
+ run_loop.QuitClosure());
+ run_loop.Run();
}
- void EnsureFileTaskFinished() {
- file_task_runner()->PostTaskAndReply(FROM_HERE, base::DoNothing(),
- base::BindOnce(&QuitLoop));
- base::RunLoop().Run();
+ base::FilePath test_dir() const { return dir_.GetPath(); }
+
+ base::SingleThreadTaskRunner* file_task_runner() const {
+ return file_thread_.task_runner().get();
}
private:
- base::test::SingleThreadTaskEnvironment task_environment_{
- base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
- base::Thread file_thread_;
base::ScopedTempDir dir_;
- base::Time test_file_modification_time_;
+ base::Thread file_thread_;
};
-TEST_F(LocalFileStreamReaderTest, NonExistent) {
- base::FilePath nonexistent_path = test_dir().AppendASCII("nonexistent");
- std::unique_ptr<LocalFileStreamReader> reader(
- CreateFileReader(nonexistent_path, 0, base::Time()));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, 10, &result);
- ASSERT_EQ(net::ERR_FILE_NOT_FOUND, result);
- ASSERT_EQ(0U, data.size());
-}
-
-TEST_F(LocalFileStreamReaderTest, Empty) {
- base::FilePath empty_path = test_dir().AppendASCII("empty");
- base::File file(empty_path, base::File::FLAG_CREATE | base::File::FLAG_READ);
- ASSERT_TRUE(file.IsValid());
- file.Close();
-
- std::unique_ptr<LocalFileStreamReader> reader(
- CreateFileReader(empty_path, 0, base::Time()));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, 10, &result);
- ASSERT_EQ(net::OK, result);
- ASSERT_EQ(0U, data.size());
-
- net::TestInt64CompletionCallback callback;
- int64_t length_result = reader->GetLength(callback.callback());
- if (length_result == net::ERR_IO_PENDING)
- length_result = callback.WaitForResult();
- ASSERT_EQ(0, result);
-}
-
-TEST_F(LocalFileStreamReaderTest, GetLengthNormal) {
- std::unique_ptr<LocalFileStreamReader> reader(
- CreateFileReader(test_path(), 0, test_file_modification_time()));
- net::TestInt64CompletionCallback callback;
- int64_t result = reader->GetLength(callback.callback());
- if (result == net::ERR_IO_PENDING)
- result = callback.WaitForResult();
- ASSERT_EQ(kTestDataSize, result);
-}
-
-TEST_F(LocalFileStreamReaderTest, GetLengthAfterModified) {
- // Touch file so that the file's modification time becomes different
- // from what we expect.
- TouchTestFile(base::TimeDelta::FromSeconds(-1));
-
- std::unique_ptr<LocalFileStreamReader> reader(
- CreateFileReader(test_path(), 0, test_file_modification_time()));
- net::TestInt64CompletionCallback callback1;
- int64_t result = reader->GetLength(callback1.callback());
- if (result == net::ERR_IO_PENDING)
- result = callback1.WaitForResult();
- ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result);
-
- // With nullptr expected modification time this should work.
- reader.reset(CreateFileReader(test_path(), 0, base::Time()));
- net::TestInt64CompletionCallback callback2;
- result = reader->GetLength(callback2.callback());
- if (result == net::ERR_IO_PENDING)
- result = callback2.WaitForResult();
- ASSERT_EQ(kTestDataSize, result);
-}
-
-TEST_F(LocalFileStreamReaderTest, GetLengthWithOffset) {
- std::unique_ptr<LocalFileStreamReader> reader(
- CreateFileReader(test_path(), 3, base::Time()));
- net::TestInt64CompletionCallback callback;
- int64_t result = reader->GetLength(callback.callback());
- if (result == net::ERR_IO_PENDING)
- result = callback.WaitForResult();
- // Initial offset does not affect the result of GetLength.
- ASSERT_EQ(kTestDataSize, result);
-}
-
-TEST_F(LocalFileStreamReaderTest, ReadNormal) {
- std::unique_ptr<LocalFileStreamReader> reader(
- CreateFileReader(test_path(), 0, test_file_modification_time()));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, kTestDataSize, &result);
- ASSERT_EQ(net::OK, result);
- ASSERT_EQ(kTestData, data);
-}
-
-TEST_F(LocalFileStreamReaderTest, ReadAfterModified) {
- // Touch file so that the file's modification time becomes different
- // from what we expect. Note that the resolution on some filesystems
- // is 1s so we can't test with deltas less than that.
- TouchTestFile(base::TimeDelta::FromSeconds(-1));
- std::unique_ptr<LocalFileStreamReader> reader(
- CreateFileReader(test_path(), 0, test_file_modification_time()));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, kTestDataSize, &result);
- EXPECT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result);
- EXPECT_EQ(0U, data.size());
-
- // Due to precision loss converting int64_t->double->int64_t (e.g. through
- // Blink) the expected/actual time may vary by microseconds. With
- // modification time delta < 10us this should work.
- TouchTestFile(base::TimeDelta::FromMicroseconds(1));
- data.clear();
- reader.reset(CreateFileReader(test_path(), 0, test_file_modification_time()));
- ReadFromReader(reader.get(), &data, kTestDataSize, &result);
- EXPECT_EQ(net::OK, result);
- EXPECT_EQ(kTestData, data);
-
- // With matching modification times time this should work.
- TouchTestFile(base::TimeDelta());
- data.clear();
- reader.reset(CreateFileReader(test_path(), 0, test_file_modification_time()));
- ReadFromReader(reader.get(), &data, kTestDataSize, &result);
- EXPECT_EQ(net::OK, result);
- EXPECT_EQ(kTestData, data);
-
- // And with nullptr expected modification time this should work.
- data.clear();
- reader.reset(CreateFileReader(test_path(), 0, base::Time()));
- ReadFromReader(reader.get(), &data, kTestDataSize, &result);
- EXPECT_EQ(net::OK, result);
- EXPECT_EQ(kTestData, data);
-}
-
-TEST_F(LocalFileStreamReaderTest, ReadWithOffset) {
- std::unique_ptr<LocalFileStreamReader> reader(
- CreateFileReader(test_path(), 3, base::Time()));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, kTestDataSize, &result);
- ASSERT_EQ(net::OK, result);
- ASSERT_EQ(&kTestData[3], data);
-}
-
-TEST_F(LocalFileStreamReaderTest, DeleteWithUnfinishedRead) {
- std::unique_ptr<LocalFileStreamReader> reader(
- CreateFileReader(test_path(), 0, base::Time()));
-
- net::TestCompletionCallback callback;
- scoped_refptr<net::IOBufferWithSize> buf =
- base::MakeRefCounted<net::IOBufferWithSize>(kTestDataSize);
- int rv = reader->Read(buf.get(), buf->size(), base::BindOnce(&NeverCalled));
- ASSERT_TRUE(rv == net::ERR_IO_PENDING || rv >= 0);
-
- // Delete immediately.
- // Should not crash; nor should NeverCalled be callback.
- reader.reset();
- EnsureFileTaskFinished();
-}
+INSTANTIATE_TYPED_TEST_SUITE_P(Local,
+ FileStreamReaderTypedTest,
+ LocalFileStreamReaderTest);
} // namespace storage
diff --git a/chromium/storage/browser/file_system/local_file_stream_writer.cc b/chromium/storage/browser/file_system/local_file_stream_writer.cc
index 342f1e8ca67..5ef1c708372 100644
--- a/chromium/storage/browser/file_system/local_file_stream_writer.cc
+++ b/chromium/storage/browser/file_system/local_file_stream_writer.cc
@@ -139,19 +139,46 @@ void LocalFileStreamWriter::DidOpen(base::OnceClosure main_operation,
return;
}
- InitiateSeek(std::move(main_operation));
+ auto file_info = std::make_unique<base::File::Info>();
+ base::File::Info* raw_file_info = file_info.get();
+ result = stream_impl_->GetFileInfo(
+ raw_file_info,
+ base::BindOnce(&LocalFileStreamWriter::InitiateSeek,
+ weak_factory_.GetWeakPtr(), std::move(main_operation),
+ std::move(file_info)));
+ DCHECK_NE(result, net::OK);
+ if (result != net::ERR_IO_PENDING) {
+ has_pending_operation_ = false;
+ std::move(write_callback_).Run(result);
+ }
}
-void LocalFileStreamWriter::InitiateSeek(base::OnceClosure main_operation) {
+void LocalFileStreamWriter::InitiateSeek(
+ base::OnceClosure main_operation,
+ std::unique_ptr<base::File::Info> file_info,
+ int file_info_result) {
DCHECK(has_pending_operation_);
DCHECK(stream_impl_.get());
+ if (file_info_result != net::OK) {
+ has_pending_operation_ = false;
+ std::move(write_callback_).Run(file_info_result);
+ return;
+ }
+
if (initial_offset_ == 0) {
// No need to seek.
std::move(main_operation).Run();
return;
}
+ if (initial_offset_ > file_info->size) {
+ // We should not be writing past the end of the file.
+ has_pending_operation_ = false;
+ std::move(write_callback_).Run(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
+ return;
+ }
+
int result = stream_impl_->Seek(
initial_offset_,
base::BindOnce(&LocalFileStreamWriter::DidSeek,
diff --git a/chromium/storage/browser/file_system/local_file_stream_writer.h b/chromium/storage/browser/file_system/local_file_stream_writer.h
index ed51d9c4fb7..df2b4d1dff2 100644
--- a/chromium/storage/browser/file_system/local_file_stream_writer.h
+++ b/chromium/storage/browser/file_system/local_file_stream_writer.h
@@ -13,6 +13,7 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/component_export.h"
+#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
@@ -54,7 +55,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) LocalFileStreamWriter
// Seeks to |initial_offset_| and proceeds to |main_operation| if it succeeds.
// If failed, the error code is returned by calling |error_callback|.
- void InitiateSeek(base::OnceClosure main_operation);
+ void InitiateSeek(base::OnceClosure main_operation,
+ std::unique_ptr<base::File::Info> file_info,
+ int file_info_result);
void DidSeek(base::OnceClosure main_operation, int64_t result);
// Passed as the |main_operation| of InitiateOpen() function.
diff --git a/chromium/storage/browser/file_system/local_file_stream_writer_unittest.cc b/chromium/storage/browser/file_system/local_file_stream_writer_unittest.cc
index e2b2c1cbeb2..704fe4f1d37 100644
--- a/chromium/storage/browser/file_system/local_file_stream_writer_unittest.cc
+++ b/chromium/storage/browser/file_system/local_file_stream_writer_unittest.cc
@@ -24,6 +24,12 @@
namespace storage {
+namespace {
+void NeverCalled(int unused) {
+ ADD_FAILURE();
+}
+} // namespace
+
class LocalFileStreamWriterTest : public testing::Test {
public:
LocalFileStreamWriterTest() : file_thread_("TestFileThread") {}
@@ -75,10 +81,6 @@ class LocalFileStreamWriterTest : public testing::Test {
base::ScopedTempDir temp_dir_;
};
-void NeverCalled(int unused) {
- ADD_FAILURE();
-}
-
TEST_F(LocalFileStreamWriterTest, Write) {
base::FilePath path = CreateFileWithContent("file_a", std::string());
std::unique_ptr<LocalFileStreamWriter> writer(CreateWriter(path, 0));
@@ -100,6 +102,16 @@ TEST_F(LocalFileStreamWriterTest, WriteMiddle) {
EXPECT_EQ("foxxxr", GetFileContent(path));
}
+TEST_F(LocalFileStreamWriterTest, WriteNearEnd) {
+ base::FilePath path = CreateFileWithContent("file_a", "foobar");
+ std::unique_ptr<LocalFileStreamWriter> writer(CreateWriter(path, 5));
+ EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "xxx"));
+ writer.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(base::PathExists(path));
+ EXPECT_EQ("foobaxxx", GetFileContent(path));
+}
+
TEST_F(LocalFileStreamWriterTest, WriteEnd) {
base::FilePath path = CreateFileWithContent("file_a", "foobar");
std::unique_ptr<LocalFileStreamWriter> writer(CreateWriter(path, 6));
@@ -110,6 +122,17 @@ TEST_F(LocalFileStreamWriterTest, WriteEnd) {
EXPECT_EQ("foobarxxx", GetFileContent(path));
}
+TEST_F(LocalFileStreamWriterTest, WriteAfterEnd) {
+ base::FilePath path = CreateFileWithContent("file_a", "foobar");
+ std::unique_ptr<LocalFileStreamWriter> writer(CreateWriter(path, 7));
+ EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE,
+ WriteStringToWriter(writer.get(), "xxx"));
+ writer.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(base::PathExists(path));
+ EXPECT_EQ("foobar", GetFileContent(path));
+}
+
TEST_F(LocalFileStreamWriterTest, WriteFailForNonexistingFile) {
base::FilePath path = Path("file_a");
ASSERT_FALSE(base::PathExists(path));
diff --git a/chromium/storage/browser/file_system/memory_file_stream_reader_unittest.cc b/chromium/storage/browser/file_system/memory_file_stream_reader_unittest.cc
index 99bcfcbeb7e..685f49c22ef 100644
--- a/chromium/storage/browser/file_system/memory_file_stream_reader_unittest.cc
+++ b/chromium/storage/browser/file_system/memory_file_stream_reader_unittest.cc
@@ -21,230 +21,69 @@
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "storage/browser/file_system/file_stream_reader.h"
+#include "storage/browser/file_system/file_stream_reader_test.h"
#include "storage/browser/file_system/file_stream_test_utils.h"
#include "storage/browser/file_system/obfuscated_file_util_memory_delegate.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace storage {
-namespace {
-
-const char kTestData[] = "0123456789";
-const int kTestDataSize = base::size(kTestData) - 1;
-
-} // namespace
-
-class MemoryFileStreamReaderTest : public testing::Test {
+class MemoryFileStreamReaderTest : public FileStreamReaderTest {
public:
- MemoryFileStreamReaderTest() {}
+ MemoryFileStreamReaderTest() = default;
void SetUp() override {
- ASSERT_TRUE(file_system_directory_.CreateUniqueTempDir());
- file_util_ = std::make_unique<ObfuscatedFileUtilMemoryDelegate>(
- file_system_directory_.GetPath());
-
- file_util_->CreateFileForTesting(
- test_path(), base::span<const char>(kTestData, kTestDataSize));
- base::File::Info info;
- ASSERT_EQ(base::File::FILE_OK, file_util_->GetFileInfo(test_path(), &info));
- test_file_modification_time_ = info.last_modified;
+ ASSERT_TRUE(dir_.CreateUniqueTempDir());
+ file_util_ = std::make_unique<ObfuscatedFileUtilMemoryDelegate>(test_dir());
}
void TearDown() override {
// In memory operations should not have any residue in file system
// directory.
- EXPECT_TRUE(base::IsDirectoryEmpty(file_system_directory_.GetPath()));
+ EXPECT_TRUE(base::IsDirectoryEmpty(test_dir()));
}
- ObfuscatedFileUtilMemoryDelegate* file_util() { return file_util_.get(); }
-
- protected:
std::unique_ptr<FileStreamReader> CreateFileReader(
- const base::FilePath& path,
+ const std::string& file_name,
int64_t initial_offset,
- const base::Time& expected_modification_time) {
+ const base::Time& expected_modification_time) override {
return FileStreamReader::CreateForMemoryFile(
- base::ThreadTaskRunnerHandle::Get(), file_util_->GetWeakPtr(), path,
- initial_offset, expected_modification_time);
+ base::ThreadTaskRunnerHandle::Get(), file_util_->GetWeakPtr(),
+ test_dir().AppendASCII(file_name), initial_offset,
+ expected_modification_time);
}
- void TouchTestFile(base::TimeDelta delta) {
- base::Time new_modified_time = test_file_modification_time() + delta;
- ASSERT_EQ(base::File::FILE_OK,
- file_util()->Touch(test_path(), test_file_modification_time(),
- new_modified_time));
+ void WriteFile(const std::string& file_name,
+ const char* buf,
+ size_t buf_size,
+ base::Time* modification_time) override {
+ base::FilePath path = test_dir().AppendASCII(file_name);
+ file_util_->CreateFileForTesting(path,
+ base::span<const char>(buf, buf_size));
+ base::File::Info file_info;
+ ASSERT_EQ(base::File::FILE_OK, file_util_->GetFileInfo(path, &file_info));
+ if (modification_time)
+ *modification_time = file_info.last_modified;
}
- base::FilePath test_dir() const { return file_system_directory_.GetPath(); }
- base::FilePath test_path() const {
- return file_system_directory_.GetPath().AppendASCII("test");
- }
- base::Time test_file_modification_time() const {
- return test_file_modification_time_;
+ void TouchFile(const std::string& file_name, base::TimeDelta delta) override {
+ base::FilePath path = test_dir().AppendASCII(file_name);
+ base::File::Info file_info;
+ ASSERT_EQ(base::File::FILE_OK, file_util_->GetFileInfo(path, &file_info));
+ ASSERT_EQ(base::File::FILE_OK,
+ file_util_->Touch(path, file_info.last_accessed,
+ file_info.last_modified + delta));
}
+ base::FilePath test_dir() const { return dir_.GetPath(); }
+
private:
- base::test::TaskEnvironment task_environment_;
- base::ScopedTempDir file_system_directory_;
+ base::ScopedTempDir dir_;
std::unique_ptr<ObfuscatedFileUtilMemoryDelegate> file_util_;
- base::Time test_file_modification_time_;
};
-TEST_F(MemoryFileStreamReaderTest, NonExistent) {
- base::FilePath nonexistent_path = test_dir().AppendASCII("nonexistent");
- std::unique_ptr<FileStreamReader> reader(
- CreateFileReader(nonexistent_path, 0, base::Time()));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, 10, &result);
- ASSERT_EQ(net::ERR_FILE_NOT_FOUND, result);
- ASSERT_EQ(0U, data.size());
-}
-
-TEST_F(MemoryFileStreamReaderTest, Empty) {
- base::FilePath empty_path = test_dir().AppendASCII("empty");
- bool created;
- EXPECT_EQ(base::File::FILE_OK,
- file_util()->EnsureFileExists(empty_path, &created));
-
- std::unique_ptr<FileStreamReader> reader(
- CreateFileReader(empty_path, 0, base::Time()));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, 10, &result);
- ASSERT_EQ(net::OK, result);
- ASSERT_EQ(0U, data.size());
-
- int64_t length_result = GetLengthFromReader(reader.get());
- ASSERT_EQ(0, length_result);
-}
-
-TEST_F(MemoryFileStreamReaderTest, GetLengthNormal) {
- std::unique_ptr<FileStreamReader> reader(
- CreateFileReader(test_path(), 0, test_file_modification_time()));
- int64_t result = GetLengthFromReader(reader.get());
- ASSERT_EQ(kTestDataSize, result);
-}
-
-TEST_F(MemoryFileStreamReaderTest, GetLengthAfterModified) {
- // Touch file so that the file's modification time becomes different
- // from what we expect.
- TouchTestFile(base::TimeDelta::FromSeconds(-1));
-
- std::unique_ptr<FileStreamReader> reader(
- CreateFileReader(test_path(), 0, test_file_modification_time()));
- int64_t result = GetLengthFromReader(reader.get());
- ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result);
-}
-
-TEST_F(MemoryFileStreamReaderTest, GetLengthAfterModifiedWithNoExpectedTime) {
- // Touch file so that the file's modification time becomes different
- // from what we expect.
- TouchTestFile(base::TimeDelta::FromSeconds(-1));
-
- std::unique_ptr<FileStreamReader> reader(
- CreateFileReader(test_path(), 0, base::Time()));
- int64_t result = GetLengthFromReader(reader.get());
- ASSERT_EQ(kTestDataSize, result);
-}
-
-TEST_F(MemoryFileStreamReaderTest, GetLengthWithOffset) {
- std::unique_ptr<FileStreamReader> reader(
- CreateFileReader(test_path(), 3, base::Time()));
- int64_t result = GetLengthFromReader(reader.get());
- // Initial offset does not affect the result of GetLength.
- ASSERT_EQ(kTestDataSize, result);
-}
-
-TEST_F(MemoryFileStreamReaderTest, ReadNormal) {
- std::unique_ptr<FileStreamReader> reader(
- CreateFileReader(test_path(), 0, test_file_modification_time()));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, kTestDataSize, &result);
- ASSERT_EQ(net::OK, result);
- ASSERT_EQ(kTestData, data);
-}
-
-TEST_F(MemoryFileStreamReaderTest, ReadAfterModified) {
- // Touch file so that the file's modification time becomes different
- // from what we expect. Note that the resolution on some filesystems
- // is 1s so we can't test with deltas less than that.
- TouchTestFile(base::TimeDelta::FromSeconds(-1));
- std::unique_ptr<FileStreamReader> reader(
- CreateFileReader(test_path(), 0, test_file_modification_time()));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, kTestDataSize, &result);
- EXPECT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result);
- EXPECT_EQ(0U, data.size());
-}
-
-TEST_F(MemoryFileStreamReaderTest, ReadAfterModifiedLessThanThreshold) {
- // Due to precision loss converting int64_t->double->int64_t (e.g. through
- // Blink) the expected/actual time may vary by microseconds. With
- // modification time delta < 10us this should work.
- TouchTestFile(base::TimeDelta::FromMicroseconds(1));
- std::unique_ptr<FileStreamReader> reader(
- CreateFileReader(test_path(), 0, test_file_modification_time()));
- int result = 0;
- std::string data;
-
- ReadFromReader(reader.get(), &data, kTestDataSize, &result);
- EXPECT_EQ(net::OK, result);
- EXPECT_EQ(kTestData, data);
-}
-
-TEST_F(MemoryFileStreamReaderTest, ReadAfterModifiedWithMatchingTimes) {
- TouchTestFile(base::TimeDelta());
- std::unique_ptr<FileStreamReader> reader(
- CreateFileReader(test_path(), 0, test_file_modification_time()));
- int result = 0;
- std::string data;
-
- ReadFromReader(reader.get(), &data, kTestDataSize, &result);
- EXPECT_EQ(net::OK, result);
- EXPECT_EQ(kTestData, data);
-}
-
-TEST_F(MemoryFileStreamReaderTest, ReadAfterModifiedWithoutExpectedTime) {
- TouchTestFile(base::TimeDelta());
- std::unique_ptr<FileStreamReader> reader(
- CreateFileReader(test_path(), 0, base::Time()));
- int result = 0;
- std::string data;
-
- ReadFromReader(reader.get(), &data, kTestDataSize, &result);
- EXPECT_EQ(net::OK, result);
- EXPECT_EQ(kTestData, data);
-}
-
-TEST_F(MemoryFileStreamReaderTest, ReadWithOffset) {
- std::unique_ptr<FileStreamReader> reader(
- CreateFileReader(test_path(), 3, base::Time()));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, kTestDataSize, &result);
- ASSERT_EQ(net::OK, result);
- ASSERT_EQ(&kTestData[3], data);
-}
-
-TEST_F(MemoryFileStreamReaderTest, ReadWithNegativeOffset) {
- std::unique_ptr<FileStreamReader> reader(
- CreateFileReader(test_path(), -1, base::Time()));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, 1, &result);
- ASSERT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, result);
-}
-
-TEST_F(MemoryFileStreamReaderTest, ReadWithOffsetLargerThanFile) {
- std::unique_ptr<FileStreamReader> reader(
- CreateFileReader(test_path(), kTestDataSize + 1, base::Time()));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, 1, &result);
- ASSERT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, result);
-}
+INSTANTIATE_TYPED_TEST_SUITE_P(Memory,
+ FileStreamReaderTypedTest,
+ MemoryFileStreamReaderTest);
} // namespace storage
diff --git a/chromium/storage/browser/file_system/memory_file_stream_writer.cc b/chromium/storage/browser/file_system/memory_file_stream_writer.cc
index b36c4b5e4bb..7f45e02a310 100644
--- a/chromium/storage/browser/file_system/memory_file_stream_writer.cc
+++ b/chromium/storage/browser/file_system/memory_file_stream_writer.cc
@@ -34,6 +34,7 @@ MemoryFileStreamWriter::MemoryFileStreamWriter(
file_path_(file_path),
offset_(initial_offset) {
DCHECK(memory_file_util_.MaybeValid());
+ has_pending_operation_ = false;
}
MemoryFileStreamWriter::~MemoryFileStreamWriter() = default;
@@ -41,6 +42,11 @@ MemoryFileStreamWriter::~MemoryFileStreamWriter() = default;
int MemoryFileStreamWriter::Write(net::IOBuffer* buf,
int buf_len,
net::CompletionOnceCallback callback) {
+ DCHECK(!has_pending_operation_);
+ DCHECK(cancel_callback_.is_null());
+
+ has_pending_operation_ = true;
+
task_runner_->PostTaskAndReplyWithResult(
FROM_HERE,
base::BindOnce(
@@ -66,17 +72,43 @@ int MemoryFileStreamWriter::Write(net::IOBuffer* buf,
void MemoryFileStreamWriter::OnWriteCompleted(
net::CompletionOnceCallback callback,
int result) {
+ DCHECK(has_pending_operation_);
+
+ if (CancelIfRequested())
+ return;
+ has_pending_operation_ = false;
+
if (result > 0)
offset_ += result;
std::move(callback).Run(result);
}
-int MemoryFileStreamWriter::Cancel(net::CompletionOnceCallback /*callback*/) {
- return net::ERR_UNEXPECTED;
+int MemoryFileStreamWriter::Cancel(net::CompletionOnceCallback callback) {
+ if (!has_pending_operation_)
+ return net::ERR_UNEXPECTED;
+
+ DCHECK(!callback.is_null());
+ cancel_callback_ = std::move(callback);
+ return net::ERR_IO_PENDING;
}
int MemoryFileStreamWriter::Flush(net::CompletionOnceCallback /*callback*/) {
+ DCHECK(!has_pending_operation_);
+ DCHECK(cancel_callback_.is_null());
+
return net::OK;
}
+
+bool MemoryFileStreamWriter::CancelIfRequested() {
+ DCHECK(has_pending_operation_);
+
+ if (cancel_callback_.is_null())
+ return false;
+
+ has_pending_operation_ = false;
+ std::move(cancel_callback_).Run(net::OK);
+ return true;
+}
+
} // namespace storage
diff --git a/chromium/storage/browser/file_system/memory_file_stream_writer.h b/chromium/storage/browser/file_system/memory_file_stream_writer.h
index 74f6213f0f8..625a18edef3 100644
--- a/chromium/storage/browser/file_system/memory_file_stream_writer.h
+++ b/chromium/storage/browser/file_system/memory_file_stream_writer.h
@@ -37,14 +37,20 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) MemoryFileStreamWriter
void OnWriteCompleted(net::CompletionOnceCallback callback, int result);
+ // Stops the in-flight operation and calls |cancel_callback_| if it has been
+ // set by Cancel() for the current operation.
+ bool CancelIfRequested();
+
base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util_;
const scoped_refptr<base::TaskRunner> task_runner_;
const base::FilePath file_path_;
int64_t offset_;
- base::WeakPtrFactory<MemoryFileStreamWriter> weak_factory_{this};
+ bool has_pending_operation_;
+ net::CompletionOnceCallback cancel_callback_;
+ base::WeakPtrFactory<MemoryFileStreamWriter> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(MemoryFileStreamWriter);
};
diff --git a/chromium/storage/browser/file_system/memory_file_stream_writer_unittest.cc b/chromium/storage/browser/file_system/memory_file_stream_writer_unittest.cc
index 44342a33c66..f15892c57e0 100644
--- a/chromium/storage/browser/file_system/memory_file_stream_writer_unittest.cc
+++ b/chromium/storage/browser/file_system/memory_file_stream_writer_unittest.cc
@@ -16,6 +16,7 @@
#include "base/test/task_environment.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
+#include "net/base/test_completion_callback.h"
#include "storage/browser/file_system/file_stream_test_utils.h"
#include "storage/browser/file_system/file_stream_writer.h"
#include "storage/browser/file_system/obfuscated_file_util_memory_delegate.h"
@@ -23,6 +24,12 @@
namespace storage {
+namespace {
+void NeverCalled(int unused) {
+ ADD_FAILURE();
+}
+} // namespace
+
class MemoryFileStreamWriterTest : public testing::Test {
public:
MemoryFileStreamWriterTest() {}
@@ -159,6 +166,25 @@ TEST_F(MemoryFileStreamWriterTest, CancelAfterFinishedOperation) {
EXPECT_EQ("foo", GetFileContent(path));
}
+TEST_F(MemoryFileStreamWriterTest, CancelWrite) {
+ base::FilePath path = Path("file_a");
+ bool created;
+ EXPECT_EQ(base::File::FILE_OK, file_util()->EnsureFileExists(path, &created));
+
+ std::unique_ptr<FileStreamWriter> writer(CreateWriter(path, 0));
+
+ scoped_refptr<net::StringIOBuffer> buffer(
+ base::MakeRefCounted<net::StringIOBuffer>("xxx"));
+ int result =
+ writer->Write(buffer.get(), buffer->size(), base::BindOnce(&NeverCalled));
+ ASSERT_EQ(net::ERR_IO_PENDING, result);
+
+ net::TestCompletionCallback callback;
+ writer->Cancel(callback.callback());
+ int cancel_result = callback.WaitForResult();
+ EXPECT_EQ(net::OK, cancel_result);
+}
+
TEST_F(MemoryFileStreamWriterTest, FlushBeforeWriting) {
base::FilePath path = Path("file_a");
bool created;
diff --git a/chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc b/chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc
index 3a3d8563e3c..ec25aacf576 100644
--- a/chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc
+++ b/chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc
@@ -456,8 +456,13 @@ int ObfuscatedFileUtilMemoryDelegate::ReadFile(const base::FilePath& path,
return net::ERR_FILE_NOT_FOUND;
int64_t remaining = dp->entry->file_content.size() - offset;
- if (offset < 0 || remaining < 0)
- return net::ERR_REQUEST_RANGE_NOT_SATISFIABLE;
+ if (offset < 0)
+ return net::ERR_INVALID_ARGUMENT;
+
+ // Seeking past the end of the file is ok, but returns nothing.
+ // This matches FileStream::Context behavior.
+ if (remaining < 0)
+ return 0;
if (buf_len > remaining)
buf_len = static_cast<int>(remaining);
diff --git a/chromium/storage/browser/file_system/sandbox_file_stream_writer.cc b/chromium/storage/browser/file_system/sandbox_file_stream_writer.cc
index ea0c93a6330..3f29d3c707e 100644
--- a/chromium/storage/browser/file_system/sandbox_file_stream_writer.cc
+++ b/chromium/storage/browser/file_system/sandbox_file_stream_writer.cc
@@ -140,7 +140,7 @@ void SandboxFileStreamWriter::DidCreateSnapshotFile(
}
file_size_ = file_info.size;
if (initial_offset_ > file_size_) {
- // We should not be writing pass the end of the file.
+ // We should not be writing past the end of the file.
std::move(callback).Run(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
return;
}
diff --git a/chromium/storage/browser/quota/quota_database.cc b/chromium/storage/browser/quota/quota_database.cc
index b65429ae2db..7322359b68c 100644
--- a/chromium/storage/browser/quota/quota_database.cc
+++ b/chromium/storage/browser/quota/quota_database.cc
@@ -470,20 +470,34 @@ bool QuotaDatabase::GetLRUOrigin(StorageType type,
return statement.Succeeded();
}
-bool QuotaDatabase::GetOriginsModifiedSince(StorageType type,
- std::set<url::Origin>* origins,
- base::Time modified_since) {
+bool QuotaDatabase::GetOriginsModifiedBetween(StorageType type,
+ std::set<url::Origin>* origins,
+ base::Time begin,
+ base::Time end) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(origins);
if (!LazyOpen(false))
return false;
- const char* kSql = "SELECT origin FROM OriginInfoTable"
- " WHERE type = ? AND last_modified_time >= ?";
+ DCHECK(!begin.is_max() && end != base::Time());
+ static constexpr char kSqlQuerySince[] =
+ "SELECT origin FROM OriginInfoTable"
+ " WHERE type = ? AND last_modified_time >= ?";
- sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ static constexpr char kSqlQueryBetween[] =
+ "SELECT origin FROM OriginInfoTable"
+ " WHERE type = ? AND last_modified_time >= ? AND last_modified_time < ?";
+
+ sql::Statement statement;
+ if (end.is_max()) {
+ statement.Assign(db_->GetCachedStatement(SQL_FROM_HERE, kSqlQuerySince));
+ } else {
+ statement.Assign(db_->GetCachedStatement(SQL_FROM_HERE, kSqlQueryBetween));
+ }
statement.BindInt(0, static_cast<int>(type));
- statement.BindInt64(1, TimeToSqlValue(modified_since));
+ statement.BindInt64(1, TimeToSqlValue(begin));
+ if (!end.is_max())
+ statement.BindInt64(2, TimeToSqlValue(end));
origins->clear();
while (statement.Step())
diff --git a/chromium/storage/browser/quota/quota_database.h b/chromium/storage/browser/quota/quota_database.h
index 286754e7268..64cbe16ec6e 100644
--- a/chromium/storage/browser/quota/quota_database.h
+++ b/chromium/storage/browser/quota/quota_database.h
@@ -124,10 +124,12 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDatabase {
base::Optional<url::Origin>* origin);
// Populates |origins| with the ones that have been modified since
- // the |modified_since|. Returns whether the operation succeeded.
- bool GetOriginsModifiedSince(blink::mojom::StorageType type,
- std::set<url::Origin>* origins,
- base::Time modified_since);
+ // the |begin| and until the |end|. Returns whether the
+ // operation succeeded.
+ bool GetOriginsModifiedBetween(blink::mojom::StorageType type,
+ std::set<url::Origin>* origins,
+ base::Time begin,
+ base::Time end);
// Returns false if SetOriginDatabaseBootstrapped has never
// been called before, which means existing origins may not have been
diff --git a/chromium/storage/browser/quota/quota_database_unittest.cc b/chromium/storage/browser/quota/quota_database_unittest.cc
index 81edd2ab2e9..0310fda6708 100644
--- a/chromium/storage/browser/quota/quota_database_unittest.cc
+++ b/chromium/storage/browser/quota/quota_database_unittest.cc
@@ -219,12 +219,13 @@ class QuotaDatabaseTest : public testing::Test {
EXPECT_FALSE(origin.has_value());
}
- void OriginLastModifiedSince(const base::FilePath& kDbFile) {
+ void OriginLastModifiedBetween(const base::FilePath& kDbFile) {
QuotaDatabase db(kDbFile);
ASSERT_TRUE(db.LazyOpen(true));
std::set<url::Origin> origins;
- EXPECT_TRUE(db.GetOriginsModifiedSince(kTemporary, &origins, base::Time()));
+ EXPECT_TRUE(db.GetOriginsModifiedBetween(kTemporary, &origins, base::Time(),
+ base::Time::Max()));
EXPECT_TRUE(origins.empty());
const url::Origin kOrigin1 = url::Origin::Create(GURL("http://a/"));
@@ -239,37 +240,58 @@ class QuotaDatabaseTest : public testing::Test {
EXPECT_TRUE(db.SetOriginLastModifiedTime(
kOrigin3, kTemporary, QuotaDatabase::TimeFromSqlValue(20)));
- EXPECT_TRUE(db.GetOriginsModifiedSince(kTemporary, &origins, base::Time()));
+ EXPECT_TRUE(db.GetOriginsModifiedBetween(kTemporary, &origins, base::Time(),
+ base::Time::Max()));
EXPECT_EQ(3U, origins.size());
EXPECT_EQ(1U, origins.count(kOrigin1));
EXPECT_EQ(1U, origins.count(kOrigin2));
EXPECT_EQ(1U, origins.count(kOrigin3));
- EXPECT_TRUE(db.GetOriginsModifiedSince(kTemporary, &origins,
- QuotaDatabase::TimeFromSqlValue(5)));
+ EXPECT_TRUE(db.GetOriginsModifiedBetween(kTemporary, &origins,
+ QuotaDatabase::TimeFromSqlValue(5),
+ base::Time::Max()));
EXPECT_EQ(2U, origins.size());
EXPECT_EQ(0U, origins.count(kOrigin1));
EXPECT_EQ(1U, origins.count(kOrigin2));
EXPECT_EQ(1U, origins.count(kOrigin3));
- EXPECT_TRUE(db.GetOriginsModifiedSince(
- kTemporary, &origins, QuotaDatabase::TimeFromSqlValue(15)));
+ EXPECT_TRUE(db.GetOriginsModifiedBetween(
+ kTemporary, &origins, QuotaDatabase::TimeFromSqlValue(15),
+ base::Time::Max()));
EXPECT_EQ(1U, origins.size());
EXPECT_EQ(0U, origins.count(kOrigin1));
EXPECT_EQ(0U, origins.count(kOrigin2));
EXPECT_EQ(1U, origins.count(kOrigin3));
- EXPECT_TRUE(db.GetOriginsModifiedSince(
- kTemporary, &origins, QuotaDatabase::TimeFromSqlValue(25)));
+ EXPECT_TRUE(db.GetOriginsModifiedBetween(
+ kTemporary, &origins, QuotaDatabase::TimeFromSqlValue(25),
+ base::Time::Max()));
EXPECT_TRUE(origins.empty());
+ EXPECT_TRUE(db.GetOriginsModifiedBetween(
+ kTemporary, &origins, QuotaDatabase::TimeFromSqlValue(5),
+ QuotaDatabase::TimeFromSqlValue(15)));
+ EXPECT_EQ(1U, origins.size());
+ EXPECT_EQ(0U, origins.count(kOrigin1));
+ EXPECT_EQ(1U, origins.count(kOrigin2));
+ EXPECT_EQ(0U, origins.count(kOrigin3));
+
+ EXPECT_TRUE(db.GetOriginsModifiedBetween(
+ kTemporary, &origins, QuotaDatabase::TimeFromSqlValue(0),
+ QuotaDatabase::TimeFromSqlValue(20)));
+ EXPECT_EQ(2U, origins.size());
+ EXPECT_EQ(1U, origins.count(kOrigin1));
+ EXPECT_EQ(1U, origins.count(kOrigin2));
+ EXPECT_EQ(0U, origins.count(kOrigin3));
+
// Update origin1's mod time but for persistent storage.
EXPECT_TRUE(db.SetOriginLastModifiedTime(
kOrigin1, kPersistent, QuotaDatabase::TimeFromSqlValue(30)));
// Must have no effects on temporary origins info.
- EXPECT_TRUE(db.GetOriginsModifiedSince(kTemporary, &origins,
- QuotaDatabase::TimeFromSqlValue(5)));
+ EXPECT_TRUE(db.GetOriginsModifiedBetween(kTemporary, &origins,
+ QuotaDatabase::TimeFromSqlValue(5),
+ base::Time::Max()));
EXPECT_EQ(2U, origins.size());
EXPECT_EQ(0U, origins.count(kOrigin1));
EXPECT_EQ(1U, origins.count(kOrigin2));
@@ -279,15 +301,17 @@ class QuotaDatabaseTest : public testing::Test {
EXPECT_TRUE(db.SetOriginLastModifiedTime(
kOrigin2, kPersistent, QuotaDatabase::TimeFromSqlValue(40)));
- EXPECT_TRUE(db.GetOriginsModifiedSince(
- kPersistent, &origins, QuotaDatabase::TimeFromSqlValue(25)));
+ EXPECT_TRUE(db.GetOriginsModifiedBetween(
+ kPersistent, &origins, QuotaDatabase::TimeFromSqlValue(25),
+ base::Time::Max()));
EXPECT_EQ(2U, origins.size());
EXPECT_EQ(1U, origins.count(kOrigin1));
EXPECT_EQ(1U, origins.count(kOrigin2));
EXPECT_EQ(0U, origins.count(kOrigin3));
- EXPECT_TRUE(db.GetOriginsModifiedSince(
- kPersistent, &origins, QuotaDatabase::TimeFromSqlValue(35)));
+ EXPECT_TRUE(db.GetOriginsModifiedBetween(
+ kPersistent, &origins, QuotaDatabase::TimeFromSqlValue(35),
+ base::Time::Max()));
EXPECT_EQ(1U, origins.size());
EXPECT_EQ(0U, origins.count(kOrigin1));
EXPECT_EQ(1U, origins.count(kOrigin2));
@@ -614,12 +638,12 @@ TEST_F(QuotaDatabaseTest, OriginLastAccessTimeLRU) {
OriginLastAccessTimeLRU(base::FilePath());
}
-TEST_F(QuotaDatabaseTest, OriginLastModifiedSince) {
+TEST_F(QuotaDatabaseTest, OriginLastModifiedBetween) {
base::ScopedTempDir data_dir;
ASSERT_TRUE(data_dir.CreateUniqueTempDir());
const base::FilePath kDbFile = data_dir.GetPath().AppendASCII(kDBFileName);
- OriginLastModifiedSince(kDbFile);
- OriginLastModifiedSince(base::FilePath());
+ OriginLastModifiedBetween(kDbFile);
+ OriginLastModifiedBetween(base::FilePath());
}
TEST_F(QuotaDatabaseTest, OriginLastEvicted) {
diff --git a/chromium/storage/browser/quota/quota_features.cc b/chromium/storage/browser/quota/quota_features.cc
index 241852ad512..5fe119cfd43 100644
--- a/chromium/storage/browser/quota/quota_features.cc
+++ b/chromium/storage/browser/quota/quota_features.cc
@@ -8,32 +8,16 @@ namespace storage {
namespace features {
-const base::Feature kQuotaExpandPoolSize{"QuotaExpandPoolSize",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
-constexpr base::FeatureParam<double> kExperimentalPoolSizeRatio{
- &kQuotaExpandPoolSize, "PoolSizeRatio", 0.8};
-
-constexpr base::FeatureParam<double> kPerHostRatio{&kQuotaExpandPoolSize,
- "PerHostRatio", 0.75};
-
-// QuotaUnlimitedPoolSize removes limitations around disk space consumption with
-// respect to client-side storage web platform APIs. When enabled, quota will
-// set no limit on how much space a single origin can consume, as well as
-// removing limits on how much disk space the temporary pool can consume.
-const base::Feature kQuotaUnlimitedPoolSize{"QuotaUnlimitedPoolSize",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
// IncognitoDynamicQuota enables dynamic assignment of quota to incognito mode
// based on the physical memory size and removes the fixed upper cap for it.
const base::Feature kIncognitoDynamicQuota{"IncognitoDynamicQuota",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
// Dynamic quota for incognito mode would be set by a random fraction of
// physical memory, between |IncognitoQuotaRatioLowerBound| and
// |IncognitoQuotaRatioUpperBound|.
constexpr base::FeatureParam<double> kIncognitoQuotaRatioLowerBound{
- &kIncognitoDynamicQuota, "IncognitoQuotaRatioLowerBound", 0.1};
+ &kIncognitoDynamicQuota, "IncognitoQuotaRatioLowerBound", 0.15};
constexpr base::FeatureParam<double> kIncognitoQuotaRatioUpperBound{
&kIncognitoDynamicQuota, "IncognitoQuotaRatioUpperBound", 0.2};
diff --git a/chromium/storage/browser/quota/quota_features.h b/chromium/storage/browser/quota/quota_features.h
index 1ddc03059b7..6364087068d 100644
--- a/chromium/storage/browser/quota/quota_features.h
+++ b/chromium/storage/browser/quota/quota_features.h
@@ -14,14 +14,6 @@ namespace storage {
namespace features {
COMPONENT_EXPORT(STORAGE_BROWSER)
-extern const base::Feature kQuotaExpandPoolSize;
-extern const base::FeatureParam<double> kExperimentalPoolSizeRatio;
-extern const base::FeatureParam<double> kPerHostRatio;
-
-COMPONENT_EXPORT(STORAGE_BROWSER)
-extern const base::Feature kQuotaUnlimitedPoolSize;
-
-COMPONENT_EXPORT(STORAGE_BROWSER)
extern const base::Feature kIncognitoDynamicQuota;
extern const base::FeatureParam<double> kIncognitoQuotaRatioLowerBound;
extern const base::FeatureParam<double> kIncognitoQuotaRatioUpperBound;
diff --git a/chromium/storage/browser/quota/quota_manager.cc b/chromium/storage/browser/quota/quota_manager.cc
index fcee14568fe..8bb8ee893da 100644
--- a/chromium/storage/browser/quota/quota_manager.cc
+++ b/chromium/storage/browser/quota/quota_manager.cc
@@ -53,7 +53,7 @@ constexpr int64_t kReportHistogramInterval = 60 * 60 * 1000; // 1 hour
// Take action on write errors if there is <= 2% disk space
// available.
-constexpr double kStoragePressureThresholdPercent = 2;
+constexpr double kStoragePressureThresholdRatio = 0.02;
// Limit how frequently QuotaManager polls for free disk space when
// only using that information to identify storage pressure.
@@ -774,22 +774,23 @@ class QuotaManager::StorageCleanupHelper : public QuotaTask {
// time frame.
//
// This class is granted ownership of itself when it is passed to
-// DidGetModifiedSince() via base::Owned(). When the closure for said function
-// goes out of scope, the object is deleted.
-// This is a thread-safe class.
+// DidGetModifiedBetween() via base::Owned(). When the closure for said
+// function goes out of scope, the object is deleted. This is a thread-safe
+// class.
class QuotaManager::GetModifiedSinceHelper {
public:
- bool GetModifiedSinceOnDBThread(StorageType type,
- base::Time modified_since,
- QuotaDatabase* database) {
+ bool GetModifiedBetweenOnDBThread(StorageType type,
+ base::Time begin,
+ base::Time end,
+ QuotaDatabase* database) {
DCHECK(database);
- return database->GetOriginsModifiedSince(type, &origins_, modified_since);
+ return database->GetOriginsModifiedBetween(type, &origins_, begin, end);
}
- void DidGetModifiedSince(const base::WeakPtr<QuotaManager>& manager,
- GetOriginsCallback callback,
- StorageType type,
- bool success) {
+ void DidGetModifiedBetween(const base::WeakPtr<QuotaManager>& manager,
+ GetOriginsCallback callback,
+ StorageType type,
+ bool success) {
if (!manager) {
// The operation was aborted.
std::move(callback).Run(std::set<url::Origin>(), type);
@@ -1189,17 +1190,18 @@ bool QuotaManager::IsStorageUnlimited(const url::Origin& origin,
special_storage_policy_->IsStorageUnlimited(origin.GetURL());
}
-void QuotaManager::GetOriginsModifiedSince(StorageType type,
- base::Time modified_since,
- GetOriginsCallback callback) {
+void QuotaManager::GetOriginsModifiedBetween(StorageType type,
+ base::Time begin,
+ base::Time end,
+ GetOriginsCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
LazyInitialize();
GetModifiedSinceHelper* helper = new GetModifiedSinceHelper;
PostTaskAndReplyWithResultForDBThread(
FROM_HERE,
- base::BindOnce(&GetModifiedSinceHelper::GetModifiedSinceOnDBThread,
- base::Unretained(helper), type, modified_since),
- base::BindOnce(&GetModifiedSinceHelper::DidGetModifiedSince,
+ base::BindOnce(&GetModifiedSinceHelper::GetModifiedBetweenOnDBThread,
+ base::Unretained(helper), type, begin, end),
+ base::BindOnce(&GetModifiedSinceHelper::DidGetModifiedBetween,
base::Owned(helper), weak_factory_.GetWeakPtr(),
std::move(callback), type));
}
@@ -1485,7 +1487,7 @@ void QuotaManager::MaybeRunStoragePressureCallback(const url::Origin& origin,
return;
}
- if (100 * available_space < kStoragePressureThresholdPercent * total_space) {
+ if (available_space < kStoragePressureThresholdRatio * total_space) {
storage_pressure_callback_.Run(std::move(origin));
}
}
diff --git a/chromium/storage/browser/quota/quota_manager.h b/chromium/storage/browser/quota/quota_manager.h
index 70e855de073..2748c4f7724 100644
--- a/chromium/storage/browser/quota/quota_manager.h
+++ b/chromium/storage/browser/quota/quota_manager.h
@@ -241,9 +241,10 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager
bool IsStorageUnlimited(const url::Origin& origin,
blink::mojom::StorageType type) const;
- virtual void GetOriginsModifiedSince(blink::mojom::StorageType type,
- base::Time modified_since,
- GetOriginsCallback callback);
+ virtual void GetOriginsModifiedBetween(blink::mojom::StorageType type,
+ base::Time begin,
+ base::Time end,
+ GetOriginsCallback callback);
bool ResetUsageTracker(blink::mojom::StorageType type);
diff --git a/chromium/storage/browser/quota/quota_manager_proxy.cc b/chromium/storage/browser/quota/quota_manager_proxy.cc
index 1cb5cd62b7a..f331f574255 100644
--- a/chromium/storage/browser/quota/quota_manager_proxy.cc
+++ b/chromium/storage/browser/quota/quota_manager_proxy.cc
@@ -41,11 +41,11 @@ void QuotaManagerProxy::RegisterClient(
scoped_refptr<QuotaClient> client,
QuotaClientType client_type,
const std::vector<blink::mojom::StorageType>& storage_types) {
- if (!io_thread_->BelongsToCurrentThread() &&
- io_thread_->PostTask(
- FROM_HERE,
- base::BindOnce(&QuotaManagerProxy::RegisterClient, this,
- std::move(client), client_type, storage_types))) {
+ if (!io_thread_->BelongsToCurrentThread()) {
+ io_thread_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&QuotaManagerProxy::RegisterClient, this,
+ std::move(client), client_type, storage_types));
return;
}
diff --git a/chromium/storage/browser/quota/quota_manager_unittest.cc b/chromium/storage/browser/quota/quota_manager_unittest.cc
index 0b093668d80..9837c45e989 100644
--- a/chromium/storage/browser/quota/quota_manager_unittest.cc
+++ b/chromium/storage/browser/quota/quota_manager_unittest.cc
@@ -306,11 +306,13 @@ class QuotaManagerTest : public testing::Test {
quota_manager_->NotifyOriginNoLongerInUse(origin);
}
- void GetOriginsModifiedSince(StorageType type, base::Time modified_since) {
+ void GetOriginsModifiedBetween(StorageType type,
+ base::Time begin,
+ base::Time end) {
modified_origins_.clear();
modified_origins_type_ = StorageType::kUnknown;
- quota_manager_->GetOriginsModifiedSince(
- type, modified_since,
+ quota_manager_->GetOriginsModifiedBetween(
+ type, begin, end,
base::BindOnce(&QuotaManagerTest::DidGetModifiedOrigins,
weak_factory_.GetWeakPtr()));
}
@@ -2302,7 +2304,7 @@ TEST_F(QuotaManagerTest, GetLRUOriginWithOriginInUse) {
EXPECT_EQ(ToOrigin("http://a.com/"), *eviction_origin());
}
-TEST_F(QuotaManagerTest, GetOriginsModifiedSince) {
+TEST_F(QuotaManagerTest, GetOriginsModifiedBetween) {
static const MockOriginData kData[] = {
{ "http://a.com/", kTemp, 0 },
{ "http://a.com:1/", kTemp, 0 },
@@ -2315,7 +2317,7 @@ TEST_F(QuotaManagerTest, GetOriginsModifiedSince) {
{blink::mojom::StorageType::kTemporary,
blink::mojom::StorageType::kPersistent});
- GetOriginsModifiedSince(kTemp, base::Time());
+ GetOriginsModifiedBetween(kTemp, base::Time(), base::Time::Max());
task_environment_.RunUntilIdle();
EXPECT_TRUE(modified_origins().empty());
EXPECT_EQ(modified_origins_type(), kTemp);
@@ -2329,7 +2331,7 @@ TEST_F(QuotaManagerTest, GetOriginsModifiedSince) {
client->ModifyOriginAndNotify(ToOrigin("http://c.com/"), kTemp, 10);
base::Time time3 = client->IncrementMockTime();
- GetOriginsModifiedSince(kTemp, time1);
+ GetOriginsModifiedBetween(kTemp, time1, base::Time::Max());
task_environment_.RunUntilIdle();
EXPECT_EQ(4U, modified_origins().size());
EXPECT_EQ(modified_origins_type(), kTemp);
@@ -2338,18 +2340,18 @@ TEST_F(QuotaManagerTest, GetOriginsModifiedSince) {
EXPECT_EQ(1U, modified_origins().count(ToOrigin(data.origin)));
}
- GetOriginsModifiedSince(kTemp, time2);
+ GetOriginsModifiedBetween(kTemp, time2, base::Time::Max());
task_environment_.RunUntilIdle();
EXPECT_EQ(2U, modified_origins().size());
- GetOriginsModifiedSince(kTemp, time3);
+ GetOriginsModifiedBetween(kTemp, time3, base::Time::Max());
task_environment_.RunUntilIdle();
EXPECT_TRUE(modified_origins().empty());
EXPECT_EQ(modified_origins_type(), kTemp);
client->ModifyOriginAndNotify(ToOrigin("http://a.com/"), kTemp, 10);
- GetOriginsModifiedSince(kTemp, time3);
+ GetOriginsModifiedBetween(kTemp, time3, base::Time::Max());
task_environment_.RunUntilIdle();
EXPECT_EQ(1U, modified_origins().size());
EXPECT_EQ(1U, modified_origins().count(ToOrigin("http://a.com/")));
diff --git a/chromium/storage/browser/quota/quota_settings.cc b/chromium/storage/browser/quota/quota_settings.cc
index d5f67095528..27c280b3638 100644
--- a/chromium/storage/browser/quota/quota_settings.cc
+++ b/chromium/storage/browser/quota/quota_settings.cc
@@ -26,6 +26,8 @@ namespace {
const int64_t kMBytes = 1024 * 1024;
const int kRandomizedPercentage = 10;
+const double kDefaultPerHostRatio = 0.75;
+const double kDefaultPoolSizeRatio = 0.8;
// Skews |value| by +/- |percent|.
int64_t RandomizeByPercent(int64_t value, int percent) {
@@ -74,10 +76,7 @@ base::Optional<QuotaSettings> CalculateNominalDynamicSettings(
// The fraction of the device's storage the browser is willing to use for
// temporary storage.
- const double kTemporaryPoolSizeRatio =
- base::FeatureList::IsEnabled(features::kQuotaUnlimitedPoolSize)
- ? 1.0
- : features::kExperimentalPoolSizeRatio.Get();
+ const double kTemporaryPoolSizeRatio = kDefaultPoolSizeRatio;
// The amount of the device's storage the browser attempts to
// keep free. If there is less than this amount of storage free
@@ -111,10 +110,7 @@ base::Optional<QuotaSettings> CalculateNominalDynamicSettings(
const double kMustRemainAvailableRatio = 0.01; // 1%
// The fraction of the temporary pool that can be utilized by a single host.
- const double kPerHostTemporaryRatio =
- base::FeatureList::IsEnabled(features::kQuotaUnlimitedPoolSize)
- ? 1.0
- : features::kPerHostRatio.Get();
+ const double kPerHostTemporaryRatio = kDefaultPerHostRatio;
// SessionOnly (or ephemeral) origins are allotted a fraction of what
// normal origins are provided, and the amount is capped to a hard limit.
diff --git a/chromium/storage/browser/quota/quota_settings_unittest.cc b/chromium/storage/browser/quota/quota_settings_unittest.cc
index 34fb66ea801..25ae21522c9 100644
--- a/chromium/storage/browser/quota/quota_settings_unittest.cc
+++ b/chromium/storage/browser/quota/quota_settings_unittest.cc
@@ -140,48 +140,6 @@ TEST_F(QuotaSettingsTest, Default) {
EXPECT_TRUE(callback_executed);
}
-TEST_F(QuotaSettingsTest, ExpandedTempPool) {
- MockQuotaDeviceInfoHelper device_info_helper;
- ON_CALL(device_info_helper, AmountOfTotalDiskSpace(_))
- .WillByDefault(::testing::Return(2000));
- scoped_feature_list_.InitAndEnableFeatureWithParameters(
- features::kQuotaExpandPoolSize,
- {{"PoolSizeRatio", "0.75"}, {"PerHostRatio", "0.5"}});
-
- bool callback_executed = false;
- GetNominalDynamicSettings(
- profile_path(), false, &device_info_helper,
- base::BindLambdaForTesting([&](base::Optional<QuotaSettings> settings) {
- callback_executed = true;
- ASSERT_NE(settings, base::nullopt);
- // 1500 = 2000 * PoolSizeRatio
- EXPECT_EQ(settings->pool_size, 1500);
- // 750 = 1500 * PerHostRatio
- EXPECT_EQ(settings->per_host_quota, 750);
- }));
- task_environment_.RunUntilIdle();
- EXPECT_TRUE(callback_executed);
-}
-
-TEST_F(QuotaSettingsTest, UnlimitedTempPool) {
- MockQuotaDeviceInfoHelper device_info_helper;
- ON_CALL(device_info_helper, AmountOfTotalDiskSpace(_))
- .WillByDefault(::testing::Return(2000));
- scoped_feature_list_.InitAndEnableFeature(features::kQuotaUnlimitedPoolSize);
-
- bool callback_executed = false;
- GetNominalDynamicSettings(
- profile_path(), false, &device_info_helper,
- base::BindLambdaForTesting([&](base::Optional<QuotaSettings> settings) {
- callback_executed = true;
- ASSERT_NE(settings, base::nullopt);
- EXPECT_EQ(settings->pool_size, 2000);
- EXPECT_EQ(settings->per_host_quota, 2000);
- }));
- task_environment_.RunUntilIdle();
- EXPECT_TRUE(callback_executed);
-}
-
TEST_F(QuotaSettingsTest, IncognitoQuotaCapped) {
MockQuotaDeviceInfoHelper device_info_helper;
EXPECT_CALL(device_info_helper, AmountOfPhysicalMemory()).Times(1);