diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-08-30 10:22:43 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-08-30 12:36:28 +0000 |
commit | 271a6c3487a14599023a9106329505597638d793 (patch) | |
tree | e040d58ffc86c1480b79ca8528020ca9ec919bf8 /chromium/storage | |
parent | 7b2ffa587235a47d4094787d72f38102089f402a (diff) | |
download | qtwebengine-chromium-271a6c3487a14599023a9106329505597638d793.tar.gz |
BASELINE: Update Chromium to 77.0.3865.59
Change-Id: I1e89a5f3b009a9519a6705102ad65c92fe736f21
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/storage')
75 files changed, 556 insertions, 2184 deletions
diff --git a/chromium/storage/browser/BUILD.gn b/chromium/storage/browser/BUILD.gn index a66b3d82622..4298143a8ec 100644 --- a/chromium/storage/browser/BUILD.gn +++ b/chromium/storage/browser/BUILD.gn @@ -207,10 +207,6 @@ jumbo_component("browser") { "quota/quota_temporary_storage_evictor.h", "quota/special_storage_policy.cc", "quota/special_storage_policy.h", - "quota/storage_monitor.cc", - "quota/storage_monitor.h", - "quota/storage_observer.cc", - "quota/storage_observer.h", "quota/usage_tracker.cc", "quota/usage_tracker.h", ] @@ -222,7 +218,7 @@ jumbo_component("browser") { ] public_deps = [ - "//components/services/filesystem/public/interfaces", + "//components/services/filesystem/public/mojom", "//storage/common", ] deps = [ @@ -316,7 +312,6 @@ source_set("unittests") { "quota/quota_manager_unittest.cc", "quota/quota_settings_unittest.cc", "quota/quota_temporary_storage_evictor_unittest.cc", - "quota/storage_monitor_unittest.cc", "quota/usage_tracker_unittest.cc", "test/mock_quota_manager_unittest.cc", ] @@ -325,7 +320,7 @@ source_set("unittests") { ":browser", ":test_support", "//base/test:test_support", - "//components/services/filesystem/public/interfaces", + "//components/services/filesystem/public/mojom", "//mojo/core/embedder", "//net:test_support", "//services/network/public/cpp", @@ -345,6 +340,8 @@ jumbo_static_library("test_support") { "test/async_file_test_helper.h", "test/fake_blob.cc", "test/fake_blob.h", + "test/fake_blob_data_handle.cc", + "test/fake_blob_data_handle.h", "test/fake_progress_client.cc", "test/fake_progress_client.h", "test/fileapi_test_file_set.cc", 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 d76174db7cd..3203ee0ae34 100644 --- a/chromium/storage/browser/blob/blob_builder_from_stream_unittest.cc +++ b/chromium/storage/browser/blob/blob_builder_from_stream_unittest.cc @@ -17,8 +17,9 @@ #include "base/test/bind_test_util.h" #include "base/test/scoped_task_environment.h" #include "mojo/public/cpp/bindings/associated_binding.h" +#include "mojo/public/cpp/system/data_pipe_producer.h" #include "mojo/public/cpp/system/data_pipe_utils.h" -#include "mojo/public/cpp/system/string_data_pipe_producer.h" +#include "mojo/public/cpp/system/string_data_source.h" #include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_data_item.h" #include "storage/browser/blob/blob_storage_context.h" @@ -457,15 +458,15 @@ TEST_F(BlobBuilderFromStreamTestWithDelayedLimits, LargeStream) { builder.Start(kData.size(), std::move(pipe.consumer_handle), nullptr); context_->set_limits_for_testing(limits_); - auto data_producer = std::make_unique<mojo::StringDataPipeProducer>( - std::move(pipe.producer_handle)); + auto data_producer = + std::make_unique<mojo::DataPipeProducer>(std::move(pipe.producer_handle)); auto* producer_ptr = data_producer.get(); producer_ptr->Write( - kData, - mojo::StringDataPipeProducer::AsyncWritingMode:: - STRING_STAYS_VALID_UNTIL_COMPLETION, + std::make_unique<mojo::StringDataSource>( + kData, mojo::StringDataSource::AsyncWritingMode:: + STRING_STAYS_VALID_UNTIL_COMPLETION), base::BindOnce( - base::DoNothing::Once<std::unique_ptr<mojo::StringDataPipeProducer>, + base::DoNothing::Once<std::unique_ptr<mojo::DataPipeProducer>, MojoResult>(), std::move(data_producer))); pipe.producer_handle.reset(); diff --git a/chromium/storage/browser/blob/blob_data_builder.cc b/chromium/storage/browser/blob/blob_data_builder.cc index 61609cb38a6..fec479c3719 100644 --- a/chromium/storage/browser/blob/blob_data_builder.cc +++ b/chromium/storage/browser/blob/blob_data_builder.cc @@ -17,7 +17,6 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/time/time.h" -#include "net/disk_cache/disk_cache.h" #include "storage/browser/blob/blob_entry.h" #include "storage/browser/blob/blob_storage_registry.h" #include "storage/browser/blob/shareable_blob_data_item.h" @@ -27,12 +26,6 @@ using base::FilePath; namespace storage { -namespace { - -const static int kInvalidDiskCacheSideStreamIndex = -1; - -} // namespace - BlobDataBuilder::FutureData::FutureData(FutureData&&) = default; BlobDataBuilder::FutureData& BlobDataBuilder::FutureData::operator=( FutureData&&) = default; @@ -305,12 +298,10 @@ void BlobDataBuilder::SliceBlob(const BlobEntry* source, source_item->file_system_context()); break; } - case BlobDataItem::Type::kDiskCacheEntry: { - data_item = BlobDataItem::CreateDiskCacheEntry( - source_item->offset() + item_offset, read_size, - source_item->data_handle_, source_item->disk_cache_entry(), - source_item->disk_cache_stream_index(), - source_item->disk_cache_side_stream_index()); + case BlobDataItem::Type::kReadableDataHandle: { + data_item = BlobDataItem::CreateReadableDataHandle( + source_item->data_handle_, source_item->offset() + item_offset, + read_size); break; } } @@ -347,24 +338,11 @@ void BlobDataBuilder::AppendFileSystemFile( total_size_ += length; } -void BlobDataBuilder::AppendDiskCacheEntry( - scoped_refptr<DataHandle> data_handle, - disk_cache::Entry* disk_cache_entry, - int disk_cache_stream_index) { - AppendDiskCacheEntryWithSideData(std::move(data_handle), disk_cache_entry, - disk_cache_stream_index, - kInvalidDiskCacheSideStreamIndex); -} - -void BlobDataBuilder::AppendDiskCacheEntryWithSideData( - scoped_refptr<DataHandle> data_handle, - disk_cache::Entry* disk_cache_entry, - int disk_cache_stream_index, - int disk_cache_side_stream_index) { - auto item = BlobDataItem::CreateDiskCacheEntry( - 0u, disk_cache_entry->GetDataSize(disk_cache_stream_index), - std::move(data_handle), disk_cache_entry, disk_cache_stream_index, - disk_cache_side_stream_index); +void BlobDataBuilder::AppendReadableDataHandle( + scoped_refptr<DataHandle> data_handle) { + uint64_t length = data_handle->GetSize(); + auto item = BlobDataItem::CreateReadableDataHandle(std::move(data_handle), 0u, + length); total_size_ += item->length(); auto shareable_item = base::MakeRefCounted<ShareableBlobDataItem>( diff --git a/chromium/storage/browser/blob/blob_data_builder.h b/chromium/storage/browser/blob/blob_data_builder.h index 1c4b838839d..81b7da90109 100644 --- a/chromium/storage/browser/blob/blob_data_builder.h +++ b/chromium/storage/browser/blob/blob_data_builder.h @@ -23,10 +23,6 @@ #include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/file_system_context.h" -namespace disk_cache { -class Entry; -} - namespace storage { class BlobSliceTest; class BlobStorageContext; @@ -145,15 +141,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobDataBuilder { const base::Time& expected_modification_time, scoped_refptr<FileSystemContext> file_system_context); - void AppendDiskCacheEntry(scoped_refptr<DataHandle> data_handle, - disk_cache::Entry* disk_cache_entry, - int disk_cache_stream_index); - - // The content of the side data is accessible with BlobReader::ReadSideData(). - void AppendDiskCacheEntryWithSideData(scoped_refptr<DataHandle> data_handle, - disk_cache::Entry* disk_cache_entry, - int disk_cache_stream_index, - int disk_cache_side_stream_index); + void AppendReadableDataHandle(scoped_refptr<DataHandle> data_handle); void set_content_type(const std::string& content_type) { content_type_ = content_type; diff --git a/chromium/storage/browser/blob/blob_data_item.cc b/chromium/storage/browser/blob/blob_data_item.cc index c500cc0ef27..22582a9a0fc 100644 --- a/chromium/storage/browser/blob/blob_data_item.cc +++ b/chromium/storage/browser/blob/blob_data_item.cc @@ -9,6 +9,7 @@ #include <utility> #include "base/strings/string_number_conversions.h" +#include "net/base/net_errors.h" #include "storage/browser/fileapi/file_system_context.h" #include "third_party/blink/public/common/blob/blob_utils.h" @@ -19,9 +20,35 @@ const base::FilePath::CharType kFutureFileName[] = FILE_PATH_LITERAL("_future_name_"); } -bool BlobDataItem::DataHandle::IsValid() { - return true; +uint64_t BlobDataItem::DataHandle::GetSize() const { + return 0; } + +int BlobDataItem::DataHandle::Read(scoped_refptr<net::IOBuffer> dst_buffer, + uint64_t src_offset, + int bytes_to_read, + base::OnceCallback<void(int)> callback) { + return net::ERR_FILE_NOT_FOUND; +} + +uint64_t BlobDataItem::DataHandle::GetSideDataSize() const { + return 0; +} + +int BlobDataItem::DataHandle::ReadSideData( + scoped_refptr<net::IOBuffer> dst_buffer, + base::OnceCallback<void(int)> callback) { + return net::ERR_FILE_NOT_FOUND; +} + +void BlobDataItem::DataHandle::PrintTo(::std::ostream* os) const { + *os << "<unknown>"; +} + +const char* BlobDataItem::DataHandle::BytesReadHistogramLabel() const { + return nullptr; +} + BlobDataItem::DataHandle::~DataHandle() = default; // static @@ -91,19 +118,15 @@ scoped_refptr<BlobDataItem> BlobDataItem::CreateFileFilesystem( } // static -scoped_refptr<BlobDataItem> BlobDataItem::CreateDiskCacheEntry( - uint64_t offset, - uint64_t length, +scoped_refptr<BlobDataItem> BlobDataItem::CreateReadableDataHandle( scoped_refptr<DataHandle> data_handle, - disk_cache::Entry* entry, - int disk_cache_stream_index, - int disk_cache_side_stream_index) { + uint64_t offset, + uint64_t length) { + DCHECK_LE(offset, data_handle->GetSize()); + DCHECK_LE(length, (data_handle->GetSize() - offset)); auto item = base::WrapRefCounted( - new BlobDataItem(Type::kDiskCacheEntry, offset, length)); + new BlobDataItem(Type::kReadableDataHandle, offset, length)); item->data_handle_ = std::move(data_handle); - item->disk_cache_entry_ = entry; - item->disk_cache_stream_index_ = disk_cache_stream_index; - item->disk_cache_side_stream_index_ = disk_cache_side_stream_index; return item; } @@ -195,11 +218,10 @@ void PrintTo(const BlobDataItem& x, ::std::ostream* os) { case BlobDataItem::Type::kFileFilesystem: *os << "kFileFilesystem, url: " << x.filesystem_url(); break; - case BlobDataItem::Type::kDiskCacheEntry: - *os << "kDiskCacheEntry" - << ", disk_cache_entry_ptr: " << x.disk_cache_entry_ - << ", disk_cache_stream_index_: " << x.disk_cache_stream_index_ - << "}"; + case BlobDataItem::Type::kReadableDataHandle: + *os << "kReadableDataHandle" + << ", data_handle_: "; + x.data_handle()->PrintTo(os); break; } *os << ", length: " << x.length() << ", offset: " << x.offset() @@ -221,11 +243,8 @@ bool operator==(const BlobDataItem& a, const BlobDataItem& b) { a.expected_modification_time() == b.expected_modification_time(); case BlobDataItem::Type::kFileFilesystem: return a.filesystem_url() == b.filesystem_url(); - case BlobDataItem::Type::kDiskCacheEntry: - return a.disk_cache_entry() == b.disk_cache_entry() && - a.disk_cache_stream_index() == b.disk_cache_stream_index() && - a.disk_cache_side_stream_index() == - b.disk_cache_side_stream_index(); + case BlobDataItem::Type::kReadableDataHandle: + return a.data_handle() == b.data_handle(); } NOTREACHED(); return false; diff --git a/chromium/storage/browser/blob/blob_data_item.h b/chromium/storage/browser/blob/blob_data_item.h index 91d5d53e723..bec072f1485 100644 --- a/chromium/storage/browser/blob/blob_data_item.h +++ b/chromium/storage/browser/blob/blob_data_item.h @@ -15,12 +15,9 @@ #include "base/containers/span.h" #include "base/files/file_path.h" #include "base/memory/ref_counted.h" +#include "net/base/io_buffer.h" #include "url/gurl.h" -namespace disk_cache { -class Entry; -} - namespace storage { class BlobDataBuilder; class BlobStorageContext; @@ -39,7 +36,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobDataItem kBytesDescription, kFile, kFileFilesystem, - kDiskCacheEntry + kReadableDataHandle, }; // The DataHandle class is used to persist resources that are needed for @@ -47,10 +44,48 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobDataItem // pending. If all blobs with this item are deleted or the item is swapped for // a different backend version (mem-to-disk or the reverse), then the item // will be destructed after all pending reads are complete. + // + // A DataHandle can also be "readable" if it overrides the size and reading + // virtual methods. If the DataHandle provides this kind of encapsulated + // implementation then it can be added to the item using the + // AppendReadableDataHandle() method. class COMPONENT_EXPORT(STORAGE_BROWSER) DataHandle : public base::RefCounted<DataHandle> { public: - virtual bool IsValid(); + // Must return the main blob data size. Returns 0 by default. + virtual uint64_t GetSize() const; + + // Reads the given data range into the given buffer. If the read is + // completed synchronously then the number of bytes read should be returned + // directly. If the read must be performed asynchronously then this + // method must return net::ERR_IO_PENDING and invoke the callback with the + // result at a later time. The default implementation returns + // net::ERR_FILE_NOT_FOUND. + virtual int Read(scoped_refptr<net::IOBuffer> dst_buffer, + uint64_t src_offset, + int bytes_to_read, + base::OnceCallback<void(int)> callback); + + // Must return the side data size. If there is no side data, then 0 should + // be returned. Returns 0 by default. + virtual uint64_t GetSideDataSize() const; + + // Reads the entire side data into the given buffer. The buffer must be + // large enough to contain the entire side data. If the read is completed + // synchronously then the number of bytes read should be returned directly. + // If the read must be performed asynchronously then this method must + // return net::ERR_IO_PENDING and invoke the callback with the result at a + // later time. The default implementation returns net::ERR_FILE_NOT_FOUND. + virtual int ReadSideData(scoped_refptr<net::IOBuffer> dst_buffer, + base::OnceCallback<void(int)> callback); + + // Print a description of the readable DataHandle for debugging. + virtual void PrintTo(::std::ostream* os) const; + + // Return the histogram label to use when calling RecordBytesRead(). If + // nullptr is returned then nothing will be recorded. Returns nullptr by + // default. + virtual const char* BytesReadHistogramLabel() const; protected: virtual ~DataHandle(); @@ -77,13 +112,10 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobDataItem uint64_t length, base::Time expected_modification_time, scoped_refptr<FileSystemContext> file_system_context); - static scoped_refptr<BlobDataItem> CreateDiskCacheEntry( - uint64_t offset, - uint64_t length, + static scoped_refptr<BlobDataItem> CreateReadableDataHandle( scoped_refptr<DataHandle> data_handle, - disk_cache::Entry* entry, - int disk_cache_stream_index, - int disk_cache_side_stream_index); + uint64_t offset, + uint64_t length); Type type() const { return type_; } uint64_t offset() const { return offset_; } @@ -115,27 +147,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobDataItem return expected_modification_time_; } - // This can return null if the underlying disk cache entry was invalidated - // (because the user cleared site data), so users should make sure to always - // check for that. - disk_cache::Entry* disk_cache_entry() const { - DCHECK_EQ(type_, Type::kDiskCacheEntry); - DCHECK(data_handle_); - return data_handle_->IsValid() ? disk_cache_entry_ : nullptr; - } - - int disk_cache_stream_index() const { - DCHECK_EQ(type_, Type::kDiskCacheEntry); - return disk_cache_stream_index_; - } - - int disk_cache_side_stream_index() const { - DCHECK_EQ(type_, Type::kDiskCacheEntry); - return disk_cache_side_stream_index_; - } - DataHandle* data_handle() const { - DCHECK(type_ == Type::kFile || type_ == Type::kDiskCacheEntry) + DCHECK(type_ == Type::kFile || type_ == Type::kReadableDataHandle) << static_cast<int>(type_); return data_handle_.get(); } @@ -186,16 +199,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobDataItem expected_modification_time_; // For Type::kFile and kFileFilesystem. scoped_refptr<DataHandle> - data_handle_; // For Type::kFile and kDiskCacheEntry. - - // This naked pointer is safe because the scope is protected by the DataHandle - // instance for disk cache entries during the lifetime of this BlobDataItem. - // Only valid if the DataHandle's IsValid method returns true. - // TODO(mek): Make this part of the DataHandle and abstract away cache - // specific logic to be part of an API exposed by DataHandle. - disk_cache::Entry* disk_cache_entry_; // For Type::kDiskCacheEntry. - int disk_cache_stream_index_; // For Type::kDiskCacheEntry. - int disk_cache_side_stream_index_; // For Type::kDiskCacheEntry. + data_handle_; // For Type::kFile and kReadableDataHandle. scoped_refptr<FileSystemContext> file_system_context_; // For Type::kFileFilesystem. diff --git a/chromium/storage/browser/blob/blob_flattener_unittest.cc b/chromium/storage/browser/blob/blob_flattener_unittest.cc index ee0f3d68af6..553eb2bc9e8 100644 --- a/chromium/storage/browser/blob/blob_flattener_unittest.cc +++ b/chromium/storage/browser/blob/blob_flattener_unittest.cc @@ -10,8 +10,8 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" #include "base/test/test_simple_task_runner.h" #include "base/time/time.h" #include "storage/browser/blob/blob_data_builder.h" @@ -117,7 +117,7 @@ class BlobFlattenerTest : public testing::Test { base::ScopedTempDir temp_dir_; scoped_refptr<TestSimpleTaskRunner> file_runner_ = new TestSimpleTaskRunner(); - base::MessageLoop fake_io_message_loop; + base::test::ScopedTaskEnvironment scoped_task_environment; std::unique_ptr<BlobStorageContext> context_; }; diff --git a/chromium/storage/browser/blob/blob_impl.cc b/chromium/storage/browser/blob/blob_impl.cc index 9acb4fd8f9e..bf6aa8cd0dc 100644 --- a/chromium/storage/browser/blob/blob_impl.cc +++ b/chromium/storage/browser/blob/blob_impl.cc @@ -12,7 +12,6 @@ #include "base/bind.h" #include "base/containers/span.h" #include "net/base/io_buffer.h" -#include "net/disk_cache/disk_cache.h" #include "storage/browser/blob/blob_data_handle.h" #include "storage/browser/blob/blob_data_item.h" #include "storage/browser/blob/blob_data_snapshot.h" @@ -124,25 +123,22 @@ void BlobImpl::ReadSideData(ReadSideDataCallback callback) { } auto snapshot = handle.CreateSnapshot(); - // Currently side data is supported only for single DiskCache entry - // blob. + // Currently side data is supported only for blobs with a single entry. const auto& items = snapshot->items(); - if (items.size() != 1 || - items[0]->type() != BlobDataItem::Type::kDiskCacheEntry) { + if (items.size() != 1) { std::move(callback).Run(base::nullopt); return; } const auto& item = items[0]; - disk_cache::Entry* entry = item->disk_cache_entry(); - if (!entry) { + if (item->type() != BlobDataItem::Type::kReadableDataHandle) { std::move(callback).Run(base::nullopt); return; } - int32_t body_size = - entry->GetDataSize(item->disk_cache_side_stream_index()); + + int32_t body_size = item->data_handle()->GetSideDataSize(); if (body_size == 0) { - std::move(callback).Run(std::vector<uint8_t>()); + std::move(callback).Run(base::nullopt); return; } auto io_buffer = base::MakeRefCounted<net::IOBufferWithSize>(body_size); @@ -161,9 +157,10 @@ void BlobImpl::ReadSideData(ReadSideDataCallback callback) { }, io_buffer, std::move(callback))); - // TODO(crbug.com/867848): Plumb BigBuffer into disk_cache::ReadData(). - int rv = entry->ReadData(item->disk_cache_side_stream_index(), 0, - io_buffer.get(), body_size, io_callback); + // TODO(crbug.com/867848): Plumb BigBuffer into + // BlobDataItem::DataHandle::ReadSideData(). + int rv = item->data_handle()->ReadSideData(std::move(io_buffer), + io_callback); if (rv != net::ERR_IO_PENDING) io_callback.Run(rv); }, diff --git a/chromium/storage/browser/blob/blob_memory_controller_unittest.cc b/chromium/storage/browser/blob/blob_memory_controller_unittest.cc index a80344c1c97..d6aa1af5a39 100644 --- a/chromium/storage/browser/blob/blob_memory_controller_unittest.cc +++ b/chromium/storage/browser/blob/blob_memory_controller_unittest.cc @@ -8,9 +8,9 @@ #include "base/bind_helpers.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/system/sys_info.h" +#include "base/test/scoped_task_environment.h" #include "base/test/test_simple_task_runner.h" #include "base/threading/thread_restrictions.h" #include "base/threading/thread_task_runner_handle.h" @@ -165,7 +165,7 @@ class BlobMemoryControllerTest : public testing::Test { scoped_refptr<TestSimpleTaskRunner> file_runner_ = new TestSimpleTaskRunner(); - base::MessageLoop fake_io_message_loop_; + base::test::ScopedTaskEnvironment scoped_task_environment_; }; TEST_F(BlobMemoryControllerTest, Strategy) { diff --git a/chromium/storage/browser/blob/blob_reader.cc b/chromium/storage/browser/blob/blob_reader.cc index 5100695dee2..71a48d61f5e 100644 --- a/chromium/storage/browser/blob/blob_reader.cc +++ b/chromium/storage/browser/blob/blob_reader.cc @@ -20,7 +20,6 @@ #include "base/trace_event/trace_event.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" -#include "net/disk_cache/disk_cache.h" #include "storage/browser/blob/blob_data_handle.h" #include "storage/browser/blob/blob_data_snapshot.h" #include "storage/browser/fileapi/file_stream_reader.h" @@ -30,7 +29,6 @@ namespace storage { namespace { -const char kCacheStorageRecordBytesLabel[] = "DiskCache.CacheStorage"; bool IsFileType(BlobDataItem::Type type) { switch (type) { @@ -119,14 +117,9 @@ bool BlobReader::has_side_data() const { if (items.size() != 1) return false; const BlobDataItem& item = *items.at(0); - if (item.type() != BlobDataItem::Type::kDiskCacheEntry) + if (item.type() != BlobDataItem::Type::kReadableDataHandle) return false; - const int disk_cache_side_stream_index = item.disk_cache_side_stream_index(); - if (disk_cache_side_stream_index < 0) - return false; - if (!item.disk_cache_entry()) - return false; - return item.disk_cache_entry()->GetDataSize(disk_cache_side_stream_index) > 0; + return item.data_handle()->GetSideDataSize() > 0; } BlobReader::Status BlobReader::ReadSideData(StatusCallback done) { @@ -134,17 +127,14 @@ BlobReader::Status BlobReader::ReadSideData(StatusCallback done) { if (!has_side_data()) return ReportError(net::ERR_FILE_NOT_FOUND); - const BlobDataItem* item = blob_data_->items()[0].get(); - const int disk_cache_side_stream_index = item->disk_cache_side_stream_index(); - const int side_data_size = - item->disk_cache_entry()->GetDataSize(disk_cache_side_stream_index); + BlobDataItem* item = blob_data_->items()[0].get(); + const int side_data_size = item->data_handle()->GetSideDataSize(); side_data_ = base::MakeRefCounted<net::IOBufferWithSize>(side_data_size); net_error_ = net::OK; - const int result = item->disk_cache_entry()->ReadData( - disk_cache_side_stream_index, 0, side_data_.get(), side_data_size, - base::BindOnce(&BlobReader::DidReadDiskCacheEntrySideData, - weak_factory_.GetWeakPtr(), std::move(done), - side_data_size)); + const int result = item->data_handle()->ReadSideData( + side_data_.get(), + base::BindOnce(&BlobReader::DidReadSideData, weak_factory_.GetWeakPtr(), + std::move(done), side_data_size)); if (result >= 0) { DCHECK_EQ(side_data_size, result); return Status::DONE; @@ -154,14 +144,13 @@ BlobReader::Status BlobReader::ReadSideData(StatusCallback done) { return ReportError(result); } -void BlobReader::DidReadDiskCacheEntrySideData(StatusCallback done, - int expected_size, - int result) { +void BlobReader::DidReadSideData(StatusCallback done, + int expected_size, + int result) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (result >= 0) { DCHECK_EQ(expected_size, result); - if (result > 0) - storage::RecordBytesRead(kCacheStorageRecordBytesLabel, result); + RecordBytesReadFromDataHandle(/* item_index= */ 0, result); std::move(done).Run(Status::DONE); return; } @@ -481,13 +470,13 @@ BlobReader::Status BlobReader::ReadItem() { } // Do the reading. - const BlobDataItem& item = *items.at(current_item_index_); + BlobDataItem& item = *items.at(current_item_index_); if (item.type() == BlobDataItem::Type::kBytes) { ReadBytesItem(item, bytes_to_read); return Status::DONE; } - if (item.type() == BlobDataItem::Type::kDiskCacheEntry) - return ReadDiskCacheEntryItem(item, bytes_to_read); + if (item.type() == BlobDataItem::Type::kReadableDataHandle) + return ReadReadableDataHandle(item, bytes_to_read); if (!IsFileType(item.type())) { NOTREACHED(); return ReportError(net::ERR_UNEXPECTED); @@ -593,39 +582,37 @@ void BlobReader::DeleteCurrentFileReader() { std::unique_ptr<FileStreamReader>()); } -BlobReader::Status BlobReader::ReadDiskCacheEntryItem(const BlobDataItem& item, +BlobReader::Status BlobReader::ReadReadableDataHandle(const BlobDataItem& item, int bytes_to_read) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!io_pending_) << "Can't begin IO while another IO operation is pending."; DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read); + DCHECK_EQ(item.type(), BlobDataItem::Type::kReadableDataHandle); - if (!item.disk_cache_entry()) - return ReportError(net::ERR_CACHE_READ_FAILURE); - const int result = item.disk_cache_entry()->ReadData( - item.disk_cache_stream_index(), item.offset() + current_item_offset_, - read_buf_.get(), bytes_to_read, - base::BindOnce(&BlobReader::DidReadDiskCacheEntry, + const int result = item.data_handle()->Read( + read_buf_, item.offset() + current_item_offset_, bytes_to_read, + base::BindOnce(&BlobReader::DidReadReadableDataHandle, weak_factory_.GetWeakPtr())); + if (result >= 0) { AdvanceBytesRead(result); return Status::DONE; } if (result == net::ERR_IO_PENDING) { - TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest::ReadDiskCacheItem", this, - "uuid", blob_data_->uuid()); + TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest::ReadReadableDataHandle", + this, "uuid", blob_data_->uuid()); io_pending_ = true; return Status::IO_PENDING; } return ReportError(result); } -void BlobReader::DidReadDiskCacheEntry(int result) { +void BlobReader::DidReadReadableDataHandle(int result) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadDiskCacheItem", this, "uuid", - blob_data_->uuid()); - if (result > 0) - storage::RecordBytesRead(kCacheStorageRecordBytesLabel, result); + TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadReadableDataHandle", this, + "uuid", blob_data_->uuid()); + RecordBytesReadFromDataHandle(current_item_index_, result); DidReadItem(result); } @@ -719,7 +706,7 @@ std::unique_ptr<FileStreamReader> BlobReader::CreateFileStreamReader( } case BlobDataItem::Type::kBytes: case BlobDataItem::Type::kBytesDescription: - case BlobDataItem::Type::kDiskCacheEntry: + case BlobDataItem::Type::kReadableDataHandle: break; } @@ -737,4 +724,14 @@ void BlobReader::SetFileReaderAtIndex( index_to_reader_.erase(index); } +void BlobReader::RecordBytesReadFromDataHandle(int item_index, int result) { + const auto& items = blob_data_->items(); + BlobDataItem& item = *items.at(item_index); + DCHECK_EQ(item.type(), BlobDataItem::Type::kReadableDataHandle); + if (item.data_handle()->BytesReadHistogramLabel()) { + storage::RecordBytesRead(item.data_handle()->BytesReadHistogramLabel(), + result); + } +} + } // namespace storage diff --git a/chromium/storage/browser/blob/blob_reader.h b/chromium/storage/browser/blob/blob_reader.h index b63b6e5376c..312b65fb464 100644 --- a/chromium/storage/browser/blob/blob_reader.h +++ b/chromium/storage/browser/blob/blob_reader.h @@ -82,10 +82,11 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobReader { Status CalculateSize(net::CompletionOnceCallback done); // Returns true when the blob has side data. CalculateSize must be called - // beforehand. Currently side data is supported only for single DiskCache - // entry blob. So it returns false when the blob has more than single data - // item. This side data is used to pass the V8 code cache which is stored - // as a side stream in the CacheStorage to the renderer. (crbug.com/581613) + // beforehand. Currently side data is supported only for single readable + // DataHandle entry blob. So it returns false when the blob has more than + // single data item. This side data is used to pass the V8 code cache which is + // stored as a side stream in the CacheStorage to the renderer. + // (crbug.com/581613) bool has_side_data() const; // Reads the side data of the blob. CalculateSize must be called beforehand. @@ -94,7 +95,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobReader { // Status::NET_ERROR and the net error code is set. // * If this function returns Status::IO_PENDING, the done callback will be // called with Status::DONE or Status::NET_ERROR. - // Currently side data is supported only for single DiskCache entry blob. + // Currently side data is supported only for single readable DataHandle entry + // blob. Status ReadSideData(StatusCallback done); // Returns the side data which has been already read with ReadSideData(). @@ -199,12 +201,10 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobReader { BlobReader::Status ReadFileItem(FileStreamReader* reader, int bytes_to_read); void DidReadFile(int result); void DeleteCurrentFileReader(); - Status ReadDiskCacheEntryItem(const BlobDataItem& item, int bytes_to_read); - void DidReadDiskCacheEntry(int result); + Status ReadReadableDataHandle(const BlobDataItem& item, int bytes_to_read); + void DidReadReadableDataHandle(int result); void DidReadItem(int result); - void DidReadDiskCacheEntrySideData(StatusCallback done, - int expected_size, - int result); + void DidReadSideData(StatusCallback done, int expected_size, int result); int ComputeBytesToRead() const; int BytesReadCompleted(); @@ -219,6 +219,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobReader { const BlobDataItem& item, uint64_t additional_offset); + void RecordBytesReadFromDataHandle(int item_index, int result); + std::unique_ptr<BlobDataHandle> blob_handle_; std::unique_ptr<BlobDataSnapshot> blob_data_; std::unique_ptr<FileStreamReaderProvider> file_stream_provider_for_testing_; diff --git a/chromium/storage/browser/blob/blob_reader_unittest.cc b/chromium/storage/browser/blob/blob_reader_unittest.cc index dbe8040d7c4..5ce2276281b 100644 --- a/chromium/storage/browser/blob/blob_reader_unittest.cc +++ b/chromium/storage/browser/blob/blob_reader_unittest.cc @@ -26,7 +26,6 @@ #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" -#include "net/disk_cache/disk_cache.h" #include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_data_handle.h" #include "storage/browser/blob/blob_reader.h" @@ -35,6 +34,7 @@ #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_file_util.h" #include "storage/browser/test/async_file_test_helper.h" +#include "storage/browser/test/fake_blob_data_handle.h" #include "storage/browser/test/test_file_system_context.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -49,9 +49,6 @@ using FileCreationInfo = storage::BlobMemoryController::FileCreationInfo; namespace storage { namespace { -const int kTestDiskCacheStreamIndex = 0; -const int kTestDiskCacheSideStreamIndex = 1; - void SaveBlobStatusAndFiles(BlobStatus* status_ptr, std::vector<FileCreationInfo>* files_ptr, BlobStatus status, @@ -62,152 +59,6 @@ void SaveBlobStatusAndFiles(BlobStatus* status_ptr, } } -// Our disk cache tests don't need a real data handle since the tests themselves -// scope the disk cache and entries. -class EmptyDataHandle : public storage::BlobDataBuilder::DataHandle { - private: - ~EmptyDataHandle() override = default; -}; - -// A disk_cache::Entry that arbitrarily delays the completion of a read -// operation to allow testing some races without flake. This is particularly -// relevant in this unit test, which uses the always-synchronous MEMORY_CACHE. -class DelayedReadEntry : public disk_cache::Entry { - public: - explicit DelayedReadEntry(disk_cache::ScopedEntryPtr entry) - : entry_(std::move(entry)) {} - ~DelayedReadEntry() override { EXPECT_FALSE(HasPendingReadCallbacks()); } - - bool HasPendingReadCallbacks() { return !pending_read_callbacks_.empty(); } - - void RunPendingReadCallbacks() { - std::vector<base::OnceCallback<void(void)>> callbacks; - pending_read_callbacks_.swap(callbacks); - for (auto& callback : callbacks) - std::move(callback).Run(); - } - - // From disk_cache::Entry: - void Doom() override { entry_->Doom(); } - - void Close() override { delete this; } // Note this is required by the API. - - std::string GetKey() const override { return entry_->GetKey(); } - - base::Time GetLastUsed() const override { return entry_->GetLastUsed(); } - - base::Time GetLastModified() const override { - return entry_->GetLastModified(); - } - - int32_t GetDataSize(int index) const override { - return entry_->GetDataSize(index); - } - - int ReadData(int index, - int offset, - IOBuffer* buf, - int buf_len, - CompletionOnceCallback original_callback) override { - net::TestCompletionCallback callback; - int rv = entry_->ReadData(index, offset, buf, buf_len, callback.callback()); - DCHECK_NE(rv, net::ERR_IO_PENDING) - << "Test expects to use a MEMORY_CACHE instance, which is synchronous."; - pending_read_callbacks_.push_back( - base::BindOnce(std::move(original_callback), rv)); - return net::ERR_IO_PENDING; - } - - int WriteData(int index, - int offset, - IOBuffer* buf, - int buf_len, - CompletionOnceCallback callback, - bool truncate) override { - return entry_->WriteData(index, offset, buf, buf_len, std::move(callback), - truncate); - } - - int ReadSparseData(int64_t offset, - IOBuffer* buf, - int buf_len, - CompletionOnceCallback callback) override { - return entry_->ReadSparseData(offset, buf, buf_len, std::move(callback)); - } - - int WriteSparseData(int64_t offset, - IOBuffer* buf, - int buf_len, - CompletionOnceCallback callback) override { - return entry_->WriteSparseData(offset, buf, buf_len, std::move(callback)); - } - - int GetAvailableRange(int64_t offset, - int len, - int64_t* start, - CompletionOnceCallback callback) override { - return entry_->GetAvailableRange(offset, len, start, std::move(callback)); - } - - bool CouldBeSparse() const override { return entry_->CouldBeSparse(); } - - void CancelSparseIO() override { entry_->CancelSparseIO(); } - - net::Error ReadyForSparseIO(CompletionOnceCallback callback) override { - return entry_->ReadyForSparseIO(std::move(callback)); - } - void SetLastUsedTimeForTest(base::Time time) override { NOTREACHED(); } - - private: - disk_cache::ScopedEntryPtr entry_; - std::vector<base::OnceCallback<void(void)>> pending_read_callbacks_; -}; - -std::unique_ptr<disk_cache::Backend> CreateInMemoryDiskCache() { - std::unique_ptr<disk_cache::Backend> cache; - net::TestCompletionCallback callback; - int rv = disk_cache::CreateCacheBackend( - net::MEMORY_CACHE, net::CACHE_BACKEND_DEFAULT, FilePath(), 0, false, - nullptr, &cache, callback.callback()); - EXPECT_EQ(net::OK, callback.GetResult(rv)); - - return cache; -} - -disk_cache::ScopedEntryPtr CreateDiskCacheEntry(disk_cache::Backend* cache, - const char* key, - const std::string& data) { - disk_cache::Entry* temp_entry = nullptr; - net::TestCompletionCallback callback; - int rv = - cache->CreateEntry(key, net::HIGHEST, &temp_entry, callback.callback()); - if (callback.GetResult(rv) != net::OK) - return nullptr; - disk_cache::ScopedEntryPtr entry(temp_entry); - - scoped_refptr<net::StringIOBuffer> iobuffer = - base::MakeRefCounted<net::StringIOBuffer>(data); - rv = entry->WriteData(kTestDiskCacheStreamIndex, 0, iobuffer.get(), - iobuffer->size(), callback.callback(), false); - EXPECT_EQ(static_cast<int>(data.size()), callback.GetResult(rv)); - return entry; -} - -disk_cache::ScopedEntryPtr CreateDiskCacheEntryWithSideData( - disk_cache::Backend* cache, - const char* key, - const std::string& data, - const std::string& side_data) { - disk_cache::ScopedEntryPtr entry = CreateDiskCacheEntry(cache, key, data); - scoped_refptr<net::StringIOBuffer> iobuffer = - base::MakeRefCounted<net::StringIOBuffer>(side_data); - net::TestCompletionCallback callback; - int rv = entry->WriteData(kTestDiskCacheSideStreamIndex, 0, iobuffer.get(), - iobuffer->size(), callback.callback(), false); - EXPECT_EQ(static_cast<int>(side_data.size()), callback.GetResult(rv)); - return entry; -} - template <typename T> void SetValue(T* address, T value) { *address = value; @@ -523,17 +374,12 @@ TEST_F(BlobReaderTest, BasicFileSystem) { EXPECT_EQ(0, memcmp(buffer->data(), "FileData!!!", kData.size())); } -TEST_F(BlobReaderTest, BasicDiskCache) { - std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache(); - ASSERT_TRUE(cache); - +TEST_F(BlobReaderTest, BasicReadableDataHandle) { auto b = std::make_unique<BlobDataBuilder>("uuid"); const std::string kData = "Test Blob Data"; - scoped_refptr<BlobDataBuilder::DataHandle> data_handle = - new EmptyDataHandle(); - disk_cache::ScopedEntryPtr entry = - CreateDiskCacheEntry(cache.get(), "test entry", kData); - b->AppendDiskCacheEntry(data_handle, entry.get(), kTestDiskCacheStreamIndex); + auto data_handle = + base::MakeRefCounted<storage::FakeBlobDataHandle>(kData, ""); + b->AppendReadableDataHandle(std::move(data_handle)); this->InitializeReader(std::move(b)); int size_result = -1; @@ -558,20 +404,13 @@ TEST_F(BlobReaderTest, BasicDiskCache) { EXPECT_EQ(0, memcmp(buffer->data(), "Test Blob Data", kData.size())); } -TEST_F(BlobReaderTest, DiskCacheWithSideData) { - std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache(); - ASSERT_TRUE(cache); - +TEST_F(BlobReaderTest, ReadableDataHandleWithSideData) { auto b = std::make_unique<BlobDataBuilder>("uuid"); const std::string kData = "Test Blob Data"; const std::string kSideData = "Test side data"; - scoped_refptr<BlobDataBuilder::DataHandle> data_handle = - new EmptyDataHandle(); - disk_cache::ScopedEntryPtr entry = CreateDiskCacheEntryWithSideData( - cache.get(), "test entry", kData, kSideData); - b->AppendDiskCacheEntryWithSideData(data_handle, entry.get(), - kTestDiskCacheStreamIndex, - kTestDiskCacheSideStreamIndex); + auto data_handle = + base::MakeRefCounted<storage::FakeBlobDataHandle>(kData, kSideData); + b->AppendReadableDataHandle(std::move(data_handle)); this->InitializeReader(std::move(b)); int size_result = -1; @@ -803,18 +642,13 @@ TEST_F(BlobReaderTest, FileSystemAsync) { EXPECT_EQ(0, memcmp(buffer->data(), "FileData!!!", kData.size())); } -TEST_F(BlobReaderTest, DiskCacheAsync) { - std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache(); - ASSERT_TRUE(cache); - +TEST_F(BlobReaderTest, ReadableDataHandleAsync) { auto b = std::make_unique<BlobDataBuilder>("uuid"); const std::string kData = "Test Blob Data"; - scoped_refptr<BlobDataBuilder::DataHandle> data_handle = - new EmptyDataHandle(); - std::unique_ptr<DelayedReadEntry> delayed_read_entry(new DelayedReadEntry( - CreateDiskCacheEntry(cache.get(), "test entry", kData))); - b->AppendDiskCacheEntry(data_handle, delayed_read_entry.get(), - kTestDiskCacheStreamIndex); + auto data_handle = + base::MakeRefCounted<storage::FakeBlobDataHandle>(kData, ""); + data_handle->EnableDelayedReading(); + b->AppendReadableDataHandle(data_handle); this->InitializeReader(std::move(b)); int size_result = -1; @@ -831,8 +665,8 @@ TEST_F(BlobReaderTest, DiskCacheAsync) { EXPECT_EQ(BlobReader::Status::IO_PENDING, reader_->Read(buffer.get(), kData.size(), &bytes_read, base::BindOnce(&SetValue<int>, &async_bytes_read))); - EXPECT_TRUE(delayed_read_entry->HasPendingReadCallbacks()); - delayed_read_entry->RunPendingReadCallbacks(); + EXPECT_TRUE(data_handle->HasPendingReadCallbacks()); + data_handle->RunPendingReadCallbacks(); EXPECT_EQ(net::OK, reader_->net_error()); EXPECT_EQ(0, bytes_read); EXPECT_EQ(kData.size(), static_cast<size_t>(async_bytes_read)); @@ -882,19 +716,14 @@ TEST_F(BlobReaderTest, FileRange) { EXPECT_EQ(0, memcmp(buffer->data(), "leD", kReadLength)); } -TEST_F(BlobReaderTest, DiskCacheRange) { - std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache(); - ASSERT_TRUE(cache); - +TEST_F(BlobReaderTest, ReadableDataHandleRange) { auto b = std::make_unique<BlobDataBuilder>("uuid"); const std::string kData = "Test Blob Data"; const uint64_t kOffset = 2; const uint64_t kReadLength = 3; - scoped_refptr<BlobDataBuilder::DataHandle> data_handle = - new EmptyDataHandle(); - disk_cache::ScopedEntryPtr entry = - CreateDiskCacheEntry(cache.get(), "test entry", kData); - b->AppendDiskCacheEntry(data_handle, entry.get(), kTestDiskCacheStreamIndex); + auto data_handle = + base::MakeRefCounted<storage::FakeBlobDataHandle>(kData, ""); + b->AppendReadableDataHandle(std::move(data_handle)); this->InitializeReader(std::move(b)); int size_result = -1; @@ -992,9 +821,7 @@ TEST_F(BlobReaderTest, FileSomeAsyncSegmentedOffsetsUnknownSizes) { } TEST_F(BlobReaderTest, MixedContent) { - // Includes data, a file, and a disk cache entry. - std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache(); - ASSERT_TRUE(cache); + // Includes data, a file, and a data handle entry. auto b = std::make_unique<BlobDataBuilder>("uuid"); const std::string kData1("Hello "); @@ -1006,14 +833,12 @@ TEST_F(BlobReaderTest, MixedContent) { const base::Time kTime = base::Time::Now(); const FilePath kData1Path = FilePath::FromUTF8Unsafe("/fake/file.txt"); - disk_cache::ScopedEntryPtr entry3 = - CreateDiskCacheEntry(cache.get(), "test entry", kData3); + auto data_handle = + base::MakeRefCounted<storage::FakeBlobDataHandle>(kData3, ""); b->AppendFile(kData1Path, 0, kData1.size(), kTime); b->AppendData(kData2); - b->AppendDiskCacheEntry( - scoped_refptr<BlobDataBuilder::DataHandle>(new EmptyDataHandle()), - entry3.get(), kTestDiskCacheStreamIndex); + b->AppendReadableDataHandle(std::move(data_handle)); b->AppendData(kData4); this->InitializeReader(std::move(b)); diff --git a/chromium/storage/browser/blob/blob_registry_impl.cc b/chromium/storage/browser/blob/blob_registry_impl.cc index aa81ace360a..1630806f28b 100644 --- a/chromium/storage/browser/blob/blob_registry_impl.cc +++ b/chromium/storage/browser/blob/blob_registry_impl.cc @@ -507,7 +507,7 @@ void BlobRegistryImpl::Register( } if (uuid.empty() || context_->registry().HasEntry(uuid) || - base::ContainsKey(blobs_under_construction_, uuid)) { + base::Contains(blobs_under_construction_, uuid)) { bindings_.ReportBadMessage("Invalid UUID passed to BlobRegistry::Register"); return; } diff --git a/chromium/storage/browser/blob/blob_storage_context.cc b/chromium/storage/browser/blob/blob_storage_context.cc index 57aba5d5964..705aaa4b1d7 100644 --- a/chromium/storage/browser/blob/blob_storage_context.cc +++ b/chromium/storage/browser/blob/blob_storage_context.cc @@ -533,7 +533,7 @@ void BlobStorageContext::FinishBuilding(BlobEntry* entry) { } case BlobDataItem::Type::kBytesDescription: case BlobDataItem::Type::kFileFilesystem: - case BlobDataItem::Type::kDiskCacheEntry: + case BlobDataItem::Type::kReadableDataHandle: NOTREACHED(); break; } diff --git a/chromium/storage/browser/blob/blob_storage_context_unittest.cc b/chromium/storage/browser/blob/blob_storage_context_unittest.cc index e2b35235d17..4e2449267fb 100644 --- a/chromium/storage/browser/blob/blob_storage_context_unittest.cc +++ b/chromium/storage/browser/blob/blob_storage_context_unittest.cc @@ -16,19 +16,19 @@ #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" +#include "base/test/scoped_task_environment.h" #include "base/test/test_simple_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "net/base/io_buffer.h" #include "net/base/test_completion_callback.h" -#include "net/disk_cache/disk_cache.h" #include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_data_handle.h" #include "storage/browser/blob/blob_data_item.h" #include "storage/browser/blob/blob_data_snapshot.h" +#include "storage/browser/test/fake_blob_data_handle.h" #include "testing/gtest/include/gtest/gtest.h" using FileCreationInfo = storage::BlobMemoryController::FileCreationInfo; @@ -37,8 +37,6 @@ namespace storage { namespace { using base::TestSimpleTaskRunner; -const int kTestDiskCacheStreamIndex = 0; - const std::string kBlobStorageDirectory = "blob_storage"; const size_t kTestBlobStorageIPCThresholdBytes = 20; const size_t kTestBlobStorageMaxSharedMemoryBytes = 50; @@ -48,43 +46,6 @@ const uint64_t kTestBlobStorageMaxDiskSpace = 4000; const uint64_t kTestBlobStorageMinFileSizeBytes = 10; const uint64_t kTestBlobStorageMaxFileSizeBytes = 100; -// Our disk cache tests don't need a real data handle since the tests themselves -// scope the disk cache and entries. -class EmptyDataHandle : public storage::BlobDataBuilder::DataHandle { - private: - ~EmptyDataHandle() override = default; -}; - -std::unique_ptr<disk_cache::Backend> CreateInMemoryDiskCache() { - std::unique_ptr<disk_cache::Backend> cache; - net::TestCompletionCallback callback; - int rv = disk_cache::CreateCacheBackend( - net::MEMORY_CACHE, net::CACHE_BACKEND_DEFAULT, base::FilePath(), 0, false, - nullptr, &cache, callback.callback()); - EXPECT_EQ(net::OK, callback.GetResult(rv)); - - return cache; -} - -disk_cache::ScopedEntryPtr CreateDiskCacheEntry(disk_cache::Backend* cache, - const char* key, - const std::string& data) { - disk_cache::Entry* temp_entry = nullptr; - net::TestCompletionCallback callback; - int rv = - cache->CreateEntry(key, net::HIGHEST, &temp_entry, callback.callback()); - if (callback.GetResult(rv) != net::OK) - return nullptr; - disk_cache::ScopedEntryPtr entry(temp_entry); - - scoped_refptr<net::StringIOBuffer> iobuffer = - base::MakeRefCounted<net::StringIOBuffer>(data); - rv = entry->WriteData(kTestDiskCacheStreamIndex, 0, iobuffer.get(), - iobuffer->size(), callback.callback(), false); - EXPECT_EQ(static_cast<int>(data.size()), callback.GetResult(rv)); - return entry; -} - void SaveBlobStatus(BlobStatus* status_ptr, BlobStatus status) { *status_ptr = status; } @@ -154,7 +115,7 @@ class BlobStorageContextTest : public testing::Test { base::ScopedTempDir temp_dir_; scoped_refptr<TestSimpleTaskRunner> file_runner_ = new TestSimpleTaskRunner(); - base::MessageLoop fake_io_message_loop_; + base::test::ScopedTaskEnvironment scoped_task_environment_; std::unique_ptr<BlobStorageContext> context_; }; @@ -492,20 +453,14 @@ TEST_F(BlobStorageContextTest, AddFinishedBlob_LargeOffset) { base::RunLoop().RunUntilIdle(); } -TEST_F(BlobStorageContextTest, BuildDiskCacheBlob) { - scoped_refptr<BlobDataBuilder::DataHandle> - data_handle = new EmptyDataHandle(); +TEST_F(BlobStorageContextTest, BuildReadableDataHandleBlob) { + const std::string kTestBlobData = "Test Blob Data"; + auto data_handle = + base::MakeRefCounted<storage::FakeBlobDataHandle>(kTestBlobData, ""); { BlobStorageContext context; - std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache(); - ASSERT_TRUE(cache); - - const std::string kTestBlobData = "Test Blob Data"; - disk_cache::ScopedEntryPtr entry = - CreateDiskCacheEntry(cache.get(), "test entry", kTestBlobData); - const std::string kId1Prime("id1.prime"); BlobDataBuilder canonicalized_blob_data(kId1Prime); canonicalized_blob_data.AppendData(kTestBlobData.c_str()); @@ -513,8 +468,7 @@ TEST_F(BlobStorageContextTest, BuildDiskCacheBlob) { const std::string kId1("id1"); auto builder = std::make_unique<BlobDataBuilder>(kId1); - builder->AppendDiskCacheEntry(data_handle, entry.get(), - kTestDiskCacheStreamIndex); + builder->AppendReadableDataHandle(data_handle); std::unique_ptr<BlobDataSnapshot> builder_data = builder->CreateSnapshot(); std::unique_ptr<BlobDataHandle> blob_data_handle = @@ -618,12 +572,9 @@ TEST_F(BlobStorageContextTest, CompoundBlobs) { auto blob_data3_builder = std::make_unique<BlobDataBuilder>(kId3); blob_data3_builder->AppendData("Data4"); - std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache(); - ASSERT_TRUE(cache); - disk_cache::ScopedEntryPtr disk_cache_entry = - CreateDiskCacheEntry(cache.get(), "another key", "Data5"); - blob_data3_builder->AppendDiskCacheEntry( - new EmptyDataHandle(), disk_cache_entry.get(), kTestDiskCacheStreamIndex); + auto data_handle = + base::MakeRefCounted<storage::FakeBlobDataHandle>("Data5", ""); + blob_data3_builder->AppendReadableDataHandle(std::move(data_handle)); std::unique_ptr<BlobDataSnapshot> blob_data3 = blob_data3_builder->CreateSnapshot(); @@ -733,7 +684,7 @@ TEST_F(BlobStorageContextTest, TestUnknownBrokenAndBuildingBlobReference) { namespace { constexpr size_t kTotalRawBlobs = 200; constexpr size_t kTotalSlicedBlobs = 100; -constexpr char kTestDiskCacheData[] = "Test Blob Data"; +constexpr char kTestDataHandleData[] = "Test Blob Data"; // Appends data and data types that depend on the index. This is designed to // exercise all types of combinations of data, future data, files, future files, @@ -743,7 +694,7 @@ size_t AppendDataInBuilder( std::vector<BlobDataBuilder::FutureData>* future_datas, std::vector<BlobDataBuilder::FutureFile>* future_files, size_t index, - disk_cache::Entry* cache_entry) { + scoped_refptr<storage::BlobDataItem::DataHandle> data_handle) { size_t size = 0; // We can't have both future data and future files, so split those up. if (index % 2 != 0) { @@ -768,11 +719,8 @@ size_t AppendDataInBuilder( size += 20u; } if (index % 3 != 0) { - scoped_refptr<BlobDataBuilder::DataHandle> disk_cache_data_handle = - new EmptyDataHandle(); - builder->AppendDiskCacheEntry(disk_cache_data_handle, cache_entry, - kTestDiskCacheStreamIndex); - size += strlen(kTestDiskCacheData); + builder->AppendReadableDataHandle(data_handle); + size += strlen(kTestDataHandleData); } return size; } @@ -809,10 +757,8 @@ TEST_F(BlobStorageContextTest, BuildBlobCombinations) { std::make_unique<BlobStorageContext>(temp_dir_.GetPath(), file_runner_); SetTestMemoryLimits(); - std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache(); - ASSERT_TRUE(cache); - disk_cache::ScopedEntryPtr entry = - CreateDiskCacheEntry(cache.get(), "test entry", kTestDiskCacheData); + auto data_handle = base::MakeRefCounted<storage::FakeBlobDataHandle>( + kTestDataHandleData, ""); // This tests mixed blob content with both synchronous and asynchronous // construction. Blobs should also be paged to disk during execution. @@ -826,7 +772,7 @@ TEST_F(BlobStorageContextTest, BuildBlobCombinations) { future_files.emplace_back(); auto& builder = *builders.back(); size_t size = AppendDataInBuilder(&builder, &future_datas.back(), - &future_files.back(), i, entry.get()); + &future_files.back(), i, data_handle); EXPECT_NE(0u, size); sizes.push_back(size); } diff --git a/chromium/storage/browser/blob/blob_url_loader.h b/chromium/storage/browser/blob/blob_url_loader.h index 0bc8a30d7b7..7c528d78d91 100644 --- a/chromium/storage/browser/blob/blob_url_loader.h +++ b/chromium/storage/browser/blob/blob_url_loader.h @@ -69,6 +69,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobURLLoader bool sent_headers_ = false; std::unique_ptr<BlobDataHandle> blob_handle_; + mojo::ScopedDataPipeProducerHandle response_body_producer_handle_; mojo::ScopedDataPipeConsumerHandle response_body_consumer_handle_; base::WeakPtrFactory<BlobURLLoader> weak_factory_; diff --git a/chromium/storage/browser/blob/blob_url_request_job.cc b/chromium/storage/browser/blob/blob_url_request_job.cc index 88bd83f2989..c4390c0c900 100644 --- a/chromium/storage/browser/blob/blob_url_request_job.cc +++ b/chromium/storage/browser/blob/blob_url_request_job.cc @@ -24,7 +24,6 @@ #include "base/trace_event/trace_event.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" -#include "net/disk_cache/disk_cache.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" #include "net/http/http_response_info.h" diff --git a/chromium/storage/browser/blob/mojo_blob_reader.cc b/chromium/storage/browser/blob/mojo_blob_reader.cc index fc96e3ed14d..96233d1b420 100644 --- a/chromium/storage/browser/blob/mojo_blob_reader.cc +++ b/chromium/storage/browser/blob/mojo_blob_reader.cc @@ -5,7 +5,6 @@ #include "storage/browser/blob/mojo_blob_reader.h" #include "base/bind.h" -#include "base/feature_list.h" #include "base/trace_event/trace_event.h" #include "net/base/io_buffer.h" #include "services/network/public/cpp/net_adapters.h" @@ -14,17 +13,6 @@ namespace storage { -namespace { - -// This feature will eagerly complete reading when there are no more remaining -// bytes to be read. The default behavior is to trigger another read cycle to -// detect the condition which may be delayed depending on the capacity of the -// target mojo data pipe. -const base::Feature kBlobReaderEagerCompletion{ - "BlobReaderEagerCompletion", base::FEATURE_DISABLED_BY_DEFAULT}; - -} // namespace - // static void MojoBlobReader::Create( const BlobDataHandle* handle, @@ -251,9 +239,7 @@ void MojoBlobReader::DidRead(bool completed_synchronously, int num_bytes) { response_body_stream_ = pending_write_->Complete(num_bytes); total_written_bytes_ += num_bytes; pending_write_ = nullptr; - if (num_bytes == 0 || - (base::FeatureList::IsEnabled(kBlobReaderEagerCompletion) && - blob_reader_->remaining_bytes() == 0)) { + if (num_bytes == 0 || blob_reader_->remaining_bytes() == 0) { response_body_stream_.reset(); // This closes the data pipe. NotifyCompletedAndDeleteIfNeeded(net::OK); return; diff --git a/chromium/storage/browser/blob/view_blob_internals_job.cc b/chromium/storage/browser/blob/view_blob_internals_job.cc index e405ff85cfa..c80b932754b 100644 --- a/chromium/storage/browser/blob/view_blob_internals_job.cc +++ b/chromium/storage/browser/blob/view_blob_internals_job.cc @@ -6,6 +6,7 @@ #include <stddef.h> #include <stdint.h> +#include <sstream> #include "base/bind.h" #include "base/compiler_specific.h" @@ -22,7 +23,6 @@ #include "base/threading/thread_task_runner_handle.h" #include "net/base/escape.h" #include "net/base/net_errors.h" -#include "net/disk_cache/disk_cache.h" #include "net/url_request/url_request.h" #include "storage/browser/blob/blob_data_item.h" #include "storage/browser/blob/blob_entry.h" @@ -273,13 +273,13 @@ void ViewBlobInternalsJob::GenerateHTMLForBlobData( out); } break; - case BlobDataItem::Type::kDiskCacheEntry: - AddHTMLListItem(kType, "disk cache entry", out); - if (item.disk_cache_entry()) - AddHTMLListItem(kURL, item.disk_cache_entry()->GetKey(), out); - else - AddHTMLListItem(kURL, "Broken", out); + case BlobDataItem::Type::kReadableDataHandle: { + AddHTMLListItem(kType, "readable data handle", out); + std::stringstream ss; + item.data_handle()->PrintTo(&ss); + AddHTMLListItem(kURL, ss.str(), out); break; + } case BlobDataItem::Type::kBytesDescription: AddHTMLListItem(kType, "pending data", out); break; diff --git a/chromium/storage/browser/fileapi/async_file_util.h b/chromium/storage/browser/fileapi/async_file_util.h index 3a5f45e1478..da9090e9bf7 100644 --- a/chromium/storage/browser/fileapi/async_file_util.h +++ b/chromium/storage/browser/fileapi/async_file_util.h @@ -14,7 +14,7 @@ #include "base/component_export.h" #include "base/files/file.h" #include "base/macros.h" -#include "components/services/filesystem/public/interfaces/types.mojom.h" +#include "components/services/filesystem/public/mojom/types.mojom.h" #include "storage/browser/fileapi/file_system_operation.h" namespace base { diff --git a/chromium/storage/browser/fileapi/async_file_util_adapter.cc b/chromium/storage/browser/fileapi/async_file_util_adapter.cc index e1cf9bcaf69..b297ec7f066 100644 --- a/chromium/storage/browser/fileapi/async_file_util_adapter.cc +++ b/chromium/storage/browser/fileapi/async_file_util_adapter.cc @@ -16,7 +16,7 @@ #include "base/sequenced_task_runner.h" #include "base/task_runner_util.h" #include "base/threading/thread_task_runner_handle.h" -#include "components/services/filesystem/public/interfaces/types.mojom.h" +#include "components/services/filesystem/public/mojom/types.mojom.h" #include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_file_util.h" diff --git a/chromium/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc b/chromium/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc index 698a36e9dfb..b6df0806153 100644 --- a/chromium/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc +++ b/chromium/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc @@ -23,7 +23,7 @@ #include "base/stl_util.h" #include "base/test/scoped_task_environment.h" #include "base/threading/thread_task_runner_handle.h" -#include "components/services/filesystem/public/interfaces/types.mojom.h" +#include "components/services/filesystem/public/mojom/types.mojom.h" #include "storage/browser/fileapi/copy_or_move_file_validator.h" #include "storage/browser/fileapi/copy_or_move_operation_delegate.h" #include "storage/browser/fileapi/file_stream_reader.h" @@ -337,7 +337,7 @@ class CopyOrMoveOperationTestHelper { base::FilePath relative; root.virtual_path().AppendRelativePath(url.virtual_path(), &relative); relative = relative.NormalizePathSeparators(); - ASSERT_TRUE(base::ContainsKey(test_case_map, relative)); + ASSERT_TRUE(base::Contains(test_case_map, relative)); if (entries[i].type == filesystem::mojom::FsFileType::DIRECTORY) { EXPECT_TRUE(test_case_map[relative]->is_directory); directories.push(url); diff --git a/chromium/storage/browser/fileapi/dragged_file_util.cc b/chromium/storage/browser/fileapi/dragged_file_util.cc index 9f913f29cc9..bcc98d3f675 100644 --- a/chromium/storage/browser/fileapi/dragged_file_util.cc +++ b/chromium/storage/browser/fileapi/dragged_file_util.cc @@ -99,7 +99,7 @@ base::File::Error DraggedFileUtil::GetFileInfo( } base::File::Error error = NativeFileUtil::GetFileInfo(url.path(), file_info); - if (base::IsLink(url.path()) && !base::FilePath().IsParent(url.path())) { + if (IsHiddenItem(url.path()) && !base::FilePath().IsParent(url.path())) { // Don't follow symlinks unless it's the one that are selected by the user. return base::File::FILE_ERROR_NOT_FOUND; } diff --git a/chromium/storage/browser/fileapi/dragged_file_util_unittest.cc b/chromium/storage/browser/fileapi/dragged_file_util_unittest.cc index c3f54f6fe3c..85ce3f4cfea 100644 --- a/chromium/storage/browser/fileapi/dragged_file_util_unittest.cc +++ b/chromium/storage/browser/fileapi/dragged_file_util_unittest.cc @@ -20,7 +20,7 @@ #include "base/stl_util.h" #include "base/time/time.h" #include "build/build_config.h" -#include "components/services/filesystem/public/interfaces/types.mojom.h" +#include "components/services/filesystem/public/mojom/types.mojom.h" #include "storage/browser/fileapi/dragged_file_util.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_operation_context.h" diff --git a/chromium/storage/browser/fileapi/file_stream_reader.h b/chromium/storage/browser/fileapi/file_stream_reader.h index 1d627759a03..6c987a0310d 100644 --- a/chromium/storage/browser/fileapi/file_stream_reader.h +++ b/chromium/storage/browser/fileapi/file_stream_reader.h @@ -74,7 +74,7 @@ class FileStreamReader { // modification time to see if the file has been modified, and if it does any // succeeding read operations should fail with ERR_UPLOAD_FILE_CHANGED error. COMPONENT_EXPORT(STORAGE_BROWSER) - static FileStreamReader* CreateForFileSystemFile( + static std::unique_ptr<FileStreamReader> CreateForFileSystemFile( storage::FileSystemContext* context, const storage::FileSystemURL& url, int64_t initial_offset, diff --git a/chromium/storage/browser/fileapi/file_system_context.cc b/chromium/storage/browser/fileapi/file_system_context.cc index cc449776b8b..e34edd52b31 100644 --- a/chromium/storage/browser/fileapi/file_system_context.cc +++ b/chromium/storage/browser/fileapi/file_system_context.cc @@ -185,8 +185,8 @@ FileSystemContext::FileSystemContext( // Chrome OS the additional backend chromeos::FileSystemBackend handles these // types. isolated_backend_.reset(new IsolatedFileSystemBackend( - !base::ContainsKey(backend_map_, kFileSystemTypeNativeLocal), - !base::ContainsKey(backend_map_, kFileSystemTypeNativeForPlatformApp))); + !base::Contains(backend_map_, kFileSystemTypeNativeLocal), + !base::Contains(backend_map_, kFileSystemTypeNativeForPlatformApp))); RegisterBackend(isolated_backend_.get()); if (quota_manager_proxy) { diff --git a/chromium/storage/browser/fileapi/file_system_dir_url_request_job.cc b/chromium/storage/browser/fileapi/file_system_dir_url_request_job.cc index a079a3129af..7daabb9d86d 100644 --- a/chromium/storage/browser/fileapi/file_system_dir_url_request_job.cc +++ b/chromium/storage/browser/fileapi/file_system_dir_url_request_job.cc @@ -17,7 +17,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "build/build_config.h" -#include "components/services/filesystem/public/interfaces/types.mojom.h" +#include "components/services/filesystem/public/mojom/types.mojom.h" #include "net/base/directory_listing.h" #include "net/base/io_buffer.h" #include "net/url_request/url_request.h" diff --git a/chromium/storage/browser/fileapi/file_system_dir_url_request_job.h b/chromium/storage/browser/fileapi/file_system_dir_url_request_job.h index 918b10b5c49..ecca687cd89 100644 --- a/chromium/storage/browser/fileapi/file_system_dir_url_request_job.h +++ b/chromium/storage/browser/fileapi/file_system_dir_url_request_job.h @@ -15,7 +15,7 @@ #include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "components/services/filesystem/public/interfaces/types.mojom.h" +#include "components/services/filesystem/public/mojom/types.mojom.h" #include "net/url_request/url_request_job.h" #include "storage/browser/fileapi/file_system_url.h" diff --git a/chromium/storage/browser/fileapi/file_system_file_stream_reader.cc b/chromium/storage/browser/fileapi/file_system_file_stream_reader.cc index 19a45d98c14..5f9a6793da2 100644 --- a/chromium/storage/browser/fileapi/file_system_file_stream_reader.cc +++ b/chromium/storage/browser/fileapi/file_system_file_stream_reader.cc @@ -8,6 +8,8 @@ #include <utility> +#include "base/memory/ptr_util.h" +#include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "net/base/file_stream.h" #include "net/base/io_buffer.h" @@ -15,6 +17,8 @@ #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_features.h" #include "storage/browser/fileapi/file_system_operation_runner.h" +#include "storage/browser/fileapi/obfuscated_file_util_memory_delegate.h" +#include "storage/browser/fileapi/plugin_private_file_system_backend.h" using storage::FileStreamReader; @@ -22,13 +26,13 @@ using storage::FileStreamReader; // blob and fileapi into content namespace. namespace storage { -FileStreamReader* FileStreamReader::CreateForFileSystemFile( - storage::FileSystemContext* file_system_context, - const storage::FileSystemURL& url, +std::unique_ptr<FileStreamReader> FileStreamReader::CreateForFileSystemFile( + FileSystemContext* file_system_context, + const FileSystemURL& url, int64_t initial_offset, const base::Time& expected_modification_time) { - return new storage::FileSystemFileStreamReader( - file_system_context, url, initial_offset, expected_modification_time); + return base::WrapUnique(new FileSystemFileStreamReader( + file_system_context, url, initial_offset, expected_modification_time)); } FileSystemFileStreamReader::FileSystemFileStreamReader( @@ -101,9 +105,20 @@ void FileSystemFileStreamReader::DidCreateSnapshot( if (file_system_context_->is_incognito() && base::FeatureList::IsEnabled(features::kEnableFilesystemInIncognito)) { + base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util_delegate; + if (url_.type() == kFileSystemTypePluginPrivate) { + auto* backend = static_cast<PluginPrivateFileSystemBackend*>( + file_system_context_->GetFileSystemBackend( + kFileSystemTypePluginPrivate)); + memory_file_util_delegate = + backend->obfuscated_file_util_memory_delegate()->GetWeakPtr(); + } else { + memory_file_util_delegate = + file_system_context_->sandbox_delegate()->memory_file_util_delegate(); + } file_reader_ = FileStreamReader::CreateForMemoryFile( - file_system_context_->sandbox_delegate()->memory_file_util_delegate(), - platform_path, initial_offset_, expected_modification_time_); + memory_file_util_delegate, platform_path, initial_offset_, + expected_modification_time_); } else { file_reader_ = FileStreamReader::CreateForLocalFile( file_system_context_->default_file_task_runner(), platform_path, diff --git a/chromium/storage/browser/fileapi/file_system_file_util.h b/chromium/storage/browser/fileapi/file_system_file_util.h index 57a073528bc..bc4b2b449c0 100644 --- a/chromium/storage/browser/fileapi/file_system_file_util.h +++ b/chromium/storage/browser/fileapi/file_system_file_util.h @@ -98,7 +98,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemFileUtil { // current call returns to the main FILE message loop. // // The supplied context must remain valid at least lifetime of the enumerator - // instance. + // instance. |this| must remain valid through the lifetime of the created + // enumerator instance. virtual std::unique_ptr<AbstractFileEnumerator> CreateFileEnumerator( FileSystemOperationContext* context, const FileSystemURL& root_url, diff --git a/chromium/storage/browser/fileapi/file_system_operation.h b/chromium/storage/browser/fileapi/file_system_operation.h index 14ca1eb766a..450bf98f658 100644 --- a/chromium/storage/browser/fileapi/file_system_operation.h +++ b/chromium/storage/browser/fileapi/file_system_operation.h @@ -15,7 +15,7 @@ #include "base/files/file.h" #include "base/files/file_path.h" #include "base/process/process.h" -#include "components/services/filesystem/public/interfaces/types.mojom.h" +#include "components/services/filesystem/public/mojom/types.mojom.h" #include "storage/browser/blob/blob_reader.h" #include "storage/browser/fileapi/file_system_operation_context.h" diff --git a/chromium/storage/browser/fileapi/file_system_operation_impl.cc b/chromium/storage/browser/fileapi/file_system_operation_impl.cc index db2527cbf86..1782d6e18c0 100644 --- a/chromium/storage/browser/fileapi/file_system_operation_impl.cc +++ b/chromium/storage/browser/fileapi/file_system_operation_impl.cc @@ -15,7 +15,6 @@ #include "base/single_thread_task_runner.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" -#include "base/trace_event/trace_event.h" #include "net/base/escape.h" #include "net/url_request/url_request.h" #include "storage/browser/blob/shareable_file_reference.h" @@ -68,9 +67,6 @@ FileSystemOperationImpl::~FileSystemOperationImpl() = default; void FileSystemOperationImpl::CreateFile(const FileSystemURL& url, bool exclusive, StatusCallback callback) { - // crbug.com/349708 - TRACE_EVENT0("io", "FileSystemOperationImpl::CreateFile"); - DCHECK(SetPendingOperationType(kOperationCreateFile)); auto repeatable_callback = @@ -89,9 +85,6 @@ void FileSystemOperationImpl::CreateDirectory(const FileSystemURL& url, StatusCallback callback) { DCHECK(SetPendingOperationType(kOperationCreateDirectory)); - // crbug.com/349708 - TRACE_EVENT0("io", "FileSystemOperationImpl::CreateDirectory"); - auto repeatable_callback = base::AdaptCallbackForRepeating(std::move(callback)); GetUsageAndQuotaThenRunTask( @@ -224,9 +217,6 @@ void FileSystemOperationImpl::Truncate(const FileSystemURL& url, StatusCallback callback) { DCHECK(SetPendingOperationType(kOperationTruncate)); - // crbug.com/349708 - TRACE_EVENT0("io", "FileSystemOperationImpl::Truncate"); - auto repeatable_callback = base::AdaptCallbackForRepeating(std::move(callback)); GetUsageAndQuotaThenRunTask( @@ -243,9 +233,6 @@ void FileSystemOperationImpl::TouchFile(const FileSystemURL& url, StatusCallback callback) { DCHECK(SetPendingOperationType(kOperationTouchFile)); - // crbug.com/349708 - TRACE_EVENT0("io", "FileSystemOperationImpl::TouchFile"); - async_file_util_->Touch( std::move(operation_context_), url, last_access_time, last_modified_time, base::BindOnce(&FileSystemOperationImpl::DidFinishOperation, @@ -263,9 +250,6 @@ void FileSystemOperationImpl::OpenFile(const FileSystemURL& url, return; } - // crbug.com/349708 - TRACE_EVENT0("io", "FileSystemOperationImpl::OpenFile"); - auto repeatable_callback = base::AdaptCallbackForRepeating(std::move(callback)); GetUsageAndQuotaThenRunTask( @@ -312,9 +296,6 @@ void FileSystemOperationImpl::CopyInForeignFile( StatusCallback callback) { DCHECK(SetPendingOperationType(kOperationCopyInForeignFile)); - // crbug.com/349708 - TRACE_EVENT0("io", "FileSystemOperationImpl::CopyInForeinFile"); - auto repeatable_callback = base::AdaptCallbackForRepeating(std::move(callback)); GetUsageAndQuotaThenRunTask( @@ -352,9 +333,6 @@ void FileSystemOperationImpl::CopyFileLocal( DCHECK(SetPendingOperationType(kOperationCopy)); DCHECK(src_url.IsInSameFileSystem(dest_url)); - // crbug.com/349708 - TRACE_EVENT0("io", "FileSystemOperationImpl::CopyFileLocal"); - auto repeatable_callback = base::AdaptCallbackForRepeating(std::move(callback)); GetUsageAndQuotaThenRunTask( @@ -372,9 +350,6 @@ void FileSystemOperationImpl::MoveFileLocal(const FileSystemURL& src_url, DCHECK(SetPendingOperationType(kOperationMove)); DCHECK(src_url.IsInSameFileSystem(dest_url)); - // crbug.com/349708 - TRACE_EVENT0("io", "FileSystemOperationImpl::MoveFileLocal"); - auto repeatable_callback = base::AdaptCallbackForRepeating(std::move(callback)); GetUsageAndQuotaThenRunTask( diff --git a/chromium/storage/browser/fileapi/file_system_operation_impl_unittest.cc b/chromium/storage/browser/fileapi/file_system_operation_impl_unittest.cc index 26fb3357ff1..264502ab215 100644 --- a/chromium/storage/browser/fileapi/file_system_operation_impl_unittest.cc +++ b/chromium/storage/browser/fileapi/file_system_operation_impl_unittest.cc @@ -23,7 +23,7 @@ #include "base/strings/stringprintf.h" #include "base/test/scoped_task_environment.h" #include "base/threading/thread_task_runner_handle.h" -#include "components/services/filesystem/public/interfaces/types.mojom.h" +#include "components/services/filesystem/public/mojom/types.mojom.h" #include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_file_util.h" diff --git a/chromium/storage/browser/fileapi/file_system_operation_runner.cc b/chromium/storage/browser/fileapi/file_system_operation_runner.cc index da43145151e..d9b52d6c40d 100644 --- a/chromium/storage/browser/fileapi/file_system_operation_runner.cc +++ b/chromium/storage/browser/fileapi/file_system_operation_runner.cc @@ -329,8 +329,8 @@ OperationID FileSystemOperationRunner::Truncate(const FileSystemURL& url, void FileSystemOperationRunner::Cancel(OperationID id, StatusCallback callback) { - if (base::ContainsKey(finished_operations_, id)) { - DCHECK(!base::ContainsKey(stray_cancel_callbacks_, id)); + if (base::Contains(finished_operations_, id)) { + DCHECK(!base::Contains(stray_cancel_callbacks_, id)); stray_cancel_callbacks_[id] = std::move(callback); return; } diff --git a/chromium/storage/browser/fileapi/file_system_operation_runner.h b/chromium/storage/browser/fileapi/file_system_operation_runner.h index 80cd29877d4..d29e26d0f52 100644 --- a/chromium/storage/browser/fileapi/file_system_operation_runner.h +++ b/chromium/storage/browser/fileapi/file_system_operation_runner.h @@ -16,7 +16,7 @@ #include "base/containers/id_map.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "components/services/filesystem/public/interfaces/types.mojom.h" +#include "components/services/filesystem/public/mojom/types.mojom.h" #include "storage/browser/blob/blob_data_handle.h" #include "storage/browser/fileapi/file_system_operation.h" #include "storage/browser/fileapi/file_system_url.h" diff --git a/chromium/storage/browser/fileapi/file_system_usage_cache.cc b/chromium/storage/browser/fileapi/file_system_usage_cache.cc index 599456d5fe3..a94d96360d1 100644 --- a/chromium/storage/browser/fileapi/file_system_usage_cache.cc +++ b/chromium/storage/browser/fileapi/file_system_usage_cache.cc @@ -148,7 +148,7 @@ bool FileSystemUsageCache::Exists(const base::FilePath& usage_file_path) { TRACE_EVENT0("FileSystem", "UsageCache::Exists"); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (is_incognito_) - return base::ContainsKey(incognito_usages_, usage_file_path); + return base::Contains(incognito_usages_, usage_file_path); return base::PathExists(usage_file_path); } @@ -157,7 +157,7 @@ bool FileSystemUsageCache::Delete(const base::FilePath& usage_file_path) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); CloseCacheFiles(); if (is_incognito_) { - if (!base::ContainsKey(incognito_usages_, usage_file_path)) + if (!base::Contains(incognito_usages_, usage_file_path)) return false; incognito_usages_.erase(incognito_usages_.find(usage_file_path)); return true; @@ -262,7 +262,7 @@ bool FileSystemUsageCache::ReadBytes(const base::FilePath& file_path, int64_t buffer_size) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (is_incognito_) { - if (!base::ContainsKey(incognito_usages_, file_path)) + if (!base::Contains(incognito_usages_, file_path)) return false; memcpy(buffer, incognito_usages_[file_path].data(), buffer_size); return true; @@ -278,7 +278,7 @@ bool FileSystemUsageCache::WriteBytes(const base::FilePath& file_path, int64_t buffer_size) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (is_incognito_) { - if (!base::ContainsKey(incognito_usages_, file_path)) + if (!base::Contains(incognito_usages_, file_path)) incognito_usages_[file_path] = std::vector<uint8_t>(buffer_size); memcpy(incognito_usages_[file_path].data(), buffer, buffer_size); return true; @@ -293,7 +293,7 @@ bool FileSystemUsageCache::FlushFile(const base::FilePath& file_path) { TRACE_EVENT0("FileSystem", "UsageCache::FlushFile"); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (is_incognito_) - return base::ContainsKey(incognito_usages_, file_path); + return base::Contains(incognito_usages_, file_path); base::File* file = GetFile(file_path); if (!file) return false; @@ -316,7 +316,7 @@ void FileSystemUsageCache::ScheduleCloseTimer() { bool FileSystemUsageCache::HasCacheFileHandle(const base::FilePath& file_path) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_LE(cache_files_.size(), kMaxHandleCacheSize); - return base::ContainsKey(cache_files_, file_path); + return base::Contains(cache_files_, file_path); } } // namespace storage diff --git a/chromium/storage/browser/fileapi/file_system_usage_cache_unittest.cc b/chromium/storage/browser/fileapi/file_system_usage_cache_unittest.cc index 00fe2340679..663fbf84cd1 100644 --- a/chromium/storage/browser/fileapi/file_system_usage_cache_unittest.cc +++ b/chromium/storage/browser/fileapi/file_system_usage_cache_unittest.cc @@ -11,8 +11,8 @@ #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/macros.h" -#include "base/message_loop/message_loop.h" #include "base/test/scoped_feature_list.h" +#include "base/test/scoped_task_environment.h" #include "storage/browser/fileapi/file_system_features.h" #include "testing/gtest/include/gtest/gtest.h" @@ -43,7 +43,7 @@ class FileSystemUsageCacheTest : public testing::Test, private: base::test::ScopedFeatureList feature_list_; - base::MessageLoop message_loop_; + base::test::ScopedTaskEnvironment scoped_task_environment_; base::ScopedTempDir data_dir_; FileSystemUsageCache usage_cache_; diff --git a/chromium/storage/browser/fileapi/local_file_util.cc b/chromium/storage/browser/fileapi/local_file_util.cc index 951bfacea95..a1cc69e5f8f 100644 --- a/chromium/storage/browser/fileapi/local_file_util.cc +++ b/chromium/storage/browser/fileapi/local_file_util.cc @@ -26,56 +26,52 @@ AsyncFileUtil* AsyncFileUtil::CreateForLocalFileSystem() { return new AsyncFileUtilAdapter(new LocalFileUtil()); } -class LocalFileEnumerator : public FileSystemFileUtil::AbstractFileEnumerator { +class LocalFileUtil::LocalFileEnumerator + : public FileSystemFileUtil::AbstractFileEnumerator { public: - LocalFileEnumerator(const base::FilePath& platform_root_path, + LocalFileEnumerator(const LocalFileUtil* file_util, + const base::FilePath& platform_root_path, const base::FilePath& virtual_root_path, bool recursive, int file_type) - : file_enum_(platform_root_path, recursive, file_type), + : file_util_(file_util), + file_enum_(platform_root_path, recursive, file_type), platform_root_path_(platform_root_path), virtual_root_path_(virtual_root_path) {} ~LocalFileEnumerator() override = default; - base::FilePath Next() override; - int64_t Size() override; - base::Time LastModifiedTime() override; - bool IsDirectory() override; + base::FilePath Next() override { + base::FilePath next = file_enum_.Next(); + while (!next.empty() && file_util_->IsHiddenItem(next)) + next = file_enum_.Next(); + if (next.empty()) + return next; + file_util_info_ = file_enum_.GetInfo(); + + base::FilePath path; + platform_root_path_.AppendRelativePath(next, &path); + return virtual_root_path_.Append(path); + } + + int64_t Size() override { return file_util_info_.GetSize(); } + + base::Time LastModifiedTime() override { + return file_util_info_.GetLastModifiedTime(); + } + + bool IsDirectory() override { return file_util_info_.IsDirectory(); } private: + // The |LocalFileUtil| producing |this| is expected to remain valid + // through the whole lifetime of the enumerator. + const LocalFileUtil* const file_util_; base::FileEnumerator file_enum_; base::FileEnumerator::FileInfo file_util_info_; base::FilePath platform_root_path_; base::FilePath virtual_root_path_; }; -base::FilePath LocalFileEnumerator::Next() { - base::FilePath next = file_enum_.Next(); - // Don't return symlinks. - while (!next.empty() && base::IsLink(next)) - next = file_enum_.Next(); - if (next.empty()) - return next; - file_util_info_ = file_enum_.GetInfo(); - - base::FilePath path; - platform_root_path_.AppendRelativePath(next, &path); - return virtual_root_path_.Append(path); -} - -int64_t LocalFileEnumerator::Size() { - return file_util_info_.GetSize(); -} - -base::Time LocalFileEnumerator::LastModifiedTime() { - return file_util_info_.GetLastModifiedTime(); -} - -bool LocalFileEnumerator::IsDirectory() { - return file_util_info_.IsDirectory(); -} - LocalFileUtil::LocalFileUtil() = default; LocalFileUtil::~LocalFileUtil() = default; @@ -87,8 +83,7 @@ base::File LocalFileUtil::CreateOrOpen( base::File::Error error = GetLocalFilePath(context, url, &file_path); if (error != base::File::FILE_OK) return base::File(error); - // Disallow opening files in symlinked paths. - if (base::IsLink(file_path)) + if (IsHiddenItem(file_path)) return base::File(base::File::FILE_ERROR_NOT_FOUND); return NativeFileUtil::CreateOrOpen(file_path, file_flags); @@ -126,8 +121,7 @@ base::File::Error LocalFileUtil::GetFileInfo( base::File::Error error = GetLocalFilePath(context, url, &file_path); if (error != base::File::FILE_OK) return error; - // We should not follow symbolic links in sandboxed file system. - if (base::IsLink(file_path)) + if (IsHiddenItem(file_path)) return base::File::FILE_ERROR_NOT_FOUND; error = NativeFileUtil::GetFileInfo(file_path, file_info); @@ -146,7 +140,7 @@ LocalFileUtil::CreateFileEnumerator(FileSystemOperationContext* context, return base::WrapUnique(new EmptyFileEnumerator); } return std::make_unique<LocalFileEnumerator>( - file_path, root_url.path(), recursive, + this, file_path, root_url.path(), recursive, base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES); } @@ -263,4 +257,9 @@ storage::ScopedFile LocalFileUtil::CreateSnapshotFile( return storage::ScopedFile(); } +bool LocalFileUtil::IsHiddenItem(const base::FilePath& local_file_path) const { + // We should not follow symbolic links in sandboxed file system. + return base::IsLink(local_file_path); +} + } // namespace storage diff --git a/chromium/storage/browser/fileapi/local_file_util.h b/chromium/storage/browser/fileapi/local_file_util.h index 47c98367e6e..96b1b9a2368 100644 --- a/chromium/storage/browser/fileapi/local_file_util.h +++ b/chromium/storage/browser/fileapi/local_file_util.h @@ -45,10 +45,13 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) LocalFileUtil const FileSystemURL& url, base::File::Info* file_info, base::FilePath* platform_file) override; + + // |this| must remain valid through the lifetime of the created enumerator. std::unique_ptr<AbstractFileEnumerator> CreateFileEnumerator( FileSystemOperationContext* context, const FileSystemURL& root_url, bool recursive) override; + base::File::Error GetLocalFilePath(FileSystemOperationContext* context, const FileSystemURL& file_system_url, base::FilePath* local_file_path) override; @@ -78,7 +81,16 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) LocalFileUtil base::File::Info* file_info, base::FilePath* platform_path) override; + protected: + // Whether this item should not be accessed. For security reasons by default + // symlinks are not exposed through |this|. If the derived implementation + // can ensure safety of symlinks in some other way, it can lift this + // restriction by overriding this method. + virtual bool IsHiddenItem(const base::FilePath& local_file_path) const; + private: + class LocalFileEnumerator; + DISALLOW_COPY_AND_ASSIGN(LocalFileUtil); }; diff --git a/chromium/storage/browser/fileapi/obfuscated_file_util.cc b/chromium/storage/browser/fileapi/obfuscated_file_util.cc index 949377c2aa3..bdb9c54fb62 100644 --- a/chromium/storage/browser/fileapi/obfuscated_file_util.cc +++ b/chromium/storage/browser/fileapi/obfuscated_file_util.cc @@ -1009,7 +1009,7 @@ void ObfuscatedFileUtil::MaybePrepopulateDatabase( for (size_t i = 0; i < type_strings_to_prepopulate.size(); ++i) { const std::string type_string = type_strings_to_prepopulate[i]; // Only handles known types. - if (!base::ContainsKey(known_type_strings_, type_string)) + if (!base::Contains(known_type_strings_, type_string)) continue; base::File::Error error = base::File::FILE_ERROR_FAILED; base::FilePath path = GetDirectoryForOriginAndType( diff --git a/chromium/storage/browser/fileapi/obfuscated_file_util_unittest.cc b/chromium/storage/browser/fileapi/obfuscated_file_util_unittest.cc index c2bd85b72a4..c49af97174f 100644 --- a/chromium/storage/browser/fileapi/obfuscated_file_util_unittest.cc +++ b/chromium/storage/browser/fileapi/obfuscated_file_util_unittest.cc @@ -24,7 +24,7 @@ #include "base/test/scoped_task_environment.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" -#include "components/services/filesystem/public/interfaces/types.mojom.h" +#include "components/services/filesystem/public/mojom/types.mojom.h" #include "net/base/io_buffer.h" #include "storage/browser/fileapi/external_mount_points.h" #include "storage/browser/fileapi/file_system_backend.h" @@ -49,6 +49,13 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/leveldatabase/leveldb_chrome.h" +// TODO(crbug.com/961068): Fix memory leaks in tests and re-enable on LSAN. +#ifdef LEAK_SANITIZER +#define MAYBE_TestQuotaOnTruncation DISABLED_TestQuotaOnTruncation +#else +#define MAYBE_TestQuotaOnTruncation TestQuotaOnTruncation +#endif + using content::AsyncFileTestHelper; using storage::FileSystemContext; using storage::FileSystemOperation; @@ -978,7 +985,7 @@ TEST_P(ObfuscatedFileUtilTest, TestTruncate) { EXPECT_TRUE(change_observer()->HasNoChange()); } -TEST_P(ObfuscatedFileUtilTest, TestQuotaOnTruncation) { +TEST_P(ObfuscatedFileUtilTest, MAYBE_TestQuotaOnTruncation) { bool created = false; FileSystemURL url = CreateURLFromUTF8("file"); diff --git a/chromium/storage/browser/fileapi/plugin_private_file_system_backend.cc b/chromium/storage/browser/fileapi/plugin_private_file_system_backend.cc index 6dbc0ba7830..bbd941731ca 100644 --- a/chromium/storage/browser/fileapi/plugin_private_file_system_backend.cc +++ b/chromium/storage/browser/fileapi/plugin_private_file_system_backend.cc @@ -26,7 +26,9 @@ #include "storage/browser/fileapi/file_system_operation_context.h" #include "storage/browser/fileapi/isolated_context.h" #include "storage/browser/fileapi/obfuscated_file_util.h" +#include "storage/browser/fileapi/obfuscated_file_util_memory_delegate.h" #include "storage/browser/fileapi/quota/quota_reservation.h" +#include "storage/browser/fileapi/sandbox_file_stream_writer.h" #include "storage/common/fileapi/file_system_util.h" namespace storage { @@ -51,7 +53,7 @@ class PluginPrivateFileSystemBackend::FileSystemIDToPluginMap { const std::string& plugin_id) { DCHECK(task_runner_->RunsTasksInCurrentSequence()); DCHECK(!filesystem_id.empty()); - DCHECK(!base::ContainsKey(map_, filesystem_id)) << filesystem_id; + DCHECK(!base::Contains(map_, filesystem_id)) << filesystem_id; map_[filesystem_id] = plugin_id; } @@ -125,7 +127,7 @@ void PluginPrivateFileSystemBackend::OpenPrivateFileSystem( const std::string& plugin_id, OpenFileSystemMode mode, StatusCallback callback) { - if (!CanHandleType(type) || file_system_options_.is_incognito()) { + if (!CanHandleType(type)) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), base::File::FILE_ERROR_SECURITY)); @@ -187,23 +189,28 @@ FileSystemOperation* PluginPrivateFileSystemBackend::CreateFileSystemOperation( } bool PluginPrivateFileSystemBackend::SupportsStreaming( - const storage::FileSystemURL& url) const { - return false; + const FileSystemURL& url) const { + // Streaming is required for incognito file systems in order to access + // memory-backed files. + DCHECK(CanHandleType(url.type())); + return file_system_options_.is_incognito(); } bool PluginPrivateFileSystemBackend::HasInplaceCopyImplementation( - storage::FileSystemType type) const { + FileSystemType type) const { return false; } -std::unique_ptr<storage::FileStreamReader> +std::unique_ptr<FileStreamReader> PluginPrivateFileSystemBackend::CreateFileStreamReader( const FileSystemURL& url, int64_t offset, int64_t max_bytes_to_read, const base::Time& expected_modification_time, FileSystemContext* context) const { - return std::unique_ptr<storage::FileStreamReader>(); + DCHECK(CanHandleType(url.type())); + return FileStreamReader::CreateForFileSystemFile(context, url, offset, + expected_modification_time); } std::unique_ptr<FileStreamWriter> @@ -211,7 +218,11 @@ PluginPrivateFileSystemBackend::CreateFileStreamWriter( const FileSystemURL& url, int64_t offset, FileSystemContext* context) const { - return std::unique_ptr<FileStreamWriter>(); + DCHECK(CanHandleType(url.type())); + + // Observers not supported by PluginPrivateFileSystemBackend. + return std::make_unique<SandboxFileStreamWriter>(context, url, offset, + UpdateObserverList()); } FileSystemQuotaUtil* PluginPrivateFileSystemBackend::GetQuotaUtil() { @@ -373,4 +384,11 @@ ObfuscatedFileUtil* PluginPrivateFileSystemBackend::obfuscated_file_util() { static_cast<AsyncFileUtilAdapter*>(file_util_.get())->sync_file_util()); } +ObfuscatedFileUtilMemoryDelegate* +PluginPrivateFileSystemBackend::obfuscated_file_util_memory_delegate() { + auto* file_util = obfuscated_file_util(); + DCHECK(file_util->is_incognito()); + return static_cast<ObfuscatedFileUtilMemoryDelegate*>(file_util->delegate()); +} + } // namespace storage diff --git a/chromium/storage/browser/fileapi/plugin_private_file_system_backend.h b/chromium/storage/browser/fileapi/plugin_private_file_system_backend.h index 6fab28d7e80..8fb94aac4a6 100644 --- a/chromium/storage/browser/fileapi/plugin_private_file_system_backend.h +++ b/chromium/storage/browser/fileapi/plugin_private_file_system_backend.h @@ -35,6 +35,7 @@ class Env; namespace storage { class ObfuscatedFileUtil; +class ObfuscatedFileUtilMemoryDelegate; class SpecialStoragePolicy; class WatcherManager; @@ -132,6 +133,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) PluginPrivateFileSystemBackend int64_t* total_size, base::Time* last_modified_time); + ObfuscatedFileUtilMemoryDelegate* obfuscated_file_util_memory_delegate(); + private: friend class content::PluginPrivateFileSystemBackendTest; diff --git a/chromium/storage/browser/fileapi/plugin_private_file_system_backend_unittest.cc b/chromium/storage/browser/fileapi/plugin_private_file_system_backend_unittest.cc index 948eddfa72a..53b33b405d7 100644 --- a/chromium/storage/browser/fileapi/plugin_private_file_system_backend_unittest.cc +++ b/chromium/storage/browser/fileapi/plugin_private_file_system_backend_unittest.cc @@ -7,8 +7,8 @@ #include "base/bind.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/isolated_context.h" #include "storage/browser/fileapi/obfuscated_file_util.h" @@ -69,7 +69,7 @@ class PluginPrivateFileSystemBackendTest : public testing::Test { const base::FilePath& base_path() const { return backend()->base_path(); } base::ScopedTempDir data_dir_; - base::MessageLoop message_loop_; + base::test::ScopedTaskEnvironment scoped_task_environment_; scoped_refptr<FileSystemContext> context_; }; diff --git a/chromium/storage/browser/fileapi/sandbox_file_stream_writer.cc b/chromium/storage/browser/fileapi/sandbox_file_stream_writer.cc index 9cf34451891..cf734fc1abc 100644 --- a/chromium/storage/browser/fileapi/sandbox_file_stream_writer.cc +++ b/chromium/storage/browser/fileapi/sandbox_file_stream_writer.cc @@ -11,8 +11,8 @@ #include <utility> #include "base/bind.h" +#include "base/memory/weak_ptr.h" #include "base/sequenced_task_runner.h" -#include "base/trace_event/trace_event.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "storage/browser/fileapi/file_observers.h" @@ -20,6 +20,8 @@ #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_features.h" #include "storage/browser/fileapi/file_system_operation_runner.h" +#include "storage/browser/fileapi/obfuscated_file_util_memory_delegate.h" +#include "storage/browser/fileapi/plugin_private_file_system_backend.h" #include "storage/browser/quota/quota_manager_proxy.h" #include "storage/common/fileapi/file_system_util.h" @@ -136,18 +138,29 @@ void SandboxFileStreamWriter::DidCreateSnapshotFile( } file_size_ = file_info.size; if (initial_offset_ > file_size_) { - LOG(ERROR) << initial_offset_ << ", " << file_size_; - // This shouldn't happen as long as we check offset in the renderer. - NOTREACHED(); - initial_offset_ = file_size_; + // We should not be writing pass the end of the file. + std::move(callback).Run(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); + return; } DCHECK(!file_writer_.get()); if (file_system_context_->is_incognito() && base::FeatureList::IsEnabled(features::kEnableFilesystemInIncognito)) { + base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util_delegate; + if (url_.type() == kFileSystemTypePluginPrivate) { + auto* backend = static_cast<PluginPrivateFileSystemBackend*>( + file_system_context_->GetFileSystemBackend( + kFileSystemTypePluginPrivate)); + memory_file_util_delegate = + backend->obfuscated_file_util_memory_delegate()->GetWeakPtr(); + } else { + memory_file_util_delegate = + file_system_context_->sandbox_delegate()->memory_file_util_delegate(); + } file_writer_ = FileStreamWriter::CreateForMemoryFile( - file_system_context_->sandbox_delegate()->memory_file_util_delegate(), - platform_path, initial_offset_, FileStreamWriter::OPEN_EXISTING_FILE); + memory_file_util_delegate, platform_path, initial_offset_, + FileStreamWriter::OPEN_EXISTING_FILE); + } else { file_writer_ = FileStreamWriter::CreateForLocalFile( file_system_context_->default_file_task_runner(), platform_path, @@ -163,9 +176,6 @@ void SandboxFileStreamWriter::DidCreateSnapshotFile( return; } - // crbug.com/349708 - TRACE_EVENT0("io", "SandboxFileStreamWriter::DidCreateSnapshotFile"); - DCHECK(quota_manager_proxy->quota_manager()); quota_manager_proxy->quota_manager()->GetUsageAndQuota( url_.origin(), FileSystemTypeToQuotaStorageType(url_.type()), @@ -183,16 +193,10 @@ void SandboxFileStreamWriter::DidGetUsageAndQuota( if (status != blink::mojom::QuotaStatusCode::kOk) { LOG(WARNING) << "Got unexpected quota error : " << static_cast<int>(status); - // crbug.com/349708 - TRACE_EVENT0("io", "SandboxFileStreamWriter::DidGetUsageAndQuota FAILED"); - std::move(callback).Run(net::ERR_FAILED); return; } - // crbug.com/349708 - TRACE_EVENT0("io", "SandboxFileStreamWriter::DidGetUsageAndQuota OK"); - allowed_bytes_to_write_ = quota - usage; std::move(callback).Run(net::OK); } diff --git a/chromium/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc b/chromium/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc index 728ac2eec4e..85570b432d1 100644 --- a/chromium/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc +++ b/chromium/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc @@ -315,17 +315,16 @@ SandboxFileSystemBackendDelegate::CreateFileSystemOperationContext( return operation_context; } -std::unique_ptr<storage::FileStreamReader> +std::unique_ptr<FileStreamReader> SandboxFileSystemBackendDelegate::CreateFileStreamReader( const FileSystemURL& url, int64_t offset, const base::Time& expected_modification_time, FileSystemContext* context) const { if (!IsAccessValid(url)) - return std::unique_ptr<storage::FileStreamReader>(); - return std::unique_ptr<storage::FileStreamReader>( - storage::FileStreamReader::CreateForFileSystemFile( - context, url, offset, expected_modification_time)); + return nullptr; + return FileStreamReader::CreateForFileSystemFile(context, url, offset, + expected_modification_time); } std::unique_ptr<FileStreamWriter> @@ -417,8 +416,7 @@ int64_t SandboxFileSystemBackendDelegate::GetOriginUsageOnFileTaskRunner( // Don't use usage cache and return recalculated usage for sticky invalidated // origins. - if (base::ContainsKey(sticky_dirty_origins_, - std::make_pair(origin_url, type))) + if (base::Contains(sticky_dirty_origins_, std::make_pair(origin_url, type))) return RecalculateUsage(file_system_context, origin_url, type); base::FilePath base_path = diff --git a/chromium/storage/browser/quota/client_usage_tracker.cc b/chromium/storage/browser/quota/client_usage_tracker.cc index a682cf704ad..368308ed6c5 100644 --- a/chromium/storage/browser/quota/client_usage_tracker.cc +++ b/chromium/storage/browser/quota/client_usage_tracker.cc @@ -7,10 +7,9 @@ #include <stdint.h> #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/stl_util.h" #include "net/base/url_util.h" -#include "storage/browser/quota/storage_monitor.h" -#include "storage/browser/quota/storage_observer.h" namespace storage { @@ -45,7 +44,7 @@ bool OriginSetContainsOrigin(const OriginSetByHost& origins, const std::string& host, const url::Origin& origin) { auto itr = origins.find(host); - return itr != origins.end() && base::ContainsKey(itr->second, origin); + return itr != origins.end() && base::Contains(itr->second, origin); } void DidGetGlobalClientUsageForLimitedGlobalClientUsage( @@ -61,11 +60,9 @@ ClientUsageTracker::ClientUsageTracker( UsageTracker* tracker, QuotaClient* client, blink::mojom::StorageType type, - SpecialStoragePolicy* special_storage_policy, - StorageMonitor* storage_monitor) + SpecialStoragePolicy* special_storage_policy) : client_(client), type_(type), - storage_monitor_(storage_monitor), global_limited_usage_(0), global_unlimited_usage_(0), global_usage_retrieved_(false), @@ -127,9 +124,9 @@ void ClientUsageTracker::GetGlobalUsage(GlobalUsageCallback callback) { void ClientUsageTracker::GetHostUsage(const std::string& host, UsageCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (base::ContainsKey(cached_hosts_, host) && - !base::ContainsKey(non_cached_limited_origins_by_host_, host) && - !base::ContainsKey(non_cached_unlimited_origins_by_host_, host)) { + if (base::Contains(cached_hosts_, host) && + !base::Contains(non_cached_limited_origins_by_host_, host) && + !base::Contains(non_cached_unlimited_origins_by_host_, host)) { // TODO(kinuko): Drop host_usage_map_ cache periodically. std::move(callback).Run(GetCachedHostUsage(host)); return; @@ -148,7 +145,7 @@ void ClientUsageTracker::UpdateUsageCache(const url::Origin& origin, int64_t delta) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); std::string host = net::GetHostOrSpecFromURL(origin.GetURL()); - if (base::ContainsKey(cached_hosts_, host)) { + if (base::Contains(cached_hosts_, host)) { if (!IsUsageCacheEnabledForOrigin(origin)) return; @@ -160,19 +157,12 @@ void ClientUsageTracker::UpdateUsageCache(const url::Origin& origin, : &global_limited_usage_, delta); - // Notify the usage monitor that usage has changed. The storage monitor may - // be nullptr during tests. - if (storage_monitor_) { - StorageObserver::Filter filter(type_, origin); - storage_monitor_->NotifyUsageChange(filter, delta); - } return; } - // We don't know about this host yet, so populate our cache for it. - GetHostUsage(host, - base::BindOnce(&ClientUsageTracker::DidGetHostUsageAfterUpdate, - AsWeakPtr(), origin)); + // We call GetHostUsage() so that the cache still updates, but we don't need + // to do anything else with the usage so we do not pass a callback. + GetHostUsage(host, base::DoNothing()); } int64_t ClientUsageTracker::GetCachedUsage() const { @@ -382,16 +372,6 @@ void ClientUsageTracker::AccumulateOriginUsage( host, info->limited_usage, info->unlimited_usage); } -void ClientUsageTracker::DidGetHostUsageAfterUpdate(const url::Origin& origin, - int64_t usage) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!storage_monitor_) - return; - - StorageObserver::Filter filter(type_, origin); - storage_monitor_->NotifyUsageChange(filter, 0); -} - void ClientUsageTracker::AddCachedOrigin(const url::Origin& origin, int64_t new_usage) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); diff --git a/chromium/storage/browser/quota/client_usage_tracker.h b/chromium/storage/browser/quota/client_usage_tracker.h index 3b4877d1c87..e56b8c2ba26 100644 --- a/chromium/storage/browser/quota/client_usage_tracker.h +++ b/chromium/storage/browser/quota/client_usage_tracker.h @@ -26,11 +26,14 @@ namespace storage { -class StorageMonitor; class UsageTracker; -// This class holds per-client usage tracking information and caches per-host -// usage data. An instance of this class is created per client. +// Holds per-client usage tracking information and caches +// per-host usage data. +// +// A UsageTracker object will own one ClientUsageTracker instance per client. +// This class is not thread-safe. All methods other than the constructor must be +// called on the same sequence. class ClientUsageTracker : public SpecialStoragePolicy::Observer, public base::SupportsWeakPtr<ClientUsageTracker> { public: @@ -39,8 +42,7 @@ class ClientUsageTracker : public SpecialStoragePolicy::Observer, ClientUsageTracker(UsageTracker* tracker, QuotaClient* client, blink::mojom::StorageType type, - SpecialStoragePolicy* special_storage_policy, - StorageMonitor* storage_monitor); + SpecialStoragePolicy* special_storage_policy); ~ClientUsageTracker() override; void GetGlobalLimitedUsage(UsageCallback callback); @@ -84,8 +86,6 @@ class ClientUsageTracker : public SpecialStoragePolicy::Observer, const base::Optional<url::Origin>& origin, int64_t usage); - void DidGetHostUsageAfterUpdate(const url::Origin& origin, int64_t usage); - // Methods used by our GatherUsage tasks, as a task makes progress // origins and hosts are added incrementally to the cache. void AddCachedOrigin(const url::Origin& origin, int64_t usage); @@ -106,7 +106,6 @@ class ClientUsageTracker : public SpecialStoragePolicy::Observer, QuotaClient* client_; const blink::mojom::StorageType type_; - StorageMonitor* storage_monitor_; int64_t global_limited_usage_; int64_t global_unlimited_usage_; diff --git a/chromium/storage/browser/quota/quota_callbacks.h b/chromium/storage/browser/quota/quota_callbacks.h index 995ceb75560..28f02c7ca32 100644 --- a/chromium/storage/browser/quota/quota_callbacks.h +++ b/chromium/storage/browser/quota/quota_callbacks.h @@ -90,7 +90,7 @@ class CallbackQueueMap { } bool HasCallbacks(const Key& key) const { - return base::ContainsKey(callback_map_, key); + return base::Contains(callback_map_, key); } bool HasAnyCallbacks() const { return !callback_map_.empty(); } diff --git a/chromium/storage/browser/quota/quota_database.cc b/chromium/storage/browser/quota/quota_database.cc index 3ac3f759048..b65429ae2db 100644 --- a/chromium/storage/browser/quota/quota_database.cc +++ b/chromium/storage/browser/quota/quota_database.cc @@ -46,15 +46,6 @@ bool VerifyValidQuotaConfig(const char* key) { const int kCommitIntervalMs = 30000; -void LogDaysSinceLastAccess(base::Time this_time, - const QuotaDatabase::OriginInfoTableEntry& entry) { - base::TimeDelta time_since = this_time - std::max(entry.last_access_time, - entry.last_modified_time); - if (time_since.InDays() < 1) - return; - UMA_HISTOGRAM_COUNTS_1000("Quota.DaysSinceLastAccess", time_since.InDays()); -} - } // anonymous namespace // static @@ -204,7 +195,6 @@ bool QuotaDatabase::SetOriginLastAccessTime(const url::Origin& origin, OriginInfoTableEntry entry; if (GetOriginInfo(origin, type, &entry)) { - LogDaysSinceLastAccess(last_access_time, entry); ++entry.used_count; const char* kSql = "UPDATE OriginInfoTable" @@ -243,7 +233,6 @@ bool QuotaDatabase::SetOriginLastModifiedTime(const url::Origin& origin, OriginInfoTableEntry entry; if (GetOriginInfo(origin, type, &entry)) { - LogDaysSinceLastAccess(last_modified_time, entry); const char* kSql = "UPDATE OriginInfoTable" " SET last_modified_time = ?" @@ -464,7 +453,7 @@ bool QuotaDatabase::GetLRUOrigin(StorageType type, while (statement.Step()) { url::Origin read_origin = url::Origin::Create(GURL(statement.ColumnString(0))); - if (base::ContainsKey(exceptions, read_origin)) + if (base::Contains(exceptions, read_origin)) continue; if (special_storage_policy && diff --git a/chromium/storage/browser/quota/quota_database.h b/chromium/storage/browser/quota/quota_database.h index 70761ef220e..887594edb9e 100644 --- a/chromium/storage/browser/quota/quota_database.h +++ b/chromium/storage/browser/quota/quota_database.h @@ -35,7 +35,11 @@ namespace storage { class SpecialStoragePolicy; -// All the methods of this class, except the constructor, must run on the DB +// Stores all origin scoped quota managed data and metadata. +// +// Instances are owned by QuotaManager. There is one instance per QuotaManager +// instance. +// All the methods of this class, except the constructor, must called on the DB // thread. class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDatabase { public: diff --git a/chromium/storage/browser/quota/quota_database_unittest.cc b/chromium/storage/browser/quota/quota_database_unittest.cc index 288049b0850..a1911fff99b 100644 --- a/chromium/storage/browser/quota/quota_database_unittest.cc +++ b/chromium/storage/browser/quota/quota_database_unittest.cc @@ -13,8 +13,8 @@ #include "base/callback.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" -#include "base/message_loop/message_loop.h" #include "base/stl_util.h" +#include "base/test/scoped_task_environment.h" #include "sql/database.h" #include "sql/meta_table.h" #include "sql/statement.h" @@ -575,7 +575,7 @@ class QuotaDatabaseTest : public testing::Test { db->CommitTransaction(); } - base::MessageLoop message_loop_; + base::test::ScopedTaskEnvironment scoped_task_environment_; }; TEST_F(QuotaDatabaseTest, LazyOpen) { diff --git a/chromium/storage/browser/quota/quota_disk_info_helper.h b/chromium/storage/browser/quota/quota_disk_info_helper.h index 2009f299c17..79ce6a7e464 100644 --- a/chromium/storage/browser/quota/quota_disk_info_helper.h +++ b/chromium/storage/browser/quota/quota_disk_info_helper.h @@ -11,11 +11,10 @@ namespace storage { -// A thread-safe wrapper class used to get total disk space. The class is -// subclassed in testing to mock the total disk space, thus allowing us to test -// experimental behavior in QuotaSettings. It is expected that -// QuotaDiskInfoHelper is instantiated in calls into QuotaSettings and owned -// by QuotaSettings. +// Interface used by the quota system to gather disk space information. +// Can be overridden in tests. +// Subclasses must be thread-safe. +// QuotaSettings instances own a singleton instance of QuotaDiskInfoHelper. class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDiskInfoHelper { public: QuotaDiskInfoHelper() = default; diff --git a/chromium/storage/browser/quota/quota_features.cc b/chromium/storage/browser/quota/quota_features.cc index a382d4edf67..6acac112f71 100644 --- a/chromium/storage/browser/quota/quota_features.cc +++ b/chromium/storage/browser/quota/quota_features.cc @@ -35,5 +35,11 @@ constexpr base::FeatureParam<double> kPerHostRatio{&kQuotaExpandPoolSize, const base::Feature kStaticHostQuota{"StaticHostQuota", base::FEATURE_DISABLED_BY_DEFAULT}; +// 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}; } // namespace features } // namespace storage diff --git a/chromium/storage/browser/quota/quota_features.h b/chromium/storage/browser/quota/quota_features.h index 8ad7a6a31de..93bcf854f3f 100644 --- a/chromium/storage/browser/quota/quota_features.h +++ b/chromium/storage/browser/quota/quota_features.h @@ -21,6 +21,9 @@ extern const base::FeatureParam<double> kPerHostRatio; COMPONENT_EXPORT(STORAGE_BROWSER) extern const base::Feature kStaticHostQuota; +COMPONENT_EXPORT(STORAGE_BROWSER) +extern const base::Feature kQuotaUnlimitedPoolSize; + } // namespace features } // namespace storage diff --git a/chromium/storage/browser/quota/quota_manager.cc b/chromium/storage/browser/quota/quota_manager.cc index 26193c1aa7e..45e0b5b4aaa 100644 --- a/chromium/storage/browser/quota/quota_manager.cc +++ b/chromium/storage/browser/quota/quota_manager.cc @@ -38,7 +38,6 @@ #include "storage/browser/quota/quota_macros.h" #include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/quota/quota_temporary_storage_evictor.h" -#include "storage/browser/quota/storage_monitor.h" #include "storage/browser/quota/usage_tracker.h" using blink::mojom::StorageType; @@ -198,9 +197,6 @@ void DidGetUsageAndQuotaForWebApps( } // namespace -// Helper to asynchronously gather usage and quota information. -// This class is not thread-safe. Each instance can only be used on the sequence -// where it was constructed. Instances of this class own and delete themselves. class QuotaManager::UsageAndQuotaInfoGatherer : public QuotaTask { public: UsageAndQuotaInfoGatherer(QuotaManager* manager, @@ -275,20 +271,23 @@ class QuotaManager::UsageAndQuotaInfoGatherer : public QuotaTask { weak_factory_.InvalidateWeakPtrs(); int64_t host_quota = desired_host_quota_; - - if (!base::FeatureList::IsEnabled(features::kStaticHostQuota)) { - // Constrain the desired |host_quota| to something that fits. - // If available space is too low, cap usage at current levels. - // If it's close to being too low, cap growth to avoid it getting too low. - int64_t temp_pool_free_space = - std::max(static_cast<int64_t>(0), - available_space_ - settings_.must_remain_available); - host_quota = std::min(host_quota, temp_pool_free_space + host_usage_); + int64_t temp_pool_free_space = + std::max(static_cast<int64_t>(0), + available_space_ - settings_.must_remain_available); + + // Constrain the desired |host_quota| to something that fits. + if (host_quota > temp_pool_free_space) { + if (is_unlimited_) { + host_quota = available_space_ + host_usage_; + } else if (!base::FeatureList::IsEnabled(features::kStaticHostQuota)) { + host_quota = temp_pool_free_space + host_usage_; + } } std::move(callback_).Run(blink::mojom::QuotaStatusCode::kOk, host_usage_, host_quota, std::move(host_usage_breakdown_)); - if (type_ == StorageType::kTemporary && !is_incognito_ && !is_unlimited_) { + if (type_ == StorageType::kTemporary && !is_incognito_ && + !is_unlimited_) { UMA_HISTOGRAM_MBYTES("Quota.QuotaForOrigin", host_quota); UMA_HISTOGRAM_MBYTES("Quota.UsageByOrigin", host_usage_); if (host_quota > 0) { @@ -366,8 +365,6 @@ class QuotaManager::UsageAndQuotaInfoGatherer : public QuotaTask { DISALLOW_COPY_AND_ASSIGN(UsageAndQuotaInfoGatherer); }; -// Helper to asynchronously gather information needed at the start of an -// eviction round. class QuotaManager::EvictionRoundInfoHelper : public QuotaTask { public: EvictionRoundInfoHelper(QuotaManager* manager, @@ -473,9 +470,6 @@ class QuotaManager::GetUsageInfoTask : public QuotaTask { protected: void Run() override { - // crbug.com/349708 - TRACE_EVENT0("io", "QuotaManager::GetUsageInfoTask::Run"); - remaining_trackers_ = 3; // This will populate cached hosts and usage info. manager() @@ -496,9 +490,6 @@ class QuotaManager::GetUsageInfoTask : public QuotaTask { } void Completed() override { - // crbug.com/349708 - TRACE_EVENT0("io", "QuotaManager::GetUsageInfoTask::Completed"); - std::move(callback_).Run(std::move(entries_)); DeleteSoon(); } @@ -580,17 +571,11 @@ class QuotaManager::OriginDataDeleter : public QuotaTask { void Completed() override { if (error_count_ == 0) { - // crbug.com/349708 - TRACE_EVENT0("io", "QuotaManager::OriginDataDeleter::Completed Ok"); - // Only remove the entire origin if we didn't skip any client types. if (skipped_clients_ == 0) manager()->DeleteOriginFromDatabase(origin_, type_, is_eviction_); std::move(callback_).Run(blink::mojom::QuotaStatusCode::kOk); } else { - // crbug.com/349708 - TRACE_EVENT0("io", "QuotaManager::OriginDataDeleter::Completed Error"); - std::move(callback_).Run( blink::mojom::QuotaStatusCode::kErrorInvalidModification); } @@ -664,14 +649,8 @@ class QuotaManager::HostDataDeleter : public QuotaTask { void Completed() override { if (error_count_ == 0) { - // crbug.com/349708 - TRACE_EVENT0("io", "QuotaManager::HostDataDeleter::Completed Ok"); - std::move(callback_).Run(blink::mojom::QuotaStatusCode::kOk); } else { - // crbug.com/349708 - TRACE_EVENT0("io", "QuotaManager::HostDataDeleter::Completed Error"); - std::move(callback_).Run( blink::mojom::QuotaStatusCode::kErrorInvalidModification); } @@ -790,6 +769,14 @@ class QuotaManager::StorageCleanupHelper : public QuotaTask { DISALLOW_COPY_AND_ASSIGN(StorageCleanupHelper); }; +// Fetch origins that have been modified since the specified time. This is used +// to clear data for origins that have been modified within the user specified +// 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. class QuotaManager::GetModifiedSinceHelper { public: bool GetModifiedSinceOnDBThread(StorageType type, @@ -816,6 +803,13 @@ class QuotaManager::GetModifiedSinceHelper { std::set<url::Origin> origins_; }; +// Gather origin info table for quota-internals page. +// +// This class is granted ownership of itself when it is passed to +// DidDumpQuotaTable() via base::Owned(). When the closure for said function +// goes out of scope, the object is deleted. +// This class is not thread-safe because there can be a race when entries_ is +// modified. class QuotaManager::DumpQuotaTableHelper { public: bool DumpQuotaTableOnDBThread(QuotaDatabase* database) { @@ -845,6 +839,13 @@ class QuotaManager::DumpQuotaTableHelper { QuotaTableEntries entries_; }; +// Gather origin info table for quota-internals page. +// +// This class is granted ownership of itself when it is passed to +// DidDumpQuotaTable() via base::Owned(). When the closure for said function +// goes out of scope, the object is deleted. +// This class is not thread-safe because there can be races when entries_ is +// modified. class QuotaManager::DumpOriginInfoTableHelper { public: bool DumpOriginInfoTableOnDBThread(QuotaDatabase* database) { @@ -896,7 +897,6 @@ QuotaManager::QuotaManager( is_getting_eviction_origin_(false), special_storage_policy_(std::move(special_storage_policy)), get_volume_info_fn_(&QuotaManager::GetVolumeInfo), - storage_monitor_(new StorageMonitor(this)), weak_factory_(this) { DCHECK_EQ(settings_.refresh_interval, base::TimeDelta::Max()); if (!get_settings_function.is_null()) { @@ -1207,18 +1207,15 @@ bool QuotaManager::ResetUsageTracker(StorageType type) { switch (type) { case StorageType::kTemporary: temporary_usage_tracker_.reset(new UsageTracker( - clients_, StorageType::kTemporary, special_storage_policy_.get(), - storage_monitor_.get())); + clients_, StorageType::kTemporary, special_storage_policy_.get())); return true; case StorageType::kPersistent: persistent_usage_tracker_.reset(new UsageTracker( - clients_, StorageType::kPersistent, special_storage_policy_.get(), - storage_monitor_.get())); + clients_, StorageType::kPersistent, special_storage_policy_.get())); return true; case StorageType::kSyncable: syncable_usage_tracker_.reset(new UsageTracker( - clients_, StorageType::kSyncable, special_storage_policy_.get(), - storage_monitor_.get())); + clients_, StorageType::kSyncable, special_storage_policy_.get())); return true; default: NOTREACHED(); @@ -1226,19 +1223,6 @@ bool QuotaManager::ResetUsageTracker(StorageType type) { return true; } -void QuotaManager::AddStorageObserver( - StorageObserver* observer, const StorageObserver::MonitorParams& params) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(observer); - storage_monitor_->AddObserver(observer, params); -} - -void QuotaManager::RemoveStorageObserver(StorageObserver* observer) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(observer); - storage_monitor_->RemoveObserver(observer); -} - QuotaManager::~QuotaManager() { proxy_->manager_ = nullptr; for (auto* client : clients_) @@ -1264,15 +1248,12 @@ void QuotaManager::LazyInitialize() { database_.reset(new QuotaDatabase(is_incognito_ ? base::FilePath() : profile_path_.AppendASCII(kDatabaseName))); - temporary_usage_tracker_.reset( - new UsageTracker(clients_, StorageType::kTemporary, - special_storage_policy_.get(), storage_monitor_.get())); - persistent_usage_tracker_.reset( - new UsageTracker(clients_, StorageType::kPersistent, - special_storage_policy_.get(), storage_monitor_.get())); - syncable_usage_tracker_.reset( - new UsageTracker(clients_, StorageType::kSyncable, - special_storage_policy_.get(), storage_monitor_.get())); + temporary_usage_tracker_.reset(new UsageTracker( + clients_, StorageType::kTemporary, special_storage_policy_.get())); + persistent_usage_tracker_.reset(new UsageTracker( + clients_, StorageType::kPersistent, special_storage_policy_.get())); + syncable_usage_tracker_.reset(new UsageTracker( + clients_, StorageType::kSyncable, special_storage_policy_.get())); if (!is_incognito_) { histogram_timer_.Start( @@ -1547,10 +1528,9 @@ void QuotaManager::DidDumpOriginInfoTableForHistogram( } } -std::set<url::Origin> QuotaManager::GetEvictionOriginExceptions( - const std::set<url::Origin>& extra_exceptions) { +std::set<url::Origin> QuotaManager::GetEvictionOriginExceptions() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - std::set<url::Origin> exceptions = extra_exceptions; + std::set<url::Origin> exceptions; for (const auto& p : origins_in_use_) { if (p.second > 0) exceptions.insert(p.first); @@ -1572,8 +1552,8 @@ void QuotaManager::DidGetEvictionOrigin( // and has not been accessed since we posted the task. DCHECK(!origin.has_value() || !origin->GetURL().is_empty()); if (origin.has_value() && - (base::ContainsKey(origins_in_use_, *origin) || - base::ContainsKey(access_notified_origins_, *origin))) { + (base::Contains(origins_in_use_, *origin) || + base::Contains(access_notified_origins_, *origin))) { std::move(callback).Run(base::nullopt); } else { std::move(callback).Run(origin); @@ -1585,7 +1565,6 @@ void QuotaManager::DidGetEvictionOrigin( void QuotaManager::GetEvictionOrigin( StorageType type, - const std::set<url::Origin>& extra_exceptions, int64_t global_quota, GetOriginCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -1651,7 +1630,7 @@ void QuotaManager::GetLRUOrigin(StorageType type, GetOriginCallback callback) { PostTaskAndReplyWithResultForDBThread( FROM_HERE, base::BindOnce(&GetLRUOriginOnDBThread, type, - GetEvictionOriginExceptions(std::set<url::Origin>()), + GetEvictionOriginExceptions(), base::RetainedRef(special_storage_policy_), base::Unretained(origin_ptr)), base::BindOnce(&QuotaManager::DidGetLRUOrigin, weak_factory_.GetWeakPtr(), @@ -1718,12 +1697,10 @@ void QuotaManager::GetQuotaSettings(QuotaSettingsCallback callback) { base::BindOnce(&DidGetSettingsThreadAdapter, base::RetainedRef(base::ThreadTaskRunnerHandle::Get()), base::BindOnce(&QuotaManager::DidGetSettings, - weak_factory_.GetWeakPtr(), - base::TimeTicks::Now())))); + weak_factory_.GetWeakPtr())))); } -void QuotaManager::DidGetSettings(base::TimeTicks start_ticks, - base::Optional<QuotaSettings> settings) { +void QuotaManager::DidGetSettings(base::Optional<QuotaSettings> settings) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!settings) { settings = settings_; @@ -1732,8 +1709,6 @@ void QuotaManager::DidGetSettings(base::TimeTicks start_ticks, SetQuotaSettings(*settings); settings_callbacks_.Run(*settings); UMA_HISTOGRAM_MBYTES("Quota.GlobalTemporaryPoolSize", settings->pool_size); - UMA_HISTOGRAM_LONG_TIMES("Quota.TimeToGetSettings", - base::TimeTicks::Now() - start_ticks); LOG_IF(WARNING, settings->pool_size == 0) << "No storage quota provided in QuotaSettings."; } @@ -1797,8 +1772,6 @@ void QuotaManager::PostTaskAndReplyWithResultForDBThread( std::tuple<int64_t, int64_t> QuotaManager::CallGetVolumeInfo( GetVolumeInfoFn get_volume_info_fn, const base::FilePath& path) { - // crbug.com/349708 - TRACE_EVENT0("io", "CallGetVolumeInfo"); if (!base::CreateDirectory(path)) { LOG(WARNING) << "Create directory failed for path" << path.value(); return std::make_tuple<int64_t, int64_t>(0, 0); diff --git a/chromium/storage/browser/quota/quota_manager.h b/chromium/storage/browser/quota/quota_manager.h index 649edf36c98..2ad77f861c9 100644 --- a/chromium/storage/browser/quota/quota_manager.h +++ b/chromium/storage/browser/quota/quota_manager.h @@ -33,7 +33,6 @@ #include "storage/browser/quota/quota_settings.h" #include "storage/browser/quota/quota_task.h" #include "storage/browser/quota/special_storage_policy.h" -#include "storage/browser/quota/storage_observer.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom-forward.h" namespace base { @@ -50,7 +49,6 @@ namespace content { class MockQuotaManager; class MockStorageClient; class QuotaManagerTest; -class StorageMonitorTest; } // namespace content namespace storage { @@ -58,12 +56,13 @@ namespace storage { class QuotaDatabase; class QuotaManagerProxy; class QuotaTemporaryStorageEvictor; -class StorageMonitor; class UsageTracker; struct QuotaManagerDeleter; -// An interface called by QuotaTemporaryStorageEvictor. +// An interface called by QuotaTemporaryStorageEvictor. This is a grab bag of +// methods called by QuotaTemporaryStorageEvictor that need to be stubbed for +// testing. class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaEvictionHandler { public: using EvictionRoundInfoCallback = @@ -81,7 +80,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaEvictionHandler { // Returns next origin to evict, or nullopt if there are no evictable // origins. virtual void GetEvictionOrigin(blink::mojom::StorageType type, - const std::set<url::Origin>& extra_exceptions, int64_t global_quota, GetOriginCallback callback) = 0; @@ -102,10 +100,19 @@ struct UsageInfo { const int64_t usage; }; -// Each StoragePartition owns exactly one QuotaManager. +// Entry point into the Quota System // -// Methods must be called on the IO thread, except for the constructor and -// proxy(). +// Each StoragePartition has exactly one QuotaManager instance, which +// coordinates quota across the Web platform features subject to quota. +// Each storage system interacts with quota via their own implementations of +// the QuotaClient interface. +// +// The class sets limits and defines the parameters of the systems heuristics. +// QuotaManager coordinates clients to orchestrate the collection of usage +// information, enforce quota limits, and evict stale data. +// +// The constructor and proxy() methods can be called on any thread. All other +// methods must be called on the IO thread. class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager : public QuotaTaskObserver, public QuotaEvictionHandler, @@ -181,7 +188,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager void NotifyOriginNoLongerInUse(const url::Origin& origin); bool IsOriginInUse(const url::Origin& origin) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return base::ContainsKey(origins_in_use_, origin); + return base::Contains(origins_in_use_, origin); } void SetUsageCacheEnabled(QuotaClient::ID client_id, @@ -243,11 +250,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager bool ResetUsageTracker(blink::mojom::StorageType type); - // Used to register/deregister observers that wish to monitor storage events. - void AddStorageObserver(StorageObserver* observer, - const StorageObserver::MonitorParams& params); - void RemoveStorageObserver(StorageObserver* observer); - static const int64_t kPerHostPersistentQuotaLimit; static const char kDatabaseName[]; static const int kThresholdOfErrorsToBeBlacklisted; @@ -268,7 +270,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager friend class base::DeleteHelper<QuotaManager>; friend class base::RefCountedDeleteOnSequence<QuotaManager>; friend class content::QuotaManagerTest; - friend class content::StorageMonitorTest; friend class content::MockQuotaManager; friend class content::MockStorageClient; friend class quota_internals::QuotaInternalsProxy; @@ -378,14 +379,12 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager void DidDumpOriginInfoTableForHistogram( const OriginInfoTableEntries& entries); - std::set<url::Origin> GetEvictionOriginExceptions( - const std::set<url::Origin>& extra_exceptions); + std::set<url::Origin> GetEvictionOriginExceptions(); void DidGetEvictionOrigin(GetOriginCallback callback, const base::Optional<url::Origin>& origin); // QuotaEvictionHandler. void GetEvictionOrigin(blink::mojom::StorageType type, - const std::set<url::Origin>& extra_exceptions, int64_t global_quota, GetOriginCallback callback) override; void EvictOriginData(const url::Origin& origin, @@ -405,8 +404,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager void DidGetLRUOrigin(std::unique_ptr<base::Optional<url::Origin>> origin, bool success); void GetQuotaSettings(QuotaSettingsCallback callback); - void DidGetSettings(base::TimeTicks start_ticks, - base::Optional<QuotaSettings> settings); + void DidGetSettings(base::Optional<QuotaSettings> settings); void GetStorageCapacity(StorageCapacityCallback callback); void ContinueIncognitoGetStorageCapacity(const QuotaSettings& settings); void DidGetStorageCapacity( @@ -482,8 +480,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager // values. The default value points to QuotaManager::GetVolumeInfo. GetVolumeInfoFn get_volume_info_fn_; - std::unique_ptr<StorageMonitor> storage_monitor_; - SEQUENCE_CHECKER(sequence_checker_); base::WeakPtrFactory<QuotaManager> weak_factory_; diff --git a/chromium/storage/browser/quota/quota_manager_proxy.cc b/chromium/storage/browser/quota/quota_manager_proxy.cc index 2473ffdedc9..8c19b11aadf 100644 --- a/chromium/storage/browser/quota/quota_manager_proxy.cc +++ b/chromium/storage/browser/quota/quota_manager_proxy.cc @@ -12,7 +12,6 @@ #include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/task_runner_util.h" -#include "base/trace_event/trace_event.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" namespace storage { @@ -31,9 +30,6 @@ void DidGetUsageAndQuota(base::SequencedTaskRunner* original_task_runner, std::move(callback), status, usage, quota)); return; } - - // crbug.com/349708 - TRACE_EVENT0("io", "QuotaManagerProxy DidGetUsageAndQuota"); std::move(callback).Run(status, usage, quota); } @@ -137,9 +133,6 @@ void QuotaManagerProxy::GetUsageAndQuota( return; } - // crbug.com/349708 - TRACE_EVENT0("io", "QuotaManagerProxy::GetUsageAndQuota"); - manager_->GetUsageAndQuota( origin, type, base::BindOnce(&DidGetUsageAndQuota, diff --git a/chromium/storage/browser/quota/quota_manager_unittest.cc b/chromium/storage/browser/quota/quota_manager_unittest.cc index c14e76fd026..e6ac568d6fb 100644 --- a/chromium/storage/browser/quota/quota_manager_unittest.cc +++ b/chromium/storage/browser/quota/quota_manager_unittest.cc @@ -312,7 +312,7 @@ class QuotaManagerTest : public testing::Test { // The quota manager's default eviction policy is to use an LRU eviction // policy. quota_manager_->GetEvictionOrigin( - type, std::set<url::Origin>(), 0, + type, 0, base::BindOnce(&QuotaManagerTest::DidGetEvictionOrigin, weak_factory_.GetWeakPtr())); } @@ -460,7 +460,6 @@ class QuotaManagerTest : public testing::Test { const blink::mojom::UsageBreakdown& usage_breakdown() const { return *usage_breakdown_; } - int64_t limited_usage() const { return limited_usage_; } int64_t unlimited_usage() const { return unlimited_usage_; } int64_t quota() const { return quota_; } int64_t total_space() const { return total_space_; } @@ -500,7 +499,6 @@ class QuotaManagerTest : public testing::Test { UsageInfoEntries usage_info_; int64_t usage_; blink::mojom::UsageBreakdownPtr usage_breakdown_; - int64_t limited_usage_; int64_t unlimited_usage_; int64_t quota_; int64_t total_space_; @@ -696,6 +694,7 @@ TEST_F(QuotaManagerTest, GetUsage_MultipleClients) { { "http://unlimited/", kTemp, 512 }, }; mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/")); + GetStorageCapacity(); RegisterClient( CreateClient(kData1, base::size(kData1), QuotaClient::kFileSystem)); RegisterClient( @@ -721,13 +720,13 @@ TEST_F(QuotaManagerTest, GetUsage_MultipleClients) { scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(512, usage()); - EXPECT_EQ(kAvailableSpaceForApp + usage(), quota()); + EXPECT_EQ(available_space() + usage(), quota()); GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kPerm); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(8, usage()); - EXPECT_EQ(kAvailableSpaceForApp + usage(), quota()); + EXPECT_EQ(available_space() + usage(), quota()); GetGlobalUsage(kTemp); scoped_task_environment_.RunUntilIdle(); @@ -1043,6 +1042,7 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Unlimited) { { "http://unlimited/", kTemp, 4000 }, }; mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/")); + GetStorageCapacity(); MockStorageClient* client = CreateClient(kData, base::size(kData), QuotaClient::kFileSystem); RegisterClient(client); @@ -1050,7 +1050,6 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Unlimited) { // Test when not overbugdet. const int kPerHostQuotaFor1000 = 200; SetQuotaSettings(1000, kPerHostQuotaFor1000, kMustRemainAvailableForSystem); - GetGlobalUsage(kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(10 + 50 + 4000, usage()); @@ -1072,7 +1071,7 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Unlimited) { scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(4000, usage()); - EXPECT_EQ(kAvailableSpaceForApp + usage(), quota()); + EXPECT_EQ(available_space() + usage(), quota()); GetUsageAndQuotaForStorageClient(ToOrigin("http://unlimited/"), kTemp); scoped_task_environment_.RunUntilIdle(); @@ -1100,7 +1099,7 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Unlimited) { scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(4000, usage()); - EXPECT_EQ(kAvailableSpaceForApp + usage(), quota()); + EXPECT_EQ(available_space() + usage(), quota()); GetUsageAndQuotaForStorageClient(ToOrigin("http://unlimited/"), kTemp); scoped_task_environment_.RunUntilIdle(); @@ -1192,6 +1191,7 @@ TEST_F(QuotaManagerTest, GetAndSetPerststentHostQuota) { } TEST_F(QuotaManagerTest, GetAndSetPersistentUsageAndQuota) { + GetStorageCapacity(); RegisterClient(CreateClient(nullptr, 0, QuotaClient::kFileSystem)); GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); @@ -1211,7 +1211,7 @@ TEST_F(QuotaManagerTest, GetAndSetPersistentUsageAndQuota) { mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/")); GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kPerm); scoped_task_environment_.RunUntilIdle(); - EXPECT_EQ(kAvailableSpaceForApp, quota()); + EXPECT_EQ(available_space() + usage(), quota()); // GetUsageAndQuotaForStorageClient should just return 0 usage and // kNoLimit quota. @@ -2022,7 +2022,7 @@ TEST_F(QuotaManagerTest, GetCachedOrigins) { for (size_t i = 0; i < base::size(kData); ++i) { if (kData[i].type == kTemp) - EXPECT_TRUE(base::ContainsKey(origins, ToOrigin(kData[i].origin))); + EXPECT_TRUE(base::Contains(origins, ToOrigin(kData[i].origin))); } } diff --git a/chromium/storage/browser/quota/quota_settings.cc b/chromium/storage/browser/quota/quota_settings.cc index 7badfa9ef7b..1f05a066c4b 100644 --- a/chromium/storage/browser/quota/quota_settings.cc +++ b/chromium/storage/browser/quota/quota_settings.cc @@ -59,7 +59,9 @@ base::Optional<storage::QuotaSettings> CalculateNominalDynamicSettings( // if experiment is enabled, otherwise fallback to ~66% for chromeOS and // ~33% otherwise. const double kTemporaryPoolSizeRatio = - features::kExperimentalPoolSizeRatio.Get(); + base::FeatureList::IsEnabled(features::kQuotaUnlimitedPoolSize) + ? 1.0 + : features::kExperimentalPoolSizeRatio.Get(); // The amount of the device's storage the browser attempts to // keep free. If there is less than this amount of storage free @@ -94,7 +96,10 @@ base::Optional<storage::QuotaSettings> CalculateNominalDynamicSettings( // Determines the portion of the temp pool that can be // utilized by a single host (ie. 5 for 20%). - const double kPerHostTemporaryRatio = features::kPerHostRatio.Get(); + const double kPerHostTemporaryRatio = + base::FeatureList::IsEnabled(features::kQuotaUnlimitedPoolSize) + ? 1.0 + : features::kPerHostRatio.Get(); // 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 abbfabf0a63..f86bd315170 100644 --- a/chromium/storage/browser/quota/quota_settings_unittest.cc +++ b/chromium/storage/browser/quota/quota_settings_unittest.cc @@ -65,4 +65,22 @@ TEST_F(QuotaSettingsTest, ExpandedTempPool) { EXPECT_TRUE(callback_executed); } +TEST_F(QuotaSettingsTest, UnlimitedTempPool) { + MockQuotaDiskInfoHelper disk_info_helper; + ON_CALL(disk_info_helper, AmountOfTotalDiskSpace(_)) + .WillByDefault(::testing::Return(2000)); + scoped_feature_list_.InitAndEnableFeature(features::kQuotaUnlimitedPoolSize); + + bool callback_executed = false; + GetNominalDynamicSettings( + profile_path(), false, &disk_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); + })); + scoped_task_environment_.RunUntilIdle(); + EXPECT_TRUE(callback_executed); +} } // namespace storage diff --git a/chromium/storage/browser/quota/quota_task.cc b/chromium/storage/browser/quota/quota_task.cc index b7266c4fdd3..ff0487573fe 100644 --- a/chromium/storage/browser/quota/quota_task.cc +++ b/chromium/storage/browser/quota/quota_task.cc @@ -22,7 +22,7 @@ namespace storage { QuotaTask::~QuotaTask() = default; void QuotaTask::Start() { - DCHECK(observer_); + DCHECK(observer_ != nullptr); observer()->RegisterTask(this); Run(); } @@ -31,6 +31,7 @@ QuotaTask::QuotaTask(QuotaTaskObserver* observer) : observer_(observer), original_task_runner_(base::ThreadTaskRunnerHandle::Get()), delete_scheduled_(false) { + DCHECK(observer != nullptr); } void QuotaTask::CallCompleted() { @@ -69,7 +70,7 @@ void QuotaTaskObserver::RegisterTask(QuotaTask* task) { } void QuotaTaskObserver::UnregisterTask(QuotaTask* task) { - DCHECK(base::ContainsKey(running_quota_tasks_, task)); + DCHECK(base::Contains(running_quota_tasks_, task)); running_quota_tasks_.erase(task); } diff --git a/chromium/storage/browser/quota/quota_task.h b/chromium/storage/browser/quota/quota_task.h index 11dcafd4493..740b24b5344 100644 --- a/chromium/storage/browser/quota/quota_task.h +++ b/chromium/storage/browser/quota/quota_task.h @@ -21,6 +21,12 @@ namespace storage { class QuotaTaskObserver; // A base class for quota tasks. +// +// Instances of this class own themselves and schedule themselves for deletion +// when async tasks are either aborted or completed. +// This class is not thread-safe and it's subclasses need not be either. +// CallCompleted(), Abort(), and DeleteSoon() must be called on the same thread +// that is the constructor is called on. // TODO(kinuko): Revise this using base::Callback. class QuotaTask { public: @@ -45,17 +51,15 @@ class QuotaTask { void DeleteSoon(); QuotaTaskObserver* observer() const { return observer_; } - base::SingleThreadTaskRunner* original_task_runner() const { - return original_task_runner_.get(); - } private: friend class base::DeleteHelper<QuotaTask>; friend class QuotaTaskObserver; void Abort(); + QuotaTaskObserver* observer_; - scoped_refptr<base::SingleThreadTaskRunner> original_task_runner_; + const scoped_refptr<base::SingleThreadTaskRunner> original_task_runner_; bool delete_scheduled_; }; diff --git a/chromium/storage/browser/quota/quota_temporary_storage_evictor.cc b/chromium/storage/browser/quota/quota_temporary_storage_evictor.cc index f97d7fbe3e3..ba4076f56da 100644 --- a/chromium/storage/browser/quota/quota_temporary_storage_evictor.cc +++ b/chromium/storage/browser/quota/quota_temporary_storage_evictor.cc @@ -114,7 +114,6 @@ void QuotaTemporaryStorageEvictor::OnEvictionRoundStarted() { void QuotaTemporaryStorageEvictor::OnEvictionRoundFinished() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - in_progress_eviction_origins_.clear(); // Check if skipped round if (round_statistics_.num_evicted_origins_in_round) { @@ -203,8 +202,7 @@ void QuotaTemporaryStorageEvictor::OnGotEvictionRoundInfo( // TODO(michaeln): if the reason for eviction is low physical disk space, // make 'unlimited' origins subject to eviction too. quota_eviction_handler_->GetEvictionOrigin( - blink::mojom::StorageType::kTemporary, in_progress_eviction_origins_, - settings.pool_size, + blink::mojom::StorageType::kTemporary, settings.pool_size, base::BindOnce(&QuotaTemporaryStorageEvictor::OnGotEvictionOrigin, weak_factory_.GetWeakPtr())); return; @@ -234,7 +232,6 @@ void QuotaTemporaryStorageEvictor::OnGotEvictionOrigin( } DCHECK(!origin->GetURL().is_empty()); - in_progress_eviction_origins_.insert(*origin); quota_eviction_handler_->EvictOriginData( *origin, blink::mojom::StorageType::kTemporary, diff --git a/chromium/storage/browser/quota/quota_temporary_storage_evictor.h b/chromium/storage/browser/quota/quota_temporary_storage_evictor.h index eb987dd1f64..09c902b2eab 100644 --- a/chromium/storage/browser/quota/quota_temporary_storage_evictor.h +++ b/chromium/storage/browser/quota/quota_temporary_storage_evictor.h @@ -102,7 +102,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaTemporaryStorageEvictor { EvictionRoundStatistics round_statistics_; base::Time time_of_end_of_last_nonskipped_round_; base::Time time_of_end_of_last_round_; - std::set<url::Origin> in_progress_eviction_origins_; int64_t interval_ms_; bool timer_disabled_for_testing_; diff --git a/chromium/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc b/chromium/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc index 7f1fe5fe680..ab7f169878a 100644 --- a/chromium/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc +++ b/chromium/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc @@ -70,7 +70,6 @@ class MockQuotaEvictionHandler : public storage::QuotaEvictionHandler { } void GetEvictionOrigin(StorageType type, - const std::set<url::Origin>& exceptions, int64_t global_quota, storage::GetOriginCallback callback) override { if (origin_order_.empty()) @@ -127,7 +126,7 @@ class MockQuotaEvictionHandler : public storage::QuotaEvictionHandler { private: int64_t EnsureOriginRemoved(const url::Origin& origin) { int64_t origin_usage; - if (!base::ContainsKey(origins_, origin)) + if (!base::Contains(origins_, origin)) return -1; else origin_usage = origins_[origin]; diff --git a/chromium/storage/browser/quota/storage_monitor.cc b/chromium/storage/browser/quota/storage_monitor.cc deleted file mode 100644 index 406845fc1d8..00000000000 --- a/chromium/storage/browser/quota/storage_monitor.cc +++ /dev/null @@ -1,355 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "storage/browser/quota/storage_monitor.h" - -#include <stdint.h> - -#include <algorithm> -#include <memory> - -#include "base/bind.h" -#include "base/trace_event/trace_event.h" -#include "net/base/url_util.h" -#include "storage/browser/quota/quota_manager.h" - -namespace storage { - -// StorageObserverList: - -StorageObserverList::ObserverState::ObserverState() - : requires_update(false) { -} - -StorageObserverList::StorageObserverList() = default; - -StorageObserverList::~StorageObserverList() = default; - -void StorageObserverList::AddObserver( - StorageObserver* observer, const StorageObserver::MonitorParams& params) { - ObserverState& observer_state = observer_state_map_[observer]; - observer_state.origin = params.filter.origin; - observer_state.rate = params.rate; -} - -void StorageObserverList::RemoveObserver(StorageObserver* observer) { - observer_state_map_.erase(observer); -} - -size_t StorageObserverList::ObserverCount() const { - return observer_state_map_.size(); -} - -void StorageObserverList::OnStorageChange(const StorageObserver::Event& event) { - // crbug.com/349708 - TRACE_EVENT0("io", - "HostStorageObserversStorageObserverList::OnStorageChange"); - - for (auto& observer_state_pair : observer_state_map_) - observer_state_pair.second.requires_update = true; - - MaybeDispatchEvent(event); -} - -void StorageObserverList::MaybeDispatchEvent( - const StorageObserver::Event& event) { - // crbug.com/349708 - TRACE_EVENT0("io", "StorageObserverList::MaybeDispatchEvent"); - - notification_timer_.Stop(); - base::TimeDelta min_delay = base::TimeDelta::Max(); - bool all_observers_notified = true; - - for (auto& observer_state_pair : observer_state_map_) { - StorageObserver* observer = observer_state_pair.first; - ObserverState& state = observer_state_pair.second; - - if (!state.requires_update) - continue; - - base::TimeTicks current_time = base::TimeTicks::Now(); - base::TimeDelta delta = current_time - state.last_notification_time; - if (state.last_notification_time.is_null() || delta >= state.rate) { - state.requires_update = false; - state.last_notification_time = current_time; - - if (state.origin == event.filter.origin) { - // crbug.com/349708 - TRACE_EVENT0("io", - "StorageObserverList::MaybeDispatchEvent OnStorageEvent1"); - - observer->OnStorageEvent(event); - } else { - // When the quota and usage of an origin is requested, QuotaManager - // returns the quota and usage of the host. Multiple origins can map to - // to the same host, so ensure the |origin| field in the dispatched - // event matches the |origin| specified by the observer when it was - // registered. - StorageObserver::Event dispatch_event(event); - dispatch_event.filter.origin = state.origin; - - // crbug.com/349708 - TRACE_EVENT0("io", - "StorageObserverList::MaybeDispatchEvent OnStorageEvent2"); - - observer->OnStorageEvent(dispatch_event); - } - } else { - all_observers_notified = false; - base::TimeDelta delay = state.rate - delta; - if (delay < min_delay) - min_delay = delay; - } - } - - // We need to respect the notification rate specified by observers. So if it - // is too soon to dispatch an event to an observer, save the event and - // dispatch it after a delay. If we simply drop the event, another one may - // not arrive anytime soon and the observer will miss the most recent event. - if (!all_observers_notified) { - pending_event_ = event; - notification_timer_.Start( - FROM_HERE, - min_delay, - this, - &StorageObserverList::DispatchPendingEvent); - } -} - -void StorageObserverList::ScheduleUpdateForObserver(StorageObserver* observer) { - DCHECK(base::ContainsKey(observer_state_map_, observer)); - observer_state_map_[observer].requires_update = true; -} - -void StorageObserverList::DispatchPendingEvent() { - MaybeDispatchEvent(pending_event_); -} - - -// HostStorageObservers: - -HostStorageObservers::HostStorageObservers(QuotaManager* quota_manager) - : quota_manager_(quota_manager), - initialized_(false), - initializing_(false), - event_occurred_before_init_(false), - usage_deltas_during_init_(0), - cached_usage_(0), - cached_quota_(0), - weak_factory_(this) { -} - -HostStorageObservers::~HostStorageObservers() = default; - -void HostStorageObservers::AddObserver( - StorageObserver* observer, - const StorageObserver::MonitorParams& params) { - observers_.AddObserver(observer, params); - - if (!params.dispatch_initial_state) - return; - - if (initialized_) { - StorageObserver::Event event(params.filter, - std::max<int64_t>(cached_usage_, 0), - std::max<int64_t>(cached_quota_, 0)); - observer->OnStorageEvent(event); - return; - } - - // Ensure the observer receives the initial storage state once initialization - // is complete. - observers_.ScheduleUpdateForObserver(observer); - StartInitialization(params.filter); -} - -void HostStorageObservers::RemoveObserver(StorageObserver* observer) { - observers_.RemoveObserver(observer); -} - -bool HostStorageObservers::ContainsObservers() const { - return observers_.ObserverCount() > 0; -} - -void HostStorageObservers::NotifyUsageChange( - const StorageObserver::Filter& filter, - int64_t delta) { - if (initialized_) { - cached_usage_ += delta; - DispatchEvent(filter, true); - return; - } - - // If a storage change occurs before initialization, ensure all observers will - // receive an event once initialization is complete. - event_occurred_before_init_ = true; - - // During QuotaManager::GetUsageAndQuotaForWebApps(), cached data is read - // synchronously, but other data may be retrieved asynchronously. A usage - // change may occur between the function call and callback. These deltas need - // to be added to the usage received by GotHostUsageAndQuota() to ensure - // |cached_usage_| is correctly initialized. - if (initializing_) { - usage_deltas_during_init_ += delta; - return; - } - - StartInitialization(filter); -} - -void HostStorageObservers::StartInitialization( - const StorageObserver::Filter& filter) { - if (initialized_ || initializing_) - return; - // crbug.com/349708 - TRACE_EVENT0("io", "HostStorageObservers::StartInitialization"); - - initializing_ = true; - quota_manager_->GetUsageAndQuotaForWebApps( - filter.origin, filter.storage_type, - base::BindOnce(&HostStorageObservers::GotHostUsageAndQuota, - weak_factory_.GetWeakPtr(), filter)); -} - -void HostStorageObservers::GotHostUsageAndQuota( - const StorageObserver::Filter& filter, - blink::mojom::QuotaStatusCode status, - int64_t usage, - int64_t quota) { - initializing_ = false; - if (status != blink::mojom::QuotaStatusCode::kOk) - return; - initialized_ = true; - cached_quota_ = quota; - cached_usage_ = usage + usage_deltas_during_init_; - DispatchEvent(filter, event_occurred_before_init_); -} - -void HostStorageObservers::DispatchEvent( - const StorageObserver::Filter& filter, bool is_update) { - StorageObserver::Event event(filter, std::max<int64_t>(cached_usage_, 0), - std::max<int64_t>(cached_quota_, 0)); - if (is_update) - observers_.OnStorageChange(event); - else - observers_.MaybeDispatchEvent(event); -} - - -// StorageTypeObservers: - -StorageTypeObservers::StorageTypeObservers(QuotaManager* quota_manager) - : quota_manager_(quota_manager) { -} - -StorageTypeObservers::~StorageTypeObservers() = default; - -void StorageTypeObservers::AddObserver( - StorageObserver* observer, const StorageObserver::MonitorParams& params) { - std::string host = net::GetHostOrSpecFromURL(params.filter.origin.GetURL()); - if (host.empty()) - return; - - auto& host_observers = host_observers_map_[host]; - if (!host_observers) { - // Because there are no null entries in host_observers_map_, the [] inserted - // a blank pointer, so let's populate it. - host_observers = std::make_unique<HostStorageObservers>(quota_manager_); - } - - host_observers->AddObserver(observer, params); -} - -void StorageTypeObservers::RemoveObserver(StorageObserver* observer) { - for (auto it = host_observers_map_.begin(); - it != host_observers_map_.end();) { - it->second->RemoveObserver(observer); - if (!it->second->ContainsObservers()) { - it = host_observers_map_.erase(it); - } else { - ++it; - } - } -} - -const HostStorageObservers* StorageTypeObservers::GetHostObservers( - const std::string& host) const { - auto it = host_observers_map_.find(host); - if (it != host_observers_map_.end()) - return it->second.get(); - - return nullptr; -} - -void StorageTypeObservers::NotifyUsageChange( - const StorageObserver::Filter& filter, - int64_t delta) { - std::string host = net::GetHostOrSpecFromURL(filter.origin.GetURL()); - auto it = host_observers_map_.find(host); - if (it == host_observers_map_.end()) - return; - - it->second->NotifyUsageChange(filter, delta); -} - - -// StorageMonitor: - -StorageMonitor::StorageMonitor(QuotaManager* quota_manager) - : quota_manager_(quota_manager) { -} - -StorageMonitor::~StorageMonitor() = default; - -void StorageMonitor::AddObserver( - StorageObserver* observer, const StorageObserver::MonitorParams& params) { - DCHECK(observer); - - // Check preconditions. - if (params.filter.storage_type == blink::mojom::StorageType::kUnknown || - params.filter.storage_type == - blink::mojom::StorageType::kQuotaNotManaged) { - NOTREACHED(); - return; - } - - auto& type_observers = - storage_type_observers_map_[params.filter.storage_type]; - if (!type_observers) - type_observers = std::make_unique<StorageTypeObservers>(quota_manager_); - - type_observers->AddObserver(observer, params); -} - -void StorageMonitor::RemoveObserver(StorageObserver* observer) { - for (const auto& type_observers_pair : storage_type_observers_map_) - type_observers_pair.second->RemoveObserver(observer); -} - -const StorageTypeObservers* StorageMonitor::GetStorageTypeObservers( - blink::mojom::StorageType storage_type) const { - auto it = storage_type_observers_map_.find(storage_type); - if (it != storage_type_observers_map_.end()) - return it->second.get(); - - return nullptr; -} - -void StorageMonitor::NotifyUsageChange(const StorageObserver::Filter& filter, - int64_t delta) { - // Check preconditions. - if (filter.storage_type == blink::mojom::StorageType::kUnknown || - filter.storage_type == blink::mojom::StorageType::kQuotaNotManaged) { - NOTREACHED(); - return; - } - - auto it = storage_type_observers_map_.find(filter.storage_type); - if (it == storage_type_observers_map_.end()) - return; - - it->second->NotifyUsageChange(filter, delta); -} - -} // namespace storage diff --git a/chromium/storage/browser/quota/storage_monitor.h b/chromium/storage/browser/quota/storage_monitor.h deleted file mode 100644 index 17ed8544525..00000000000 --- a/chromium/storage/browser/quota/storage_monitor.h +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef STORAGE_BROWSER_QUOTA_STORAGE_MONITOR_H_ -#define STORAGE_BROWSER_QUOTA_STORAGE_MONITOR_H_ - -#include <stdint.h> - -#include <map> -#include <memory> - -#include "base/component_export.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "base/time/time.h" -#include "base/timer/timer.h" -#include "storage/browser/quota/storage_observer.h" -#include "third_party/blink/public/mojom/quota/quota_types.mojom.h" -#include "url/origin.h" - -namespace content { -class StorageMonitorTestBase; -} - -namespace storage { - -class QuotaManager; - -// This class dispatches storage events to observers of a common -// StorageObserver::Filter. -class COMPONENT_EXPORT(STORAGE_BROWSER) StorageObserverList { - public: - StorageObserverList(); - virtual ~StorageObserverList(); - - // Adds/removes an observer. - void AddObserver(StorageObserver* observer, - const StorageObserver::MonitorParams& params); - void RemoveObserver(StorageObserver* observer); - - // Returns the number of observers. - size_t ObserverCount() const; - - // Forwards a storage change to observers. The event may be dispatched - // immediately to an observer or after a delay, depending on the desired event - // rate of the observer. - void OnStorageChange(const StorageObserver::Event& event); - - // Dispatch an event to observers that require it. - void MaybeDispatchEvent(const StorageObserver::Event& event); - - // Ensure the specified observer receives the next dispatched event. - void ScheduleUpdateForObserver(StorageObserver* observer); - - private: - struct COMPONENT_EXPORT(STORAGE_BROWSER) ObserverState { - url::Origin origin; - base::TimeTicks last_notification_time; - base::TimeDelta rate; - bool requires_update; - - ObserverState(); - }; - - void DispatchPendingEvent(); - - std::map<StorageObserver*, ObserverState> observer_state_map_; - base::OneShotTimer notification_timer_; - StorageObserver::Event pending_event_; - - friend class content::StorageMonitorTestBase; - - DISALLOW_COPY_AND_ASSIGN(StorageObserverList); -}; - -// Manages the storage observers of a common host. Caches the usage and quota of -// the host to avoid accumulating for every change. -class COMPONENT_EXPORT(STORAGE_BROWSER) HostStorageObservers { - public: - explicit HostStorageObservers(QuotaManager* quota_manager); - virtual ~HostStorageObservers(); - - bool is_initialized() const { return initialized_; } - - // Adds/removes an observer. - void AddObserver( - StorageObserver* observer, - const StorageObserver::MonitorParams& params); - void RemoveObserver(StorageObserver* observer); - bool ContainsObservers() const; - - // Handles a usage change. - void NotifyUsageChange(const StorageObserver::Filter& filter, int64_t delta); - - private: - void StartInitialization(const StorageObserver::Filter& filter); - void GotHostUsageAndQuota(const StorageObserver::Filter& filter, - blink::mojom::QuotaStatusCode status, - int64_t usage, - int64_t quota); - void DispatchEvent(const StorageObserver::Filter& filter, bool is_update); - - QuotaManager* quota_manager_; - StorageObserverList observers_; - - // Flags used during initialization of the cached properties. - bool initialized_; - bool initializing_; - bool event_occurred_before_init_; - int64_t usage_deltas_during_init_; - - // Cached accumulated usage and quota for the host. - int64_t cached_usage_; - int64_t cached_quota_; - - base::WeakPtrFactory<HostStorageObservers> weak_factory_; - - friend class content::StorageMonitorTestBase; - - DISALLOW_COPY_AND_ASSIGN(HostStorageObservers); -}; - -// Manages the observers of a common storage type. -class COMPONENT_EXPORT(STORAGE_BROWSER) StorageTypeObservers { - public: - explicit StorageTypeObservers(QuotaManager* quota_manager); - virtual ~StorageTypeObservers(); - - // Adds and removes an observer. - void AddObserver(StorageObserver* observer, - const StorageObserver::MonitorParams& params); - void RemoveObserver(StorageObserver* observer); - - // Returns the observers of a specific host. - const HostStorageObservers* GetHostObservers(const std::string& host) const; - - // Handles a usage change. - void NotifyUsageChange(const StorageObserver::Filter& filter, int64_t delta); - - private: - QuotaManager* quota_manager_; - std::map<std::string, std::unique_ptr<HostStorageObservers>> - host_observers_map_; - - DISALLOW_COPY_AND_ASSIGN(StorageTypeObservers); -}; - -// Storage monitor manages observers and dispatches storage events to them. -class COMPONENT_EXPORT(STORAGE_BROWSER) StorageMonitor { - public: - explicit StorageMonitor(QuotaManager* quota_manager); - virtual ~StorageMonitor(); - - // Adds and removes an observer. - void AddObserver(StorageObserver* observer, - const StorageObserver::MonitorParams& params); - void RemoveObserver(StorageObserver* observer); - void RemoveObserverForFilter(StorageObserver* observer, - const StorageObserver::Filter& filter); - - // Returns the observers of a specific storage type. - const StorageTypeObservers* GetStorageTypeObservers( - blink::mojom::StorageType storage_type) const; - - // Handles a usage change. - void NotifyUsageChange(const StorageObserver::Filter& filter, int64_t delta); - - private: - QuotaManager* quota_manager_; - std::map<blink::mojom::StorageType, std::unique_ptr<StorageTypeObservers>> - storage_type_observers_map_; - - DISALLOW_COPY_AND_ASSIGN(StorageMonitor); -}; - -} // namespace storage - -#endif // STORAGE_BROWSER_QUOTA_STORAGE_MONITOR_H_ diff --git a/chromium/storage/browser/quota/storage_monitor_unittest.cc b/chromium/storage/browser/quota/storage_monitor_unittest.cc deleted file mode 100644 index 92c821f49e0..00000000000 --- a/chromium/storage/browser/quota/storage_monitor_unittest.cc +++ /dev/null @@ -1,679 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stdint.h> - -#include <vector> - -#include "base/files/scoped_temp_dir.h" -#include "base/run_loop.h" -#include "base/stl_util.h" -#include "base/test/scoped_task_environment.h" -#include "base/threading/thread_task_runner_handle.h" -#include "net/base/url_util.h" -#include "storage/browser/quota/quota_manager.h" -#include "storage/browser/quota/quota_manager_proxy.h" -#include "storage/browser/quota/storage_monitor.h" -#include "storage/browser/quota/storage_observer.h" -#include "storage/browser/test/mock_special_storage_policy.h" -#include "storage/browser/test/mock_storage_client.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" -#include "url/origin.h" - -using blink::mojom::QuotaStatusCode; -using blink::mojom::StorageType; -using storage::HostStorageObservers; -using storage::QuotaClient; -using storage::QuotaManager; -using storage::SpecialStoragePolicy; -using storage::StorageMonitor; -using storage::StorageObserver; -using storage::StorageObserverList; -using storage::StorageTypeObservers; - -namespace content { - -namespace { - -// TODO(crbug.com/889590): Use helper for url::Origin creation from string. -const url::Origin kDefaultOrigin = - url::Origin::Create(GURL("http://www.foo.com/")); -const url::Origin kAlternativeOrigin = - url::Origin::Create(GURL("http://www.bar.com/")); - -class MockObserver : public StorageObserver { - public: - const StorageObserver::Event& LastEvent() const { - CHECK(!events_.empty()); - return events_.back(); - } - - size_t EventCount() const { return events_.size(); } - - // StorageObserver implementation: - void OnStorageEvent(const StorageObserver::Event& event) override { - events_.push_back(event); - } - - private: - std::vector<StorageObserver::Event> events_; -}; - -// A mock quota manager for overriding GetUsageAndQuotaForWebApps(). -class UsageMockQuotaManager : public QuotaManager { - public: - UsageMockQuotaManager(SpecialStoragePolicy* special_storage_policy) - : QuotaManager(false, - base::FilePath(), - base::ThreadTaskRunnerHandle::Get().get(), - special_storage_policy, - storage::GetQuotaSettingsFunc()), - callback_usage_(0), - callback_quota_(0), - callback_status_(QuotaStatusCode::kOk), - initialized_(false) {} - - void SetCallbackParams(int64_t usage, int64_t quota, QuotaStatusCode status) { - initialized_ = true; - callback_quota_ = quota; - callback_usage_ = usage; - callback_status_ = status; - } - - void InvokeCallback() { - std::move(delayed_callback_) - .Run(callback_status_, callback_usage_, callback_quota_); - } - - void GetUsageAndQuotaForWebApps(const url::Origin& origin, - StorageType type, - UsageAndQuotaCallback callback) override { - if (initialized_) - std::move(callback).Run(callback_status_, callback_usage_, - callback_quota_); - else - delayed_callback_ = std::move(callback); - } - - protected: - ~UsageMockQuotaManager() override = default; - - private: - int64_t callback_usage_; - int64_t callback_quota_; - QuotaStatusCode callback_status_; - bool initialized_; - UsageAndQuotaCallback delayed_callback_; -}; - -} // namespace - -class StorageMonitorTestBase : public testing::Test { - protected: - void DispatchPendingEvents(StorageObserverList& observer_list) { - observer_list.DispatchPendingEvent(); - } - - const StorageObserver::Event* GetPendingEvent( - const StorageObserverList& observer_list) { - return observer_list.notification_timer_.IsRunning() - ? &observer_list.pending_event_ - : nullptr; - } - - const StorageObserver::Event* GetPendingEvent( - const HostStorageObservers& host_observers) { - return GetPendingEvent(host_observers.observers_); - } - - int GetRequiredUpdatesCount(const StorageObserverList& observer_list) { - int count = 0; - for (const auto& observer_state_pair : observer_list.observer_state_map_) { - if (observer_state_pair.second.requires_update) - ++count; - } - - return count; - } - - int GetRequiredUpdatesCount(const HostStorageObservers& host_observers) { - return GetRequiredUpdatesCount(host_observers.observers_); - } - - void SetLastNotificationTime(StorageObserverList& observer_list, - StorageObserver* observer) { - ASSERT_TRUE(base::ContainsKey(observer_list.observer_state_map_, observer)); - StorageObserverList::ObserverState& state = - observer_list.observer_state_map_[observer]; - state.last_notification_time = base::TimeTicks::Now() - state.rate; - } - - void SetLastNotificationTime(HostStorageObservers& host_observers, - StorageObserver* observer) { - SetLastNotificationTime(host_observers.observers_, observer); - } - - size_t GetObserverCount(const HostStorageObservers& host_observers) { - return host_observers.observers_.ObserverCount(); - } - - base::test::ScopedTaskEnvironment scoped_task_environment_; -}; - -class StorageTestWithManagerBase : public StorageMonitorTestBase { - public: - void SetUp() override { - storage_policy_ = new MockSpecialStoragePolicy(); - quota_manager_ = new UsageMockQuotaManager(storage_policy_.get()); - } - - void TearDown() override { - // This ensures the quota manager is destroyed correctly. - quota_manager_ = nullptr; - scoped_task_environment_.RunUntilIdle(); - } - - protected: - scoped_refptr<MockSpecialStoragePolicy> storage_policy_; - scoped_refptr<UsageMockQuotaManager> quota_manager_; -}; - -// Tests for StorageObserverList: - -using StorageObserverListTest = StorageMonitorTestBase; - -// Test dispatching events to one observer. -TEST_F(StorageObserverListTest, DispatchEventToSingleObserver) { - StorageObserver::MonitorParams params(StorageType::kPersistent, - kDefaultOrigin, - base::TimeDelta::FromHours(1), false); - MockObserver mock_observer; - StorageObserverList observer_list; - observer_list.AddObserver(&mock_observer, params); - - StorageObserver::Event event; - event.filter = params.filter; - - // Verify that the first event is dispatched immediately. - event.quota = 1; - event.usage = 1; - observer_list.OnStorageChange(event); - EXPECT_EQ(1u, mock_observer.EventCount()); - EXPECT_EQ(event, mock_observer.LastEvent()); - EXPECT_EQ(nullptr, GetPendingEvent(observer_list)); - EXPECT_EQ(0, GetRequiredUpdatesCount(observer_list)); - - // Verify that the next event is pending. - event.quota = 2; - event.usage = 2; - observer_list.OnStorageChange(event); - EXPECT_EQ(1u, mock_observer.EventCount()); - ASSERT_TRUE(GetPendingEvent(observer_list)); - EXPECT_EQ(event, *GetPendingEvent(observer_list)); - EXPECT_EQ(1, GetRequiredUpdatesCount(observer_list)); - - // Fake the last notification time so that an event will be dispatched. - SetLastNotificationTime(observer_list, &mock_observer); - event.quota = 3; - event.usage = 3; - observer_list.OnStorageChange(event); - EXPECT_EQ(2u, mock_observer.EventCount()); - EXPECT_EQ(event, mock_observer.LastEvent()); - EXPECT_EQ(nullptr, GetPendingEvent(observer_list)); - EXPECT_EQ(0, GetRequiredUpdatesCount(observer_list)); - - // Remove the observer. - event.quota = 4; - event.usage = 4; - observer_list.RemoveObserver(&mock_observer); - observer_list.OnStorageChange(event); - EXPECT_EQ(2u, mock_observer.EventCount()); - EXPECT_EQ(nullptr, GetPendingEvent(observer_list)); -} - -// Test dispatching events to multiple observers. -TEST_F(StorageObserverListTest, DispatchEventToMultipleObservers) { - MockObserver mock_observer1; - MockObserver mock_observer2; - StorageObserverList observer_list; - StorageObserver::Filter filter(StorageType::kPersistent, kDefaultOrigin); - observer_list.AddObserver( - &mock_observer1, - StorageObserver::MonitorParams( - filter, base::TimeDelta::FromHours(1), false)); - observer_list.AddObserver( - &mock_observer2, - StorageObserver::MonitorParams( - filter, base::TimeDelta::FromHours(2), false)); - - StorageObserver::Event event; - event.filter = filter; - - // Verify that the first event is dispatched immediately. - event.quota = 1; - event.usage = 1; - observer_list.OnStorageChange(event); - EXPECT_EQ(1u, mock_observer1.EventCount()); - EXPECT_EQ(1u, mock_observer2.EventCount()); - EXPECT_EQ(event, mock_observer1.LastEvent()); - EXPECT_EQ(event, mock_observer2.LastEvent()); - EXPECT_EQ(nullptr, GetPendingEvent(observer_list)); - EXPECT_EQ(0, GetRequiredUpdatesCount(observer_list)); - - // Fake the last notification time so that observer1 will receive the next - // event, but it will be pending for observer2. - SetLastNotificationTime(observer_list, &mock_observer1); - event.quota = 2; - event.usage = 2; - observer_list.OnStorageChange(event); - EXPECT_EQ(2u, mock_observer1.EventCount()); - EXPECT_EQ(1u, mock_observer2.EventCount()); - EXPECT_EQ(event, mock_observer1.LastEvent()); - ASSERT_TRUE(GetPendingEvent(observer_list)); - EXPECT_EQ(event, *GetPendingEvent(observer_list)); - EXPECT_EQ(1, GetRequiredUpdatesCount(observer_list)); - - // Now dispatch the pending event to observer2. - SetLastNotificationTime(observer_list, &mock_observer2); - DispatchPendingEvents(observer_list); - EXPECT_EQ(2u, mock_observer1.EventCount()); - EXPECT_EQ(2u, mock_observer2.EventCount()); - EXPECT_EQ(event, mock_observer1.LastEvent()); - EXPECT_EQ(event, mock_observer2.LastEvent()); - EXPECT_EQ(nullptr, GetPendingEvent(observer_list)); - EXPECT_EQ(0, GetRequiredUpdatesCount(observer_list)); -} - -// Ensure that the |origin| field in events match the origin specified by the -// observer on registration. -TEST_F(StorageObserverListTest, ReplaceEventOrigin) { - StorageObserver::MonitorParams params(StorageType::kPersistent, - kDefaultOrigin, - base::TimeDelta::FromHours(1), false); - MockObserver mock_observer; - StorageObserverList observer_list; - observer_list.AddObserver(&mock_observer, params); - - StorageObserver::Event dispatched_event; - dispatched_event.filter = params.filter; - dispatched_event.filter.origin = - url::Origin::Create(GURL("https://www.foo.com/bar")); - observer_list.OnStorageChange(dispatched_event); - - EXPECT_EQ(params.filter.origin, mock_observer.LastEvent().filter.origin); -} - -// Tests for HostStorageObservers: - -using HostStorageObserversTest = StorageTestWithManagerBase; - -// Verify that HostStorageObservers is initialized after the first usage change. -TEST_F(HostStorageObserversTest, InitializeOnUsageChange) { - StorageObserver::MonitorParams params(StorageType::kPersistent, - kDefaultOrigin, - base::TimeDelta::FromHours(1), false); - const int64_t kUsage = 324554; - const int64_t kQuota = 234354354; - quota_manager_->SetCallbackParams(kUsage, kQuota, QuotaStatusCode::kOk); - - MockObserver mock_observer; - HostStorageObservers host_observers(quota_manager_.get()); - host_observers.AddObserver(&mock_observer, params); - - // Verify that HostStorageObservers dispatches the first event correctly. - StorageObserver::Event expected_event(params.filter, kUsage, kQuota); - host_observers.NotifyUsageChange(params.filter, 87324); - EXPECT_EQ(1u, mock_observer.EventCount()); - EXPECT_EQ(expected_event, mock_observer.LastEvent()); - EXPECT_TRUE(host_observers.is_initialized()); - - // Verify that HostStorageObservers handles subsequent usage changes - // correctly. - const int64_t kDelta = 2345; - expected_event.usage += kDelta; - SetLastNotificationTime(host_observers, &mock_observer); - host_observers.NotifyUsageChange(params.filter, kDelta); - EXPECT_EQ(2u, mock_observer.EventCount()); - EXPECT_EQ(expected_event, mock_observer.LastEvent()); -} - -// Verify that HostStorageObservers is initialized after the adding the first -// observer that elected to receive the initial state. -TEST_F(HostStorageObserversTest, InitializeOnObserver) { - const int64_t kUsage = 74387; - const int64_t kQuota = 92834743; - quota_manager_->SetCallbackParams(kUsage, kQuota, QuotaStatusCode::kOk); - HostStorageObservers host_observers(quota_manager_.get()); - - // |host_observers| should not be initialized after the first observer is - // added because it did not elect to receive the initial state. - StorageObserver::MonitorParams params(StorageType::kPersistent, - kDefaultOrigin, - base::TimeDelta::FromHours(1), false); - MockObserver mock_observer1; - host_observers.AddObserver(&mock_observer1, params); - EXPECT_FALSE(host_observers.is_initialized()); - EXPECT_EQ(0u, mock_observer1.EventCount()); - - // |host_observers| should be initialized after the second observer is - // added. - MockObserver mock_observer2; - params.dispatch_initial_state = true; - host_observers.AddObserver(&mock_observer2, params); - StorageObserver::Event expected_event(params.filter, kUsage, kQuota); - EXPECT_EQ(0u, mock_observer1.EventCount()); - EXPECT_EQ(1u, mock_observer2.EventCount()); - EXPECT_EQ(expected_event, mock_observer2.LastEvent()); - EXPECT_TRUE(host_observers.is_initialized()); - EXPECT_EQ(nullptr, GetPendingEvent(host_observers)); - EXPECT_EQ(0, GetRequiredUpdatesCount(host_observers)); - - // Verify that both observers will receive events after a usage change. - const int64_t kDelta = 2345; - expected_event.usage += kDelta; - SetLastNotificationTime(host_observers, &mock_observer2); - host_observers.NotifyUsageChange(params.filter, kDelta); - EXPECT_EQ(1u, mock_observer1.EventCount()); - EXPECT_EQ(2u, mock_observer2.EventCount()); - EXPECT_EQ(expected_event, mock_observer1.LastEvent()); - EXPECT_EQ(expected_event, mock_observer2.LastEvent()); - EXPECT_EQ(nullptr, GetPendingEvent(host_observers)); - EXPECT_EQ(0, GetRequiredUpdatesCount(host_observers)); - - // Verify that the addition of a third observer only causes an event to be - // dispatched to the new observer. - MockObserver mock_observer3; - params.dispatch_initial_state = true; - host_observers.AddObserver(&mock_observer3, params); - EXPECT_EQ(1u, mock_observer1.EventCount()); - EXPECT_EQ(2u, mock_observer2.EventCount()); - EXPECT_EQ(1u, mock_observer3.EventCount()); - EXPECT_EQ(expected_event, mock_observer3.LastEvent()); -} - -// Verify that negative usage and quota is changed to zero. -TEST_F(HostStorageObserversTest, NegativeUsageAndQuota) { - StorageObserver::MonitorParams params(StorageType::kPersistent, - kDefaultOrigin, - base::TimeDelta::FromHours(1), false); - const int64_t kUsage = -324554; - const int64_t kQuota = -234354354; - quota_manager_->SetCallbackParams(kUsage, kQuota, QuotaStatusCode::kOk); - - MockObserver mock_observer; - HostStorageObservers host_observers(quota_manager_.get()); - host_observers.AddObserver(&mock_observer, params); - - StorageObserver::Event expected_event(params.filter, 0, 0); - host_observers.NotifyUsageChange(params.filter, -87324); - EXPECT_EQ(expected_event, mock_observer.LastEvent()); -} - -// Verify that HostStorageObservers can recover from a bad initialization. -TEST_F(HostStorageObserversTest, RecoverFromBadUsageInit) { - StorageObserver::MonitorParams params(StorageType::kPersistent, - kDefaultOrigin, - base::TimeDelta::FromHours(1), false); - MockObserver mock_observer; - HostStorageObservers host_observers(quota_manager_.get()); - host_observers.AddObserver(&mock_observer, params); - - // Set up the quota manager to return an error status. - const int64_t kUsage = 6656; - const int64_t kQuota = 99585556; - quota_manager_->SetCallbackParams(kUsage, kQuota, - QuotaStatusCode::kErrorNotSupported); - - // Verify that |host_observers| is not initialized and an event has not been - // dispatched. - host_observers.NotifyUsageChange(params.filter, 9438); - EXPECT_EQ(0u, mock_observer.EventCount()); - EXPECT_FALSE(host_observers.is_initialized()); - EXPECT_EQ(nullptr, GetPendingEvent(host_observers)); - EXPECT_EQ(0, GetRequiredUpdatesCount(host_observers)); - - // Now ensure that quota manager returns a good status. - quota_manager_->SetCallbackParams(kUsage, kQuota, QuotaStatusCode::kOk); - host_observers.NotifyUsageChange(params.filter, 9048543); - StorageObserver::Event expected_event(params.filter, kUsage, kQuota); - EXPECT_EQ(1u, mock_observer.EventCount()); - EXPECT_EQ(expected_event, mock_observer.LastEvent()); - EXPECT_TRUE(host_observers.is_initialized()); -} - -// Verify that HostStorageObservers handle initialization of the cached usage -// and quota correctly. -TEST_F(HostStorageObserversTest, AsyncInitialization) { - StorageObserver::MonitorParams params(StorageType::kPersistent, - kDefaultOrigin, - base::TimeDelta::FromHours(1), false); - MockObserver mock_observer; - HostStorageObservers host_observers(quota_manager_.get()); - host_observers.AddObserver(&mock_observer, params); - - // Trigger initialization. Leave the mock quota manager uninitialized so that - // the callback is not invoked. - host_observers.NotifyUsageChange(params.filter, 7645); - EXPECT_EQ(0u, mock_observer.EventCount()); - EXPECT_FALSE(host_observers.is_initialized()); - EXPECT_EQ(nullptr, GetPendingEvent(host_observers)); - EXPECT_EQ(0, GetRequiredUpdatesCount(host_observers)); - - // Simulate notifying |host_observers| of a usage change before initialization - // is complete. - const int64_t kUsage = 6656; - const int64_t kQuota = 99585556; - const int64_t kDelta = 327643; - host_observers.NotifyUsageChange(params.filter, kDelta); - EXPECT_EQ(0u, mock_observer.EventCount()); - EXPECT_FALSE(host_observers.is_initialized()); - EXPECT_EQ(nullptr, GetPendingEvent(host_observers)); - EXPECT_EQ(0, GetRequiredUpdatesCount(host_observers)); - - // Simulate an asynchronous callback from QuotaManager. - quota_manager_->SetCallbackParams(kUsage, kQuota, QuotaStatusCode::kOk); - quota_manager_->InvokeCallback(); - StorageObserver::Event expected_event(params.filter, kUsage + kDelta, kQuota); - EXPECT_EQ(1u, mock_observer.EventCount()); - EXPECT_EQ(expected_event, mock_observer.LastEvent()); - EXPECT_TRUE(host_observers.is_initialized()); - EXPECT_EQ(nullptr, GetPendingEvent(host_observers)); - EXPECT_EQ(0, GetRequiredUpdatesCount(host_observers)); -} - -// Tests for StorageTypeObservers: - -using StorageTypeObserversTest = StorageTestWithManagerBase; - -// Test adding and removing observers. -TEST_F(StorageTypeObserversTest, AddRemoveObservers) { - StorageTypeObservers type_observers(quota_manager_.get()); - - StorageObserver::MonitorParams params1(StorageType::kPersistent, - kDefaultOrigin, - base::TimeDelta::FromHours(1), false); - StorageObserver::MonitorParams params2(StorageType::kPersistent, - kAlternativeOrigin, - base::TimeDelta::FromHours(1), false); - std::string host1 = net::GetHostOrSpecFromURL(params1.filter.origin.GetURL()); - std::string host2 = net::GetHostOrSpecFromURL(params2.filter.origin.GetURL()); - - MockObserver mock_observer1; - MockObserver mock_observer2; - MockObserver mock_observer3; - type_observers.AddObserver(&mock_observer1, params1); - type_observers.AddObserver(&mock_observer2, params1); - - type_observers.AddObserver(&mock_observer1, params2); - type_observers.AddObserver(&mock_observer2, params2); - type_observers.AddObserver(&mock_observer3, params2); - - // Verify that the observers have been removed correctly. - ASSERT_TRUE(type_observers.GetHostObservers(host1)); - ASSERT_TRUE(type_observers.GetHostObservers(host2)); - EXPECT_EQ(2u, GetObserverCount(*type_observers.GetHostObservers(host1))); - EXPECT_EQ(3u, GetObserverCount(*type_observers.GetHostObservers(host2))); - - // Remove all instances of observer1. - type_observers.RemoveObserver(&mock_observer1); - ASSERT_TRUE(type_observers.GetHostObservers(host1)); - ASSERT_TRUE(type_observers.GetHostObservers(host2)); - EXPECT_EQ(1u, GetObserverCount(*type_observers.GetHostObservers(host1))); - EXPECT_EQ(2u, GetObserverCount(*type_observers.GetHostObservers(host2))); - - // Remove all instances of observer2. - type_observers.RemoveObserver(&mock_observer2); - ASSERT_TRUE(type_observers.GetHostObservers(host2)); - EXPECT_EQ(1u, GetObserverCount(*type_observers.GetHostObservers(host2))); - // Observers of host1 has been deleted as it is empty. - EXPECT_FALSE(type_observers.GetHostObservers(host1)); -} - -// Tests for StorageMonitor: - -class StorageMonitorTest : public StorageTestWithManagerBase { - public: - StorageMonitorTest() - : storage_monitor_(nullptr), - params1_(StorageType::kTemporary, - kDefaultOrigin, - base::TimeDelta::FromHours(1), - false), - params2_(StorageType::kPersistent, - kDefaultOrigin, - base::TimeDelta::FromHours(1), - false) {} - - protected: - void SetUp() override { - StorageTestWithManagerBase::SetUp(); - - storage_monitor_ = quota_manager_->storage_monitor_.get(); - host_ = net::GetHostOrSpecFromURL(params1_.filter.origin.GetURL()); - - storage_monitor_->AddObserver(&mock_observer1_, params1_); - storage_monitor_->AddObserver(&mock_observer2_, params1_); - - storage_monitor_->AddObserver(&mock_observer1_, params2_); - storage_monitor_->AddObserver(&mock_observer2_, params2_); - storage_monitor_->AddObserver(&mock_observer3_, params2_); - } - - size_t GetObserverCount(StorageType storage_type) { - const StorageTypeObservers* type_observers = - storage_monitor_->GetStorageTypeObservers(storage_type); - return StorageMonitorTestBase::GetObserverCount( - *type_observers->GetHostObservers(host_)); - } - - void CheckObserverCount(size_t expected_temporary, - size_t expected_persistent) { - ASSERT_TRUE( - storage_monitor_->GetStorageTypeObservers(StorageType::kTemporary)); - ASSERT_TRUE( - storage_monitor_->GetStorageTypeObservers(StorageType::kTemporary) - ->GetHostObservers(host_)); - EXPECT_EQ(expected_temporary, GetObserverCount(StorageType::kTemporary)); - - ASSERT_TRUE( - storage_monitor_->GetStorageTypeObservers(StorageType::kPersistent)); - ASSERT_TRUE( - storage_monitor_->GetStorageTypeObservers(StorageType::kPersistent) - ->GetHostObservers(host_)); - EXPECT_EQ(expected_persistent, GetObserverCount(StorageType::kPersistent)); - } - - StorageMonitor* storage_monitor_; - StorageObserver::MonitorParams params1_; - StorageObserver::MonitorParams params2_; - MockObserver mock_observer1_; - MockObserver mock_observer2_; - MockObserver mock_observer3_; - std::string host_; -}; - -// Test adding storage observers. -TEST_F(StorageMonitorTest, AddObservers) { - // Verify that the observers are added correctly. - CheckObserverCount(2, 3); -} - -// Test dispatching events to storage observers. -TEST_F(StorageMonitorTest, EventDispatch) { - // Verify dispatch of events. - const int64_t kUsage = 5325; - const int64_t kQuota = 903845; - quota_manager_->SetCallbackParams(kUsage, kQuota, QuotaStatusCode::kOk); - storage_monitor_->NotifyUsageChange(params1_.filter, 9048543); - - StorageObserver::Event expected_event(params1_.filter, kUsage, kQuota); - EXPECT_EQ(1u, mock_observer1_.EventCount()); - EXPECT_EQ(1u, mock_observer2_.EventCount()); - EXPECT_EQ(0u, mock_observer3_.EventCount()); - EXPECT_EQ(expected_event, mock_observer1_.LastEvent()); - EXPECT_EQ(expected_event, mock_observer2_.LastEvent()); -} - -// Test removing all instances of an observer. -TEST_F(StorageMonitorTest, RemoveObserver) { - storage_monitor_->RemoveObserver(&mock_observer1_); - CheckObserverCount(1, 2); -} - -// Integration test for QuotaManager and StorageMonitor: - -class StorageMonitorIntegrationTest : public testing::Test { - public: - void SetUp() override { - ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); - storage_policy_ = new MockSpecialStoragePolicy(); - quota_manager_ = new QuotaManager( - false, data_dir_.GetPath(), base::ThreadTaskRunnerHandle::Get().get(), - storage_policy_.get(), storage::GetQuotaSettingsFunc()); - - client_ = new MockStorageClient(quota_manager_->proxy(), nullptr, - QuotaClient::kFileSystem, 0); - - quota_manager_->proxy()->RegisterClient(client_); - } - - void TearDown() override { - // This ensures the quota manager is destroyed correctly. - quota_manager_ = nullptr; - scoped_task_environment_.RunUntilIdle(); - } - - protected: - base::test::ScopedTaskEnvironment scoped_task_environment_; - base::ScopedTempDir data_dir_; - scoped_refptr<MockSpecialStoragePolicy> storage_policy_; - scoped_refptr<QuotaManager> quota_manager_; - MockStorageClient* client_; -}; - -// This test simulates a usage change in a quota client and verifies that a -// storage observer will receive a storage event. -TEST_F(StorageMonitorIntegrationTest, NotifyUsageEvent) { - const StorageType kTestStorageType = StorageType::kPersistent; - const int64_t kTestUsage = 234743; - - // Register the observer. - StorageObserver::MonitorParams params(kTestStorageType, kDefaultOrigin, - base::TimeDelta::FromHours(1), false); - MockObserver mock_observer; - quota_manager_->AddStorageObserver(&mock_observer, params); - - // Fire a usage change. - client_->AddOriginAndNotify(kDefaultOrigin, kTestStorageType, kTestUsage); - scoped_task_environment_.RunUntilIdle(); - - // Verify that the observer receives it. - ASSERT_EQ(1u, mock_observer.EventCount()); - const StorageObserver::Event& event = mock_observer.LastEvent(); - EXPECT_EQ(params.filter, event.filter); - EXPECT_EQ(kTestUsage, event.usage); -} - -} // namespace content diff --git a/chromium/storage/browser/quota/storage_observer.cc b/chromium/storage/browser/quota/storage_observer.cc deleted file mode 100644 index b7ab0b1b673..00000000000 --- a/chromium/storage/browser/quota/storage_observer.cc +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "storage/browser/quota/storage_observer.h" - -#include <stdint.h> - -#include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h" - -namespace storage { - -// StorageObserver::Filter - -StorageObserver::Filter::Filter() - : storage_type(blink::mojom::StorageType::kUnknown) {} - -StorageObserver::Filter::Filter(blink::mojom::StorageType storage_type, - const url::Origin& origin) - : storage_type(storage_type), origin(origin) {} - -bool StorageObserver::Filter::operator==(const Filter& other) const { - return storage_type == other.storage_type && - origin == other.origin; -} - -// StorageObserver::MonitorParams - -StorageObserver::MonitorParams::MonitorParams() - : dispatch_initial_state(false) { -} - -StorageObserver::MonitorParams::MonitorParams( - blink::mojom::StorageType storage_type, - const url::Origin& origin, - const base::TimeDelta& rate, - bool get_initial_state) - : filter(storage_type, origin), - rate(rate), - dispatch_initial_state(get_initial_state) {} - -StorageObserver::MonitorParams::MonitorParams( - const Filter& filter, - const base::TimeDelta& rate, - bool get_initial_state) - : filter(filter), - rate(rate), - dispatch_initial_state(get_initial_state) { -} - -// StorageObserver::Event - -StorageObserver::Event::Event() - : usage(0), quota(0) { -} - -StorageObserver::Event::Event(const Filter& filter, - int64_t usage, - int64_t quota) - : filter(filter), usage(usage), quota(quota) {} - -bool StorageObserver::Event::operator==(const Event& other) const { - return filter == other.filter && - usage == other.usage && - quota == other.quota; -} - -} // namespace storage diff --git a/chromium/storage/browser/quota/storage_observer.h b/chromium/storage/browser/quota/storage_observer.h deleted file mode 100644 index e38c19ad781..00000000000 --- a/chromium/storage/browser/quota/storage_observer.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef STORAGE_BROWSER_QUOTA_STORAGE_OBSERVER_H_ -#define STORAGE_BROWSER_QUOTA_STORAGE_OBSERVER_H_ - -#include <stdint.h> - -#include "base/component_export.h" -#include "base/time/time.h" -#include "storage/browser/quota/quota_client.h" -#include "third_party/blink/public/mojom/quota/quota_types.mojom-forward.h" -#include "url/origin.h" - -namespace storage { - -// This interface is implemented by observers that wish to monitor storage -// events, such as changes in quota or usage. -class COMPONENT_EXPORT(STORAGE_BROWSER) StorageObserver { - public: - struct COMPONENT_EXPORT(STORAGE_BROWSER) Filter { - // The storage type to monitor. This must not be kUnknown or - // kQuotaNotManaged. - blink::mojom::StorageType storage_type; - - // The origin to monitor usage for. Must be specified. - url::Origin origin; - - Filter(); - Filter(blink::mojom::StorageType storage_type, const url::Origin& origin); - bool operator==(const Filter& other) const; - }; - - struct COMPONENT_EXPORT(STORAGE_BROWSER) MonitorParams { - // Storage type and origin to monitor. - Filter filter; - - // The rate at which storage events will be fired. Events will be fired at - // approximately this rate, or when a storage status change has been - // detected, whichever is the least frequent. - base::TimeDelta rate; - - // If set to true, the observer will be dispatched an event when added. - bool dispatch_initial_state; - - MonitorParams(); - MonitorParams(blink::mojom::StorageType storage_type, - const url::Origin& origin, - const base::TimeDelta& rate, - bool get_initial_state); - MonitorParams(const Filter& filter, - const base::TimeDelta& rate, - bool get_initial_state); - }; - - struct COMPONENT_EXPORT(STORAGE_BROWSER) Event { - // The storage type and origin monitored. - Filter filter; - - // The current usage corresponding to the filter. - int64_t usage; - - // The quota corresponding to the filter. - int64_t quota; - - Event(); - Event(const Filter& filter, int64_t usage, int64_t quota); - bool operator==(const Event& other) const; - }; - - // Will be called on the IO thread when a storage event occurs. - virtual void OnStorageEvent(const Event& event) = 0; - - protected: - virtual ~StorageObserver() {} -}; - -} // namespace storage - -#endif // STORAGE_BROWSER_QUOTA_STORAGE_OBSERVER_H_ diff --git a/chromium/storage/browser/quota/usage_tracker.cc b/chromium/storage/browser/quota/usage_tracker.cc index 8f3516d292b..989a9bc33f6 100644 --- a/chromium/storage/browser/quota/usage_tracker.cc +++ b/chromium/storage/browser/quota/usage_tracker.cc @@ -12,7 +12,6 @@ #include "base/barrier_closure.h" #include "base/bind.h" #include "storage/browser/quota/client_usage_tracker.h" -#include "storage/browser/quota/storage_monitor.h" namespace storage { @@ -35,13 +34,12 @@ void StripUsageWithBreakdownCallback( UsageTracker::UsageTracker(const std::vector<QuotaClient*>& clients, blink::mojom::StorageType type, - SpecialStoragePolicy* special_storage_policy, - StorageMonitor* storage_monitor) - : type_(type), storage_monitor_(storage_monitor), weak_factory_(this) { + SpecialStoragePolicy* special_storage_policy) + : type_(type), weak_factory_(this) { for (auto* client : clients) { if (client->DoesSupport(type)) { client_tracker_map_[client->id()] = std::make_unique<ClientUsageTracker>( - this, client, type, special_storage_policy, storage_monitor_); + this, client, type, special_storage_policy); } } } diff --git a/chromium/storage/browser/quota/usage_tracker.h b/chromium/storage/browser/quota/usage_tracker.h index 74bcb1fd7a4..18863c15248 100644 --- a/chromium/storage/browser/quota/usage_tracker.h +++ b/chromium/storage/browser/quota/usage_tracker.h @@ -27,18 +27,20 @@ namespace storage { class ClientUsageTracker; -class StorageMonitor; // A helper class that gathers and tracks the amount of data stored in // all quota clients. -// An instance of this class is created per storage type. +// +// Ownership: Each QuotaManager instance owns 3 instances of this class (one per +// storage type: Persistent, Temporary, Syncable). +// Thread-safety: All methods except the constructor must be called on the same +// sequence. class COMPONENT_EXPORT(STORAGE_BROWSER) UsageTracker : public QuotaTaskObserver { public: UsageTracker(const std::vector<QuotaClient*>& clients, blink::mojom::StorageType type, - SpecialStoragePolicy* special_storage_policy, - StorageMonitor* storage_monitor); + SpecialStoragePolicy* special_storage_policy); ~UsageTracker() override; blink::mojom::StorageType type() const { @@ -103,8 +105,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) UsageTracker std::map<std::string, std::vector<UsageWithBreakdownCallback>> host_usage_callbacks_; - StorageMonitor* storage_monitor_; - SEQUENCE_CHECKER(sequence_checker_); base::WeakPtrFactory<UsageTracker> weak_factory_; diff --git a/chromium/storage/browser/quota/usage_tracker_unittest.cc b/chromium/storage/browser/quota/usage_tracker_unittest.cc index dbb48977f9a..720d756a2ee 100644 --- a/chromium/storage/browser/quota/usage_tracker_unittest.cc +++ b/chromium/storage/browser/quota/usage_tracker_unittest.cc @@ -128,8 +128,7 @@ class UsageTrackerTest : public testing::Test { : storage_policy_(new MockSpecialStoragePolicy()), usage_tracker_(GetUsageTrackerList(), StorageType::kTemporary, - storage_policy_.get(), - nullptr) {} + storage_policy_.get()) {} ~UsageTrackerTest() override = default; diff --git a/chromium/storage/common/BUILD.gn b/chromium/storage/common/BUILD.gn index 6c7d280ae42..5168f016c31 100644 --- a/chromium/storage/common/BUILD.gn +++ b/chromium/storage/common/BUILD.gn @@ -36,7 +36,7 @@ component("common") { defines = [ "IS_STORAGE_COMMON_IMPL" ] public_deps = [ - "//components/services/filesystem/public/interfaces", + "//components/services/filesystem/public/mojom", "//services/network/public/mojom", "//third_party/blink/public:blink_headers", ] |