summaryrefslogtreecommitdiff
path: root/chromium/storage
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2021-05-20 09:47:09 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2021-06-07 11:15:42 +0000
commit189d4fd8fad9e3c776873be51938cd31a42b6177 (patch)
tree6497caeff5e383937996768766ab3bb2081a40b2 /chromium/storage
parent8bc75099d364490b22f43a7ce366b366c08f4164 (diff)
downloadqtwebengine-chromium-189d4fd8fad9e3c776873be51938cd31a42b6177.tar.gz
BASELINE: Update Chromium to 90.0.4430.221
Change-Id: Iff4d9d18d2fcf1a576f3b1f453010f744a232920 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/storage')
-rw-r--r--chromium/storage/OWNERS1
-rw-r--r--chromium/storage/browser/BUILD.gn8
-rw-r--r--chromium/storage/browser/blob/blob_builder_from_stream_unittest.cc59
-rw-r--r--chromium/storage/browser/blob/blob_impl_unittest.cc82
-rw-r--r--chromium/storage/browser/blob/blob_reader.cc2
-rw-r--r--chromium/storage/browser/blob/blob_reader_unittest.cc4
-rw-r--r--chromium/storage/browser/blob/blob_registry_impl_unittest.cc19
-rw-r--r--chromium/storage/browser/blob/blob_storage_context_mojo_unittest.cc4
-rw-r--r--chromium/storage/browser/blob/blob_transport_strategy.cc6
-rw-r--r--chromium/storage/browser/blob/blob_url_loader.cc2
-rw-r--r--chromium/storage/browser/database/database_quota_client.cc104
-rw-r--r--chromium/storage/browser/database/database_quota_client.h13
-rw-r--r--chromium/storage/browser/database/database_quota_client_unittest.cc13
-rw-r--r--chromium/storage/browser/database/database_tracker.cc250
-rw-r--r--chromium/storage/browser/database/database_tracker.h123
-rw-r--r--chromium/storage/browser/database/database_tracker_unittest.cc93
-rw-r--r--chromium/storage/browser/file_system/README.md6
-rw-r--r--chromium/storage/browser/file_system/async_file_util.h6
-rw-r--r--chromium/storage/browser/file_system/async_file_util_adapter.cc5
-rw-r--r--chromium/storage/browser/file_system/async_file_util_adapter.h7
-rw-r--r--chromium/storage/browser/file_system/copy_or_move_file_validator_unittest.cc19
-rw-r--r--chromium/storage/browser/file_system/copy_or_move_operation_delegate.cc13
-rw-r--r--chromium/storage/browser/file_system/copy_or_move_operation_delegate_unittest.cc18
-rw-r--r--chromium/storage/browser/file_system/external_mount_points.cc8
-rw-r--r--chromium/storage/browser/file_system/external_mount_points_unittest.cc45
-rw-r--r--chromium/storage/browser/file_system/file_stream_writer_test.h10
-rw-r--r--chromium/storage/browser/file_system/file_system_context.cc68
-rw-r--r--chromium/storage/browser/file_system/file_system_context_unittest.cc45
-rw-r--r--chromium/storage/browser/file_system/file_system_operation_impl.cc24
-rw-r--r--chromium/storage/browser/file_system/file_system_operation_impl.h7
-rw-r--r--chromium/storage/browser/file_system/file_system_operation_impl_unittest.cc18
-rw-r--r--chromium/storage/browser/file_system/file_system_operation_impl_write_unittest.cc11
-rw-r--r--chromium/storage/browser/file_system/file_system_operation_runner.cc14
-rw-r--r--chromium/storage/browser/file_system/file_system_operation_runner.h6
-rw-r--r--chromium/storage/browser/file_system/file_system_quota_client.cc45
-rw-r--r--chromium/storage/browser/file_system/file_system_usage_cache.cc2
-rw-r--r--chromium/storage/browser/file_system/isolated_context_unittest.cc14
-rw-r--r--chromium/storage/browser/file_system/isolated_file_system_backend.cc17
-rw-r--r--chromium/storage/browser/file_system/local_file_stream_reader.cc3
-rw-r--r--chromium/storage/browser/file_system/local_file_stream_writer.cc35
-rw-r--r--chromium/storage/browser/file_system/local_file_stream_writer.h5
-rw-r--r--chromium/storage/browser/file_system/local_file_util.cc4
-rw-r--r--chromium/storage/browser/file_system/local_file_util_unittest.cc28
-rw-r--r--chromium/storage/browser/file_system/obfuscated_file_util.cc23
-rw-r--r--chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc47
-rw-r--r--chromium/storage/browser/file_system/obfuscated_file_util_unittest.cc262
-rw-r--r--chromium/storage/browser/file_system/plugin_private_file_system_backend.cc18
-rw-r--r--chromium/storage/browser/file_system/quota/quota_backend_impl.cc5
-rw-r--r--chromium/storage/browser/file_system/quota/quota_backend_impl_unittest.cc32
-rw-r--r--chromium/storage/browser/file_system/quota/quota_reservation_manager_unittest.cc6
-rw-r--r--chromium/storage/browser/file_system/recursive_operation_delegate_unittest.cc5
-rw-r--r--chromium/storage/browser/file_system/sandbox_directory_database_unittest.cc4
-rw-r--r--chromium/storage/browser/file_system/sandbox_file_stream_writer.cc44
-rw-r--r--chromium/storage/browser/file_system/sandbox_file_stream_writer.h3
-rw-r--r--chromium/storage/browser/file_system/sandbox_file_stream_writer_unittest.cc241
-rw-r--r--chromium/storage/browser/file_system/sandbox_file_system_backend_delegate.cc75
-rw-r--r--chromium/storage/browser/file_system/sandbox_file_system_backend_delegate_unittest.cc2
-rw-r--r--chromium/storage/browser/file_system/sandbox_file_system_backend_unittest.cc6
-rw-r--r--chromium/storage/browser/file_system/sandbox_origin_database_unittest.cc10
-rw-r--r--chromium/storage/browser/file_system/sandbox_prioritized_origin_database.cc16
-rw-r--r--chromium/storage/browser/file_system/sandbox_quota_observer.cc5
-rw-r--r--chromium/storage/browser/quota/README.md78
-rw-r--r--chromium/storage/browser/quota/client_usage_tracker.cc2
-rw-r--r--chromium/storage/browser/quota/mojo_quota_client_wrapper.cc71
-rw-r--r--chromium/storage/browser/quota/mojo_quota_client_wrapper.h61
-rw-r--r--chromium/storage/browser/quota/padding_key.h70
-rw-r--r--chromium/storage/browser/quota/quota_callbacks.h3
-rw-r--r--chromium/storage/browser/quota/quota_client.h67
-rw-r--r--chromium/storage/browser/quota/quota_client_type.cc1
-rw-r--r--chromium/storage/browser/quota/quota_client_type.h1
-rw-r--r--chromium/storage/browser/quota/quota_database.cc35
-rw-r--r--chromium/storage/browser/quota/quota_database.h20
-rw-r--r--chromium/storage/browser/quota/quota_database_unittest.cc38
-rw-r--r--chromium/storage/browser/quota/quota_features.cc26
-rw-r--r--chromium/storage/browser/quota/quota_features.h9
-rw-r--r--chromium/storage/browser/quota/quota_manager.cc1961
-rw-r--r--chromium/storage/browser/quota/quota_manager.h566
-rw-r--r--chromium/storage/browser/quota/quota_manager_impl.cc1999
-rw-r--r--chromium/storage/browser/quota/quota_manager_impl.h613
-rw-r--r--chromium/storage/browser/quota/quota_manager_proxy.cc321
-rw-r--r--chromium/storage/browser/quota/quota_manager_proxy.h157
-rw-r--r--chromium/storage/browser/quota/quota_manager_unittest.cc702
-rw-r--r--chromium/storage/browser/quota/quota_override_handle.cc16
-rw-r--r--chromium/storage/browser/quota/quota_override_handle.h15
-rw-r--r--chromium/storage/browser/quota/quota_settings.cc29
-rw-r--r--chromium/storage/browser/quota/quota_settings_unittest.cc137
-rw-r--r--chromium/storage/browser/quota/quota_task.cc2
-rw-r--r--chromium/storage/browser/quota/quota_task.h3
-rw-r--r--chromium/storage/browser/quota/quota_temporary_storage_evictor.cc2
-rw-r--r--chromium/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc4
-rw-r--r--chromium/storage/browser/quota/storage_policy_observer.cc136
-rw-r--r--chromium/storage/browser/quota/storage_policy_observer.h85
-rw-r--r--chromium/storage/browser/quota/usage_tracker.cc3
-rw-r--r--chromium/storage/browser/quota/usage_tracker.h10
-rw-r--r--chromium/storage/common/BUILD.gn2
-rw-r--r--chromium/storage/common/database/database_identifier.cc4
-rw-r--r--chromium/storage/common/file_system/file_system_types.h19
-rw-r--r--chromium/storage/common/file_system/file_system_util.cc22
-rw-r--r--chromium/storage/common/quota/padding_key.cc (renamed from chromium/storage/browser/quota/padding_key.cc)67
-rw-r--r--chromium/storage/common/quota/padding_key.h51
100 files changed, 5390 insertions, 4088 deletions
diff --git a/chromium/storage/OWNERS b/chromium/storage/OWNERS
index 919ed9bbf50..7ccd317ff28 100644
--- a/chromium/storage/OWNERS
+++ b/chromium/storage/OWNERS
@@ -1,3 +1,4 @@
+set noparent
dmurph@chromium.org
jsbell@chromium.org
pwnall@chromium.org
diff --git a/chromium/storage/browser/BUILD.gn b/chromium/storage/browser/BUILD.gn
index 92d357a9636..bb9f5ff3184 100644
--- a/chromium/storage/browser/BUILD.gn
+++ b/chromium/storage/browser/BUILD.gn
@@ -182,8 +182,8 @@ component("browser") {
"file_system/watcher_manager.h",
"quota/client_usage_tracker.cc",
"quota/client_usage_tracker.h",
- "quota/padding_key.cc",
- "quota/padding_key.h",
+ "quota/mojo_quota_client_wrapper.cc",
+ "quota/mojo_quota_client_wrapper.h",
"quota/quota_callbacks.h",
"quota/quota_client.h",
"quota/quota_client_type.cc",
@@ -197,6 +197,8 @@ component("browser") {
"quota/quota_macros.h",
"quota/quota_manager.cc",
"quota/quota_manager.h",
+ "quota/quota_manager_impl.cc",
+ "quota/quota_manager_impl.h",
"quota/quota_manager_proxy.cc",
"quota/quota_manager_proxy.h",
"quota/quota_override_handle.cc",
@@ -209,6 +211,8 @@ component("browser") {
"quota/quota_temporary_storage_evictor.h",
"quota/special_storage_policy.cc",
"quota/special_storage_policy.h",
+ "quota/storage_policy_observer.cc",
+ "quota/storage_policy_observer.h",
"quota/usage_tracker.cc",
"quota/usage_tracker.h",
]
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 89df0f70f96..3db6bbb9926 100644
--- a/chromium/storage/browser/blob/blob_builder_from_stream_unittest.cc
+++ b/chromium/storage/browser/blob/blob_builder_from_stream_unittest.cc
@@ -91,7 +91,11 @@ class BlobBuilderFromStreamTestWithDelayedLimits
std::unique_ptr<BlobDataHandle> BuildFromString(
std::string data,
bool initial_allocation_should_succeed = true) {
- mojo::DataPipe pipe;
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ EXPECT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
+
base::RunLoop loop;
std::unique_ptr<BlobDataHandle> result;
uint64_t length_hint = GetLengthHint(data.length());
@@ -104,7 +108,7 @@ class BlobBuilderFromStreamTestWithDelayedLimits
result = std::move(blob);
loop.Quit();
}));
- builder.Start(length_hint, std::move(pipe.consumer_handle),
+ builder.Start(length_hint, std::move(consumer_handle),
mojo::NullAssociatedRemote());
// Make sure the initial memory allocation done by the builder matches the
@@ -117,8 +121,8 @@ class BlobBuilderFromStreamTestWithDelayedLimits
<< ", disk_usage: " << context_->memory_controller().disk_usage();
}
- mojo::BlockingCopyFromString(data, pipe.producer_handle);
- pipe.producer_handle.reset();
+ mojo::BlockingCopyFromString(data, producer_handle);
+ producer_handle.reset();
loop.Run();
EXPECT_EQ(&builder, finished_builder);
@@ -195,7 +199,10 @@ class BlobBuilderFromStreamTest
};
TEST_P(BlobBuilderFromStreamTest, CallbackCalledOnAbortBeforeDeletion) {
- mojo::DataPipe pipe;
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
base::RunLoop loop;
BlobBuilderFromStream* builder_ptr = nullptr;
@@ -208,7 +215,7 @@ TEST_P(BlobBuilderFromStreamTest, CallbackCalledOnAbortBeforeDeletion) {
loop.Quit();
}));
builder_ptr = builder.get();
- builder->Start(GetLengthHint(16), std::move(pipe.consumer_handle),
+ builder->Start(GetLengthHint(16), std::move(consumer_handle),
mojo::NullAssociatedRemote());
builder->Abort();
builder.reset();
@@ -364,7 +371,11 @@ TEST_P(BlobBuilderFromStreamTest, TooLargeForQuotaAndNoDisk) {
TEST_F(BlobBuilderFromStreamTest, HintTooLargeForQuota) {
const uint64_t kLengthHint =
kTestBlobStorageMaxDiskSpace + kTestBlobStorageMaxBlobMemorySize + 1;
- mojo::DataPipe pipe;
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
+
base::RunLoop loop;
std::unique_ptr<BlobDataHandle> result;
BlobBuilderFromStream builder(
@@ -374,9 +385,9 @@ TEST_F(BlobBuilderFromStreamTest, HintTooLargeForQuota) {
result = std::move(blob);
loop.Quit();
}));
- builder.Start(kLengthHint, std::move(pipe.consumer_handle),
+ builder.Start(kLengthHint, std::move(consumer_handle),
mojo::NullAssociatedRemote());
- pipe.producer_handle.reset();
+ producer_handle.reset();
loop.Run();
EXPECT_FALSE(result);
@@ -388,7 +399,10 @@ TEST_F(BlobBuilderFromStreamTest, HintTooLargeForQuotaAndNoDisk) {
context_->DisableFilePagingForTesting();
const uint64_t kLengthHint = kTestBlobStorageMaxBlobMemorySize + 1;
- mojo::DataPipe pipe;
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
base::RunLoop loop;
std::unique_ptr<BlobDataHandle> result;
BlobBuilderFromStream builder(
@@ -398,9 +412,9 @@ TEST_F(BlobBuilderFromStreamTest, HintTooLargeForQuotaAndNoDisk) {
result = std::move(blob);
loop.Quit();
}));
- builder.Start(kLengthHint, std::move(pipe.consumer_handle),
+ builder.Start(kLengthHint, std::move(consumer_handle),
mojo::NullAssociatedRemote());
- pipe.producer_handle.reset();
+ producer_handle.reset();
loop.Run();
EXPECT_FALSE(result);
@@ -418,7 +432,10 @@ TEST_P(BlobBuilderFromStreamTest, ProgressEvents) {
&progress_client,
progress_client_remote.BindNewEndpointAndPassDedicatedReceiver());
- mojo::DataPipe pipe;
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
base::RunLoop loop;
std::unique_ptr<BlobDataHandle> result;
BlobBuilderFromStream builder(
@@ -428,10 +445,10 @@ TEST_P(BlobBuilderFromStreamTest, ProgressEvents) {
result = std::move(blob);
loop.Quit();
}));
- builder.Start(GetLengthHint(kData.size()), std::move(pipe.consumer_handle),
+ builder.Start(GetLengthHint(kData.size()), std::move(consumer_handle),
progress_client_remote.Unbind());
- mojo::BlockingCopyFromString(kData, pipe.producer_handle);
- pipe.producer_handle.reset();
+ mojo::BlockingCopyFromString(kData, producer_handle);
+ producer_handle.reset();
loop.Run();
progress_receiver.FlushForTesting();
@@ -453,7 +470,10 @@ TEST_F(BlobBuilderFromStreamTestWithDelayedLimits, LargeStream) {
limits_.desired_max_disk_space = kDefaultMinPageFileSize * 2;
limits_.effective_max_disk_space = kDefaultMinPageFileSize * 2;
- mojo::DataPipe pipe;
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
base::RunLoop loop;
std::unique_ptr<BlobDataHandle> result;
BlobBuilderFromStream builder(
@@ -463,12 +483,12 @@ TEST_F(BlobBuilderFromStreamTestWithDelayedLimits, LargeStream) {
result = std::move(blob);
loop.Quit();
}));
- builder.Start(kData.size(), std::move(pipe.consumer_handle),
+ builder.Start(kData.size(), std::move(consumer_handle),
mojo::NullAssociatedRemote());
context_->set_limits_for_testing(limits_);
auto data_producer =
- std::make_unique<mojo::DataPipeProducer>(std::move(pipe.producer_handle));
+ std::make_unique<mojo::DataPipeProducer>(std::move(producer_handle));
auto* producer_ptr = data_producer.get();
producer_ptr->Write(
std::make_unique<mojo::StringDataSource>(
@@ -478,7 +498,6 @@ TEST_F(BlobBuilderFromStreamTestWithDelayedLimits, LargeStream) {
base::DoNothing::Once<std::unique_ptr<mojo::DataPipeProducer>,
MojoResult>(),
std::move(data_producer)));
- pipe.producer_handle.reset();
loop.Run();
ASSERT_TRUE(result);
diff --git a/chromium/storage/browser/blob/blob_impl_unittest.cc b/chromium/storage/browser/blob/blob_impl_unittest.cc
index 95f3908e98c..fcb524760b3 100644
--- a/chromium/storage/browser/blob/blob_impl_unittest.cc
+++ b/chromium/storage/browser/blob/blob_impl_unittest.cc
@@ -160,10 +160,14 @@ TEST_F(BlobImplTest, ReadAll) {
MockBlobReaderClient client;
mojo::Receiver<blink::mojom::BlobReaderClient> client_receiver(&client);
- mojo::DataPipe pipe;
- remote->ReadAll(std::move(pipe.producer_handle),
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
+
+ remote->ReadAll(std::move(producer_handle),
client_receiver.BindNewPipeAndPassRemote());
- std::string received = ReadDataPipe(std::move(pipe.consumer_handle));
+ std::string received = ReadDataPipe(std::move(consumer_handle));
EXPECT_EQ(kContents, received);
client_receiver.FlushForTesting();
@@ -184,9 +188,12 @@ TEST_F(BlobImplTest, ReadAll_WithoutClient) {
mojo::Remote<blink::mojom::Blob> remote;
BlobImpl::Create(std::move(handle), remote.BindNewPipeAndPassReceiver());
- mojo::DataPipe pipe;
- remote->ReadAll(std::move(pipe.producer_handle), mojo::NullRemote());
- std::string received = ReadDataPipe(std::move(pipe.consumer_handle));
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
+ remote->ReadAll(std::move(producer_handle), mojo::NullRemote());
+ std::string received = ReadDataPipe(std::move(consumer_handle));
EXPECT_EQ(kContents, received);
}
@@ -201,11 +208,14 @@ TEST_F(BlobImplTest, ReadAll_BrokenBlob) {
MockBlobReaderClient client;
mojo::Receiver<blink::mojom::BlobReaderClient> client_receiver(&client);
- mojo::DataPipe pipe;
- remote->ReadAll(std::move(pipe.producer_handle),
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
+ remote->ReadAll(std::move(producer_handle),
client_receiver.BindNewPipeAndPassRemote());
- std::string received = ReadDataPipe(std::move(pipe.consumer_handle));
+ std::string received = ReadDataPipe(std::move(consumer_handle));
EXPECT_EQ("", received);
client_receiver.FlushForTesting();
@@ -226,11 +236,14 @@ TEST_F(BlobImplTest, ReadRange) {
MockBlobReaderClient client;
mojo::Receiver<blink::mojom::BlobReaderClient> client_receiver(&client);
- mojo::DataPipe pipe;
- remote->ReadRange(2, 5, std::move(pipe.producer_handle),
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
+ remote->ReadRange(2, 5, std::move(producer_handle),
client_receiver.BindNewPipeAndPassRemote());
- std::string received = ReadDataPipe(std::move(pipe.consumer_handle));
+ std::string received = ReadDataPipe(std::move(consumer_handle));
EXPECT_EQ(kContents.substr(2, 5), received);
client_receiver.FlushForTesting();
@@ -251,10 +264,13 @@ TEST_F(BlobImplTest, ReadRange_WithoutClient) {
mojo::Remote<blink::mojom::Blob> remote;
BlobImpl::Create(std::move(handle), remote.BindNewPipeAndPassReceiver());
- mojo::DataPipe pipe;
- remote->ReadRange(2, 5, std::move(pipe.producer_handle), mojo::NullRemote());
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
+ remote->ReadRange(2, 5, std::move(producer_handle), mojo::NullRemote());
- std::string received = ReadDataPipe(std::move(pipe.consumer_handle));
+ std::string received = ReadDataPipe(std::move(consumer_handle));
EXPECT_EQ(kContents.substr(2, 5), received);
}
@@ -269,11 +285,14 @@ TEST_F(BlobImplTest, ReadRange_TooLargeLength) {
MockBlobReaderClient client;
mojo::Receiver<blink::mojom::BlobReaderClient> client_receiver(&client);
- mojo::DataPipe pipe;
- remote->ReadRange(2, 15, std::move(pipe.producer_handle),
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
+ remote->ReadRange(2, 15, std::move(producer_handle),
client_receiver.BindNewPipeAndPassRemote());
- std::string received = ReadDataPipe(std::move(pipe.consumer_handle));
+ std::string received = ReadDataPipe(std::move(consumer_handle));
EXPECT_EQ(kContents.substr(2, 15), received);
client_receiver.FlushForTesting();
@@ -297,12 +316,15 @@ TEST_F(BlobImplTest, ReadRange_UnboundedLength) {
MockBlobReaderClient client;
mojo::Receiver<blink::mojom::BlobReaderClient> client_receiver(&client);
- mojo::DataPipe pipe;
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
remote->ReadRange(2, std::numeric_limits<uint64_t>::max(),
- std::move(pipe.producer_handle),
+ std::move(producer_handle),
client_receiver.BindNewPipeAndPassRemote());
- std::string received = ReadDataPipe(std::move(pipe.consumer_handle));
+ std::string received = ReadDataPipe(std::move(consumer_handle));
EXPECT_EQ(kContents.substr(2, kContents.size()), received);
client_receiver.FlushForTesting();
@@ -326,11 +348,14 @@ TEST_F(BlobImplTest, ReadRange_BrokenBlob) {
MockBlobReaderClient client;
mojo::Receiver<blink::mojom::BlobReaderClient> client_receiver(&client);
- mojo::DataPipe pipe;
- remote->ReadRange(2, 5, std::move(pipe.producer_handle),
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
+ remote->ReadRange(2, 5, std::move(producer_handle),
client_receiver.BindNewPipeAndPassRemote());
- std::string received = ReadDataPipe(std::move(pipe.consumer_handle));
+ std::string received = ReadDataPipe(std::move(consumer_handle));
EXPECT_EQ("", received);
client_receiver.FlushForTesting();
@@ -352,11 +377,14 @@ TEST_F(BlobImplTest, ReadRange_InvalidRange) {
mojo::Receiver<blink::mojom::BlobReaderClient> client_receiver(&client);
base::RunLoop loop;
- mojo::DataPipe pipe;
- remote->ReadRange(15, 4, std::move(pipe.producer_handle),
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
+ MOJO_RESULT_OK);
+ remote->ReadRange(15, 4, std::move(producer_handle),
client_receiver.BindNewPipeAndPassRemote());
- std::string received = ReadDataPipe(std::move(pipe.consumer_handle));
+ std::string received = ReadDataPipe(std::move(consumer_handle));
EXPECT_EQ("", received);
client_receiver.FlushForTesting();
diff --git a/chromium/storage/browser/blob/blob_reader.cc b/chromium/storage/browser/blob/blob_reader.cc
index 9be28796b69..1adc28006a0 100644
--- a/chromium/storage/browser/blob/blob_reader.cc
+++ b/chromium/storage/browser/blob/blob_reader.cc
@@ -803,7 +803,7 @@ std::unique_ptr<network::DataPipeToSourceStream> BlobReader::CreateDataPipe(
options.capacity_num_bytes =
blink::BlobUtils::GetDataPipeCapacity(max_bytes_to_read);
- MojoResult result = mojo::CreateDataPipe(&options, &producer, &consumer);
+ MojoResult result = mojo::CreateDataPipe(&options, producer, consumer);
if (result != MOJO_RESULT_OK)
return nullptr;
diff --git a/chromium/storage/browser/blob/blob_reader_unittest.cc b/chromium/storage/browser/blob/blob_reader_unittest.cc
index 1d56b6c7ac9..26a4973299f 100644
--- a/chromium/storage/browser/blob/blob_reader_unittest.cc
+++ b/chromium/storage/browser/blob/blob_reader_unittest.cc
@@ -673,7 +673,7 @@ TEST_F(BlobReaderTest, ReadableDataHandleSingle) {
mojo::ScopedDataPipeProducerHandle producer;
mojo::ScopedDataPipeConsumerHandle consumer;
- MojoResult pipe_result = mojo::CreateDataPipe(nullptr, &producer, &consumer);
+ MojoResult pipe_result = mojo::CreateDataPipe(nullptr, producer, consumer);
ASSERT_EQ(MOJO_RESULT_OK, pipe_result);
int bytes_read = net::ERR_UNEXPECTED;
@@ -720,7 +720,7 @@ TEST_F(BlobReaderTest, ReadableDataHandleSingleRange) {
mojo::ScopedDataPipeProducerHandle producer;
mojo::ScopedDataPipeConsumerHandle consumer;
- MojoResult pipe_result = mojo::CreateDataPipe(nullptr, &producer, &consumer);
+ MojoResult pipe_result = mojo::CreateDataPipe(nullptr, producer, consumer);
ASSERT_EQ(MOJO_RESULT_OK, pipe_result);
int bytes_read = net::ERR_UNEXPECTED;
diff --git a/chromium/storage/browser/blob/blob_registry_impl_unittest.cc b/chromium/storage/browser/blob/blob_registry_impl_unittest.cc
index 69039f08d5a..64ed3dff9f3 100644
--- a/chromium/storage/browser/blob/blob_registry_impl_unittest.cc
+++ b/chromium/storage/browser/blob/blob_registry_impl_unittest.cc
@@ -1102,7 +1102,7 @@ TEST_F(BlobRegistryImplTest, RegisterFromStream) {
mojo::ScopedDataPipeProducerHandle producer;
mojo::ScopedDataPipeConsumerHandle consumer;
- mojo::CreateDataPipe(nullptr, &producer, &consumer);
+ mojo::CreateDataPipe(nullptr, producer, consumer);
blink::mojom::SerializedBlobPtr blob;
base::RunLoop loop;
registry_->RegisterFromStream(
@@ -1142,7 +1142,7 @@ TEST_F(BlobRegistryImplTest, RegisterFromStream_NoDiskSpace) {
mojo::ScopedDataPipeProducerHandle producer;
mojo::ScopedDataPipeConsumerHandle consumer;
- mojo::CreateDataPipe(nullptr, &producer, &consumer);
+ mojo::CreateDataPipe(nullptr, producer, consumer);
blink::mojom::SerializedBlobPtr blob;
base::RunLoop loop;
registry_->RegisterFromStream(
@@ -1161,11 +1161,20 @@ TEST_F(BlobRegistryImplTest, RegisterFromStream_NoDiskSpace) {
}
TEST_F(BlobRegistryImplTest, DestroyWithUnfinishedStream) {
- mojo::DataPipe pipe1, pipe2;
- registry_->RegisterFromStream("", "", 0, std::move(pipe1.consumer_handle),
+ mojo::ScopedDataPipeProducerHandle producer_handle1;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle1;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle1, consumer_handle1),
+ MOJO_RESULT_OK);
+
+ mojo::ScopedDataPipeProducerHandle producer_handle2;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle2;
+ ASSERT_EQ(mojo::CreateDataPipe(nullptr, producer_handle2, consumer_handle2),
+ MOJO_RESULT_OK);
+
+ registry_->RegisterFromStream("", "", 0, std::move(consumer_handle1),
mojo::NullAssociatedRemote(),
base::DoNothing());
- registry_->RegisterFromStream("", "", 0, std::move(pipe2.consumer_handle),
+ registry_->RegisterFromStream("", "", 0, std::move(consumer_handle2),
mojo::NullAssociatedRemote(),
base::DoNothing());
registry_.FlushForTesting();
diff --git a/chromium/storage/browser/blob/blob_storage_context_mojo_unittest.cc b/chromium/storage/browser/blob/blob_storage_context_mojo_unittest.cc
index ea95526e8bd..effedb22b2d 100644
--- a/chromium/storage/browser/blob/blob_storage_context_mojo_unittest.cc
+++ b/chromium/storage/browser/blob/blob_storage_context_mojo_unittest.cc
@@ -150,8 +150,8 @@ TEST_F(BlobStorageContextMojoTest, BasicBlobCreation) {
mojo::ScopedDataPipeProducerHandle data_pipe_producer;
mojo::ScopedDataPipeConsumerHandle data_pipe_consumer;
- ASSERT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(nullptr, &data_pipe_producer,
- &data_pipe_consumer));
+ ASSERT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(nullptr, data_pipe_producer,
+ data_pipe_consumer));
blob->ReadAll(std::move(data_pipe_producer), mojo::NullRemote());
std::string received = ReadDataPipe(std::move(data_pipe_consumer));
EXPECT_EQ(std::string(kData), received);
diff --git a/chromium/storage/browser/blob/blob_transport_strategy.cc b/chromium/storage/browser/blob/blob_transport_strategy.cc
index eb660147922..05827b6748e 100644
--- a/chromium/storage/browser/blob/blob_transport_strategy.cc
+++ b/chromium/storage/browser/blob/blob_transport_strategy.cc
@@ -154,7 +154,7 @@ class DataPipeTransportStrategy : public BlobTransportStrategy {
options.capacity_num_bytes =
std::min(expected_source_size, limits_.max_shared_memory_size);
MojoResult result =
- CreateDataPipe(&options, &producer_handle, &consumer_handle_);
+ CreateDataPipe(&options, producer_handle, consumer_handle_);
if (result != MOJO_RESULT_OK) {
DVLOG(1) << "Unable to create data pipe for blob transfer.";
std::move(result_callback_).Run(BlobStatus::ERR_OUT_OF_MEMORY);
@@ -239,7 +239,7 @@ class DataPipeTransportStrategy : public BlobTransportStrategy {
}
}
- const BlobStorageLimits& limits_;
+ const BlobStorageLimits limits_;
base::circular_deque<base::OnceClosure> requests_;
mojo::ScopedDataPipeConsumerHandle consumer_handle_;
@@ -336,7 +336,7 @@ class FileTransportStrategy : public BlobTransportStrategy {
std::move(result_callback_).Run(BlobStatus::DONE);
}
- const BlobStorageLimits& limits_;
+ const BlobStorageLimits limits_;
// State used to assign bytes elements to individual files.
// The index of the first file that still has available space.
diff --git a/chromium/storage/browser/blob/blob_url_loader.cc b/chromium/storage/browser/blob/blob_url_loader.cc
index aa5801ca5c2..072337a8d7c 100644
--- a/chromium/storage/browser/blob/blob_url_loader.cc
+++ b/chromium/storage/browser/blob/blob_url_loader.cc
@@ -155,7 +155,7 @@ void BlobURLLoader::Start(const std::string& method,
options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
options.element_num_bytes = 1;
options.capacity_num_bytes = network::kDataPipeDefaultAllocationSize;
- if (mojo::CreateDataPipe(&options, &producer_handle, &consumer_handle) !=
+ if (mojo::CreateDataPipe(&options, producer_handle, consumer_handle) !=
MOJO_RESULT_OK) {
OnComplete(net::ERR_INSUFFICIENT_RESOURCES, 0);
delete this;
diff --git a/chromium/storage/browser/database/database_quota_client.cc b/chromium/storage/browser/database/database_quota_client.cc
index 7f0c4424153..c297fb3e228 100644
--- a/chromium/storage/browser/database/database_quota_client.cc
+++ b/chromium/storage/browser/database/database_quota_client.cc
@@ -7,12 +7,15 @@
#include <stdint.h>
#include <memory>
+#include <string>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/location.h"
+#include "base/sequence_checker.h"
+#include "base/sequenced_task_runner.h"
#include "base/task_runner_util.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "net/base/completion_once_callback.h"
@@ -38,43 +41,41 @@ int64_t GetOriginUsageOnDBThread(DatabaseTracker* db_tracker,
return 0;
}
-void GetOriginsOnDBThread(DatabaseTracker* db_tracker,
- std::vector<url::Origin>* origins_ptr) {
+std::vector<url::Origin> GetOriginsOnDBThread(DatabaseTracker* db_tracker) {
+ std::vector<url::Origin> all_origins;
std::vector<std::string> origin_identifiers;
if (db_tracker->GetAllOriginIdentifiers(&origin_identifiers)) {
+ all_origins.reserve(origin_identifiers.size());
for (const auto& identifier : origin_identifiers) {
- origins_ptr->push_back(GetOriginFromIdentifier(identifier));
+ all_origins.push_back(GetOriginFromIdentifier(identifier));
}
}
+ return all_origins;
}
-void GetOriginsForHostOnDBThread(DatabaseTracker* db_tracker,
- std::vector<url::Origin>* origins_ptr,
- const std::string& host) {
+std::vector<url::Origin> GetOriginsForHostOnDBThread(
+ DatabaseTracker* db_tracker,
+ const std::string& host) {
+ std::vector<url::Origin> host_origins;
+ // In the vast majority of cases, this vector will end up with exactly one
+ // origin. The origin will be https://host or http://host.
+ host_origins.reserve(1);
+
std::vector<std::string> origin_identifiers;
if (db_tracker->GetAllOriginIdentifiers(&origin_identifiers)) {
for (const auto& identifier : origin_identifiers) {
url::Origin origin = GetOriginFromIdentifier(identifier);
if (host == origin.host())
- origins_ptr->push_back(std::move(origin));
+ host_origins.push_back(std::move(origin));
}
}
+ return host_origins;
}
-void DidGetQuotaClientOrigins(QuotaClient::GetOriginsForTypeCallback callback,
- std::vector<url::Origin>* origins_ptr) {
- std::move(callback).Run(*origins_ptr);
-}
-
-void DidDeleteOriginData(base::SequencedTaskRunner* original_task_runner,
- QuotaClient::DeleteOriginDataCallback callback,
- int result) {
- if (result == net::ERR_IO_PENDING) {
- // The callback will be invoked via
- // DatabaseTracker::ScheduleDatabasesForDeletion.
- return;
- }
-
+void DidDeleteOriginData(
+ scoped_refptr<base::SequencedTaskRunner> original_task_runner,
+ QuotaClient::DeleteOriginDataCallback callback,
+ int result) {
blink::mojom::QuotaStatusCode status;
if (result == net::OK)
status = blink::mojom::QuotaStatusCode::kOk;
@@ -89,25 +90,32 @@ void DidDeleteOriginData(base::SequencedTaskRunner* original_task_runner,
DatabaseQuotaClient::DatabaseQuotaClient(
scoped_refptr<DatabaseTracker> db_tracker)
- : db_tracker_(std::move(db_tracker)) {}
+ : db_tracker_(std::move(db_tracker)) {
+ DCHECK(db_tracker_.get());
+
+ DETACH_FROM_SEQUENCE(sequence_checker_);
+}
DatabaseQuotaClient::~DatabaseQuotaClient() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!db_tracker_->task_runner()->RunsTasksInCurrentSequence()) {
db_tracker_->task_runner()->ReleaseSoon(FROM_HERE, std::move(db_tracker_));
}
}
-void DatabaseQuotaClient::OnQuotaManagerDestroyed() {}
+void DatabaseQuotaClient::OnQuotaManagerDestroyed() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
void DatabaseQuotaClient::GetOriginUsage(const url::Origin& origin,
StorageType type,
GetOriginUsageCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!callback.is_null());
- DCHECK(db_tracker_.get());
DCHECK_EQ(type, StorageType::kTemporary);
- base::PostTaskAndReplyWithResult(
- db_tracker_->task_runner(), FROM_HERE,
+ db_tracker_->task_runner()->PostTaskAndReplyWithResult(
+ FROM_HERE,
base::BindOnce(&GetOriginUsageOnDBThread, base::RetainedRef(db_tracker_),
origin),
std::move(callback));
@@ -116,65 +124,53 @@ void DatabaseQuotaClient::GetOriginUsage(const url::Origin& origin,
void DatabaseQuotaClient::GetOriginsForType(
StorageType type,
GetOriginsForTypeCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!callback.is_null());
- DCHECK(db_tracker_.get());
DCHECK_EQ(type, StorageType::kTemporary);
- auto* origins_ptr = new std::vector<url::Origin>();
- db_tracker_->task_runner()->PostTaskAndReply(
+ db_tracker_->task_runner()->PostTaskAndReplyWithResult(
FROM_HERE,
- base::BindOnce(&GetOriginsOnDBThread, base::RetainedRef(db_tracker_),
- base::Unretained(origins_ptr)),
- base::BindOnce(&DidGetQuotaClientOrigins, std::move(callback),
- base::Owned(origins_ptr)));
+ base::BindOnce(&GetOriginsOnDBThread, base::RetainedRef(db_tracker_)),
+ std::move(callback));
}
void DatabaseQuotaClient::GetOriginsForHost(
StorageType type,
const std::string& host,
GetOriginsForHostCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!callback.is_null());
- DCHECK(db_tracker_.get());
DCHECK_EQ(type, StorageType::kTemporary);
- auto* origins_ptr = new std::vector<url::Origin>();
- db_tracker_->task_runner()->PostTaskAndReply(
+ db_tracker_->task_runner()->PostTaskAndReplyWithResult(
FROM_HERE,
base::BindOnce(&GetOriginsForHostOnDBThread,
- base::RetainedRef(db_tracker_),
- base::Unretained(origins_ptr), host),
- base::BindOnce(&DidGetQuotaClientOrigins, std::move(callback),
- base::Owned(origins_ptr)));
+ base::RetainedRef(db_tracker_), host),
+ std::move(callback));
}
void DatabaseQuotaClient::DeleteOriginData(const url::Origin& origin,
StorageType type,
DeleteOriginDataCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!callback.is_null());
- DCHECK(db_tracker_.get());
DCHECK_EQ(type, StorageType::kTemporary);
- // DidDeleteOriginData() translates the net::Error response to a
- // blink::mojom::QuotaStatusCode if necessary, and no-ops as appropriate if
- // DatabaseTracker::ScheduleDatabasesForDeletion will also invoke the
- // callback.
- auto delete_callback = base::BindRepeating(
- &DidDeleteOriginData,
- base::RetainedRef(base::SequencedTaskRunnerHandle::Get()),
- base::AdaptCallbackForRepeating(std::move(callback)));
-
- base::PostTaskAndReplyWithResult(
- db_tracker_->task_runner(), FROM_HERE,
+ db_tracker_->task_runner()->PostTask(
+ FROM_HERE,
base::BindOnce(&DatabaseTracker::DeleteDataForOrigin, db_tracker_, origin,
- delete_callback),
- net::CompletionOnceCallback(delete_callback));
+ base::BindOnce(&DidDeleteOriginData,
+ base::SequencedTaskRunnerHandle::Get(),
+ std::move(callback))));
}
void DatabaseQuotaClient::PerformStorageCleanup(
blink::mojom::StorageType type,
PerformStorageCleanupCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!callback.is_null());
DCHECK_EQ(type, StorageType::kTemporary);
+
std::move(callback).Run();
}
diff --git a/chromium/storage/browser/database/database_quota_client.h b/chromium/storage/browser/database/database_quota_client.h
index de235c1593a..f098ee618c9 100644
--- a/chromium/storage/browser/database/database_quota_client.h
+++ b/chromium/storage/browser/database/database_quota_client.h
@@ -11,7 +11,9 @@
#include "base/component_export.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/sequence_checker.h"
#include "base/single_thread_task_runner.h"
+#include "base/thread_annotations.h"
#include "storage/browser/quota/quota_client.h"
#include "storage/browser/quota/quota_client_type.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
@@ -29,6 +31,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseQuotaClient
public:
explicit DatabaseQuotaClient(scoped_refptr<DatabaseTracker> tracker);
+ DatabaseQuotaClient(const DatabaseQuotaClient&) = delete;
+ DatabaseQuotaClient& operator=(const DatabaseQuotaClient&) = delete;
+
// QuotaClient method overrides
void OnQuotaManagerDestroyed() override;
void GetOriginUsage(const url::Origin& origin,
@@ -48,9 +53,13 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseQuotaClient
private:
~DatabaseQuotaClient() override;
- scoped_refptr<DatabaseTracker> db_tracker_; // only used on its sequence
+ SEQUENCE_CHECKER(sequence_checker_);
- DISALLOW_COPY_AND_ASSIGN(DatabaseQuotaClient);
+ // The scoped_refptr is only be dereferenced on the QuotaClient's sequence.
+ // However, the DatabaseTracker it points to must only be used on the database
+ // sequence.
+ scoped_refptr<DatabaseTracker> db_tracker_
+ GUARDED_BY_CONTEXT(sequence_checker_);
};
} // namespace storage
diff --git a/chromium/storage/browser/database/database_quota_client_unittest.cc b/chromium/storage/browser/database/database_quota_client_unittest.cc
index 2b3c50443f6..b0c161b9aeb 100644
--- a/chromium/storage/browser/database/database_quota_client_unittest.cc
+++ b/chromium/storage/browser/database/database_quota_client_unittest.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/containers/contains.h"
#include "base/files/file_path.h"
#include "base/location.h"
#include "base/memory/scoped_refptr.h"
@@ -69,17 +70,17 @@ class MockDatabaseTracker : public DatabaseTracker {
return true;
}
- int DeleteDataForOrigin(const url::Origin& origin,
- net::CompletionOnceCallback callback) override {
+ void DeleteDataForOrigin(const url::Origin& origin,
+ net::CompletionOnceCallback callback) override {
++delete_called_count_;
if (async_delete()) {
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&MockDatabaseTracker::AsyncDeleteDataForOrigin, this,
std::move(callback)));
- return net::ERR_IO_PENDING;
+ return;
}
- return net::OK;
+ std::move(callback).Run(net::OK);
}
void AsyncDeleteDataForOrigin(net::CompletionOnceCallback callback) {
@@ -107,8 +108,8 @@ class MockDatabaseTracker : public DatabaseTracker {
}
void AddMockDatabase(const base::string16& name, int size) {
- EXPECT_TRUE(database_info_.find(name) == database_info_.end());
- database_info_[name].size = size;
+ EXPECT_FALSE(base::Contains(database_sizes_, name));
+ database_sizes_[name] = size;
total_size_ += size;
}
};
diff --git a/chromium/storage/browser/database/database_tracker.cc b/chromium/storage/browser/database/database_tracker.cc
index fdf4b246607..cb40db94762 100644
--- a/chromium/storage/browser/database/database_tracker.cc
+++ b/chromium/storage/browser/database/database_tracker.cc
@@ -9,12 +9,14 @@
#include <algorithm>
#include "base/bind.h"
+#include "base/callback_helpers.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
+#include "base/time/time.h"
#include "net/base/net_errors.h"
#include "sql/database.h"
#include "sql/meta_table.h"
@@ -34,7 +36,7 @@ namespace storage {
const base::FilePath::CharType kDatabaseDirectoryName[] =
FILE_PATH_LITERAL("databases");
-const base::FilePath::CharType kOffTheRecordDatabaseDirectoryName[] =
+const base::FilePath::CharType kIncognitoDatabaseDirectoryName[] =
FILE_PATH_LITERAL("databases-off-the-record");
const base::FilePath::CharType kTrackerDatabaseFileName[] =
FILE_PATH_LITERAL("Databases.db");
@@ -55,44 +57,28 @@ OriginInfo::~OriginInfo() = default;
void OriginInfo::GetAllDatabaseNames(
std::vector<base::string16>* databases) const {
- for (const auto& pair : database_info_)
- databases->push_back(pair.first);
+ for (const auto& name_and_size : database_sizes_)
+ databases->push_back(name_and_size.first);
}
int64_t OriginInfo::GetDatabaseSize(const base::string16& database_name) const {
- auto it = database_info_.find(database_name);
- if (it != database_info_.end())
- return it->second.size;
+ auto it = database_sizes_.find(database_name);
+ if (it != database_sizes_.end())
+ return it->second;
return 0;
}
-base::string16 OriginInfo::GetDatabaseDescription(
- const base::string16& database_name) const {
- auto it = database_info_.find(database_name);
- if (it != database_info_.end())
- return it->second.description;
- return base::string16();
-}
-
-base::Time OriginInfo::GetDatabaseLastModified(
- const base::string16& database_name) const {
- auto it = database_info_.find(database_name);
- if (it != database_info_.end())
- return it->second.last_modified;
- return base::Time();
-}
-
OriginInfo::OriginInfo(const std::string& origin_identifier, int64_t total_size)
: origin_identifier_(origin_identifier), total_size_(total_size) {}
DatabaseTracker::DatabaseTracker(const base::FilePath& profile_path,
- bool is_off_the_record,
+ bool is_incognito,
SpecialStoragePolicy* special_storage_policy,
QuotaManagerProxy* quota_manager_proxy)
- : is_off_the_record_(is_off_the_record),
+ : is_incognito_(is_incognito),
profile_path_(profile_path),
- db_dir_(is_off_the_record_
- ? profile_path_.Append(kOffTheRecordDatabaseDirectoryName)
+ db_dir_(is_incognito_
+ ? profile_path_.Append(kIncognitoDatabaseDirectoryName)
: profile_path_.Append(kDatabaseDirectoryName)),
db_(new sql::Database()),
special_storage_policy_(special_storage_policy),
@@ -101,7 +87,8 @@ DatabaseTracker::DatabaseTracker(const base::FilePath& profile_path,
{base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) {
if (quota_manager_proxy) {
- quota_manager_proxy->RegisterClient(
+ // TODO(crbug.com/1163048): Use mojo and switch to RegisterClient().
+ quota_manager_proxy->RegisterLegacyClient(
base::MakeRefCounted<DatabaseQuotaClient>(this),
QuotaClientType::kDatabase, {blink::mojom::StorageType::kTemporary});
}
@@ -126,7 +113,7 @@ void DatabaseTracker::DatabaseOpened(const std::string& origin_identifier,
if (quota_manager_proxy_.get())
quota_manager_proxy_->NotifyStorageAccessed(
GetOriginFromIdentifier(origin_identifier),
- blink::mojom::StorageType::kTemporary);
+ blink::mojom::StorageType::kTemporary, base::Time::Now());
InsertOrUpdateDatabaseDetails(origin_identifier, database_name,
database_description, estimated_size);
@@ -162,7 +149,7 @@ void DatabaseTracker::DatabaseClosed(const std::string& origin_identifier,
if (quota_manager_proxy_.get())
quota_manager_proxy_->NotifyStorageAccessed(
GetOriginFromIdentifier(origin_identifier),
- blink::mojom::StorageType::kTemporary);
+ blink::mojom::StorageType::kTemporary, base::Time::Now());
UpdateOpenDatabaseSizeAndNotify(origin_identifier, database_name);
if (database_connections_.RemoveConnection(origin_identifier, database_name))
@@ -183,8 +170,7 @@ void DatabaseTracker::HandleSqliteError(
// Note: the client-side filters out all but these two errors as
// a small optimization, see WebDatabaseObserverImpl::HandleSqliteError.
if (error == SQLITE_CORRUPT || error == SQLITE_NOTADB) {
- DeleteDatabase(origin_identifier, database_name,
- net::CompletionOnceCallback());
+ DeleteDatabase(origin_identifier, database_name, base::DoNothing());
}
}
@@ -259,7 +245,7 @@ void DatabaseTracker::CloseTrackerDatabaseAndClearCaches() {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
ClearAllCachedOriginInfo();
- if (!is_off_the_record_) {
+ if (!is_incognito_) {
meta_table_.reset(nullptr);
databases_table_.reset(nullptr);
db_->Close();
@@ -273,16 +259,16 @@ base::FilePath DatabaseTracker::GetOriginDirectory(
base::string16 origin_directory;
- if (!is_off_the_record_) {
+ if (!is_incognito_) {
origin_directory = base::UTF8ToUTF16(origin_identifier);
} else {
- auto it = off_the_record_origin_directories_.find(origin_identifier);
- if (it != off_the_record_origin_directories_.end()) {
+ auto it = incognito_origin_directories_.find(origin_identifier);
+ if (it != incognito_origin_directories_.end()) {
origin_directory = it->second;
} else {
- origin_directory = base::NumberToString16(
- off_the_record_origin_directories_generator_++);
- off_the_record_origin_directories_[origin_identifier] = origin_directory;
+ origin_directory =
+ base::NumberToString16(incognito_origin_directories_generator_++);
+ incognito_origin_directories_[origin_identifier] = origin_directory;
}
}
@@ -373,7 +359,8 @@ bool DatabaseTracker::DeleteClosedDatabase(
if (quota_manager_proxy_.get() && db_file_size)
quota_manager_proxy_->NotifyStorageModified(
QuotaClientType::kDatabase, GetOriginFromIdentifier(origin_identifier),
- blink::mojom::StorageType::kTemporary, -db_file_size);
+ blink::mojom::StorageType::kTemporary, -db_file_size,
+ base::Time::Now());
// Clean up the main database and invalidate the cached record.
databases_table_->DeleteDatabaseDetails(origin_identifier, database_name);
@@ -427,18 +414,18 @@ bool DatabaseTracker::DeleteOrigin(const std::string& origin_identifier,
base::DeletePathRecursively(origin_dir);
base::DeletePathRecursively(new_origin_dir); // Might fail on windows.
- if (is_off_the_record_) {
- off_the_record_origin_directories_.erase(origin_identifier);
+ if (is_incognito_) {
+ incognito_origin_directories_.erase(origin_identifier);
// TODO(jsbell): Consider alternate data structures to avoid this
// linear scan.
- for (auto it = off_the_record_file_handles_.begin();
- it != off_the_record_file_handles_.end();) {
+ for (auto it = incognito_file_handles_.begin();
+ it != incognito_file_handles_.end();) {
std::string id;
if (DatabaseUtil::CrackVfsFileName(it->first, &id, nullptr, nullptr) &&
id == origin_identifier) {
delete it->second;
- it = off_the_record_file_handles_.erase(it);
+ it = incognito_file_handles_.erase(it);
} else {
++it;
}
@@ -450,7 +437,8 @@ bool DatabaseTracker::DeleteOrigin(const std::string& origin_identifier,
if (quota_manager_proxy_.get() && deleted_size) {
quota_manager_proxy_->NotifyStorageModified(
QuotaClientType::kDatabase, GetOriginFromIdentifier(origin_identifier),
- blink::mojom::StorageType::kTemporary, -deleted_size);
+ blink::mojom::StorageType::kTemporary, -deleted_size,
+ base::Time::Now());
}
return true;
@@ -507,12 +495,11 @@ bool DatabaseTracker::LazyInit() {
databases_table_.reset(new DatabasesTable(db_.get()));
meta_table_.reset(new sql::MetaTable());
- is_initialized_ =
- base::CreateDirectory(db_dir_) &&
- (db_->is_open() ||
- (is_off_the_record_ ? db_->OpenInMemory()
- : db_->Open(kTrackerDatabaseFullPath))) &&
- UpgradeToCurrentVersion();
+ is_initialized_ = base::CreateDirectory(db_dir_) &&
+ (db_->is_open() ||
+ (is_incognito_ ? db_->OpenInMemory()
+ : db_->Open(kTrackerDatabaseFullPath))) &&
+ UpgradeToCurrentVersion();
if (!is_initialized_) {
databases_table_.reset(nullptr);
meta_table_.reset(nullptr);
@@ -595,7 +582,6 @@ DatabaseTracker::CachedOriginInfo* DatabaseTracker::MaybeGetCachedOriginInfo(
db_file_size = GetDBFileSize(origin_identifier, db.database_name);
}
origin_info.SetDatabaseSize(db.database_name, db_file_size);
- origin_info.SetDatabaseDescription(db.database_name, db.description);
base::FilePath path =
GetFullDBFilePath(origin_identifier, db.database_name);
@@ -603,8 +589,7 @@ DatabaseTracker::CachedOriginInfo* DatabaseTracker::MaybeGetCachedOriginInfo(
// TODO(jsbell): Avoid duplicate base::GetFileInfo calls between this and
// the GetDBFileSize() call above.
if (base::GetFileInfo(path, &file_info)) {
- origin_info.SetDatabaseLastModified(db.database_name,
- file_info.last_modified);
+ origin_info.UpdateLastModified(file_info.last_modified);
}
}
}
@@ -634,7 +619,6 @@ int64_t DatabaseTracker::SeedOpenDatabaseInfo(
CachedOriginInfo* info = MaybeGetCachedOriginInfo(origin_id, false);
if (info) {
info->SetDatabaseSize(name, size);
- info->SetDatabaseDescription(name, description);
}
return size;
}
@@ -648,8 +632,6 @@ int64_t DatabaseTracker::UpdateOpenDatabaseInfoAndNotify(
int64_t new_size = GetDBFileSize(origin_id, name);
int64_t old_size = database_connections_.GetOpenDatabaseSize(origin_id, name);
CachedOriginInfo* info = MaybeGetCachedOriginInfo(origin_id, false);
- if (info && opt_description)
- info->SetDatabaseDescription(name, *opt_description);
if (old_size != new_size) {
database_connections_.SetOpenDatabaseSize(origin_id, name, new_size);
if (info)
@@ -657,7 +639,8 @@ int64_t DatabaseTracker::UpdateOpenDatabaseInfoAndNotify(
if (quota_manager_proxy_.get())
quota_manager_proxy_->NotifyStorageModified(
QuotaClientType::kDatabase, GetOriginFromIdentifier(origin_id),
- blink::mojom::StorageType::kTemporary, new_size - old_size);
+ blink::mojom::StorageType::kTemporary, new_size - old_size,
+ base::Time::Now());
for (auto& observer : observers_)
observer.OnDatabaseSizeChanged(origin_id, name, new_size);
}
@@ -689,39 +672,46 @@ void DatabaseTracker::ScheduleDatabasesForDeletion(
}
}
-int DatabaseTracker::DeleteDatabase(const std::string& origin_identifier,
- const base::string16& database_name,
- net::CompletionOnceCallback callback) {
+void DatabaseTracker::DeleteDatabase(const std::string& origin_identifier,
+ const base::string16& database_name,
+ net::CompletionOnceCallback callback) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
- if (!LazyInit())
- return net::ERR_FAILED;
+ DCHECK(!callback.is_null());
+ if (!LazyInit()) {
+ std::move(callback).Run(net::ERR_FAILED);
+ return;
+ }
if (database_connections_.IsDatabaseOpened(origin_identifier,
database_name)) {
- if (!callback.is_null()) {
- DatabaseSet set;
- set[origin_identifier].insert(database_name);
- deletion_callbacks_.emplace_back(std::move(callback), set);
- }
+ DatabaseSet set;
+ set[origin_identifier].insert(database_name);
+ deletion_callbacks_.emplace_back(std::move(callback), std::move(set));
ScheduleDatabaseForDeletion(origin_identifier, database_name);
- return net::ERR_IO_PENDING;
+ return;
}
+
DeleteClosedDatabase(origin_identifier, database_name);
- return net::OK;
+ std::move(callback).Run(net::OK);
}
-int DatabaseTracker::DeleteDataModifiedSince(
+void DatabaseTracker::DeleteDataModifiedSince(
const base::Time& cutoff,
net::CompletionOnceCallback callback) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
- if (!LazyInit())
- return net::ERR_FAILED;
-
- DatabaseSet to_be_deleted;
+ DCHECK(!callback.is_null());
+ if (!LazyInit()) {
+ std::move(callback).Run(net::ERR_FAILED);
+ return;
+ }
std::vector<std::string> origins_identifiers;
- if (!databases_table_->GetAllOriginIdentifiers(&origins_identifiers))
- return net::ERR_FAILED;
+ if (!databases_table_->GetAllOriginIdentifiers(&origins_identifiers)) {
+ std::move(callback).Run(net::ERR_FAILED);
+ return;
+ }
+
+ DatabaseSet to_be_deleted;
int rv = net::OK;
for (const auto& origin : origins_identifiers) {
if (special_storage_policy_.get() &&
@@ -732,8 +722,9 @@ int DatabaseTracker::DeleteDataModifiedSince(
std::vector<DatabaseDetails> details;
if (!databases_table_->GetAllDatabaseDetailsForOriginIdentifier(origin,
- &details))
+ &details)) {
rv = net::ERR_FAILED;
+ }
for (const DatabaseDetails& db : details) {
base::FilePath db_file = GetFullDBFilePath(origin, db.database_name);
base::File::Info file_info;
@@ -742,110 +733,123 @@ int DatabaseTracker::DeleteDataModifiedSince(
continue;
// Check if the database is opened by any renderer.
- if (database_connections_.IsDatabaseOpened(origin, db.database_name))
+ if (database_connections_.IsDatabaseOpened(origin, db.database_name)) {
to_be_deleted[origin].insert(db.database_name);
- else
+ } else {
DeleteClosedDatabase(origin, db.database_name);
+ }
}
}
- if (rv != net::OK)
- return rv;
+ if (rv != net::OK) {
+ DCHECK_EQ(rv, net::ERR_FAILED);
+ std::move(callback).Run(rv);
+ return;
+ }
if (!to_be_deleted.empty()) {
ScheduleDatabasesForDeletion(to_be_deleted, std::move(callback));
- return net::ERR_IO_PENDING;
+ return;
}
- return net::OK;
+
+ std::move(callback).Run(net::OK);
}
-int DatabaseTracker::DeleteDataForOrigin(const url::Origin& origin,
- net::CompletionOnceCallback callback) {
+void DatabaseTracker::DeleteDataForOrigin(
+ const url::Origin& origin,
+ net::CompletionOnceCallback callback) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
- if (!LazyInit())
- return net::ERR_FAILED;
-
- DatabaseSet to_be_deleted;
+ DCHECK(!callback.is_null());
+ if (!LazyInit()) {
+ std::move(callback).Run(net::ERR_FAILED);
+ return;
+ }
const std::string identifier = GetIdentifierFromOrigin(origin);
std::vector<DatabaseDetails> details;
if (!databases_table_->GetAllDatabaseDetailsForOriginIdentifier(identifier,
- &details))
- return net::ERR_FAILED;
- for (const auto& db : details) {
+ &details)) {
+ std::move(callback).Run(net::ERR_FAILED);
+ return;
+ }
+
+ DatabaseSet to_be_deleted;
+ for (const DatabaseDetails& db : details) {
// Check if the database is opened by any renderer.
- if (database_connections_.IsDatabaseOpened(identifier, db.database_name))
+ if (database_connections_.IsDatabaseOpened(identifier, db.database_name)) {
to_be_deleted[identifier].insert(db.database_name);
- else
+ } else {
DeleteClosedDatabase(identifier, db.database_name);
+ }
}
if (!to_be_deleted.empty()) {
ScheduleDatabasesForDeletion(to_be_deleted, std::move(callback));
- return net::ERR_IO_PENDING;
+ return;
}
- return net::OK;
+
+ std::move(callback).Run(net::OK);
}
-const base::File* DatabaseTracker::GetOffTheRecordFile(
+const base::File* DatabaseTracker::GetIncognitoFile(
const base::string16& vfs_file_name) const {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
- DCHECK(is_off_the_record_);
- auto it = off_the_record_file_handles_.find(vfs_file_name);
- if (it != off_the_record_file_handles_.end())
+ DCHECK(is_incognito_);
+ auto it = incognito_file_handles_.find(vfs_file_name);
+ if (it != incognito_file_handles_.end())
return it->second;
return nullptr;
}
-const base::File* DatabaseTracker::SaveOffTheRecordFile(
+const base::File* DatabaseTracker::SaveIncognitoFile(
const base::string16& vfs_file_name,
base::File file) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
- DCHECK(is_off_the_record_);
+ DCHECK(is_incognito_);
if (!file.IsValid())
return nullptr;
base::File* to_insert = new base::File(std::move(file));
- auto rv = off_the_record_file_handles_.insert(
- std::make_pair(vfs_file_name, to_insert));
+ auto rv =
+ incognito_file_handles_.insert(std::make_pair(vfs_file_name, to_insert));
DCHECK(rv.second);
return rv.first->second;
}
-void DatabaseTracker::CloseOffTheRecordFileHandle(
+void DatabaseTracker::CloseIncognitoFileHandle(
const base::string16& vfs_file_name) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
- DCHECK(is_off_the_record_);
- DCHECK(off_the_record_file_handles_.find(vfs_file_name) !=
- off_the_record_file_handles_.end());
+ DCHECK(is_incognito_);
+ DCHECK(incognito_file_handles_.find(vfs_file_name) !=
+ incognito_file_handles_.end());
- auto it = off_the_record_file_handles_.find(vfs_file_name);
- if (it != off_the_record_file_handles_.end()) {
+ auto it = incognito_file_handles_.find(vfs_file_name);
+ if (it != incognito_file_handles_.end()) {
delete it->second;
- off_the_record_file_handles_.erase(it);
+ incognito_file_handles_.erase(it);
}
}
-bool DatabaseTracker::HasSavedOffTheRecordFileHandle(
+bool DatabaseTracker::HasSavedIncognitoFileHandle(
const base::string16& vfs_file_name) const {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
- return (off_the_record_file_handles_.find(vfs_file_name) !=
- off_the_record_file_handles_.end());
+ return (incognito_file_handles_.find(vfs_file_name) !=
+ incognito_file_handles_.end());
}
-void DatabaseTracker::DeleteOffTheRecordDBDirectory() {
+void DatabaseTracker::DeleteIncognitoDBDirectory() {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
is_initialized_ = false;
- for (auto& pair : off_the_record_file_handles_)
+ for (auto& pair : incognito_file_handles_)
delete pair.second;
- base::FilePath off_the_record_db_dir =
- profile_path_.Append(kOffTheRecordDatabaseDirectoryName);
- if (base::DirectoryExists(off_the_record_db_dir))
- base::DeletePathRecursively(off_the_record_db_dir);
+ base::FilePath incognito_db_dir =
+ profile_path_.Append(kIncognitoDatabaseDirectoryName);
+ if (base::DirectoryExists(incognito_db_dir))
+ base::DeletePathRecursively(incognito_db_dir);
}
void DatabaseTracker::ClearSessionOnlyOrigins() {
@@ -893,8 +897,8 @@ void DatabaseTracker::Shutdown() {
return;
}
shutting_down_ = true;
- if (is_off_the_record_)
- DeleteOffTheRecordDBDirectory();
+ if (is_incognito_)
+ DeleteIncognitoDBDirectory();
else if (!force_keep_session_state_)
ClearSessionOnlyOrigins();
CloseTrackerDatabaseAndClearCaches();
diff --git a/chromium/storage/browser/database/database_tracker.h b/chromium/storage/browser/database/database_tracker.h
index 1898fac9d34..e1e34ba48a3 100644
--- a/chromium/storage/browser/database/database_tracker.h
+++ b/chromium/storage/browser/database/database_tracker.h
@@ -57,22 +57,14 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) OriginInfo {
base::Time LastModified() const { return last_modified_; }
void GetAllDatabaseNames(std::vector<base::string16>* databases) const;
int64_t GetDatabaseSize(const base::string16& database_name) const;
- base::string16 GetDatabaseDescription(
- const base::string16& database_name) const;
- base::Time GetDatabaseLastModified(const base::string16& database_name) const;
protected:
- struct DBInfo {
- base::string16 description;
- int64_t size;
- base::Time last_modified;
- };
OriginInfo(const std::string& origin_identifier, int64_t total_size);
std::string origin_identifier_;
int64_t total_size_;
base::Time last_modified_;
- std::map<base::string16, DBInfo> database_info_;
+ std::map<base::string16, int64_t> database_sizes_;
};
// This class manages the main database and keeps track of open databases.
@@ -98,7 +90,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseTracker
};
DatabaseTracker(const base::FilePath& profile_path,
- bool is_off_the_record,
+ bool is_incognito,
SpecialStoragePolicy* special_storage_policy,
QuotaManagerProxy* quota_manager_proxy);
@@ -141,41 +133,46 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseTracker
bool IsDatabaseScheduledForDeletion(const std::string& origin_identifier,
const base::string16& database_name);
- // Deletes a single database. Returns net::OK on success, net::FAILED on
- // failure, or net::ERR_IO_PENDING and |callback| is invoked upon completion,
- // if non-null.
- int DeleteDatabase(const std::string& origin_identifier,
- const base::string16& database_name,
- net::CompletionOnceCallback callback);
-
- // Delete any databases that have been touched since the cutoff date that's
- // supplied, omitting any that match IDs within |protected_origins|.
- // Returns net::OK on success, net::FAILED if not all databases could be
- // deleted, and net::ERR_IO_PENDING and |callback| is invoked upon completion,
- // if non-null. Protected origins, according the the SpecialStoragePolicy,
- // are not deleted by this method.
- int DeleteDataModifiedSince(const base::Time& cutoff,
- net::CompletionOnceCallback callback);
-
- // Delete all databases that belong to the given origin. Returns net::OK on
- // success, net::FAILED if not all databases could be deleted, and
- // net::ERR_IO_PENDING and |callback| is invoked upon completion, if non-null.
- // virtual for unit testing only
- virtual int DeleteDataForOrigin(const url::Origin& origin,
- net::CompletionOnceCallback callback);
-
- bool IsOffTheRecordProfile() const { return is_off_the_record_; }
-
- const base::File* GetOffTheRecordFile(
- const base::string16& vfs_file_path) const;
- const base::File* SaveOffTheRecordFile(const base::string16& vfs_file_path,
- base::File file);
- void CloseOffTheRecordFileHandle(const base::string16& vfs_file_path);
- bool HasSavedOffTheRecordFileHandle(
- const base::string16& vfs_file_path) const;
+ // Deletes a single database.
+ //
+ // `callback` must be non-null, and is invoked upon completion with a
+ // net::Error, which will most likely be net::OK or net::FAILED. `callback`
+ // may be called before this method returns.
+ void DeleteDatabase(const std::string& origin_identifier,
+ const base::string16& database_name,
+ net::CompletionOnceCallback callback);
+
+ // Deletes databases touched since `cutoff`.
+ //
+ // Does not delete databases belonging to origins designated as protected by
+ // the SpecialStoragePolicy passed to the DatabaseTracker constructor.
+ //
+ // `callback` must must be non-null, and is invoked upon completion with a
+ // net::Error. The status will be net::OK on success, or net::FAILED if not
+ // all databases could be deleted. `callback` may be called before this method
+ // returns.
+ void DeleteDataModifiedSince(const base::Time& cutoff,
+ net::CompletionOnceCallback callback);
+
+ // Deletes all databases that belong to the given origin.
+ //
+ // `callback` must must be non-null, and is invoked upon completion with a
+ // net::Error. The status will be net::OK on success, or net::FAILED if not
+ // all databases could be deleted. `callback` may be called before this method
+ // returns.
+ virtual void DeleteDataForOrigin(const url::Origin& origin,
+ net::CompletionOnceCallback callback);
+
+ bool IsIncognitoProfile() const { return is_incognito_; }
+
+ const base::File* GetIncognitoFile(const base::string16& vfs_file_path) const;
+ const base::File* SaveIncognitoFile(const base::string16& vfs_file_path,
+ base::File file);
+ void CloseIncognitoFileHandle(const base::string16& vfs_file_path);
+ bool HasSavedIncognitoFileHandle(const base::string16& vfs_file_path) const;
// Shutdown the database tracker, deleting database files if the tracker is
- // used for an OffTheRecord profile.
+ // used for an Incognito profile.
void Shutdown();
// Disables the exit-time deletion of session-only data.
void SetForceKeepSessionState();
@@ -197,20 +194,18 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseTracker
}
void SetDatabaseSize(const base::string16& database_name,
int64_t new_size) {
- int64_t old_size = 0;
- if (database_info_.find(database_name) != database_info_.end())
- old_size = database_info_[database_name].size;
- database_info_[database_name].size = new_size;
+ // If the name does not exist in the map, operator[] creates a new entry
+ // with a default-constructed value. The default-constructed value for
+ // int64_t is zero (0), which is exactly what we want `old_size` to be set
+ // to in this case.
+ int64_t& database_size = database_sizes_[database_name];
+ int64_t old_size = database_size;
+
+ database_size = new_size;
if (new_size != old_size)
total_size_ += new_size - old_size;
}
- void SetDatabaseDescription(const base::string16& database_name,
- const base::string16& description) {
- database_info_[database_name].description = description;
- }
- void SetDatabaseLastModified(const base::string16& database_name,
- const base::Time& last_modified) {
- database_info_[database_name].last_modified = last_modified;
+ void UpdateLastModified(base::Time last_modified) {
if (last_modified > last_modified_)
last_modified_ = last_modified;
}
@@ -219,9 +214,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseTracker
// virtual for unit-testing only.
virtual ~DatabaseTracker();
- // Deletes the directory that stores all DBs in OffTheRecord mode, if it
+ // Deletes the directory that stores all DBs in Incognito mode, if it
// exists.
- void DeleteOffTheRecordDBDirectory();
+ void DeleteIncognitoDBDirectory();
// Deletes session-only databases. Blocks databases from being created/opened.
void ClearSessionOnlyOrigins();
@@ -279,7 +274,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseTracker
base::FilePath GetOriginDirectory(const std::string& origin_identifier);
bool is_initialized_ = false;
- const bool is_off_the_record_;
+ const bool is_incognito_;
bool force_keep_session_state_ = false;
bool shutting_down_ = false;
const base::FilePath profile_path_;
@@ -312,20 +307,20 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseTracker
// The database tracker thread we're supposed to run file IO on.
scoped_refptr<base::SequencedTaskRunner> task_runner_;
- // When in OffTheRecord mode, store a DELETE_ON_CLOSE handle to each
- // main DB and journal file that was accessed. When the OffTheRecord profile
+ // When in Incognito mode, store a DELETE_ON_CLOSE handle to each
+ // main DB and journal file that was accessed. When the Incognito profile
// goes away (or when the browser crashes), all these handles will be
// closed, and the files will be deleted.
- std::map<base::string16, base::File*> off_the_record_file_handles_;
+ std::map<base::string16, base::File*> incognito_file_handles_;
- // In a non-OffTheRecord profile, all DBs in an origin are stored in a
- // directory named after the origin. In an OffTheRecord profile though, we do
+ // In a non-Incognito profile, all DBs in an origin are stored in a
+ // directory named after the origin. In an Incognito profile though, we do
// not want the directory structure to reveal the origins visited by the user
// (in case the browser process crashes and those directories are not
// deleted). So we use this map to assign directory names that do not reveal
// this information.
- std::map<std::string, base::string16> off_the_record_origin_directories_;
- int off_the_record_origin_directories_generator_ = 0;
+ std::map<std::string, base::string16> incognito_origin_directories_;
+ int incognito_origin_directories_generator_ = 0;
FRIEND_TEST_ALL_PREFIXES(DatabaseTracker, TestHelper);
};
diff --git a/chromium/storage/browser/database/database_tracker_unittest.cc b/chromium/storage/browser/database/database_tracker_unittest.cc
index 04c31e2b0d1..03a534a78c2 100644
--- a/chromium/storage/browser/database/database_tracker_unittest.cc
+++ b/chromium/storage/browser/database/database_tracker_unittest.cc
@@ -13,6 +13,8 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/notreached.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
@@ -99,9 +101,10 @@ void CheckNotificationReceived(TestObserver* observer,
class TestQuotaManagerProxy : public QuotaManagerProxy {
public:
TestQuotaManagerProxy()
- : QuotaManagerProxy(nullptr, nullptr), registered_client_(nullptr) {}
+ : QuotaManagerProxy(nullptr, base::SequencedTaskRunnerHandle::Get()),
+ registered_client_(nullptr) {}
- void RegisterClient(
+ void RegisterLegacyClient(
scoped_refptr<QuotaClient> client,
QuotaClientType client_type,
const std::vector<blink::mojom::StorageType>& storage_types) override {
@@ -109,20 +112,34 @@ class TestQuotaManagerProxy : public QuotaManagerProxy {
registered_client_ = client;
}
+ void RegisterClient(
+ mojo::PendingRemote<mojom::QuotaClient> client,
+ QuotaClientType client_type,
+ const std::vector<blink::mojom::StorageType>& storage_types) override {
+ NOTREACHED();
+ }
+
void NotifyStorageAccessed(const url::Origin& origin,
- blink::mojom::StorageType type) override {
+ blink::mojom::StorageType type,
+ base::Time access_time) override {
EXPECT_EQ(blink::mojom::StorageType::kTemporary, type);
accesses_[origin] += 1;
}
- void NotifyStorageModified(QuotaClientType client_id,
- const url::Origin& origin,
- blink::mojom::StorageType type,
- int64_t delta) override {
+ void NotifyStorageModified(
+ QuotaClientType client_id,
+ const url::Origin& origin,
+ blink::mojom::StorageType type,
+ int64_t delta,
+ base::Time modification_time,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ base::OnceClosure callback) override {
EXPECT_EQ(QuotaClientType::kDatabase, client_id);
EXPECT_EQ(blink::mojom::StorageType::kTemporary, type);
modifications_[origin].first += 1;
modifications_[origin].second += delta;
+ if (callback)
+ callback_task_runner->PostTask(FROM_HERE, std::move(callback));
}
// Not needed for our tests.
@@ -132,10 +149,11 @@ class TestQuotaManagerProxy : public QuotaManagerProxy {
const url::Origin& origin,
blink::mojom::StorageType type,
bool enabled) override {}
- void GetUsageAndQuota(base::SequencedTaskRunner* original_task_runner,
- const url::Origin& origin,
- blink::mojom::StorageType type,
- UsageAndQuotaCallback callback) override {}
+ void GetUsageAndQuota(
+ const url::Origin& origin,
+ blink::mojom::StorageType type,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ UsageAndQuotaCallback callback) override {}
void SimulateQuotaManagerDestroyed() {
if (registered_client_) {
@@ -240,17 +258,15 @@ class DatabaseTracker_TestHelper_Test {
// Delete db1. Should also delete origin1.
TestObserver observer;
tracker->AddObserver(&observer);
- net::TestCompletionCallback callback1;
- int result =
- tracker->DeleteDatabase(kOrigin1, kDB1, callback1.callback());
- EXPECT_EQ(net::ERR_IO_PENDING, result);
- ASSERT_FALSE(callback1.have_result());
+ net::TestCompletionCallback delete_database_callback;
+ tracker->DeleteDatabase(kOrigin1, kDB1,
+ delete_database_callback.callback());
+ EXPECT_FALSE(delete_database_callback.have_result());
EXPECT_TRUE(observer.DidReceiveNewNotification());
EXPECT_EQ(kOrigin1, observer.GetNotificationOriginIdentifier());
EXPECT_EQ(kDB1, observer.GetNotificationDatabaseName());
tracker->DatabaseClosed(kOrigin1, kDB1);
- result = callback1.GetResult(result);
- EXPECT_EQ(net::OK, result);
+ EXPECT_EQ(net::OK, delete_database_callback.WaitForResult());
EXPECT_FALSE(base::PathExists(tracker->GetOriginDirectory(kOrigin1)));
// Recreate db1.
@@ -278,16 +294,15 @@ class DatabaseTracker_TestHelper_Test {
base::Time yesterday = base::Time::Now();
yesterday -= base::TimeDelta::FromDays(1);
- net::TestCompletionCallback callback2;
- result =
- tracker->DeleteDataModifiedSince(yesterday, callback2.callback());
- EXPECT_EQ(net::ERR_IO_PENDING, result);
- ASSERT_FALSE(callback2.have_result());
+ net::TestCompletionCallback delete_data_modified_since_callback;
+ tracker->DeleteDataModifiedSince(
+ yesterday, delete_data_modified_since_callback.callback());
+ EXPECT_FALSE(delete_data_modified_since_callback.have_result());
EXPECT_TRUE(observer.DidReceiveNewNotification());
tracker->DatabaseClosed(kOrigin1, kDB1);
tracker->DatabaseClosed(kOrigin2, kDB2);
- result = callback2.GetResult(result);
- EXPECT_EQ(net::OK, result);
+ EXPECT_EQ(net::OK,
+ delete_data_modified_since_callback.WaitForResult());
EXPECT_FALSE(base::PathExists(tracker->GetOriginDirectory(kOrigin1)));
EXPECT_TRUE(
base::PathExists(tracker->GetFullDBFilePath(kOrigin2, kDB2)));
@@ -506,9 +521,11 @@ class DatabaseTracker_TestHelper_Test {
tracker->DatabaseClosed(kOriginId, kName);
EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin));
- EXPECT_EQ(net::OK,
- tracker->DeleteDatabase(kOriginId, kName,
- net::CompletionOnceCallback()));
+ net::TestCompletionCallback delete_database_callback;
+ tracker->DeleteDatabase(kOriginId, kName,
+ delete_database_callback.callback());
+ EXPECT_TRUE(delete_database_callback.have_result());
+ EXPECT_EQ(net::OK, delete_database_callback.WaitForResult());
EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, -100));
test_quota_proxy->reset();
@@ -534,9 +551,10 @@ class DatabaseTracker_TestHelper_Test {
EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, 100));
test_quota_proxy->reset();
- EXPECT_EQ(net::ERR_IO_PENDING,
- tracker->DeleteDatabase(kOriginId, kName,
- net::CompletionOnceCallback()));
+ net::TestCompletionCallback delete_database_callback2;
+ tracker->DeleteDatabase(kOriginId, kName,
+ delete_database_callback2.callback());
+ EXPECT_FALSE(delete_database_callback2.have_result());
EXPECT_FALSE(
test_quota_proxy->WasModificationNotified(kOrigin, -100));
EXPECT_TRUE(base::PathExists(tracker->GetOriginDirectory(kOriginId)));
@@ -546,6 +564,8 @@ class DatabaseTracker_TestHelper_Test {
EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, -100));
EXPECT_FALSE(
base::PathExists(tracker->GetOriginDirectory(kOriginId)));
+ EXPECT_TRUE(delete_database_callback2.have_result());
+ EXPECT_EQ(net::OK, delete_database_callback2.WaitForResult());
test_quota_proxy->reset();
// Create a database and up the file size without telling
@@ -799,7 +819,6 @@ class DatabaseTracker_TestHelper_Test {
tracker->DatabaseModified(kOriginId, kEmptyName);
EXPECT_TRUE(tracker->GetAllOriginsInfo(&infos));
EXPECT_EQ(1u, infos.size());
- EXPECT_EQ(kDescription, infos[0].GetDatabaseDescription(kEmptyName));
EXPECT_FALSE(
tracker->GetFullDBFilePath(kOriginId, kEmptyName).empty());
tracker->DatabaseOpened(kOriginId, kEmptyName, kChangedDescription, 0,
@@ -807,15 +826,15 @@ class DatabaseTracker_TestHelper_Test {
infos.clear();
EXPECT_TRUE(tracker->GetAllOriginsInfo(&infos));
EXPECT_EQ(1u, infos.size());
- EXPECT_EQ(kChangedDescription,
- infos[0].GetDatabaseDescription(kEmptyName));
tracker->DatabaseClosed(kOriginId, kEmptyName);
tracker->DatabaseClosed(kOriginId, kEmptyName);
// Deleting it should return to the initial state.
- EXPECT_EQ(net::OK,
- tracker->DeleteDatabase(kOriginId, kEmptyName,
- net::CompletionOnceCallback()));
+ net::TestCompletionCallback delete_database_callback;
+ tracker->DeleteDatabase(kOriginId, kEmptyName,
+ delete_database_callback.callback());
+ EXPECT_TRUE(delete_database_callback.have_result());
+ EXPECT_EQ(net::OK, delete_database_callback.WaitForResult());
infos.clear();
EXPECT_TRUE(tracker->GetAllOriginsInfo(&infos));
EXPECT_TRUE(infos.empty());
diff --git a/chromium/storage/browser/file_system/README.md b/chromium/storage/browser/file_system/README.md
index 1e498f0f2e1..53460ee93ef 100644
--- a/chromium/storage/browser/file_system/README.md
+++ b/chromium/storage/browser/file_system/README.md
@@ -50,7 +50,7 @@ specification](https://dev.w3.org/2009/dap/file-system/file-dir-sys.html).
There are two flavors of this, "temporary" and "persistent".
This same file system (or at least the "temporary" version) is also exposed via
-the new Native File System API.
+the new File System Access API.
### Isolated File Systems
@@ -58,7 +58,7 @@ Isolated file systems generally are used to expose files from other file system
types to the web for the [Files and Directory Entries API](https://wicg.github.io/entries-api/),
either via Drag&Drop or `<input type=file>`. They are also used for the (deprecated)
[Chrome Apps chrome.fileSystem API](https://developer.chrome.com/apps/fileSystem),
-and the new [Native File System API](http://wicg.github.io/native-file-system/).
+and the new [File System Access API](http://wicg.github.io/file-system-access/).
# Interesting Classes
@@ -143,6 +143,6 @@ Today reference counts are increased/decreased implicitly by granting access to
certain file systems to certain renderer processes (i.e.
`content::ChildProcessSecurityPolicyImpl` calls `AddReference` when
permission is granted, and call `RemoveReference` when the process is destroyed
-on all the file systems that renderer has access to). The Native File System API
+on all the file systems that renderer has access to). The File System Access API
will introduce its own way of adding and removing references to these file
systems.
diff --git a/chromium/storage/browser/file_system/async_file_util.h b/chromium/storage/browser/file_system/async_file_util.h
index 8528fadf41f..a5ef84d7783 100644
--- a/chromium/storage/browser/file_system/async_file_util.h
+++ b/chromium/storage/browser/file_system/async_file_util.h
@@ -79,9 +79,9 @@ class AsyncFileUtil {
using CopyOrMoveOption = FileSystemOperation::CopyOrMoveOption;
using GetMetadataField = FileSystemOperation::GetMetadataField;
- // Creates an AsyncFileUtil instance which performs file operations on
- // local native file system. The created instance assumes
- // FileSystemURL::path() has the target platform path.
+ // Creates an AsyncFileUtil instance which performs file operations on local
+ // file system. The created instance assumes FileSystemURL::path() has the
+ // target platform path.
COMPONENT_EXPORT(STORAGE_BROWSER)
static AsyncFileUtil* CreateForLocalFileSystem();
diff --git a/chromium/storage/browser/file_system/async_file_util_adapter.cc b/chromium/storage/browser/file_system/async_file_util_adapter.cc
index 8dfc2cf5c39..a28d6f5760f 100644
--- a/chromium/storage/browser/file_system/async_file_util_adapter.cc
+++ b/chromium/storage/browser/file_system/async_file_util_adapter.cc
@@ -162,8 +162,9 @@ void RunCreateOrOpenCallback(FileSystemOperationContext* context,
} // namespace
-AsyncFileUtilAdapter::AsyncFileUtilAdapter(FileSystemFileUtil* sync_file_util)
- : sync_file_util_(sync_file_util) {
+AsyncFileUtilAdapter::AsyncFileUtilAdapter(
+ std::unique_ptr<FileSystemFileUtil> sync_file_util)
+ : sync_file_util_(std::move(sync_file_util)) {
DCHECK(sync_file_util_.get());
}
diff --git a/chromium/storage/browser/file_system/async_file_util_adapter.h b/chromium/storage/browser/file_system/async_file_util_adapter.h
index ad4abec2b1c..441533a04e4 100644
--- a/chromium/storage/browser/file_system/async_file_util_adapter.h
+++ b/chromium/storage/browser/file_system/async_file_util_adapter.h
@@ -31,11 +31,8 @@ class FileSystemFileUtil;
class COMPONENT_EXPORT(STORAGE_BROWSER) AsyncFileUtilAdapter
: public AsyncFileUtil {
public:
- // Creates a new AsyncFileUtil for |sync_file_util|. This takes the
- // ownership of |sync_file_util|. (This doesn't take std::unique_ptr<> just
- // to save extra base::WrapUnique; in all use cases a new fresh FileUtil is
- // created only for this adapter.)
- explicit AsyncFileUtilAdapter(FileSystemFileUtil* sync_file_util);
+ explicit AsyncFileUtilAdapter(
+ std::unique_ptr<FileSystemFileUtil> sync_file_util);
~AsyncFileUtilAdapter() override;
diff --git a/chromium/storage/browser/file_system/copy_or_move_file_validator_unittest.cc b/chromium/storage/browser/file_system/copy_or_move_file_validator_unittest.cc
index f8918394c2a..d0dbaf018b7 100644
--- a/chromium/storage/browser/file_system/copy_or_move_file_validator_unittest.cc
+++ b/chromium/storage/browser/file_system/copy_or_move_file_validator_unittest.cc
@@ -269,8 +269,7 @@ TEST(CopyOrMoveFileValidatorTest, AcceptAll) {
CopyOrMoveFileValidatorTestHelper helper("http://foo", kNoValidatorType,
kWithValidatorType);
helper.SetUp();
- std::unique_ptr<CopyOrMoveFileValidatorFactory> factory(
- new TestCopyOrMoveFileValidatorFactory(VALID));
+ auto factory = std::make_unique<TestCopyOrMoveFileValidatorFactory>(VALID);
helper.SetMediaCopyOrMoveFileValidatorFactory(std::move(factory));
helper.CopyTest(base::File::FILE_OK);
@@ -281,8 +280,8 @@ TEST(CopyOrMoveFileValidatorTest, AcceptNone) {
CopyOrMoveFileValidatorTestHelper helper("http://foo", kNoValidatorType,
kWithValidatorType);
helper.SetUp();
- std::unique_ptr<CopyOrMoveFileValidatorFactory> factory(
- new TestCopyOrMoveFileValidatorFactory(PRE_WRITE_INVALID));
+ auto factory =
+ std::make_unique<TestCopyOrMoveFileValidatorFactory>(PRE_WRITE_INVALID);
helper.SetMediaCopyOrMoveFileValidatorFactory(std::move(factory));
helper.CopyTest(base::File::FILE_ERROR_SECURITY);
@@ -294,12 +293,12 @@ TEST(CopyOrMoveFileValidatorTest, OverrideValidator) {
CopyOrMoveFileValidatorTestHelper helper("http://foo", kNoValidatorType,
kWithValidatorType);
helper.SetUp();
- std::unique_ptr<CopyOrMoveFileValidatorFactory> reject_factory(
- new TestCopyOrMoveFileValidatorFactory(PRE_WRITE_INVALID));
+ auto reject_factory =
+ std::make_unique<TestCopyOrMoveFileValidatorFactory>(PRE_WRITE_INVALID);
helper.SetMediaCopyOrMoveFileValidatorFactory(std::move(reject_factory));
- std::unique_ptr<CopyOrMoveFileValidatorFactory> accept_factory(
- new TestCopyOrMoveFileValidatorFactory(VALID));
+ auto accept_factory =
+ std::make_unique<TestCopyOrMoveFileValidatorFactory>(VALID);
helper.SetMediaCopyOrMoveFileValidatorFactory(std::move(accept_factory));
helper.CopyTest(base::File::FILE_ERROR_SECURITY);
@@ -310,8 +309,8 @@ TEST(CopyOrMoveFileValidatorTest, RejectPostWrite) {
CopyOrMoveFileValidatorTestHelper helper("http://foo", kNoValidatorType,
kWithValidatorType);
helper.SetUp();
- std::unique_ptr<CopyOrMoveFileValidatorFactory> factory(
- new TestCopyOrMoveFileValidatorFactory(POST_WRITE_INVALID));
+ auto factory =
+ std::make_unique<TestCopyOrMoveFileValidatorFactory>(POST_WRITE_INVALID);
helper.SetMediaCopyOrMoveFileValidatorFactory(std::move(factory));
helper.CopyTest(base::File::FILE_ERROR_SECURITY);
diff --git a/chromium/storage/browser/file_system/copy_or_move_operation_delegate.cc b/chromium/storage/browser/file_system/copy_or_move_operation_delegate.cc
index 91e146d3faf..86cbd036681 100644
--- a/chromium/storage/browser/file_system/copy_or_move_operation_delegate.cc
+++ b/chromium/storage/browser/file_system/copy_or_move_operation_delegate.cc
@@ -499,12 +499,13 @@ class StreamCopyOrMoveImpl
NotifyOnStartUpdate(dest_url_);
DCHECK(!copy_helper_);
- copy_helper_.reset(new CopyOrMoveOperationDelegate::StreamCopyHelper(
- std::move(reader_), std::move(writer_),
- dest_url_.mount_option().flush_policy(), kReadBufferSize,
- file_progress_callback_,
- base::TimeDelta::FromMilliseconds(
- kMinProgressCallbackInvocationSpanInMilliseconds)));
+ copy_helper_ =
+ std::make_unique<CopyOrMoveOperationDelegate::StreamCopyHelper>(
+ std::move(reader_), std::move(writer_),
+ dest_url_.mount_option().flush_policy(), kReadBufferSize,
+ file_progress_callback_,
+ base::TimeDelta::FromMilliseconds(
+ kMinProgressCallbackInvocationSpanInMilliseconds));
copy_helper_->Run(base::BindOnce(&StreamCopyOrMoveImpl::RunAfterStreamCopy,
weak_factory_.GetWeakPtr(),
std::move(callback), last_modified));
diff --git a/chromium/storage/browser/file_system/copy_or_move_operation_delegate_unittest.cc b/chromium/storage/browser/file_system/copy_or_move_operation_delegate_unittest.cc
index 7d8aa80bc98..edaf1d252f9 100644
--- a/chromium/storage/browser/file_system/copy_or_move_operation_delegate_unittest.cc
+++ b/chromium/storage/browser/file_system/copy_or_move_operation_delegate_unittest.cc
@@ -12,14 +12,15 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/containers/contains.h"
#include "base/containers/queue.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/location.h"
#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/services/filesystem/public/mojom/types.mojom.h"
@@ -191,12 +192,12 @@ class CopyOrMoveOperationTestHelper {
bool init_copy_or_move_validator) {
ASSERT_TRUE(base_.CreateUniqueTempDir());
base::FilePath base_dir = base_.GetPath();
- quota_manager_ =
- new MockQuotaManager(false /* is_incognito */, base_dir,
- base::ThreadTaskRunnerHandle::Get().get(),
- nullptr /* special storage policy */);
- quota_manager_proxy_ = new MockQuotaManagerProxy(
- quota_manager_.get(), base::ThreadTaskRunnerHandle::Get().get());
+ quota_manager_ = base::MakeRefCounted<MockQuotaManager>(
+ false /* is_incognito */, base_dir,
+ base::ThreadTaskRunnerHandle::Get().get(),
+ nullptr /* special storage policy */);
+ quota_manager_proxy_ = base::MakeRefCounted<MockQuotaManagerProxy>(
+ quota_manager_.get(), base::ThreadTaskRunnerHandle::Get());
file_system_context_ =
CreateFileSystemContextForTesting(quota_manager_proxy_.get(), base_dir);
@@ -210,8 +211,7 @@ class CopyOrMoveOperationTestHelper {
if (dest_type_ == kFileSystemTypeTest) {
TestFileSystemBackend* test_backend =
static_cast<TestFileSystemBackend*>(backend);
- std::unique_ptr<CopyOrMoveFileValidatorFactory> factory(
- new TestValidatorFactory);
+ auto factory = std::make_unique<TestValidatorFactory>();
test_backend->set_require_copy_or_move_validator(
require_copy_or_move_validator);
if (init_copy_or_move_validator)
diff --git a/chromium/storage/browser/file_system/external_mount_points.cc b/chromium/storage/browser/file_system/external_mount_points.cc
index 0c2e804bcce..985a050e1eb 100644
--- a/chromium/storage/browser/file_system/external_mount_points.cc
+++ b/chromium/storage/browser/file_system/external_mount_points.cc
@@ -36,7 +36,7 @@ base::FilePath NormalizeFilePath(const base::FilePath& path) {
}
bool IsOverlappingMountPathForbidden(FileSystemType type) {
- return type != kFileSystemTypeNativeMedia &&
+ return type != kFileSystemTypeLocalMedia &&
type != kFileSystemTypeDeviceMedia;
}
@@ -115,7 +115,7 @@ bool ExternalMountPoints::RegisterFileSystem(
bool ExternalMountPoints::HandlesFileSystemMountType(
FileSystemType type) const {
return type == kFileSystemTypeExternal ||
- type == kFileSystemTypeNativeForPlatformApp;
+ type == kFileSystemTypeLocalForPlatformApp;
}
bool ExternalMountPoints::RevokeFileSystem(const std::string& mount_name) {
@@ -264,7 +264,7 @@ FileSystemURL ExternalMountPoints::CrackFileSystemURL(
return FileSystemURL();
base::FilePath virtual_path = url.path();
- if (url.type() == kFileSystemTypeNativeForPlatformApp) {
+ if (url.type() == kFileSystemTypeLocalForPlatformApp) {
#if BUILDFLAG(IS_CHROMEOS_ASH)
// On Chrome OS, find a mount point and virtual path for the external fs.
if (!GetVirtualPath(url.path(), &virtual_path))
@@ -272,7 +272,7 @@ FileSystemURL ExternalMountPoints::CrackFileSystemURL(
#else
// On other OS, it is simply a native local path.
return FileSystemURL(url.origin(), url.mount_type(), url.virtual_path(),
- url.mount_filesystem_id(), kFileSystemTypeNativeLocal,
+ url.mount_filesystem_id(), kFileSystemTypeLocal,
url.path(), url.filesystem_id(), url.mount_option());
#endif
}
diff --git a/chromium/storage/browser/file_system/external_mount_points_unittest.cc b/chromium/storage/browser/file_system/external_mount_points_unittest.cc
index 7911a420b6f..e3df98989c5 100644
--- a/chromium/storage/browser/file_system/external_mount_points_unittest.cc
+++ b/chromium/storage/browser/file_system/external_mount_points_unittest.cc
@@ -111,9 +111,9 @@ TEST(ExternalMountPointsTest, AddMountPoint) {
// Test adding mount points.
for (const auto& test : kTestCases) {
EXPECT_EQ(test.success,
- mount_points->RegisterFileSystem(
- test.name, kFileSystemTypeNativeLocal,
- FileSystemMountOption(), base::FilePath(test.path)))
+ mount_points->RegisterFileSystem(test.name, kFileSystemTypeLocal,
+ FileSystemMountOption(),
+ base::FilePath(test.path)))
<< "Adding mount point: " << test.name << " with path " << test.path;
}
@@ -135,25 +135,25 @@ TEST(ExternalMountPointsTest, GetVirtualPath) {
scoped_refptr<ExternalMountPoints> mount_points =
ExternalMountPoints::CreateRefCounted();
- mount_points->RegisterFileSystem("c", kFileSystemTypeNativeLocal,
+ mount_points->RegisterFileSystem("c", kFileSystemTypeLocal,
FileSystemMountOption(),
base::FilePath(DRIVE FPL("/a/b/c")));
// Note that "/a/b/c" < "/a/b/c(1)" < "/a/b/c/".
- mount_points->RegisterFileSystem("c(1)", kFileSystemTypeNativeLocal,
+ mount_points->RegisterFileSystem("c(1)", kFileSystemTypeLocal,
FileSystemMountOption(),
base::FilePath(DRIVE FPL("/a/b/c(1)")));
- mount_points->RegisterFileSystem("x", kFileSystemTypeNativeLocal,
+ mount_points->RegisterFileSystem("x", kFileSystemTypeLocal,
FileSystemMountOption(),
base::FilePath(DRIVE FPL("/z/y/x")));
- mount_points->RegisterFileSystem("o", kFileSystemTypeNativeLocal,
+ mount_points->RegisterFileSystem("o", kFileSystemTypeLocal,
FileSystemMountOption(),
base::FilePath(DRIVE FPL("/m/n/o")));
// A mount point whose name does not match its path base name.
- mount_points->RegisterFileSystem("mount", kFileSystemTypeNativeLocal,
+ mount_points->RegisterFileSystem("mount", kFileSystemTypeLocal,
FileSystemMountOption(),
base::FilePath(DRIVE FPL("/root/foo")));
// A mount point with an empty path.
- mount_points->RegisterFileSystem("empty_path", kFileSystemTypeNativeLocal,
+ mount_points->RegisterFileSystem("empty_path", kFileSystemTypeLocal,
FileSystemMountOption(), base::FilePath());
struct TestCase {
@@ -246,10 +246,9 @@ TEST(ExternalMountPointsTest, HandlesFileSystemMountType) {
mount_points->HandlesFileSystemMountType(kFileSystemTypePersistent));
EXPECT_FALSE(mount_points->HandlesFileSystemMountType(kFileSystemTypeTest));
// Not even if it's external subtype.
+ EXPECT_FALSE(mount_points->HandlesFileSystemMountType(kFileSystemTypeLocal));
EXPECT_FALSE(
- mount_points->HandlesFileSystemMountType(kFileSystemTypeNativeLocal));
- EXPECT_FALSE(mount_points->HandlesFileSystemMountType(
- kFileSystemTypeRestrictedNativeLocal));
+ mount_points->HandlesFileSystemMountType(kFileSystemTypeRestrictedLocal));
EXPECT_FALSE(
mount_points->HandlesFileSystemMountType(kFileSystemTypeDriveFs));
EXPECT_FALSE(
@@ -263,7 +262,7 @@ TEST(ExternalMountPointsTest, CreateCrackedFileSystemURL) {
const url::Origin kTestOrigin =
url::Origin::Create(GURL("http://chromium.org"));
- mount_points->RegisterFileSystem("c", kFileSystemTypeNativeLocal,
+ mount_points->RegisterFileSystem("c", kFileSystemTypeLocal,
FileSystemMountOption(),
base::FilePath(DRIVE FPL("/a/b/c")));
mount_points->RegisterFileSystem("c(1)", kFileSystemTypeDriveFs,
@@ -286,7 +285,7 @@ TEST(ExternalMountPointsTest, CreateCrackedFileSystemURL) {
// Try native local which is not cracked.
FileSystemURL native_local = mount_points->CreateCrackedFileSystemURL(
- kTestOrigin, kFileSystemTypeNativeLocal, base::FilePath(FPL("c")));
+ kTestOrigin, kFileSystemTypeLocal, base::FilePath(FPL("c")));
EXPECT_FALSE(native_local.is_valid());
struct TestCase {
@@ -298,8 +297,7 @@ TEST(ExternalMountPointsTest, CreateCrackedFileSystemURL) {
};
const TestCase kTestCases[] = {
- {FPL("c/d/e"), true, kFileSystemTypeNativeLocal, DRIVE FPL("/a/b/c/d/e"),
- "c"},
+ {FPL("c/d/e"), true, kFileSystemTypeLocal, DRIVE FPL("/a/b/c/d/e"), "c"},
{FPL("c(1)/d/e"), true, kFileSystemTypeDriveFs, DRIVE FPL("/a/b/c(1)/d/e"),
"c(1)"},
{FPL("c(1)"), true, kFileSystemTypeDriveFs, DRIVE FPL("/a/b/c(1)"), "c(1)"},
@@ -320,8 +318,7 @@ TEST(ExternalMountPointsTest, CreateCrackedFileSystemURL) {
{FPL("c/d/../e"), false, kFileSystemTypeUnknown, FPL(""), ""},
{FPL("/empty_path/a/../b"), false, kFileSystemTypeUnknown, FPL(""), ""},
#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- {FPL("c/d\\e"), true, kFileSystemTypeNativeLocal, DRIVE FPL("/a/b/c/d/e"),
- "c"},
+ {FPL("c/d\\e"), true, kFileSystemTypeLocal, DRIVE FPL("/a/b/c/d/e"), "c"},
{FPL("mount\\a\\b"), true, kFileSystemTypeDriveFs, DRIVE FPL("/root/a/b"),
"mount"},
#endif
@@ -361,7 +358,7 @@ TEST(ExternalMountPointsTest, CrackVirtualPath) {
const GURL kTestOrigin("http://chromium.org");
- mount_points->RegisterFileSystem("c", kFileSystemTypeNativeLocal,
+ mount_points->RegisterFileSystem("c", kFileSystemTypeLocal,
FileSystemMountOption(),
base::FilePath(DRIVE FPL("/a/b/c")));
mount_points->RegisterFileSystem("c(1)", kFileSystemTypeDriveFs,
@@ -382,8 +379,7 @@ TEST(ExternalMountPointsTest, CrackVirtualPath) {
};
const TestCase kTestCases[] = {
- {FPL("c/d/e"), true, kFileSystemTypeNativeLocal, DRIVE FPL("/a/b/c/d/e"),
- "c"},
+ {FPL("c/d/e"), true, kFileSystemTypeLocal, DRIVE FPL("/a/b/c/d/e"), "c"},
{FPL("c(1)/d/e"), true, kFileSystemTypeDriveFs, DRIVE FPL("/a/b/c(1)/d/e"),
"c(1)"},
{FPL("c(1)"), true, kFileSystemTypeDriveFs, DRIVE FPL("/a/b/c(1)"), "c(1)"},
@@ -404,8 +400,7 @@ TEST(ExternalMountPointsTest, CrackVirtualPath) {
{FPL("c/d/../e"), false, kFileSystemTypeUnknown, FPL(""), ""},
{FPL("/empty_path/a/../b"), false, kFileSystemTypeUnknown, FPL(""), ""},
#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- {FPL("c/d\\e"), true, kFileSystemTypeNativeLocal, DRIVE FPL("/a/b/c/d/e"),
- "c"},
+ {FPL("c/d\\e"), true, kFileSystemTypeLocal, DRIVE FPL("/a/b/c/d/e"), "c"},
{FPL("mount\\a\\b"), true, kFileSystemTypeDriveFs, DRIVE FPL("/root/a/b"),
"mount"},
#endif
@@ -445,11 +440,11 @@ TEST(ExternalMountPointsTest, MountOption) {
ExternalMountPoints::CreateRefCounted();
mount_points->RegisterFileSystem(
- "nosync", kFileSystemTypeNativeLocal,
+ "nosync", kFileSystemTypeLocal,
FileSystemMountOption(FlushPolicy::NO_FLUSH_ON_COMPLETION),
base::FilePath(DRIVE FPL("/nosync")));
mount_points->RegisterFileSystem(
- "sync", kFileSystemTypeNativeLocal,
+ "sync", kFileSystemTypeLocal,
FileSystemMountOption(FlushPolicy::FLUSH_ON_COMPLETION),
base::FilePath(DRIVE FPL("/sync")));
diff --git a/chromium/storage/browser/file_system/file_stream_writer_test.h b/chromium/storage/browser/file_system/file_stream_writer_test.h
index e8cf2d74dc5..eb84a69b7a6 100644
--- a/chromium/storage/browser/file_system/file_stream_writer_test.h
+++ b/chromium/storage/browser/file_system/file_stream_writer_test.h
@@ -41,8 +41,8 @@ class FileStreamWriterTest : public testing::Test {
static void NeverCalled(int unused) { ADD_FAILURE(); }
private:
- base::test::SingleThreadTaskEnvironment task_environment_{
- base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::MainThreadType::IO};
};
template <class SubClass>
@@ -109,11 +109,11 @@ TYPED_TEST_P(FileStreamWriterTypedTest, WriteAfterEnd) {
std::unique_ptr<FileStreamWriter> writer(
this->CreateWriter(std::string(this->kTestFileName), 7));
- EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE,
- WriteStringToWriter(writer.get(), "xxx"));
+ EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "xxx"));
EXPECT_TRUE(this->FilePathExists(std::string(this->kTestFileName)));
- EXPECT_EQ("foobar", this->GetFileContent(std::string(this->kTestFileName)));
+ EXPECT_EQ(std::string("foobar\0xxx", 10),
+ this->GetFileContent(std::string(this->kTestFileName)));
}
TYPED_TEST_P(FileStreamWriterTypedTest, WriteFailForNonexistingFile) {
diff --git a/chromium/storage/browser/file_system/file_system_context.cc b/chromium/storage/browser/file_system/file_system_context.cc
index 553455ce2f5..e249cc7e780 100644
--- a/chromium/storage/browser/file_system/file_system_context.cc
+++ b/chromium/storage/browser/file_system/file_system_context.cc
@@ -12,13 +12,13 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/containers/contains.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "base/util/type_safety/pass_key.h"
+#include "base/types/pass_key.h"
#include "net/url_request/url_request.h"
#include "storage/browser/file_system/copy_or_move_file_validator.h"
#include "storage/browser/file_system/external_mount_points.h"
@@ -90,8 +90,8 @@ int FileSystemContext::GetPermissionPolicy(FileSystemType type) {
case kFileSystemTypeSyncable:
return FILE_PERMISSION_SANDBOX;
- case kFileSystemTypeNativeForPlatformApp:
- case kFileSystemTypeNativeLocal:
+ case kFileSystemTypeLocalForPlatformApp:
+ case kFileSystemTypeLocal:
case kFileSystemTypeCloudDevice:
case kFileSystemTypeProvided:
case kFileSystemTypeDeviceMediaAsFileStorage:
@@ -101,11 +101,11 @@ int FileSystemContext::GetPermissionPolicy(FileSystemType type) {
case kFileSystemTypeSmbFs:
return FILE_PERMISSION_USE_FILE_PERMISSION;
- case kFileSystemTypeRestrictedNativeLocal:
+ case kFileSystemTypeRestrictedLocal:
return FILE_PERMISSION_READ_ONLY | FILE_PERMISSION_USE_FILE_PERMISSION;
case kFileSystemTypeDeviceMedia:
- case kFileSystemTypeNativeMedia:
+ case kFileSystemTypeLocalMedia:
return FILE_PERMISSION_USE_FILE_PERMISSION;
// Following types are only accessed via IsolatedFileSystem, and
@@ -150,28 +150,29 @@ FileSystemContext::FileSystemContext(
io_task_runner_(io_task_runner),
default_file_task_runner_(file_task_runner),
quota_manager_proxy_(quota_manager_proxy),
- sandbox_delegate_(
- new SandboxFileSystemBackendDelegate(quota_manager_proxy,
- file_task_runner,
- partition_path,
- special_storage_policy,
- options,
- env_override_.get())),
- sandbox_backend_(new SandboxFileSystemBackend(sandbox_delegate_.get())),
- plugin_private_backend_(
- new PluginPrivateFileSystemBackend(file_task_runner,
- partition_path,
- special_storage_policy,
- options,
- env_override_.get())),
+ sandbox_delegate_(std::make_unique<SandboxFileSystemBackendDelegate>(
+ quota_manager_proxy,
+ file_task_runner,
+ partition_path,
+ special_storage_policy,
+ options,
+ env_override_.get())),
+ sandbox_backend_(
+ std::make_unique<SandboxFileSystemBackend>(sandbox_delegate_.get())),
+ plugin_private_backend_(std::make_unique<PluginPrivateFileSystemBackend>(
+ file_task_runner,
+ partition_path,
+ special_storage_policy,
+ options,
+ env_override_.get())),
additional_backends_(std::move(additional_backends)),
auto_mount_handlers_(auto_mount_handlers),
external_mount_points_(external_mount_points),
partition_path_(partition_path),
is_incognito_(options.is_incognito()),
- operation_runner_(
- new FileSystemOperationRunner(util::PassKey<FileSystemContext>(),
- this)) {
+ operation_runner_(std::make_unique<FileSystemOperationRunner>(
+ base::PassKey<FileSystemContext>(),
+ this)) {
RegisterBackend(sandbox_backend_.get());
RegisterBackend(plugin_private_backend_.get());
@@ -179,18 +180,19 @@ FileSystemContext::FileSystemContext(
RegisterBackend(backend.get());
// If the embedder's additional backends already provide support for
- // kFileSystemTypeNativeLocal and kFileSystemTypeNativeForPlatformApp then
+ // kFileSystemTypeLocal and kFileSystemTypeLocalForPlatformApp then
// IsolatedFileSystemBackend does not need to handle them. For example, on
// Chrome OS the additional backend chromeos::FileSystemBackend handles these
// types.
- isolated_backend_.reset(new IsolatedFileSystemBackend(
- !base::Contains(backend_map_, kFileSystemTypeNativeLocal),
- !base::Contains(backend_map_, kFileSystemTypeNativeForPlatformApp)));
+ isolated_backend_ = std::make_unique<IsolatedFileSystemBackend>(
+ !base::Contains(backend_map_, kFileSystemTypeLocal),
+ !base::Contains(backend_map_, kFileSystemTypeLocalForPlatformApp));
RegisterBackend(isolated_backend_.get());
if (quota_manager_proxy) {
// Quota client assumes all backends have registered.
- quota_manager_proxy->RegisterClient(
+ // TODO(crbug.com/1163048): Use mojo and switch to RegisterClient().
+ quota_manager_proxy->RegisterLegacyClient(
base::MakeRefCounted<FileSystemQuotaClient>(this),
QuotaClientType::kFileSystem, QuotaManagedStorageTypes());
}
@@ -458,13 +460,13 @@ std::unique_ptr<FileStreamWriter> FileSystemContext::CreateFileStreamWriter(
std::unique_ptr<FileSystemOperationRunner>
FileSystemContext::CreateFileSystemOperationRunner() {
return std::make_unique<FileSystemOperationRunner>(
- util::PassKey<FileSystemContext>(), this);
+ base::PassKey<FileSystemContext>(), this);
}
base::SequenceBound<FileSystemOperationRunner>
FileSystemContext::CreateSequenceBoundFileSystemOperationRunner() {
return base::SequenceBound<FileSystemOperationRunner>(
- io_task_runner_, util::PassKey<FileSystemContext>(),
+ io_task_runner_, base::PassKey<FileSystemContext>(),
base::WrapRefCounted(this));
}
@@ -639,12 +641,8 @@ void FileSystemContext::DidOpenFileSystemForResolveURL(
DCHECK(result);
}
- // TODO(mtomasz): Not all fields should be required for ResolveURL.
operation_runner()->GetMetadata(
- url,
- FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY |
- FileSystemOperation::GET_METADATA_FIELD_SIZE |
- FileSystemOperation::GET_METADATA_FIELD_LAST_MODIFIED,
+ url, FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY,
base::BindOnce(&DidGetMetadataForResolveURL, path, std::move(callback),
info));
}
diff --git a/chromium/storage/browser/file_system/file_system_context_unittest.cc b/chromium/storage/browser/file_system/file_system_context_unittest.cc
index 2cc657c177f..76aa905b046 100644
--- a/chromium/storage/browser/file_system/file_system_context_unittest.cc
+++ b/chromium/storage/browser/file_system/file_system_context_unittest.cc
@@ -8,6 +8,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/test/task_environment.h"
@@ -51,9 +52,9 @@ class FileSystemContextTest : public testing::Test {
void SetUp() override {
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
- storage_policy_ = new MockSpecialStoragePolicy();
+ storage_policy_ = base::MakeRefCounted<MockSpecialStoragePolicy>();
- mock_quota_manager_ = new MockQuotaManager(
+ mock_quota_manager_ = base::MakeRefCounted<MockQuotaManager>(
false /* is_incognito */, data_dir_.GetPath(),
base::ThreadTaskRunnerHandle::Get().get(), storage_policy_.get());
}
@@ -106,12 +107,12 @@ TEST_F(FileSystemContextTest, NullExternalMountPoints) {
std::string isolated_name = "root";
IsolatedContext::ScopedFSHandle isolated_fs =
IsolatedContext::GetInstance()->RegisterFileSystemForPath(
- kFileSystemTypeNativeLocal, std::string(),
+ kFileSystemTypeLocal, std::string(),
base::FilePath(DRIVE FPL("/test/isolated/root")), &isolated_name);
std::string isolated_id = isolated_fs.id();
// Register system external mount point.
ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
- "system", kFileSystemTypeNativeLocal, FileSystemMountOption(),
+ "system", kFileSystemTypeLocal, FileSystemMountOption(),
base::FilePath(DRIVE FPL("/test/sys/"))));
FileSystemURL cracked_isolated = file_system_context->CrackURL(
@@ -119,7 +120,7 @@ TEST_F(FileSystemContextTest, NullExternalMountPoints) {
ExpectFileSystemURLMatches(
cracked_isolated, GURL(kTestOrigin), kFileSystemTypeIsolated,
- kFileSystemTypeNativeLocal,
+ kFileSystemTypeLocal,
base::FilePath(DRIVE FPL("/test/isolated/root/file"))
.NormalizePathSeparators(),
base::FilePath::FromUTF8Unsafe(isolated_id)
@@ -132,7 +133,7 @@ TEST_F(FileSystemContextTest, NullExternalMountPoints) {
ExpectFileSystemURLMatches(
cracked_external, GURL(kTestOrigin), kFileSystemTypeExternal,
- kFileSystemTypeNativeLocal,
+ kFileSystemTypeLocal,
base::FilePath(DRIVE FPL("/test/sys/root/file"))
.NormalizePathSeparators(),
base::FilePath(FPL("system/root/file")).NormalizePathSeparators(),
@@ -149,7 +150,7 @@ TEST_F(FileSystemContextTest, FileSystemContextKeepsMountPointsAlive) {
// Register system external mount point.
ASSERT_TRUE(mount_points->RegisterFileSystem(
- "system", kFileSystemTypeNativeLocal, FileSystemMountOption(),
+ "system", kFileSystemTypeLocal, FileSystemMountOption(),
base::FilePath(DRIVE FPL("/test/sys/"))));
scoped_refptr<FileSystemContext> file_system_context(
@@ -165,7 +166,7 @@ TEST_F(FileSystemContextTest, FileSystemContextKeepsMountPointsAlive) {
ExpectFileSystemURLMatches(
cracked_external, GURL(kTestOrigin), kFileSystemTypeExternal,
- kFileSystemTypeNativeLocal,
+ kFileSystemTypeLocal,
base::FilePath(DRIVE FPL("/test/sys/root/file"))
.NormalizePathSeparators(),
base::FilePath(FPL("system/root/file")).NormalizePathSeparators(),
@@ -185,27 +186,27 @@ TEST_F(FileSystemContextTest, CrackFileSystemURL) {
std::string isolated_file_system_name = "root";
IsolatedContext::ScopedFSHandle isolated_fs =
IsolatedContext::GetInstance()->RegisterFileSystemForPath(
- kFileSystemTypeNativeLocal, std::string(),
+ kFileSystemTypeLocal, std::string(),
base::FilePath(DRIVE FPL("/test/isolated/root")),
&isolated_file_system_name);
const std::string kIsolatedFileSystemID = isolated_fs.id();
// Register system external mount point.
ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
- "system", kFileSystemTypeNativeLocal, FileSystemMountOption(),
+ "system", kFileSystemTypeLocal, FileSystemMountOption(),
base::FilePath(DRIVE FPL("/test/sys/"))));
ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
- "ext", kFileSystemTypeNativeLocal, FileSystemMountOption(),
+ "ext", kFileSystemTypeLocal, FileSystemMountOption(),
base::FilePath(DRIVE FPL("/test/ext"))));
// Register a system external mount point with the same name/id as the
// registered isolated mount point.
ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
- kIsolatedFileSystemID, kFileSystemTypeRestrictedNativeLocal,
+ kIsolatedFileSystemID, kFileSystemTypeRestrictedLocal,
FileSystemMountOption(),
base::FilePath(DRIVE FPL("/test/system/isolated"))));
// Add a mount points with the same name as a system mount point to
// FileSystemContext's external mount points.
ASSERT_TRUE(external_mount_points->RegisterFileSystem(
- "ext", kFileSystemTypeNativeLocal, FileSystemMountOption(),
+ "ext", kFileSystemTypeLocal, FileSystemMountOption(),
base::FilePath(DRIVE FPL("/test/local/ext/"))));
const GURL kTestOrigin = GURL("http://chromium.org/");
@@ -238,18 +239,17 @@ TEST_F(FileSystemContextTest, CrackFileSystemURL) {
},
// Should be cracked by isolated mount points:
{kIsolatedFileSystemID, "isolated", true /* is_valid */,
- kFileSystemTypeIsolated, kFileSystemTypeNativeLocal,
+ kFileSystemTypeIsolated, kFileSystemTypeLocal,
DRIVE FPL("/test/isolated/root/file"), kIsolatedFileSystemID},
// Should be cracked by system mount points:
{"system", "external", true /* is_valid */, kFileSystemTypeExternal,
- kFileSystemTypeNativeLocal, DRIVE FPL("/test/sys/root/file"), "system"},
+ kFileSystemTypeLocal, DRIVE FPL("/test/sys/root/file"), "system"},
{kIsolatedFileSystemID, "external", true /* is_valid */,
- kFileSystemTypeExternal, kFileSystemTypeRestrictedNativeLocal,
+ kFileSystemTypeExternal, kFileSystemTypeRestrictedLocal,
DRIVE FPL("/test/system/isolated/root/file"), kIsolatedFileSystemID},
// Should be cracked by FileSystemContext's ExternalMountPoints.
{"ext", "external", true /* is_valid */, kFileSystemTypeExternal,
- kFileSystemTypeNativeLocal, DRIVE FPL("/test/local/ext/root/file"),
- "ext"},
+ kFileSystemTypeLocal, DRIVE FPL("/test/local/ext/root/file"), "ext"},
// Test for invalid filesystem url (made invalid by adding invalid
// filesystem type).
{"sytem", "external", false /* is_valid */,
@@ -309,7 +309,7 @@ TEST_F(FileSystemContextTest, CanServeURLRequest) {
std::string isolated_fs_name = "root";
IsolatedContext::ScopedFSHandle isolated_fs =
IsolatedContext::GetInstance()->RegisterFileSystemForPath(
- kFileSystemTypeNativeLocal, std::string(),
+ kFileSystemTypeLocal, std::string(),
base::FilePath(DRIVE FPL("/test/isolated/root")), &isolated_fs_name);
std::string isolated_fs_id = isolated_fs.id();
cracked_url =
@@ -320,7 +320,7 @@ TEST_F(FileSystemContextTest, CanServeURLRequest) {
// A request for an external mount point should be served.
const std::string kExternalMountName = "ext_mount";
ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
- kExternalMountName, kFileSystemTypeNativeLocal, FileSystemMountOption(),
+ kExternalMountName, kFileSystemTypeLocal, FileSystemMountOption(),
base::FilePath()));
cracked_url =
context->CrackURL(CreateRawFileSystemURL("external", kExternalMountName));
@@ -347,10 +347,9 @@ TEST_F(FileSystemContextTest, IsolatedFileSystemsTypesHandled) {
file_system_context->GetFileSystemBackend(kFileSystemTypeDragged));
EXPECT_TRUE(file_system_context->GetFileSystemBackend(
kFileSystemTypeForTransientFile));
- EXPECT_TRUE(
- file_system_context->GetFileSystemBackend(kFileSystemTypeNativeLocal));
+ EXPECT_TRUE(file_system_context->GetFileSystemBackend(kFileSystemTypeLocal));
EXPECT_TRUE(file_system_context->GetFileSystemBackend(
- kFileSystemTypeNativeForPlatformApp));
+ kFileSystemTypeLocalForPlatformApp));
}
} // namespace
diff --git a/chromium/storage/browser/file_system/file_system_operation_impl.cc b/chromium/storage/browser/file_system/file_system_operation_impl.cc
index 1c00df8b879..a897d6f4c73 100644
--- a/chromium/storage/browser/file_system/file_system_operation_impl.cc
+++ b/chromium/storage/browser/file_system/file_system_operation_impl.cc
@@ -15,6 +15,7 @@
#include "base/callback_helpers.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
#include "net/base/escape.h"
#include "net/url_request/url_request.h"
@@ -104,12 +105,12 @@ void FileSystemOperationImpl::Copy(
DCHECK(SetPendingOperationType(kOperationCopy));
DCHECK(!recursive_operation_delegate_);
- recursive_operation_delegate_.reset(new CopyOrMoveOperationDelegate(
+ recursive_operation_delegate_ = std::make_unique<CopyOrMoveOperationDelegate>(
file_system_context(), src_url, dest_url,
CopyOrMoveOperationDelegate::OPERATION_COPY, option, error_behavior,
progress_callback,
base::BindOnce(&FileSystemOperationImpl::DidFinishOperation,
- weak_factory_.GetWeakPtr(), std::move(callback))));
+ weak_factory_.GetWeakPtr(), std::move(callback)));
recursive_operation_delegate_->RunRecursively();
}
@@ -119,12 +120,12 @@ void FileSystemOperationImpl::Move(const FileSystemURL& src_url,
StatusCallback callback) {
DCHECK(SetPendingOperationType(kOperationMove));
DCHECK(!recursive_operation_delegate_);
- recursive_operation_delegate_.reset(new CopyOrMoveOperationDelegate(
+ recursive_operation_delegate_ = std::make_unique<CopyOrMoveOperationDelegate>(
file_system_context(), src_url, dest_url,
CopyOrMoveOperationDelegate::OPERATION_MOVE, option, ERROR_BEHAVIOR_ABORT,
FileSystemOperation::CopyProgressCallback(),
base::BindOnce(&FileSystemOperationImpl::DidFinishOperation,
- weak_factory_.GetWeakPtr(), std::move(callback))));
+ weak_factory_.GetWeakPtr(), std::move(callback)));
recursive_operation_delegate_->RunRecursively();
}
@@ -178,10 +179,10 @@ void FileSystemOperationImpl::Remove(const FileSystemURL& url,
return;
}
- recursive_operation_delegate_.reset(new RemoveOperationDelegate(
+ recursive_operation_delegate_ = std::make_unique<RemoveOperationDelegate>(
file_system_context(), url,
base::BindOnce(&FileSystemOperationImpl::DidFinishOperation,
- weak_factory_.GetWeakPtr(), std::move(callback))));
+ weak_factory_.GetWeakPtr(), std::move(callback)));
recursive_operation_delegate_->Run();
}
@@ -414,10 +415,9 @@ void FileSystemOperationImpl::GetUsageAndQuotaThenRunTask(
}
DCHECK(quota_manager_proxy);
- DCHECK(quota_manager_proxy->quota_manager());
- quota_manager_proxy->quota_manager()->GetUsageAndQuota(
- url::Origin::Create(url.origin().GetURL()),
- FileSystemTypeToQuotaStorageType(url.type()),
+ quota_manager_proxy->GetUsageAndQuota(
+ url.origin(), FileSystemTypeToQuotaStorageType(url.type()),
+ base::SequencedTaskRunnerHandle::Get(),
base::BindOnce(&FileSystemOperationImpl::DidGetUsageAndQuotaAndRunTask,
weak_ptr_, std::move(task), std::move(error_callback)));
}
@@ -567,10 +567,10 @@ void FileSystemOperationImpl::DidDeleteRecursively(const FileSystemURL& url,
if (rv == base::File::FILE_ERROR_INVALID_OPERATION) {
// Recursive removal is not supported on this platform.
DCHECK(!recursive_operation_delegate_);
- recursive_operation_delegate_.reset(new RemoveOperationDelegate(
+ recursive_operation_delegate_ = std::make_unique<RemoveOperationDelegate>(
file_system_context(), url,
base::BindOnce(&FileSystemOperationImpl::DidFinishOperation, weak_ptr_,
- std::move(callback))));
+ std::move(callback)));
recursive_operation_delegate_->RunRecursively();
return;
}
diff --git a/chromium/storage/browser/file_system/file_system_operation_impl.h b/chromium/storage/browser/file_system/file_system_operation_impl.h
index 425b0aad9c7..c096e2a63df 100644
--- a/chromium/storage/browser/file_system/file_system_operation_impl.h
+++ b/chromium/storage/browser/file_system/file_system_operation_impl.h
@@ -105,14 +105,15 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemOperationImpl
return file_system_context_.get();
}
- private:
- friend class FileSystemOperation;
-
+ protected:
FileSystemOperationImpl(
const FileSystemURL& url,
FileSystemContext* file_system_context,
std::unique_ptr<FileSystemOperationContext> operation_context);
+ private:
+ friend class FileSystemOperation;
+
// Queries the quota and usage and then runs the given |task|.
// If an error occurs during the quota query it runs |error_callback| instead.
void GetUsageAndQuotaThenRunTask(const FileSystemURL& url,
diff --git a/chromium/storage/browser/file_system/file_system_operation_impl_unittest.cc b/chromium/storage/browser/file_system/file_system_operation_impl_unittest.cc
index d1eb56cdc3c..8ba68dfa6d7 100644
--- a/chromium/storage/browser/file_system/file_system_operation_impl_unittest.cc
+++ b/chromium/storage/browser/file_system/file_system_operation_impl_unittest.cc
@@ -16,6 +16,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
@@ -56,12 +57,12 @@ class FileSystemOperationImplTest : public testing::Test {
update_observers_ = MockFileUpdateObserver::CreateList(&update_observer_);
base::FilePath base_dir = base_.GetPath().AppendASCII("filesystem");
- quota_manager_ =
- new MockQuotaManager(false /* is_incognito */, base_dir,
- base::ThreadTaskRunnerHandle::Get().get(),
- nullptr /* special storage policy */);
- quota_manager_proxy_ = new MockQuotaManagerProxy(
- quota_manager(), base::ThreadTaskRunnerHandle::Get().get());
+ quota_manager_ = base::MakeRefCounted<MockQuotaManager>(
+ /* is_incognito= */ false, base_dir,
+ base::ThreadTaskRunnerHandle::Get().get(),
+ /* special storage policy= */ nullptr);
+ quota_manager_proxy_ = base::MakeRefCounted<MockQuotaManagerProxy>(
+ quota_manager(), base::ThreadTaskRunnerHandle::Get());
sandbox_file_system_.SetUp(base_dir, quota_manager_proxy_.get());
sandbox_file_system_.AddFileChangeObserver(&change_observer_);
sandbox_file_system_.AddFileUpdateObserver(&update_observer_);
@@ -103,11 +104,10 @@ class FileSystemOperationImplTest : public testing::Test {
MockFileChangeObserver* change_observer() { return &change_observer_; }
std::unique_ptr<FileSystemOperationContext> NewContext() {
- FileSystemOperationContext* context =
- sandbox_file_system_.NewOperationContext();
+ auto context = sandbox_file_system_.NewOperationContext();
// Grant enough quota for all test cases.
context->set_allowed_bytes_growth(1000000);
- return base::WrapUnique(context);
+ return context;
}
FileSystemURL URLForPath(const std::string& path) const {
diff --git a/chromium/storage/browser/file_system/file_system_operation_impl_write_unittest.cc b/chromium/storage/browser/file_system/file_system_operation_impl_write_unittest.cc
index f8a3c40465a..987ff4fd608 100644
--- a/chromium/storage/browser/file_system/file_system_operation_impl_write_unittest.cc
+++ b/chromium/storage/browser/file_system/file_system_operation_impl_write_unittest.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
@@ -59,15 +60,15 @@ class FileSystemOperationImplWriteTest : public testing::Test {
void SetUp() override {
ASSERT_TRUE(dir_.CreateUniqueTempDir());
- quota_manager_ =
- new MockQuotaManager(false /* is_incognito */, dir_.GetPath(),
- base::ThreadTaskRunnerHandle::Get().get(),
- nullptr /* special storage policy */);
+ quota_manager_ = base::MakeRefCounted<MockQuotaManager>(
+ /* is_incognito= */ false, dir_.GetPath(),
+ base::ThreadTaskRunnerHandle::Get().get(),
+ /* special storage policy= */ nullptr);
virtual_path_ = base::FilePath(FILE_PATH_LITERAL("temporary file"));
file_system_context_ = CreateFileSystemContextForTesting(
quota_manager_->proxy(), dir_.GetPath());
- blob_storage_context_.reset(new BlobStorageContext);
+ blob_storage_context_ = std::make_unique<BlobStorageContext>();
file_system_context_->operation_runner()->CreateFile(
URLForPath(virtual_path_), true /* exclusive */,
diff --git a/chromium/storage/browser/file_system/file_system_operation_runner.cc b/chromium/storage/browser/file_system/file_system_operation_runner.cc
index 3e99ddc30c5..7c186bdee47 100644
--- a/chromium/storage/browser/file_system/file_system_operation_runner.cc
+++ b/chromium/storage/browser/file_system/file_system_operation_runner.cc
@@ -12,9 +12,9 @@
#include "base/auto_reset.h"
#include "base/bind.h"
+#include "base/containers/contains.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "base/stl_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "net/url_request/url_request_context.h"
#include "storage/browser/blob/shareable_file_reference.h"
@@ -28,12 +28,12 @@ namespace storage {
using OperationID = FileSystemOperationRunner::OperationID;
FileSystemOperationRunner::FileSystemOperationRunner(
- util::PassKey<FileSystemContext>,
+ base::PassKey<FileSystemContext>,
const scoped_refptr<FileSystemContext>& file_system_context)
: FileSystemOperationRunner(file_system_context.get()) {}
FileSystemOperationRunner::FileSystemOperationRunner(
- util::PassKey<FileSystemContext>,
+ base::PassKey<FileSystemContext>,
FileSystemContext* file_system_context)
: FileSystemOperationRunner(file_system_context) {}
@@ -267,8 +267,8 @@ OperationID FileSystemOperationRunner::Write(
return id;
}
- std::unique_ptr<FileWriterDelegate> writer_delegate(new FileWriterDelegate(
- std::move(writer), url.mount_option().flush_policy()));
+ auto writer_delegate = std::make_unique<FileWriterDelegate>(
+ std::move(writer), url.mount_option().flush_policy());
std::unique_ptr<BlobReader> blob_reader;
if (blob)
@@ -306,8 +306,8 @@ OperationID FileSystemOperationRunner::WriteStream(
return id;
}
- std::unique_ptr<FileWriterDelegate> writer_delegate(new FileWriterDelegate(
- std::move(writer), url.mount_option().flush_policy()));
+ auto writer_delegate = std::make_unique<FileWriterDelegate>(
+ std::move(writer), url.mount_option().flush_policy());
PrepareForWrite(id, url);
operation_raw->Write(url, std::move(writer_delegate), std::move(data_pipe),
diff --git a/chromium/storage/browser/file_system/file_system_operation_runner.h b/chromium/storage/browser/file_system/file_system_operation_runner.h
index a5ec0e63d79..661cbe0b99e 100644
--- a/chromium/storage/browser/file_system/file_system_operation_runner.h
+++ b/chromium/storage/browser/file_system/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 "base/util/type_safety/pass_key.h"
+#include "base/types/pass_key.h"
#include "components/services/filesystem/public/mojom/types.mojom.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "storage/browser/file_system/file_system_operation.h"
@@ -54,9 +54,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemOperationRunner {
// |file_system_context| is stored as a raw pointer. The caller must ensure
// that |file_system_context| outlives the new instance.
FileSystemOperationRunner(
- util::PassKey<FileSystemContext>,
+ base::PassKey<FileSystemContext>,
const scoped_refptr<FileSystemContext>& file_system_context);
- FileSystemOperationRunner(util::PassKey<FileSystemContext>,
+ FileSystemOperationRunner(base::PassKey<FileSystemContext>,
FileSystemContext* file_system_context);
virtual ~FileSystemOperationRunner();
diff --git a/chromium/storage/browser/file_system/file_system_quota_client.cc b/chromium/storage/browser/file_system/file_system_quota_client.cc
index e9f3f9bfc05..ee87ffb244d 100644
--- a/chromium/storage/browser/file_system/file_system_quota_client.cc
+++ b/chromium/storage/browser/file_system/file_system_quota_client.cc
@@ -29,35 +29,29 @@ namespace storage {
namespace {
-void GetOriginsForTypeOnFileTaskRunner(FileSystemContext* context,
- StorageType storage_type,
- std::vector<url::Origin>* origins_ptr) {
+std::vector<url::Origin> GetOriginsForTypeOnFileTaskRunner(
+ FileSystemContext* context,
+ StorageType storage_type) {
FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type);
DCHECK(type != kFileSystemTypeUnknown);
FileSystemQuotaUtil* quota_util = context->GetQuotaUtil(type);
if (!quota_util)
- return;
- *origins_ptr = quota_util->GetOriginsForTypeOnFileTaskRunner(type);
+ return {};
+ return quota_util->GetOriginsForTypeOnFileTaskRunner(type);
}
-void GetOriginsForHostOnFileTaskRunner(FileSystemContext* context,
- StorageType storage_type,
- const std::string& host,
- std::vector<url::Origin>* origins_ptr) {
+std::vector<url::Origin> GetOriginsForHostOnFileTaskRunner(
+ FileSystemContext* context,
+ StorageType storage_type,
+ const std::string& host) {
FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type);
DCHECK(type != kFileSystemTypeUnknown);
FileSystemQuotaUtil* quota_util = context->GetQuotaUtil(type);
if (!quota_util)
- return;
- *origins_ptr = quota_util->GetOriginsForHostOnFileTaskRunner(type, host);
-}
-
-void DidGetFileSystemQuotaClientOrigins(
- QuotaClient::GetOriginsForTypeCallback callback,
- std::vector<url::Origin>* origins_ptr) {
- std::move(callback).Run(*origins_ptr);
+ return {};
+ return quota_util->GetOriginsForHostOnFileTaskRunner(type, host);
}
blink::mojom::QuotaStatusCode DeleteOriginOnFileTaskRunner(
@@ -120,14 +114,11 @@ void FileSystemQuotaClient::GetOriginsForType(
GetOriginsForTypeCallback callback) {
DCHECK(!callback.is_null());
- auto* origins_ptr = new std::vector<url::Origin>();
- file_task_runner()->PostTaskAndReply(
+ file_task_runner()->PostTaskAndReplyWithResult(
FROM_HERE,
base::BindOnce(&GetOriginsForTypeOnFileTaskRunner,
- base::RetainedRef(file_system_context_), storage_type,
- base::Unretained(origins_ptr)),
- base::BindOnce(&DidGetFileSystemQuotaClientOrigins, std::move(callback),
- base::Owned(origins_ptr)));
+ base::RetainedRef(file_system_context_), storage_type),
+ std::move(callback));
}
void FileSystemQuotaClient::GetOriginsForHost(
@@ -136,14 +127,12 @@ void FileSystemQuotaClient::GetOriginsForHost(
GetOriginsForHostCallback callback) {
DCHECK(!callback.is_null());
- auto* origins_ptr = new std::vector<url::Origin>();
- file_task_runner()->PostTaskAndReply(
+ file_task_runner()->PostTaskAndReplyWithResult(
FROM_HERE,
base::BindOnce(&GetOriginsForHostOnFileTaskRunner,
base::RetainedRef(file_system_context_), storage_type,
- host, base::Unretained(origins_ptr)),
- base::BindOnce(&DidGetFileSystemQuotaClientOrigins, std::move(callback),
- base::Owned(origins_ptr)));
+ host),
+ std::move(callback));
}
void FileSystemQuotaClient::DeleteOriginData(
diff --git a/chromium/storage/browser/file_system/file_system_usage_cache.cc b/chromium/storage/browser/file_system/file_system_usage_cache.cc
index ca742a0892d..3fb3e21957f 100644
--- a/chromium/storage/browser/file_system/file_system_usage_cache.cc
+++ b/chromium/storage/browser/file_system/file_system_usage_cache.cc
@@ -11,9 +11,9 @@
#include <utility>
#include "base/bind.h"
+#include "base/containers/contains.h"
#include "base/files/file_util.h"
#include "base/pickle.h"
-#include "base/stl_util.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
diff --git a/chromium/storage/browser/file_system/isolated_context_unittest.cc b/chromium/storage/browser/file_system/isolated_context_unittest.cc
index 2c28720f820..b8544bdb494 100644
--- a/chromium/storage/browser/file_system/isolated_context_unittest.cc
+++ b/chromium/storage/browser/file_system/isolated_context_unittest.cc
@@ -119,7 +119,7 @@ TEST_F(IsolatedContextTest, RegisterAndRevokeTest) {
IsolatedContext::ScopedFSHandle fs2 =
isolated_context()->RegisterFileSystemForPath(
- kFileSystemTypeNativeLocal, std::string(),
+ kFileSystemTypeLocal, std::string(),
base::FilePath(DRIVE FPL("/foo")), nullptr);
// Make sure the GetDraggedFileInfo returns false for both ones.
@@ -133,13 +133,13 @@ TEST_F(IsolatedContextTest, RegisterAndRevokeTest) {
// Try registering three more file systems for the same path as id2.
IsolatedContext::ScopedFSHandle fs3 =
isolated_context()->RegisterFileSystemForPath(
- kFileSystemTypeNativeLocal, std::string(), path, nullptr);
+ kFileSystemTypeLocal, std::string(), path, nullptr);
IsolatedContext::ScopedFSHandle fs4 =
isolated_context()->RegisterFileSystemForPath(
- kFileSystemTypeNativeLocal, std::string(), path, nullptr);
+ kFileSystemTypeLocal, std::string(), path, nullptr);
IsolatedContext::ScopedFSHandle fs5 =
isolated_context()->RegisterFileSystemForPath(
- kFileSystemTypeNativeLocal, std::string(), path, nullptr);
+ kFileSystemTypeLocal, std::string(), path, nullptr);
// Remove file system for id4.
fs4 = IsolatedContext::ScopedFSHandle();
@@ -317,12 +317,12 @@ TEST_F(IsolatedContextTest, CanHandleURL) {
EXPECT_FALSE(
isolated_context()->HandlesFileSystemMountType(kFileSystemTypeTest));
// Not even if it's isolated subtype.
- EXPECT_FALSE(isolated_context()->HandlesFileSystemMountType(
- kFileSystemTypeNativeLocal));
+ EXPECT_FALSE(
+ isolated_context()->HandlesFileSystemMountType(kFileSystemTypeLocal));
EXPECT_FALSE(
isolated_context()->HandlesFileSystemMountType(kFileSystemTypeDragged));
EXPECT_FALSE(isolated_context()->HandlesFileSystemMountType(
- kFileSystemTypeNativeMedia));
+ kFileSystemTypeLocalMedia));
EXPECT_FALSE(isolated_context()->HandlesFileSystemMountType(
kFileSystemTypeDeviceMedia));
}
diff --git a/chromium/storage/browser/file_system/isolated_file_system_backend.cc b/chromium/storage/browser/file_system/isolated_file_system_backend.cc
index ef345ee9b3e..49e2e3dca7a 100644
--- a/chromium/storage/browser/file_system/isolated_file_system_backend.cc
+++ b/chromium/storage/browser/file_system/isolated_file_system_backend.cc
@@ -38,9 +38,12 @@ IsolatedFileSystemBackend::IsolatedFileSystemBackend(
bool use_for_type_platform_app)
: use_for_type_native_local_(use_for_type_native_local),
use_for_type_platform_app_(use_for_type_platform_app),
- isolated_file_util_(new AsyncFileUtilAdapter(new LocalFileUtil())),
- dragged_file_util_(new AsyncFileUtilAdapter(new DraggedFileUtil())),
- transient_file_util_(new AsyncFileUtilAdapter(new TransientFileUtil())) {}
+ isolated_file_util_(std::make_unique<AsyncFileUtilAdapter>(
+ std::make_unique<LocalFileUtil>())),
+ dragged_file_util_(std::make_unique<AsyncFileUtilAdapter>(
+ std::make_unique<DraggedFileUtil>())),
+ transient_file_util_(std::make_unique<AsyncFileUtilAdapter>(
+ std::make_unique<TransientFileUtil>())) {}
IsolatedFileSystemBackend::~IsolatedFileSystemBackend() = default;
@@ -50,9 +53,9 @@ bool IsolatedFileSystemBackend::CanHandleType(FileSystemType type) const {
case kFileSystemTypeDragged:
case kFileSystemTypeForTransientFile:
return true;
- case kFileSystemTypeNativeLocal:
+ case kFileSystemTypeLocal:
return use_for_type_native_local_;
- case kFileSystemTypeNativeForPlatformApp:
+ case kFileSystemTypeLocalForPlatformApp:
return use_for_type_platform_app_;
default:
return false;
@@ -73,7 +76,7 @@ void IsolatedFileSystemBackend::ResolveURL(const FileSystemURL& url,
AsyncFileUtil* IsolatedFileSystemBackend::GetAsyncFileUtil(
FileSystemType type) {
switch (type) {
- case kFileSystemTypeNativeLocal:
+ case kFileSystemTypeLocal:
return isolated_file_util_.get();
case kFileSystemTypeDragged:
return dragged_file_util_.get();
@@ -114,7 +117,7 @@ bool IsolatedFileSystemBackend::SupportsStreaming(
bool IsolatedFileSystemBackend::HasInplaceCopyImplementation(
FileSystemType type) const {
- DCHECK(type == kFileSystemTypeNativeLocal || type == kFileSystemTypeDragged ||
+ DCHECK(type == kFileSystemTypeLocal || type == kFileSystemTypeDragged ||
type == kFileSystemTypeForTransientFile);
return false;
}
diff --git a/chromium/storage/browser/file_system/local_file_stream_reader.cc b/chromium/storage/browser/file_system/local_file_stream_reader.cc
index efd958857eb..89db58c714d 100644
--- a/chromium/storage/browser/file_system/local_file_stream_reader.cc
+++ b/chromium/storage/browser/file_system/local_file_stream_reader.cc
@@ -6,6 +6,7 @@
#include <stdint.h>
+#include <memory>
#include <utility>
#include "base/bind.h"
@@ -107,7 +108,7 @@ void LocalFileStreamReader::DidVerifyForOpen(
return;
}
- stream_impl_.reset(new net::FileStream(task_runner_));
+ stream_impl_ = std::make_unique<net::FileStream>(task_runner_);
callback_ = std::move(callback);
const int result = stream_impl_->Open(
file_path_, kOpenFlagsForRead,
diff --git a/chromium/storage/browser/file_system/local_file_stream_writer.cc b/chromium/storage/browser/file_system/local_file_stream_writer.cc
index 5ef1c708372..abb82703cf4 100644
--- a/chromium/storage/browser/file_system/local_file_stream_writer.cc
+++ b/chromium/storage/browser/file_system/local_file_stream_writer.cc
@@ -6,6 +6,8 @@
#include <stdint.h>
+#include <memory>
+
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "net/base/file_stream.h"
@@ -103,7 +105,7 @@ int LocalFileStreamWriter::InitiateOpen(base::OnceClosure main_operation) {
DCHECK(has_pending_operation_);
DCHECK(!stream_impl_.get());
- stream_impl_.reset(new net::FileStream(task_runner_));
+ stream_impl_ = std::make_unique<net::FileStream>(task_runner_);
int open_flags = 0;
switch (open_or_create_) {
@@ -139,46 +141,19 @@ void LocalFileStreamWriter::DidOpen(base::OnceClosure main_operation,
return;
}
- auto file_info = std::make_unique<base::File::Info>();
- base::File::Info* raw_file_info = file_info.get();
- result = stream_impl_->GetFileInfo(
- raw_file_info,
- base::BindOnce(&LocalFileStreamWriter::InitiateSeek,
- weak_factory_.GetWeakPtr(), std::move(main_operation),
- std::move(file_info)));
- DCHECK_NE(result, net::OK);
- if (result != net::ERR_IO_PENDING) {
- has_pending_operation_ = false;
- std::move(write_callback_).Run(result);
- }
+ InitiateSeek(std::move(main_operation));
}
-void LocalFileStreamWriter::InitiateSeek(
- base::OnceClosure main_operation,
- std::unique_ptr<base::File::Info> file_info,
- int file_info_result) {
+void LocalFileStreamWriter::InitiateSeek(base::OnceClosure main_operation) {
DCHECK(has_pending_operation_);
DCHECK(stream_impl_.get());
- if (file_info_result != net::OK) {
- has_pending_operation_ = false;
- std::move(write_callback_).Run(file_info_result);
- return;
- }
-
if (initial_offset_ == 0) {
// No need to seek.
std::move(main_operation).Run();
return;
}
- if (initial_offset_ > file_info->size) {
- // We should not be writing past the end of the file.
- has_pending_operation_ = false;
- std::move(write_callback_).Run(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
- return;
- }
-
int result = stream_impl_->Seek(
initial_offset_,
base::BindOnce(&LocalFileStreamWriter::DidSeek,
diff --git a/chromium/storage/browser/file_system/local_file_stream_writer.h b/chromium/storage/browser/file_system/local_file_stream_writer.h
index df2b4d1dff2..ed51d9c4fb7 100644
--- a/chromium/storage/browser/file_system/local_file_stream_writer.h
+++ b/chromium/storage/browser/file_system/local_file_stream_writer.h
@@ -13,7 +13,6 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/component_export.h"
-#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
@@ -55,9 +54,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) LocalFileStreamWriter
// Seeks to |initial_offset_| and proceeds to |main_operation| if it succeeds.
// If failed, the error code is returned by calling |error_callback|.
- void InitiateSeek(base::OnceClosure main_operation,
- std::unique_ptr<base::File::Info> file_info,
- int file_info_result);
+ void InitiateSeek(base::OnceClosure main_operation);
void DidSeek(base::OnceClosure main_operation, int64_t result);
// Passed as the |main_operation| of InitiateOpen() function.
diff --git a/chromium/storage/browser/file_system/local_file_util.cc b/chromium/storage/browser/file_system/local_file_util.cc
index 807079a6732..771e750b2c7 100644
--- a/chromium/storage/browser/file_system/local_file_util.cc
+++ b/chromium/storage/browser/file_system/local_file_util.cc
@@ -23,7 +23,7 @@
namespace storage {
AsyncFileUtil* AsyncFileUtil::CreateForLocalFileSystem() {
- return new AsyncFileUtilAdapter(new LocalFileUtil());
+ return new AsyncFileUtilAdapter(std::make_unique<LocalFileUtil>());
}
class LocalFileUtil::LocalFileEnumerator
@@ -136,7 +136,7 @@ LocalFileUtil::CreateFileEnumerator(FileSystemOperationContext* context,
bool recursive) {
base::FilePath file_path;
if (GetLocalFilePath(context, root_url, &file_path) != base::File::FILE_OK) {
- return base::WrapUnique(new EmptyFileEnumerator);
+ return std::make_unique<EmptyFileEnumerator>();
}
return std::make_unique<LocalFileEnumerator>(
this, file_path, root_url.path(), recursive,
diff --git a/chromium/storage/browser/file_system/local_file_util_unittest.cc b/chromium/storage/browser/file_system/local_file_util_unittest.cc
index 33e73e39238..c9e1b6d484b 100644
--- a/chromium/storage/browser/file_system/local_file_util_unittest.cc
+++ b/chromium/storage/browser/file_system/local_file_util_unittest.cc
@@ -54,9 +54,9 @@ class LocalFileUtilTest : public testing::Test {
}
protected:
- FileSystemOperationContext* NewContext() {
- FileSystemOperationContext* context =
- new FileSystemOperationContext(file_system_context_.get());
+ std::unique_ptr<FileSystemOperationContext> NewContext() {
+ auto context = std::make_unique<FileSystemOperationContext>(
+ file_system_context_.get());
context->set_update_observers(
*file_system_context_->GetUpdateObservers(kFileSystemType));
return context;
@@ -230,7 +230,7 @@ TEST_F(LocalFileUtilTest, Truncate) {
std::unique_ptr<FileSystemOperationContext> context;
- context.reset(NewContext());
+ context = NewContext();
ASSERT_EQ(base::File::FILE_OK,
file_util()->Truncate(context.get(), CreateURL(file_name), 1020));
@@ -247,7 +247,7 @@ TEST_F(LocalFileUtilTest, CopyFile) {
ASSERT_TRUE(created);
std::unique_ptr<FileSystemOperationContext> context;
- context.reset(NewContext());
+ context = NewContext();
ASSERT_EQ(base::File::FILE_OK,
file_util()->Truncate(context.get(), CreateURL(from_file), 1020));
@@ -259,7 +259,7 @@ TEST_F(LocalFileUtilTest, CopyFile) {
AsyncFileTestHelper::Copy(file_system_context(), CreateURL(from_file),
CreateURL(to_file1)));
- context.reset(NewContext());
+ context = NewContext();
ASSERT_EQ(
base::File::FILE_OK,
AsyncFileTestHelper::Copy(file_system_context(), CreateURL(from_file),
@@ -281,14 +281,14 @@ TEST_F(LocalFileUtilTest, CopyDirectory) {
bool created;
std::unique_ptr<FileSystemOperationContext> context;
- context.reset(NewContext());
+ context = NewContext();
ASSERT_EQ(base::File::FILE_OK,
file_util()->CreateDirectory(context.get(), CreateURL(from_dir),
false, false));
ASSERT_EQ(base::File::FILE_OK, EnsureFileExists(from_file, &created));
ASSERT_TRUE(created);
- context.reset(NewContext());
+ context = NewContext();
ASSERT_EQ(base::File::FILE_OK,
file_util()->Truncate(context.get(), CreateURL(from_file), 1020));
@@ -297,7 +297,7 @@ TEST_F(LocalFileUtilTest, CopyDirectory) {
EXPECT_EQ(1020, GetSize(from_file));
EXPECT_FALSE(DirectoryExists(to_dir));
- context.reset(NewContext());
+ context = NewContext();
ASSERT_EQ(base::File::FILE_OK,
AsyncFileTestHelper::Copy(file_system_context(),
CreateURL(from_dir), CreateURL(to_dir)));
@@ -318,14 +318,14 @@ TEST_F(LocalFileUtilTest, MoveFile) {
ASSERT_TRUE(created);
std::unique_ptr<FileSystemOperationContext> context;
- context.reset(NewContext());
+ context = NewContext();
ASSERT_EQ(base::File::FILE_OK,
file_util()->Truncate(context.get(), CreateURL(from_file), 1020));
EXPECT_TRUE(FileExists(from_file));
EXPECT_EQ(1020, GetSize(from_file));
- context.reset(NewContext());
+ context = NewContext();
ASSERT_EQ(base::File::FILE_OK, AsyncFileTestHelper::Move(
file_system_context(),
CreateURL(from_file), CreateURL(to_file)));
@@ -343,14 +343,14 @@ TEST_F(LocalFileUtilTest, MoveDirectory) {
bool created;
std::unique_ptr<FileSystemOperationContext> context;
- context.reset(NewContext());
+ context = NewContext();
ASSERT_EQ(base::File::FILE_OK,
file_util()->CreateDirectory(context.get(), CreateURL(from_dir),
false, false));
ASSERT_EQ(base::File::FILE_OK, EnsureFileExists(from_file, &created));
ASSERT_TRUE(created);
- context.reset(NewContext());
+ context = NewContext();
ASSERT_EQ(base::File::FILE_OK,
file_util()->Truncate(context.get(), CreateURL(from_file), 1020));
@@ -359,7 +359,7 @@ TEST_F(LocalFileUtilTest, MoveDirectory) {
EXPECT_EQ(1020, GetSize(from_file));
EXPECT_FALSE(DirectoryExists(to_dir));
- context.reset(NewContext());
+ context = NewContext();
ASSERT_EQ(base::File::FILE_OK,
AsyncFileTestHelper::Move(file_system_context(),
CreateURL(from_dir), CreateURL(to_dir)));
diff --git a/chromium/storage/browser/file_system/obfuscated_file_util.cc b/chromium/storage/browser/file_system/obfuscated_file_util.cc
index 78b74678b00..f2ad76f4342 100644
--- a/chromium/storage/browser/file_system/obfuscated_file_util.cc
+++ b/chromium/storage/browser/file_system/obfuscated_file_util.cc
@@ -819,7 +819,7 @@ ObfuscatedFileUtil::CreateFileEnumerator(FileSystemOperationContext* context,
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
SandboxDirectoryDatabase* db = GetDirectoryDatabase(root_url, false);
if (!db) {
- return base::WrapUnique(new EmptyFileEnumerator);
+ return std::make_unique<EmptyFileEnumerator>();
}
return std::make_unique<ObfuscatedFileEnumerator>(
db, context, this, root_url, recursive);
@@ -1348,18 +1348,19 @@ bool ObfuscatedFileUtil::InitOriginDatabase(const url::Origin& origin_hint,
}
}
- SandboxPrioritizedOriginDatabase* prioritized_origin_database =
- new SandboxPrioritizedOriginDatabase(file_system_directory_,
- env_override_);
- origin_database_.reset(prioritized_origin_database);
+ std::unique_ptr<SandboxPrioritizedOriginDatabase>
+ prioritized_origin_database =
+ std::make_unique<SandboxPrioritizedOriginDatabase>(
+ file_system_directory_, env_override_);
- if (!origin_hint.opaque() || !HasIsolatedStorage(origin_hint))
- return true;
-
- const std::string isolated_origin_string =
- GetIdentifierFromOrigin(origin_hint);
+ if (origin_hint.opaque() && HasIsolatedStorage(origin_hint)) {
+ const std::string isolated_origin_string =
+ GetIdentifierFromOrigin(origin_hint);
+ prioritized_origin_database->InitializePrimaryOrigin(
+ isolated_origin_string);
+ }
- prioritized_origin_database->InitializePrimaryOrigin(isolated_origin_string);
+ origin_database_ = std::move(prioritized_origin_database);
return true;
}
diff --git a/chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc b/chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc
index ec25aacf576..20b000b6cae 100644
--- a/chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc
+++ b/chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc
@@ -8,10 +8,33 @@
#include "base/files/file_util.h"
#include "base/numerics/checked_math.h"
+#include "base/system/sys_info.h"
#include "build/build_config.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
+namespace {
+
+// We are giving a relatively large quota to in-memory filesystem (see
+// quota_settings.cc), but we do not allocate this memory beforehand for the
+// filesystem. Therefore, specially on low-end devices, a website can get to a
+// state where it has not used all its quota, but there is no more memory
+// available and memory allocation fails and results in Chrome crash.
+// By checking for availability of memory before allocating it, we reduce the
+// crash possibility.
+// Note that quota assignment is the same for on-disk filesystem and the
+// assigned quota is not guaranteed to be allocatable later.
+bool IsMemoryAvailable(int64_t required_memory) {
+#if defined(OS_FUCHSIA)
+ // This function is not implemented on FUCHSIA, yet. (crbug.com/986608)
+ return true;
+#else
+ return base::SysInfo::AmountOfAvailablePhysicalMemory() >= required_memory;
+#endif
+}
+
+} // namespace
+
namespace storage {
// Struct keeping one entry of the directory tree.
@@ -305,6 +328,12 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::Truncate(
if (!dp || !dp->entry || dp->entry->type != Entry::kFile)
return base::File::FILE_ERROR_NOT_FOUND;
+ // Fail if enough memory is not available.
+ if (static_cast<size_t>(length) > dp->entry->file_content.capacity() &&
+ !IsMemoryAvailable(length)) {
+ return base::File::FILE_ERROR_NO_SPACE;
+ }
+
dp->entry->file_content.resize(length);
return base::File::FILE_OK;
}
@@ -356,9 +385,13 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::CopyOrMoveFile(
case NativeFileUtil::CopyOrMoveMode::COPY_NOSYNC:
case NativeFileUtil::CopyOrMoveMode::COPY_SYNC:
DCHECK(!src_is_directory);
+ // Fail if enough memory is not available.
+ if (!IsMemoryAvailable(src_dp->entry->file_content.size()))
+ return base::File::FILE_ERROR_NO_SPACE;
if (!CopyOrMoveFileInternal(*src_dp, *dest_dp, false))
return base::File::FILE_ERROR_FAILED;
break;
+
case NativeFileUtil::CopyOrMoveMode::MOVE:
if (src_is_directory) {
if (!MoveDirectoryInternal(*src_dp, *dest_dp))
@@ -485,7 +518,7 @@ int ObfuscatedFileUtilMemoryDelegate::WriteFile(
size_t offset_u = static_cast<size_t>(offset);
// Fail if |offset| or |buf_len| not valid.
- if (offset < 0 || buf_len < 0 || offset_u > dp->entry->file_content.size())
+ if (offset < 0 || buf_len < 0)
return net::ERR_REQUEST_RANGE_NOT_SATISFIABLE;
// Fail if result doesn't fit in a std::vector.
@@ -493,6 +526,12 @@ int ObfuscatedFileUtilMemoryDelegate::WriteFile(
static_cast<size_t>(buf_len))
return net::ERR_REQUEST_RANGE_NOT_SATISFIABLE;
+ // Fail if enough memory is not available.
+ if (offset_u + buf_len > dp->entry->file_content.capacity() &&
+ !IsMemoryAvailable(offset_u + buf_len)) {
+ return net::ERR_FILE_NO_SPACE;
+ }
+
if (offset_u == dp->entry->file_content.size()) {
dp->entry->file_content.insert(dp->entry->file_content.end(), buf->data(),
buf->data() + buf_len);
@@ -500,6 +539,8 @@ int ObfuscatedFileUtilMemoryDelegate::WriteFile(
if (offset_u + buf_len > dp->entry->file_content.size())
dp->entry->file_content.resize(offset_u + buf_len);
+ // if |offset_u| is larger than the original file size, there will be null
+ // bytes between the end of the file and |offset_u|.
memcpy(dp->entry->file_content.data() + offset, buf->data(), buf_len);
}
return buf_len;
@@ -548,6 +589,10 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::CopyInForeignFile(
return base::File::FILE_ERROR_NO_SPACE;
}
+ // Fail if enough memory is not available.
+ if (!IsMemoryAvailable(source_info.size))
+ return base::File::FILE_ERROR_NO_SPACE;
+
// Create file.
Entry* entry = &dest_dp->parent->directory_content
.emplace(dest_dp->components.back(), Entry::kFile)
diff --git a/chromium/storage/browser/file_system/obfuscated_file_util_unittest.cc b/chromium/storage/browser/file_system/obfuscated_file_util_unittest.cc
index ce28f2a91ef..cd1d6cee87a 100644
--- a/chromium/storage/browser/file_system/obfuscated_file_util_unittest.cc
+++ b/chromium/storage/browser/file_system/obfuscated_file_util_unittest.cc
@@ -13,6 +13,7 @@
#include <vector>
#include "base/bind.h"
+#include "base/callback_helpers.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
@@ -50,13 +51,6 @@
#include "url/gurl.h"
#include "url/origin.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 url::Origin;
namespace storage {
@@ -174,7 +168,8 @@ class ObfuscatedFileUtilTest : public testing::Test,
quota_manager_ = base::MakeRefCounted<QuotaManager>(
is_incognito(), data_dir_.GetPath(),
- base::ThreadTaskRunnerHandle::Get().get(), storage_policy_.get(),
+ base::ThreadTaskRunnerHandle::Get().get(),
+ /*quota_change_callback=*/base::DoNothing(), storage_policy_.get(),
GetQuotaSettingsFunc());
QuotaSettings settings;
settings.per_host_quota = 25 * 1024 * 1024;
@@ -224,10 +219,10 @@ class ObfuscatedFileUtilTest : public testing::Test,
return LimitedContext(std::numeric_limits<int64_t>::max());
}
- FileSystemOperationContext* NewContext(
+ std::unique_ptr<FileSystemOperationContext> NewContext(
SandboxFileSystemTestHelper* file_system) {
change_observer()->ResetCount();
- FileSystemOperationContext* context;
+ std::unique_ptr<FileSystemOperationContext> context;
if (file_system)
context = file_system->NewOperationContext();
else
@@ -387,7 +382,7 @@ class ObfuscatedFileUtilTest : public testing::Test,
if (!is_incognito())
EXPECT_EQ(length, GetLocalFileSize(data_path));
EXPECT_EQ(length, GetPathSize(url));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->GetFileInfo(context.get(), url, &file_info1, &data_path));
EXPECT_EQ(data_path, local_path);
@@ -400,12 +395,12 @@ class ObfuscatedFileUtilTest : public testing::Test,
EXPECT_EQ(length, file_info1.size);
EXPECT_LE(file_info0.last_modified, file_info1.last_modified);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->Truncate(context.get(), url, length * 2));
EXPECT_EQ(length * 2, GetPathSize(url));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK, ofu()->Truncate(context.get(), url, 0));
EXPECT_EQ(0, GetPathSize(url));
}
@@ -417,7 +412,7 @@ class ObfuscatedFileUtilTest : public testing::Test,
std::unique_ptr<FileSystemOperationContext> context;
for (const auto& file : files) {
bool created = true;
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
ASSERT_EQ(
base::File::FILE_OK,
ofu()->EnsureFileExists(
@@ -425,7 +420,7 @@ class ObfuscatedFileUtilTest : public testing::Test,
ASSERT_FALSE(created);
}
for (const auto& directory : directories) {
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_TRUE(DirectoryExists(FileSystemURLAppend(root_url, directory)));
}
}
@@ -462,17 +457,17 @@ class ObfuscatedFileUtilTest : public testing::Test,
std::unique_ptr<UsageVerifyHelper> AllowUsageIncrease(
int64_t requested_growth) {
int64_t usage = sandbox_file_system_.GetCachedOriginUsage();
- return std::unique_ptr<UsageVerifyHelper>(new UsageVerifyHelper(
- LimitedContext(requested_growth), &sandbox_file_system_,
- usage + requested_growth, this));
+ return std::make_unique<UsageVerifyHelper>(LimitedContext(requested_growth),
+ &sandbox_file_system_,
+ usage + requested_growth, this);
}
std::unique_ptr<UsageVerifyHelper> DisallowUsageIncrease(
int64_t requested_growth) {
int64_t usage = sandbox_file_system_.GetCachedOriginUsage();
- return std::unique_ptr<UsageVerifyHelper>(
- new UsageVerifyHelper(LimitedContext(requested_growth - 1),
- &sandbox_file_system_, usage, this));
+ return std::make_unique<UsageVerifyHelper>(
+ LimitedContext(requested_growth - 1), &sandbox_file_system_, usage,
+ this);
}
void FillTestDirectory(const FileSystemURL& root_url,
@@ -495,7 +490,7 @@ class ObfuscatedFileUtilTest : public testing::Test,
directories->insert(FILE_PATH_LITERAL("sixth"));
for (const auto& file : *files) {
bool created = false;
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
ASSERT_EQ(
base::File::FILE_OK,
ofu()->EnsureFileExists(
@@ -505,7 +500,7 @@ class ObfuscatedFileUtilTest : public testing::Test,
for (const auto& directory : *directories) {
bool exclusive = true;
bool recursive = false;
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->CreateDirectory(context.get(),
FileSystemURLAppend(root_url, directory),
@@ -521,7 +516,7 @@ class ObfuscatedFileUtilTest : public testing::Test,
std::unique_ptr<FileSystemOperationContext> context;
std::vector<filesystem::mojom::DirectoryEntry> entries;
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
AsyncFileTestHelper::ReadDirectory(file_system_context(),
root_url, &entries));
@@ -553,7 +548,7 @@ class ObfuscatedFileUtilTest : public testing::Test,
EXPECT_TRUE(change_observer()->HasNoChange());
base::FilePath local_path;
base::File::Info file_info;
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->GetFileInfo(context.get(), url, &file_info, &local_path));
// We compare as time_t here to lower our resolution, to avoid false
@@ -561,14 +556,14 @@ class ObfuscatedFileUtilTest : public testing::Test,
// representation and back.
EXPECT_EQ(file_info.last_modified.ToTimeT(), last_modified_time.ToTimeT());
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
last_modified_time += base::TimeDelta::FromHours(1);
last_access_time += base::TimeDelta::FromHours(14);
EXPECT_EQ(
base::File::FILE_OK,
ofu()->Touch(context.get(), url, last_access_time, last_modified_time));
EXPECT_TRUE(change_observer()->HasNoChange());
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->GetFileInfo(context.get(), url, &file_info, &local_path));
EXPECT_EQ(file_info.last_modified.ToTimeT(), last_modified_time.ToTimeT());
@@ -594,7 +589,7 @@ class ObfuscatedFileUtilTest : public testing::Test,
std::unique_ptr<FileSystemOperationContext> context;
if (overwrite) {
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
bool created = false;
EXPECT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), dest_url, &created));
@@ -609,14 +604,14 @@ class ObfuscatedFileUtilTest : public testing::Test,
ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path());
if (!overwrite) {
// Verify that file creation requires sufficient quota for the path.
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
context->set_allowed_bytes_growth(path_cost + src_file_length - 1);
EXPECT_EQ(
base::File::FILE_ERROR_NO_SPACE,
ofu()->CopyInForeignFile(context.get(), src_file_path, dest_url));
}
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
context->set_allowed_bytes_growth(path_cost + src_file_length);
EXPECT_EQ(base::File::FILE_OK,
ofu()->CopyInForeignFile(context.get(), src_file_path, dest_url));
@@ -624,7 +619,7 @@ class ObfuscatedFileUtilTest : public testing::Test,
EXPECT_TRUE(PathExists(dest_url));
EXPECT_FALSE(DirectoryExists(dest_url));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
base::File::Info file_info;
base::FilePath data_path;
EXPECT_EQ(base::File::FILE_OK, ofu()->GetFileInfo(context.get(), dest_url,
@@ -647,7 +642,7 @@ class ObfuscatedFileUtilTest : public testing::Test,
std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr));
base::FilePath data_path;
base::File::Info file_info;
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->GetFileInfo(context.get(), url, &file_info, &data_path));
EXPECT_TRUE(change_observer()->HasNoChange());
@@ -668,19 +663,19 @@ class ObfuscatedFileUtilTest : public testing::Test,
const FileSystemURL dest_file_url(
FileSystemURLAppendUTF8(dest_dir_url, "fuga"));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->CreateDirectory(context.get(), src_dir_url, true, true));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->CreateDirectory(context.get(), dest_dir_url, true, true));
bool created = false;
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), src_file_url, &created));
if (overwrite) {
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(
base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), dest_file_url, &created));
@@ -688,7 +683,7 @@ class ObfuscatedFileUtilTest : public testing::Test,
ClearTimestamp(src_dir_url);
ClearTimestamp(dest_dir_url);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->CopyOrMoveFile(context.get(), src_file_url, dest_file_url,
FileSystemOperation::OPTION_NONE, copy));
@@ -822,7 +817,7 @@ TEST_P(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) {
ofu()->EnsureFileExists(context.get(), url, &created);
EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, result);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
ofu()->DeleteFile(context.get(), url));
@@ -831,13 +826,13 @@ TEST_P(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) {
EXPECT_TRUE(change_observer()->HasNoChange());
// Verify that file creation requires sufficient quota for the path.
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
context->set_allowed_bytes_growth(
ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1);
result = ofu()->EnsureFileExists(context.get(), url, &created);
ASSERT_EQ(base::File::FILE_ERROR_NO_SPACE, result);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
context->set_allowed_bytes_growth(
ObfuscatedFileUtil::ComputeFilePathCost(url.path()));
created = false;
@@ -848,7 +843,7 @@ TEST_P(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) {
CheckFile(url);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
base::FilePath local_path;
EXPECT_EQ(base::File::FILE_OK,
ofu()->GetLocalFilePath(context.get(), url, &local_path));
@@ -857,7 +852,7 @@ TEST_P(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) {
// Verify that deleting a file isn't stopped by zero quota, and that it frees
// up quote from its path.
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
context->set_allowed_bytes_growth(0);
EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), url));
EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
@@ -865,7 +860,7 @@ TEST_P(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) {
EXPECT_EQ(ObfuscatedFileUtil::ComputeFilePathCost(url.path()),
context->allowed_bytes_growth());
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
bool exclusive = true;
bool recursive = true;
FileSystemURL directory_url = CreateURLFromUTF8("series/of/directories");
@@ -876,7 +871,7 @@ TEST_P(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) {
// The oepration created 3 directories recursively.
EXPECT_EQ(3, change_observer()->get_and_reset_create_directory_count());
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
created = false;
result = ofu()->EnsureFileExists(context.get(), url, &created);
ASSERT_TRUE(created);
@@ -885,13 +880,13 @@ TEST_P(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) {
CheckFile(url);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->GetLocalFilePath(context.get(), url, &local_path));
EXPECT_NE(is_incognito(), base::PathExists(local_path));
EXPECT_TRUE(PathExists(url));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), url));
EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
EXPECT_FALSE(PathExists(url));
@@ -908,24 +903,24 @@ TEST_P(ObfuscatedFileUtilTest, TestTruncate) {
EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
ofu()->Truncate(context.get(), url, 4));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
ASSERT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), url, &created));
ASSERT_TRUE(created);
EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
base::FilePath local_path;
EXPECT_EQ(base::File::FILE_OK,
ofu()->GetLocalFilePath(context.get(), url, &local_path));
CheckFileSize(url, local_path, 0);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK, ofu()->Truncate(context.get(), url, 10));
EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
CheckFileSize(url, local_path, 10);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK, ofu()->Truncate(context.get(), url, 1));
EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
CheckFileSize(url, local_path, 1);
@@ -937,7 +932,7 @@ TEST_P(ObfuscatedFileUtilTest, TestTruncate) {
EXPECT_TRUE(change_observer()->HasNoChange());
}
-TEST_P(ObfuscatedFileUtilTest, MAYBE_TestQuotaOnTruncation) {
+TEST_P(ObfuscatedFileUtilTest, TestQuotaOnTruncation) {
bool created = false;
FileSystemURL url = CreateURLFromUTF8("file");
@@ -989,7 +984,8 @@ TEST_P(ObfuscatedFileUtilTest, MAYBE_TestQuotaOnTruncation) {
EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
ofu()->Truncate(LimitedContext(1234).get(), url, 1234));
} else {
- EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(NewContext(nullptr), url));
+ EXPECT_EQ(base::File::FILE_OK,
+ ofu()->DeleteFile(NewContext(nullptr).get(), url));
}
ASSERT_EQ(0, ComputeTotalFileSize());
}
@@ -1003,7 +999,7 @@ TEST_P(ObfuscatedFileUtilTest, TestEnsureFileExists) {
EXPECT_TRUE(change_observer()->HasNoChange());
// Verify that file creation requires sufficient quota for the path.
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
url = CreateURLFromUTF8("test file");
created = false;
context->set_allowed_bytes_growth(
@@ -1013,7 +1009,7 @@ TEST_P(ObfuscatedFileUtilTest, TestEnsureFileExists) {
ASSERT_FALSE(created);
EXPECT_TRUE(change_observer()->HasNoChange());
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
context->set_allowed_bytes_growth(
ObfuscatedFileUtil::ComputeFilePathCost(url.path()));
ASSERT_EQ(base::File::FILE_OK,
@@ -1023,7 +1019,7 @@ TEST_P(ObfuscatedFileUtilTest, TestEnsureFileExists) {
CheckFile(url);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
ASSERT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), url, &created));
ASSERT_FALSE(created);
@@ -1031,7 +1027,7 @@ TEST_P(ObfuscatedFileUtilTest, TestEnsureFileExists) {
// Also test in a subdirectory.
url = CreateURLFromUTF8("path/to/file.txt");
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
bool exclusive = true;
bool recursive = true;
EXPECT_EQ(base::File::FILE_OK,
@@ -1040,7 +1036,7 @@ TEST_P(ObfuscatedFileUtilTest, TestEnsureFileExists) {
// 2 directories: path/ and path/to.
EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
ASSERT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), url, &created));
ASSERT_TRUE(created);
@@ -1058,17 +1054,17 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryOps) {
EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
ofu()->DeleteDirectory(context.get(), url));
FileSystemURL root = CreateURLFromUTF8(std::string());
EXPECT_FALSE(DirectoryExists(url));
EXPECT_FALSE(PathExists(url));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), root));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
exclusive = false;
recursive = true;
EXPECT_EQ(base::File::FILE_OK,
@@ -1078,16 +1074,16 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryOps) {
EXPECT_TRUE(DirectoryExists(url));
EXPECT_TRUE(PathExists(url));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_FALSE(ofu()->IsDirectoryEmpty(context.get(), root));
EXPECT_TRUE(DirectoryExists(FileSystemURLDirName(url)));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_FALSE(
ofu()->IsDirectoryEmpty(context.get(), FileSystemURLDirName(url)));
// Can't remove a non-empty directory.
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY,
ofu()->DeleteDirectory(context.get(), FileSystemURLDirName(url)));
EXPECT_TRUE(change_observer()->HasNoChange());
@@ -1101,21 +1097,21 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryOps) {
EXPECT_FALSE(file_info.is_symbolic_link);
// Same create again should succeed, since exclusive is false.
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
EXPECT_TRUE(change_observer()->HasNoChange());
exclusive = true;
recursive = true;
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_ERROR_EXISTS,
ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
EXPECT_TRUE(change_observer()->HasNoChange());
// Verify that deleting a directory isn't stopped by zero quota, and that it
// frees up quota from its path.
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
context->set_allowed_bytes_growth(0);
EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteDirectory(context.get(), url));
EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
@@ -1127,7 +1123,7 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryOps) {
EXPECT_FALSE(DirectoryExists(url));
EXPECT_FALSE(PathExists(url));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), url));
EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
ofu()->GetFileInfo(context.get(), url, &file_info, &local_path));
@@ -1135,14 +1131,14 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryOps) {
// Verify that file creation requires sufficient quota for the path.
exclusive = true;
recursive = false;
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
context->set_allowed_bytes_growth(
ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1);
EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
EXPECT_TRUE(change_observer()->HasNoChange());
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
context->set_allowed_bytes_growth(
ObfuscatedFileUtil::ComputeFilePathCost(url.path()));
EXPECT_EQ(base::File::FILE_OK,
@@ -1154,7 +1150,7 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryOps) {
exclusive = true;
recursive = false;
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_ERROR_EXISTS,
ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
EXPECT_TRUE(change_observer()->HasNoChange());
@@ -1162,7 +1158,7 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryOps) {
exclusive = true;
recursive = false;
url = CreateURLFromUTF8("foo");
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_ERROR_EXISTS,
ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
EXPECT_TRUE(change_observer()->HasNoChange());
@@ -1174,7 +1170,7 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryOps) {
exclusive = true;
recursive = false;
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
@@ -1184,7 +1180,7 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryOps) {
exclusive = true;
recursive = false;
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_ERROR_EXISTS,
ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
EXPECT_TRUE(change_observer()->HasNoChange());
@@ -1238,7 +1234,7 @@ TEST_P(ObfuscatedFileUtilTest, TestTouch) {
ofu()->Touch(context.get(), url, last_access_time, last_modified_time));
// OK, now create it.
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
bool created = false;
ASSERT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), url, &created));
@@ -1246,7 +1242,7 @@ TEST_P(ObfuscatedFileUtilTest, TestTouch) {
TestTouchHelper(url, true);
// Now test a directory:
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
bool exclusive = true;
bool recursive = false;
url = CreateURLFromUTF8("dir");
@@ -1283,7 +1279,7 @@ TEST_P(ObfuscatedFileUtilTest, TestPathQuotas) {
path_cost +=
ObfuscatedFileUtil::ComputeFilePathCost(base::FilePath(component));
}
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
context->set_allowed_bytes_growth(1024);
EXPECT_EQ(base::File::FILE_OK,
ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
@@ -1301,7 +1297,7 @@ TEST_P(ObfuscatedFileUtilTest, TestCopyOrMoveFileNotFound) {
FileSystemOperation::OPTION_NONE,
is_copy_not_move));
EXPECT_TRUE(change_observer()->HasNoChange());
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
is_copy_not_move = true;
EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
@@ -1311,7 +1307,7 @@ TEST_P(ObfuscatedFileUtilTest, TestCopyOrMoveFileNotFound) {
source_url = CreateURLFromUTF8("dir/dir/file");
bool exclusive = true;
bool recursive = true;
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
ASSERT_EQ(
base::File::FILE_OK,
ofu()->CreateDirectory(context.get(), FileSystemURLDirName(source_url),
@@ -1323,7 +1319,7 @@ TEST_P(ObfuscatedFileUtilTest, TestCopyOrMoveFileNotFound) {
FileSystemOperation::OPTION_NONE,
is_copy_not_move));
EXPECT_TRUE(change_observer()->HasNoChange());
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
is_copy_not_move = true;
EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
@@ -1353,38 +1349,38 @@ TEST_P(ObfuscatedFileUtilTest, TestCopyOrMoveFileSuccess) {
FileSystemURL source_url = CreateURLFromUTF8(test_case.source_path);
FileSystemURL dest_url = CreateURLFromUTF8(test_case.dest_path);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
ASSERT_EQ(
base::File::FILE_OK,
ofu()->CreateDirectory(context.get(), FileSystemURLDirName(source_url),
exclusive, recursive));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
ASSERT_EQ(
base::File::FILE_OK,
ofu()->CreateDirectory(context.get(), FileSystemURLDirName(dest_url),
exclusive, recursive));
bool created = false;
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
ASSERT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), source_url, &created));
ASSERT_TRUE(created);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
ASSERT_EQ(base::File::FILE_OK,
ofu()->Truncate(context.get(), source_url, kSourceLength));
if (test_case.cause_overwrite) {
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
created = false;
ASSERT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), dest_url, &created));
ASSERT_TRUE(created);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
ASSERT_EQ(base::File::FILE_OK,
ofu()->Truncate(context.get(), dest_url, kDestLength));
}
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
FileSystemOperation::OPTION_NONE,
@@ -1393,7 +1389,7 @@ TEST_P(ObfuscatedFileUtilTest, TestCopyOrMoveFileSuccess) {
if (test_case.is_copy_not_move) {
base::File::Info file_info;
base::FilePath local_path;
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->GetFileInfo(context.get(), source_url, &file_info,
&local_path));
@@ -1403,7 +1399,7 @@ TEST_P(ObfuscatedFileUtilTest, TestCopyOrMoveFileSuccess) {
} else {
base::File::Info file_info;
base::FilePath local_path;
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
ofu()->GetFileInfo(context.get(), source_url, &file_info,
&local_path));
@@ -1433,7 +1429,7 @@ TEST_P(ObfuscatedFileUtilTest, TestCopyPathQuotas) {
EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
FileSystemOperation::OPTION_NONE, is_copy));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
context->set_allowed_bytes_growth(
ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()));
EXPECT_EQ(base::File::FILE_OK,
@@ -1441,7 +1437,7 @@ TEST_P(ObfuscatedFileUtilTest, TestCopyPathQuotas) {
FileSystemOperation::OPTION_NONE, is_copy));
// Copy, with overwrite.
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
context->set_allowed_bytes_growth(0);
EXPECT_EQ(base::File::FILE_OK,
ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
@@ -1458,14 +1454,14 @@ TEST_P(ObfuscatedFileUtilTest, TestMovePathQuotasWithRename) {
bool is_copy = false;
// Move, rename, no overwrite.
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
context->set_allowed_bytes_growth(
ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) -
ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()) - 1);
EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
FileSystemOperation::OPTION_NONE, is_copy));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
context->set_allowed_bytes_growth(
ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) -
ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()));
@@ -1473,12 +1469,12 @@ TEST_P(ObfuscatedFileUtilTest, TestMovePathQuotasWithRename) {
ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
FileSystemOperation::OPTION_NONE, is_copy));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
ASSERT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), src_url, &created));
// Move, rename, with overwrite.
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
context->set_allowed_bytes_growth(0);
EXPECT_EQ(base::File::FILE_OK,
ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
@@ -1495,7 +1491,7 @@ TEST_P(ObfuscatedFileUtilTest, TestMovePathQuotasWithoutRename) {
bool exclusive = true;
bool recursive = false;
FileSystemURL dir_url = CreateURLFromUTF8("directory path");
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
ASSERT_EQ(base::File::FILE_OK, ofu()->CreateDirectory(context.get(), dir_url,
exclusive, recursive));
@@ -1504,7 +1500,7 @@ TEST_P(ObfuscatedFileUtilTest, TestMovePathQuotasWithoutRename) {
bool is_copy = false;
int64_t allowed_bytes_growth = -1000; // Over quota, this should still work.
// Move, no rename, no overwrite.
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
context->set_allowed_bytes_growth(allowed_bytes_growth);
EXPECT_EQ(base::File::FILE_OK,
ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
@@ -1512,10 +1508,10 @@ TEST_P(ObfuscatedFileUtilTest, TestMovePathQuotasWithoutRename) {
EXPECT_EQ(allowed_bytes_growth, context->allowed_bytes_growth());
// Move, no rename, with overwrite.
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
ASSERT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), src_url, &created));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
context->set_allowed_bytes_growth(allowed_bytes_growth);
EXPECT_EQ(base::File::FILE_OK,
ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
@@ -1698,13 +1694,13 @@ TEST_P(ObfuscatedFileUtilTest, TestInconsistency) {
bool created = false;
// Create a non-empty file.
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), kPath1, &created));
EXPECT_TRUE(created);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK, ofu()->Truncate(context.get(), kPath1, 10));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->GetFileInfo(context.get(), kPath1, &file_info, &data_path));
EXPECT_EQ(10, file_info.size);
@@ -1714,17 +1710,17 @@ TEST_P(ObfuscatedFileUtilTest, TestInconsistency) {
// Try to get file info of broken file.
EXPECT_FALSE(PathExists(kPath1));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), kPath1, &created));
EXPECT_TRUE(created);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->GetFileInfo(context.get(), kPath1, &file_info, &data_path));
EXPECT_EQ(0, file_info.size);
// Make another broken file to |kPath2|.
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), kPath2, &created));
EXPECT_TRUE(created);
@@ -1733,7 +1729,7 @@ TEST_P(ObfuscatedFileUtilTest, TestInconsistency) {
ofu()->DestroyDirectoryDatabase(origin(), type_string());
// Repair broken |kPath1|.
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
ofu()->Touch(context.get(), kPath1, base::Time::Now(),
base::Time::Now()));
@@ -1742,14 +1738,14 @@ TEST_P(ObfuscatedFileUtilTest, TestInconsistency) {
EXPECT_TRUE(created);
// Copy from sound |kPath1| to broken |kPath2|.
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(
base::File::FILE_OK,
ofu()->CopyOrMoveFile(context.get(), kPath1, kPath2,
FileSystemOperation::OPTION_NONE, true /* copy */));
ofu()->DestroyDirectoryDatabase(origin(), type_string());
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
created = false;
EXPECT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), kPath1, &created));
@@ -1767,7 +1763,7 @@ TEST_P(ObfuscatedFileUtilTest, TestIncompleteDirectoryReading) {
for (const auto& path : kPath) {
bool created = false;
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), path, &created));
EXPECT_TRUE(created);
@@ -1800,7 +1796,7 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) {
FileSystemURL url(FileSystemURLAppendUTF8(dir_url, "EnsureFileExists_file"));
bool created = false;
ClearTimestamp(dir_url);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), url, &created));
EXPECT_TRUE(created);
@@ -1809,7 +1805,7 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) {
// non create case.
created = true;
ClearTimestamp(dir_url);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), url, &created));
EXPECT_FALSE(created);
@@ -1817,12 +1813,12 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) {
// fail case.
url = FileSystemURLAppendUTF8(dir_url, "EnsureFileExists_dir");
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->CreateDirectory(context.get(), url, false, false));
ClearTimestamp(dir_url);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_ERROR_NOT_A_FILE,
ofu()->EnsureFileExists(context.get(), url, &created));
EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
@@ -1830,7 +1826,7 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) {
// CreateOrOpen, create case.
url = FileSystemURLAppendUTF8(dir_url, "CreateOrOpen_file");
ClearTimestamp(dir_url);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
created = false;
EXPECT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), url, &created));
@@ -1839,7 +1835,7 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) {
// open case.
ClearTimestamp(dir_url);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), url, &created));
EXPECT_FALSE(created);
@@ -1847,7 +1843,7 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) {
// fail case
ClearTimestamp(dir_url);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), url, &created));
EXPECT_FALSE(created);
@@ -1858,7 +1854,7 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) {
url = FileSystemURLAppendUTF8(dir_url, "CreateDirectory_dir");
FileSystemURL subdir_url(FileSystemURLAppendUTF8(url, "subdir"));
ClearTimestamp(dir_url);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->CreateDirectory(context.get(), subdir_url,
true /* exclusive */, true /* recursive */));
@@ -1869,7 +1865,7 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) {
subdir_url = FileSystemURLAppendUTF8(url, "subdir2");
ClearTimestamp(dir_url);
ClearTimestamp(url);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->CreateDirectory(context.get(), subdir_url,
true /* exclusive */, true /* recursive */));
@@ -1879,7 +1875,7 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) {
// fail case.
url = FileSystemURLAppendUTF8(dir_url, "CreateDirectory_dir");
ClearTimestamp(dir_url);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_ERROR_EXISTS,
ofu()->CreateDirectory(context.get(), url, true /* exclusive */,
true /* recursive */));
@@ -1897,7 +1893,7 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) {
EXPECT_TRUE(created);
ClearTimestamp(dir_url);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(
base::File::FILE_OK,
ofu()->CopyInForeignFile(context.get(), foreign_src_file_path, url));
@@ -1915,19 +1911,19 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryTimestampForDeletion) {
// DeleteFile, delete case.
FileSystemURL url = FileSystemURLAppendUTF8(dir_url, "DeleteFile_file");
bool created = false;
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), url, &created));
EXPECT_TRUE(created);
ClearTimestamp(dir_url);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), url));
EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
// fail case.
ClearTimestamp(dir_url);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
ofu()->DeleteFile(context.get(), url));
EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
@@ -1935,27 +1931,27 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryTimestampForDeletion) {
// DeleteDirectory, fail case.
url = FileSystemURLAppendUTF8(dir_url, "DeleteDirectory_dir");
FileSystemURL file_path(FileSystemURLAppendUTF8(url, "pakeratta"));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->CreateDirectory(context.get(), url, true, true));
created = false;
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), file_path, &created));
EXPECT_TRUE(created);
ClearTimestamp(dir_url);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY,
ofu()->DeleteDirectory(context.get(), url));
EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
// delete case.
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), file_path));
ClearTimestamp(dir_url);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteDirectory(context.get(), url));
EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
}
@@ -1980,35 +1976,35 @@ TEST_P(ObfuscatedFileUtilTest, TestFileEnumeratorTimestamp) {
ofu()->CreateDirectory(context.get(), dir, false, false));
bool created = false;
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->EnsureFileExists(context.get(), url1, &created));
EXPECT_TRUE(created);
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->CreateDirectory(context.get(), url2, false, false));
base::FilePath file_path;
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->GetLocalFilePath(context.get(), url1, &file_path));
EXPECT_FALSE(file_path.empty());
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
EXPECT_EQ(base::File::FILE_OK,
ofu()->Touch(context.get(), url1,
base::Time::Now() + base::TimeDelta::FromHours(1),
base::Time()));
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
std::unique_ptr<FileSystemFileUtil::AbstractFileEnumerator> file_enum =
ofu()->CreateFileEnumerator(context.get(), dir, false);
int count = 0;
base::FilePath file_path_each;
while (!(file_path_each = file_enum->Next()).empty()) {
- context.reset(NewContext(nullptr));
+ context = NewContext(nullptr);
base::File::Info file_info;
base::FilePath file_path;
EXPECT_EQ(
diff --git a/chromium/storage/browser/file_system/plugin_private_file_system_backend.cc b/chromium/storage/browser/file_system/plugin_private_file_system_backend.cc
index 70975f6b46a..ee251a933b2 100644
--- a/chromium/storage/browser/file_system/plugin_private_file_system_backend.cc
+++ b/chromium/storage/browser/file_system/plugin_private_file_system_backend.cc
@@ -11,9 +11,9 @@
#include <utility>
#include "base/bind.h"
+#include "base/containers/contains.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
-#include "base/stl_util.h"
#include "base/synchronization/lock.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -103,11 +103,13 @@ PluginPrivateFileSystemBackend::PluginPrivateFileSystemBackend(
base_path_(profile_path.Append(kFileSystemDirectory)
.Append(kPluginPrivateDirectory)),
plugin_map_(new FileSystemIDToPluginMap(file_task_runner)) {
- file_util_ = std::make_unique<AsyncFileUtilAdapter>(new ObfuscatedFileUtil(
- special_storage_policy, base_path_, env_override,
- base::BindRepeating(&FileSystemIDToPluginMap::GetPluginIDForURL,
- base::Owned(plugin_map_)),
- std::set<std::string>(), nullptr, file_system_options.is_incognito()));
+ file_util_ = std::make_unique<AsyncFileUtilAdapter>(
+ std::make_unique<ObfuscatedFileUtil>(
+ special_storage_policy, base_path_, env_override,
+ base::BindRepeating(&FileSystemIDToPluginMap::GetPluginIDForURL,
+ base::Owned(plugin_map_)),
+ std::set<std::string>(), nullptr,
+ file_system_options.is_incognito()));
}
PluginPrivateFileSystemBackend::~PluginPrivateFileSystemBackend() {
@@ -180,7 +182,7 @@ FileSystemOperation* PluginPrivateFileSystemBackend::CreateFileSystemOperation(
FileSystemContext* context,
base::File::Error* error_code) const {
std::unique_ptr<FileSystemOperationContext> operation_context(
- new FileSystemOperationContext(context));
+ std::make_unique<FileSystemOperationContext>(context));
return FileSystemOperation::Create(url, context,
std::move(operation_context));
}
@@ -315,7 +317,7 @@ void PluginPrivateFileSystemBackend::GetOriginDetailsOnFileTaskRunner(
"pluginprivate");
std::unique_ptr<FileSystemOperationContext> operation_context(
- new FileSystemOperationContext(context));
+ std::make_unique<FileSystemOperationContext>(context));
// Determine the available plugin private filesystem directories for this
// origin. Currently the plugin private filesystem is only used by Encrypted
diff --git a/chromium/storage/browser/file_system/quota/quota_backend_impl.cc b/chromium/storage/browser/file_system/quota/quota_backend_impl.cc
index f5a5ddacfbf..9a3af570aca 100644
--- a/chromium/storage/browser/file_system/quota/quota_backend_impl.cc
+++ b/chromium/storage/browser/file_system/quota/quota_backend_impl.cc
@@ -47,7 +47,7 @@ void QuotaBackendImpl::ReserveQuota(const url::Origin& origin,
}
DCHECK(quota_manager_proxy_.get());
quota_manager_proxy_->GetUsageAndQuota(
- file_task_runner_.get(), origin, FileSystemTypeToQuotaStorageType(type),
+ origin, FileSystemTypeToQuotaStorageType(type), file_task_runner_,
base::BindOnce(&QuotaBackendImpl::DidGetUsageAndQuotaForReserveQuota,
weak_ptr_factory_.GetWeakPtr(),
QuotaReservationInfo(origin, type, delta),
@@ -141,7 +141,8 @@ void QuotaBackendImpl::ReserveQuotaInternal(const QuotaReservationInfo& info) {
DCHECK(quota_manager_proxy_.get());
quota_manager_proxy_->NotifyStorageModified(
QuotaClientType::kFileSystem, info.origin,
- FileSystemTypeToQuotaStorageType(info.type), info.delta);
+ FileSystemTypeToQuotaStorageType(info.type), info.delta,
+ base::Time::Now());
}
base::File::Error QuotaBackendImpl::GetUsageCachePath(
diff --git a/chromium/storage/browser/file_system/quota/quota_backend_impl_unittest.cc b/chromium/storage/browser/file_system/quota/quota_backend_impl_unittest.cc
index e7e8c49e7f1..84dc3a1af71 100644
--- a/chromium/storage/browser/file_system/quota/quota_backend_impl_unittest.cc
+++ b/chromium/storage/browser/file_system/quota/quota_backend_impl_unittest.cc
@@ -11,9 +11,12 @@
#include <utility>
#include "base/bind.h"
+#include "base/check.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
+#include "base/sequenced_task_runner.h"
#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "storage/browser/file_system/file_system_usage_cache.h"
@@ -41,7 +44,7 @@ bool DidReserveQuota(bool accepted,
class MockQuotaManagerProxy : public QuotaManagerProxy {
public:
MockQuotaManagerProxy()
- : QuotaManagerProxy(nullptr, nullptr),
+ : QuotaManagerProxy(nullptr, base::ThreadTaskRunnerHandle::Get()),
storage_modified_count_(0),
usage_(0),
quota_(0) {}
@@ -54,19 +57,28 @@ class MockQuotaManagerProxy : public QuotaManagerProxy {
blink::mojom::StorageType type,
bool enabled) override {}
- void NotifyStorageModified(QuotaClientType client_id,
- const url::Origin& origin,
- blink::mojom::StorageType type,
- int64_t delta) override {
+ void NotifyStorageModified(
+ QuotaClientType client_id,
+ const url::Origin& origin,
+ blink::mojom::StorageType type,
+ int64_t delta,
+ base::Time modification_time,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ base::OnceClosure callback) override {
++storage_modified_count_;
usage_ += delta;
ASSERT_LE(usage_, quota_);
+ if (callback)
+ callback_task_runner->PostTask(FROM_HERE, std::move(callback));
}
- void GetUsageAndQuota(base::SequencedTaskRunner* original_task_runner,
- const url::Origin& origin,
- blink::mojom::StorageType type,
- UsageAndQuotaCallback callback) override {
+ void GetUsageAndQuota(
+ const url::Origin& origin,
+ blink::mojom::StorageType type,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ UsageAndQuotaCallback callback) override {
+ DCHECK(callback_task_runner);
+ DCHECK(callback_task_runner->RunsTasksInCurrentSequence());
std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk, usage_, quota_);
}
@@ -93,7 +105,7 @@ class QuotaBackendImplTest : public testing::Test,
public:
QuotaBackendImplTest()
: file_system_usage_cache_(is_incognito()),
- quota_manager_proxy_(new MockQuotaManagerProxy) {}
+ quota_manager_proxy_(base::MakeRefCounted<MockQuotaManagerProxy>()) {}
void SetUp() override {
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
diff --git a/chromium/storage/browser/file_system/quota/quota_reservation_manager_unittest.cc b/chromium/storage/browser/file_system/quota/quota_reservation_manager_unittest.cc
index 3e5f74dc6ba..f588e185d30 100644
--- a/chromium/storage/browser/file_system/quota/quota_reservation_manager_unittest.cc
+++ b/chromium/storage/browser/file_system/quota/quota_reservation_manager_unittest.cc
@@ -188,9 +188,9 @@ class QuotaReservationManagerTest : public testing::Test {
file_path_ = work_dir_.GetPath().Append(FILE_PATH_LITERAL("hoge"));
SetFileSize(file_path_, kInitialFileSize);
- std::unique_ptr<QuotaReservationManager::QuotaBackend> backend(
- new FakeBackend);
- reservation_manager_.reset(new QuotaReservationManager(std::move(backend)));
+ auto backend = std::make_unique<FakeBackend>();
+ reservation_manager_ =
+ std::make_unique<QuotaReservationManager>(std::move(backend));
}
void TearDown() override { reservation_manager_.reset(); }
diff --git a/chromium/storage/browser/file_system/recursive_operation_delegate_unittest.cc b/chromium/storage/browser/file_system/recursive_operation_delegate_unittest.cc
index 4195b5bb5ba..cd4c1f2e310 100644
--- a/chromium/storage/browser/file_system/recursive_operation_delegate_unittest.cc
+++ b/chromium/storage/browser/file_system/recursive_operation_delegate_unittest.cc
@@ -148,11 +148,10 @@ class RecursiveOperationDelegateTest : public testing::Test {
void TearDown() override { sandbox_file_system_.TearDown(); }
std::unique_ptr<FileSystemOperationContext> NewContext() {
- FileSystemOperationContext* context =
- sandbox_file_system_.NewOperationContext();
+ auto context = sandbox_file_system_.NewOperationContext();
// Grant enough quota for all test cases.
context->set_allowed_bytes_growth(1000000);
- return base::WrapUnique(context);
+ return context;
}
FileSystemFileUtil* file_util() { return sandbox_file_system_.file_util(); }
diff --git a/chromium/storage/browser/file_system/sandbox_directory_database_unittest.cc b/chromium/storage/browser/file_system/sandbox_directory_database_unittest.cc
index 2f844339fab..e24f825f338 100644
--- a/chromium/storage/browser/file_system/sandbox_directory_database_unittest.cc
+++ b/chromium/storage/browser/file_system/sandbox_directory_database_unittest.cc
@@ -46,7 +46,7 @@ class SandboxDirectoryDatabaseTest : public testing::Test {
// Call CloseDatabase() to avoid having multiple database instances for
// single directory at once.
CloseDatabase();
- db_.reset(new SandboxDirectoryDatabase(path(), nullptr));
+ db_ = std::make_unique<SandboxDirectoryDatabase>(path(), nullptr);
}
void CloseDatabase() { db_.reset(); }
@@ -98,7 +98,7 @@ class SandboxDirectoryDatabaseTest : public testing::Test {
db_.reset();
ASSERT_TRUE(base::DeletePathRecursively(path()));
ASSERT_TRUE(base::CreateDirectory(path()));
- db_.reset(new SandboxDirectoryDatabase(path(), nullptr));
+ db_ = std::make_unique<SandboxDirectoryDatabase>(path(), nullptr);
}
bool RepairDatabase() {
diff --git a/chromium/storage/browser/file_system/sandbox_file_stream_writer.cc b/chromium/storage/browser/file_system/sandbox_file_stream_writer.cc
index 2a09c4cf6ec..fcc3cfb2548 100644
--- a/chromium/storage/browser/file_system/sandbox_file_stream_writer.cc
+++ b/chromium/storage/browser/file_system/sandbox_file_stream_writer.cc
@@ -13,6 +13,7 @@
#include "base/bind.h"
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h"
+#include "base/threading/sequenced_task_runner_handle.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "storage/browser/file_system/file_observers.h"
@@ -28,18 +29,18 @@ namespace storage {
namespace {
-// Adjust the |quota| value in overwriting case (i.e. |file_size| > 0 and
-// |file_offset| < |file_size|) to make the remaining quota calculation easier.
-// Specifically this widens the quota for overlapping range (so that we can
-// simply compare written bytes against the adjusted quota).
+// Adjust the |quota| value to make the remaining quota calculation easier. This
+// allows us to simply compare written bytes against the adjusted quota.
int64_t AdjustQuotaForOverlap(int64_t quota,
int64_t file_offset,
int64_t file_size) {
- DCHECK_LE(file_offset, file_size);
if (quota < 0)
quota = 0;
+ // |overlap| can be negative if |file_offset| is past the end of the file.
+ // Negative |overlap| ensures null bytes between the end of the file and the
+ // |file_offset| are counted towards the file's quota.
int64_t overlap = file_size - file_offset;
- if (std::numeric_limits<int64_t>::max() - overlap > quota)
+ if (overlap < 0 || std::numeric_limits<int64_t>::max() - overlap > quota)
quota += overlap;
return quota;
}
@@ -102,8 +103,9 @@ int SandboxFileStreamWriter::WriteInternal(net::IOBuffer* buf, int buf_len) {
DCHECK(total_bytes_written_ <= allowed_bytes_to_write_ ||
allowed_bytes_to_write_ < 0);
if (total_bytes_written_ >= allowed_bytes_to_write_) {
- has_pending_operation_ = false;
- return net::ERR_FILE_NO_SPACE;
+ const int out_of_quota = net::ERR_FILE_NO_SPACE;
+ DidWrite(out_of_quota);
+ return out_of_quota;
}
if (buf_len > allowed_bytes_to_write_ - total_bytes_written_)
@@ -139,11 +141,7 @@ void SandboxFileStreamWriter::DidCreateSnapshotFile(
return;
}
file_size_ = file_info.size;
- if (initial_offset_ > file_size_) {
- // We should not be writing past 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()) {
@@ -177,9 +175,10 @@ void SandboxFileStreamWriter::DidCreateSnapshotFile(
return;
}
- DCHECK(quota_manager_proxy->quota_manager());
- quota_manager_proxy->quota_manager()->GetUsageAndQuota(
+ DCHECK(quota_manager_proxy);
+ quota_manager_proxy->GetUsageAndQuota(
url_.origin(), FileSystemTypeToQuotaStorageType(url_.type()),
+ base::SequencedTaskRunnerHandle::Get(),
base::BindOnce(&SandboxFileStreamWriter::DidGetUsageAndQuota,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
@@ -226,17 +225,24 @@ void SandboxFileStreamWriter::DidWrite(int write_response) {
if (write_response <= 0) {
// TODO(crbug.com/1091792): Consider listening explicitly for out
// of space errors instead of surfacing all write errors to quota.
- file_system_context_->quota_manager_proxy()->NotifyWriteFailed(
- url_.origin());
+ QuotaManagerProxy* quota_manager_proxy =
+ file_system_context_->quota_manager_proxy();
+ if (quota_manager_proxy) {
+ quota_manager_proxy->NotifyWriteFailed(url_.origin());
+ }
if (CancelIfRequested())
return;
- std::move(write_callback_).Run(write_response);
+ if (write_callback_)
+ std::move(write_callback_).Run(write_response);
return;
}
if (total_bytes_written_ + write_response + initial_offset_ > file_size_) {
int overlapped = file_size_ - total_bytes_written_ - initial_offset_;
- if (overlapped < 0)
+ // If writing past the end of a file, the distance seeked past the file
+ // needs to be accounted for. This adjustment should only be made for the
+ // first such write (when |total_bytes_written_| is 0).
+ if (overlapped < 0 && total_bytes_written_ != 0)
overlapped = 0;
observers_.Notify(&FileUpdateObserver::OnUpdate, url_,
write_response - overlapped);
diff --git a/chromium/storage/browser/file_system/sandbox_file_stream_writer.h b/chromium/storage/browser/file_system/sandbox_file_stream_writer.h
index 3fc751e101e..ed4414b78a1 100644
--- a/chromium/storage/browser/file_system/sandbox_file_stream_writer.h
+++ b/chromium/storage/browser/file_system/sandbox_file_stream_writer.h
@@ -47,6 +47,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) SandboxFileStreamWriter
private:
// Performs quota calculation and calls file_writer_->Write().
+ // Will either return synchronously, or run asynchronously and call
+ // |write_callback_|.
int WriteInternal(net::IOBuffer* buf, int buf_len);
// Callbacks that are chained for the first write. This eventually calls
@@ -62,6 +64,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) SandboxFileStreamWriter
int64_t quota);
void DidInitializeForWrite(net::IOBuffer* buf, int buf_len, int init_status);
+ // Will call |write_callback_| if set, or return synchronously.
void DidWrite(int write_response);
void DidFlush(net::CompletionOnceCallback callback, int result);
diff --git a/chromium/storage/browser/file_system/sandbox_file_stream_writer_unittest.cc b/chromium/storage/browser/file_system/sandbox_file_stream_writer_unittest.cc
index f88ef6970f7..8678c9f22ca 100644
--- a/chromium/storage/browser/file_system/sandbox_file_stream_writer_unittest.cc
+++ b/chromium/storage/browser/file_system/sandbox_file_stream_writer_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "storage/browser/file_system/sandbox_file_stream_writer.h"
+#include "base/test/bind.h"
#include "storage/browser/file_system/file_stream_writer_test.h"
#include <stdint.h>
@@ -22,6 +23,8 @@
#include "storage/browser/file_system/file_stream_writer.h"
#include "storage/browser/file_system/file_system_context.h"
#include "storage/browser/test/async_file_test_helper.h"
+#include "storage/browser/test/mock_quota_manager_proxy.h"
+#include "storage/browser/test/mock_special_storage_policy.h"
#include "storage/browser/test/test_file_system_context.h"
#include "storage/common/file_system/file_system_types.h"
@@ -38,7 +41,14 @@ class SandboxFileStreamWriterTest : public FileStreamWriterTest {
void SetUp() override {
ASSERT_TRUE(dir_.CreateUniqueTempDir());
- file_system_context_ = CreateFileSystemContext(dir_);
+ quota_manager_ = base::MakeRefCounted<storage::MockQuotaManager>(
+ is_incognito(), dir_.GetPath(), base::ThreadTaskRunnerHandle::Get(),
+ nullptr);
+ quota_manager_proxy_ = base::MakeRefCounted<storage::MockQuotaManagerProxy>(
+ quota_manager_.get(), base::ThreadTaskRunnerHandle::Get().get());
+
+ file_system_context_ =
+ CreateFileSystemContext(quota_manager_proxy_.get(), dir_);
file_system_context_->OpenFileSystem(
url::Origin::Create(GURL(kURLOrigin)), kFileSystemTypeTemporary,
@@ -47,20 +57,38 @@ class SandboxFileStreamWriterTest : public FileStreamWriterTest {
base::File::Error result) {
ASSERT_EQ(base::File::FILE_OK, result);
}));
+
+ SetQuota(1024 * 1024 * 100);
base::RunLoop().RunUntilIdle();
}
- void TearDown() override { base::RunLoop().RunUntilIdle(); }
+ void TearDown() override {
+ quota_manager_proxy_->SimulateQuotaManagerDestroyed();
+ quota_manager_.reset();
+ base::RunLoop().RunUntilIdle();
+ }
protected:
base::ScopedTempDir dir_;
scoped_refptr<FileSystemContext> file_system_context_;
+ scoped_refptr<MockQuotaManager> quota_manager_;
+ scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
+
+ struct quota_usage_and_info {
+ blink::mojom::QuotaStatusCode status;
+ int64_t usage;
+ int64_t quota;
+ };
virtual FileSystemContext* CreateFileSystemContext(
+ QuotaManagerProxy* quota_manager_proxy,
const base::ScopedTempDir& dir) {
- return CreateFileSystemContextForTesting(nullptr, dir.GetPath());
+ return CreateFileSystemContextForTesting(quota_manager_proxy,
+ dir.GetPath());
}
+ virtual bool is_incognito() { return false; }
+
FileSystemURL GetFileSystemURL(const std::string& file_name) {
return file_system_context_->CreateCrackedFileSystemURL(
url::Origin::Create(GURL(kURLOrigin)), kFileSystemTypeTemporary,
@@ -107,8 +135,181 @@ class SandboxFileStreamWriterTest : public FileStreamWriterTest {
return content;
}
+
+ std::unique_ptr<SandboxFileStreamWriter> CreateSandboxWriter(
+ const std::string& name,
+ int64_t offset) {
+ auto writer = std::make_unique<SandboxFileStreamWriter>(
+ file_system_context_.get(), GetFileSystemURL(name), offset,
+ *file_system_context_->GetUpdateObservers(kFileSystemTypeTemporary));
+ return writer;
+ }
+
+ quota_usage_and_info GetUsageAndQuotaSync() {
+ quota_usage_and_info info;
+ quota_manager_->GetUsageAndQuota(
+ url::Origin::Create(GURL(kURLOrigin)),
+ blink::mojom::StorageType::kTemporary,
+ base::BindLambdaForTesting([&](blink::mojom::QuotaStatusCode status,
+ int64_t usage, int64_t quota) {
+ info.status = status;
+ info.usage = usage;
+ info.quota = quota;
+ }));
+ return info;
+ }
+
+ void SetQuota(int64_t quota) {
+ quota_manager_->SetQuota(url::Origin::Create(GURL(kURLOrigin)),
+ blink::mojom::StorageType::kTemporary, quota);
+ }
+
+ int64_t GetFreeQuota() {
+ auto info = GetUsageAndQuotaSync();
+ return info.quota - info.usage;
+ }
+
+ void SetFreeQuota(int64_t free_quota) {
+ auto info = GetUsageAndQuotaSync();
+ SetQuota(info.usage + free_quota);
+ }
+
+ void Test_Quota_OK() {
+ std::string name = "file_a";
+ EXPECT_TRUE(CreateFileWithContent(name, "foo"));
+
+ SetFreeQuota(7);
+ std::unique_ptr<SandboxFileStreamWriter> writer(
+ CreateSandboxWriter(name, 3));
+ EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "xxx"));
+ writer.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(FilePathExists(name));
+ EXPECT_EQ(std::string("fooxxx", 6), GetFileContent(name));
+ EXPECT_EQ(GetFreeQuota(), 4);
+ }
+
+ void Test_Quota_WritePastEnd() {
+ std::string name = "file_a";
+ EXPECT_TRUE(CreateFileWithContent(name, "foo"));
+
+ SetFreeQuota(6);
+ std::unique_ptr<SandboxFileStreamWriter> writer(
+ CreateSandboxWriter(name, 6));
+ EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "xxx"));
+ writer.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(FilePathExists(name));
+ EXPECT_EQ(std::string("foo\0\0\0xxx", 9), GetFileContent(name));
+ EXPECT_EQ(GetFreeQuota(), 0);
+ }
+
+ void Test_Quota_NoSpace() {
+ std::string name = "file_a";
+ EXPECT_TRUE(CreateFileWithContent(name, "foo"));
+
+ SetFreeQuota(0);
+ std::unique_ptr<SandboxFileStreamWriter> writer(
+ CreateSandboxWriter(name, 3));
+ EXPECT_EQ(net::ERR_FILE_NO_SPACE, WriteStringToWriter(writer.get(), "xxx"));
+ writer.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(FilePathExists(name));
+ EXPECT_EQ(std::string("foo", 3), GetFileContent(name));
+ EXPECT_EQ(GetFreeQuota(), 0);
+ }
+
+ void Test_Quota_NoSpace_PartialWrite() {
+ std::string name = "file_a";
+ EXPECT_TRUE(CreateFileWithContent(name, "foo"));
+
+ SetFreeQuota(5);
+ std::unique_ptr<SandboxFileStreamWriter> writer(
+ CreateSandboxWriter(name, 6));
+ EXPECT_EQ(net::ERR_FILE_NO_SPACE, WriteStringToWriter(writer.get(), "xxx"));
+ writer.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(FilePathExists(name));
+ EXPECT_EQ(std::string("foo\0\0\0xx", 8), GetFileContent(name));
+ EXPECT_EQ(GetFreeQuota(), 0);
+ }
+
+ void Test_Quota_Negative() {
+ std::string name = "file_a";
+ EXPECT_TRUE(CreateFileWithContent(name, "foo"));
+
+ SetFreeQuota(-1);
+ std::unique_ptr<SandboxFileStreamWriter> writer(
+ CreateSandboxWriter(name, 3));
+ EXPECT_EQ(net::ERR_FILE_NO_SPACE, WriteStringToWriter(writer.get(), "xxx"));
+ writer.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(FilePathExists(name));
+ EXPECT_EQ(std::string("foo", 3), GetFileContent(name));
+ EXPECT_EQ(GetFreeQuota(), -1);
+ }
+
+ void Test_Quota_WritePastEndTwice_OK() {
+ std::string name = "file_a";
+ EXPECT_TRUE(CreateFileWithContent(name, "foo"));
+
+ SetFreeQuota(9);
+ std::unique_ptr<SandboxFileStreamWriter> writer(
+ CreateSandboxWriter(name, 6));
+ EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "xxx"));
+ EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "yyy"));
+ writer.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(FilePathExists(name));
+ EXPECT_EQ(std::string("foo\0\0\0xxxyyy", 12), GetFileContent(name));
+ EXPECT_EQ(GetFreeQuota(), 0);
+ }
+
+ void Test_Quota_WritePastEndTwice_NoSpace() {
+ std::string name = "file_a";
+ EXPECT_TRUE(CreateFileWithContent(name, "foo"));
+
+ SetFreeQuota(7);
+ std::unique_ptr<SandboxFileStreamWriter> writer(
+ CreateSandboxWriter(name, 6));
+ EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "xxx"));
+ EXPECT_EQ(net::ERR_FILE_NO_SPACE, WriteStringToWriter(writer.get(), "yyy"));
+ writer.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(FilePathExists(name));
+ EXPECT_EQ(std::string("foo\0\0\0xxxy", 10), GetFileContent(name));
+ EXPECT_EQ(GetFreeQuota(), 0);
+ }
};
+TEST_F(SandboxFileStreamWriterTest, Quota_OK) {
+ Test_Quota_OK();
+}
+
+TEST_F(SandboxFileStreamWriterTest, Quota_WritePastEnd) {
+ Test_Quota_WritePastEnd();
+}
+
+TEST_F(SandboxFileStreamWriterTest, Quota_NoSpace) {
+ Test_Quota_NoSpace();
+}
+
+TEST_F(SandboxFileStreamWriterTest, Quota_NoSpace_PartialWrite) {
+ Test_Quota_NoSpace_PartialWrite();
+}
+
+TEST_F(SandboxFileStreamWriterTest, Quota_Negative) {
+ Test_Quota_Negative();
+}
+
+TEST_F(SandboxFileStreamWriterTest, Quota_WritePastEndTwice_OK) {
+ Test_Quota_WritePastEndTwice_OK();
+}
+
+TEST_F(SandboxFileStreamWriterTest, Quota_WritePastEndTwice_NoSpace) {
+ Test_Quota_WritePastEndTwice_NoSpace();
+}
+
INSTANTIATE_TYPED_TEST_SUITE_P(Sandbox,
FileStreamWriterTypedTest,
SandboxFileStreamWriterTest);
@@ -120,13 +321,45 @@ class SandboxFileStreamWriterIncognitoTest
protected:
FileSystemContext* CreateFileSystemContext(
+ QuotaManagerProxy* quota_manager_proxy,
const base::ScopedTempDir& dir) override {
return CreateIncognitoFileSystemContextForTesting(
base::ThreadTaskRunnerHandle::Get(),
- base::ThreadTaskRunnerHandle::Get(), nullptr, dir.GetPath());
+ base::ThreadTaskRunnerHandle::Get(), quota_manager_proxy,
+ dir.GetPath());
}
+
+ bool is_incognito() override { return true; }
};
+TEST_F(SandboxFileStreamWriterIncognitoTest, Quota_OK) {
+ Test_Quota_OK();
+}
+
+TEST_F(SandboxFileStreamWriterIncognitoTest, Quota_WritePastEnd) {
+ Test_Quota_WritePastEnd();
+}
+
+TEST_F(SandboxFileStreamWriterIncognitoTest, Quota_NoSpace) {
+ Test_Quota_NoSpace();
+}
+
+TEST_F(SandboxFileStreamWriterIncognitoTest, Quota_NoSpace_PartialWrite) {
+ Test_Quota_NoSpace_PartialWrite();
+}
+
+TEST_F(SandboxFileStreamWriterIncognitoTest, Quota_Negative) {
+ Test_Quota_Negative();
+}
+
+TEST_F(SandboxFileStreamWriterIncognitoTest, Quota_WritePastEndTwice_OK) {
+ Test_Quota_WritePastEndTwice_OK();
+}
+
+TEST_F(SandboxFileStreamWriterIncognitoTest, Quota_WritePastEndTwice_NoSpace) {
+ Test_Quota_WritePastEndTwice_NoSpace();
+}
+
INSTANTIATE_TYPED_TEST_SUITE_P(SandboxIncognito,
FileStreamWriterTypedTest,
SandboxFileStreamWriterIncognitoTest);
diff --git a/chromium/storage/browser/file_system/sandbox_file_system_backend_delegate.cc b/chromium/storage/browser/file_system/sandbox_file_system_backend_delegate.cc
index 17a9a301c67..b6cd5b58fd0 100644
--- a/chromium/storage/browser/file_system/sandbox_file_system_backend_delegate.cc
+++ b/chromium/storage/browser/file_system/sandbox_file_system_backend_delegate.cc
@@ -13,11 +13,12 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
+#include "base/containers/contains.h"
#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
#include "base/task_runner_util.h"
+#include "base/time/time.h"
#include "storage/browser/file_system/async_file_util_adapter.h"
#include "storage/browser/file_system/file_stream_reader.h"
#include "storage/browser/file_system/file_system_context.h"
@@ -113,17 +114,17 @@ class SandboxObfuscatedOriginEnumerator
std::unique_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enum_;
};
-void OpenSandboxFileSystemOnFileTaskRunner(ObfuscatedFileUtil* file_util,
- const GURL& origin_url,
- FileSystemType type,
- OpenFileSystemMode mode,
- base::File::Error* error_ptr) {
- DCHECK(error_ptr);
+base::File::Error OpenSandboxFileSystemOnFileTaskRunner(
+ ObfuscatedFileUtil* file_util,
+ const GURL& origin_url,
+ FileSystemType type,
+ OpenFileSystemMode mode) {
const bool create = (mode == OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT);
+ base::File::Error error;
file_util->GetDirectoryForOriginAndType(
url::Origin::Create(origin_url),
- SandboxFileSystemBackendDelegate::GetTypeString(type), create, error_ptr);
- if (*error_ptr != base::File::FILE_OK) {
+ SandboxFileSystemBackendDelegate::GetTypeString(type), create, &error);
+ if (error != base::File::FILE_OK) {
UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel, kCreateDirectoryError,
kFileSystemErrorMax);
} else {
@@ -132,18 +133,20 @@ void OpenSandboxFileSystemOnFileTaskRunner(ObfuscatedFileUtil* file_util,
// The reference of file_util will be derefed on the FILE thread
// when the storage of this callback gets deleted regardless of whether
// this method is called or not.
+
+ return error;
}
void DidOpenFileSystem(
base::WeakPtr<SandboxFileSystemBackendDelegate> delegate,
base::OnceClosure quota_callback,
base::OnceCallback<void(base::File::Error error)> callback,
- base::File::Error* error) {
+ base::File::Error error) {
if (delegate)
- delegate->CollectOpenFileSystemMetrics(*error);
- if (*error == base::File::FILE_OK)
+ delegate->CollectOpenFileSystemMetrics(error);
+ if (error == base::File::FILE_OK)
std::move(quota_callback).Run();
- std::move(callback).Run(*error);
+ std::move(callback).Run(error);
}
template <typename T>
@@ -186,20 +189,22 @@ SandboxFileSystemBackendDelegate::SandboxFileSystemBackendDelegate(
: file_task_runner_(file_task_runner),
quota_manager_proxy_(quota_manager_proxy),
sandbox_file_util_(std::make_unique<AsyncFileUtilAdapter>(
- new ObfuscatedFileUtil(special_storage_policy,
- profile_path.Append(kFileSystemDirectory),
- env_override,
- base::BindRepeating(&GetTypeStringForURL),
- GetKnownTypeStrings(),
- this,
- file_system_options.is_incognito()))),
+ std::make_unique<ObfuscatedFileUtil>(
+ special_storage_policy,
+ profile_path.Append(kFileSystemDirectory),
+ env_override,
+ base::BindRepeating(&GetTypeStringForURL),
+ GetKnownTypeStrings(),
+ this,
+ file_system_options.is_incognito()))),
file_system_usage_cache_(std::make_unique<FileSystemUsageCache>(
file_system_options.is_incognito())),
- quota_observer_(new SandboxQuotaObserver(quota_manager_proxy,
- file_task_runner,
- obfuscated_file_util(),
- usage_cache())),
- quota_reservation_manager_(new QuotaReservationManager(
+ quota_observer_(
+ std::make_unique<SandboxQuotaObserver>(quota_manager_proxy,
+ file_task_runner,
+ obfuscated_file_util(),
+ usage_cache())),
+ quota_reservation_manager_(std::make_unique<QuotaReservationManager>(
std::make_unique<QuotaBackendImpl>(file_task_runner_.get(),
obfuscated_file_util(),
usage_cache(),
@@ -270,19 +275,17 @@ void SandboxFileSystemBackendDelegate::OpenFileSystem(
(quota_manager_proxy_.get())
? base::BindOnce(&QuotaManagerProxy::NotifyStorageAccessed,
quota_manager_proxy_, origin,
- FileSystemTypeToQuotaStorageType(type))
+ FileSystemTypeToQuotaStorageType(type),
+ base::Time::Now())
: base::DoNothing();
- base::File::Error* error_ptr = new base::File::Error;
- file_task_runner_->PostTaskAndReply(
+ file_task_runner_->PostTaskAndReplyWithResult(
FROM_HERE,
base::BindOnce(&OpenSandboxFileSystemOnFileTaskRunner,
- obfuscated_file_util(), origin.GetURL(), type, mode,
- base::Unretained(error_ptr)),
+ obfuscated_file_util(), origin.GetURL(), type, mode),
base::BindOnce(&DidOpenFileSystem, weak_factory_.GetWeakPtr(),
std::move(quota_callback),
- base::BindOnce(std::move(callback), root_url, name),
- base::Owned(error_ptr)));
+ base::BindOnce(std::move(callback), root_url, name)));
DETACH_FROM_THREAD(io_thread_checker_);
is_filesystem_opened_ = true;
@@ -302,8 +305,8 @@ SandboxFileSystemBackendDelegate::CreateFileSystemOperationContext(
const ChangeObserverList* change_observers = GetChangeObservers(url.type());
DCHECK(update_observers);
- std::unique_ptr<FileSystemOperationContext> operation_context(
- new FileSystemOperationContext(context));
+ auto operation_context =
+ std::make_unique<FileSystemOperationContext>(context);
operation_context->set_update_observers(*update_observers);
operation_context->set_change_observers(
change_observers ? *change_observers : ChangeObserverList());
@@ -351,8 +354,8 @@ SandboxFileSystemBackendDelegate::DeleteOriginDataOnFileTaskRunner(
origin, GetTypeString(type));
if (result && proxy && usage) {
proxy->NotifyStorageModified(QuotaClientType::kFileSystem, origin,
- FileSystemTypeToQuotaStorageType(type),
- -usage);
+ FileSystemTypeToQuotaStorageType(type), -usage,
+ base::Time::Now());
}
if (result)
diff --git a/chromium/storage/browser/file_system/sandbox_file_system_backend_delegate_unittest.cc b/chromium/storage/browser/file_system/sandbox_file_system_backend_delegate_unittest.cc
index 48a2098f1e2..b480ff2e4a6 100644
--- a/chromium/storage/browser/file_system/sandbox_file_system_backend_delegate_unittest.cc
+++ b/chromium/storage/browser/file_system/sandbox_file_system_backend_delegate_unittest.cc
@@ -37,7 +37,7 @@ class SandboxFileSystemBackendDelegateTest : public testing::Test {
void SetUp() override {
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
quota_manager_proxy_ = base::MakeRefCounted<MockQuotaManagerProxy>(
- nullptr, base::ThreadTaskRunnerHandle::Get().get());
+ nullptr, base::ThreadTaskRunnerHandle::Get());
delegate_ = std::make_unique<SandboxFileSystemBackendDelegate>(
quota_manager_proxy_.get(), base::ThreadTaskRunnerHandle::Get().get(),
data_dir_.GetPath(), /*special_storage_policy=*/nullptr,
diff --git a/chromium/storage/browser/file_system/sandbox_file_system_backend_unittest.cc b/chromium/storage/browser/file_system/sandbox_file_system_backend_unittest.cc
index 7e029cb8f69..52d6d9f74d2 100644
--- a/chromium/storage/browser/file_system/sandbox_file_system_backend_unittest.cc
+++ b/chromium/storage/browser/file_system/sandbox_file_system_backend_unittest.cc
@@ -91,16 +91,16 @@ class SandboxFileSystemBackendTest
void SetUpNewDelegate(const FileSystemOptions& options) {
incognito_env_override_ = leveldb_chrome::NewMemEnv("FileSystem");
- delegate_.reset(new SandboxFileSystemBackendDelegate(
+ delegate_ = std::make_unique<SandboxFileSystemBackendDelegate>(
nullptr /* quota_manager_proxy */,
base::ThreadTaskRunnerHandle::Get().get(), data_dir_.GetPath(),
nullptr /* special_storage_policy */, options,
- options.is_in_memory() ? incognito_env_override_.get() : nullptr));
+ options.is_in_memory() ? incognito_env_override_.get() : nullptr);
}
void SetUpNewBackend(const FileSystemOptions& options) {
SetUpNewDelegate(options);
- backend_.reset(new SandboxFileSystemBackend(delegate_.get()));
+ backend_ = std::make_unique<SandboxFileSystemBackend>(delegate_.get());
}
SandboxFileSystemBackendDelegate::OriginEnumerator* CreateOriginEnumerator()
diff --git a/chromium/storage/browser/file_system/sandbox_origin_database_unittest.cc b/chromium/storage/browser/file_system/sandbox_origin_database_unittest.cc
index a52ab31858b..f9b1aa4e493 100644
--- a/chromium/storage/browser/file_system/sandbox_origin_database_unittest.cc
+++ b/chromium/storage/browser/file_system/sandbox_origin_database_unittest.cc
@@ -208,8 +208,7 @@ TEST(SandboxOriginDatabaseTest, DatabaseRecoveryTest) {
"hoge.example.com", "fuga.example.com",
};
- std::unique_ptr<SandboxOriginDatabase> database(
- new SandboxOriginDatabase(kFSDir, nullptr));
+ auto database = std::make_unique<SandboxOriginDatabase>(kFSDir, nullptr);
for (size_t i = 0; i < base::size(kOrigins); ++i) {
base::FilePath path;
EXPECT_FALSE(database->HasOriginPath(kOrigins[i]));
@@ -238,7 +237,7 @@ TEST(SandboxOriginDatabaseTest, DatabaseRecoveryTest) {
CorruptDatabase(kDBDir, leveldb::kLogFile, -1, 1);
base::FilePath path;
- database.reset(new SandboxOriginDatabase(kFSDir, nullptr));
+ database = std::make_unique<SandboxOriginDatabase>(kFSDir, nullptr);
std::vector<SandboxOriginDatabase::OriginRecord> origins_in_db;
EXPECT_TRUE(database->ListAllOrigins(&origins_in_db));
@@ -274,8 +273,7 @@ TEST(SandboxOriginDatabaseTest, DatabaseRecoveryForMissingDBFileTest) {
const std::string kOrigin = "foo.example.com";
base::FilePath path;
- std::unique_ptr<SandboxOriginDatabase> database(
- new SandboxOriginDatabase(kFSDir, nullptr));
+ auto database = std::make_unique<SandboxOriginDatabase>(kFSDir, nullptr);
EXPECT_FALSE(database->HasOriginPath(kOrigin));
EXPECT_TRUE(database->GetPathForOrigin(kOrigin, &path));
EXPECT_FALSE(path.empty());
@@ -285,7 +283,7 @@ TEST(SandboxOriginDatabaseTest, DatabaseRecoveryForMissingDBFileTest) {
DeleteDatabaseFile(kDBDir, file_type);
- database.reset(new SandboxOriginDatabase(kFSDir, nullptr));
+ database = std::make_unique<SandboxOriginDatabase>(kFSDir, nullptr);
std::vector<SandboxOriginDatabase::OriginRecord> origins_in_db;
EXPECT_TRUE(database->ListAllOrigins(&origins_in_db));
diff --git a/chromium/storage/browser/file_system/sandbox_prioritized_origin_database.cc b/chromium/storage/browser/file_system/sandbox_prioritized_origin_database.cc
index 5c46bff3601..d364b549cde 100644
--- a/chromium/storage/browser/file_system/sandbox_prioritized_origin_database.cc
+++ b/chromium/storage/browser/file_system/sandbox_prioritized_origin_database.cc
@@ -4,6 +4,8 @@
#include "storage/browser/file_system/sandbox_prioritized_origin_database.h"
+#include <memory>
+
#include "base/check.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
@@ -65,8 +67,10 @@ bool SandboxPrioritizedOriginDatabase::InitializePrimaryOrigin(
if (!primary_origin_database_ && !is_in_memory) {
if (!MaybeLoadPrimaryOrigin() && ResetPrimaryOrigin(origin)) {
MaybeMigrateDatabase(origin);
- primary_origin_database_.reset(new SandboxIsolatedOriginDatabase(
- origin, file_system_directory_, base::FilePath(kPrimaryDirectory)));
+ primary_origin_database_ =
+ std::make_unique<SandboxIsolatedOriginDatabase>(
+ origin, file_system_directory_,
+ base::FilePath(kPrimaryDirectory));
return true;
}
}
@@ -151,8 +155,8 @@ bool SandboxPrioritizedOriginDatabase::MaybeLoadPrimaryOrigin() {
std::string saved_origin;
if (!ReadPrimaryOriginFile(primary_origin_file_, &saved_origin))
return false;
- primary_origin_database_.reset(new SandboxIsolatedOriginDatabase(
- saved_origin, file_system_directory_, base::FilePath(kPrimaryDirectory)));
+ primary_origin_database_ = std::make_unique<SandboxIsolatedOriginDatabase>(
+ saved_origin, file_system_directory_, base::FilePath(kPrimaryDirectory));
return true;
}
@@ -207,8 +211,8 @@ void SandboxPrioritizedOriginDatabase::MaybeInitializeNonPrimaryDatabase(
if (origin_database_)
return;
- origin_database_.reset(
- new SandboxOriginDatabase(file_system_directory_, env_override_));
+ origin_database_ = std::make_unique<SandboxOriginDatabase>(
+ file_system_directory_, env_override_);
if (!create && !base::DirectoryExists(origin_database_->GetDatabasePath())) {
origin_database_.reset();
return;
diff --git a/chromium/storage/browser/file_system/sandbox_quota_observer.cc b/chromium/storage/browser/file_system/sandbox_quota_observer.cc
index 894f56cbd3a..10b0616eb76 100644
--- a/chromium/storage/browser/file_system/sandbox_quota_observer.cc
+++ b/chromium/storage/browser/file_system/sandbox_quota_observer.cc
@@ -42,7 +42,7 @@ void SandboxQuotaObserver::OnUpdate(const FileSystemURL& url, int64_t delta) {
if (quota_manager_proxy_.get()) {
quota_manager_proxy_->NotifyStorageModified(
QuotaClientType::kFileSystem, url.origin(),
- FileSystemTypeToQuotaStorageType(url.type()), delta);
+ FileSystemTypeToQuotaStorageType(url.type()), delta, base::Time::Now());
}
base::FilePath usage_file_path = GetUsageCachePath(url);
@@ -78,7 +78,8 @@ void SandboxQuotaObserver::OnEndUpdate(const FileSystemURL& url) {
void SandboxQuotaObserver::OnAccess(const FileSystemURL& url) {
if (quota_manager_proxy_.get()) {
quota_manager_proxy_->NotifyStorageAccessed(
- url.origin(), FileSystemTypeToQuotaStorageType(url.type()));
+ url.origin(), FileSystemTypeToQuotaStorageType(url.type()),
+ base::Time::Now());
}
}
diff --git a/chromium/storage/browser/quota/README.md b/chromium/storage/browser/quota/README.md
new file mode 100644
index 00000000000..b1f532f9ec6
--- /dev/null
+++ b/chromium/storage/browser/quota/README.md
@@ -0,0 +1,78 @@
+# Overview
+
+The quota system's primary role is to set and enforce limits on disk usage at
+both the browser level, and at the origin level (see ./quota_settings.cc for
+these limit values). The quota system manages disk usage only for certain web
+platform storage APIs.
+
+In order for a storage backend to integrate with the quota system, it must
+implement the QuotaClient interface.
+
+Most work on the quota system is currently done on the browser process' IO
+thread. There are plans for quota to be moved to [the Storage
+Service](https://docs.google.com/document/d/1v83XKVxnasgf2uNfb_Uc-rfhDa3-ynNP23yU2DWqshI/),
+which will run on its own process on desktop platforms.
+
+# Key Components
+## Interface
+The quota system's interface is comprised of the following classes:
+
+### QuotaManagerImpl
+The "heart" of the quota system. This class lives on the browser
+process' IO thread, but is primarily accessed through QuotaManagerProxy, which
+handles thread hops. In the future, QuotaManagerProxy will turn into
+mojom::QuotaManager, and the quota system will be accessed exclusively via mojo.
+
+### QuotaClient
+This interface must be implemented by any storage backend that wants to
+integrate with the quota system. This is probably the most used interface from
+outside of the quota system.
+
+### PaddingKey
+Helpers for computing quota usage for opaque resources. Features that store
+opaque resources (AppCache, Cache Storage) should use these helpers to avoid
+leaking cross-origin information via the quota usage they report.
+
+### SpecialStoragePolicy
+Hook that allows browser features (currently Extensions and Chrome Apps) to
+change an origin's quota.
+
+## Implementation
+The quota system's implementation is made up of the following components:
+
+### UsageTracker, ClientUsageTracker
+QuotaManagerImpl helpers that distribute tasks (e.g. measure an origin's quota
+usage) across QuotaClient instances, and cache results as needed.
+
+### QuotaDatabase
+Stores persistent information in a per-profile SQLite database. Currently stores
+a few bits of implementation details, and will likely be expanded to cover
+Storage Buckets. The currently stored information is a usage count,
+last-modified-time, and last-accessed-time for each origin (used to implement
+LRU eviction on storage pressure, and Clear Site Data with a time filter), and
+quota granted via the deprecated API
+webkitStorageInfo.requestQuota(PERSISTENT,...).
+
+### QuotaTemporaryStorageEvictor
+Handles eviction and records stats about eviction rounds.
+
+### QuotaTask
+Implementation detail of QuotaManagerImpl.
+
+# Glossary
+
+## Storage Pressure
+A device is said to be under storage pressure when it is close to capacity.
+Storage pressure is used to signal a couple of behaviors in the quota system:
+ - Eviction
+ - The QuotaChange event
+ - Triggering storage pressure UI (implementation specific)
+
+## Eviction
+This is the process by which the quota system cleans up app's data as disk usage
+gets close to the disk's capacity.
+
+# Resources
+ - [Chrome Web Storage and Quota Concepts](https://docs.google.com/document/d/19QemRTdIxYaJ4gkHYf2WWBNPbpuZQDNMpUVf8dQxj4U/)
+ - In-depth description of the quota system that also explains related
+ concepts and legacy APIs that left a mark on quota.
diff --git a/chromium/storage/browser/quota/client_usage_tracker.cc b/chromium/storage/browser/quota/client_usage_tracker.cc
index f06c6a342ba..84b1cbc885c 100644
--- a/chromium/storage/browser/quota/client_usage_tracker.cc
+++ b/chromium/storage/browser/quota/client_usage_tracker.cc
@@ -8,8 +8,8 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/containers/contains.h"
#include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
namespace storage {
diff --git a/chromium/storage/browser/quota/mojo_quota_client_wrapper.cc b/chromium/storage/browser/quota/mojo_quota_client_wrapper.cc
new file mode 100644
index 00000000000..59ea75264d7
--- /dev/null
+++ b/chromium/storage/browser/quota/mojo_quota_client_wrapper.cc
@@ -0,0 +1,71 @@
+// Copyright 2021 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/mojo_quota_client_wrapper.h"
+
+#include <utility>
+
+#include "base/check.h"
+#include "base/sequence_checker.h"
+#include "components/services/storage/public/mojom/quota_client.mojom.h"
+#include "url/origin.h"
+
+namespace storage {
+
+MojoQuotaClientWrapper::MojoQuotaClientWrapper(
+ mojom::QuotaClient* wrapped_client)
+ : wrapped_client_(wrapped_client) {
+ DCHECK(wrapped_client);
+ DETACH_FROM_SEQUENCE(sequence_checker_);
+}
+
+MojoQuotaClientWrapper::~MojoQuotaClientWrapper() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+void MojoQuotaClientWrapper::GetOriginUsage(const url::Origin& origin,
+ blink::mojom::StorageType type,
+ GetOriginUsageCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ wrapped_client_->GetOriginUsage(origin, type, std::move(callback));
+}
+
+void MojoQuotaClientWrapper::GetOriginsForType(
+ blink::mojom::StorageType type,
+ GetOriginsForTypeCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ wrapped_client_->GetOriginsForType(type, std::move(callback));
+}
+
+void MojoQuotaClientWrapper::GetOriginsForHost(
+ blink::mojom::StorageType type,
+ const std::string& host,
+ GetOriginsForHostCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ wrapped_client_->GetOriginsForHost(type, host, std::move(callback));
+}
+
+void MojoQuotaClientWrapper::DeleteOriginData(
+ const url::Origin& origin,
+ blink::mojom::StorageType type,
+ DeleteOriginDataCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ wrapped_client_->DeleteOriginData(origin, type, std::move(callback));
+}
+
+void MojoQuotaClientWrapper::PerformStorageCleanup(
+ blink::mojom::StorageType type,
+ PerformStorageCleanupCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ wrapped_client_->PerformStorageCleanup(type, std::move(callback));
+}
+
+void MojoQuotaClientWrapper::OnQuotaManagerDestroyed() {}
+
+} // namespace storage
diff --git a/chromium/storage/browser/quota/mojo_quota_client_wrapper.h b/chromium/storage/browser/quota/mojo_quota_client_wrapper.h
new file mode 100644
index 00000000000..9b598ed47c0
--- /dev/null
+++ b/chromium/storage/browser/quota/mojo_quota_client_wrapper.h
@@ -0,0 +1,61 @@
+// Copyright 2021 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_MOJO_QUOTA_CLIENT_WRAPPER_H_
+#define STORAGE_BROWSER_QUOTA_MOJO_QUOTA_CLIENT_WRAPPER_H_
+
+#include <string>
+
+#include "base/component_export.h"
+#include "base/sequence_checker.h"
+#include "base/thread_annotations.h"
+#include "components/services/storage/public/mojom/quota_client.mojom.h"
+#include "storage/browser/quota/quota_client.h"
+#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
+
+namespace url {
+class Origin;
+} // namespace url
+
+namespace storage {
+
+// TODO(crbug.com/1163009): Remove this class after all QuotaClients have been
+// mojofied.
+class COMPONENT_EXPORT(STORAGE_BROWSER) MojoQuotaClientWrapper
+ : public storage::QuotaClient {
+ public:
+ // `wrapped_client` must outlive this instance.
+ explicit MojoQuotaClientWrapper(storage::mojom::QuotaClient* wrapped_client);
+
+ MojoQuotaClientWrapper(const MojoQuotaClientWrapper&) = delete;
+ MojoQuotaClientWrapper& operator=(const MojoQuotaClientWrapper&) = delete;
+
+ // QuotaClient.
+ void GetOriginUsage(const url::Origin& origin,
+ blink::mojom::StorageType type,
+ GetOriginUsageCallback callback) override;
+ void GetOriginsForType(blink::mojom::StorageType type,
+ GetOriginsForTypeCallback callback) override;
+ void GetOriginsForHost(blink::mojom::StorageType type,
+ const std::string& host,
+ GetOriginsForHostCallback callback) override;
+ void DeleteOriginData(const url::Origin& origin,
+ blink::mojom::StorageType type,
+ DeleteOriginDataCallback callback) override;
+ void PerformStorageCleanup(blink::mojom::StorageType type,
+ PerformStorageCleanupCallback callback) override;
+ void OnQuotaManagerDestroyed() override;
+
+ private:
+ ~MojoQuotaClientWrapper() override;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ storage::mojom::QuotaClient* const wrapped_client_
+ GUARDED_BY_CONTEXT(sequence_checker_);
+};
+
+} // namespace storage
+
+#endif // STORAGE_BROWSER_QUOTA_MOJO_QUOTA_CLIENT_WRAPPER_H_
diff --git a/chromium/storage/browser/quota/padding_key.h b/chromium/storage/browser/quota/padding_key.h
deleted file mode 100644
index 4b5978a82e7..00000000000
--- a/chromium/storage/browser/quota/padding_key.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2019 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_PADDING_KEY_H_
-#define STORAGE_BROWSER_QUOTA_PADDING_KEY_H_
-
-#include <memory>
-#include <string>
-
-#include "base/component_export.h"
-#include "crypto/symmetric_key.h"
-#include "url/gurl.h"
-
-namespace storage {
-
-COMPONENT_EXPORT(STORAGE_BROWSER)
-const crypto::SymmetricKey* GetDefaultPaddingKey();
-
-// Returns a copy of the default key used to calculate padding sizes.
-//
-// The default padding key is a singleton object whose value is randomly
-// generated the first time it is requested on every browser startup. In
-// CacheStorage, when a cache does not have a padding key, it is assigned the
-// current default key.
-COMPONENT_EXPORT(STORAGE_BROWSER)
-std::unique_ptr<crypto::SymmetricKey> CopyDefaultPaddingKey();
-
-// Builds a key whose value is the given string.
-//
-// May return null if deserializing fails (e.g. if the raw key is the wrong
-// size).
-COMPONENT_EXPORT(STORAGE_BROWSER)
-std::unique_ptr<crypto::SymmetricKey> DeserializePaddingKey(
- const std::string& raw_key);
-
-// Gets the raw value of the default padding key.
-//
-// Each cache stores the raw value of the key that should be used when
-// calculating its padding size.
-COMPONENT_EXPORT(STORAGE_BROWSER)
-std::string SerializeDefaultPaddingKey();
-
-// Resets the default key to a random value.
-//
-// Simulating a key change across a browser restart lets us test that padding
-// calculations are using the appropriate key.
-COMPONENT_EXPORT(STORAGE_BROWSER)
-void ResetPaddingKeyForTesting();
-
-// Computes the padding size for a resource.
-//
-// For AppCache, which does not support storing metadata for a resource,
-// |has_metadata| will always be false.
-//
-// For CacheStorage, the padding size of an entry depends on whether it contains
-// metadata (a.k.a. "side data") and if the response was loaded with
-// credentials. If metadata is added to the entry, the entry must be assigned a
-// new padding size. Otherwise, the growth in the entry's size would leak the
-// exact size of the added metadata.
-COMPONENT_EXPORT(STORAGE_BROWSER)
-int64_t ComputeResponsePadding(const std::string& response_url,
- const crypto::SymmetricKey* padding_key,
- bool has_metadata,
- bool loaded_with_credentials,
- const std::string& request_method);
-
-} // namespace storage
-
-#endif // STORAGE_BROWSER_QUOTA_PADDING_KEY_H_
diff --git a/chromium/storage/browser/quota/quota_callbacks.h b/chromium/storage/browser/quota/quota_callbacks.h
index 4716375a327..f530e4628cb 100644
--- a/chromium/storage/browser/quota/quota_callbacks.h
+++ b/chromium/storage/browser/quota/quota_callbacks.h
@@ -14,9 +14,8 @@
#include <vector>
#include "base/callback.h"
+#include "base/containers/contains.h"
#include "base/optional.h"
-#include "base/stl_util.h"
-#include "storage/browser/quota/quota_client.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom-forward.h"
namespace url {
diff --git a/chromium/storage/browser/quota/quota_client.h b/chromium/storage/browser/quota/quota_client.h
index bd4de1d8e59..9d86a42d497 100644
--- a/chromium/storage/browser/quota/quota_client.h
+++ b/chromium/storage/browser/quota/quota_client.h
@@ -12,76 +12,35 @@
#include "base/callback.h"
#include "base/component_export.h"
+#include "components/services/storage/public/mojom/quota_client.mojom.h"
#include "storage/browser/quota/quota_client_type.h"
-#include "third_party/blink/public/mojom/quota/quota_types.mojom-forward.h"
+#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
#include "url/origin.h"
namespace storage {
-// Interface between each storage API and the quota manager.
+// Interface between the legacy quota clients and the QuotaManager.
//
-// Each storage API must register an implementation of this interface with
-// the quota manager, by calling QuotaManager::RegisterClient().
+// Implementations of this class will be transitioned to inherit from
+// storage::mojom::QuotaClient and talk to the QuotaManager via mojo.
//
-// All the methods will be called on the IO thread in the browser.
+// This inherits from storage::mojom::QuotaClient so that MockQuotaClient
+// instances can be passed to QuotaManger::RegisterLegacyClient(),
+// as well as used via mojo with QuotaManager::RegisterClient().
//
-// When AppCache is deleted, this can become a std::unique_ptr instead
-// of refcounted, and owned by the QuotaManager.
+// TODO(crbug.com/1163009): Remove this class after all QuotaClients have
+// been mojofied.
class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaClient
- : public base::RefCountedThreadSafe<QuotaClient> {
+ : public base::RefCountedThreadSafe<QuotaClient>,
+ public storage::mojom::QuotaClient {
public:
- // The callback aliases precisely follow mojo conventions, because this
- // abstract class will become a mojo interface soon. See crbug.com/1016065.
- using GetOriginUsageCallback = base::OnceCallback<void(int64_t usage)>;
- using GetOriginsForTypeCallback =
- base::OnceCallback<void(const std::vector<url::Origin>& origins)>;
- using GetOriginsForHostCallback =
- base::OnceCallback<void(const std::vector<url::Origin>& origins)>;
- using DeleteOriginDataCallback =
- base::OnceCallback<void(blink::mojom::QuotaStatusCode status)>;
- using PerformStorageCleanupCallback = base::OnceClosure;
-
// Called when the QuotaManager is destroyed.
virtual void OnQuotaManagerDestroyed() = 0;
- // Called by the QuotaManager.
- // Gets the amount of data stored in the storage specified by
- // |origin| and |type|.
- // Note it is safe to fire the callback after the QuotaClient is destructed.
- virtual void GetOriginUsage(const url::Origin& origin,
- blink::mojom::StorageType type,
- GetOriginUsageCallback callback) = 0;
-
- // Called by the QuotaManager.
- // Returns a list of origins that has data in the |type| storage.
- // Note it is safe to fire the callback after the QuotaClient is destructed.
- virtual void GetOriginsForType(blink::mojom::StorageType type,
- GetOriginsForTypeCallback callback) = 0;
-
- // Called by the QuotaManager.
- // Returns a list of origins that match the |host|.
- // Note it is safe to fire the callback after the QuotaClient is destructed.
- virtual void GetOriginsForHost(blink::mojom::StorageType type,
- const std::string& host,
- GetOriginsForHostCallback callback) = 0;
-
- // Called by the QuotaManager.
- // Note it is safe to fire the callback after the QuotaClient is destructed.
- virtual void DeleteOriginData(const url::Origin& origin,
- blink::mojom::StorageType type,
- DeleteOriginDataCallback callback) = 0;
-
- // Called by the QuotaManager.
- // Gives the QuotaClient an opportunity to perform a cleanup step after major
- // deletions.
- virtual void PerformStorageCleanup(
- blink::mojom::StorageType type,
- PerformStorageCleanupCallback callback) = 0;
-
protected:
friend class RefCountedThreadSafe<QuotaClient>;
- virtual ~QuotaClient() = default;
+ ~QuotaClient() override = default;
};
} // namespace storage
diff --git a/chromium/storage/browser/quota/quota_client_type.cc b/chromium/storage/browser/quota/quota_client_type.cc
index a2daaa23b5e..f74f7236f29 100644
--- a/chromium/storage/browser/quota/quota_client_type.cc
+++ b/chromium/storage/browser/quota/quota_client_type.cc
@@ -17,6 +17,7 @@ const QuotaClientTypes& AllQuotaClientTypes() {
QuotaClientType::kServiceWorkerCache,
QuotaClientType::kServiceWorker,
QuotaClientType::kBackgroundFetch,
+ QuotaClientType::kNativeIO,
}};
return *all;
}
diff --git a/chromium/storage/browser/quota/quota_client_type.h b/chromium/storage/browser/quota/quota_client_type.h
index f3c62f8eb5d..c69f2b36df0 100644
--- a/chromium/storage/browser/quota/quota_client_type.h
+++ b/chromium/storage/browser/quota/quota_client_type.h
@@ -22,6 +22,7 @@ enum class QuotaClientType {
kServiceWorker = 5,
kBackgroundFetch = 6,
kAppcache = 7,
+ kNativeIO = 8,
};
// Set of QuotaClientType values.
diff --git a/chromium/storage/browser/quota/quota_database.cc b/chromium/storage/browser/quota/quota_database.cc
index 7322359b68c..6033663757b 100644
--- a/chromium/storage/browser/quota/quota_database.cc
+++ b/chromium/storage/browser/quota/quota_database.cc
@@ -12,9 +12,9 @@
#include "base/auto_reset.h"
#include "base/bind.h"
+#include "base/containers/contains.h"
#include "base/files/file_util.h"
#include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
#include "sql/database.h"
#include "sql/meta_table.h"
#include "sql/statement.h"
@@ -38,21 +38,10 @@ const char kOriginInfoTable[] = "OriginInfoTable";
const char kEvictionInfoTable[] = "EvictionInfoTable";
const char kIsOriginTableBootstrapped[] = "IsOriginTableBootstrapped";
-bool VerifyValidQuotaConfig(const char* key) {
- return (key != nullptr &&
- (!strcmp(key, QuotaDatabase::kDesiredAvailableSpaceKey) ||
- !strcmp(key, QuotaDatabase::kTemporaryQuotaOverrideKey)));
-}
-
const int kCommitIntervalMs = 30000;
} // anonymous namespace
-// static
-const char QuotaDatabase::kDesiredAvailableSpaceKey[] = "DesiredAvailableSpace";
-const char QuotaDatabase::kTemporaryQuotaOverrideKey[] =
- "TemporaryQuotaOverride";
-
const QuotaDatabase::TableSchema QuotaDatabase::kTables[] = {
{kHostQuotaTable,
"(host TEXT NOT NULL,"
@@ -139,12 +128,6 @@ QuotaDatabase::~QuotaDatabase() {
}
}
-void QuotaDatabase::CloseDatabase() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- meta_table_.reset();
- db_.reset();
-}
-
bool QuotaDatabase::GetHostQuota(const std::string& host,
StorageType type,
int64_t* quota) {
@@ -417,22 +400,6 @@ bool QuotaDatabase::DeleteOriginInfo(const url::Origin& origin,
return true;
}
-bool QuotaDatabase::GetQuotaConfigValue(const char* key, int64_t* value) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (!LazyOpen(false))
- return false;
- DCHECK(VerifyValidQuotaConfig(key));
- return meta_table_->GetValue(key, value);
-}
-
-bool QuotaDatabase::SetQuotaConfigValue(const char* key, int64_t value) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (!LazyOpen(true))
- return false;
- DCHECK(VerifyValidQuotaConfig(key));
- return meta_table_->SetValue(key, value);
-}
-
bool QuotaDatabase::GetLRUOrigin(StorageType type,
const std::set<url::Origin>& exceptions,
SpecialStoragePolicy* special_storage_policy,
diff --git a/chromium/storage/browser/quota/quota_database.h b/chromium/storage/browser/quota/quota_database.h
index 64cbe16ec6e..816b4002417 100644
--- a/chromium/storage/browser/quota/quota_database.h
+++ b/chromium/storage/browser/quota/quota_database.h
@@ -33,10 +33,9 @@ class SpecialStoragePolicy;
// 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.
+// Instances are owned by QuotaManagerImpl. There is one instance per
+// QuotaManagerImpl instance. All the methods of this class, except the
+// constructor, must called on the DB thread.
class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDatabase {
public:
struct COMPONENT_EXPORT(STORAGE_BROWSER) OriginInfoTableEntry {
@@ -53,16 +52,10 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDatabase {
base::Time last_modified_time;
};
- // Constants for {Get,Set}QuotaConfigValue keys.
- static const char kDesiredAvailableSpaceKey[];
- static const char kTemporaryQuotaOverrideKey[];
-
// If 'path' is empty, an in memory database will be used.
explicit QuotaDatabase(const base::FilePath& path);
~QuotaDatabase();
- void CloseDatabase();
-
// Returns whether the record could be found.
bool GetHostQuota(const std::string& host,
blink::mojom::StorageType type,
@@ -111,9 +104,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDatabase {
bool DeleteOriginInfo(const url::Origin& origin,
blink::mojom::StorageType type);
- bool GetQuotaConfigValue(const char* key, int64_t* value);
- bool SetQuotaConfigValue(const char* key, int64_t value);
-
// Sets |origin| to the least recently used origin of origins not included
// in |exceptions| and not granted the special unlimited storage right.
// It returns false when it failed in accessing the database.
@@ -207,7 +197,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDatabase {
static base::Time TimeFromSqlValue(int64_t time);
static int64_t TimeToSqlValue(const base::Time& time);
- base::FilePath db_file_path_;
+ const base::FilePath db_file_path_;
std::unique_ptr<sql::Database> db_;
std::unique_ptr<sql::MetaTable> meta_table_;
@@ -217,7 +207,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDatabase {
base::OneShotTimer timer_;
friend class QuotaDatabaseTest;
- friend class QuotaManager;
+ friend class QuotaManagerImpl;
static const TableSchema kTables[];
static const IndexSchema kIndexes[];
diff --git a/chromium/storage/browser/quota/quota_database_unittest.cc b/chromium/storage/browser/quota/quota_database_unittest.cc
index 0310fda6708..f4c8bd611bc 100644
--- a/chromium/storage/browser/quota/quota_database_unittest.cc
+++ b/chromium/storage/browser/quota/quota_database_unittest.cc
@@ -116,36 +116,6 @@ class QuotaDatabaseTest : public testing::Test {
EXPECT_FALSE(db.GetHostQuota(kHost, kPersistent, &quota));
}
- void GlobalQuota(const base::FilePath& kDbFile) {
- QuotaDatabase db(kDbFile);
- ASSERT_TRUE(db.LazyOpen(true));
-
- const char* kTempQuotaKey = QuotaDatabase::kTemporaryQuotaOverrideKey;
- const char* kAvailSpaceKey = QuotaDatabase::kDesiredAvailableSpaceKey;
-
- int64_t value = 0;
- const int64_t kValue1 = 456;
- const int64_t kValue2 = 123000;
- EXPECT_FALSE(db.GetQuotaConfigValue(kTempQuotaKey, &value));
- EXPECT_FALSE(db.GetQuotaConfigValue(kAvailSpaceKey, &value));
-
- EXPECT_TRUE(db.SetQuotaConfigValue(kTempQuotaKey, kValue1));
- EXPECT_TRUE(db.GetQuotaConfigValue(kTempQuotaKey, &value));
- EXPECT_EQ(kValue1, value);
-
- EXPECT_TRUE(db.SetQuotaConfigValue(kTempQuotaKey, kValue2));
- EXPECT_TRUE(db.GetQuotaConfigValue(kTempQuotaKey, &value));
- EXPECT_EQ(kValue2, value);
-
- EXPECT_TRUE(db.SetQuotaConfigValue(kAvailSpaceKey, kValue1));
- EXPECT_TRUE(db.GetQuotaConfigValue(kAvailSpaceKey, &value));
- EXPECT_EQ(kValue1, value);
-
- EXPECT_TRUE(db.SetQuotaConfigValue(kAvailSpaceKey, kValue2));
- EXPECT_TRUE(db.GetQuotaConfigValue(kAvailSpaceKey, &value));
- EXPECT_EQ(kValue2, value);
- }
-
void OriginLastAccessTimeLRU(const base::FilePath& kDbFile) {
QuotaDatabase db(kDbFile);
ASSERT_TRUE(db.LazyOpen(true));
@@ -622,14 +592,6 @@ TEST_F(QuotaDatabaseTest, HostQuota) {
HostQuota(base::FilePath());
}
-TEST_F(QuotaDatabaseTest, GlobalQuota) {
- base::ScopedTempDir data_dir;
- ASSERT_TRUE(data_dir.CreateUniqueTempDir());
- const base::FilePath kDbFile = data_dir.GetPath().AppendASCII(kDBFileName);
- GlobalQuota(kDbFile);
- GlobalQuota(base::FilePath());
-}
-
TEST_F(QuotaDatabaseTest, OriginLastAccessTimeLRU) {
base::ScopedTempDir data_dir;
ASSERT_TRUE(data_dir.CreateUniqueTempDir());
diff --git a/chromium/storage/browser/quota/quota_features.cc b/chromium/storage/browser/quota/quota_features.cc
index b638a01437b..cfb874fbd0f 100644
--- a/chromium/storage/browser/quota/quota_features.cc
+++ b/chromium/storage/browser/quota/quota_features.cc
@@ -8,9 +8,35 @@ namespace storage {
namespace features {
+namespace {
+constexpr int64_t kMBytes = 1024 * 1024;
+} // namespace
+
// Enables Storage Pressure Event.
const base::Feature kStoragePressureEvent{"StoragePressureEvent",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Enables customized storage quota settings for embedders.
+const base::Feature kStorageQuotaSettings{"StorageQuotaSettings",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+constexpr base::FeatureParam<double> kMustRemainAvailableBytes{
+ &kStorageQuotaSettings, "MustRemainAvailableBytes", 1024 * kMBytes /* 1GB */
+};
+constexpr base::FeatureParam<double> kMustRemainAvailableRatio{
+ &kStorageQuotaSettings, "MustRemainAvailableRatio", 0.01 /* 1% */
+};
+constexpr base::FeatureParam<double> kPoolSizeBytes{&kStorageQuotaSettings,
+ "PoolSizeBytes", 0};
+constexpr base::FeatureParam<double> kPoolSizeRatio{
+ &kStorageQuotaSettings, "PoolSizeRatio", 0.8 /* 80% */
+};
+constexpr base::FeatureParam<double> kShouldRemainAvailableBytes{
+ &kStorageQuotaSettings, "ShouldRemainAvailableBytes",
+ 2048 * kMBytes /* 2GB */
+};
+constexpr base::FeatureParam<double> kShouldRemainAvailableRatio{
+ &kStorageQuotaSettings, "ShouldRemainAvailableRatio", 0.1 /* 10% */
+};
+
} // namespace features
} // namespace storage
diff --git a/chromium/storage/browser/quota/quota_features.h b/chromium/storage/browser/quota/quota_features.h
index 2203dd63248..6bf775fdfdb 100644
--- a/chromium/storage/browser/quota/quota_features.h
+++ b/chromium/storage/browser/quota/quota_features.h
@@ -16,6 +16,15 @@ namespace features {
COMPONENT_EXPORT(STORAGE_BROWSER)
extern const base::Feature kStoragePressureEvent;
+COMPONENT_EXPORT(STORAGE_BROWSER)
+extern const base::Feature kStorageQuotaSettings;
+extern const base::FeatureParam<double> kMustRemainAvailableBytes;
+extern const base::FeatureParam<double> kMustRemainAvailableRatio;
+extern const base::FeatureParam<double> kPoolSizeBytes;
+extern const base::FeatureParam<double> kPoolSizeRatio;
+extern const base::FeatureParam<double> kShouldRemainAvailableBytes;
+extern const base::FeatureParam<double> kShouldRemainAvailableRatio;
+
} // namespace features
} // namespace storage
diff --git a/chromium/storage/browser/quota/quota_manager.cc b/chromium/storage/browser/quota/quota_manager.cc
index 4b1d43e3ff6..739f981d98e 100644
--- a/chromium/storage/browser/quota/quota_manager.cc
+++ b/chromium/storage/browser/quota/quota_manager.cc
@@ -1,1968 +1,27 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2021 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/quota_manager.h"
-#include <stddef.h>
-#include <stdint.h>
-
-#include <algorithm>
-#include <functional>
-#include <limits>
-#include <memory>
#include <utility>
-#include "base/barrier_closure.h"
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/macros.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/rand_util.h"
-#include "base/sequence_checker.h"
-#include "base/sequenced_task_runner.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/system/sys_info.h"
-#include "base/task/post_task.h"
-#include "base/task/thread_pool.h"
-#include "base/task_runner_util.h"
-#include "base/threading/thread_restrictions.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "base/trace_event/trace_event.h"
-#include "storage/browser/quota/client_usage_tracker.h"
-#include "storage/browser/quota/quota_client_type.h"
-#include "storage/browser/quota/quota_features.h"
-#include "storage/browser/quota/quota_macros.h"
-#include "storage/browser/quota/quota_manager_proxy.h"
-#include "storage/browser/quota/quota_override_handle.h"
-#include "storage/browser/quota/quota_temporary_storage_evictor.h"
-#include "storage/browser/quota/usage_tracker.h"
-#include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h"
-
-using blink::mojom::StorageType;
-
namespace storage {
-namespace {
-
-constexpr int64_t kReportHistogramInterval = 60 * 60 * 1000; // 1 hour
-
-// Take action on write errors if there is <= 2% disk space
-// available.
-constexpr double kStoragePressureThresholdRatio = 0.02;
-
-// Limit how frequently QuotaManager polls for free disk space when
-// only using that information to identify storage pressure.
-constexpr base::TimeDelta kStoragePressureCheckDiskStatsInterval =
- base::TimeDelta::FromMinutes(5);
-
-// Modifies a given value by a uniformly random amount from
-// -percent to +percent.
-int64_t RandomizeByPercent(int64_t value, int percent) {
- double random_percent = (base::RandDouble() - 0.5) * percent * 2;
- return value * (1 + (random_percent / 100.0));
-}
-} // namespace
-
-// Heuristics: assuming average cloud server allows a few Gigs storage
-// on the server side and the storage needs to be shared for user data
-// and by multiple apps.
-int64_t QuotaManager::kSyncableStorageDefaultHostQuota = 500 * kMBytes;
-
-namespace {
-
-bool IsSupportedType(StorageType type) {
- return type == StorageType::kTemporary || type == StorageType::kPersistent ||
- type == StorageType::kSyncable;
-}
-
-bool IsSupportedIncognitoType(StorageType type) {
- return type == StorageType::kTemporary || type == StorageType::kPersistent;
-}
-
-bool GetPersistentHostQuotaOnDBThread(const std::string& host,
- int64_t* quota,
- QuotaDatabase* database) {
- DCHECK(database);
- database->GetHostQuota(host, StorageType::kPersistent, quota);
- return true;
-}
-
-bool SetPersistentHostQuotaOnDBThread(const std::string& host,
- int64_t* new_quota,
- QuotaDatabase* database) {
- DCHECK(database);
- if (database->SetHostQuota(host, StorageType::kPersistent, *new_quota))
- return true;
- *new_quota = 0;
- return false;
-}
-
-bool GetLRUOriginOnDBThread(StorageType type,
- const std::set<url::Origin>& exceptions,
- SpecialStoragePolicy* policy,
- base::Optional<url::Origin>* origin,
- QuotaDatabase* database) {
- DCHECK(database);
- database->GetLRUOrigin(type, exceptions, policy, origin);
- return true;
-}
-
-bool DeleteOriginInfoOnDBThread(const url::Origin& origin,
- StorageType type,
- bool is_eviction,
- QuotaDatabase* database) {
- DCHECK(database);
-
- base::Time now = base::Time::Now();
-
- if (is_eviction) {
- QuotaDatabase::OriginInfoTableEntry entry;
- database->GetOriginInfo(origin, type, &entry);
- UMA_HISTOGRAM_COUNTS_1M(QuotaManager::kEvictedOriginAccessedCountHistogram,
- entry.used_count);
- UMA_HISTOGRAM_COUNTS_1000(
- QuotaManager::kEvictedOriginDaysSinceAccessHistogram,
- (now - entry.last_access_time).InDays());
- }
-
- if (!database->DeleteOriginInfo(origin, type))
- return false;
-
- // If the deletion is not due to an eviction, delete the entry in the eviction
- // table as well due to privacy concerns.
- if (!is_eviction)
- return database->DeleteOriginLastEvictionTime(origin, type);
-
- base::Time last_eviction_time;
- database->GetOriginLastEvictionTime(origin, type, &last_eviction_time);
-
- if (last_eviction_time != base::Time()) {
- UMA_HISTOGRAM_COUNTS_1000(
- QuotaManager::kDaysBetweenRepeatedOriginEvictionsHistogram,
- (now - last_eviction_time).InDays());
- }
-
- return database->SetOriginLastEvictionTime(origin, type, now);
-}
-
-bool BootstrapDatabaseOnDBThread(std::set<url::Origin> origins,
- QuotaDatabase* database) {
- DCHECK(database);
- if (database->IsOriginDatabaseBootstrapped())
- return true;
-
- // Register existing origins with 0 last time access.
- if (database->RegisterInitialOriginInfo(origins, StorageType::kTemporary)) {
- database->SetOriginDatabaseBootstrapped(true);
- return true;
- }
- return false;
-}
-
-bool UpdateAccessTimeOnDBThread(const url::Origin& origin,
- StorageType type,
- base::Time accessed_time,
- QuotaDatabase* database) {
- DCHECK(database);
- return database->SetOriginLastAccessTime(origin, type, accessed_time);
-}
-
-bool UpdateModifiedTimeOnDBThread(const url::Origin& origin,
- StorageType type,
- base::Time modified_time,
- QuotaDatabase* database) {
- DCHECK(database);
- return database->SetOriginLastModifiedTime(origin, type, modified_time);
-}
-
-void DidGetUsageAndQuotaStripBreakdown(
- QuotaManager::UsageAndQuotaCallback callback,
- blink::mojom::QuotaStatusCode status,
- int64_t usage,
- int64_t quota,
- blink::mojom::UsageBreakdownPtr usage_breakdown) {
- std::move(callback).Run(status, usage, quota);
-}
-
-void DidGetUsageAndQuotaStripOverride(
- QuotaManager::UsageAndQuotaWithBreakdownCallback callback,
- blink::mojom::QuotaStatusCode status,
- int64_t usage,
- int64_t quota,
- bool is_override_enabled,
- blink::mojom::UsageBreakdownPtr usage_breakdown) {
- std::move(callback).Run(status, usage, quota, std::move(usage_breakdown));
-}
-
-} // namespace
-
-constexpr int64_t QuotaManager::kGBytes;
-constexpr int64_t QuotaManager::kNoLimit;
-constexpr int64_t QuotaManager::kPerHostPersistentQuotaLimit;
-constexpr int QuotaManager::kEvictionIntervalInMilliSeconds;
-constexpr int QuotaManager::kThresholdOfErrorsToBeDenylisted;
-constexpr int QuotaManager::kThresholdRandomizationPercent;
-constexpr char QuotaManager::kDatabaseName[];
-constexpr char QuotaManager::kDaysBetweenRepeatedOriginEvictionsHistogram[];
-constexpr char QuotaManager::kEvictedOriginAccessedCountHistogram[];
-constexpr char QuotaManager::kEvictedOriginDaysSinceAccessHistogram[];
-
-QuotaManager::QuotaOverride::QuotaOverride() = default;
-QuotaManager::QuotaOverride::~QuotaOverride() = default;
-
-class QuotaManager::UsageAndQuotaInfoGatherer : public QuotaTask {
- public:
- UsageAndQuotaInfoGatherer(QuotaManager* manager,
- const url::Origin& origin,
- StorageType type,
- bool is_unlimited,
- bool is_session_only,
- bool is_incognito,
- base::Optional<int64_t> quota_override_size,
- UsageAndQuotaForDevtoolsCallback callback)
- : QuotaTask(manager),
- origin_(origin),
- callback_(std::move(callback)),
- type_(type),
- is_unlimited_(is_unlimited),
- is_session_only_(is_session_only),
- is_incognito_(is_incognito),
- is_override_enabled_(quota_override_size.has_value()),
- quota_override_size_(quota_override_size) {}
-
- protected:
- void Run() override {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // Start the async process of gathering the info we need.
- // Gather 4 pieces of info before computing an answer:
- // settings, device_storage_capacity, host_usage, and host_quota.
- base::RepeatingClosure barrier = base::BarrierClosure(
- 4, base::BindOnce(&UsageAndQuotaInfoGatherer::OnBarrierComplete,
- weak_factory_.GetWeakPtr()));
-
- const std::string& host = origin_.host();
-
- manager()->GetQuotaSettings(
- base::BindOnce(&UsageAndQuotaInfoGatherer::OnGotSettings,
- weak_factory_.GetWeakPtr(), barrier));
- manager()->GetStorageCapacity(
- base::BindOnce(&UsageAndQuotaInfoGatherer::OnGotCapacity,
- weak_factory_.GetWeakPtr(), barrier));
- manager()->GetHostUsageWithBreakdown(
- host, type_,
- base::BindOnce(&UsageAndQuotaInfoGatherer::OnGotHostUsage,
- weak_factory_.GetWeakPtr(), barrier));
-
- // Determine host_quota differently depending on type.
- if (is_unlimited_) {
- SetDesiredHostQuota(barrier, blink::mojom::QuotaStatusCode::kOk,
- kNoLimit);
- } else if (type_ == StorageType::kSyncable) {
- SetDesiredHostQuota(barrier, blink::mojom::QuotaStatusCode::kOk,
- kSyncableStorageDefaultHostQuota);
- } else if (type_ == StorageType::kPersistent) {
- manager()->GetPersistentHostQuota(
- host, base::BindOnce(&UsageAndQuotaInfoGatherer::SetDesiredHostQuota,
- weak_factory_.GetWeakPtr(), barrier));
- } else {
- DCHECK_EQ(StorageType::kTemporary, type_);
- // For temporary storage, OnGotSettings will set the host quota.
- }
- }
-
- void Aborted() override {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- weak_factory_.InvalidateWeakPtrs();
- std::move(callback_).Run(blink::mojom::QuotaStatusCode::kErrorAbort,
- /*usage=*/0,
- /*quota=*/0,
- /*is_override_enabled=*/false,
- /*usage_breakdown=*/nullptr);
- DeleteSoon();
- }
-
- void Completed() override {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- weak_factory_.InvalidateWeakPtrs();
-
- int64_t host_quota = quota_override_size_.has_value()
- ? quota_override_size_.value()
- : desired_host_quota_;
- 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_;
- }
- }
-
- std::move(callback_).Run(blink::mojom::QuotaStatusCode::kOk, host_usage_,
- host_quota, is_override_enabled_,
- std::move(host_usage_breakdown_));
- 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) {
- UMA_HISTOGRAM_PERCENTAGE("Quota.PercentUsedByOrigin",
- std::min(100, static_cast<int>((host_usage_ * 100) / host_quota)));
- }
- }
- DeleteSoon();
- }
-
- private:
- QuotaManager* manager() const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return static_cast<QuotaManager*>(observer());
- }
-
- void OnGotSettings(base::RepeatingClosure barrier_closure,
- const QuotaSettings& settings) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- settings_ = settings;
- barrier_closure.Run();
- if (type_ == StorageType::kTemporary && !is_unlimited_) {
- int64_t host_quota = is_session_only_
- ? settings.session_only_per_host_quota
- : settings.per_host_quota;
- SetDesiredHostQuota(barrier_closure, blink::mojom::QuotaStatusCode::kOk,
- host_quota);
- }
- }
-
- void OnGotCapacity(base::OnceClosure barrier_closure,
- int64_t total_space,
- int64_t available_space) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- total_space_ = total_space;
- available_space_ = available_space;
- std::move(barrier_closure).Run();
- }
-
- void OnGotHostUsage(base::OnceClosure barrier_closure,
- int64_t usage,
- blink::mojom::UsageBreakdownPtr usage_breakdown) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- host_usage_ = usage;
- host_usage_breakdown_ = std::move(usage_breakdown);
- std::move(barrier_closure).Run();
- }
-
- void SetDesiredHostQuota(base::OnceClosure barrier_closure,
- blink::mojom::QuotaStatusCode status,
- int64_t quota) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- desired_host_quota_ = quota;
- std::move(barrier_closure).Run();
- }
-
- void OnBarrierComplete() { CallCompleted(); }
-
- const url::Origin origin_;
- QuotaManager::UsageAndQuotaForDevtoolsCallback callback_;
- const StorageType type_;
- const bool is_unlimited_;
- const bool is_session_only_;
- const bool is_incognito_;
- int64_t available_space_ = 0;
- int64_t total_space_ = 0;
- int64_t desired_host_quota_ = 0;
- int64_t host_usage_ = 0;
- const bool is_override_enabled_;
- base::Optional<int64_t> quota_override_size_;
- blink::mojom::UsageBreakdownPtr host_usage_breakdown_;
- QuotaSettings settings_;
- SEQUENCE_CHECKER(sequence_checker_);
-
- // Weak pointers are used to support cancelling work.
- base::WeakPtrFactory<UsageAndQuotaInfoGatherer> weak_factory_{this};
- DISALLOW_COPY_AND_ASSIGN(UsageAndQuotaInfoGatherer);
-};
-
-class QuotaManager::EvictionRoundInfoHelper : public QuotaTask {
- public:
- EvictionRoundInfoHelper(QuotaManager* manager,
- EvictionRoundInfoCallback callback)
- : QuotaTask(manager), callback_(std::move(callback)) {}
-
- protected:
- void Run() override {
- // Gather 2 pieces of info before deciding if we need to get GlobalUsage:
- // settings and device_storage_capacity.
- base::RepeatingClosure barrier = base::BarrierClosure(
- 2, base::BindOnce(&EvictionRoundInfoHelper::OnBarrierComplete,
- weak_factory_.GetWeakPtr()));
-
- manager()->GetQuotaSettings(
- base::BindOnce(&EvictionRoundInfoHelper::OnGotSettings,
- weak_factory_.GetWeakPtr(), barrier));
- manager()->GetStorageCapacity(
- base::BindOnce(&EvictionRoundInfoHelper::OnGotCapacity,
- weak_factory_.GetWeakPtr(), barrier));
- }
-
- void Aborted() override {
- weak_factory_.InvalidateWeakPtrs();
- std::move(callback_).Run(blink::mojom::QuotaStatusCode::kErrorAbort,
- QuotaSettings(), 0, 0, 0, false);
- DeleteSoon();
- }
-
- void Completed() override {
- weak_factory_.InvalidateWeakPtrs();
- std::move(callback_).Run(blink::mojom::QuotaStatusCode::kOk, settings_,
- available_space_, total_space_, global_usage_,
- global_usage_is_complete_);
- DeleteSoon();
- }
-
- private:
- QuotaManager* manager() const {
- return static_cast<QuotaManager*>(observer());
- }
-
- void OnGotSettings(base::OnceClosure barrier_closure,
- const QuotaSettings& settings) {
- settings_ = settings;
- std::move(barrier_closure).Run();
- }
-
- void OnGotCapacity(base::OnceClosure barrier_closure,
- int64_t total_space,
- int64_t available_space) {
- total_space_ = total_space;
- available_space_ = available_space;
- std::move(barrier_closure).Run();
- }
-
- void OnBarrierComplete() {
- // Avoid computing the full current_usage when there's no pressure.
- int64_t consumed_space = total_space_ - available_space_;
- if (consumed_space < settings_.pool_size &&
- available_space_ > settings_.should_remain_available) {
- DCHECK(!global_usage_is_complete_);
- global_usage_ =
- manager()->GetUsageTracker(StorageType::kTemporary)->GetCachedUsage();
- CallCompleted();
- return;
- }
- manager()->GetGlobalUsage(
- StorageType::kTemporary,
- base::BindOnce(&EvictionRoundInfoHelper::OnGotGlobalUsage,
- weak_factory_.GetWeakPtr()));
- }
-
- void OnGotGlobalUsage(int64_t usage, int64_t unlimited_usage) {
- global_usage_ = std::max(INT64_C(0), usage - unlimited_usage);
- global_usage_is_complete_ = true;
- CallCompleted();
- }
-
- EvictionRoundInfoCallback callback_;
- QuotaSettings settings_;
- int64_t available_space_ = 0;
- int64_t total_space_ = 0;
- int64_t global_usage_ = 0;
- bool global_usage_is_complete_ = false;
- base::WeakPtrFactory<EvictionRoundInfoHelper> weak_factory_{this};
- DISALLOW_COPY_AND_ASSIGN(EvictionRoundInfoHelper);
-};
-
-class QuotaManager::GetUsageInfoTask : public QuotaTask {
- public:
- GetUsageInfoTask(QuotaManager* manager, GetUsageInfoCallback callback)
- : QuotaTask(manager), callback_(std::move(callback)) {}
-
- protected:
- void Run() override {
- remaining_trackers_ = 3;
- // This will populate cached hosts and usage info.
- manager()
- ->GetUsageTracker(StorageType::kTemporary)
- ->GetGlobalUsage(base::BindOnce(&GetUsageInfoTask::DidGetGlobalUsage,
- weak_factory_.GetWeakPtr(),
- StorageType::kTemporary));
- manager()
- ->GetUsageTracker(StorageType::kPersistent)
- ->GetGlobalUsage(base::BindOnce(&GetUsageInfoTask::DidGetGlobalUsage,
- weak_factory_.GetWeakPtr(),
- StorageType::kPersistent));
- manager()
- ->GetUsageTracker(StorageType::kSyncable)
- ->GetGlobalUsage(base::BindOnce(&GetUsageInfoTask::DidGetGlobalUsage,
- weak_factory_.GetWeakPtr(),
- StorageType::kSyncable));
- }
-
- void Completed() override {
- std::move(callback_).Run(std::move(entries_));
- DeleteSoon();
- }
-
- void Aborted() override {
- std::move(callback_).Run(UsageInfoEntries());
- DeleteSoon();
- }
-
- private:
- void AddEntries(StorageType type, UsageTracker* tracker) {
- std::map<std::string, int64_t> host_usage = tracker->GetCachedHostsUsage();
- for (const auto& host_usage_pair : host_usage) {
- entries_.emplace_back(host_usage_pair.first, type,
- host_usage_pair.second);
- }
- if (--remaining_trackers_ == 0)
- CallCompleted();
- }
-
- void DidGetGlobalUsage(StorageType type, int64_t, int64_t) {
- DCHECK(manager()->GetUsageTracker(type));
- AddEntries(type, manager()->GetUsageTracker(type));
- }
-
- QuotaManager* manager() const {
- return static_cast<QuotaManager*>(observer());
- }
-
- GetUsageInfoCallback callback_;
- UsageInfoEntries entries_;
- int remaining_trackers_;
- base::WeakPtrFactory<GetUsageInfoTask> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(GetUsageInfoTask);
-};
-
-class QuotaManager::OriginDataDeleter : public QuotaTask {
- public:
- OriginDataDeleter(QuotaManager* manager,
- const url::Origin& origin,
- StorageType type,
- QuotaClientTypes quota_client_types,
- bool is_eviction,
- StatusCallback callback)
- : QuotaTask(manager),
- origin_(origin),
- type_(type),
- quota_client_types_(std::move(quota_client_types)),
- error_count_(0),
- remaining_clients_(0),
- skipped_clients_(0),
- is_eviction_(is_eviction),
- callback_(std::move(callback)) {}
-
- protected:
- void Run() override {
- DCHECK(manager()->client_types_.contains(type_));
- remaining_clients_ = manager()->client_types_[type_].size();
-
- for (const auto& client_and_type : manager()->client_types_[type_]) {
- QuotaClient* client = client_and_type.first;
- QuotaClientType client_type = client_and_type.second;
- if (quota_client_types_.contains(client_type)) {
- static int tracing_id = 0;
- TRACE_EVENT_ASYNC_BEGIN2(
- "browsing_data", "QuotaManager::OriginDataDeleter", ++tracing_id,
- "client_type", client_type, "origin", origin_.Serialize());
- client->DeleteOriginData(
- origin_, type_,
- base::BindOnce(&OriginDataDeleter::DidDeleteOriginData,
- weak_factory_.GetWeakPtr(), tracing_id));
- } else {
- ++skipped_clients_;
- --remaining_clients_;
- }
- }
-
- if (remaining_clients_ == 0)
- CallCompleted();
- }
-
- void Completed() override {
- if (error_count_ == 0) {
- // 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 {
- std::move(callback_).Run(
- blink::mojom::QuotaStatusCode::kErrorInvalidModification);
- }
- DeleteSoon();
- }
-
- void Aborted() override {
- std::move(callback_).Run(blink::mojom::QuotaStatusCode::kErrorAbort);
- DeleteSoon();
- }
-
- private:
- void DidDeleteOriginData(int tracing_id,
- blink::mojom::QuotaStatusCode status) {
- DCHECK_GT(remaining_clients_, 0U);
- TRACE_EVENT_ASYNC_END0("browsing_data", "QuotaManager::OriginDataDeleter",
- tracing_id);
-
- if (status != blink::mojom::QuotaStatusCode::kOk)
- ++error_count_;
-
- if (--remaining_clients_ == 0)
- CallCompleted();
- }
-
- QuotaManager* manager() const {
- return static_cast<QuotaManager*>(observer());
- }
-
- const url::Origin origin_;
- const StorageType type_;
- const QuotaClientTypes quota_client_types_;
- int error_count_;
- size_t remaining_clients_;
- int skipped_clients_;
- const bool is_eviction_;
- StatusCallback callback_;
-
- base::WeakPtrFactory<OriginDataDeleter> weak_factory_{this};
- DISALLOW_COPY_AND_ASSIGN(OriginDataDeleter);
-};
-
-class QuotaManager::HostDataDeleter : public QuotaTask {
- public:
- HostDataDeleter(QuotaManager* manager,
- const std::string& host,
- StorageType type,
- QuotaClientTypes quota_client_types,
- StatusCallback callback)
- : QuotaTask(manager),
- host_(host),
- type_(type),
- quota_client_types_(std::move(quota_client_types)),
- error_count_(0),
- remaining_clients_(0),
- remaining_deleters_(0),
- callback_(std::move(callback)) {}
-
- protected:
- void Run() override {
- DCHECK(manager()->client_types_.contains(type_));
- remaining_clients_ = manager()->client_types_[type_].size();
-
- for (const auto& client_and_type : manager()->client_types_[type_]) {
- client_and_type.first->GetOriginsForHost(
- type_, host_,
- base::BindOnce(&HostDataDeleter::DidGetOriginsForHost,
- weak_factory_.GetWeakPtr()));
- }
- }
-
- void Completed() override {
- if (error_count_ == 0) {
- std::move(callback_).Run(blink::mojom::QuotaStatusCode::kOk);
- } else {
- std::move(callback_).Run(
- blink::mojom::QuotaStatusCode::kErrorInvalidModification);
- }
- DeleteSoon();
- }
-
- void Aborted() override {
- std::move(callback_).Run(blink::mojom::QuotaStatusCode::kErrorAbort);
- DeleteSoon();
- }
-
- private:
- void DidGetOriginsForHost(const std::vector<url::Origin>& origins) {
- DCHECK_GT(remaining_clients_, 0U);
-
- for (const auto& origin : origins)
- origins_.insert(origin);
-
- if (--remaining_clients_ == 0) {
- if (!origins_.empty())
- ScheduleOriginsDeletion();
- else
- CallCompleted();
- }
- }
-
- void ScheduleOriginsDeletion() {
- remaining_deleters_ = origins_.size();
- for (const auto& origin : origins_) {
- OriginDataDeleter* deleter = new OriginDataDeleter(
- manager(), origin, type_, std::move(quota_client_types_), false,
- base::BindOnce(&HostDataDeleter::DidDeleteOriginData,
- weak_factory_.GetWeakPtr()));
- deleter->Start();
- }
- }
-
- void DidDeleteOriginData(blink::mojom::QuotaStatusCode status) {
- DCHECK_GT(remaining_deleters_, 0U);
-
- if (status != blink::mojom::QuotaStatusCode::kOk)
- ++error_count_;
-
- if (--remaining_deleters_ == 0)
- CallCompleted();
- }
-
- QuotaManager* manager() const {
- return static_cast<QuotaManager*>(observer());
- }
-
- const std::string host_;
- const StorageType type_;
- const QuotaClientTypes quota_client_types_;
- std::set<url::Origin> origins_;
- int error_count_;
- size_t remaining_clients_;
- size_t remaining_deleters_;
- StatusCallback callback_;
-
- base::WeakPtrFactory<HostDataDeleter> weak_factory_{this};
- DISALLOW_COPY_AND_ASSIGN(HostDataDeleter);
-};
-
-class QuotaManager::StorageCleanupHelper : public QuotaTask {
- public:
- StorageCleanupHelper(QuotaManager* manager,
- StorageType type,
- QuotaClientTypes quota_client_types,
- base::OnceClosure callback)
- : QuotaTask(manager),
- type_(type),
- quota_client_types_(std::move(quota_client_types)),
- callback_(std::move(callback)) {
- DCHECK(manager->client_types_.contains(type_));
- }
-
- protected:
- void Run() override {
- DCHECK(manager()->client_types_.contains(type_));
- base::RepeatingClosure barrier = base::BarrierClosure(
- manager()->client_types_[type_].size(),
- base::BindOnce(&StorageCleanupHelper::CallCompleted,
- weak_factory_.GetWeakPtr()));
-
- // This may synchronously trigger |callback_| at the end of the for loop,
- // make sure we do nothing after this block.
- for (const auto& client_and_type : manager()->client_types_[type_]) {
- QuotaClient* client = client_and_type.first;
- QuotaClientType client_type = client_and_type.second;
- if (quota_client_types_.contains(client_type)) {
- client->PerformStorageCleanup(type_, barrier);
- } else {
- barrier.Run();
- }
- }
- }
-
- void Aborted() override {
- weak_factory_.InvalidateWeakPtrs();
- std::move(callback_).Run();
- DeleteSoon();
- }
-
- void Completed() override {
- weak_factory_.InvalidateWeakPtrs();
- std::move(callback_).Run();
- DeleteSoon();
- }
-
- private:
- QuotaManager* manager() const {
- return static_cast<QuotaManager*>(observer());
- }
-
- const StorageType type_;
- const QuotaClientTypes quota_client_types_;
- base::OnceClosure callback_;
- base::WeakPtrFactory<StorageCleanupHelper> weak_factory_{this};
- 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
-// DidGetModifiedBetween() via base::Owned(). When the closure for said
-// function goes out of scope, the object is deleted. This is a thread-safe
-// class.
-class QuotaManager::GetModifiedSinceHelper {
- public:
- bool GetModifiedBetweenOnDBThread(StorageType type,
- base::Time begin,
- base::Time end,
- QuotaDatabase* database) {
- DCHECK(database);
- return database->GetOriginsModifiedBetween(type, &origins_, begin, end);
- }
-
- void DidGetModifiedBetween(const base::WeakPtr<QuotaManager>& manager,
- GetOriginsCallback callback,
- StorageType type,
- bool success) {
- if (!manager) {
- // The operation was aborted.
- std::move(callback).Run(std::set<url::Origin>(), type);
- return;
- }
- manager->DidDatabaseWork(success);
- std::move(callback).Run(origins_, type);
- }
-
- private:
- 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) {
- DCHECK(database);
- return database->DumpQuotaTable(base::BindRepeating(
- &DumpQuotaTableHelper::AppendEntry, base::Unretained(this)));
- }
-
- void DidDumpQuotaTable(const base::WeakPtr<QuotaManager>& manager,
- DumpQuotaTableCallback callback,
- bool success) {
- if (!manager) {
- // The operation was aborted.
- std::move(callback).Run(QuotaTableEntries());
- return;
- }
- manager->DidDatabaseWork(success);
- std::move(callback).Run(entries_);
- }
-
- private:
- bool AppendEntry(const QuotaTableEntry& entry) {
- entries_.push_back(entry);
- return true;
- }
-
- 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) {
- DCHECK(database);
- return database->DumpOriginInfoTable(base::BindRepeating(
- &DumpOriginInfoTableHelper::AppendEntry, base::Unretained(this)));
- }
-
- void DidDumpOriginInfoTable(const base::WeakPtr<QuotaManager>& manager,
- DumpOriginInfoTableCallback callback,
- bool success) {
- if (!manager) {
- // The operation was aborted.
- std::move(callback).Run(OriginInfoTableEntries());
- return;
- }
- manager->DidDatabaseWork(success);
- std::move(callback).Run(entries_);
- }
-
- private:
- bool AppendEntry(const OriginInfoTableEntry& entry) {
- entries_.push_back(entry);
- return true;
- }
-
- OriginInfoTableEntries entries_;
-};
-
-// QuotaManager ---------------------------------------------------------------
-
QuotaManager::QuotaManager(
bool is_incognito,
const base::FilePath& profile_path,
scoped_refptr<base::SingleThreadTaskRunner> io_thread,
+ base::RepeatingClosure quota_change_callback,
scoped_refptr<SpecialStoragePolicy> special_storage_policy,
const GetQuotaSettingsFunc& get_settings_function)
- : RefCountedDeleteOnSequence<QuotaManager>(io_thread),
- is_incognito_(is_incognito),
- profile_path_(profile_path),
- proxy_(new QuotaManagerProxy(this, io_thread)),
- db_disabled_(false),
- eviction_disabled_(false),
- io_thread_(io_thread),
- db_runner_(base::ThreadPool::CreateSequencedTaskRunner(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
- base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
- get_settings_function_(get_settings_function),
- is_getting_eviction_origin_(false),
- special_storage_policy_(std::move(special_storage_policy)),
- get_volume_info_fn_(&QuotaManager::GetVolumeInfo) {
- DCHECK_EQ(settings_.refresh_interval, base::TimeDelta::Max());
- if (!get_settings_function.is_null()) {
- // Reset the interval to ensure we use the get_settings_function
- // the first times settings_ is needed.
- settings_.refresh_interval = base::TimeDelta();
- get_settings_task_runner_ = base::ThreadTaskRunnerHandle::Get();
- }
- DETACH_FROM_SEQUENCE(sequence_checker_);
-}
-
-void QuotaManager::SetQuotaSettings(const QuotaSettings& settings) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- settings_ = settings;
- settings_timestamp_ = base::TimeTicks::Now();
-}
-
-void QuotaManager::GetUsageInfo(GetUsageInfoCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- LazyInitialize();
- GetUsageInfoTask* get_usage_info =
- new GetUsageInfoTask(this, std::move(callback));
- get_usage_info->Start();
-}
-
-void QuotaManager::GetUsageAndQuotaForWebApps(const url::Origin& origin,
- StorageType type,
- UsageAndQuotaCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- GetUsageAndQuotaWithBreakdown(
- origin, type,
- base::BindOnce(&DidGetUsageAndQuotaStripBreakdown, std::move(callback)));
-}
-
-void QuotaManager::GetUsageAndQuotaWithBreakdown(
- const url::Origin& origin,
- StorageType type,
- UsageAndQuotaWithBreakdownCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- GetUsageAndQuotaForDevtools(
- origin, type,
- base::BindOnce(&DidGetUsageAndQuotaStripOverride, std::move(callback)));
-}
-
-void QuotaManager::GetUsageAndQuotaForDevtools(
- const url::Origin& origin,
- StorageType type,
- UsageAndQuotaForDevtoolsCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (!IsSupportedType(type) ||
- (is_incognito_ && !IsSupportedIncognitoType(type))) {
- std::move(callback).Run(blink::mojom::QuotaStatusCode::kErrorNotSupported,
- /*usage=*/0,
- /*quota=*/0,
- /*is_override_enabled=*/false,
- /*usage_breakdown=*/nullptr);
- return;
- }
- LazyInitialize();
-
- bool is_session_only =
- type == StorageType::kTemporary && special_storage_policy_ &&
- special_storage_policy_->IsStorageSessionOnly(origin.GetURL());
-
- base::Optional<int64_t> quota_override = GetQuotaOverrideForOrigin(origin);
-
- UsageAndQuotaInfoGatherer* helper = new UsageAndQuotaInfoGatherer(
- this, origin, type, IsStorageUnlimited(origin, type), is_session_only,
- is_incognito_, quota_override, std::move(callback));
- helper->Start();
-}
-
-void QuotaManager::GetUsageAndQuota(const url::Origin& origin,
- StorageType type,
- UsageAndQuotaCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (IsStorageUnlimited(origin, type)) {
- // TODO(michaeln): This seems like a non-obvious odd behavior, probably for
- // apps/extensions, but it would be good to eliminate this special case.
- std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk, 0, kNoLimit);
- return;
- }
-
- if (!IsSupportedType(type) ||
- (is_incognito_ && !IsSupportedIncognitoType(type))) {
- std::move(callback).Run(
- /*status*/ blink::mojom::QuotaStatusCode::kErrorNotSupported,
- /*usage*/ 0,
- /*quota*/ 0);
- return;
- }
- LazyInitialize();
-
- bool is_session_only =
- type == StorageType::kTemporary && special_storage_policy_ &&
- special_storage_policy_->IsStorageSessionOnly(origin.GetURL());
-
- base::Optional<int64_t> quota_override = GetQuotaOverrideForOrigin(origin);
-
- UsageAndQuotaInfoGatherer* helper = new UsageAndQuotaInfoGatherer(
- this, origin, type, IsStorageUnlimited(origin, type), is_session_only,
- is_incognito_, quota_override,
- base::BindOnce(&DidGetUsageAndQuotaStripOverride,
- base::BindOnce(&DidGetUsageAndQuotaStripBreakdown,
- std::move(callback))));
- helper->Start();
-}
-
-void QuotaManager::NotifyStorageAccessed(const url::Origin& origin,
- StorageType type) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- NotifyStorageAccessedInternal(origin, type, base::Time::Now());
-}
-
-void QuotaManager::NotifyStorageModified(QuotaClientType client_id,
- const url::Origin& origin,
- StorageType type,
- int64_t delta) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- NotifyStorageModifiedInternal(client_id, origin, type, delta,
- base::Time::Now());
-}
-
-void QuotaManager::NotifyWriteFailed(const url::Origin& origin) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- auto age_of_disk_stats = base::TimeTicks::Now() -
- std::get<0>(cached_disk_stats_for_storage_pressure_);
-
- // Avoid polling for free disk space if disk stats have been recently
- // queried.
- if (age_of_disk_stats < kStoragePressureCheckDiskStatsInterval) {
- int64_t total_space = std::get<1>(cached_disk_stats_for_storage_pressure_);
- int64_t available_space =
- std::get<2>(cached_disk_stats_for_storage_pressure_);
- MaybeRunStoragePressureCallback(origin, total_space, available_space);
- }
-
- GetStorageCapacity(
- base::BindOnce(&QuotaManager::MaybeRunStoragePressureCallback,
- weak_factory_.GetWeakPtr(), origin));
-}
-
-void QuotaManager::NotifyOriginInUse(const url::Origin& origin) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(io_thread_->BelongsToCurrentThread());
- origins_in_use_[origin]++;
-}
-
-void QuotaManager::NotifyOriginNoLongerInUse(const url::Origin& origin) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(io_thread_->BelongsToCurrentThread());
- DCHECK(IsOriginInUse(origin));
- int& count = origins_in_use_[origin];
- if (--count == 0)
- origins_in_use_.erase(origin);
-}
-
-void QuotaManager::SetUsageCacheEnabled(QuotaClientType client_id,
- const url::Origin& origin,
- StorageType type,
- bool enabled) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- LazyInitialize();
- DCHECK(GetUsageTracker(type));
- GetUsageTracker(type)->SetUsageCacheEnabled(client_id, origin, enabled);
-}
-
-void QuotaManager::DeleteOriginData(const url::Origin& origin,
- StorageType type,
- QuotaClientTypes quota_client_types,
- StatusCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DeleteOriginDataInternal(origin, type, std::move(quota_client_types), false,
- std::move(callback));
-}
-
-void QuotaManager::PerformStorageCleanup(StorageType type,
- QuotaClientTypes quota_client_types,
- base::OnceClosure callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- StorageCleanupHelper* deleter = new StorageCleanupHelper(
- this, type, std::move(quota_client_types), std::move(callback));
- deleter->Start();
-}
-
-void QuotaManager::DeleteHostData(const std::string& host,
- StorageType type,
- QuotaClientTypes quota_client_types,
- StatusCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- LazyInitialize();
-
- DCHECK(client_types_.contains(type));
- if (host.empty() || client_types_[type].empty()) {
- std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk);
- return;
- }
-
- HostDataDeleter* deleter = new HostDataDeleter(
- this, host, type, std::move(quota_client_types), std::move(callback));
- deleter->Start();
-}
-
-void QuotaManager::GetPersistentHostQuota(const std::string& host,
- QuotaCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- LazyInitialize();
- if (host.empty()) {
- // This could happen if we are called on file:///.
- // TODO(kinuko) We may want to respect --allow-file-access-from-files
- // command line switch.
- std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk, 0);
- return;
- }
-
- if (!persistent_host_quota_callbacks_.Add(host, std::move(callback)))
- return;
-
- int64_t* quota_ptr = new int64_t(0);
- PostTaskAndReplyWithResultForDBThread(
- FROM_HERE,
- base::BindOnce(&GetPersistentHostQuotaOnDBThread, host,
- base::Unretained(quota_ptr)),
- base::BindOnce(&QuotaManager::DidGetPersistentHostQuota,
- weak_factory_.GetWeakPtr(), host, base::Owned(quota_ptr)));
-}
-
-void QuotaManager::SetPersistentHostQuota(const std::string& host,
- int64_t new_quota,
- QuotaCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- LazyInitialize();
- if (host.empty()) {
- // This could happen if we are called on file:///.
- std::move(callback).Run(blink::mojom::QuotaStatusCode::kErrorNotSupported,
- 0);
- return;
- }
-
- if (new_quota < 0) {
- std::move(callback).Run(
- blink::mojom::QuotaStatusCode::kErrorInvalidModification, -1);
- return;
- }
-
- // Cap the requested size at the per-host quota limit.
- new_quota = std::min(new_quota, kPerHostPersistentQuotaLimit);
-
- if (db_disabled_) {
- std::move(callback).Run(blink::mojom::QuotaStatusCode::kErrorInvalidAccess,
- -1);
- return;
- }
-
- int64_t* new_quota_ptr = new int64_t(new_quota);
- PostTaskAndReplyWithResultForDBThread(
- FROM_HERE,
- base::BindOnce(&SetPersistentHostQuotaOnDBThread, host,
- base::Unretained(new_quota_ptr)),
- base::BindOnce(&QuotaManager::DidSetPersistentHostQuota,
- weak_factory_.GetWeakPtr(), host, std::move(callback),
- base::Owned(new_quota_ptr)));
-}
-
-void QuotaManager::GetGlobalUsage(StorageType type,
- GlobalUsageCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- LazyInitialize();
- DCHECK(GetUsageTracker(type));
- GetUsageTracker(type)->GetGlobalUsage(std::move(callback));
-}
-
-void QuotaManager::GetHostUsageWithBreakdown(
- const std::string& host,
- StorageType type,
- UsageWithBreakdownCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- LazyInitialize();
- DCHECK(GetUsageTracker(type));
- GetUsageTracker(type)->GetHostUsageWithBreakdown(host, std::move(callback));
-}
-
-std::map<std::string, std::string> QuotaManager::GetStatistics() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- std::map<std::string, std::string> statistics;
- if (temporary_storage_evictor_) {
- std::map<std::string, int64_t> stats;
- temporary_storage_evictor_->GetStatistics(&stats);
- for (const auto& origin_usage_pair : stats) {
- statistics[origin_usage_pair.first] =
- base::NumberToString(origin_usage_pair.second);
- }
- }
- return statistics;
-}
-
-bool QuotaManager::IsStorageUnlimited(const url::Origin& origin,
- StorageType type) const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // For syncable storage we should always enforce quota (since the
- // quota must be capped by the server limit).
- if (type == StorageType::kSyncable)
- return false;
- if (type == StorageType::kQuotaNotManaged)
- return true;
- return special_storage_policy_.get() &&
- special_storage_policy_->IsStorageUnlimited(origin.GetURL());
-}
-
-void QuotaManager::GetOriginsModifiedBetween(StorageType type,
- base::Time begin,
- base::Time end,
- GetOriginsCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- LazyInitialize();
- GetModifiedSinceHelper* helper = new GetModifiedSinceHelper;
- PostTaskAndReplyWithResultForDBThread(
- FROM_HERE,
- base::BindOnce(&GetModifiedSinceHelper::GetModifiedBetweenOnDBThread,
- base::Unretained(helper), type, begin, end),
- base::BindOnce(&GetModifiedSinceHelper::DidGetModifiedBetween,
- base::Owned(helper), weak_factory_.GetWeakPtr(),
- std::move(callback), type));
-}
-
-bool QuotaManager::ResetUsageTracker(StorageType type) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(GetUsageTracker(type));
- if (GetUsageTracker(type)->IsWorking())
- return false;
-
- auto usage_tracker = std::make_unique<UsageTracker>(
- client_types_[type], type, special_storage_policy_.get());
- switch (type) {
- case StorageType::kTemporary:
- temporary_usage_tracker_ = std::move(usage_tracker);
- return true;
- case StorageType::kPersistent:
- persistent_usage_tracker_ = std::move(usage_tracker);
- return true;
- case StorageType::kSyncable:
- syncable_usage_tracker_ = std::move(usage_tracker);
- return true;
- default:
- NOTREACHED();
- }
- return true;
-}
-
-QuotaManager::~QuotaManager() {
- proxy_->manager_ = nullptr;
-
- // Iterating over |clients_for_ownership_| is correct here because we want to
- // call OnQuotaManagerDestroyed() once per QuotaClient.
- for (const auto& client : clients_for_ownership_)
- client->OnQuotaManagerDestroyed();
-
- if (database_)
- db_runner_->DeleteSoon(FROM_HERE, database_.release());
-}
-
-QuotaManager::EvictionContext::EvictionContext()
- : evicted_type(StorageType::kUnknown) {}
-
-QuotaManager::EvictionContext::~EvictionContext() = default;
-
-void QuotaManager::LazyInitialize() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(io_thread_->BelongsToCurrentThread());
- if (database_) {
- // Already initialized.
- return;
- }
-
- // Use an empty path to open an in-memory only database for incognito.
- database_ = std::make_unique<QuotaDatabase>(
- is_incognito_ ? base::FilePath()
- : profile_path_.AppendASCII(kDatabaseName));
-
- temporary_usage_tracker_ = std::make_unique<UsageTracker>(
- client_types_[StorageType::kTemporary], StorageType::kTemporary,
- special_storage_policy_.get());
- persistent_usage_tracker_ = std::make_unique<UsageTracker>(
- client_types_[StorageType::kPersistent], StorageType::kPersistent,
- special_storage_policy_.get());
- syncable_usage_tracker_ = std::make_unique<UsageTracker>(
- client_types_[StorageType::kSyncable], StorageType::kSyncable,
- special_storage_policy_.get());
-
- if (!is_incognito_) {
- histogram_timer_.Start(
- FROM_HERE, base::TimeDelta::FromMilliseconds(kReportHistogramInterval),
- this, &QuotaManager::ReportHistogram);
- }
-
- base::PostTaskAndReplyWithResult(
- db_runner_.get(), FROM_HERE,
- base::BindOnce(&QuotaDatabase::IsOriginDatabaseBootstrapped,
- base::Unretained(database_.get())),
- base::BindOnce(&QuotaManager::FinishLazyInitialize,
- weak_factory_.GetWeakPtr()));
-}
-
-void QuotaManager::FinishLazyInitialize(bool is_database_bootstrapped) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- is_database_bootstrapped_ = is_database_bootstrapped;
- StartEviction();
-}
-
-void QuotaManager::BootstrapDatabaseForEviction(
- GetOriginCallback did_get_origin_callback,
- int64_t usage,
- int64_t unlimited_usage) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // The usage cache should be fully populated now so we can
- // seed the database with origins we know about.
- std::set<url::Origin> origins = temporary_usage_tracker_->GetCachedOrigins();
- PostTaskAndReplyWithResultForDBThread(
- FROM_HERE,
- base::BindOnce(&BootstrapDatabaseOnDBThread, std::move(origins)),
- base::BindOnce(&QuotaManager::DidBootstrapDatabase,
- weak_factory_.GetWeakPtr(),
- std::move(did_get_origin_callback)));
-}
-
-void QuotaManager::DidBootstrapDatabase(
- GetOriginCallback did_get_origin_callback,
- bool success) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- is_database_bootstrapped_ = success;
- DidDatabaseWork(success);
- GetLRUOrigin(StorageType::kTemporary, std::move(did_get_origin_callback));
-}
-
-void QuotaManager::RegisterClient(
- scoped_refptr<QuotaClient> client,
- QuotaClientType client_type,
- const std::vector<blink::mojom::StorageType>& storage_types) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(!database_.get())
- << "All clients must be registered before the database is initialized";
- DCHECK(client.get());
-
- for (blink::mojom::StorageType storage_type : storage_types)
- client_types_[storage_type].insert({client.get(), client_type});
- clients_for_ownership_.push_back(std::move(client));
-}
-
-UsageTracker* QuotaManager::GetUsageTracker(StorageType type) const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- switch (type) {
- case StorageType::kTemporary:
- return temporary_usage_tracker_.get();
- case StorageType::kPersistent:
- return persistent_usage_tracker_.get();
- case StorageType::kSyncable:
- return syncable_usage_tracker_.get();
- case StorageType::kQuotaNotManaged:
- return nullptr;
- case StorageType::kUnknown:
- NOTREACHED();
- }
- return nullptr;
-}
-
-std::set<url::Origin> QuotaManager::GetCachedOrigins(StorageType type) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- LazyInitialize();
- DCHECK(GetUsageTracker(type));
- return GetUsageTracker(type)->GetCachedOrigins();
-}
-
-void QuotaManager::NotifyStorageAccessedInternal(const url::Origin& origin,
- StorageType type,
- base::Time accessed_time) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- LazyInitialize();
- if (type == StorageType::kTemporary && is_getting_eviction_origin_) {
- // Record the accessed origins while GetLRUOrigin task is runing
- // to filter out them from eviction.
- access_notified_origins_.insert(origin);
- }
-
- if (db_disabled_)
- return;
- PostTaskAndReplyWithResultForDBThread(
- FROM_HERE,
- base::BindOnce(&UpdateAccessTimeOnDBThread, origin, type, accessed_time),
- base::BindOnce(&QuotaManager::DidDatabaseWork,
- weak_factory_.GetWeakPtr()));
-}
-
-void QuotaManager::NotifyStorageModifiedInternal(QuotaClientType client_id,
- const url::Origin& origin,
- StorageType type,
- int64_t delta,
- base::Time modified_time) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- LazyInitialize();
- DCHECK(GetUsageTracker(type));
- GetUsageTracker(type)->UpdateUsageCache(client_id, origin, delta);
-
- if (db_disabled_)
- return;
-
- PostTaskAndReplyWithResultForDBThread(
- FROM_HERE,
- base::BindOnce(&UpdateModifiedTimeOnDBThread, origin, type,
- modified_time),
- base::BindOnce(&QuotaManager::DidDatabaseWork,
- weak_factory_.GetWeakPtr()));
-}
-
-void QuotaManager::DumpQuotaTable(DumpQuotaTableCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DumpQuotaTableHelper* helper = new DumpQuotaTableHelper;
- PostTaskAndReplyWithResultForDBThread(
- FROM_HERE,
- base::BindOnce(&DumpQuotaTableHelper::DumpQuotaTableOnDBThread,
- base::Unretained(helper)),
- base::BindOnce(&DumpQuotaTableHelper::DidDumpQuotaTable,
- base::Owned(helper), weak_factory_.GetWeakPtr(),
- std::move(callback)));
-}
-
-void QuotaManager::DumpOriginInfoTable(DumpOriginInfoTableCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DumpOriginInfoTableHelper* helper = new DumpOriginInfoTableHelper;
- PostTaskAndReplyWithResultForDBThread(
- FROM_HERE,
- base::BindOnce(&DumpOriginInfoTableHelper::DumpOriginInfoTableOnDBThread,
- base::Unretained(helper)),
- base::BindOnce(&DumpOriginInfoTableHelper::DidDumpOriginInfoTable,
- base::Owned(helper), weak_factory_.GetWeakPtr(),
- std::move(callback)));
-}
-
-void QuotaManager::StartEviction() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(!temporary_storage_evictor_.get());
- if (eviction_disabled_)
- return;
- temporary_storage_evictor_ = std::make_unique<QuotaTemporaryStorageEvictor>(
- this, kEvictionIntervalInMilliSeconds);
- temporary_storage_evictor_->Start();
-}
-
-void QuotaManager::DeleteOriginFromDatabase(const url::Origin& origin,
- StorageType type,
- bool is_eviction) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- LazyInitialize();
- if (db_disabled_)
- return;
-
- PostTaskAndReplyWithResultForDBThread(
- FROM_HERE,
- base::BindOnce(&DeleteOriginInfoOnDBThread, origin, type, is_eviction),
- base::BindOnce(&QuotaManager::DidDatabaseWork,
- weak_factory_.GetWeakPtr()));
-}
-
-void QuotaManager::DidOriginDataEvicted(blink::mojom::QuotaStatusCode status) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(io_thread_->BelongsToCurrentThread());
-
- // We only try evict origins that are not in use, so basically
- // deletion attempt for eviction should not fail. Let's record
- // the origin if we get error and exclude it from future eviction
- // if the error happens consistently (> kThresholdOfErrorsToBeDenylisted).
- if (status != blink::mojom::QuotaStatusCode::kOk)
- origins_in_error_[eviction_context_.evicted_origin]++;
-
- std::move(eviction_context_.evict_origin_data_callback).Run(status);
-}
-
-void QuotaManager::DeleteOriginDataInternal(const url::Origin& origin,
- StorageType type,
- QuotaClientTypes quota_client_types,
- bool is_eviction,
- StatusCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- LazyInitialize();
-
- OriginDataDeleter* deleter =
- new OriginDataDeleter(this, origin, type, std::move(quota_client_types),
- is_eviction, std::move(callback));
- deleter->Start();
-}
-
-void QuotaManager::MaybeRunStoragePressureCallback(const url::Origin& origin,
- int64_t total_space,
- int64_t available_space) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // TODO(https://crbug.com/1059560): Figure out what 0 total_space means
- // and how to handle the storage pressure callback in these cases.
- if (total_space == 0)
- return;
-
- if (!storage_pressure_callback_) {
- // Quota will hold onto a storage pressure notification if no storage
- // pressure callback is set.
- origin_for_pending_storage_pressure_callback_ = std::move(origin);
- return;
- }
-
- if (available_space < kStoragePressureThresholdRatio * total_space) {
- storage_pressure_callback_.Run(std::move(origin));
- }
-}
-
-void QuotaManager::SimulateStoragePressure(const url::Origin origin) {
- storage_pressure_callback_.Run(origin);
-}
-
-void QuotaManager::DetermineStoragePressure(int64_t free_space,
- int64_t total_space) {
- if (!base::FeatureList::IsEnabled(features::kStoragePressureEvent)) {
- return;
- }
- int64_t threshold_bytes =
- RandomizeByPercent(kGBytes, kThresholdRandomizationPercent);
- int64_t threshold = RandomizeByPercent(
- static_cast<int64_t>(total_space *
- (kThresholdRandomizationPercent / 100.0)),
- kThresholdRandomizationPercent);
- threshold = std::min(threshold_bytes, threshold);
-
- if (free_space < threshold) {
- // TODO(https://crbug.com/1096549): Implement StoragePressureEvent
- // dispatching.
- }
-}
-
-void QuotaManager::SetStoragePressureCallback(
- base::RepeatingCallback<void(url::Origin)> storage_pressure_callback) {
- storage_pressure_callback_ = storage_pressure_callback;
- if (origin_for_pending_storage_pressure_callback_.has_value()) {
- storage_pressure_callback_.Run(
- std::move(origin_for_pending_storage_pressure_callback_.value()));
- origin_for_pending_storage_pressure_callback_ = base::nullopt;
- }
-}
-
-int QuotaManager::GetOverrideHandleId() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return ++next_override_handle_id_;
-}
-
-void QuotaManager::OverrideQuotaForOrigin(int handle_id,
- const url::Origin& origin,
- base::Optional<int64_t> quota_size) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (quota_size.has_value()) {
- DCHECK_GE(next_override_handle_id_, handle_id);
- // Bracket notation is safe here because we want to construct a new
- // QuotaOverride in the case that one does not exist for origin.
- devtools_overrides_[origin].active_override_session_ids.insert(handle_id);
- devtools_overrides_[origin].quota_size = quota_size.value();
- } else {
- devtools_overrides_.erase(origin);
- }
-}
-
-void QuotaManager::WithdrawOverridesForHandle(int handle_id) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- std::vector<url::Origin> origins_to_clear;
- for (auto& devtools_override : devtools_overrides_) {
- auto& quota_override = devtools_override.second;
- auto& origin = devtools_override.first;
-
- quota_override.active_override_session_ids.erase(handle_id);
-
- if (!quota_override.active_override_session_ids.size()) {
- origins_to_clear.push_back(origin);
- }
- }
-
- for (auto& origin : origins_to_clear) {
- devtools_overrides_.erase(origin);
- }
-}
-
-base::Optional<int64_t> QuotaManager::GetQuotaOverrideForOrigin(
- const url::Origin& origin) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (!base::Contains(devtools_overrides_, origin)) {
- return base::nullopt;
- }
- return devtools_overrides_[origin].quota_size;
-}
-
-void QuotaManager::ReportHistogram() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(!is_incognito_);
- GetGlobalUsage(
- StorageType::kTemporary,
- base::BindOnce(&QuotaManager::DidGetTemporaryGlobalUsageForHistogram,
- weak_factory_.GetWeakPtr()));
-}
-
-void QuotaManager::DidGetTemporaryGlobalUsageForHistogram(
- int64_t usage,
- int64_t unlimited_usage) {
- GetStorageCapacity(
- base::BindOnce(&QuotaManager::DidGetStorageCapacityForHistogram,
- weak_factory_.GetWeakPtr(), usage));
-}
-
-void QuotaManager::DidGetStorageCapacityForHistogram(int64_t usage,
- int64_t total_space,
- int64_t available_space) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- UMA_HISTOGRAM_MBYTES("Quota.GlobalUsageOfTemporaryStorage", usage);
- if (total_space > 0) {
- UMA_HISTOGRAM_PERCENTAGE("Quota.PercentUsedForTemporaryStorage2",
- static_cast<int>((usage * 100) / total_space));
- UMA_HISTOGRAM_MBYTES("Quota.AvailableDiskSpace2", available_space);
- UMA_HISTOGRAM_PERCENTAGE(
- "Quota.PercentDiskAvailable2",
- std::min(100, static_cast<int>((available_space * 100 / total_space))));
- }
-
- GetGlobalUsage(
- StorageType::kPersistent,
- base::BindOnce(&QuotaManager::DidGetPersistentGlobalUsageForHistogram,
- weak_factory_.GetWeakPtr()));
-}
-
-void QuotaManager::DidGetPersistentGlobalUsageForHistogram(
- int64_t usage,
- int64_t unlimited_usage) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- UMA_HISTOGRAM_MBYTES("Quota.GlobalUsageOfPersistentStorage", usage);
-
- // We DumpOriginInfoTable last to ensure the trackers caches are loaded.
- DumpOriginInfoTable(
- base::BindOnce(&QuotaManager::DidDumpOriginInfoTableForHistogram,
- weak_factory_.GetWeakPtr()));
-}
-
-void QuotaManager::DidDumpOriginInfoTableForHistogram(
- const OriginInfoTableEntries& entries) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- std::map<url::Origin, int64_t> usage_map =
- GetUsageTracker(StorageType::kTemporary)->GetCachedOriginsUsage();
- base::Time now = base::Time::Now();
- for (const auto& info : entries) {
- if (info.type != StorageType::kTemporary)
- continue;
-
- // Ignore stale database entries. If there is no map entry, the origin's
- // data has been deleted.
- auto it = usage_map.find(info.origin);
- if (it == usage_map.end() || it->second == 0)
- continue;
-
- base::TimeDelta age = now - std::max(info.last_access_time,
- info.last_modified_time);
- UMA_HISTOGRAM_COUNTS_1000("Quota.AgeOfOriginInDays", age.InDays());
-
- int64_t kilobytes = std::max(it->second / INT64_C(1024), INT64_C(1));
- base::Histogram::FactoryGet(
- "Quota.AgeOfDataInDays", 1, 1000, 50,
- base::HistogramBase::kUmaTargetedHistogramFlag)->
- AddCount(age.InDays(),
- base::saturated_cast<int>(kilobytes));
- }
-}
-
-std::set<url::Origin> QuotaManager::GetEvictionOriginExceptions() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- std::set<url::Origin> exceptions;
- for (const auto& p : origins_in_use_) {
- if (p.second > 0)
- exceptions.insert(p.first);
- }
-
- for (const auto& p : origins_in_error_) {
- if (p.second > QuotaManager::kThresholdOfErrorsToBeDenylisted)
- exceptions.insert(p.first);
- }
-
- return exceptions;
-}
-
-void QuotaManager::DidGetEvictionOrigin(
- GetOriginCallback callback,
- const base::Optional<url::Origin>& origin) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // Make sure the returned origin is (still) not in the origin_in_use_ set
- // and has not been accessed since we posted the task.
- DCHECK(!origin.has_value() || !origin->GetURL().is_empty());
- if (origin.has_value() &&
- (base::Contains(origins_in_use_, *origin) ||
- base::Contains(access_notified_origins_, *origin))) {
- std::move(callback).Run(base::nullopt);
- } else {
- std::move(callback).Run(origin);
- }
- access_notified_origins_.clear();
-
- is_getting_eviction_origin_ = false;
-}
-
-void QuotaManager::GetEvictionOrigin(
- StorageType type,
- int64_t global_quota,
- GetOriginCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- LazyInitialize();
- // This must not be called while there's an in-flight task.
- DCHECK(!is_getting_eviction_origin_);
- is_getting_eviction_origin_ = true;
-
- auto did_get_origin_callback =
- base::BindOnce(&QuotaManager::DidGetEvictionOrigin,
- weak_factory_.GetWeakPtr(), std::move(callback));
-
- if (!is_database_bootstrapped_ && !eviction_disabled_) {
- // Once bootstrapped, GetLRUOrigin will be called.
- GetGlobalUsage(StorageType::kTemporary,
- base::BindOnce(&QuotaManager::BootstrapDatabaseForEviction,
- weak_factory_.GetWeakPtr(),
- std::move(did_get_origin_callback)));
- return;
- }
-
- GetLRUOrigin(type, std::move(did_get_origin_callback));
-}
-
-void QuotaManager::EvictOriginData(const url::Origin& origin,
- StorageType type,
- StatusCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(io_thread_->BelongsToCurrentThread());
- DCHECK_EQ(type, StorageType::kTemporary);
-
- eviction_context_.evicted_origin = origin;
- eviction_context_.evicted_type = type;
- eviction_context_.evict_origin_data_callback = std::move(callback);
-
- DeleteOriginDataInternal(origin, type, AllQuotaClientTypes(), true,
- base::BindOnce(&QuotaManager::DidOriginDataEvicted,
- weak_factory_.GetWeakPtr()));
-}
-
-void QuotaManager::GetEvictionRoundInfo(EvictionRoundInfoCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(io_thread_->BelongsToCurrentThread());
- LazyInitialize();
- EvictionRoundInfoHelper* helper =
- new EvictionRoundInfoHelper(this, std::move(callback));
- helper->Start();
-}
-
-void QuotaManager::GetLRUOrigin(StorageType type, GetOriginCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- LazyInitialize();
- // This must not be called while there's an in-flight task.
- DCHECK(lru_origin_callback_.is_null());
- lru_origin_callback_ = std::move(callback);
- if (db_disabled_) {
- std::move(lru_origin_callback_).Run(base::nullopt);
- return;
- }
-
- auto origin = std::make_unique<base::Optional<url::Origin>>();
- auto* origin_ptr = origin.get();
- PostTaskAndReplyWithResultForDBThread(
- FROM_HERE,
- base::BindOnce(&GetLRUOriginOnDBThread, type,
- GetEvictionOriginExceptions(),
- base::RetainedRef(special_storage_policy_),
- base::Unretained(origin_ptr)),
- base::BindOnce(&QuotaManager::DidGetLRUOrigin, weak_factory_.GetWeakPtr(),
- std::move(origin)));
-}
-
-void QuotaManager::DidGetPersistentHostQuota(const std::string& host,
- const int64_t* quota,
- bool success) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DidDatabaseWork(success);
- persistent_host_quota_callbacks_.Run(
- host, blink::mojom::QuotaStatusCode::kOk,
- std::min(*quota, kPerHostPersistentQuotaLimit));
-}
-
-void QuotaManager::DidSetPersistentHostQuota(const std::string& host,
- QuotaCallback callback,
- const int64_t* new_quota,
- bool success) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DidDatabaseWork(success);
- std::move(callback).Run(
- success ? blink::mojom::QuotaStatusCode::kOk
- : blink::mojom::QuotaStatusCode::kErrorInvalidAccess,
- *new_quota);
-}
-
-void QuotaManager::DidGetLRUOrigin(
- std::unique_ptr<base::Optional<url::Origin>> origin,
- bool success) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DidDatabaseWork(success);
-
- std::move(lru_origin_callback_).Run(*origin);
-}
-
-namespace {
-void DidGetSettingsThreadAdapter(base::TaskRunner* task_runner,
- OptionalQuotaSettingsCallback callback,
- base::Optional<QuotaSettings> settings) {
- task_runner->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), std::move(settings)));
-}
-} // namespace
-
-void QuotaManager::GetQuotaSettings(QuotaSettingsCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (base::TimeTicks::Now() - settings_timestamp_ <
- settings_.refresh_interval) {
- std::move(callback).Run(settings_);
- return;
- }
-
- if (!settings_callbacks_.Add(std::move(callback)))
- return;
-
- // We invoke our clients GetQuotaSettingsFunc on the
- // UI thread and plumb the resulting value back to this thread.
- get_settings_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- get_settings_function_,
- base::BindOnce(&DidGetSettingsThreadAdapter,
- base::RetainedRef(base::ThreadTaskRunnerHandle::Get()),
- base::BindOnce(&QuotaManager::DidGetSettings,
- weak_factory_.GetWeakPtr()))));
-}
-
-void QuotaManager::DidGetSettings(base::Optional<QuotaSettings> settings) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (!settings) {
- settings = settings_;
- settings->refresh_interval = base::TimeDelta::FromMinutes(1);
- }
- SetQuotaSettings(*settings);
- settings_callbacks_.Run(*settings);
- UMA_HISTOGRAM_MBYTES("Quota.GlobalTemporaryPoolSize", settings->pool_size);
- LOG_IF(WARNING, settings->pool_size == 0)
- << "No storage quota provided in QuotaSettings.";
-}
-
-void QuotaManager::GetStorageCapacity(StorageCapacityCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (!storage_capacity_callbacks_.Add(std::move(callback)))
- return;
- if (is_incognito_) {
- GetQuotaSettings(
- base::BindOnce(&QuotaManager::ContinueIncognitoGetStorageCapacity,
- weak_factory_.GetWeakPtr()));
- return;
- }
- base::PostTaskAndReplyWithResult(
- db_runner_.get(), FROM_HERE,
- base::BindOnce(&QuotaManager::CallGetVolumeInfo, get_volume_info_fn_,
- profile_path_),
- base::BindOnce(&QuotaManager::DidGetStorageCapacity,
- weak_factory_.GetWeakPtr()));
-}
-
-void QuotaManager::ContinueIncognitoGetStorageCapacity(
- const QuotaSettings& settings) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- int64_t current_usage =
- GetUsageTracker(StorageType::kTemporary)->GetCachedUsage();
- current_usage += GetUsageTracker(StorageType::kPersistent)->GetCachedUsage();
- int64_t available_space =
- std::max(INT64_C(0), settings.pool_size - current_usage);
- DidGetStorageCapacity(std::make_tuple(settings.pool_size, available_space));
-}
-
-void QuotaManager::DidGetStorageCapacity(
- const std::tuple<int64_t, int64_t>& total_and_available) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- cached_disk_stats_for_storage_pressure_ =
- std::make_tuple(base::TimeTicks::Now(), std::get<0>(total_and_available),
- std::get<1>(total_and_available));
- storage_capacity_callbacks_.Run(std::get<0>(total_and_available),
- std::get<1>(total_and_available));
-}
-
-void QuotaManager::DidDatabaseWork(bool success) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- db_disabled_ = !success;
-}
-
-void QuotaManager::PostTaskAndReplyWithResultForDBThread(
- const base::Location& from_here,
- base::OnceCallback<bool(QuotaDatabase*)> task,
- base::OnceCallback<void(bool)> reply) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // Deleting manager will post another task to DB sequence to delete
- // |database_|, therefore we can be sure that database_ is alive when this
- // task runs.
- base::PostTaskAndReplyWithResult(
- db_runner_.get(), from_here,
- base::BindOnce(std::move(task), base::Unretained(database_.get())),
- std::move(reply));
-}
-
-// static
-std::tuple<int64_t, int64_t> QuotaManager::CallGetVolumeInfo(
- GetVolumeInfoFn get_volume_info_fn,
- const base::FilePath& path) {
- if (!base::CreateDirectory(path)) {
- LOG(WARNING) << "Create directory failed for path" << path.value();
- return std::make_tuple<int64_t, int64_t>(0, 0);
- }
- int64_t total;
- int64_t available;
- std::tie(total, available) = get_volume_info_fn(path);
- if (total < 0 || available < 0) {
- LOG(WARNING) << "Unable to get volume info: " << path.value();
- return std::make_tuple<int64_t, int64_t>(0, 0);
- }
- UMA_HISTOGRAM_MBYTES("Quota.TotalDiskSpace", total);
- UMA_HISTOGRAM_MBYTES("Quota.AvailableDiskSpace", available);
- if (total > 0) {
- UMA_HISTOGRAM_PERCENTAGE("Quota.PercentDiskAvailable",
- std::min(100, static_cast<int>((available * 100) / total)));
- }
- return std::make_tuple(total, available);
-}
-
-// static
-std::tuple<int64_t, int64_t> QuotaManager::GetVolumeInfo(
- const base::FilePath& path) {
- return std::make_tuple(base::SysInfo::AmountOfTotalDiskSpace(path),
- base::SysInfo::AmountOfFreeDiskSpace(path));
-}
+ : QuotaManagerImpl(is_incognito,
+ profile_path,
+ std::move(io_thread),
+ std::move(quota_change_callback),
+ std::move(special_storage_policy),
+ get_settings_function) {}
+
+QuotaManager::~QuotaManager() = default;
} // namespace storage
diff --git a/chromium/storage/browser/quota/quota_manager.h b/chromium/storage/browser/quota/quota_manager.h
index 75b74e97f7a..309fd4a34a1 100644
--- a/chromium/storage/browser/quota/quota_manager.h
+++ b/chromium/storage/browser/quota/quota_manager.h
@@ -1,579 +1,31 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2021 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_QUOTA_MANAGER_H_
#define STORAGE_BROWSER_QUOTA_QUOTA_MANAGER_H_
-#include <stdint.h>
-
-#include <list>
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/component_export.h"
-#include "base/containers/flat_set.h"
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/ref_counted_delete_on_sequence.h"
-#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
-#include "base/sequence_checker.h"
-#include "base/stl_util.h"
-#include "base/timer/timer.h"
-#include "storage/browser/quota/quota_callbacks.h"
-#include "storage/browser/quota/quota_client.h"
-#include "storage/browser/quota/quota_client_type.h"
-#include "storage/browser/quota/quota_database.h"
-#include "storage/browser/quota/quota_settings.h"
-#include "storage/browser/quota/quota_task.h"
-#include "storage/browser/quota/special_storage_policy.h"
-#include "third_party/blink/public/mojom/quota/quota_types.mojom-forward.h"
-#include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h"
-#include "url/origin.h"
-
-namespace base {
-class SequencedTaskRunner;
-class SingleThreadTaskRunner;
-class TaskRunner;
-} // namespace base
-
-namespace quota_internals {
-class QuotaInternalsProxy;
-} // namespace quota_internals
+#include "storage/browser/quota/quota_manager_impl.h"
namespace storage {
-class QuotaManagerProxy;
-class QuotaOverrideHandle;
-class QuotaTemporaryStorageEvictor;
-class UsageTracker;
-
-// 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 =
- base::OnceCallback<void(blink::mojom::QuotaStatusCode status,
- const QuotaSettings& settings,
- int64_t available_space,
- int64_t total_space,
- int64_t global_usage,
- bool global_usage_is_complete)>;
-
- // Called at the beginning of an eviction round to gather the info about
- // the current settings, capacity, and usage.
- virtual void GetEvictionRoundInfo(EvictionRoundInfoCallback callback) = 0;
-
- // Returns next origin to evict, or nullopt if there are no evictable
- // origins.
- virtual void GetEvictionOrigin(blink::mojom::StorageType type,
- int64_t global_quota,
- GetOriginCallback callback) = 0;
-
- // Called to evict an origin.
- virtual void EvictOriginData(const url::Origin& origin,
- blink::mojom::StorageType type,
- StatusCallback callback) = 0;
-
- protected:
- virtual ~QuotaEvictionHandler() = default;
-};
-
-struct UsageInfo {
- UsageInfo(std::string host, blink::mojom::StorageType type, int64_t usage)
- : host(std::move(host)), type(type), usage(usage) {}
- const std::string host;
- const blink::mojom::StorageType type;
- const int64_t usage;
-};
-
-// Entry point into the Quota System
+// QuotaManager will eventually become a mojo interface facilitating
+// inter-process access to QuotaManagerImpl. As an intermediary step,
+// QuotaManager will become an abstract base class, which will be implemented by
+// QuotaManagerProxy.
//
-// 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,
- public base::RefCountedDeleteOnSequence<QuotaManager> {
+// As a first step, QuotaManager is an alias for QuotaManagerImpl.
+class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager : public QuotaManagerImpl {
public:
- using UsageAndQuotaCallback = base::OnceCallback<
- void(blink::mojom::QuotaStatusCode, int64_t usage, int64_t quota)>;
-
- using UsageAndQuotaWithBreakdownCallback =
- base::OnceCallback<void(blink::mojom::QuotaStatusCode,
- int64_t usage,
- int64_t quota,
- blink::mojom::UsageBreakdownPtr usage_breakdown)>;
-
- using UsageAndQuotaForDevtoolsCallback =
- base::OnceCallback<void(blink::mojom::QuotaStatusCode,
- int64_t usage,
- int64_t quota,
- bool is_override_enabled,
- blink::mojom::UsageBreakdownPtr usage_breakdown)>;
-
- static constexpr int64_t kGBytes = 1024 * 1024 * 1024;
- static constexpr int64_t kNoLimit = INT64_MAX;
- static constexpr int64_t kMBytes = 1024 * 1024;
- static constexpr int kMinutesInMilliSeconds = 60 * 1000;
-
QuotaManager(bool is_incognito,
const base::FilePath& profile_path,
scoped_refptr<base::SingleThreadTaskRunner> io_thread,
+ base::RepeatingClosure quota_change_callback,
scoped_refptr<SpecialStoragePolicy> special_storage_policy,
const GetQuotaSettingsFunc& get_settings_function);
- const QuotaSettings& settings() const { return settings_; }
- void SetQuotaSettings(const QuotaSettings& settings);
-
- // Returns a proxy object that can be used on any thread.
- QuotaManagerProxy* proxy() { return proxy_.get(); }
-
- // Called by clients or webapps. Returns usage per host.
- void GetUsageInfo(GetUsageInfoCallback callback);
-
- // Called by Web Apps (deprecated quota API).
- // This method is declared as virtual to allow test code to override it.
- virtual void GetUsageAndQuotaForWebApps(const url::Origin& origin,
- blink::mojom::StorageType type,
- UsageAndQuotaCallback callback);
-
- // Called by Web Apps (navigator.storage.estimate())
- // This method is declared as virtual to allow test code to override it.
- virtual void GetUsageAndQuotaWithBreakdown(
- const url::Origin& origin,
- blink::mojom::StorageType type,
- UsageAndQuotaWithBreakdownCallback callback);
-
- // Called by DevTools.
- virtual void GetUsageAndQuotaForDevtools(
- const url::Origin& origin,
- blink::mojom::StorageType type,
- UsageAndQuotaForDevtoolsCallback callback);
-
- // Called by storage backends.
- //
- // For UnlimitedStorage origins, this version skips usage and quota handling
- // to avoid extra query cost. Do not call this method for apps/user-facing
- // code.
- //
- // This method is declared as virtual to allow test code to override it.
- virtual void GetUsageAndQuota(const url::Origin& origin,
- blink::mojom::StorageType type,
- UsageAndQuotaCallback callback);
-
- // Called by storage backends via proxy.
- //
- // Quota-managed storage backends should call this method when storage is
- // accessed. Used to maintain LRU ordering.
- void NotifyStorageAccessed(const url::Origin& origin,
- blink::mojom::StorageType type);
-
- // Called by storage backends via proxy.
- //
- // Quota-managed storage backends must call this method when they have made
- // any modifications that change the amount of data stored in their storage.
- void NotifyStorageModified(QuotaClientType client_id,
- const url::Origin& origin,
- blink::mojom::StorageType type,
- int64_t delta);
-
- // Called by storage backends via proxy.
- //
- // Client storage must call this method whenever they run into disk
- // write errors. Used as a hint to determine if the storage partition is out
- // of space, and trigger actions if deemed appropriate.
- //
- // This method is declared as virtual to allow test code to override it.
- virtual void NotifyWriteFailed(const url::Origin& origin);
-
- // Used to avoid evicting origins with open pages.
- // A call to NotifyOriginInUse must be balanced by a later call
- // to NotifyOriginNoLongerInUse.
- void NotifyOriginInUse(const url::Origin& origin);
- void NotifyOriginNoLongerInUse(const url::Origin& origin);
- bool IsOriginInUse(const url::Origin& origin) const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return base::Contains(origins_in_use_, origin);
- }
-
- void SetUsageCacheEnabled(QuotaClientType client_id,
- const url::Origin& origin,
- blink::mojom::StorageType type,
- bool enabled);
-
- // DeleteOriginData and DeleteHostData (surprisingly enough) delete data of a
- // particular blink::mojom::StorageType associated with either a specific
- // origin or set of origins. Each method additionally requires a
- // |quota_client_types| which specifies the types of QuotaClients to delete
- // from the origin. Pass in QuotaClientType::AllClients() to remove all
- // clients from the origin, regardless of type.
- virtual void DeleteOriginData(const url::Origin& origin,
- blink::mojom::StorageType type,
- QuotaClientTypes quota_client_types,
- StatusCallback callback);
- void DeleteHostData(const std::string& host,
- blink::mojom::StorageType type,
- QuotaClientTypes quota_client_types,
- StatusCallback callback);
-
- // Instructs each QuotaClient to remove possible traces of deleted
- // data on the disk.
- void PerformStorageCleanup(blink::mojom::StorageType type,
- QuotaClientTypes quota_client_types,
- base::OnceClosure callback);
-
- // Called by UI and internal modules.
- void GetPersistentHostQuota(const std::string& host, QuotaCallback callback);
- void SetPersistentHostQuota(const std::string& host,
- int64_t new_quota,
- QuotaCallback callback);
- void GetGlobalUsage(blink::mojom::StorageType type,
- GlobalUsageCallback callback);
- void GetHostUsageWithBreakdown(const std::string& host,
- blink::mojom::StorageType type,
- UsageWithBreakdownCallback callback);
-
- std::map<std::string, std::string> GetStatistics();
-
- bool IsStorageUnlimited(const url::Origin& origin,
- blink::mojom::StorageType type) const;
-
- virtual void GetOriginsModifiedBetween(blink::mojom::StorageType type,
- base::Time begin,
- base::Time end,
- GetOriginsCallback callback);
-
- bool ResetUsageTracker(blink::mojom::StorageType type);
-
- // Called when StoragePartition is initialized if embedder has an
- // implementation of StorageNotificationService.
- void SetStoragePressureCallback(
- base::RepeatingCallback<void(url::Origin)> storage_pressure_callback);
-
- // DevTools Quota Override methods:
- int GetOverrideHandleId();
- void OverrideQuotaForOrigin(int handle_id,
- const url::Origin& origin,
- base::Optional<int64_t> quota_size);
- // Called when a DevTools client releases all overrides, however, overrides
- // will not be disabled for any origins for which there are other DevTools
- // clients/QuotaOverrideHandle with an active override.
- void WithdrawOverridesForHandle(int handle_id);
-
- // Cap size for per-host persistent quota determined by the histogram.
- // This is a bit lax value because the histogram says nothing about per-host
- // persistent storage usage and we determined by global persistent storage
- // usage that is less than 10GB for almost all users.
- static constexpr int64_t kPerHostPersistentQuotaLimit = 10 * 1024 * kMBytes;
-
- static constexpr int kEvictionIntervalInMilliSeconds =
- 30 * kMinutesInMilliSeconds;
- static constexpr int kThresholdOfErrorsToBeDenylisted = 3;
- static constexpr int kThresholdRandomizationPercent = 5;
-
- static constexpr char kDatabaseName[] = "QuotaManager";
- static constexpr char kDaysBetweenRepeatedOriginEvictionsHistogram[] =
- "Quota.DaysBetweenRepeatedOriginEvictions";
- static constexpr char kEvictedOriginAccessedCountHistogram[] =
- "Quota.EvictedOriginAccessCount";
- static constexpr char kEvictedOriginDaysSinceAccessHistogram[] =
- "Quota.EvictedOriginDaysSinceAccess";
-
- // Kept non-const so that test code can change the value.
- // TODO(kinuko): Make this a real const value and add a proper way to set
- // the quota for syncable storage. (http://crbug.com/155488)
- static int64_t kSyncableStorageDefaultHostQuota;
-
- void DisableDatabaseForTesting() { db_disabled_ = true; }
-
protected:
~QuotaManager() override;
-
- private:
- friend class base::DeleteHelper<QuotaManager>;
- friend class base::RefCountedDeleteOnSequence<QuotaManager>;
- friend class quota_internals::QuotaInternalsProxy;
- friend class MockQuotaManager;
- friend class MockQuotaClient;
- friend class QuotaManagerProxy;
- friend class QuotaManagerTest;
- friend class QuotaTemporaryStorageEvictor;
-
- class EvictionRoundInfoHelper;
- class UsageAndQuotaInfoGatherer;
- class GetUsageInfoTask;
- class OriginDataDeleter;
- class HostDataDeleter;
- class GetModifiedSinceHelper;
- class DumpQuotaTableHelper;
- class DumpOriginInfoTableHelper;
- class StorageCleanupHelper;
-
- struct QuotaOverride {
- QuotaOverride();
- ~QuotaOverride();
-
- QuotaOverride(const QuotaOverride& quota_override) = delete;
- QuotaOverride& operator=(const QuotaOverride&) = delete;
-
- int64_t quota_size;
-
- // Keeps track of the DevTools clients that have an active override.
- std::set<int> active_override_session_ids;
- };
-
- using QuotaTableEntry = QuotaDatabase::QuotaTableEntry;
- using OriginInfoTableEntry = QuotaDatabase::OriginInfoTableEntry;
- using QuotaTableEntries = std::vector<QuotaTableEntry>;
- using OriginInfoTableEntries = std::vector<OriginInfoTableEntry>;
-
- using QuotaSettingsCallback = base::OnceCallback<void(const QuotaSettings&)>;
-
- // Function pointer type used to store the function which returns
- // information about the volume containing the given FilePath.
- // The value returned is std::tuple<total_space, available_space>.
- using GetVolumeInfoFn =
- std::tuple<int64_t, int64_t> (*)(const base::FilePath&);
-
- using DumpQuotaTableCallback =
- base::OnceCallback<void(const QuotaTableEntries&)>;
- using DumpOriginInfoTableCallback =
- base::OnceCallback<void(const OriginInfoTableEntries&)>;
-
- // The values returned total_space, available_space.
- using StorageCapacityCallback = base::OnceCallback<void(int64_t, int64_t)>;
-
- struct EvictionContext {
- EvictionContext();
- ~EvictionContext();
- url::Origin evicted_origin;
- blink::mojom::StorageType evicted_type;
- StatusCallback evict_origin_data_callback;
- };
-
- // Lazily called on the IO thread when the first quota manager API is called.
- //
- // Initialize() must be called after all quota clients are added to the
- // manager by RegisterClient.
- void LazyInitialize();
- void FinishLazyInitialize(bool is_database_bootstraped);
- void BootstrapDatabaseForEviction(GetOriginCallback did_get_origin_callback,
- int64_t unused_usage,
- int64_t unused_unlimited_usage);
- void DidBootstrapDatabase(GetOriginCallback did_get_origin_callback,
- bool success);
-
- // Called by clients via proxy.
- // Registers a quota client to the manager.
- void RegisterClient(
- scoped_refptr<QuotaClient> client,
- QuotaClientType client_type,
- const std::vector<blink::mojom::StorageType>& storage_types);
-
- UsageTracker* GetUsageTracker(blink::mojom::StorageType type) const;
-
- // Extract cached origins list from the usage tracker.
- // (Might return empty list if no origin is tracked by the tracker.)
- std::set<url::Origin> GetCachedOrigins(blink::mojom::StorageType type);
-
- // These internal methods are separately defined mainly for testing.
- void NotifyStorageAccessedInternal(const url::Origin& origin,
- blink::mojom::StorageType type,
- base::Time accessed_time);
- void NotifyStorageModifiedInternal(QuotaClientType client_id,
- const url::Origin& origin,
- blink::mojom::StorageType type,
- int64_t delta,
- base::Time modified_time);
-
- void DumpQuotaTable(DumpQuotaTableCallback callback);
- void DumpOriginInfoTable(DumpOriginInfoTableCallback callback);
-
- void DeleteOriginDataInternal(const url::Origin& origin,
- blink::mojom::StorageType type,
- QuotaClientTypes quota_client_types,
- bool is_eviction,
- StatusCallback callback);
-
- // Methods for eviction logic.
- void StartEviction();
- void DeleteOriginFromDatabase(const url::Origin& origin,
- blink::mojom::StorageType type,
- bool is_eviction);
-
- void DidOriginDataEvicted(blink::mojom::QuotaStatusCode status);
-
- void ReportHistogram();
- void DidGetTemporaryGlobalUsageForHistogram(int64_t usage,
- int64_t unlimited_usage);
- void DidGetStorageCapacityForHistogram(int64_t usage,
- int64_t total_space,
- int64_t available_space);
- void DidGetPersistentGlobalUsageForHistogram(int64_t usage,
- int64_t unlimited_usage);
- void DidDumpOriginInfoTableForHistogram(
- const OriginInfoTableEntries& entries);
-
- std::set<url::Origin> GetEvictionOriginExceptions();
- void DidGetEvictionOrigin(GetOriginCallback callback,
- const base::Optional<url::Origin>& origin);
-
- // QuotaEvictionHandler.
- void GetEvictionOrigin(blink::mojom::StorageType type,
- int64_t global_quota,
- GetOriginCallback callback) override;
- void EvictOriginData(const url::Origin& origin,
- blink::mojom::StorageType type,
- StatusCallback callback) override;
- void GetEvictionRoundInfo(EvictionRoundInfoCallback callback) override;
-
- void GetLRUOrigin(blink::mojom::StorageType type, GetOriginCallback callback);
-
- void DidGetPersistentHostQuota(const std::string& host,
- const int64_t* quota,
- bool success);
- void DidSetPersistentHostQuota(const std::string& host,
- QuotaCallback callback,
- const int64_t* new_quota,
- bool success);
- void DidGetLRUOrigin(std::unique_ptr<base::Optional<url::Origin>> origin,
- bool success);
- void GetQuotaSettings(QuotaSettingsCallback callback);
- void DidGetSettings(base::Optional<QuotaSettings> settings);
- void GetStorageCapacity(StorageCapacityCallback callback);
- void ContinueIncognitoGetStorageCapacity(const QuotaSettings& settings);
- void DidGetStorageCapacity(
- const std::tuple<int64_t, int64_t>& total_and_available);
-
- void DidDatabaseWork(bool success);
-
- void DeleteOnCorrectThread() const;
-
- void MaybeRunStoragePressureCallback(const url::Origin& origin,
- int64_t total_space,
- int64_t available_space);
- // Used from quota-internals page to test behavior of the storage pressure
- // callback.
- void SimulateStoragePressure(const url::Origin origin);
-
- // Evaluates disk statistics to identify storage pressure
- // (low disk space availability) and starts the storage
- // pressure event dispatch if appropriate.
- // TODO(crbug.com/1088004): Implement UsageAndQuotaInfoGatherer::Completed()
- // to use DetermineStoragePressure().
- // TODO(crbug.com/1102433): Define and explain StoragePressure in the README.
- void DetermineStoragePressure(int64_t free_space, int64_t total_space);
-
- base::Optional<int64_t> GetQuotaOverrideForOrigin(const url::Origin&);
-
- void PostTaskAndReplyWithResultForDBThread(
- const base::Location& from_here,
- base::OnceCallback<bool(QuotaDatabase*)> task,
- base::OnceCallback<void(bool)> reply);
-
- static std::tuple<int64_t, int64_t> CallGetVolumeInfo(
- GetVolumeInfoFn get_volume_info_fn,
- const base::FilePath& path);
- static std::tuple<int64_t, int64_t> GetVolumeInfo(const base::FilePath& path);
-
- const bool is_incognito_;
- const base::FilePath profile_path_;
-
- // proxy_ can be accessed by any thread so it must be thread-safe
- const scoped_refptr<QuotaManagerProxy> proxy_;
- bool db_disabled_;
- bool eviction_disabled_;
- base::Optional<url::Origin> origin_for_pending_storage_pressure_callback_;
- scoped_refptr<base::SingleThreadTaskRunner> io_thread_;
- scoped_refptr<base::SequencedTaskRunner> db_runner_;
- mutable std::unique_ptr<QuotaDatabase> database_;
- bool is_database_bootstrapped_ = false;
-
- GetQuotaSettingsFunc get_settings_function_;
- scoped_refptr<base::TaskRunner> get_settings_task_runner_;
- base::RepeatingCallback<void(url::Origin)> storage_pressure_callback_;
- QuotaSettings settings_;
- base::TimeTicks settings_timestamp_;
- std::tuple<base::TimeTicks, int64_t, int64_t>
- cached_disk_stats_for_storage_pressure_;
- CallbackQueue<QuotaSettingsCallback, const QuotaSettings&>
- settings_callbacks_;
- CallbackQueue<StorageCapacityCallback, int64_t, int64_t>
- storage_capacity_callbacks_;
-
- GetOriginCallback lru_origin_callback_;
- std::set<url::Origin> access_notified_origins_;
-
- std::map<url::Origin, QuotaOverride> devtools_overrides_;
- int next_override_handle_id_ = 0;
-
- // Owns the QuotaClient instances registered via RegisterClient().
- //
- // Iterating over this list is almost always incorrect. Most algorithms should
- // iterate over an entry in |client_types_|.
- std::vector<scoped_refptr<QuotaClient>> clients_for_ownership_;
- // Maps QuotaClient instances to client types.
- //
- // The QuotaClient instances pointed to by the map keys are guaranteed to be
- // alive, because they are owned by |clients_for_ownership_|.
- base::flat_map<blink::mojom::StorageType,
- base::flat_map<QuotaClient*, QuotaClientType>>
- client_types_;
-
- std::unique_ptr<UsageTracker> temporary_usage_tracker_;
- std::unique_ptr<UsageTracker> persistent_usage_tracker_;
- std::unique_ptr<UsageTracker> syncable_usage_tracker_;
- // TODO(michaeln): Need a way to clear the cache, drop and
- // reinstantiate the trackers when they're not handling requests.
-
- std::unique_ptr<QuotaTemporaryStorageEvictor> temporary_storage_evictor_;
- EvictionContext eviction_context_;
- bool is_getting_eviction_origin_;
-
- CallbackQueueMap<QuotaCallback,
- std::string,
- blink::mojom::QuotaStatusCode,
- int64_t>
- persistent_host_quota_callbacks_;
-
- // Map from origin to count.
- std::map<url::Origin, int> origins_in_use_;
- // Map from origin to error count.
- std::map<url::Origin, int> origins_in_error_;
-
- scoped_refptr<SpecialStoragePolicy> special_storage_policy_;
-
- base::RepeatingTimer histogram_timer_;
-
- // Pointer to the function used to get volume information. This is
- // overwritten by QuotaManagerTest in order to attain deterministic reported
- // values. The default value points to QuotaManager::GetVolumeInfo.
- GetVolumeInfoFn get_volume_info_fn_;
-
- SEQUENCE_CHECKER(sequence_checker_);
-
- base::WeakPtrFactory<QuotaManager> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(QuotaManager);
};
} // namespace storage
diff --git a/chromium/storage/browser/quota/quota_manager_impl.cc b/chromium/storage/browser/quota/quota_manager_impl.cc
new file mode 100644
index 00000000000..727512649d8
--- /dev/null
+++ b/chromium/storage/browser/quota/quota_manager_impl.cc
@@ -0,0 +1,1999 @@
+// Copyright 2013 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/quota_manager_impl.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <algorithm>
+#include <functional>
+#include <limits>
+#include <memory>
+#include <utility>
+
+#include "base/barrier_closure.h"
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/rand_util.h"
+#include "base/sequence_checker.h"
+#include "base/sequenced_task_runner.h"
+#include "base/single_thread_task_runner.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/system/sys_info.h"
+#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
+#include "base/task_runner_util.h"
+#include "base/threading/thread_restrictions.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
+#include "base/types/pass_key.h"
+#include "components/services/storage/public/mojom/quota_client.mojom.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "storage/browser/quota/client_usage_tracker.h"
+#include "storage/browser/quota/mojo_quota_client_wrapper.h"
+#include "storage/browser/quota/quota_client_type.h"
+#include "storage/browser/quota/quota_features.h"
+#include "storage/browser/quota/quota_macros.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+#include "storage/browser/quota/quota_override_handle.h"
+#include "storage/browser/quota/quota_temporary_storage_evictor.h"
+#include "storage/browser/quota/usage_tracker.h"
+#include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h"
+
+using blink::mojom::StorageType;
+
+namespace storage {
+
+namespace {
+
+constexpr int64_t kReportHistogramInterval = 60 * 60 * 1000; // 1 hour
+
+// Take action on write errors if there is <= 2% disk space
+// available.
+constexpr double kStoragePressureThresholdRatio = 0.02;
+
+// Limit how frequently QuotaManagerImpl polls for free disk space when
+// only using that information to identify storage pressure.
+constexpr base::TimeDelta kStoragePressureCheckDiskStatsInterval =
+ base::TimeDelta::FromMinutes(5);
+
+// Modifies a given value by a uniformly random amount from
+// -percent to +percent.
+int64_t RandomizeByPercent(int64_t value, int percent) {
+ double random_percent = (base::RandDouble() - 0.5) * percent * 2;
+ return value * (1 + (random_percent / 100.0));
+}
+} // namespace
+
+// Heuristics: assuming average cloud server allows a few Gigs storage
+// on the server side and the storage needs to be shared for user data
+// and by multiple apps.
+int64_t QuotaManagerImpl::kSyncableStorageDefaultHostQuota = 500 * kMBytes;
+
+namespace {
+
+bool IsSupportedType(StorageType type) {
+ return type == StorageType::kTemporary || type == StorageType::kPersistent ||
+ type == StorageType::kSyncable;
+}
+
+bool IsSupportedIncognitoType(StorageType type) {
+ return type == StorageType::kTemporary || type == StorageType::kPersistent;
+}
+
+bool GetPersistentHostQuotaOnDBThread(const std::string& host,
+ int64_t* quota,
+ QuotaDatabase* database) {
+ DCHECK(database);
+ database->GetHostQuota(host, StorageType::kPersistent, quota);
+ return true;
+}
+
+bool SetPersistentHostQuotaOnDBThread(const std::string& host,
+ int64_t* new_quota,
+ QuotaDatabase* database) {
+ DCHECK(database);
+ if (database->SetHostQuota(host, StorageType::kPersistent, *new_quota))
+ return true;
+ *new_quota = 0;
+ return false;
+}
+
+bool GetLRUOriginOnDBThread(StorageType type,
+ const std::set<url::Origin>& exceptions,
+ SpecialStoragePolicy* policy,
+ base::Optional<url::Origin>* origin,
+ QuotaDatabase* database) {
+ DCHECK(database);
+ database->GetLRUOrigin(type, exceptions, policy, origin);
+ return true;
+}
+
+bool DeleteOriginInfoOnDBThread(const url::Origin& origin,
+ StorageType type,
+ bool is_eviction,
+ QuotaDatabase* database) {
+ DCHECK(database);
+
+ base::Time now = base::Time::Now();
+
+ if (is_eviction) {
+ QuotaDatabase::OriginInfoTableEntry entry;
+ database->GetOriginInfo(origin, type, &entry);
+ UMA_HISTOGRAM_COUNTS_1M(
+ QuotaManagerImpl::kEvictedOriginAccessedCountHistogram,
+ entry.used_count);
+ UMA_HISTOGRAM_COUNTS_1000(
+ QuotaManagerImpl::kEvictedOriginDaysSinceAccessHistogram,
+ (now - entry.last_access_time).InDays());
+ }
+
+ if (!database->DeleteOriginInfo(origin, type))
+ return false;
+
+ // If the deletion is not due to an eviction, delete the entry in the eviction
+ // table as well due to privacy concerns.
+ if (!is_eviction)
+ return database->DeleteOriginLastEvictionTime(origin, type);
+
+ base::Time last_eviction_time;
+ database->GetOriginLastEvictionTime(origin, type, &last_eviction_time);
+
+ if (last_eviction_time != base::Time()) {
+ UMA_HISTOGRAM_COUNTS_1000(
+ QuotaManagerImpl::kDaysBetweenRepeatedOriginEvictionsHistogram,
+ (now - last_eviction_time).InDays());
+ }
+
+ return database->SetOriginLastEvictionTime(origin, type, now);
+}
+
+bool BootstrapDatabaseOnDBThread(std::set<url::Origin> origins,
+ QuotaDatabase* database) {
+ DCHECK(database);
+ if (database->IsOriginDatabaseBootstrapped())
+ return true;
+
+ // Register existing origins with 0 last time access.
+ if (database->RegisterInitialOriginInfo(origins, StorageType::kTemporary)) {
+ database->SetOriginDatabaseBootstrapped(true);
+ return true;
+ }
+ return false;
+}
+
+bool UpdateAccessTimeOnDBThread(const url::Origin& origin,
+ StorageType type,
+ base::Time accessed_time,
+ QuotaDatabase* database) {
+ DCHECK(database);
+ return database->SetOriginLastAccessTime(origin, type, accessed_time);
+}
+
+bool UpdateModifiedTimeOnDBThread(const url::Origin& origin,
+ StorageType type,
+ base::Time modified_time,
+ QuotaDatabase* database) {
+ DCHECK(database);
+ return database->SetOriginLastModifiedTime(origin, type, modified_time);
+}
+
+void DidGetUsageAndQuotaStripBreakdown(
+ QuotaManagerImpl::UsageAndQuotaCallback callback,
+ blink::mojom::QuotaStatusCode status,
+ int64_t usage,
+ int64_t quota,
+ blink::mojom::UsageBreakdownPtr usage_breakdown) {
+ std::move(callback).Run(status, usage, quota);
+}
+
+void DidGetUsageAndQuotaStripOverride(
+ QuotaManagerImpl::UsageAndQuotaWithBreakdownCallback callback,
+ blink::mojom::QuotaStatusCode status,
+ int64_t usage,
+ int64_t quota,
+ bool is_override_enabled,
+ blink::mojom::UsageBreakdownPtr usage_breakdown) {
+ std::move(callback).Run(status, usage, quota, std::move(usage_breakdown));
+}
+
+} // namespace
+
+constexpr int64_t QuotaManagerImpl::kGBytes;
+constexpr int64_t QuotaManagerImpl::kNoLimit;
+constexpr int64_t QuotaManagerImpl::kPerHostPersistentQuotaLimit;
+constexpr int QuotaManagerImpl::kEvictionIntervalInMilliSeconds;
+constexpr int QuotaManagerImpl::kThresholdOfErrorsToBeDenylisted;
+constexpr int QuotaManagerImpl::kThresholdRandomizationPercent;
+constexpr char QuotaManagerImpl::kDatabaseName[];
+constexpr char QuotaManagerImpl::kDaysBetweenRepeatedOriginEvictionsHistogram[];
+constexpr char QuotaManagerImpl::kEvictedOriginAccessedCountHistogram[];
+constexpr char QuotaManagerImpl::kEvictedOriginDaysSinceAccessHistogram[];
+
+QuotaManagerImpl::QuotaOverride::QuotaOverride() = default;
+QuotaManagerImpl::QuotaOverride::~QuotaOverride() = default;
+
+class QuotaManagerImpl::UsageAndQuotaInfoGatherer : public QuotaTask {
+ public:
+ UsageAndQuotaInfoGatherer(QuotaManagerImpl* manager,
+ const url::Origin& origin,
+ StorageType type,
+ bool is_unlimited,
+ bool is_session_only,
+ bool is_incognito,
+ base::Optional<int64_t> quota_override_size,
+ UsageAndQuotaForDevtoolsCallback callback)
+ : QuotaTask(manager),
+ origin_(origin),
+ callback_(std::move(callback)),
+ type_(type),
+ is_unlimited_(is_unlimited),
+ is_session_only_(is_session_only),
+ is_incognito_(is_incognito),
+ is_override_enabled_(quota_override_size.has_value()),
+ quota_override_size_(quota_override_size) {}
+
+ protected:
+ void Run() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // Start the async process of gathering the info we need.
+ // Gather 4 pieces of info before computing an answer:
+ // settings, device_storage_capacity, host_usage, and host_quota.
+ base::RepeatingClosure barrier = base::BarrierClosure(
+ 4, base::BindOnce(&UsageAndQuotaInfoGatherer::OnBarrierComplete,
+ weak_factory_.GetWeakPtr()));
+
+ const std::string& host = origin_.host();
+
+ manager()->GetQuotaSettings(
+ base::BindOnce(&UsageAndQuotaInfoGatherer::OnGotSettings,
+ weak_factory_.GetWeakPtr(), barrier));
+ manager()->GetStorageCapacity(
+ base::BindOnce(&UsageAndQuotaInfoGatherer::OnGotCapacity,
+ weak_factory_.GetWeakPtr(), barrier));
+ manager()->GetHostUsageWithBreakdown(
+ host, type_,
+ base::BindOnce(&UsageAndQuotaInfoGatherer::OnGotHostUsage,
+ weak_factory_.GetWeakPtr(), barrier));
+
+ // Determine host_quota differently depending on type.
+ if (is_unlimited_) {
+ SetDesiredHostQuota(barrier, blink::mojom::QuotaStatusCode::kOk,
+ kNoLimit);
+ } else if (type_ == StorageType::kSyncable) {
+ SetDesiredHostQuota(barrier, blink::mojom::QuotaStatusCode::kOk,
+ kSyncableStorageDefaultHostQuota);
+ } else if (type_ == StorageType::kPersistent) {
+ manager()->GetPersistentHostQuota(
+ host, base::BindOnce(&UsageAndQuotaInfoGatherer::SetDesiredHostQuota,
+ weak_factory_.GetWeakPtr(), barrier));
+ } else {
+ DCHECK_EQ(StorageType::kTemporary, type_);
+ // For temporary storage, OnGotSettings will set the host quota.
+ }
+ }
+
+ void Aborted() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ weak_factory_.InvalidateWeakPtrs();
+ std::move(callback_).Run(blink::mojom::QuotaStatusCode::kErrorAbort,
+ /*usage=*/0,
+ /*quota=*/0,
+ /*is_override_enabled=*/false,
+ /*usage_breakdown=*/nullptr);
+ DeleteSoon();
+ }
+
+ void Completed() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ weak_factory_.InvalidateWeakPtrs();
+
+ int64_t host_quota = quota_override_size_.has_value()
+ ? quota_override_size_.value()
+ : desired_host_quota_;
+ 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_;
+ }
+ }
+
+ std::move(callback_).Run(blink::mojom::QuotaStatusCode::kOk, host_usage_,
+ host_quota, is_override_enabled_,
+ std::move(host_usage_breakdown_));
+ 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) {
+ UMA_HISTOGRAM_PERCENTAGE("Quota.PercentUsedByOrigin",
+ std::min(100, static_cast<int>((host_usage_ * 100) / host_quota)));
+ }
+ }
+ DeleteSoon();
+ }
+
+ private:
+ QuotaManagerImpl* manager() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return static_cast<QuotaManagerImpl*>(observer());
+ }
+
+ void OnGotSettings(base::RepeatingClosure barrier_closure,
+ const QuotaSettings& settings) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ settings_ = settings;
+ barrier_closure.Run();
+ if (type_ == StorageType::kTemporary && !is_unlimited_) {
+ int64_t host_quota = is_session_only_
+ ? settings.session_only_per_host_quota
+ : settings.per_host_quota;
+ SetDesiredHostQuota(barrier_closure, blink::mojom::QuotaStatusCode::kOk,
+ host_quota);
+ }
+ }
+
+ void OnGotCapacity(base::OnceClosure barrier_closure,
+ int64_t total_space,
+ int64_t available_space) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ total_space_ = total_space;
+ available_space_ = available_space;
+ std::move(barrier_closure).Run();
+ }
+
+ void OnGotHostUsage(base::OnceClosure barrier_closure,
+ int64_t usage,
+ blink::mojom::UsageBreakdownPtr usage_breakdown) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ host_usage_ = usage;
+ host_usage_breakdown_ = std::move(usage_breakdown);
+ std::move(barrier_closure).Run();
+ }
+
+ void SetDesiredHostQuota(base::OnceClosure barrier_closure,
+ blink::mojom::QuotaStatusCode status,
+ int64_t quota) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ desired_host_quota_ = quota;
+ std::move(barrier_closure).Run();
+ }
+
+ void OnBarrierComplete() { CallCompleted(); }
+
+ const url::Origin origin_;
+ QuotaManagerImpl::UsageAndQuotaForDevtoolsCallback callback_;
+ const StorageType type_;
+ const bool is_unlimited_;
+ const bool is_session_only_;
+ const bool is_incognito_;
+ int64_t available_space_ = 0;
+ int64_t total_space_ = 0;
+ int64_t desired_host_quota_ = 0;
+ int64_t host_usage_ = 0;
+ const bool is_override_enabled_;
+ base::Optional<int64_t> quota_override_size_;
+ blink::mojom::UsageBreakdownPtr host_usage_breakdown_;
+ QuotaSettings settings_;
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ // Weak pointers are used to support cancelling work.
+ base::WeakPtrFactory<UsageAndQuotaInfoGatherer> weak_factory_{this};
+};
+
+class QuotaManagerImpl::EvictionRoundInfoHelper : public QuotaTask {
+ public:
+ EvictionRoundInfoHelper(QuotaManagerImpl* manager,
+ EvictionRoundInfoCallback callback)
+ : QuotaTask(manager), callback_(std::move(callback)) {}
+
+ protected:
+ void Run() override {
+ // Gather 2 pieces of info before deciding if we need to get GlobalUsage:
+ // settings and device_storage_capacity.
+ base::RepeatingClosure barrier = base::BarrierClosure(
+ 2, base::BindOnce(&EvictionRoundInfoHelper::OnBarrierComplete,
+ weak_factory_.GetWeakPtr()));
+
+ manager()->GetQuotaSettings(
+ base::BindOnce(&EvictionRoundInfoHelper::OnGotSettings,
+ weak_factory_.GetWeakPtr(), barrier));
+ manager()->GetStorageCapacity(
+ base::BindOnce(&EvictionRoundInfoHelper::OnGotCapacity,
+ weak_factory_.GetWeakPtr(), barrier));
+ }
+
+ void Aborted() override {
+ weak_factory_.InvalidateWeakPtrs();
+ std::move(callback_).Run(blink::mojom::QuotaStatusCode::kErrorAbort,
+ QuotaSettings(), 0, 0, 0, false);
+ DeleteSoon();
+ }
+
+ void Completed() override {
+ weak_factory_.InvalidateWeakPtrs();
+ std::move(callback_).Run(blink::mojom::QuotaStatusCode::kOk, settings_,
+ available_space_, total_space_, global_usage_,
+ global_usage_is_complete_);
+ DeleteSoon();
+ }
+
+ private:
+ QuotaManagerImpl* manager() const {
+ return static_cast<QuotaManagerImpl*>(observer());
+ }
+
+ void OnGotSettings(base::OnceClosure barrier_closure,
+ const QuotaSettings& settings) {
+ settings_ = settings;
+ std::move(barrier_closure).Run();
+ }
+
+ void OnGotCapacity(base::OnceClosure barrier_closure,
+ int64_t total_space,
+ int64_t available_space) {
+ total_space_ = total_space;
+ available_space_ = available_space;
+ std::move(barrier_closure).Run();
+ }
+
+ void OnBarrierComplete() {
+ // Avoid computing the full current_usage when there's no pressure.
+ int64_t consumed_space = total_space_ - available_space_;
+ if (consumed_space < settings_.pool_size &&
+ available_space_ > settings_.should_remain_available) {
+ DCHECK(!global_usage_is_complete_);
+ global_usage_ =
+ manager()->GetUsageTracker(StorageType::kTemporary)->GetCachedUsage();
+ CallCompleted();
+ return;
+ }
+ manager()->GetGlobalUsage(
+ StorageType::kTemporary,
+ base::BindOnce(&EvictionRoundInfoHelper::OnGotGlobalUsage,
+ weak_factory_.GetWeakPtr()));
+ }
+
+ void OnGotGlobalUsage(int64_t usage, int64_t unlimited_usage) {
+ global_usage_ = std::max(INT64_C(0), usage - unlimited_usage);
+ global_usage_is_complete_ = true;
+ CallCompleted();
+ }
+
+ EvictionRoundInfoCallback callback_;
+ QuotaSettings settings_;
+ int64_t available_space_ = 0;
+ int64_t total_space_ = 0;
+ int64_t global_usage_ = 0;
+ bool global_usage_is_complete_ = false;
+ base::WeakPtrFactory<EvictionRoundInfoHelper> weak_factory_{this};
+};
+
+class QuotaManagerImpl::GetUsageInfoTask : public QuotaTask {
+ public:
+ GetUsageInfoTask(QuotaManagerImpl* manager, GetUsageInfoCallback callback)
+ : QuotaTask(manager), callback_(std::move(callback)) {}
+
+ protected:
+ void Run() override {
+ remaining_trackers_ = 3;
+ // This will populate cached hosts and usage info.
+ manager()
+ ->GetUsageTracker(StorageType::kTemporary)
+ ->GetGlobalUsage(base::BindOnce(&GetUsageInfoTask::DidGetGlobalUsage,
+ weak_factory_.GetWeakPtr(),
+ StorageType::kTemporary));
+ manager()
+ ->GetUsageTracker(StorageType::kPersistent)
+ ->GetGlobalUsage(base::BindOnce(&GetUsageInfoTask::DidGetGlobalUsage,
+ weak_factory_.GetWeakPtr(),
+ StorageType::kPersistent));
+ manager()
+ ->GetUsageTracker(StorageType::kSyncable)
+ ->GetGlobalUsage(base::BindOnce(&GetUsageInfoTask::DidGetGlobalUsage,
+ weak_factory_.GetWeakPtr(),
+ StorageType::kSyncable));
+ }
+
+ void Completed() override {
+ std::move(callback_).Run(std::move(entries_));
+ DeleteSoon();
+ }
+
+ void Aborted() override {
+ std::move(callback_).Run(UsageInfoEntries());
+ DeleteSoon();
+ }
+
+ private:
+ void AddEntries(StorageType type, UsageTracker* tracker) {
+ std::map<std::string, int64_t> host_usage = tracker->GetCachedHostsUsage();
+ for (const auto& host_usage_pair : host_usage) {
+ entries_.emplace_back(host_usage_pair.first, type,
+ host_usage_pair.second);
+ }
+ if (--remaining_trackers_ == 0)
+ CallCompleted();
+ }
+
+ void DidGetGlobalUsage(StorageType type, int64_t, int64_t) {
+ DCHECK(manager()->GetUsageTracker(type));
+ AddEntries(type, manager()->GetUsageTracker(type));
+ }
+
+ QuotaManagerImpl* manager() const {
+ return static_cast<QuotaManagerImpl*>(observer());
+ }
+
+ GetUsageInfoCallback callback_;
+ UsageInfoEntries entries_;
+ int remaining_trackers_;
+ base::WeakPtrFactory<GetUsageInfoTask> weak_factory_{this};
+};
+
+class QuotaManagerImpl::OriginDataDeleter : public QuotaTask {
+ public:
+ OriginDataDeleter(QuotaManagerImpl* manager,
+ const url::Origin& origin,
+ StorageType type,
+ QuotaClientTypes quota_client_types,
+ bool is_eviction,
+ StatusCallback callback)
+ : QuotaTask(manager),
+ origin_(origin),
+ type_(type),
+ quota_client_types_(std::move(quota_client_types)),
+ error_count_(0),
+ remaining_clients_(0),
+ skipped_clients_(0),
+ is_eviction_(is_eviction),
+ callback_(std::move(callback)) {}
+
+ protected:
+ void Run() override {
+ DCHECK(manager()->client_types_.contains(type_));
+ remaining_clients_ = manager()->client_types_[type_].size();
+
+ for (const auto& client_and_type : manager()->client_types_[type_]) {
+ QuotaClient* client = client_and_type.first;
+ QuotaClientType client_type = client_and_type.second;
+ if (quota_client_types_.contains(client_type)) {
+ static int tracing_id = 0;
+ TRACE_EVENT_ASYNC_BEGIN2("browsing_data",
+ "QuotaManagerImpl::OriginDataDeleter",
+ ++tracing_id, "client_type", client_type,
+ "origin", origin_.Serialize());
+ client->DeleteOriginData(
+ origin_, type_,
+ base::BindOnce(&OriginDataDeleter::DidDeleteOriginData,
+ weak_factory_.GetWeakPtr(), tracing_id));
+ } else {
+ ++skipped_clients_;
+ --remaining_clients_;
+ }
+ }
+
+ if (remaining_clients_ == 0)
+ CallCompleted();
+ }
+
+ void Completed() override {
+ if (error_count_ == 0) {
+ // 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 {
+ std::move(callback_).Run(
+ blink::mojom::QuotaStatusCode::kErrorInvalidModification);
+ }
+ DeleteSoon();
+ }
+
+ void Aborted() override {
+ std::move(callback_).Run(blink::mojom::QuotaStatusCode::kErrorAbort);
+ DeleteSoon();
+ }
+
+ private:
+ void DidDeleteOriginData(int tracing_id,
+ blink::mojom::QuotaStatusCode status) {
+ DCHECK_GT(remaining_clients_, 0U);
+ TRACE_EVENT_ASYNC_END0("browsing_data",
+ "QuotaManagerImpl::OriginDataDeleter", tracing_id);
+
+ if (status != blink::mojom::QuotaStatusCode::kOk)
+ ++error_count_;
+
+ if (--remaining_clients_ == 0)
+ CallCompleted();
+ }
+
+ QuotaManagerImpl* manager() const {
+ return static_cast<QuotaManagerImpl*>(observer());
+ }
+
+ const url::Origin origin_;
+ const StorageType type_;
+ const QuotaClientTypes quota_client_types_;
+ int error_count_;
+ size_t remaining_clients_;
+ int skipped_clients_;
+ const bool is_eviction_;
+ StatusCallback callback_;
+
+ base::WeakPtrFactory<OriginDataDeleter> weak_factory_{this};
+};
+
+class QuotaManagerImpl::HostDataDeleter : public QuotaTask {
+ public:
+ HostDataDeleter(QuotaManagerImpl* manager,
+ const std::string& host,
+ StorageType type,
+ QuotaClientTypes quota_client_types,
+ StatusCallback callback)
+ : QuotaTask(manager),
+ host_(host),
+ type_(type),
+ quota_client_types_(std::move(quota_client_types)),
+ error_count_(0),
+ remaining_clients_(0),
+ remaining_deleters_(0),
+ callback_(std::move(callback)) {}
+
+ protected:
+ void Run() override {
+ DCHECK(manager()->client_types_.contains(type_));
+ remaining_clients_ = manager()->client_types_[type_].size();
+
+ for (const auto& client_and_type : manager()->client_types_[type_]) {
+ client_and_type.first->GetOriginsForHost(
+ type_, host_,
+ base::BindOnce(&HostDataDeleter::DidGetOriginsForHost,
+ weak_factory_.GetWeakPtr()));
+ }
+ }
+
+ void Completed() override {
+ if (error_count_ == 0) {
+ std::move(callback_).Run(blink::mojom::QuotaStatusCode::kOk);
+ } else {
+ std::move(callback_).Run(
+ blink::mojom::QuotaStatusCode::kErrorInvalidModification);
+ }
+ DeleteSoon();
+ }
+
+ void Aborted() override {
+ std::move(callback_).Run(blink::mojom::QuotaStatusCode::kErrorAbort);
+ DeleteSoon();
+ }
+
+ private:
+ void DidGetOriginsForHost(const std::vector<url::Origin>& origins) {
+ DCHECK_GT(remaining_clients_, 0U);
+
+ for (const auto& origin : origins)
+ origins_.insert(origin);
+
+ if (--remaining_clients_ == 0) {
+ if (!origins_.empty())
+ ScheduleOriginsDeletion();
+ else
+ CallCompleted();
+ }
+ }
+
+ void ScheduleOriginsDeletion() {
+ remaining_deleters_ = origins_.size();
+ for (const auto& origin : origins_) {
+ OriginDataDeleter* deleter = new OriginDataDeleter(
+ manager(), origin, type_, std::move(quota_client_types_), false,
+ base::BindOnce(&HostDataDeleter::DidDeleteOriginData,
+ weak_factory_.GetWeakPtr()));
+ deleter->Start();
+ }
+ }
+
+ void DidDeleteOriginData(blink::mojom::QuotaStatusCode status) {
+ DCHECK_GT(remaining_deleters_, 0U);
+
+ if (status != blink::mojom::QuotaStatusCode::kOk)
+ ++error_count_;
+
+ if (--remaining_deleters_ == 0)
+ CallCompleted();
+ }
+
+ QuotaManagerImpl* manager() const {
+ return static_cast<QuotaManagerImpl*>(observer());
+ }
+
+ const std::string host_;
+ const StorageType type_;
+ const QuotaClientTypes quota_client_types_;
+ std::set<url::Origin> origins_;
+ int error_count_;
+ size_t remaining_clients_;
+ size_t remaining_deleters_;
+ StatusCallback callback_;
+
+ base::WeakPtrFactory<HostDataDeleter> weak_factory_{this};
+};
+
+class QuotaManagerImpl::StorageCleanupHelper : public QuotaTask {
+ public:
+ StorageCleanupHelper(QuotaManagerImpl* manager,
+ StorageType type,
+ QuotaClientTypes quota_client_types,
+ base::OnceClosure callback)
+ : QuotaTask(manager),
+ type_(type),
+ quota_client_types_(std::move(quota_client_types)),
+ callback_(std::move(callback)) {
+ DCHECK(manager->client_types_.contains(type_));
+ }
+
+ protected:
+ void Run() override {
+ DCHECK(manager()->client_types_.contains(type_));
+ base::RepeatingClosure barrier = base::BarrierClosure(
+ manager()->client_types_[type_].size(),
+ base::BindOnce(&StorageCleanupHelper::CallCompleted,
+ weak_factory_.GetWeakPtr()));
+
+ // This may synchronously trigger |callback_| at the end of the for loop,
+ // make sure we do nothing after this block.
+ for (const auto& client_and_type : manager()->client_types_[type_]) {
+ QuotaClient* client = client_and_type.first;
+ QuotaClientType client_type = client_and_type.second;
+ if (quota_client_types_.contains(client_type)) {
+ client->PerformStorageCleanup(type_, barrier);
+ } else {
+ barrier.Run();
+ }
+ }
+ }
+
+ void Aborted() override {
+ weak_factory_.InvalidateWeakPtrs();
+ std::move(callback_).Run();
+ DeleteSoon();
+ }
+
+ void Completed() override {
+ weak_factory_.InvalidateWeakPtrs();
+ std::move(callback_).Run();
+ DeleteSoon();
+ }
+
+ private:
+ QuotaManagerImpl* manager() const {
+ return static_cast<QuotaManagerImpl*>(observer());
+ }
+
+ const StorageType type_;
+ const QuotaClientTypes quota_client_types_;
+ base::OnceClosure callback_;
+ base::WeakPtrFactory<StorageCleanupHelper> weak_factory_{this};
+};
+
+// 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
+// DidGetModifiedBetween() via base::Owned(). When the closure for said
+// function goes out of scope, the object is deleted. This is a thread-safe
+// class.
+class QuotaManagerImpl::GetModifiedSinceHelper {
+ public:
+ bool GetModifiedBetweenOnDBThread(StorageType type,
+ base::Time begin,
+ base::Time end,
+ QuotaDatabase* database) {
+ DCHECK(database);
+ return database->GetOriginsModifiedBetween(type, &origins_, begin, end);
+ }
+
+ void DidGetModifiedBetween(const base::WeakPtr<QuotaManagerImpl>& manager,
+ GetOriginsCallback callback,
+ StorageType type,
+ bool success) {
+ if (!manager) {
+ // The operation was aborted.
+ std::move(callback).Run(std::set<url::Origin>(), type);
+ return;
+ }
+ manager->DidDatabaseWork(success);
+ std::move(callback).Run(origins_, type);
+ }
+
+ private:
+ 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 QuotaManagerImpl::DumpQuotaTableHelper {
+ public:
+ bool DumpQuotaTableOnDBThread(QuotaDatabase* database) {
+ DCHECK(database);
+ return database->DumpQuotaTable(base::BindRepeating(
+ &DumpQuotaTableHelper::AppendEntry, base::Unretained(this)));
+ }
+
+ void DidDumpQuotaTable(const base::WeakPtr<QuotaManagerImpl>& manager,
+ DumpQuotaTableCallback callback,
+ bool success) {
+ if (!manager) {
+ // The operation was aborted.
+ std::move(callback).Run(QuotaTableEntries());
+ return;
+ }
+ manager->DidDatabaseWork(success);
+ std::move(callback).Run(entries_);
+ }
+
+ private:
+ bool AppendEntry(const QuotaTableEntry& entry) {
+ entries_.push_back(entry);
+ return true;
+ }
+
+ 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 QuotaManagerImpl::DumpOriginInfoTableHelper {
+ public:
+ bool DumpOriginInfoTableOnDBThread(QuotaDatabase* database) {
+ DCHECK(database);
+ return database->DumpOriginInfoTable(base::BindRepeating(
+ &DumpOriginInfoTableHelper::AppendEntry, base::Unretained(this)));
+ }
+
+ void DidDumpOriginInfoTable(const base::WeakPtr<QuotaManagerImpl>& manager,
+ DumpOriginInfoTableCallback callback,
+ bool success) {
+ if (!manager) {
+ // The operation was aborted.
+ std::move(callback).Run(OriginInfoTableEntries());
+ return;
+ }
+ manager->DidDatabaseWork(success);
+ std::move(callback).Run(entries_);
+ }
+
+ private:
+ bool AppendEntry(const OriginInfoTableEntry& entry) {
+ entries_.push_back(entry);
+ return true;
+ }
+
+ OriginInfoTableEntries entries_;
+};
+
+// QuotaManagerImpl -----------------------------------------------------------
+
+QuotaManagerImpl::QuotaManagerImpl(
+ bool is_incognito,
+ const base::FilePath& profile_path,
+ scoped_refptr<base::SingleThreadTaskRunner> io_thread,
+ base::RepeatingClosure quota_change_callback,
+ scoped_refptr<SpecialStoragePolicy> special_storage_policy,
+ const GetQuotaSettingsFunc& get_settings_function)
+ : RefCountedDeleteOnSequence<QuotaManagerImpl>(io_thread),
+ is_incognito_(is_incognito),
+ profile_path_(profile_path),
+ proxy_(base::MakeRefCounted<QuotaManagerProxy>(this, io_thread)),
+ db_disabled_(false),
+ eviction_disabled_(false),
+ io_thread_(std::move(io_thread)),
+ db_runner_(base::ThreadPool::CreateSequencedTaskRunner(
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+ base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
+ get_settings_function_(get_settings_function),
+ quota_change_callback_(std::move(quota_change_callback)),
+ is_getting_eviction_origin_(false),
+ special_storage_policy_(std::move(special_storage_policy)),
+ get_volume_info_fn_(&QuotaManagerImpl::GetVolumeInfo) {
+ DCHECK_EQ(settings_.refresh_interval, base::TimeDelta::Max());
+ if (!get_settings_function.is_null()) {
+ // Reset the interval to ensure we use the get_settings_function
+ // the first times settings_ is needed.
+ settings_.refresh_interval = base::TimeDelta();
+ get_settings_task_runner_ = base::ThreadTaskRunnerHandle::Get();
+ }
+ DETACH_FROM_SEQUENCE(sequence_checker_);
+}
+
+void QuotaManagerImpl::SetQuotaSettings(const QuotaSettings& settings) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ settings_ = settings;
+ settings_timestamp_ = base::TimeTicks::Now();
+}
+
+void QuotaManagerImpl::GetUsageInfo(GetUsageInfoCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ LazyInitialize();
+ GetUsageInfoTask* get_usage_info =
+ new GetUsageInfoTask(this, std::move(callback));
+ get_usage_info->Start();
+}
+
+void QuotaManagerImpl::GetUsageAndQuotaForWebApps(
+ const url::Origin& origin,
+ StorageType type,
+ UsageAndQuotaCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ GetUsageAndQuotaWithBreakdown(
+ origin, type,
+ base::BindOnce(&DidGetUsageAndQuotaStripBreakdown, std::move(callback)));
+}
+
+void QuotaManagerImpl::GetUsageAndQuotaWithBreakdown(
+ const url::Origin& origin,
+ StorageType type,
+ UsageAndQuotaWithBreakdownCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ GetUsageAndQuotaForDevtools(
+ origin, type,
+ base::BindOnce(&DidGetUsageAndQuotaStripOverride, std::move(callback)));
+}
+
+void QuotaManagerImpl::GetUsageAndQuotaForDevtools(
+ const url::Origin& origin,
+ StorageType type,
+ UsageAndQuotaForDevtoolsCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!IsSupportedType(type) ||
+ (is_incognito_ && !IsSupportedIncognitoType(type))) {
+ std::move(callback).Run(blink::mojom::QuotaStatusCode::kErrorNotSupported,
+ /*usage=*/0,
+ /*quota=*/0,
+ /*is_override_enabled=*/false,
+ /*usage_breakdown=*/nullptr);
+ return;
+ }
+ LazyInitialize();
+
+ bool is_session_only =
+ type == StorageType::kTemporary && special_storage_policy_ &&
+ special_storage_policy_->IsStorageSessionOnly(origin.GetURL());
+
+ base::Optional<int64_t> quota_override = GetQuotaOverrideForOrigin(origin);
+
+ UsageAndQuotaInfoGatherer* helper = new UsageAndQuotaInfoGatherer(
+ this, origin, type, IsStorageUnlimited(origin, type), is_session_only,
+ is_incognito_, quota_override, std::move(callback));
+ helper->Start();
+}
+
+void QuotaManagerImpl::GetUsageAndQuota(const url::Origin& origin,
+ StorageType type,
+ UsageAndQuotaCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (IsStorageUnlimited(origin, type)) {
+ // TODO(michaeln): This seems like a non-obvious odd behavior, probably for
+ // apps/extensions, but it would be good to eliminate this special case.
+ std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk, 0, kNoLimit);
+ return;
+ }
+
+ if (!IsSupportedType(type) ||
+ (is_incognito_ && !IsSupportedIncognitoType(type))) {
+ std::move(callback).Run(
+ /*status*/ blink::mojom::QuotaStatusCode::kErrorNotSupported,
+ /*usage*/ 0,
+ /*quota*/ 0);
+ return;
+ }
+ LazyInitialize();
+
+ bool is_session_only =
+ type == StorageType::kTemporary && special_storage_policy_ &&
+ special_storage_policy_->IsStorageSessionOnly(origin.GetURL());
+
+ base::Optional<int64_t> quota_override = GetQuotaOverrideForOrigin(origin);
+
+ UsageAndQuotaInfoGatherer* helper = new UsageAndQuotaInfoGatherer(
+ this, origin, type, IsStorageUnlimited(origin, type), is_session_only,
+ is_incognito_, quota_override,
+ base::BindOnce(&DidGetUsageAndQuotaStripOverride,
+ base::BindOnce(&DidGetUsageAndQuotaStripBreakdown,
+ std::move(callback))));
+ helper->Start();
+}
+
+void QuotaManagerImpl::NotifyWriteFailed(const url::Origin& origin) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ auto age_of_disk_stats = base::TimeTicks::Now() -
+ std::get<0>(cached_disk_stats_for_storage_pressure_);
+
+ // Avoid polling for free disk space if disk stats have been recently
+ // queried.
+ if (age_of_disk_stats < kStoragePressureCheckDiskStatsInterval) {
+ int64_t total_space = std::get<1>(cached_disk_stats_for_storage_pressure_);
+ int64_t available_space =
+ std::get<2>(cached_disk_stats_for_storage_pressure_);
+ MaybeRunStoragePressureCallback(origin, total_space, available_space);
+ }
+
+ GetStorageCapacity(
+ base::BindOnce(&QuotaManagerImpl::MaybeRunStoragePressureCallback,
+ weak_factory_.GetWeakPtr(), origin));
+}
+
+void QuotaManagerImpl::NotifyOriginInUse(const url::Origin& origin) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(io_thread_->BelongsToCurrentThread());
+ origins_in_use_[origin]++;
+}
+
+void QuotaManagerImpl::NotifyOriginNoLongerInUse(const url::Origin& origin) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(io_thread_->BelongsToCurrentThread());
+ DCHECK(IsOriginInUse(origin));
+ int& count = origins_in_use_[origin];
+ if (--count == 0)
+ origins_in_use_.erase(origin);
+}
+
+void QuotaManagerImpl::SetUsageCacheEnabled(QuotaClientType client_id,
+ const url::Origin& origin,
+ StorageType type,
+ bool enabled) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ LazyInitialize();
+ DCHECK(GetUsageTracker(type));
+ GetUsageTracker(type)->SetUsageCacheEnabled(client_id, origin, enabled);
+}
+
+void QuotaManagerImpl::DeleteOriginData(const url::Origin& origin,
+ StorageType type,
+ QuotaClientTypes quota_client_types,
+ StatusCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DeleteOriginDataInternal(origin, type, std::move(quota_client_types), false,
+ std::move(callback));
+}
+
+void QuotaManagerImpl::PerformStorageCleanup(
+ StorageType type,
+ QuotaClientTypes quota_client_types,
+ base::OnceClosure callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ StorageCleanupHelper* deleter = new StorageCleanupHelper(
+ this, type, std::move(quota_client_types), std::move(callback));
+ deleter->Start();
+}
+
+void QuotaManagerImpl::DeleteHostData(const std::string& host,
+ StorageType type,
+ QuotaClientTypes quota_client_types,
+ StatusCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ LazyInitialize();
+
+ DCHECK(client_types_.contains(type));
+ if (host.empty() || client_types_[type].empty()) {
+ std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk);
+ return;
+ }
+
+ HostDataDeleter* deleter = new HostDataDeleter(
+ this, host, type, std::move(quota_client_types), std::move(callback));
+ deleter->Start();
+}
+
+void QuotaManagerImpl::GetPersistentHostQuota(const std::string& host,
+ QuotaCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ LazyInitialize();
+ if (host.empty()) {
+ // This could happen if we are called on file:///.
+ // TODO(kinuko) We may want to respect --allow-file-access-from-files
+ // command line switch.
+ std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk, 0);
+ return;
+ }
+
+ if (!persistent_host_quota_callbacks_.Add(host, std::move(callback)))
+ return;
+
+ int64_t* quota_ptr = new int64_t(0);
+ PostTaskAndReplyWithResultForDBThread(
+ FROM_HERE,
+ base::BindOnce(&GetPersistentHostQuotaOnDBThread, host,
+ base::Unretained(quota_ptr)),
+ base::BindOnce(&QuotaManagerImpl::DidGetPersistentHostQuota,
+ weak_factory_.GetWeakPtr(), host, base::Owned(quota_ptr)));
+}
+
+void QuotaManagerImpl::SetPersistentHostQuota(const std::string& host,
+ int64_t new_quota,
+ QuotaCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ LazyInitialize();
+ if (host.empty()) {
+ // This could happen if we are called on file:///.
+ std::move(callback).Run(blink::mojom::QuotaStatusCode::kErrorNotSupported,
+ 0);
+ return;
+ }
+
+ if (new_quota < 0) {
+ std::move(callback).Run(
+ blink::mojom::QuotaStatusCode::kErrorInvalidModification, -1);
+ return;
+ }
+
+ // Cap the requested size at the per-host quota limit.
+ new_quota = std::min(new_quota, kPerHostPersistentQuotaLimit);
+
+ if (db_disabled_) {
+ std::move(callback).Run(blink::mojom::QuotaStatusCode::kErrorInvalidAccess,
+ -1);
+ return;
+ }
+
+ int64_t* new_quota_ptr = new int64_t(new_quota);
+ PostTaskAndReplyWithResultForDBThread(
+ FROM_HERE,
+ base::BindOnce(&SetPersistentHostQuotaOnDBThread, host,
+ base::Unretained(new_quota_ptr)),
+ base::BindOnce(&QuotaManagerImpl::DidSetPersistentHostQuota,
+ weak_factory_.GetWeakPtr(), host, std::move(callback),
+ base::Owned(new_quota_ptr)));
+}
+
+void QuotaManagerImpl::GetGlobalUsage(StorageType type,
+ GlobalUsageCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ LazyInitialize();
+ DCHECK(GetUsageTracker(type));
+ GetUsageTracker(type)->GetGlobalUsage(std::move(callback));
+}
+
+void QuotaManagerImpl::GetHostUsageWithBreakdown(
+ const std::string& host,
+ StorageType type,
+ UsageWithBreakdownCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ LazyInitialize();
+ DCHECK(GetUsageTracker(type));
+ GetUsageTracker(type)->GetHostUsageWithBreakdown(host, std::move(callback));
+}
+
+std::map<std::string, std::string> QuotaManagerImpl::GetStatistics() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ std::map<std::string, std::string> statistics;
+ if (temporary_storage_evictor_) {
+ std::map<std::string, int64_t> stats;
+ temporary_storage_evictor_->GetStatistics(&stats);
+ for (const auto& origin_usage_pair : stats) {
+ statistics[origin_usage_pair.first] =
+ base::NumberToString(origin_usage_pair.second);
+ }
+ }
+ return statistics;
+}
+
+bool QuotaManagerImpl::IsStorageUnlimited(const url::Origin& origin,
+ StorageType type) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // For syncable storage we should always enforce quota (since the
+ // quota must be capped by the server limit).
+ if (type == StorageType::kSyncable)
+ return false;
+ if (type == StorageType::kQuotaNotManaged)
+ return true;
+ return special_storage_policy_.get() &&
+ special_storage_policy_->IsStorageUnlimited(origin.GetURL());
+}
+
+void QuotaManagerImpl::GetOriginsModifiedBetween(StorageType type,
+ base::Time begin,
+ base::Time end,
+ GetOriginsCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ LazyInitialize();
+ GetModifiedSinceHelper* helper = new GetModifiedSinceHelper;
+ PostTaskAndReplyWithResultForDBThread(
+ FROM_HERE,
+ base::BindOnce(&GetModifiedSinceHelper::GetModifiedBetweenOnDBThread,
+ base::Unretained(helper), type, begin, end),
+ base::BindOnce(&GetModifiedSinceHelper::DidGetModifiedBetween,
+ base::Owned(helper), weak_factory_.GetWeakPtr(),
+ std::move(callback), type));
+}
+
+bool QuotaManagerImpl::ResetUsageTracker(StorageType type) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(GetUsageTracker(type));
+ if (GetUsageTracker(type)->IsWorking())
+ return false;
+
+ auto usage_tracker = std::make_unique<UsageTracker>(
+ client_types_[type], type, special_storage_policy_.get());
+ switch (type) {
+ case StorageType::kTemporary:
+ temporary_usage_tracker_ = std::move(usage_tracker);
+ return true;
+ case StorageType::kPersistent:
+ persistent_usage_tracker_ = std::move(usage_tracker);
+ return true;
+ case StorageType::kSyncable:
+ syncable_usage_tracker_ = std::move(usage_tracker);
+ return true;
+ default:
+ NOTREACHED();
+ }
+ return true;
+}
+
+QuotaManagerImpl::~QuotaManagerImpl() {
+ proxy_->InvalidateQuotaManagerImpl(base::PassKey<QuotaManagerImpl>());
+
+ // Iterating over `legacy_clients_for_ownership_` is correct here because we
+ // want to call OnQuotaManagerDestroyed() once per QuotaClient.
+ for (const auto& client : legacy_clients_for_ownership_)
+ client->OnQuotaManagerDestroyed();
+
+ if (database_)
+ db_runner_->DeleteSoon(FROM_HERE, database_.release());
+}
+
+QuotaManagerImpl::EvictionContext::EvictionContext()
+ : evicted_type(StorageType::kUnknown) {}
+
+QuotaManagerImpl::EvictionContext::~EvictionContext() = default;
+
+void QuotaManagerImpl::LazyInitialize() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(io_thread_->BelongsToCurrentThread());
+ if (database_) {
+ // Already initialized.
+ return;
+ }
+
+ // Use an empty path to open an in-memory only database for incognito.
+ database_ = std::make_unique<QuotaDatabase>(
+ is_incognito_ ? base::FilePath()
+ : profile_path_.AppendASCII(kDatabaseName));
+
+ temporary_usage_tracker_ = std::make_unique<UsageTracker>(
+ client_types_[StorageType::kTemporary], StorageType::kTemporary,
+ special_storage_policy_.get());
+ persistent_usage_tracker_ = std::make_unique<UsageTracker>(
+ client_types_[StorageType::kPersistent], StorageType::kPersistent,
+ special_storage_policy_.get());
+ syncable_usage_tracker_ = std::make_unique<UsageTracker>(
+ client_types_[StorageType::kSyncable], StorageType::kSyncable,
+ special_storage_policy_.get());
+
+ if (!is_incognito_) {
+ histogram_timer_.Start(
+ FROM_HERE, base::TimeDelta::FromMilliseconds(kReportHistogramInterval),
+ this, &QuotaManagerImpl::ReportHistogram);
+ }
+
+ base::PostTaskAndReplyWithResult(
+ db_runner_.get(), FROM_HERE,
+ base::BindOnce(&QuotaDatabase::IsOriginDatabaseBootstrapped,
+ base::Unretained(database_.get())),
+ base::BindOnce(&QuotaManagerImpl::FinishLazyInitialize,
+ weak_factory_.GetWeakPtr()));
+}
+
+void QuotaManagerImpl::FinishLazyInitialize(bool is_database_bootstrapped) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ is_database_bootstrapped_ = is_database_bootstrapped;
+ StartEviction();
+}
+
+void QuotaManagerImpl::BootstrapDatabaseForEviction(
+ GetOriginCallback did_get_origin_callback,
+ int64_t usage,
+ int64_t unlimited_usage) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // The usage cache should be fully populated now so we can
+ // seed the database with origins we know about.
+ std::set<url::Origin> origins = temporary_usage_tracker_->GetCachedOrigins();
+ PostTaskAndReplyWithResultForDBThread(
+ FROM_HERE,
+ base::BindOnce(&BootstrapDatabaseOnDBThread, std::move(origins)),
+ base::BindOnce(&QuotaManagerImpl::DidBootstrapDatabase,
+ weak_factory_.GetWeakPtr(),
+ std::move(did_get_origin_callback)));
+}
+
+void QuotaManagerImpl::DidBootstrapDatabase(
+ GetOriginCallback did_get_origin_callback,
+ bool success) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ is_database_bootstrapped_ = success;
+ DidDatabaseWork(success);
+ GetLRUOrigin(StorageType::kTemporary, std::move(did_get_origin_callback));
+}
+
+void QuotaManagerImpl::RegisterClient(
+ mojo::PendingRemote<mojom::QuotaClient> client,
+ QuotaClientType client_type,
+ const std::vector<blink::mojom::StorageType>& storage_types) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!database_.get())
+ << "All clients must be registered before the database is initialized";
+
+ clients_for_ownership_.emplace_back(std::move(client));
+ mojom::QuotaClient* client_ptr = clients_for_ownership_.back().get();
+
+ // TODO(crbug.com/1163009): Remove this block after all QuotaClients have been
+ // mojofied.
+ legacy_clients_for_ownership_.push_back(
+ base::MakeRefCounted<MojoQuotaClientWrapper>(client_ptr));
+ QuotaClient* legacy_client_ptr = legacy_clients_for_ownership_.back().get();
+
+ // TODO(crbug.com/1163009): Use client_ptr instead of legacy_client_ptr after
+ // all QuotaClients have been mojofied.
+ for (blink::mojom::StorageType storage_type : storage_types)
+ client_types_[storage_type].insert({legacy_client_ptr, client_type});
+}
+
+void QuotaManagerImpl::RegisterLegacyClient(
+ scoped_refptr<QuotaClient> client,
+ QuotaClientType client_type,
+ const std::vector<blink::mojom::StorageType>& storage_types) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!database_.get())
+ << "All clients must be registered before the database is initialized";
+ DCHECK(client.get());
+
+ for (blink::mojom::StorageType storage_type : storage_types)
+ client_types_[storage_type].insert({client.get(), client_type});
+ legacy_clients_for_ownership_.push_back(std::move(client));
+}
+
+UsageTracker* QuotaManagerImpl::GetUsageTracker(StorageType type) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ switch (type) {
+ case StorageType::kTemporary:
+ return temporary_usage_tracker_.get();
+ case StorageType::kPersistent:
+ return persistent_usage_tracker_.get();
+ case StorageType::kSyncable:
+ return syncable_usage_tracker_.get();
+ case StorageType::kQuotaNotManaged:
+ return nullptr;
+ case StorageType::kUnknown:
+ NOTREACHED();
+ }
+ return nullptr;
+}
+
+std::set<url::Origin> QuotaManagerImpl::GetCachedOrigins(StorageType type) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ LazyInitialize();
+ DCHECK(GetUsageTracker(type));
+ return GetUsageTracker(type)->GetCachedOrigins();
+}
+
+void QuotaManagerImpl::NotifyStorageAccessed(const url::Origin& origin,
+ StorageType type,
+ base::Time access_time) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ LazyInitialize();
+ if (type == StorageType::kTemporary && is_getting_eviction_origin_) {
+ // Record the accessed origins while GetLRUOrigin task is runing
+ // to filter out them from eviction.
+ access_notified_origins_.insert(origin);
+ }
+
+ if (db_disabled_)
+ return;
+ PostTaskAndReplyWithResultForDBThread(
+ FROM_HERE,
+ base::BindOnce(&UpdateAccessTimeOnDBThread, origin, type, access_time),
+ base::BindOnce(&QuotaManagerImpl::DidDatabaseWork,
+ weak_factory_.GetWeakPtr()));
+}
+
+void QuotaManagerImpl::NotifyStorageModified(QuotaClientType client_id,
+ const url::Origin& origin,
+ StorageType type,
+ int64_t delta,
+ base::Time modification_time,
+ base::OnceClosure callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ LazyInitialize();
+ DCHECK(GetUsageTracker(type));
+ GetUsageTracker(type)->UpdateUsageCache(client_id, origin, delta);
+
+ if (callback)
+ std::move(callback).Run();
+
+ if (db_disabled_)
+ return;
+
+ PostTaskAndReplyWithResultForDBThread(
+ FROM_HERE,
+ base::BindOnce(&UpdateModifiedTimeOnDBThread, origin, type,
+ modification_time),
+ base::BindOnce(&QuotaManagerImpl::DidDatabaseWork,
+ weak_factory_.GetWeakPtr()));
+}
+
+void QuotaManagerImpl::DumpQuotaTable(DumpQuotaTableCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DumpQuotaTableHelper* helper = new DumpQuotaTableHelper;
+ PostTaskAndReplyWithResultForDBThread(
+ FROM_HERE,
+ base::BindOnce(&DumpQuotaTableHelper::DumpQuotaTableOnDBThread,
+ base::Unretained(helper)),
+ base::BindOnce(&DumpQuotaTableHelper::DidDumpQuotaTable,
+ base::Owned(helper), weak_factory_.GetWeakPtr(),
+ std::move(callback)));
+}
+
+void QuotaManagerImpl::DumpOriginInfoTable(
+ DumpOriginInfoTableCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DumpOriginInfoTableHelper* helper = new DumpOriginInfoTableHelper;
+ PostTaskAndReplyWithResultForDBThread(
+ FROM_HERE,
+ base::BindOnce(&DumpOriginInfoTableHelper::DumpOriginInfoTableOnDBThread,
+ base::Unretained(helper)),
+ base::BindOnce(&DumpOriginInfoTableHelper::DidDumpOriginInfoTable,
+ base::Owned(helper), weak_factory_.GetWeakPtr(),
+ std::move(callback)));
+}
+
+void QuotaManagerImpl::StartEviction() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!temporary_storage_evictor_.get());
+ if (eviction_disabled_)
+ return;
+ temporary_storage_evictor_ = std::make_unique<QuotaTemporaryStorageEvictor>(
+ this, kEvictionIntervalInMilliSeconds);
+ temporary_storage_evictor_->Start();
+}
+
+void QuotaManagerImpl::DeleteOriginFromDatabase(const url::Origin& origin,
+ StorageType type,
+ bool is_eviction) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ LazyInitialize();
+ if (db_disabled_)
+ return;
+
+ PostTaskAndReplyWithResultForDBThread(
+ FROM_HERE,
+ base::BindOnce(&DeleteOriginInfoOnDBThread, origin, type, is_eviction),
+ base::BindOnce(&QuotaManagerImpl::DidDatabaseWork,
+ weak_factory_.GetWeakPtr()));
+}
+
+void QuotaManagerImpl::DidOriginDataEvicted(
+ blink::mojom::QuotaStatusCode status) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(io_thread_->BelongsToCurrentThread());
+
+ // We only try evict origins that are not in use, so basically
+ // deletion attempt for eviction should not fail. Let's record
+ // the origin if we get error and exclude it from future eviction
+ // if the error happens consistently (> kThresholdOfErrorsToBeDenylisted).
+ if (status != blink::mojom::QuotaStatusCode::kOk)
+ origins_in_error_[eviction_context_.evicted_origin]++;
+
+ std::move(eviction_context_.evict_origin_data_callback).Run(status);
+}
+
+void QuotaManagerImpl::DeleteOriginDataInternal(
+ const url::Origin& origin,
+ StorageType type,
+ QuotaClientTypes quota_client_types,
+ bool is_eviction,
+ StatusCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ LazyInitialize();
+
+ OriginDataDeleter* deleter =
+ new OriginDataDeleter(this, origin, type, std::move(quota_client_types),
+ is_eviction, std::move(callback));
+ deleter->Start();
+}
+
+void QuotaManagerImpl::MaybeRunStoragePressureCallback(
+ const url::Origin& origin,
+ int64_t total_space,
+ int64_t available_space) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // TODO(https://crbug.com/1059560): Figure out what 0 total_space means
+ // and how to handle the storage pressure callback in these cases.
+ if (total_space == 0)
+ return;
+
+ if (!storage_pressure_callback_) {
+ // Quota will hold onto a storage pressure notification if no storage
+ // pressure callback is set.
+ origin_for_pending_storage_pressure_callback_ = std::move(origin);
+ return;
+ }
+
+ if (available_space < kStoragePressureThresholdRatio * total_space) {
+ storage_pressure_callback_.Run(std::move(origin));
+ }
+}
+
+void QuotaManagerImpl::SimulateStoragePressure(const url::Origin origin) {
+ storage_pressure_callback_.Run(origin);
+}
+
+void QuotaManagerImpl::DetermineStoragePressure(int64_t total_space,
+ int64_t free_space) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!base::FeatureList::IsEnabled(features::kStoragePressureEvent)) {
+ return;
+ }
+ int64_t threshold_bytes =
+ RandomizeByPercent(kGBytes, kThresholdRandomizationPercent);
+ int64_t threshold = RandomizeByPercent(
+ static_cast<int64_t>(total_space *
+ (kThresholdRandomizationPercent / 100.0)),
+ kThresholdRandomizationPercent);
+ threshold = std::min(threshold_bytes, threshold);
+ if (free_space < threshold && !quota_change_callback_.is_null()) {
+ quota_change_callback_.Run();
+ }
+}
+
+void QuotaManagerImpl::SetStoragePressureCallback(
+ base::RepeatingCallback<void(url::Origin)> storage_pressure_callback) {
+ storage_pressure_callback_ = storage_pressure_callback;
+ if (origin_for_pending_storage_pressure_callback_.has_value()) {
+ storage_pressure_callback_.Run(
+ std::move(origin_for_pending_storage_pressure_callback_.value()));
+ origin_for_pending_storage_pressure_callback_ = base::nullopt;
+ }
+}
+
+int QuotaManagerImpl::GetOverrideHandleId() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return ++next_override_handle_id_;
+}
+
+void QuotaManagerImpl::OverrideQuotaForOrigin(
+ int handle_id,
+ const url::Origin& origin,
+ base::Optional<int64_t> quota_size) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (quota_size.has_value()) {
+ DCHECK_GE(next_override_handle_id_, handle_id);
+ // Bracket notation is safe here because we want to construct a new
+ // QuotaOverride in the case that one does not exist for origin.
+ devtools_overrides_[origin].active_override_session_ids.insert(handle_id);
+ devtools_overrides_[origin].quota_size = quota_size.value();
+ } else {
+ devtools_overrides_.erase(origin);
+ }
+}
+
+void QuotaManagerImpl::WithdrawOverridesForHandle(int handle_id) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ std::vector<url::Origin> origins_to_clear;
+ for (auto& devtools_override : devtools_overrides_) {
+ auto& quota_override = devtools_override.second;
+ auto& origin = devtools_override.first;
+
+ quota_override.active_override_session_ids.erase(handle_id);
+
+ if (!quota_override.active_override_session_ids.size()) {
+ origins_to_clear.push_back(origin);
+ }
+ }
+
+ for (auto& origin : origins_to_clear) {
+ devtools_overrides_.erase(origin);
+ }
+}
+
+base::Optional<int64_t> QuotaManagerImpl::GetQuotaOverrideForOrigin(
+ const url::Origin& origin) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!base::Contains(devtools_overrides_, origin)) {
+ return base::nullopt;
+ }
+ return devtools_overrides_[origin].quota_size;
+}
+
+void QuotaManagerImpl::SetQuotaChangeCallbackForTesting(
+ base::RepeatingClosure storage_pressure_event_callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ quota_change_callback_ = std::move(storage_pressure_event_callback);
+}
+
+void QuotaManagerImpl::ReportHistogram() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!is_incognito_);
+ GetGlobalUsage(
+ StorageType::kTemporary,
+ base::BindOnce(&QuotaManagerImpl::DidGetTemporaryGlobalUsageForHistogram,
+ weak_factory_.GetWeakPtr()));
+}
+
+void QuotaManagerImpl::DidGetTemporaryGlobalUsageForHistogram(
+ int64_t usage,
+ int64_t unlimited_usage) {
+ GetStorageCapacity(
+ base::BindOnce(&QuotaManagerImpl::DidGetStorageCapacityForHistogram,
+ weak_factory_.GetWeakPtr(), usage));
+}
+
+void QuotaManagerImpl::DidGetStorageCapacityForHistogram(
+ int64_t usage,
+ int64_t total_space,
+ int64_t available_space) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ UMA_HISTOGRAM_MBYTES("Quota.GlobalUsageOfTemporaryStorage", usage);
+ if (total_space > 0) {
+ UMA_HISTOGRAM_PERCENTAGE("Quota.PercentUsedForTemporaryStorage2",
+ static_cast<int>((usage * 100) / total_space));
+ UMA_HISTOGRAM_MBYTES("Quota.AvailableDiskSpace2", available_space);
+ UMA_HISTOGRAM_PERCENTAGE(
+ "Quota.PercentDiskAvailable2",
+ std::min(100, static_cast<int>((available_space * 100 / total_space))));
+ }
+
+ GetGlobalUsage(
+ StorageType::kPersistent,
+ base::BindOnce(&QuotaManagerImpl::DidGetPersistentGlobalUsageForHistogram,
+ weak_factory_.GetWeakPtr()));
+}
+
+void QuotaManagerImpl::DidGetPersistentGlobalUsageForHistogram(
+ int64_t usage,
+ int64_t unlimited_usage) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ UMA_HISTOGRAM_MBYTES("Quota.GlobalUsageOfPersistentStorage", usage);
+
+ // We DumpOriginInfoTable last to ensure the trackers caches are loaded.
+ DumpOriginInfoTable(
+ base::BindOnce(&QuotaManagerImpl::DidDumpOriginInfoTableForHistogram,
+ weak_factory_.GetWeakPtr()));
+}
+
+void QuotaManagerImpl::DidDumpOriginInfoTableForHistogram(
+ const OriginInfoTableEntries& entries) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ std::map<url::Origin, int64_t> usage_map =
+ GetUsageTracker(StorageType::kTemporary)->GetCachedOriginsUsage();
+ base::Time now = base::Time::Now();
+ for (const auto& info : entries) {
+ if (info.type != StorageType::kTemporary)
+ continue;
+
+ // Ignore stale database entries. If there is no map entry, the origin's
+ // data has been deleted.
+ auto it = usage_map.find(info.origin);
+ if (it == usage_map.end() || it->second == 0)
+ continue;
+
+ base::TimeDelta age = now - std::max(info.last_access_time,
+ info.last_modified_time);
+ UMA_HISTOGRAM_COUNTS_1000("Quota.AgeOfOriginInDays", age.InDays());
+
+ int64_t kilobytes = std::max(it->second / INT64_C(1024), INT64_C(1));
+ base::Histogram::FactoryGet(
+ "Quota.AgeOfDataInDays", 1, 1000, 50,
+ base::HistogramBase::kUmaTargetedHistogramFlag)->
+ AddCount(age.InDays(),
+ base::saturated_cast<int>(kilobytes));
+ }
+}
+
+std::set<url::Origin> QuotaManagerImpl::GetEvictionOriginExceptions() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ std::set<url::Origin> exceptions;
+ for (const auto& p : origins_in_use_) {
+ if (p.second > 0)
+ exceptions.insert(p.first);
+ }
+
+ for (const auto& p : origins_in_error_) {
+ if (p.second > QuotaManagerImpl::kThresholdOfErrorsToBeDenylisted)
+ exceptions.insert(p.first);
+ }
+
+ return exceptions;
+}
+
+void QuotaManagerImpl::DidGetEvictionOrigin(
+ GetOriginCallback callback,
+ const base::Optional<url::Origin>& origin) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // Make sure the returned origin is (still) not in the origin_in_use_ set
+ // and has not been accessed since we posted the task.
+ DCHECK(!origin.has_value() || !origin->GetURL().is_empty());
+ if (origin.has_value() &&
+ (base::Contains(origins_in_use_, *origin) ||
+ base::Contains(access_notified_origins_, *origin))) {
+ std::move(callback).Run(base::nullopt);
+ } else {
+ std::move(callback).Run(origin);
+ }
+ access_notified_origins_.clear();
+
+ is_getting_eviction_origin_ = false;
+}
+
+void QuotaManagerImpl::GetEvictionOrigin(StorageType type,
+ int64_t global_quota,
+ GetOriginCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ LazyInitialize();
+ // This must not be called while there's an in-flight task.
+ DCHECK(!is_getting_eviction_origin_);
+ is_getting_eviction_origin_ = true;
+
+ auto did_get_origin_callback =
+ base::BindOnce(&QuotaManagerImpl::DidGetEvictionOrigin,
+ weak_factory_.GetWeakPtr(), std::move(callback));
+
+ if (!is_database_bootstrapped_ && !eviction_disabled_) {
+ // Once bootstrapped, GetLRUOrigin will be called.
+ GetGlobalUsage(
+ StorageType::kTemporary,
+ base::BindOnce(&QuotaManagerImpl::BootstrapDatabaseForEviction,
+ weak_factory_.GetWeakPtr(),
+ std::move(did_get_origin_callback)));
+ return;
+ }
+
+ GetLRUOrigin(type, std::move(did_get_origin_callback));
+}
+
+void QuotaManagerImpl::EvictOriginData(const url::Origin& origin,
+ StorageType type,
+ StatusCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(io_thread_->BelongsToCurrentThread());
+ DCHECK_EQ(type, StorageType::kTemporary);
+
+ eviction_context_.evicted_origin = origin;
+ eviction_context_.evicted_type = type;
+ eviction_context_.evict_origin_data_callback = std::move(callback);
+
+ DeleteOriginDataInternal(
+ origin, type, AllQuotaClientTypes(), true,
+ base::BindOnce(&QuotaManagerImpl::DidOriginDataEvicted,
+ weak_factory_.GetWeakPtr()));
+}
+
+void QuotaManagerImpl::GetEvictionRoundInfo(
+ EvictionRoundInfoCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(io_thread_->BelongsToCurrentThread());
+ LazyInitialize();
+ EvictionRoundInfoHelper* helper =
+ new EvictionRoundInfoHelper(this, std::move(callback));
+ helper->Start();
+}
+
+void QuotaManagerImpl::GetLRUOrigin(StorageType type,
+ GetOriginCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ LazyInitialize();
+ // This must not be called while there's an in-flight task.
+ DCHECK(lru_origin_callback_.is_null());
+ lru_origin_callback_ = std::move(callback);
+ if (db_disabled_) {
+ std::move(lru_origin_callback_).Run(base::nullopt);
+ return;
+ }
+
+ auto origin = std::make_unique<base::Optional<url::Origin>>();
+ auto* origin_ptr = origin.get();
+ PostTaskAndReplyWithResultForDBThread(
+ FROM_HERE,
+ base::BindOnce(&GetLRUOriginOnDBThread, type,
+ GetEvictionOriginExceptions(),
+ base::RetainedRef(special_storage_policy_),
+ base::Unretained(origin_ptr)),
+ base::BindOnce(&QuotaManagerImpl::DidGetLRUOrigin,
+ weak_factory_.GetWeakPtr(), std::move(origin)));
+}
+
+void QuotaManagerImpl::DidGetPersistentHostQuota(const std::string& host,
+ const int64_t* quota,
+ bool success) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DidDatabaseWork(success);
+ persistent_host_quota_callbacks_.Run(
+ host, blink::mojom::QuotaStatusCode::kOk,
+ std::min(*quota, kPerHostPersistentQuotaLimit));
+}
+
+void QuotaManagerImpl::DidSetPersistentHostQuota(const std::string& host,
+ QuotaCallback callback,
+ const int64_t* new_quota,
+ bool success) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DidDatabaseWork(success);
+ std::move(callback).Run(
+ success ? blink::mojom::QuotaStatusCode::kOk
+ : blink::mojom::QuotaStatusCode::kErrorInvalidAccess,
+ *new_quota);
+}
+
+void QuotaManagerImpl::DidGetLRUOrigin(
+ std::unique_ptr<base::Optional<url::Origin>> origin,
+ bool success) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DidDatabaseWork(success);
+
+ std::move(lru_origin_callback_).Run(*origin);
+}
+
+namespace {
+void DidGetSettingsThreadAdapter(base::TaskRunner* task_runner,
+ OptionalQuotaSettingsCallback callback,
+ base::Optional<QuotaSettings> settings) {
+ task_runner->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), std::move(settings)));
+}
+} // namespace
+
+void QuotaManagerImpl::GetQuotaSettings(QuotaSettingsCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (base::TimeTicks::Now() - settings_timestamp_ <
+ settings_.refresh_interval) {
+ std::move(callback).Run(settings_);
+ return;
+ }
+
+ if (!settings_callbacks_.Add(std::move(callback)))
+ return;
+
+ // We invoke our clients GetQuotaSettingsFunc on the
+ // UI thread and plumb the resulting value back to this thread.
+ get_settings_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ get_settings_function_,
+ base::BindOnce(&DidGetSettingsThreadAdapter,
+ base::RetainedRef(base::ThreadTaskRunnerHandle::Get()),
+ base::BindOnce(&QuotaManagerImpl::DidGetSettings,
+ weak_factory_.GetWeakPtr()))));
+}
+
+void QuotaManagerImpl::DidGetSettings(base::Optional<QuotaSettings> settings) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!settings) {
+ settings = settings_;
+ settings->refresh_interval = base::TimeDelta::FromMinutes(1);
+ }
+ SetQuotaSettings(*settings);
+ settings_callbacks_.Run(*settings);
+ UMA_HISTOGRAM_MBYTES("Quota.GlobalTemporaryPoolSize", settings->pool_size);
+ LOG_IF(WARNING, settings->pool_size == 0)
+ << "No storage quota provided in QuotaSettings.";
+}
+
+void QuotaManagerImpl::GetStorageCapacity(StorageCapacityCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!storage_capacity_callbacks_.Add(std::move(callback)))
+ return;
+ if (is_incognito_) {
+ GetQuotaSettings(
+ base::BindOnce(&QuotaManagerImpl::ContinueIncognitoGetStorageCapacity,
+ weak_factory_.GetWeakPtr()));
+ return;
+ }
+ base::PostTaskAndReplyWithResult(
+ db_runner_.get(), FROM_HERE,
+ base::BindOnce(&QuotaManagerImpl::CallGetVolumeInfo, get_volume_info_fn_,
+ profile_path_),
+ base::BindOnce(&QuotaManagerImpl::DidGetStorageCapacity,
+ weak_factory_.GetWeakPtr()));
+}
+
+void QuotaManagerImpl::ContinueIncognitoGetStorageCapacity(
+ const QuotaSettings& settings) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ int64_t current_usage =
+ GetUsageTracker(StorageType::kTemporary)->GetCachedUsage();
+ current_usage += GetUsageTracker(StorageType::kPersistent)->GetCachedUsage();
+ int64_t available_space =
+ std::max(INT64_C(0), settings.pool_size - current_usage);
+ DidGetStorageCapacity(std::make_tuple(settings.pool_size, available_space));
+}
+
+void QuotaManagerImpl::DidGetStorageCapacity(
+ const std::tuple<int64_t, int64_t>& total_and_available) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ int64_t total_space = std::get<0>(total_and_available);
+ int64_t available_space = std::get<1>(total_and_available);
+ cached_disk_stats_for_storage_pressure_ =
+ std::make_tuple(base::TimeTicks::Now(), total_space, available_space);
+ storage_capacity_callbacks_.Run(total_space, available_space);
+ DetermineStoragePressure(total_space, available_space);
+}
+
+void QuotaManagerImpl::DidDatabaseWork(bool success) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ db_disabled_ = !success;
+}
+
+void QuotaManagerImpl::PostTaskAndReplyWithResultForDBThread(
+ const base::Location& from_here,
+ base::OnceCallback<bool(QuotaDatabase*)> task,
+ base::OnceCallback<void(bool)> reply) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // Deleting manager will post another task to DB sequence to delete
+ // |database_|, therefore we can be sure that database_ is alive when this
+ // task runs.
+ base::PostTaskAndReplyWithResult(
+ db_runner_.get(), from_here,
+ base::BindOnce(std::move(task), base::Unretained(database_.get())),
+ std::move(reply));
+}
+
+// static
+std::tuple<int64_t, int64_t> QuotaManagerImpl::CallGetVolumeInfo(
+ GetVolumeInfoFn get_volume_info_fn,
+ const base::FilePath& path) {
+ if (!base::CreateDirectory(path)) {
+ LOG(WARNING) << "Create directory failed for path" << path.value();
+ return std::make_tuple<int64_t, int64_t>(0, 0);
+ }
+ int64_t total;
+ int64_t available;
+ std::tie(total, available) = get_volume_info_fn(path);
+ if (total < 0 || available < 0) {
+ LOG(WARNING) << "Unable to get volume info: " << path.value();
+ return std::make_tuple<int64_t, int64_t>(0, 0);
+ }
+ UMA_HISTOGRAM_MBYTES("Quota.TotalDiskSpace", total);
+ UMA_HISTOGRAM_MBYTES("Quota.AvailableDiskSpace", available);
+ if (total > 0) {
+ UMA_HISTOGRAM_PERCENTAGE("Quota.PercentDiskAvailable",
+ std::min(100, static_cast<int>((available * 100) / total)));
+ }
+ return std::make_tuple(total, available);
+}
+
+// static
+std::tuple<int64_t, int64_t> QuotaManagerImpl::GetVolumeInfo(
+ const base::FilePath& path) {
+ return std::make_tuple(base::SysInfo::AmountOfTotalDiskSpace(path),
+ base::SysInfo::AmountOfFreeDiskSpace(path));
+}
+
+} // namespace storage
diff --git a/chromium/storage/browser/quota/quota_manager_impl.h b/chromium/storage/browser/quota/quota_manager_impl.h
new file mode 100644
index 00000000000..817f16ecd9c
--- /dev/null
+++ b/chromium/storage/browser/quota/quota_manager_impl.h
@@ -0,0 +1,613 @@
+// Copyright 2013 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_QUOTA_MANAGER_IMPL_H_
+#define STORAGE_BROWSER_QUOTA_QUOTA_MANAGER_IMPL_H_
+
+#include <stdint.h>
+
+#include <list>
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/component_export.h"
+#include "base/containers/contains.h"
+#include "base/containers/flat_set.h"
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/ref_counted_delete_on_sequence.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "base/sequence_checker.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "components/services/storage/public/mojom/quota_client.mojom.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "storage/browser/quota/quota_callbacks.h"
+#include "storage/browser/quota/quota_client.h"
+#include "storage/browser/quota/quota_client_type.h"
+#include "storage/browser/quota/quota_database.h"
+#include "storage/browser/quota/quota_settings.h"
+#include "storage/browser/quota/quota_task.h"
+#include "storage/browser/quota/special_storage_policy.h"
+#include "third_party/blink/public/mojom/quota/quota_types.mojom-forward.h"
+#include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h"
+#include "url/origin.h"
+
+namespace base {
+class SequencedTaskRunner;
+class SingleThreadTaskRunner;
+class TaskRunner;
+} // namespace base
+
+namespace quota_internals {
+class QuotaInternalsProxy;
+} // namespace quota_internals
+
+namespace storage {
+
+class QuotaManagerProxy;
+class QuotaOverrideHandle;
+class QuotaTemporaryStorageEvictor;
+class UsageTracker;
+
+// 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 =
+ base::OnceCallback<void(blink::mojom::QuotaStatusCode status,
+ const QuotaSettings& settings,
+ int64_t available_space,
+ int64_t total_space,
+ int64_t global_usage,
+ bool global_usage_is_complete)>;
+
+ // Called at the beginning of an eviction round to gather the info about
+ // the current settings, capacity, and usage.
+ virtual void GetEvictionRoundInfo(EvictionRoundInfoCallback callback) = 0;
+
+ // Returns next origin to evict, or nullopt if there are no evictable
+ // origins.
+ virtual void GetEvictionOrigin(blink::mojom::StorageType type,
+ int64_t global_quota,
+ GetOriginCallback callback) = 0;
+
+ // Called to evict an origin.
+ virtual void EvictOriginData(const url::Origin& origin,
+ blink::mojom::StorageType type,
+ StatusCallback callback) = 0;
+
+ protected:
+ virtual ~QuotaEvictionHandler() = default;
+};
+
+struct UsageInfo {
+ UsageInfo(std::string host, blink::mojom::StorageType type, int64_t usage)
+ : host(std::move(host)), type(type), usage(usage) {}
+ const std::string host;
+ const blink::mojom::StorageType type;
+ const int64_t usage;
+};
+
+// Entry point into the Quota System
+//
+// Each StoragePartition has exactly one QuotaManagerImpl 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.
+// QuotaManagerImpl 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) QuotaManagerImpl
+ : public QuotaTaskObserver,
+ public QuotaEvictionHandler,
+ public base::RefCountedDeleteOnSequence<QuotaManagerImpl> {
+ public:
+ using UsageAndQuotaCallback = base::OnceCallback<
+ void(blink::mojom::QuotaStatusCode, int64_t usage, int64_t quota)>;
+
+ using UsageAndQuotaWithBreakdownCallback =
+ base::OnceCallback<void(blink::mojom::QuotaStatusCode,
+ int64_t usage,
+ int64_t quota,
+ blink::mojom::UsageBreakdownPtr usage_breakdown)>;
+
+ using UsageAndQuotaForDevtoolsCallback =
+ base::OnceCallback<void(blink::mojom::QuotaStatusCode,
+ int64_t usage,
+ int64_t quota,
+ bool is_override_enabled,
+ blink::mojom::UsageBreakdownPtr usage_breakdown)>;
+
+ // Function pointer type used to store the function which returns
+ // information about the volume containing the given FilePath.
+ // The value returned is std::tuple<total_space, available_space>.
+ using GetVolumeInfoFn =
+ std::tuple<int64_t, int64_t> (*)(const base::FilePath&);
+
+ static constexpr int64_t kGBytes = 1024 * 1024 * 1024;
+ static constexpr int64_t kNoLimit = INT64_MAX;
+ static constexpr int64_t kMBytes = 1024 * 1024;
+ static constexpr int kMinutesInMilliSeconds = 60 * 1000;
+
+ QuotaManagerImpl(bool is_incognito,
+ const base::FilePath& profile_path,
+ scoped_refptr<base::SingleThreadTaskRunner> io_thread,
+ base::RepeatingClosure quota_change_callback,
+ scoped_refptr<SpecialStoragePolicy> special_storage_policy,
+ const GetQuotaSettingsFunc& get_settings_function);
+ QuotaManagerImpl(const QuotaManagerImpl&) = delete;
+ QuotaManagerImpl& operator=(const QuotaManagerImpl&) = delete;
+
+ const QuotaSettings& settings() const { return settings_; }
+ void SetQuotaSettings(const QuotaSettings& settings);
+
+ // Returns a proxy object that can be used on any thread.
+ QuotaManagerProxy* proxy() { return proxy_.get(); }
+
+ // Called by clients or webapps. Returns usage per host.
+ void GetUsageInfo(GetUsageInfoCallback callback);
+
+ // Called by Web Apps (deprecated quota API).
+ // This method is declared as virtual to allow test code to override it.
+ virtual void GetUsageAndQuotaForWebApps(const url::Origin& origin,
+ blink::mojom::StorageType type,
+ UsageAndQuotaCallback callback);
+
+ // Called by Web Apps (navigator.storage.estimate())
+ // This method is declared as virtual to allow test code to override it.
+ virtual void GetUsageAndQuotaWithBreakdown(
+ const url::Origin& origin,
+ blink::mojom::StorageType type,
+ UsageAndQuotaWithBreakdownCallback callback);
+
+ // Called by DevTools.
+ virtual void GetUsageAndQuotaForDevtools(
+ const url::Origin& origin,
+ blink::mojom::StorageType type,
+ UsageAndQuotaForDevtoolsCallback callback);
+
+ // Called by storage backends.
+ //
+ // For UnlimitedStorage origins, this version skips usage and quota handling
+ // to avoid extra query cost. Do not call this method for apps/user-facing
+ // code.
+ //
+ // This method is declared as virtual to allow test code to override it.
+ virtual void GetUsageAndQuota(const url::Origin& origin,
+ blink::mojom::StorageType type,
+ UsageAndQuotaCallback callback);
+
+ // Called by storage backends via proxy.
+ //
+ // Quota-managed storage backends should call this method when storage is
+ // accessed. Used to maintain LRU ordering.
+ void NotifyStorageAccessed(const url::Origin& origin,
+ blink::mojom::StorageType type,
+ base::Time access_time);
+
+ // Called by storage backends via proxy.
+ //
+ // Quota-managed storage backends must call this method when they have made
+ // any modifications that change the amount of data stored in their storage.
+ void NotifyStorageModified(QuotaClientType client_id,
+ const url::Origin& origin,
+ blink::mojom::StorageType type,
+ int64_t delta,
+ base::Time modification_time,
+ base::OnceClosure callback);
+
+ // Called by storage backends via proxy.
+ //
+ // Client storage must call this method whenever they run into disk
+ // write errors. Used as a hint to determine if the storage partition is out
+ // of space, and trigger actions if deemed appropriate.
+ //
+ // This method is declared as virtual to allow test code to override it.
+ virtual void NotifyWriteFailed(const url::Origin& origin);
+
+ // Used to avoid evicting origins with open pages.
+ // A call to NotifyOriginInUse must be balanced by a later call
+ // to NotifyOriginNoLongerInUse.
+ void NotifyOriginInUse(const url::Origin& origin);
+ void NotifyOriginNoLongerInUse(const url::Origin& origin);
+ bool IsOriginInUse(const url::Origin& origin) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return base::Contains(origins_in_use_, origin);
+ }
+
+ void SetUsageCacheEnabled(QuotaClientType client_id,
+ const url::Origin& origin,
+ blink::mojom::StorageType type,
+ bool enabled);
+
+ // DeleteOriginData and DeleteHostData (surprisingly enough) delete data of a
+ // particular blink::mojom::StorageType associated with either a specific
+ // origin or set of origins. Each method additionally requires a
+ // |quota_client_types| which specifies the types of QuotaClients to delete
+ // from the origin. Pass in QuotaClientType::AllClients() to remove all
+ // clients from the origin, regardless of type.
+ virtual void DeleteOriginData(const url::Origin& origin,
+ blink::mojom::StorageType type,
+ QuotaClientTypes quota_client_types,
+ StatusCallback callback);
+ void DeleteHostData(const std::string& host,
+ blink::mojom::StorageType type,
+ QuotaClientTypes quota_client_types,
+ StatusCallback callback);
+
+ // Instructs each QuotaClient to remove possible traces of deleted
+ // data on the disk.
+ void PerformStorageCleanup(blink::mojom::StorageType type,
+ QuotaClientTypes quota_client_types,
+ base::OnceClosure callback);
+
+ // Called by UI and internal modules.
+ void GetPersistentHostQuota(const std::string& host, QuotaCallback callback);
+ void SetPersistentHostQuota(const std::string& host,
+ int64_t new_quota,
+ QuotaCallback callback);
+ void GetGlobalUsage(blink::mojom::StorageType type,
+ GlobalUsageCallback callback);
+ void GetHostUsageWithBreakdown(const std::string& host,
+ blink::mojom::StorageType type,
+ UsageWithBreakdownCallback callback);
+
+ std::map<std::string, std::string> GetStatistics();
+
+ bool IsStorageUnlimited(const url::Origin& origin,
+ blink::mojom::StorageType type) const;
+
+ virtual void GetOriginsModifiedBetween(blink::mojom::StorageType type,
+ base::Time begin,
+ base::Time end,
+ GetOriginsCallback callback);
+
+ bool ResetUsageTracker(blink::mojom::StorageType type);
+
+ // Called when StoragePartition is initialized if embedder has an
+ // implementation of StorageNotificationService.
+ void SetStoragePressureCallback(
+ base::RepeatingCallback<void(url::Origin)> storage_pressure_callback);
+
+ // DevTools Quota Override methods:
+ int GetOverrideHandleId();
+ void OverrideQuotaForOrigin(int handle_id,
+ const url::Origin& origin,
+ base::Optional<int64_t> quota_size);
+ // Called when a DevTools client releases all overrides, however, overrides
+ // will not be disabled for any origins for which there are other DevTools
+ // clients/QuotaOverrideHandle with an active override.
+ void WithdrawOverridesForHandle(int handle_id);
+
+ // Cap size for per-host persistent quota determined by the histogram.
+ // Cap size for per-host persistent quota determined by the histogram.
+ // This is a bit lax value because the histogram says nothing about per-host
+ // persistent storage usage and we determined by global persistent storage
+ // usage that is less than 10GB for almost all users.
+ static constexpr int64_t kPerHostPersistentQuotaLimit = 10 * 1024 * kMBytes;
+
+ static constexpr int kEvictionIntervalInMilliSeconds =
+ 30 * kMinutesInMilliSeconds;
+ static constexpr int kThresholdOfErrorsToBeDenylisted = 3;
+ static constexpr int kThresholdRandomizationPercent = 5;
+
+ static constexpr char kDatabaseName[] = "QuotaManager";
+ static constexpr char kDaysBetweenRepeatedOriginEvictionsHistogram[] =
+ "Quota.DaysBetweenRepeatedOriginEvictions";
+ static constexpr char kEvictedOriginAccessedCountHistogram[] =
+ "Quota.EvictedOriginAccessCount";
+ static constexpr char kEvictedOriginDaysSinceAccessHistogram[] =
+ "Quota.EvictedOriginDaysSinceAccess";
+
+ // Kept non-const so that test code can change the value.
+ // TODO(kinuko): Make this a real const value and add a proper way to set
+ // the quota for syncable storage. (http://crbug.com/155488)
+ static int64_t kSyncableStorageDefaultHostQuota;
+
+ void DisableDatabaseForTesting() { db_disabled_ = true; }
+
+ void SetGetVolumeInfoFnForTesting(GetVolumeInfoFn fn) {
+ get_volume_info_fn_ = fn;
+ }
+
+ protected:
+ ~QuotaManagerImpl() override;
+ void SetQuotaChangeCallbackForTesting(
+ base::RepeatingClosure storage_pressure_event_callback);
+
+ private:
+ friend class base::DeleteHelper<QuotaManagerImpl>;
+ friend class base::RefCountedDeleteOnSequence<QuotaManagerImpl>;
+ friend class quota_internals::QuotaInternalsProxy;
+ friend class MockQuotaManager;
+ friend class MockQuotaClient;
+ friend class QuotaManagerProxy;
+ friend class QuotaManagerImplTest;
+ friend class QuotaTemporaryStorageEvictor;
+
+ class EvictionRoundInfoHelper;
+ class UsageAndQuotaInfoGatherer;
+ class GetUsageInfoTask;
+ class OriginDataDeleter;
+ class HostDataDeleter;
+ class GetModifiedSinceHelper;
+ class DumpQuotaTableHelper;
+ class DumpOriginInfoTableHelper;
+ class StorageCleanupHelper;
+
+ struct QuotaOverride {
+ QuotaOverride();
+ ~QuotaOverride();
+
+ QuotaOverride(const QuotaOverride& quota_override) = delete;
+ QuotaOverride& operator=(const QuotaOverride&) = delete;
+
+ int64_t quota_size;
+
+ // Keeps track of the DevTools clients that have an active override.
+ std::set<int> active_override_session_ids;
+ };
+
+ using QuotaTableEntry = QuotaDatabase::QuotaTableEntry;
+ using OriginInfoTableEntry = QuotaDatabase::OriginInfoTableEntry;
+ using QuotaTableEntries = std::vector<QuotaTableEntry>;
+ using OriginInfoTableEntries = std::vector<OriginInfoTableEntry>;
+
+ using QuotaSettingsCallback = base::OnceCallback<void(const QuotaSettings&)>;
+
+ using DumpQuotaTableCallback =
+ base::OnceCallback<void(const QuotaTableEntries&)>;
+ using DumpOriginInfoTableCallback =
+ base::OnceCallback<void(const OriginInfoTableEntries&)>;
+
+ // The values returned total_space, available_space.
+ using StorageCapacityCallback = base::OnceCallback<void(int64_t, int64_t)>;
+
+ struct EvictionContext {
+ EvictionContext();
+ ~EvictionContext();
+ url::Origin evicted_origin;
+ blink::mojom::StorageType evicted_type;
+ StatusCallback evict_origin_data_callback;
+ };
+
+ // Lazily called on the IO thread when the first quota manager API is called.
+ //
+ // Initialize() must be called after all quota clients are added to the
+ // manager by RegisterClient().
+ void LazyInitialize();
+ void FinishLazyInitialize(bool is_database_bootstraped);
+ void BootstrapDatabaseForEviction(GetOriginCallback did_get_origin_callback,
+ int64_t unused_usage,
+ int64_t unused_unlimited_usage);
+ void DidBootstrapDatabase(GetOriginCallback did_get_origin_callback,
+ bool success);
+
+ // Called by clients via proxy.
+ // Registers a quota client to the manager.
+ void RegisterClient(
+ mojo::PendingRemote<mojom::QuotaClient> client,
+ QuotaClientType client_type,
+ const std::vector<blink::mojom::StorageType>& storage_types);
+
+ // Legacy overload for QuotaClients that have not been mojofied yet.
+ //
+ // TODO(crbug.com/1163009): Remove this overload after all QuotaClients have
+ // been mojofied.
+ void RegisterLegacyClient(
+ scoped_refptr<QuotaClient> client,
+ QuotaClientType client_type,
+ const std::vector<blink::mojom::StorageType>& storage_types);
+
+ UsageTracker* GetUsageTracker(blink::mojom::StorageType type) const;
+
+ // Extract cached origins list from the usage tracker.
+ // (Might return empty list if no origin is tracked by the tracker.)
+ std::set<url::Origin> GetCachedOrigins(blink::mojom::StorageType type);
+
+ void DumpQuotaTable(DumpQuotaTableCallback callback);
+ void DumpOriginInfoTable(DumpOriginInfoTableCallback callback);
+
+ void DeleteOriginDataInternal(const url::Origin& origin,
+ blink::mojom::StorageType type,
+ QuotaClientTypes quota_client_types,
+ bool is_eviction,
+ StatusCallback callback);
+
+ // Methods for eviction logic.
+ void StartEviction();
+ void DeleteOriginFromDatabase(const url::Origin& origin,
+ blink::mojom::StorageType type,
+ bool is_eviction);
+
+ void DidOriginDataEvicted(blink::mojom::QuotaStatusCode status);
+
+ void ReportHistogram();
+ void DidGetTemporaryGlobalUsageForHistogram(int64_t usage,
+ int64_t unlimited_usage);
+ void DidGetStorageCapacityForHistogram(int64_t usage,
+ int64_t total_space,
+ int64_t available_space);
+ void DidGetPersistentGlobalUsageForHistogram(int64_t usage,
+ int64_t unlimited_usage);
+ void DidDumpOriginInfoTableForHistogram(
+ const OriginInfoTableEntries& entries);
+
+ std::set<url::Origin> GetEvictionOriginExceptions();
+ void DidGetEvictionOrigin(GetOriginCallback callback,
+ const base::Optional<url::Origin>& origin);
+
+ // QuotaEvictionHandler.
+ void GetEvictionOrigin(blink::mojom::StorageType type,
+ int64_t global_quota,
+ GetOriginCallback callback) override;
+ void EvictOriginData(const url::Origin& origin,
+ blink::mojom::StorageType type,
+ StatusCallback callback) override;
+ void GetEvictionRoundInfo(EvictionRoundInfoCallback callback) override;
+
+ void GetLRUOrigin(blink::mojom::StorageType type, GetOriginCallback callback);
+
+ void DidGetPersistentHostQuota(const std::string& host,
+ const int64_t* quota,
+ bool success);
+ void DidSetPersistentHostQuota(const std::string& host,
+ QuotaCallback callback,
+ const int64_t* new_quota,
+ bool success);
+ void DidGetLRUOrigin(std::unique_ptr<base::Optional<url::Origin>> origin,
+ bool success);
+ void GetQuotaSettings(QuotaSettingsCallback callback);
+ void DidGetSettings(base::Optional<QuotaSettings> settings);
+ void GetStorageCapacity(StorageCapacityCallback callback);
+ void ContinueIncognitoGetStorageCapacity(const QuotaSettings& settings);
+ void DidGetStorageCapacity(
+ const std::tuple<int64_t, int64_t>& total_and_available);
+
+ void DidDatabaseWork(bool success);
+
+ void DeleteOnCorrectThread() const;
+
+ void MaybeRunStoragePressureCallback(const url::Origin& origin,
+ int64_t total_space,
+ int64_t available_space);
+ // Used from quota-internals page to test behavior of the storage pressure
+ // callback.
+ void SimulateStoragePressure(const url::Origin origin);
+
+ // Evaluates disk statistics to identify storage pressure
+ // (low disk space availability) and starts the storage
+ // pressure event dispatch if appropriate.
+ // TODO(crbug.com/1088004): Implement UsageAndQuotaInfoGatherer::Completed()
+ // to use DetermineStoragePressure().
+ // TODO(crbug.com/1102433): Define and explain StoragePressure in the README.
+ void DetermineStoragePressure(int64_t free_space, int64_t total_space);
+
+ base::Optional<int64_t> GetQuotaOverrideForOrigin(const url::Origin&);
+
+ void PostTaskAndReplyWithResultForDBThread(
+ const base::Location& from_here,
+ base::OnceCallback<bool(QuotaDatabase*)> task,
+ base::OnceCallback<void(bool)> reply);
+
+ static std::tuple<int64_t, int64_t> CallGetVolumeInfo(
+ GetVolumeInfoFn get_volume_info_fn,
+ const base::FilePath& path);
+ static std::tuple<int64_t, int64_t> GetVolumeInfo(const base::FilePath& path);
+
+ const bool is_incognito_;
+ const base::FilePath profile_path_;
+
+ // This member is thread-safe. The scoped_refptr is immutable (the object it
+ // points to never changes), and the underlying object is thread-safe.
+ const scoped_refptr<QuotaManagerProxy> proxy_;
+
+ bool db_disabled_;
+ bool eviction_disabled_;
+ base::Optional<url::Origin> origin_for_pending_storage_pressure_callback_;
+ scoped_refptr<base::SingleThreadTaskRunner> io_thread_;
+ scoped_refptr<base::SequencedTaskRunner> db_runner_;
+ mutable std::unique_ptr<QuotaDatabase> database_;
+ bool is_database_bootstrapped_ = false;
+
+ GetQuotaSettingsFunc get_settings_function_;
+ scoped_refptr<base::TaskRunner> get_settings_task_runner_;
+ base::RepeatingCallback<void(url::Origin)> storage_pressure_callback_;
+ base::RepeatingClosure quota_change_callback_;
+ QuotaSettings settings_;
+ base::TimeTicks settings_timestamp_;
+ std::tuple<base::TimeTicks, int64_t, int64_t>
+ cached_disk_stats_for_storage_pressure_;
+ CallbackQueue<QuotaSettingsCallback, const QuotaSettings&>
+ settings_callbacks_;
+ CallbackQueue<StorageCapacityCallback, int64_t, int64_t>
+ storage_capacity_callbacks_;
+
+ GetOriginCallback lru_origin_callback_;
+ std::set<url::Origin> access_notified_origins_;
+
+ std::map<url::Origin, QuotaOverride> devtools_overrides_;
+ int next_override_handle_id_ = 0;
+
+ // Owns the QuotaClient remotes registered via RegisterClient().
+ //
+ // Iterating over this list is almost always incorrect. Most algorithms should
+ // iterate over an entry in |client_types_|.
+ //
+ // TODO(crbug.com/1016065): Handle Storage Service crashes. Will likely entail
+ // using a mojo::RemoteSet here.
+ std::vector<mojo::Remote<mojom::QuotaClient>> clients_for_ownership_;
+
+ // Owns the QuotaClient instances registered by RegisterLegacyClient() and
+ // their wrappers.
+ //
+ // TODO(crbug.com/1163009): Remove this member after all QuotaClients have
+ // been mojofied.
+ std::vector<scoped_refptr<QuotaClient>> legacy_clients_for_ownership_;
+
+ // Maps QuotaClient instances to client types.
+ //
+ // The QuotaClient instances pointed to by the map keys are guaranteed to be
+ // alive, because they are owned by `legacy_clients_for_ownership_`.
+ //
+ // TODO(crbug.com/1163009): Replace the map key with mojom::QuotaClient* after
+ // all QuotaClients have been mojofied.
+ base::flat_map<blink::mojom::StorageType,
+ base::flat_map<QuotaClient*, QuotaClientType>>
+ client_types_;
+
+ std::unique_ptr<UsageTracker> temporary_usage_tracker_;
+ std::unique_ptr<UsageTracker> persistent_usage_tracker_;
+ std::unique_ptr<UsageTracker> syncable_usage_tracker_;
+ // TODO(michaeln): Need a way to clear the cache, drop and
+ // reinstantiate the trackers when they're not handling requests.
+
+ std::unique_ptr<QuotaTemporaryStorageEvictor> temporary_storage_evictor_;
+ EvictionContext eviction_context_;
+ bool is_getting_eviction_origin_;
+
+ CallbackQueueMap<QuotaCallback,
+ std::string,
+ blink::mojom::QuotaStatusCode,
+ int64_t>
+ persistent_host_quota_callbacks_;
+
+ // Map from origin to count.
+ std::map<url::Origin, int> origins_in_use_;
+ // Map from origin to error count.
+ std::map<url::Origin, int> origins_in_error_;
+
+ scoped_refptr<SpecialStoragePolicy> special_storage_policy_;
+
+ base::RepeatingTimer histogram_timer_;
+
+ // Pointer to the function used to get volume information. This is
+ // overwritten by QuotaManagerImplTest in order to attain deterministic
+ // reported values. The default value points to
+ // QuotaManagerImpl::GetVolumeInfo.
+ GetVolumeInfoFn get_volume_info_fn_;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ base::WeakPtrFactory<QuotaManagerImpl> weak_factory_{this};
+};
+
+} // namespace storage
+
+#endif // STORAGE_BROWSER_QUOTA_QUOTA_MANAGER_IMPL_H_
diff --git a/chromium/storage/browser/quota/quota_manager_proxy.cc b/chromium/storage/browser/quota/quota_manager_proxy.cc
index df7ec05bc43..de6b66c63c8 100644
--- a/chromium/storage/browser/quota/quota_manager_proxy.cc
+++ b/chromium/storage/browser/quota/quota_manager_proxy.cc
@@ -5,161 +5,261 @@
#include "storage/browser/quota/quota_manager_proxy.h"
#include <stdint.h>
+
+#include <memory>
#include <utility>
+#include <vector>
#include "base/bind.h"
-#include "base/callback_helpers.h"
+#include "base/location.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/task/post_task.h"
-#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
+#include "components/services/storage/public/mojom/quota_client.mojom.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "storage/browser/quota/quota_client.h"
#include "storage/browser/quota/quota_client_type.h"
-#include "storage/browser/quota/quota_manager.h"
+#include "storage/browser/quota/quota_manager_impl.h"
+#include "storage/browser/quota/quota_override_handle.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
+#include "url/origin.h"
namespace storage {
-namespace {
+QuotaManagerProxy::QuotaManagerProxy(
+ QuotaManagerImpl* quota_manager_impl,
+ scoped_refptr<base::SequencedTaskRunner> quota_manager_impl_task_runner)
+ : quota_manager_impl_(quota_manager_impl),
+ quota_manager_impl_task_runner_(
+ std::move(quota_manager_impl_task_runner)) {
+ DCHECK(quota_manager_impl_task_runner_.get());
+
+ DETACH_FROM_SEQUENCE(quota_manager_impl_sequence_checker_);
+}
-void DidGetUsageAndQuota(base::SequencedTaskRunner* original_task_runner,
- QuotaManagerProxy::UsageAndQuotaCallback callback,
- blink::mojom::QuotaStatusCode status,
- int64_t usage,
- int64_t quota) {
- if (!original_task_runner->RunsTasksInCurrentSequence()) {
- original_task_runner->PostTask(
- FROM_HERE, base::BindOnce(&DidGetUsageAndQuota,
- base::RetainedRef(original_task_runner),
- std::move(callback), status, usage, quota));
+void QuotaManagerProxy::RegisterLegacyClient(
+ scoped_refptr<QuotaClient> client,
+ QuotaClientType client_type,
+ const std::vector<blink::mojom::StorageType>& storage_types) {
+ if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
+ quota_manager_impl_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&QuotaManagerProxy::RegisterLegacyClient, this,
+ std::move(client), client_type, storage_types));
return;
}
- std::move(callback).Run(status, usage, quota);
-}
-} // namespace
+ DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_);
+ if (!quota_manager_impl_) {
+ client->OnQuotaManagerDestroyed();
+ return;
+ }
+
+ quota_manager_impl_->RegisterLegacyClient(std::move(client), client_type,
+ storage_types);
+}
void QuotaManagerProxy::RegisterClient(
- scoped_refptr<QuotaClient> client,
+ mojo::PendingRemote<mojom::QuotaClient> client,
QuotaClientType client_type,
const std::vector<blink::mojom::StorageType>& storage_types) {
- if (!io_thread_->BelongsToCurrentThread()) {
- io_thread_->PostTask(
+ if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
+ quota_manager_impl_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&QuotaManagerProxy::RegisterClient, this,
std::move(client), client_type, storage_types));
return;
}
- if (manager_) {
- manager_->RegisterClient(std::move(client), client_type, storage_types);
- } else {
- client->OnQuotaManagerDestroyed();
+ DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_);
+ if (quota_manager_impl_) {
+ quota_manager_impl_->RegisterClient(std::move(client), client_type,
+ storage_types);
}
}
void QuotaManagerProxy::NotifyStorageAccessed(const url::Origin& origin,
- blink::mojom::StorageType type) {
- if (!io_thread_->BelongsToCurrentThread()) {
- io_thread_->PostTask(
+ blink::mojom::StorageType type,
+ base::Time access_time) {
+ if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
+ quota_manager_impl_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&QuotaManagerProxy::NotifyStorageAccessed,
- this, origin, type));
+ this, origin, type, access_time));
return;
}
- if (manager_)
- manager_->NotifyStorageAccessed(origin, type);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_);
+ if (quota_manager_impl_)
+ quota_manager_impl_->NotifyStorageAccessed(origin, type, access_time);
}
-void QuotaManagerProxy::NotifyStorageModified(QuotaClientType client_id,
- const url::Origin& origin,
- blink::mojom::StorageType type,
- int64_t delta) {
- if (!io_thread_->BelongsToCurrentThread()) {
- io_thread_->PostTask(
- FROM_HERE, base::BindOnce(&QuotaManagerProxy::NotifyStorageModified,
- this, client_id, origin, type, delta));
+void QuotaManagerProxy::NotifyStorageModified(
+ QuotaClientType client_id,
+ const url::Origin& origin,
+ blink::mojom::StorageType type,
+ int64_t delta,
+ base::Time modification_time,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ base::OnceClosure callback) {
+ DCHECK(!callback || callback_task_runner);
+ if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
+ quota_manager_impl_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&QuotaManagerProxy::NotifyStorageModified, this,
+ client_id, origin, type, delta, modification_time,
+ std::move(callback_task_runner), std::move(callback)));
return;
}
- if (manager_)
- manager_->NotifyStorageModified(client_id, origin, type, delta);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_);
+ if (quota_manager_impl_) {
+ base::OnceClosure manager_callback;
+ if (callback) {
+ manager_callback = base::BindOnce(
+ [](scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ base::OnceClosure callback) {
+ if (callback_task_runner->RunsTasksInCurrentSequence()) {
+ std::move(callback).Run();
+ return;
+ }
+ callback_task_runner->PostTask(FROM_HERE, std::move(callback));
+ },
+ std::move(callback_task_runner), std::move(callback));
+ }
+ quota_manager_impl_->NotifyStorageModified(client_id, origin, type, delta,
+ modification_time,
+ std::move(manager_callback));
+ }
}
void QuotaManagerProxy::NotifyOriginInUse(const url::Origin& origin) {
- if (!io_thread_->BelongsToCurrentThread()) {
- io_thread_->PostTask(
+ if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
+ quota_manager_impl_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&QuotaManagerProxy::NotifyOriginInUse, this, origin));
return;
}
- if (manager_)
- manager_->NotifyOriginInUse(origin);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_);
+ if (quota_manager_impl_)
+ quota_manager_impl_->NotifyOriginInUse(origin);
}
void QuotaManagerProxy::NotifyOriginNoLongerInUse(const url::Origin& origin) {
- if (!io_thread_->BelongsToCurrentThread()) {
- io_thread_->PostTask(
+ if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
+ quota_manager_impl_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&QuotaManagerProxy::NotifyOriginNoLongerInUse,
this, origin));
return;
}
- if (manager_)
- manager_->NotifyOriginNoLongerInUse(origin);
+
+ DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_);
+ if (quota_manager_impl_)
+ quota_manager_impl_->NotifyOriginNoLongerInUse(origin);
}
void QuotaManagerProxy::NotifyWriteFailed(const url::Origin& origin) {
- if (!io_thread_->BelongsToCurrentThread()) {
- io_thread_->PostTask(
+ if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
+ quota_manager_impl_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&QuotaManagerProxy::NotifyWriteFailed, this, origin));
return;
}
- if (manager_)
- manager_->NotifyWriteFailed(origin);
+
+ DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_);
+ if (quota_manager_impl_)
+ quota_manager_impl_->NotifyWriteFailed(origin);
}
void QuotaManagerProxy::SetUsageCacheEnabled(QuotaClientType client_id,
const url::Origin& origin,
blink::mojom::StorageType type,
bool enabled) {
- if (!io_thread_->BelongsToCurrentThread()) {
- io_thread_->PostTask(
+ if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
+ quota_manager_impl_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&QuotaManagerProxy::SetUsageCacheEnabled,
this, client_id, origin, type, enabled));
return;
}
- if (manager_)
- manager_->SetUsageCacheEnabled(client_id, origin, type, enabled);
+
+ DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_);
+ if (quota_manager_impl_)
+ quota_manager_impl_->SetUsageCacheEnabled(client_id, origin, type, enabled);
}
+namespace {
+
+void DidGetUsageAndQuota(
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ QuotaManagerProxy::UsageAndQuotaCallback callback,
+ blink::mojom::QuotaStatusCode status,
+ int64_t usage,
+ int64_t quota) {
+ if (callback_task_runner->RunsTasksInCurrentSequence()) {
+ std::move(callback).Run(status, usage, quota);
+ return;
+ }
+ callback_task_runner->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), status, usage, quota));
+}
+
+} // namespace
+
void QuotaManagerProxy::GetUsageAndQuota(
- base::SequencedTaskRunner* original_task_runner,
const url::Origin& origin,
blink::mojom::StorageType type,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
UsageAndQuotaCallback callback) {
- if (!io_thread_->BelongsToCurrentThread()) {
- io_thread_->PostTask(
- FROM_HERE, base::BindOnce(&QuotaManagerProxy::GetUsageAndQuota, this,
- base::RetainedRef(original_task_runner),
- origin, type, std::move(callback)));
+ if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
+ quota_manager_impl_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&QuotaManagerProxy::GetUsageAndQuota, this, origin, type,
+ std::move(callback_task_runner), std::move(callback)));
return;
}
- if (!manager_) {
- DidGetUsageAndQuota(original_task_runner, std::move(callback),
+
+ DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_);
+ if (!quota_manager_impl_) {
+ DidGetUsageAndQuota(std::move(callback_task_runner), std::move(callback),
blink::mojom::QuotaStatusCode::kErrorAbort, 0, 0);
return;
}
- manager_->GetUsageAndQuota(
+ quota_manager_impl_->GetUsageAndQuota(
origin, type,
- base::BindOnce(&DidGetUsageAndQuota,
- base::RetainedRef(original_task_runner),
+ base::BindOnce(&DidGetUsageAndQuota, std::move(callback_task_runner),
std::move(callback)));
}
+void QuotaManagerProxy::IsStorageUnlimited(
+ const url::Origin& origin,
+ blink::mojom::StorageType type,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ base::OnceCallback<void(bool)> callback) {
+ if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
+ quota_manager_impl_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&QuotaManagerProxy::IsStorageUnlimited, this,
+ origin, type, std::move(callback_task_runner),
+ std::move(callback)));
+ return;
+ }
+
+ DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_);
+ bool is_storage_unlimited =
+ quota_manager_impl_
+ ? quota_manager_impl_->IsStorageUnlimited(origin, type)
+ : false;
+
+ if (callback_task_runner->RunsTasksInCurrentSequence()) {
+ std::move(callback).Run(is_storage_unlimited);
+ return;
+ }
+ callback_task_runner->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), is_storage_unlimited));
+}
+
std::unique_ptr<QuotaOverrideHandle>
QuotaManagerProxy::GetQuotaOverrideHandle() {
return std::make_unique<QuotaOverrideHandle>(this);
@@ -169,40 +269,73 @@ void QuotaManagerProxy::OverrideQuotaForOrigin(
int handle_id,
url::Origin origin,
base::Optional<int64_t> quota_size,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
base::OnceClosure callback) {
- io_thread_->PostTaskAndReply(
- FROM_HERE,
- base::BindOnce(&QuotaManager::OverrideQuotaForOrigin,
- base::RetainedRef(manager_), handle_id, origin,
- quota_size),
- std::move(callback));
+ if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
+ quota_manager_impl_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&QuotaManagerProxy::OverrideQuotaForOrigin, this,
+ handle_id, origin, quota_size,
+ std::move(callback_task_runner), std::move(callback)));
+ return;
+ }
+
+ DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_);
+ if (quota_manager_impl_)
+ quota_manager_impl_->OverrideQuotaForOrigin(handle_id, origin, quota_size);
+
+ if (callback_task_runner->RunsTasksInCurrentSequence()) {
+ std::move(callback).Run();
+ return;
+ }
+ callback_task_runner->PostTask(FROM_HERE, std::move(callback));
}
void QuotaManagerProxy::WithdrawOverridesForHandle(int handle_id) {
- io_thread_->PostTask(FROM_HERE,
- base::BindOnce(&QuotaManager::WithdrawOverridesForHandle,
- base::RetainedRef(manager_), handle_id));
-}
+ if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
+ quota_manager_impl_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&QuotaManagerProxy::WithdrawOverridesForHandle, this,
+ handle_id));
+ return;
+ }
-QuotaManager* QuotaManagerProxy::quota_manager() const {
- DCHECK(!io_thread_.get() || io_thread_->BelongsToCurrentThread());
- return manager_;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_);
+ if (quota_manager_impl_)
+ quota_manager_impl_->WithdrawOverridesForHandle(handle_id);
}
-QuotaManagerProxy::QuotaManagerProxy(
- QuotaManager* manager,
- scoped_refptr<base::SingleThreadTaskRunner> io_thread)
- : manager_(manager), io_thread_(std::move(io_thread)) {}
+void QuotaManagerProxy::GetOverrideHandleId(
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ base::OnceCallback<void(int)> callback) {
+ if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) {
+ quota_manager_impl_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&QuotaManagerProxy::GetOverrideHandleId, this,
+ std::move(callback_task_runner), std::move(callback)));
+ return;
+ }
+
+ DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_);
+ int handle_id =
+ quota_manager_impl_ ? quota_manager_impl_->GetOverrideHandleId() : 0;
+
+ if (callback_task_runner->RunsTasksInCurrentSequence()) {
+ std::move(callback).Run(handle_id);
+ return;
+ }
+ callback_task_runner->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), handle_id));
+}
QuotaManagerProxy::~QuotaManagerProxy() = default;
-void QuotaManagerProxy::GetOverrideHandleId(
- base::OnceCallback<void(int)> callback) {
- io_thread_->PostTaskAndReplyWithResult(
- FROM_HERE,
- base::BindOnce(&QuotaManager::GetOverrideHandleId,
- base::RetainedRef(manager_)),
- std::move(callback));
+void QuotaManagerProxy::InvalidateQuotaManagerImpl(
+ base::PassKey<QuotaManagerImpl>) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_);
+
+ DCHECK(quota_manager_impl_) << __func__ << " called multiple times";
+ quota_manager_impl_ = nullptr;
}
} // namespace storage
diff --git a/chromium/storage/browser/quota/quota_manager_proxy.h b/chromium/storage/browser/quota/quota_manager_proxy.h
index 4655f7da5cb..ac64cf6265b 100644
--- a/chromium/storage/browser/quota/quota_manager_proxy.h
+++ b/chromium/storage/browser/quota/quota_manager_proxy.h
@@ -12,45 +12,88 @@
#include "base/callback.h"
#include "base/component_export.h"
-#include "base/files/file_path.h"
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
#include "base/sequenced_task_runner_helpers.h"
+#include "base/thread_annotations.h"
+#include "base/time/time.h"
+#include "base/types/pass_key.h"
+#include "components/services/storage/public/mojom/quota_client.mojom-forward.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "storage/browser/quota/quota_callbacks.h"
-#include "storage/browser/quota/quota_client.h"
#include "storage/browser/quota/quota_client_type.h"
-#include "storage/browser/quota/quota_database.h"
-#include "storage/browser/quota/quota_manager.h"
-#include "storage/browser/quota/quota_override_handle.h"
-#include "storage/browser/quota/quota_task.h"
-#include "storage/browser/quota/special_storage_policy.h"
+#include "storage/browser/quota/quota_manager_impl.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
-#include "url/origin.h"
namespace base {
+
class SequencedTaskRunner;
-class SingleThreadTaskRunner;
-}
+
+} // namespace base
+
+namespace url {
+
+class Origin;
+
+} // namespace url
namespace storage {
-// The proxy may be called and finally released on any thread.
+class QuotaClient;
+class QuotaOverrideHandle;
+
+// Thread-safe proxy for QuotaManagerImpl.
+//
+// Most methods can be called from any thread. The few exceptions are marked
+// accordingly in the associated comments.
class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerProxy
: public base::RefCountedThreadSafe<QuotaManagerProxy> {
public:
- using UsageAndQuotaCallback = QuotaManager::UsageAndQuotaCallback;
+ using UsageAndQuotaCallback = QuotaManagerImpl::UsageAndQuotaCallback;
+
+ // The caller is responsible for calling InvalidateQuotaManagerImpl() before
+ // `quota_manager_impl` is destroyed. `quota_manager_impl_task_runner` must be
+ // associated with the sequence that `quota_manager_impl` may be used on.
+ //
+ // See the comment on `quota_manager_impl_` for an explanation why
+ // `quota_manager_impl` isn't a base::WeakPtr<QuotaManagerImpl>.
+ QuotaManagerProxy(
+ QuotaManagerImpl* quota_manager_impl,
+ scoped_refptr<base::SequencedTaskRunner> quota_manager_impl_task_runner);
+
+ QuotaManagerProxy(const QuotaManagerProxy&) = delete;
+ QuotaManagerProxy& operator=(const QuotaManagerProxy&) = delete;
+
+ // TODO(crbug.com/1163009): Remove this method after all QuotaClients have
+ // been mojofied.
+ virtual void RegisterLegacyClient(
+ scoped_refptr<QuotaClient> client,
+ QuotaClientType client_type,
+ const std::vector<blink::mojom::StorageType>& storage_types);
virtual void RegisterClient(
- scoped_refptr<QuotaClient> client,
+ mojo::PendingRemote<mojom::QuotaClient> client,
QuotaClientType client_type,
const std::vector<blink::mojom::StorageType>& storage_types);
virtual void NotifyStorageAccessed(const url::Origin& origin,
- blink::mojom::StorageType type);
- virtual void NotifyStorageModified(QuotaClientType client_id,
- const url::Origin& origin,
blink::mojom::StorageType type,
- int64_t delta);
+ base::Time access_time);
+
+ // Notify the quota manager that storage has been modified for the given
+ // client. A |callback| may be optionally provided to be invoked on the
+ // given task runner when the quota system's state in memory has been
+ // updated. If a |callback| is provided then |callback_task_runner| must
+ // also be provided. If the quota manager runs on |callback_task_runner|,
+ // then the |callback| may be invoked synchronously.
+ virtual void NotifyStorageModified(
+ QuotaClientType client_id,
+ const url::Origin& origin,
+ blink::mojom::StorageType type,
+ int64_t delta,
+ base::Time modification_time,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner = nullptr,
+ base::OnceClosure callback = base::OnceClosure());
+
virtual void NotifyOriginInUse(const url::Origin& origin);
virtual void NotifyOriginNoLongerInUse(const url::Origin& origin);
virtual void NotifyWriteFailed(const url::Origin& origin);
@@ -59,39 +102,77 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerProxy
const url::Origin& origin,
blink::mojom::StorageType type,
bool enabled);
- virtual void GetUsageAndQuota(base::SequencedTaskRunner* original_task_runner,
- const url::Origin& origin,
- blink::mojom::StorageType type,
- UsageAndQuotaCallback callback);
+ virtual void GetUsageAndQuota(
+ const url::Origin& origin,
+ blink::mojom::StorageType type,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ UsageAndQuotaCallback callback);
+
+ virtual void IsStorageUnlimited(
+ const url::Origin& origin,
+ blink::mojom::StorageType type,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ base::OnceCallback<void(bool)> callback);
// DevTools Quota Override methods:
std::unique_ptr<QuotaOverrideHandle> GetQuotaOverrideHandle();
// Called by QuotaOverrideHandle upon construction to asynchronously
// fetch an id.
- void GetOverrideHandleId(base::OnceCallback<void(int)>);
- void OverrideQuotaForOrigin(int handle_id,
- url::Origin origin,
- base::Optional<int64_t> quota_size,
- base::OnceClosure callback);
+ void GetOverrideHandleId(
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ base::OnceCallback<void(int)> callback);
+ void OverrideQuotaForOrigin(
+ int handle_id,
+ url::Origin origin,
+ base::Optional<int64_t> quota_size,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ base::OnceClosure callback);
void WithdrawOverridesForHandle(int handle_id);
- // This method may only be called on the IO thread.
- // It may return nullptr if the manager has already been deleted.
- QuotaManager* quota_manager() const;
+ // Called right before the QuotaManagerImpl is destroyed.
+ // This method may only be called on the QuotaManagerImpl sequence.
+ void InvalidateQuotaManagerImpl(base::PassKey<QuotaManagerImpl>);
protected:
- friend class QuotaManager;
friend class base::RefCountedThreadSafe<QuotaManagerProxy>;
+ friend class base::DeleteHelper<QuotaManagerProxy>;
- QuotaManagerProxy(QuotaManager* manager,
- scoped_refptr<base::SingleThreadTaskRunner> io_thread);
virtual ~QuotaManagerProxy();
private:
- QuotaManager* manager_; // only accessed on the io thread
- scoped_refptr<base::SingleThreadTaskRunner> io_thread_;
-
- DISALLOW_COPY_AND_ASSIGN(QuotaManagerProxy);
+ // Bound to QuotaManagerImpl's sequence.
+ //
+ // At the time this code is written, there is no way to explicitly bind a
+ // SequenceChecker to a sequence. The implementation ensures that the
+ // SequenceChecker binds to the right sequence by DCHECKing that
+ // `quota_manager_impl_task_runner_` runs on the current sequence before
+ // calling DCHECK_CALLED_ON_VALID_SEQUENCE(). New methods added to
+ // QuotaManagerProxy must follow the same pattern.
+ SEQUENCE_CHECKER(quota_manager_impl_sequence_checker_);
+
+ // Conceptually, this member is a base::WeakPtr<QuotaManagerImpl>. Like a
+ // WeakPtr, it becomes null after the target QuotaManagerImpl is destroyed.
+ //
+ // base::WeakPtr cannot be used here for two reasons:
+ // 1) QuotaManagerProxy can be deleted on any thread, whereas WeakPtrs must be
+ // invalidated on the same sequence where they are accessed. In this case,
+ // the WeakPtr would need to be accessed on the QuotaManagerImpl sequence,
+ // and then invalidated wherever the destructor happens to run.
+ // 2) QuotaManagerProxy instances must be created during the QuotaManagerImpl
+ // constructor, before the QuotaManagerImpl's WeakPtrFactory is
+ // constructed. This is because the easiest way to ensure that
+ // QuotaManagerImpl exposes its QuotaManagerProxy in a thread-safe manner
+ // is to have the QuotaManagerImpl's QuotaManagerProxy reference be const.
+ QuotaManagerImpl* quota_manager_impl_
+ GUARDED_BY_CONTEXT(quota_manager_impl_sequence_checker_);
+
+ // TaskRunner that accesses QuotaManagerImpl's sequence.
+ //
+ // This member is not GUARDED_BY_CONTEXT() and may be accessed from any
+ // thread. This is safe because the scoped_refptr is immutable (always points
+ // to the same object), and the object it points to is thread-safe.
+ const scoped_refptr<base::SequencedTaskRunner>
+ quota_manager_impl_task_runner_;
};
} // namespace storage
diff --git a/chromium/storage/browser/quota/quota_manager_unittest.cc b/chromium/storage/browser/quota/quota_manager_unittest.cc
index 434521fcd47..08458755356 100644
--- a/chromium/storage/browser/quota/quota_manager_unittest.cc
+++ b/chromium/storage/browser/quota/quota_manager_unittest.cc
@@ -13,6 +13,8 @@
#include <vector>
#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/containers/contains.h"
#include "base/containers/span.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
@@ -21,7 +23,6 @@
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/system/sys_info.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
@@ -29,11 +30,16 @@
#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
+#include "components/services/storage/public/mojom/quota_client.mojom.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+#include "storage/browser/quota/mojo_quota_client_wrapper.h"
#include "storage/browser/quota/quota_client_type.h"
#include "storage/browser/quota/quota_database.h"
#include "storage/browser/quota/quota_features.h"
-#include "storage/browser/quota/quota_manager.h"
+#include "storage/browser/quota/quota_manager_impl.h"
#include "storage/browser/quota/quota_manager_proxy.h"
+#include "storage/browser/quota/quota_override_handle.h"
#include "storage/browser/test/mock_quota_client.h"
#include "storage/browser/test/mock_special_storage_policy.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -58,6 +64,7 @@ const int64_t kAvailableSpaceForApp = 13377331U;
const int64_t kMustRemainAvailableForSystem = kAvailableSpaceForApp / 2;
const int64_t kDefaultPoolSize = 1000;
const int64_t kDefaultPerHostQuota = 200;
+const int64_t kGigabytes = QuotaManagerImpl::kMBytes * 1024;
// Returns a deterministic value for the amount of available disk space.
int64_t GetAvailableDiskSpaceForTest() {
@@ -78,68 +85,93 @@ url::Origin ToOrigin(const std::string& url) {
} // namespace
-class QuotaManagerTest : public testing::Test {
+class QuotaManagerImplTest : public testing::Test {
protected:
- using QuotaTableEntry = QuotaManager::QuotaTableEntry;
- using QuotaTableEntries = QuotaManager::QuotaTableEntries;
- using OriginInfoTableEntries = QuotaManager::OriginInfoTableEntries;
+ using QuotaTableEntry = QuotaManagerImpl::QuotaTableEntry;
+ using QuotaTableEntries = QuotaManagerImpl::QuotaTableEntries;
+ using OriginInfoTableEntries = QuotaManagerImpl::OriginInfoTableEntries;
public:
- QuotaManagerTest() : mock_time_counter_(0) {}
+ QuotaManagerImplTest() : mock_time_counter_(0) {}
void SetUp() override {
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
mock_special_storage_policy_ =
base::MakeRefCounted<MockSpecialStoragePolicy>();
- ResetQuotaManager(false /* is_incognito */);
+ ResetQuotaManagerImpl(false /* is_incognito */);
}
void TearDown() override {
// Make sure the quota manager cleans up correctly.
- quota_manager_ = nullptr;
+ quota_manager_impl_ = nullptr;
task_environment_.RunUntilIdle();
}
protected:
- void ResetQuotaManager(bool is_incognito) {
- quota_manager_ = base::MakeRefCounted<QuotaManager>(
+ void ResetQuotaManagerImpl(bool is_incognito) {
+ quota_manager_impl_ = base::MakeRefCounted<QuotaManagerImpl>(
is_incognito, data_dir_.GetPath(),
base::ThreadTaskRunnerHandle::Get().get(),
+ /*quota_change_callback=*/base::DoNothing(),
mock_special_storage_policy_.get(), GetQuotaSettingsFunc());
SetQuotaSettings(kDefaultPoolSize, kDefaultPerHostQuota,
is_incognito ? INT64_C(0) : kMustRemainAvailableForSystem);
// Don't (automatically) start the eviction for testing.
- quota_manager_->eviction_disabled_ = true;
+ quota_manager_impl_->eviction_disabled_ = true;
// Don't query the hard disk for remaining capacity.
- quota_manager_->get_volume_info_fn_ = &GetVolumeInfoForTests;
+ quota_manager_impl_->get_volume_info_fn_ = &GetVolumeInfoForTests;
additional_callback_count_ = 0;
}
- scoped_refptr<MockQuotaClient> CreateAndRegisterClient(
+ MockQuotaClient* CreateAndRegisterClient(
base::span<const MockOriginData> mock_data,
QuotaClientType client_type,
const std::vector<blink::mojom::StorageType> storage_types) {
- scoped_refptr<MockQuotaClient> client =
- base::MakeRefCounted<MockQuotaClient>(quota_manager_->proxy(),
- mock_data, client_type);
- quota_manager_->proxy()->RegisterClient(client, client_type, storage_types);
- return client;
+ auto mock_quota_client = std::make_unique<storage::MockQuotaClient>(
+ quota_manager_impl_->proxy(), mock_data, client_type);
+ MockQuotaClient* mock_quota_client_ptr = mock_quota_client.get();
+
+ mojo::PendingRemote<storage::mojom::QuotaClient> quota_client;
+ mojo::MakeSelfOwnedReceiver(std::move(mock_quota_client),
+ quota_client.InitWithNewPipeAndPassReceiver());
+ quota_manager_impl_->proxy()->RegisterClient(std::move(quota_client),
+ client_type, storage_types);
+ return mock_quota_client_ptr;
+ }
+
+ // TODO(crbug.com/1163009): Remove this method and replace all calls with
+ // CreateAndRegisterClient() after all QuotaClients
+ // have been mojofied
+ MockQuotaClient* CreateAndRegisterLegacyClient(
+ base::span<const MockOriginData> mock_data,
+ QuotaClientType client_type,
+ const std::vector<blink::mojom::StorageType> storage_types) {
+ auto mock_quota_client = std::make_unique<storage::MockQuotaClient>(
+ quota_manager_impl_->proxy(), mock_data, client_type);
+ MockQuotaClient* mock_quota_client_ptr = mock_quota_client.get();
+ legacy_clients_.push_back(std::move(mock_quota_client));
+
+ scoped_refptr<QuotaClient> legacy_client =
+ base::MakeRefCounted<MojoQuotaClientWrapper>(mock_quota_client_ptr);
+ quota_manager_impl_->proxy()->RegisterLegacyClient(
+ std::move(legacy_client), client_type, storage_types);
+ return mock_quota_client_ptr;
}
void GetUsageInfo() {
usage_info_.clear();
- quota_manager_->GetUsageInfo(base::BindOnce(
- &QuotaManagerTest::DidGetUsageInfo, weak_factory_.GetWeakPtr()));
+ quota_manager_impl_->GetUsageInfo(base::BindOnce(
+ &QuotaManagerImplTest::DidGetUsageInfo, weak_factory_.GetWeakPtr()));
}
void GetUsageAndQuotaForWebApps(const url::Origin& origin, StorageType type) {
quota_status_ = QuotaStatusCode::kUnknown;
usage_ = -1;
quota_ = -1;
- quota_manager_->GetUsageAndQuotaForWebApps(
+ quota_manager_impl_->GetUsageAndQuotaForWebApps(
origin, type,
- base::BindOnce(&QuotaManagerTest::DidGetUsageAndQuota,
+ base::BindOnce(&QuotaManagerImplTest::DidGetUsageAndQuota,
weak_factory_.GetWeakPtr()));
}
@@ -149,9 +181,9 @@ class QuotaManagerTest : public testing::Test {
usage_ = -1;
quota_ = -1;
usage_breakdown_ = nullptr;
- quota_manager_->GetUsageAndQuotaWithBreakdown(
+ quota_manager_impl_->GetUsageAndQuotaWithBreakdown(
origin, type,
- base::BindOnce(&QuotaManagerTest::DidGetUsageAndQuotaWithBreakdown,
+ base::BindOnce(&QuotaManagerImplTest::DidGetUsageAndQuotaWithBreakdown,
weak_factory_.GetWeakPtr()));
}
@@ -160,9 +192,9 @@ class QuotaManagerTest : public testing::Test {
quota_status_ = QuotaStatusCode::kUnknown;
usage_ = -1;
quota_ = -1;
- quota_manager_->GetUsageAndQuota(
+ quota_manager_impl_->GetUsageAndQuota(
origin, type,
- base::BindOnce(&QuotaManagerTest::DidGetUsageAndQuota,
+ base::BindOnce(&QuotaManagerImplTest::DidGetUsageAndQuota,
weak_factory_.GetWeakPtr()));
}
@@ -176,65 +208,73 @@ class QuotaManagerTest : public testing::Test {
(per_host_quota > 0) ? (per_host_quota - 1) : 0;
settings.must_remain_available = must_remain_available;
settings.refresh_interval = base::TimeDelta::Max();
- quota_manager_->SetQuotaSettings(settings);
+ quota_manager_impl_->SetQuotaSettings(settings);
+ }
+
+ using GetVolumeInfoFn =
+ std::tuple<int64_t, int64_t> (*)(const base::FilePath&);
+
+ void SetGetVolumeInfoFn(GetVolumeInfoFn fn) {
+ quota_manager_impl_->SetGetVolumeInfoFnForTesting(fn);
}
void GetPersistentHostQuota(const std::string& host) {
quota_status_ = QuotaStatusCode::kUnknown;
quota_ = -1;
- quota_manager_->GetPersistentHostQuota(
- host, base::BindOnce(&QuotaManagerTest::DidGetHostQuota,
+ quota_manager_impl_->GetPersistentHostQuota(
+ host, base::BindOnce(&QuotaManagerImplTest::DidGetHostQuota,
weak_factory_.GetWeakPtr()));
}
void SetPersistentHostQuota(const std::string& host, int64_t new_quota) {
quota_status_ = QuotaStatusCode::kUnknown;
quota_ = -1;
- quota_manager_->SetPersistentHostQuota(
+ quota_manager_impl_->SetPersistentHostQuota(
host, new_quota,
- base::BindOnce(&QuotaManagerTest::DidGetHostQuota,
+ base::BindOnce(&QuotaManagerImplTest::DidGetHostQuota,
weak_factory_.GetWeakPtr()));
}
void GetGlobalUsage(StorageType type) {
usage_ = -1;
unlimited_usage_ = -1;
- quota_manager_->GetGlobalUsage(
- type, base::BindOnce(&QuotaManagerTest::DidGetGlobalUsage,
+ quota_manager_impl_->GetGlobalUsage(
+ type, base::BindOnce(&QuotaManagerImplTest::DidGetGlobalUsage,
weak_factory_.GetWeakPtr()));
}
void GetHostUsageWithBreakdown(const std::string& host, StorageType type) {
usage_ = -1;
- quota_manager_->GetHostUsageWithBreakdown(
+ quota_manager_impl_->GetHostUsageWithBreakdown(
host, type,
- base::BindOnce(&QuotaManagerTest::DidGetHostUsageBreakdown,
+ base::BindOnce(&QuotaManagerImplTest::DidGetHostUsageBreakdown,
weak_factory_.GetWeakPtr()));
}
void RunAdditionalUsageAndQuotaTask(const url::Origin& origin,
StorageType type) {
- quota_manager_->GetUsageAndQuota(
+ quota_manager_impl_->GetUsageAndQuota(
origin, type,
- base::BindOnce(&QuotaManagerTest::DidGetUsageAndQuotaAdditional,
+ base::BindOnce(&QuotaManagerImplTest::DidGetUsageAndQuotaAdditional,
weak_factory_.GetWeakPtr()));
}
- void DeleteClientOriginData(QuotaClient* client,
+ void DeleteClientOriginData(mojom::QuotaClient* client,
const url::Origin& origin,
StorageType type) {
DCHECK(client);
quota_status_ = QuotaStatusCode::kUnknown;
- client->DeleteOriginData(origin, type,
- base::BindOnce(&QuotaManagerTest::StatusCallback,
- weak_factory_.GetWeakPtr()));
+ client->DeleteOriginData(
+ origin, type,
+ base::BindOnce(&QuotaManagerImplTest::StatusCallback,
+ weak_factory_.GetWeakPtr()));
}
void EvictOriginData(const url::Origin& origin, StorageType type) {
quota_status_ = QuotaStatusCode::kUnknown;
- quota_manager_->EvictOriginData(
+ quota_manager_impl_->EvictOriginData(
origin, type,
- base::BindOnce(&QuotaManagerTest::StatusCallback,
+ base::BindOnce(&QuotaManagerImplTest::StatusCallback,
weak_factory_.GetWeakPtr()));
}
@@ -242,9 +282,9 @@ class QuotaManagerTest : public testing::Test {
StorageType type,
QuotaClientTypes quota_client_types) {
quota_status_ = QuotaStatusCode::kUnknown;
- quota_manager_->DeleteOriginData(
+ quota_manager_impl_->DeleteOriginData(
origin, type, std::move(quota_client_types),
- base::BindOnce(&QuotaManagerTest::StatusCallback,
+ base::BindOnce(&QuotaManagerImplTest::StatusCallback,
weak_factory_.GetWeakPtr()));
}
@@ -252,17 +292,18 @@ class QuotaManagerTest : public testing::Test {
StorageType type,
QuotaClientTypes quota_client_types) {
quota_status_ = QuotaStatusCode::kUnknown;
- quota_manager_->DeleteHostData(
+ quota_manager_impl_->DeleteHostData(
host, type, std::move(quota_client_types),
- base::BindOnce(&QuotaManagerTest::StatusCallback,
+ base::BindOnce(&QuotaManagerImplTest::StatusCallback,
weak_factory_.GetWeakPtr()));
}
void GetStorageCapacity() {
available_space_ = -1;
total_space_ = -1;
- quota_manager_->GetStorageCapacity(base::BindOnce(
- &QuotaManagerTest::DidGetStorageCapacity, weak_factory_.GetWeakPtr()));
+ quota_manager_impl_->GetStorageCapacity(
+ base::BindOnce(&QuotaManagerImplTest::DidGetStorageCapacity,
+ weak_factory_.GetWeakPtr()));
}
void GetEvictionRoundInfo() {
@@ -271,40 +312,40 @@ class QuotaManagerTest : public testing::Test {
available_space_ = -1;
total_space_ = -1;
usage_ = -1;
- quota_manager_->GetEvictionRoundInfo(
- base::BindOnce(&QuotaManagerTest::DidGetEvictionRoundInfo,
+ quota_manager_impl_->GetEvictionRoundInfo(
+ base::BindOnce(&QuotaManagerImplTest::DidGetEvictionRoundInfo,
weak_factory_.GetWeakPtr()));
}
std::set<url::Origin> GetCachedOrigins(StorageType type) {
- return quota_manager_->GetCachedOrigins(type);
+ return quota_manager_impl_->GetCachedOrigins(type);
}
void NotifyStorageAccessed(const url::Origin& origin, StorageType type) {
- quota_manager_->NotifyStorageAccessedInternal(origin, type,
- IncrementMockTime());
+ quota_manager_impl_->NotifyStorageAccessed(origin, type,
+ IncrementMockTime());
}
void DeleteOriginFromDatabase(const url::Origin& origin, StorageType type) {
- quota_manager_->DeleteOriginFromDatabase(origin, type, false);
+ quota_manager_impl_->DeleteOriginFromDatabase(origin, type, false);
}
void GetEvictionOrigin(StorageType type) {
eviction_origin_.reset();
// The quota manager's default eviction policy is to use an LRU eviction
// policy.
- quota_manager_->GetEvictionOrigin(
+ quota_manager_impl_->GetEvictionOrigin(
type, 0,
- base::BindOnce(&QuotaManagerTest::DidGetEvictionOrigin,
+ base::BindOnce(&QuotaManagerImplTest::DidGetEvictionOrigin,
weak_factory_.GetWeakPtr()));
}
void NotifyOriginInUse(const url::Origin& origin) {
- quota_manager_->NotifyOriginInUse(origin);
+ quota_manager_impl_->NotifyOriginInUse(origin);
}
void NotifyOriginNoLongerInUse(const url::Origin& origin) {
- quota_manager_->NotifyOriginNoLongerInUse(origin);
+ quota_manager_impl_->NotifyOriginNoLongerInUse(origin);
}
void GetOriginsModifiedBetween(StorageType type,
@@ -312,22 +353,23 @@ class QuotaManagerTest : public testing::Test {
base::Time end) {
modified_origins_.clear();
modified_origins_type_ = StorageType::kUnknown;
- quota_manager_->GetOriginsModifiedBetween(
+ quota_manager_impl_->GetOriginsModifiedBetween(
type, begin, end,
- base::BindOnce(&QuotaManagerTest::DidGetModifiedOrigins,
+ base::BindOnce(&QuotaManagerImplTest::DidGetModifiedOrigins,
weak_factory_.GetWeakPtr()));
}
void DumpQuotaTable() {
quota_entries_.clear();
- quota_manager_->DumpQuotaTable(base::BindOnce(
- &QuotaManagerTest::DidDumpQuotaTable, weak_factory_.GetWeakPtr()));
+ quota_manager_impl_->DumpQuotaTable(base::BindOnce(
+ &QuotaManagerImplTest::DidDumpQuotaTable, weak_factory_.GetWeakPtr()));
}
void DumpOriginInfoTable() {
origin_info_entries_.clear();
- quota_manager_->DumpOriginInfoTable(base::BindOnce(
- &QuotaManagerTest::DidDumpOriginInfoTable, weak_factory_.GetWeakPtr()));
+ quota_manager_impl_->DumpOriginInfoTable(
+ base::BindOnce(&QuotaManagerImplTest::DidDumpOriginInfoTable,
+ weak_factory_.GetWeakPtr()));
}
void DidGetUsageInfo(UsageInfoEntries entries) {
@@ -423,13 +465,14 @@ class QuotaManagerTest : public testing::Test {
void SetStoragePressureCallback(
base::RepeatingCallback<void(url::Origin)> callback) {
- quota_manager_->SetStoragePressureCallback(std::move(callback));
+ quota_manager_impl_->SetStoragePressureCallback(std::move(callback));
}
void MaybeRunStoragePressureCallback(const url::Origin& origin,
int64_t total,
int64_t available) {
- quota_manager_->MaybeRunStoragePressureCallback(origin, total, available);
+ quota_manager_impl_->MaybeRunStoragePressureCallback(origin, total,
+ available);
}
void set_additional_callback_count(int c) { additional_callback_count_ = c; }
@@ -440,9 +483,11 @@ class QuotaManagerTest : public testing::Test {
++additional_callback_count_;
}
- QuotaManager* quota_manager() const { return quota_manager_.get(); }
- void set_quota_manager(QuotaManager* quota_manager) {
- quota_manager_ = quota_manager;
+ QuotaManagerImpl* quota_manager_impl() const {
+ return quota_manager_impl_.get();
+ }
+ void set_quota_manager_impl(QuotaManagerImpl* quota_manager_impl) {
+ quota_manager_impl_ = quota_manager_impl;
}
MockSpecialStoragePolicy* mock_special_storage_policy() const {
@@ -450,7 +495,11 @@ class QuotaManagerTest : public testing::Test {
}
std::unique_ptr<QuotaOverrideHandle> GetQuotaOverrideHandle() {
- return quota_manager_->proxy()->GetQuotaOverrideHandle();
+ return quota_manager_impl_->proxy()->GetQuotaOverrideHandle();
+ }
+
+ void SetQuotaChangeCallback(base::RepeatingClosure cb) {
+ quota_manager_impl_->SetQuotaChangeCallbackForTesting(std::move(cb));
}
QuotaStatusCode status() const { return quota_status_; }
@@ -496,7 +545,7 @@ class QuotaManagerTest : public testing::Test {
base::ScopedTempDir data_dir_;
- scoped_refptr<QuotaManager> quota_manager_;
+ scoped_refptr<QuotaManagerImpl> quota_manager_impl_;
scoped_refptr<MockSpecialStoragePolicy> mock_special_storage_policy_;
QuotaStatusCode quota_status_;
@@ -519,12 +568,16 @@ class QuotaManagerTest : public testing::Test {
int mock_time_counter_;
- base::WeakPtrFactory<QuotaManagerTest> weak_factory_{this};
+ // TODO(crbug.com/1163009): Remove this member after all QuotaClients have
+ // been mojofied.
+ std::vector<std::unique_ptr<MockQuotaClient>> legacy_clients_;
+
+ base::WeakPtrFactory<QuotaManagerImplTest> weak_factory_{this};
- DISALLOW_COPY_AND_ASSIGN(QuotaManagerTest);
+ DISALLOW_COPY_AND_ASSIGN(QuotaManagerImplTest);
};
-TEST_F(QuotaManagerTest, GetUsageInfo) {
+TEST_F(QuotaManagerImplTest, GetUsageInfo) {
static const MockOriginData kData1[] = {
{ "http://foo.com/", kTemp, 10 },
{ "http://foo.com:8080/", kTemp, 15 },
@@ -537,12 +590,12 @@ TEST_F(QuotaManagerTest, GetUsageInfo) {
{ "http://bar.com/", kPerm, 40 },
{ "http://example.com/", kPerm, 40 },
};
- CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
- CreateAndRegisterClient(kData2, QuotaClientType::kDatabase,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem,
+ {blink::mojom::StorageType::kTemporary,
+ blink::mojom::StorageType::kPersistent});
+ CreateAndRegisterLegacyClient(kData2, QuotaClientType::kDatabase,
+ {blink::mojom::StorageType::kTemporary,
+ blink::mojom::StorageType::kPersistent});
GetUsageInfo();
task_environment_.RunUntilIdle();
@@ -564,7 +617,7 @@ TEST_F(QuotaManagerTest, GetUsageInfo) {
}
}
-TEST_F(QuotaManagerTest, GetUsageAndQuota_Simple) {
+TEST_F(QuotaManagerImplTest, GetUsageAndQuota_Simple) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kTemp, 10 },
{ "http://foo.com/", kPerm, 80 },
@@ -593,7 +646,7 @@ TEST_F(QuotaManagerTest, GetUsageAndQuota_Simple) {
EXPECT_EQ(quota_returned_for_foo, quota());
}
-TEST_F(QuotaManagerTest, GetUsage_NoClient) {
+TEST_F(QuotaManagerImplTest, GetUsage_NoClient) {
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp);
task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
@@ -623,11 +676,11 @@ TEST_F(QuotaManagerTest, GetUsage_NoClient) {
EXPECT_EQ(0, unlimited_usage());
}
-TEST_F(QuotaManagerTest, GetUsage_EmptyClient) {
- CreateAndRegisterClient(base::span<MockOriginData>(),
- QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+TEST_F(QuotaManagerImplTest, GetUsage_EmptyClient) {
+ CreateAndRegisterLegacyClient(base::span<MockOriginData>(),
+ QuotaClientType::kFileSystem,
+ {blink::mojom::StorageType::kTemporary,
+ blink::mojom::StorageType::kPersistent});
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp);
task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
@@ -657,7 +710,7 @@ TEST_F(QuotaManagerTest, GetUsage_EmptyClient) {
EXPECT_EQ(0, unlimited_usage());
}
-TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_MultiOrigins) {
+TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_MultiOrigins) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kTemp, 10 },
{ "http://foo.com:8080/", kTemp, 20 },
@@ -691,7 +744,7 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_MultiOrigins) {
EXPECT_EQ(kPerHostQuota, quota());
}
-TEST_F(QuotaManagerTest, GetUsage_MultipleClients) {
+TEST_F(QuotaManagerImplTest, GetUsage_MultipleClients) {
static const MockOriginData kData1[] = {
{ "http://foo.com/", kTemp, 1 },
{ "http://bar.com/", kTemp, 2 },
@@ -708,9 +761,9 @@ TEST_F(QuotaManagerTest, GetUsage_MultipleClients) {
CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem,
{blink::mojom::StorageType::kTemporary,
blink::mojom::StorageType::kPersistent});
- CreateAndRegisterClient(kData2, QuotaClientType::kDatabase,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ CreateAndRegisterLegacyClient(kData2, QuotaClientType::kDatabase,
+ {blink::mojom::StorageType::kTemporary,
+ blink::mojom::StorageType::kPersistent});
const int64_t kPoolSize = GetAvailableDiskSpaceForTest();
const int64_t kPerHostQuota = kPoolSize / 5;
@@ -753,7 +806,7 @@ TEST_F(QuotaManagerTest, GetUsage_MultipleClients) {
EXPECT_EQ(8, unlimited_usage());
}
-TEST_F(QuotaManagerTest, GetUsageWithBreakdown_Simple) {
+TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_Simple) {
blink::mojom::UsageBreakdown usage_breakdown_expected =
blink::mojom::UsageBreakdown();
static const MockOriginData kData1[] = {
@@ -765,9 +818,9 @@ TEST_F(QuotaManagerTest, GetUsageWithBreakdown_Simple) {
static const MockOriginData kData3[] = {
{"http://foo.com/", kTemp, 8},
};
- CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem,
+ {blink::mojom::StorageType::kTemporary,
+ blink::mojom::StorageType::kPersistent});
CreateAndRegisterClient(kData2, QuotaClientType::kDatabase,
{blink::mojom::StorageType::kTemporary});
CreateAndRegisterClient(kData3, QuotaClientType::kAppcache,
@@ -801,7 +854,7 @@ TEST_F(QuotaManagerTest, GetUsageWithBreakdown_Simple) {
EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown()));
}
-TEST_F(QuotaManagerTest, GetUsageWithBreakdown_NoClient) {
+TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_NoClient) {
blink::mojom::UsageBreakdown usage_breakdown_expected =
blink::mojom::UsageBreakdown();
@@ -828,7 +881,7 @@ TEST_F(QuotaManagerTest, GetUsageWithBreakdown_NoClient) {
EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown()));
}
-TEST_F(QuotaManagerTest, GetUsageWithBreakdown_MultiOrigins) {
+TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_MultiOrigins) {
blink::mojom::UsageBreakdown usage_breakdown_expected =
blink::mojom::UsageBreakdown();
static const MockOriginData kData[] = {
@@ -855,7 +908,7 @@ TEST_F(QuotaManagerTest, GetUsageWithBreakdown_MultiOrigins) {
EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown()));
}
-TEST_F(QuotaManagerTest, GetUsageWithBreakdown_MultipleClients) {
+TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_MultipleClients) {
blink::mojom::UsageBreakdown usage_breakdown_expected =
blink::mojom::UsageBreakdown();
static const MockOriginData kData1[] = {
@@ -870,9 +923,9 @@ TEST_F(QuotaManagerTest, GetUsageWithBreakdown_MultipleClients) {
{"http://unlimited/", kTemp, 512},
};
mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/"));
- CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem,
+ {blink::mojom::StorageType::kTemporary,
+ blink::mojom::StorageType::kPersistent});
CreateAndRegisterClient(kData2, QuotaClientType::kDatabase,
{blink::mojom::StorageType::kTemporary,
blink::mojom::StorageType::kPersistent});
@@ -910,12 +963,12 @@ TEST_F(QuotaManagerTest, GetUsageWithBreakdown_MultipleClients) {
EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown()));
}
-void QuotaManagerTest::GetUsage_WithModifyTestBody(const StorageType type) {
+void QuotaManagerImplTest::GetUsage_WithModifyTestBody(const StorageType type) {
const MockOriginData data[] = {
{ "http://foo.com/", type, 10 },
{ "http://foo.com:1/", type, 20 },
};
- scoped_refptr<MockQuotaClient> client =
+ MockQuotaClient* client =
CreateAndRegisterClient(data, QuotaClientType::kFileSystem, {type});
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), type);
@@ -945,11 +998,11 @@ void QuotaManagerTest::GetUsage_WithModifyTestBody(const StorageType type) {
EXPECT_EQ(0, unlimited_usage());
}
-TEST_F(QuotaManagerTest, GetTemporaryUsage_WithModify) {
+TEST_F(QuotaManagerImplTest, GetTemporaryUsage_WithModify) {
GetUsage_WithModifyTestBody(kTemp);
}
-TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_WithAdditionalTasks) {
+TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_WithAdditionalTasks) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kTemp, 10 },
{ "http://foo.com:8080/", kTemp, 20 },
@@ -983,7 +1036,7 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_WithAdditionalTasks) {
EXPECT_EQ(2, additional_callback_count());
}
-TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_NukeManager) {
+TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_NukeManager) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kTemp, 10 },
{ "http://foo.com:8080/", kTemp, 20 },
@@ -1006,12 +1059,42 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_NukeManager) {
DeleteOriginData(ToOrigin("http://bar.com/"), kTemp, AllQuotaClientTypes());
// Nuke before waiting for callbacks.
- set_quota_manager(nullptr);
+ set_quota_manager_impl(nullptr);
task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kErrorAbort, status());
}
-TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Overbudget) {
+// TODO(crbug.com/1163009): Remove this test after all QuotaClients have been
+// mojofied
+TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_NukeManager_Legacy) {
+ static const MockOriginData kData[] = {
+ {"http://foo.com/", kTemp, 10},
+ {"http://foo.com:8080/", kTemp, 20},
+ {"http://bar.com/", kTemp, 13},
+ {"http://foo.com/", kPerm, 40},
+ };
+ CreateAndRegisterLegacyClient(kData, QuotaClientType::kFileSystem,
+ {blink::mojom::StorageType::kTemporary,
+ blink::mojom::StorageType::kPersistent});
+ const int kPoolSize = 100;
+ const int kPerHostQuota = 20;
+ SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem);
+
+ set_additional_callback_count(0);
+ GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp);
+ RunAdditionalUsageAndQuotaTask(ToOrigin("http://foo.com/"), kTemp);
+ RunAdditionalUsageAndQuotaTask(ToOrigin("http://bar.com/"), kTemp);
+
+ DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, AllQuotaClientTypes());
+ DeleteOriginData(ToOrigin("http://bar.com/"), kTemp, AllQuotaClientTypes());
+
+ // Nuke before waiting for callbacks.
+ set_quota_manager_impl(nullptr);
+ task_environment_.RunUntilIdle();
+ EXPECT_EQ(QuotaStatusCode::kErrorAbort, status());
+}
+
+TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_Overbudget) {
static const MockOriginData kData[] = {
{ "http://usage1/", kTemp, 1 },
{ "http://usage10/", kTemp, 10 },
@@ -1049,7 +1132,7 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Overbudget) {
EXPECT_EQ(kPerHostQuota, quota()); // should be clamped to the nominal quota
}
-TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Unlimited) {
+TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_Unlimited) {
static const MockOriginData kData[] = {
{ "http://usage10/", kTemp, 10 },
{ "http://usage50/", kTemp, 50 },
@@ -1090,7 +1173,7 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Unlimited) {
task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(0, usage());
- EXPECT_EQ(QuotaManager::kNoLimit, quota());
+ EXPECT_EQ(QuotaManagerImpl::kNoLimit, quota());
// Test when overbugdet.
const int kPerHostQuotaFor100 = 20;
@@ -1118,7 +1201,7 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Unlimited) {
task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(0, usage());
- EXPECT_EQ(QuotaManager::kNoLimit, quota());
+ EXPECT_EQ(QuotaManagerImpl::kNoLimit, quota());
// Revoke the unlimited rights and make sure the change is noticed.
mock_special_storage_policy()->Reset();
@@ -1154,29 +1237,29 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Unlimited) {
EXPECT_EQ(kPerHostQuotaFor100, quota());
}
-TEST_F(QuotaManagerTest, OriginInUse) {
+TEST_F(QuotaManagerImplTest, OriginInUse) {
const url::Origin kFooOrigin = ToOrigin("http://foo.com/");
const url::Origin kBarOrigin = ToOrigin("http://bar.com/");
- EXPECT_FALSE(quota_manager()->IsOriginInUse(kFooOrigin));
- quota_manager()->NotifyOriginInUse(kFooOrigin); // count of 1
- EXPECT_TRUE(quota_manager()->IsOriginInUse(kFooOrigin));
- quota_manager()->NotifyOriginInUse(kFooOrigin); // count of 2
- EXPECT_TRUE(quota_manager()->IsOriginInUse(kFooOrigin));
- quota_manager()->NotifyOriginNoLongerInUse(kFooOrigin); // count of 1
- EXPECT_TRUE(quota_manager()->IsOriginInUse(kFooOrigin));
-
- EXPECT_FALSE(quota_manager()->IsOriginInUse(kBarOrigin));
- quota_manager()->NotifyOriginInUse(kBarOrigin);
- EXPECT_TRUE(quota_manager()->IsOriginInUse(kBarOrigin));
- quota_manager()->NotifyOriginNoLongerInUse(kBarOrigin);
- EXPECT_FALSE(quota_manager()->IsOriginInUse(kBarOrigin));
-
- quota_manager()->NotifyOriginNoLongerInUse(kFooOrigin);
- EXPECT_FALSE(quota_manager()->IsOriginInUse(kFooOrigin));
+ EXPECT_FALSE(quota_manager_impl()->IsOriginInUse(kFooOrigin));
+ quota_manager_impl()->NotifyOriginInUse(kFooOrigin); // count of 1
+ EXPECT_TRUE(quota_manager_impl()->IsOriginInUse(kFooOrigin));
+ quota_manager_impl()->NotifyOriginInUse(kFooOrigin); // count of 2
+ EXPECT_TRUE(quota_manager_impl()->IsOriginInUse(kFooOrigin));
+ quota_manager_impl()->NotifyOriginNoLongerInUse(kFooOrigin); // count of 1
+ EXPECT_TRUE(quota_manager_impl()->IsOriginInUse(kFooOrigin));
+
+ EXPECT_FALSE(quota_manager_impl()->IsOriginInUse(kBarOrigin));
+ quota_manager_impl()->NotifyOriginInUse(kBarOrigin);
+ EXPECT_TRUE(quota_manager_impl()->IsOriginInUse(kBarOrigin));
+ quota_manager_impl()->NotifyOriginNoLongerInUse(kBarOrigin);
+ EXPECT_FALSE(quota_manager_impl()->IsOriginInUse(kBarOrigin));
+
+ quota_manager_impl()->NotifyOriginNoLongerInUse(kFooOrigin);
+ EXPECT_FALSE(quota_manager_impl()->IsOriginInUse(kFooOrigin));
}
-TEST_F(QuotaManagerTest, GetAndSetPerststentHostQuota) {
+TEST_F(QuotaManagerImplTest, GetAndSetPerststentHostQuota) {
CreateAndRegisterClient(base::span<MockOriginData>(),
QuotaClientType::kFileSystem,
{blink::mojom::StorageType::kTemporary,
@@ -1193,20 +1276,21 @@ TEST_F(QuotaManagerTest, GetAndSetPerststentHostQuota) {
GetPersistentHostQuota("foo.com");
SetPersistentHostQuota("foo.com", 200);
GetPersistentHostQuota("foo.com");
- SetPersistentHostQuota("foo.com", QuotaManager::kPerHostPersistentQuotaLimit);
+ SetPersistentHostQuota("foo.com",
+ QuotaManagerImpl::kPerHostPersistentQuotaLimit);
GetPersistentHostQuota("foo.com");
task_environment_.RunUntilIdle();
- EXPECT_EQ(QuotaManager::kPerHostPersistentQuotaLimit, quota());
+ EXPECT_EQ(QuotaManagerImpl::kPerHostPersistentQuotaLimit, quota());
// Persistent quota should be capped at the per-host quota limit.
SetPersistentHostQuota("foo.com",
- QuotaManager::kPerHostPersistentQuotaLimit + 100);
+ QuotaManagerImpl::kPerHostPersistentQuotaLimit + 100);
GetPersistentHostQuota("foo.com");
task_environment_.RunUntilIdle();
- EXPECT_EQ(QuotaManager::kPerHostPersistentQuotaLimit, quota());
+ EXPECT_EQ(QuotaManagerImpl::kPerHostPersistentQuotaLimit, quota());
}
-TEST_F(QuotaManagerTest, GetAndSetPersistentUsageAndQuota) {
+TEST_F(QuotaManagerImplTest, GetAndSetPersistentUsageAndQuota) {
GetStorageCapacity();
CreateAndRegisterClient(base::span<MockOriginData>(),
QuotaClientType::kFileSystem,
@@ -1237,10 +1321,10 @@ TEST_F(QuotaManagerTest, GetAndSetPersistentUsageAndQuota) {
GetUsageAndQuotaForStorageClient(ToOrigin("http://unlimited/"), kPerm);
task_environment_.RunUntilIdle();
EXPECT_EQ(0, usage());
- EXPECT_EQ(QuotaManager::kNoLimit, quota());
+ EXPECT_EQ(QuotaManagerImpl::kNoLimit, quota());
}
-TEST_F(QuotaManagerTest, GetQuotaLowAvailableDiskSpace) {
+TEST_F(QuotaManagerImplTest, GetQuotaLowAvailableDiskSpace) {
static const MockOriginData kData[] = {
{"http://foo.com/", kTemp, 100000},
{"http://unlimited/", kTemp, 4000000},
@@ -1253,9 +1337,9 @@ TEST_F(QuotaManagerTest, GetQuotaLowAvailableDiskSpace) {
const int kPerHostQuota = kPoolSize / 5;
// In here, we expect the low available space logic branch
- // to be ignored. Doing so should have QuotaManager return the same per-host
- // quota as what is set in QuotaSettings, despite being in a state of low
- // available space.
+ // to be ignored. Doing so should have QuotaManagerImpl return the same
+ // per-host quota as what is set in QuotaSettings, despite being in a state of
+ // low available space.
const int kMustRemainAvailable =
static_cast<int>(GetAvailableDiskSpaceForTest() - 65536);
SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailable);
@@ -1267,7 +1351,7 @@ TEST_F(QuotaManagerTest, GetQuotaLowAvailableDiskSpace) {
EXPECT_EQ(kPerHostQuota, quota());
}
-TEST_F(QuotaManagerTest, GetSyncableQuota) {
+TEST_F(QuotaManagerImplTest, GetSyncableQuota) {
CreateAndRegisterClient(base::span<MockOriginData>(),
QuotaClientType::kFileSystem,
{blink::mojom::StorageType::kTemporary,
@@ -1276,10 +1360,10 @@ TEST_F(QuotaManagerTest, GetSyncableQuota) {
// Pre-condition check: available disk space (for testing) is less than
// the default quota for syncable storage.
EXPECT_LE(kAvailableSpaceForApp,
- QuotaManager::kSyncableStorageDefaultHostQuota);
+ QuotaManagerImpl::kSyncableStorageDefaultHostQuota);
// The quota manager should return
- // QuotaManager::kSyncableStorageDefaultHostQuota as syncable quota,
+ // QuotaManagerImpl::kSyncableStorageDefaultHostQuota as syncable quota,
// despite available space being less than the desired quota. Only
// origins with unlimited storage, which is never the case for syncable
// storage, shall have their quota calculation take into account the amount of
@@ -1289,10 +1373,10 @@ TEST_F(QuotaManagerTest, GetSyncableQuota) {
task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(0, usage());
- EXPECT_EQ(QuotaManager::kSyncableStorageDefaultHostQuota, quota());
+ EXPECT_EQ(QuotaManagerImpl::kSyncableStorageDefaultHostQuota, quota());
}
-TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_MultiOrigins) {
+TEST_F(QuotaManagerImplTest, GetPersistentUsageAndQuota_MultiOrigins) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kPerm, 10 },
{ "http://foo.com:8080/", kPerm, 20 },
@@ -1315,11 +1399,11 @@ TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_MultiOrigins) {
EXPECT_EQ(100, quota());
}
-TEST_F(QuotaManagerTest, GetPersistentUsage_WithModify) {
+TEST_F(QuotaManagerImplTest, GetPersistentUsage_WithModify) {
GetUsage_WithModifyTestBody(kPerm);
}
-TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_WithAdditionalTasks) {
+TEST_F(QuotaManagerImplTest, GetPersistentUsageAndQuota_WithAdditionalTasks) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kPerm, 10 },
{ "http://foo.com:8080/", kPerm, 20 },
@@ -1349,7 +1433,40 @@ TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_WithAdditionalTasks) {
EXPECT_EQ(2, additional_callback_count());
}
-TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_NukeManager) {
+// TODO(crbug.com/1163009): Remove this test after all QuotaClients have been
+// mojofied
+TEST_F(QuotaManagerImplTest,
+ GetPersistentUsageAndQuota_WithAdditionalTasks_Legacy) {
+ static const MockOriginData kData[] = {
+ {"http://foo.com/", kPerm, 10},
+ {"http://foo.com:8080/", kPerm, 20},
+ {"http://bar.com/", kPerm, 13},
+ {"http://foo.com/", kTemp, 40},
+ };
+ CreateAndRegisterLegacyClient(kData, QuotaClientType::kFileSystem,
+ {blink::mojom::StorageType::kTemporary,
+ blink::mojom::StorageType::kPersistent});
+ SetPersistentHostQuota("foo.com", 100);
+
+ GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm);
+ GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm);
+ GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm);
+ task_environment_.RunUntilIdle();
+ EXPECT_EQ(QuotaStatusCode::kOk, status());
+ EXPECT_EQ(10 + 20, usage());
+ EXPECT_EQ(100, quota());
+
+ set_additional_callback_count(0);
+ RunAdditionalUsageAndQuotaTask(ToOrigin("http://foo.com/"), kPerm);
+ GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm);
+ RunAdditionalUsageAndQuotaTask(ToOrigin("http://bar.com/"), kPerm);
+ task_environment_.RunUntilIdle();
+ EXPECT_EQ(QuotaStatusCode::kOk, status());
+ EXPECT_EQ(10 + 20, usage());
+ EXPECT_EQ(2, additional_callback_count());
+}
+
+TEST_F(QuotaManagerImplTest, GetPersistentUsageAndQuota_NukeManager) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kPerm, 10 },
{ "http://foo.com:8080/", kPerm, 20 },
@@ -1367,12 +1484,37 @@ TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_NukeManager) {
RunAdditionalUsageAndQuotaTask(ToOrigin("http://bar.com/"), kPerm);
// Nuke before waiting for callbacks.
- set_quota_manager(nullptr);
+ set_quota_manager_impl(nullptr);
task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kErrorAbort, status());
}
-TEST_F(QuotaManagerTest, GetUsage_Simple) {
+// TODO(crbug.com/1163009): Remove this test after all QuotaClients have been
+// mojofied
+TEST_F(QuotaManagerImplTest, GetPersistentUsageAndQuota_NukeManager_Legacy) {
+ static const MockOriginData kData[] = {
+ {"http://foo.com/", kPerm, 10},
+ {"http://foo.com:8080/", kPerm, 20},
+ {"http://bar.com/", kPerm, 13},
+ {"http://foo.com/", kTemp, 40},
+ };
+ CreateAndRegisterLegacyClient(kData, QuotaClientType::kFileSystem,
+ {blink::mojom::StorageType::kTemporary,
+ blink::mojom::StorageType::kPersistent});
+ SetPersistentHostQuota("foo.com", 100);
+
+ set_additional_callback_count(0);
+ GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm);
+ RunAdditionalUsageAndQuotaTask(ToOrigin("http://foo.com/"), kPerm);
+ RunAdditionalUsageAndQuotaTask(ToOrigin("http://bar.com/"), kPerm);
+
+ // Nuke before waiting for callbacks.
+ set_quota_manager_impl(nullptr);
+ task_environment_.RunUntilIdle();
+ EXPECT_EQ(QuotaStatusCode::kErrorAbort, status());
+}
+
+TEST_F(QuotaManagerImplTest, GetUsage_Simple) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kPerm, 1 },
{ "http://foo.com:1/", kPerm, 20 },
@@ -1405,7 +1547,7 @@ TEST_F(QuotaManagerTest, GetUsage_Simple) {
EXPECT_EQ(usage(), 4000 + 50000);
}
-TEST_F(QuotaManagerTest, GetUsage_WithModification) {
+TEST_F(QuotaManagerImplTest, GetUsage_WithModification) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kPerm, 1 },
{ "http://foo.com:1/", kPerm, 20 },
@@ -1416,7 +1558,7 @@ TEST_F(QuotaManagerTest, GetUsage_WithModification) {
{ "http://foo.com/", kTemp, 7000000 },
};
- scoped_refptr<MockQuotaClient> client =
+ MockQuotaClient* client =
CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
{blink::mojom::StorageType::kTemporary,
blink::mojom::StorageType::kPersistent});
@@ -1456,14 +1598,14 @@ TEST_F(QuotaManagerTest, GetUsage_WithModification) {
EXPECT_EQ(usage(), 4000 + 50000 + 900000000);
}
-TEST_F(QuotaManagerTest, GetUsage_WithDeleteOrigin) {
+TEST_F(QuotaManagerImplTest, GetUsage_WithDeleteOrigin) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kTemp, 1 },
{ "http://foo.com:1/", kTemp, 20 },
{ "http://foo.com/", kPerm, 300 },
{ "http://bar.com/", kTemp, 4000 },
};
- scoped_refptr<MockQuotaClient> client =
+ MockQuotaClient* client =
CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
{blink::mojom::StorageType::kTemporary,
blink::mojom::StorageType::kPersistent});
@@ -1480,7 +1622,7 @@ TEST_F(QuotaManagerTest, GetUsage_WithDeleteOrigin) {
task_environment_.RunUntilIdle();
int64_t predelete_host_pers = usage();
- DeleteClientOriginData(client.get(), ToOrigin("http://foo.com/"), kTemp);
+ DeleteClientOriginData(client, ToOrigin("http://foo.com/"), kTemp);
task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
@@ -1497,14 +1639,14 @@ TEST_F(QuotaManagerTest, GetUsage_WithDeleteOrigin) {
EXPECT_EQ(predelete_host_pers, usage());
}
-TEST_F(QuotaManagerTest, GetStorageCapacity) {
+TEST_F(QuotaManagerImplTest, GetStorageCapacity) {
GetStorageCapacity();
task_environment_.RunUntilIdle();
EXPECT_LE(0, total_space());
EXPECT_LE(0, available_space());
}
-TEST_F(QuotaManagerTest, EvictOriginData) {
+TEST_F(QuotaManagerImplTest, EvictOriginData) {
static const MockOriginData kData1[] = {
{ "http://foo.com/", kTemp, 1 },
{ "http://foo.com:1/", kTemp, 20 },
@@ -1518,9 +1660,9 @@ TEST_F(QuotaManagerTest, EvictOriginData) {
{ "https://foo.com/", kTemp, 80 },
{ "http://bar.com/", kTemp, 9 },
};
- CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem,
+ {blink::mojom::StorageType::kTemporary,
+ blink::mojom::StorageType::kPersistent});
CreateAndRegisterClient(kData2, QuotaClientType::kDatabase,
{blink::mojom::StorageType::kTemporary,
blink::mojom::StorageType::kPersistent});
@@ -1538,12 +1680,12 @@ TEST_F(QuotaManagerTest, EvictOriginData) {
int64_t predelete_host_pers = usage();
for (const MockOriginData& data : kData1) {
- quota_manager()->NotifyStorageAccessed(
- url::Origin::Create(GURL(data.origin)), data.type);
+ quota_manager_impl()->NotifyStorageAccessed(
+ url::Origin::Create(GURL(data.origin)), data.type, base::Time::Now());
}
for (const MockOriginData& data : kData2) {
- quota_manager()->NotifyStorageAccessed(
- url::Origin::Create(GURL(data.origin)), data.type);
+ quota_manager_impl()->NotifyStorageAccessed(
+ url::Origin::Create(GURL(data.origin)), data.type, base::Time::Now());
}
task_environment_.RunUntilIdle();
@@ -1571,14 +1713,14 @@ TEST_F(QuotaManagerTest, EvictOriginData) {
EXPECT_EQ(predelete_host_pers, usage());
}
-TEST_F(QuotaManagerTest, EvictOriginDataHistogram) {
+TEST_F(QuotaManagerImplTest, EvictOriginDataHistogram) {
const url::Origin kOrigin = ToOrigin("http://foo.com/");
static const MockOriginData kData[] = {
{"http://foo.com/", kTemp, 1},
};
base::HistogramTester histograms;
- scoped_refptr<MockQuotaClient> client =
+ MockQuotaClient* client =
CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
{blink::mojom::StorageType::kTemporary});
@@ -1590,20 +1732,21 @@ TEST_F(QuotaManagerTest, EvictOriginDataHistogram) {
// Ensure used count and time since access are recorded.
histograms.ExpectTotalCount(
- QuotaManager::kEvictedOriginAccessedCountHistogram, 1);
+ QuotaManagerImpl::kEvictedOriginAccessedCountHistogram, 1);
histograms.ExpectBucketCount(
- QuotaManager::kEvictedOriginAccessedCountHistogram, 0, 1);
+ QuotaManagerImpl::kEvictedOriginAccessedCountHistogram, 0, 1);
histograms.ExpectTotalCount(
- QuotaManager::kEvictedOriginDaysSinceAccessHistogram, 1);
+ QuotaManagerImpl::kEvictedOriginDaysSinceAccessHistogram, 1);
// First eviction has no 'last' time to compare to.
histograms.ExpectTotalCount(
- QuotaManager::kDaysBetweenRepeatedOriginEvictionsHistogram, 0);
+ QuotaManagerImpl::kDaysBetweenRepeatedOriginEvictionsHistogram, 0);
client->AddOriginAndNotify(kOrigin, kTemp, 100);
// Change the used count of the origin.
- quota_manager()->NotifyStorageAccessed(kOrigin, kTemp);
+ quota_manager_impl()->NotifyStorageAccessed(kOrigin, kTemp,
+ base::Time::Now());
task_environment_.RunUntilIdle();
GetGlobalUsage(kTemp);
@@ -1614,15 +1757,15 @@ TEST_F(QuotaManagerTest, EvictOriginDataHistogram) {
// The new used count should be logged.
histograms.ExpectTotalCount(
- QuotaManager::kEvictedOriginAccessedCountHistogram, 2);
+ QuotaManagerImpl::kEvictedOriginAccessedCountHistogram, 2);
histograms.ExpectBucketCount(
- QuotaManager::kEvictedOriginAccessedCountHistogram, 1, 1);
+ QuotaManagerImpl::kEvictedOriginAccessedCountHistogram, 1, 1);
histograms.ExpectTotalCount(
- QuotaManager::kEvictedOriginDaysSinceAccessHistogram, 2);
+ QuotaManagerImpl::kEvictedOriginDaysSinceAccessHistogram, 2);
// Second eviction should log a 'time between repeated eviction' sample.
histograms.ExpectTotalCount(
- QuotaManager::kDaysBetweenRepeatedOriginEvictionsHistogram, 1);
+ QuotaManagerImpl::kDaysBetweenRepeatedOriginEvictionsHistogram, 1);
client->AddOriginAndNotify(kOrigin, kTemp, 100);
@@ -1633,10 +1776,10 @@ TEST_F(QuotaManagerTest, EvictOriginDataHistogram) {
// Deletion from non-eviction source should not log a histogram sample.
histograms.ExpectTotalCount(
- QuotaManager::kDaysBetweenRepeatedOriginEvictionsHistogram, 1);
+ QuotaManagerImpl::kDaysBetweenRepeatedOriginEvictionsHistogram, 1);
}
-TEST_F(QuotaManagerTest, EvictOriginDataWithDeletionError) {
+TEST_F(QuotaManagerImplTest, EvictOriginDataWithDeletionError) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kTemp, 1 },
{ "http://foo.com:1/", kTemp, 20 },
@@ -1644,7 +1787,7 @@ TEST_F(QuotaManagerTest, EvictOriginDataWithDeletionError) {
{ "http://bar.com/", kTemp, 4000 },
};
static const int kNumberOfTemporaryOrigins = 3;
- scoped_refptr<MockQuotaClient> client =
+ MockQuotaClient* client =
CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
{blink::mojom::StorageType::kTemporary,
blink::mojom::StorageType::kPersistent});
@@ -1667,7 +1810,8 @@ TEST_F(QuotaManagerTest, EvictOriginDataWithDeletionError) {
client->AddOriginToErrorSet(ToOrigin("http://foo.com/"), kTemp);
- for (int i = 0; i < QuotaManager::kThresholdOfErrorsToBeDenylisted + 1; ++i) {
+ for (int i = 0; i < QuotaManagerImpl::kThresholdOfErrorsToBeDenylisted + 1;
+ ++i) {
EvictOriginData(ToOrigin("http://foo.com/"), kTemp);
task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kErrorInvalidModification, status());
@@ -1717,7 +1861,7 @@ TEST_F(QuotaManagerTest, EvictOriginDataWithDeletionError) {
EXPECT_EQ(predelete_host_pers, usage());
}
-TEST_F(QuotaManagerTest, GetEvictionRoundInfo) {
+TEST_F(QuotaManagerImplTest, GetEvictionRoundInfo) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kTemp, 1 },
{ "http://foo.com:1/", kTemp, 20 },
@@ -1742,13 +1886,13 @@ TEST_F(QuotaManagerTest, GetEvictionRoundInfo) {
EXPECT_LE(0, available_space());
}
-TEST_F(QuotaManagerTest, DeleteHostDataNoClients) {
+TEST_F(QuotaManagerImplTest, DeleteHostDataNoClients) {
DeleteHostData(std::string(), kTemp, AllQuotaClientTypes());
task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
}
-TEST_F(QuotaManagerTest, DeleteHostDataSimple) {
+TEST_F(QuotaManagerImplTest, DeleteHostDataSimple) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kTemp, 1 },
};
@@ -1801,7 +1945,7 @@ TEST_F(QuotaManagerTest, DeleteHostDataSimple) {
EXPECT_EQ(predelete_host_pers, usage());
}
-TEST_F(QuotaManagerTest, DeleteHostDataMultiple) {
+TEST_F(QuotaManagerImplTest, DeleteHostDataMultiple) {
static const MockOriginData kData1[] = {
{ "http://foo.com/", kTemp, 1 },
{ "http://foo.com:1/", kTemp, 20 },
@@ -1815,9 +1959,9 @@ TEST_F(QuotaManagerTest, DeleteHostDataMultiple) {
{ "https://foo.com/", kTemp, 80 },
{ "http://bar.com/", kTemp, 9 },
};
- CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem,
+ {blink::mojom::StorageType::kTemporary,
+ blink::mojom::StorageType::kPersistent});
CreateAndRegisterClient(kData2, QuotaClientType::kDatabase,
{blink::mojom::StorageType::kTemporary,
blink::mojom::StorageType::kPersistent});
@@ -1885,7 +2029,7 @@ TEST_F(QuotaManagerTest, DeleteHostDataMultiple) {
EXPECT_EQ(predelete_bar_pers, usage());
}
-TEST_F(QuotaManagerTest, DeleteHostDataMultipleClientsDifferentTypes) {
+TEST_F(QuotaManagerImplTest, DeleteHostDataMultipleClientsDifferentTypes) {
static const MockOriginData kData1[] = {
{"http://foo.com/", kPerm, 1},
{"http://foo.com:1/", kPerm, 10},
@@ -1898,9 +2042,9 @@ TEST_F(QuotaManagerTest, DeleteHostDataMultipleClientsDifferentTypes) {
{"https://foo.com/", kTemp, 1000000},
{"http://bar.com/", kTemp, 10000000},
};
- CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem,
+ {blink::mojom::StorageType::kTemporary,
+ blink::mojom::StorageType::kPersistent});
CreateAndRegisterClient(kData2, QuotaClientType::kDatabase,
{blink::mojom::StorageType::kTemporary});
@@ -1973,7 +2117,7 @@ TEST_F(QuotaManagerTest, DeleteHostDataMultipleClientsDifferentTypes) {
EXPECT_EQ(predelete_bar_pers - 1000, usage());
}
-TEST_F(QuotaManagerTest, DeleteOriginDataNoClients) {
+TEST_F(QuotaManagerImplTest, DeleteOriginDataNoClients) {
DeleteOriginData(url::Origin::Create(GURL("http://foo.com/")), kTemp,
AllQuotaClientTypes());
task_environment_.RunUntilIdle();
@@ -1982,7 +2126,7 @@ TEST_F(QuotaManagerTest, DeleteOriginDataNoClients) {
// Single-run DeleteOriginData cases must be well covered by
// EvictOriginData tests.
-TEST_F(QuotaManagerTest, DeleteOriginDataMultiple) {
+TEST_F(QuotaManagerImplTest, DeleteOriginDataMultiple) {
static const MockOriginData kData1[] = {
{ "http://foo.com/", kTemp, 1 },
{ "http://foo.com:1/", kTemp, 20 },
@@ -1996,9 +2140,9 @@ TEST_F(QuotaManagerTest, DeleteOriginDataMultiple) {
{ "https://foo.com/", kTemp, 80 },
{ "http://bar.com/", kTemp, 9 },
};
- CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem,
+ {blink::mojom::StorageType::kTemporary,
+ blink::mojom::StorageType::kPersistent});
CreateAndRegisterClient(kData2, QuotaClientType::kDatabase,
{blink::mojom::StorageType::kTemporary,
blink::mojom::StorageType::kPersistent});
@@ -2024,12 +2168,12 @@ TEST_F(QuotaManagerTest, DeleteOriginDataMultiple) {
const int64_t predelete_bar_pers = usage();
for (const MockOriginData& data : kData1) {
- quota_manager()->NotifyStorageAccessed(
- url::Origin::Create(GURL(data.origin)), data.type);
+ quota_manager_impl()->NotifyStorageAccessed(
+ url::Origin::Create(GURL(data.origin)), data.type, base::Time::Now());
}
for (const MockOriginData& data : kData2) {
- quota_manager()->NotifyStorageAccessed(
- url::Origin::Create(GURL(data.origin)), data.type);
+ quota_manager_impl()->NotifyStorageAccessed(
+ url::Origin::Create(GURL(data.origin)), data.type, base::Time::Now());
}
task_environment_.RunUntilIdle();
@@ -2073,7 +2217,7 @@ TEST_F(QuotaManagerTest, DeleteOriginDataMultiple) {
EXPECT_EQ(predelete_bar_pers, usage());
}
-TEST_F(QuotaManagerTest, DeleteOriginDataMultipleClientsDifferentTypes) {
+TEST_F(QuotaManagerImplTest, DeleteOriginDataMultipleClientsDifferentTypes) {
static const MockOriginData kData1[] = {
{"http://foo.com/", kPerm, 1},
{"http://foo.com:1/", kPerm, 10},
@@ -2086,9 +2230,9 @@ TEST_F(QuotaManagerTest, DeleteOriginDataMultipleClientsDifferentTypes) {
{"https://foo.com/", kTemp, 1000000},
{"http://bar.com/", kTemp, 10000000},
};
- CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary,
- blink::mojom::StorageType::kPersistent});
+ CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem,
+ {blink::mojom::StorageType::kTemporary,
+ blink::mojom::StorageType::kPersistent});
CreateAndRegisterClient(kData2, QuotaClientType::kDatabase,
{blink::mojom::StorageType::kTemporary});
@@ -2117,12 +2261,12 @@ TEST_F(QuotaManagerTest, DeleteOriginDataMultipleClientsDifferentTypes) {
const int64_t predelete_bar_pers = usage();
for (const MockOriginData& data : kData1) {
- quota_manager()->NotifyStorageAccessed(
- url::Origin::Create(GURL(data.origin)), data.type);
+ quota_manager_impl()->NotifyStorageAccessed(
+ url::Origin::Create(GURL(data.origin)), data.type, base::Time::Now());
}
for (const MockOriginData& data : kData2) {
- quota_manager()->NotifyStorageAccessed(
- url::Origin::Create(GURL(data.origin)), data.type);
+ quota_manager_impl()->NotifyStorageAccessed(
+ url::Origin::Create(GURL(data.origin)), data.type, base::Time::Now());
}
task_environment_.RunUntilIdle();
@@ -2169,7 +2313,7 @@ TEST_F(QuotaManagerTest, DeleteOriginDataMultipleClientsDifferentTypes) {
EXPECT_EQ(predelete_bar_pers - 1000, usage());
}
-TEST_F(QuotaManagerTest, GetCachedOrigins) {
+TEST_F(QuotaManagerImplTest, GetCachedOrigins) {
static const MockOriginData kData[] = {
{ "http://a.com/", kTemp, 1 },
{ "http://a.com:1/", kTemp, 20 },
@@ -2214,7 +2358,7 @@ TEST_F(QuotaManagerTest, GetCachedOrigins) {
}
}
-TEST_F(QuotaManagerTest, NotifyAndLRUOrigin) {
+TEST_F(QuotaManagerImplTest, NotifyAndLRUOrigin) {
static const MockOriginData kData[] = {
{ "http://a.com/", kTemp, 0 },
{ "http://a.com:1/", kTemp, 0 },
@@ -2254,7 +2398,7 @@ TEST_F(QuotaManagerTest, NotifyAndLRUOrigin) {
EXPECT_EQ("http://c.com/", eviction_origin()->GetURL().spec());
}
-TEST_F(QuotaManagerTest, GetLRUOriginWithOriginInUse) {
+TEST_F(QuotaManagerImplTest, GetLRUOriginWithOriginInUse) {
static const MockOriginData kData[] = {
{ "http://a.com/", kTemp, 0 },
{ "http://a.com:1/", kTemp, 0 },
@@ -2309,7 +2453,7 @@ TEST_F(QuotaManagerTest, GetLRUOriginWithOriginInUse) {
EXPECT_EQ(ToOrigin("http://a.com/"), *eviction_origin());
}
-TEST_F(QuotaManagerTest, GetOriginsModifiedBetween) {
+TEST_F(QuotaManagerImplTest, GetOriginsModifiedBetween) {
static const MockOriginData kData[] = {
{ "http://a.com/", kTemp, 0 },
{ "http://a.com:1/", kTemp, 0 },
@@ -2317,7 +2461,7 @@ TEST_F(QuotaManagerTest, GetOriginsModifiedBetween) {
{ "http://b.com/", kPerm, 0 }, // persistent
{ "http://c.com/", kTemp, 0 },
};
- scoped_refptr<MockQuotaClient> client =
+ MockQuotaClient* client =
CreateAndRegisterClient(kData, QuotaClientType::kFileSystem,
{blink::mojom::StorageType::kTemporary,
blink::mojom::StorageType::kPersistent});
@@ -2363,7 +2507,7 @@ TEST_F(QuotaManagerTest, GetOriginsModifiedBetween) {
EXPECT_EQ(modified_origins_type(), kTemp);
}
-TEST_F(QuotaManagerTest, DumpQuotaTable) {
+TEST_F(QuotaManagerImplTest, DumpQuotaTable) {
SetPersistentHostQuota("example1.com", 1);
SetPersistentHostQuota("example2.com", 20);
SetPersistentHostQuota("example3.com", 300);
@@ -2387,15 +2531,15 @@ TEST_F(QuotaManagerTest, DumpQuotaTable) {
EXPECT_TRUE(entries.empty());
}
-TEST_F(QuotaManagerTest, DumpOriginInfoTable) {
+TEST_F(QuotaManagerImplTest, DumpOriginInfoTable) {
using std::make_pair;
- quota_manager()->NotifyStorageAccessed(ToOrigin("http://example.com/"),
- kTemp);
- quota_manager()->NotifyStorageAccessed(ToOrigin("http://example.com/"),
- kPerm);
- quota_manager()->NotifyStorageAccessed(ToOrigin("http://example.com/"),
- kPerm);
+ quota_manager_impl()->NotifyStorageAccessed(ToOrigin("http://example.com/"),
+ kTemp, base::Time::Now());
+ quota_manager_impl()->NotifyStorageAccessed(ToOrigin("http://example.com/"),
+ kPerm, base::Time::Now());
+ quota_manager_impl()->NotifyStorageAccessed(ToOrigin("http://example.com/"),
+ kPerm, base::Time::Now());
task_environment_.RunUntilIdle();
DumpOriginInfoTable();
@@ -2421,7 +2565,7 @@ TEST_F(QuotaManagerTest, DumpOriginInfoTable) {
EXPECT_TRUE(entries.empty());
}
-TEST_F(QuotaManagerTest, QuotaForEmptyHost) {
+TEST_F(QuotaManagerImplTest, QuotaForEmptyHost) {
GetPersistentHostQuota(std::string());
task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
@@ -2432,7 +2576,7 @@ TEST_F(QuotaManagerTest, QuotaForEmptyHost) {
EXPECT_EQ(QuotaStatusCode::kErrorNotSupported, status());
}
-TEST_F(QuotaManagerTest, DeleteSpecificClientTypeSingleOrigin) {
+TEST_F(QuotaManagerImplTest, DeleteSpecificClientTypeSingleOrigin) {
static const MockOriginData kData1[] = {
{ "http://foo.com/", kTemp, 1 },
};
@@ -2445,12 +2589,12 @@ TEST_F(QuotaManagerTest, DeleteSpecificClientTypeSingleOrigin) {
static const MockOriginData kData4[] = {
{ "http://foo.com/", kTemp, 8 },
};
- CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary});
+ CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem,
+ {blink::mojom::StorageType::kTemporary});
CreateAndRegisterClient(kData2, QuotaClientType::kAppcache,
{blink::mojom::StorageType::kTemporary});
- CreateAndRegisterClient(kData3, QuotaClientType::kDatabase,
- {blink::mojom::StorageType::kTemporary});
+ CreateAndRegisterLegacyClient(kData3, QuotaClientType::kDatabase,
+ {blink::mojom::StorageType::kTemporary});
CreateAndRegisterClient(kData4, QuotaClientType::kIndexedDatabase,
{blink::mojom::StorageType::kTemporary});
@@ -2487,7 +2631,7 @@ TEST_F(QuotaManagerTest, DeleteSpecificClientTypeSingleOrigin) {
EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage());
}
-TEST_F(QuotaManagerTest, DeleteSpecificClientTypeSingleHost) {
+TEST_F(QuotaManagerImplTest, DeleteSpecificClientTypeSingleHost) {
static const MockOriginData kData1[] = {
{ "http://foo.com:1111/", kTemp, 1 },
};
@@ -2500,12 +2644,12 @@ TEST_F(QuotaManagerTest, DeleteSpecificClientTypeSingleHost) {
static const MockOriginData kData4[] = {
{ "http://foo.com:4444/", kTemp, 8 },
};
- CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary});
+ CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem,
+ {blink::mojom::StorageType::kTemporary});
CreateAndRegisterClient(kData2, QuotaClientType::kAppcache,
{blink::mojom::StorageType::kTemporary});
- CreateAndRegisterClient(kData3, QuotaClientType::kDatabase,
- {blink::mojom::StorageType::kTemporary});
+ CreateAndRegisterLegacyClient(kData3, QuotaClientType::kDatabase,
+ {blink::mojom::StorageType::kTemporary});
CreateAndRegisterClient(kData4, QuotaClientType::kIndexedDatabase,
{blink::mojom::StorageType::kTemporary});
@@ -2538,7 +2682,7 @@ TEST_F(QuotaManagerTest, DeleteSpecificClientTypeSingleHost) {
EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage());
}
-TEST_F(QuotaManagerTest, DeleteMultipleClientTypesSingleOrigin) {
+TEST_F(QuotaManagerImplTest, DeleteMultipleClientTypesSingleOrigin) {
static const MockOriginData kData1[] = {
{ "http://foo.com/", kTemp, 1 },
};
@@ -2551,12 +2695,12 @@ TEST_F(QuotaManagerTest, DeleteMultipleClientTypesSingleOrigin) {
static const MockOriginData kData4[] = {
{ "http://foo.com/", kTemp, 8 },
};
- CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary});
+ CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem,
+ {blink::mojom::StorageType::kTemporary});
CreateAndRegisterClient(kData2, QuotaClientType::kAppcache,
{blink::mojom::StorageType::kTemporary});
- CreateAndRegisterClient(kData3, QuotaClientType::kDatabase,
- {blink::mojom::StorageType::kTemporary});
+ CreateAndRegisterLegacyClient(kData3, QuotaClientType::kDatabase,
+ {blink::mojom::StorageType::kTemporary});
CreateAndRegisterClient(kData4, QuotaClientType::kIndexedDatabase,
{blink::mojom::StorageType::kTemporary});
@@ -2580,7 +2724,7 @@ TEST_F(QuotaManagerTest, DeleteMultipleClientTypesSingleOrigin) {
EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage());
}
-TEST_F(QuotaManagerTest, DeleteMultipleClientTypesSingleHost) {
+TEST_F(QuotaManagerImplTest, DeleteMultipleClientTypesSingleHost) {
static const MockOriginData kData1[] = {
{ "http://foo.com:1111/", kTemp, 1 },
};
@@ -2593,12 +2737,12 @@ TEST_F(QuotaManagerTest, DeleteMultipleClientTypesSingleHost) {
static const MockOriginData kData4[] = {
{ "http://foo.com:4444/", kTemp, 8 },
};
- CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem,
- {blink::mojom::StorageType::kTemporary});
+ CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem,
+ {blink::mojom::StorageType::kTemporary});
CreateAndRegisterClient(kData2, QuotaClientType::kAppcache,
{blink::mojom::StorageType::kTemporary});
- CreateAndRegisterClient(kData3, QuotaClientType::kDatabase,
- {blink::mojom::StorageType::kTemporary});
+ CreateAndRegisterLegacyClient(kData3, QuotaClientType::kDatabase,
+ {blink::mojom::StorageType::kTemporary});
CreateAndRegisterClient(kData4, QuotaClientType::kIndexedDatabase,
{blink::mojom::StorageType::kTemporary});
@@ -2622,8 +2766,8 @@ TEST_F(QuotaManagerTest, DeleteMultipleClientTypesSingleHost) {
EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage());
}
-TEST_F(QuotaManagerTest, GetUsageAndQuota_Incognito) {
- ResetQuotaManager(true);
+TEST_F(QuotaManagerImplTest, GetUsageAndQuota_Incognito) {
+ ResetQuotaManagerImpl(true);
static const MockOriginData kData[] = {
{ "http://foo.com/", kTemp, 10 },
@@ -2673,20 +2817,21 @@ TEST_F(QuotaManagerTest, GetUsageAndQuota_Incognito) {
EXPECT_EQ(available_space() + usage(), quota());
}
-TEST_F(QuotaManagerTest, GetUsageAndQuota_SessionOnly) {
+TEST_F(QuotaManagerImplTest, GetUsageAndQuota_SessionOnly) {
const url::Origin kEpheremalOrigin = ToOrigin("http://ephemeral/");
mock_special_storage_policy()->AddSessionOnly(kEpheremalOrigin.GetURL());
GetUsageAndQuotaForWebApps(kEpheremalOrigin, kTemp);
task_environment_.RunUntilIdle();
- EXPECT_EQ(quota_manager()->settings().session_only_per_host_quota, quota());
+ EXPECT_EQ(quota_manager_impl()->settings().session_only_per_host_quota,
+ quota());
GetUsageAndQuotaForWebApps(kEpheremalOrigin, kPerm);
task_environment_.RunUntilIdle();
EXPECT_EQ(0, quota());
}
-TEST_F(QuotaManagerTest, MaybeRunStoragePressureCallback) {
+TEST_F(QuotaManagerImplTest, MaybeRunStoragePressureCallback) {
bool callback_ran = false;
auto cb = base::BindRepeating(
[](bool* callback_ran, url::Origin origin) { *callback_ran = true; },
@@ -2694,7 +2839,7 @@ TEST_F(QuotaManagerTest, MaybeRunStoragePressureCallback) {
SetStoragePressureCallback(std::move(cb));
- int64_t kGBytes = QuotaManager::kMBytes * 1024;
+ int64_t kGBytes = QuotaManagerImpl::kMBytes * 1024;
MaybeRunStoragePressureCallback(url::Origin(), 100 * kGBytes, 2 * kGBytes);
task_environment_.RunUntilIdle();
EXPECT_FALSE(callback_ran);
@@ -2704,7 +2849,7 @@ TEST_F(QuotaManagerTest, MaybeRunStoragePressureCallback) {
EXPECT_TRUE(callback_ran);
}
-TEST_F(QuotaManagerTest, OverrideQuotaForOrigin) {
+TEST_F(QuotaManagerImplTest, OverrideQuotaForOrigin) {
url::Origin origin = ToOrigin("https://foo.com");
std::unique_ptr<QuotaOverrideHandle> handle = GetQuotaOverrideHandle();
@@ -2720,7 +2865,7 @@ TEST_F(QuotaManagerTest, OverrideQuotaForOrigin) {
EXPECT_EQ(5000, quota());
}
-TEST_F(QuotaManagerTest, OverrideQuotaForOrigin_Disable) {
+TEST_F(QuotaManagerImplTest, OverrideQuotaForOrigin_Disable) {
url::Origin origin = ToOrigin("https://foo.com");
std::unique_ptr<QuotaOverrideHandle> handle1 = GetQuotaOverrideHandle();
std::unique_ptr<QuotaOverrideHandle> handle2 = GetQuotaOverrideHandle();
@@ -2757,7 +2902,7 @@ TEST_F(QuotaManagerTest, OverrideQuotaForOrigin_Disable) {
EXPECT_EQ(kDefaultPerHostQuota, quota());
}
-TEST_F(QuotaManagerTest, WithdrawQuotaOverride) {
+TEST_F(QuotaManagerImplTest, WithdrawQuotaOverride) {
url::Origin origin = ToOrigin("https://foo.com");
std::unique_ptr<QuotaOverrideHandle> handle1 = GetQuotaOverrideHandle();
std::unique_ptr<QuotaOverrideHandle> handle2 = GetQuotaOverrideHandle();
@@ -2798,4 +2943,57 @@ TEST_F(QuotaManagerTest, WithdrawQuotaOverride) {
EXPECT_EQ(kDefaultPerHostQuota, quota());
}
+TEST_F(QuotaManagerImplTest, QuotaChangeEvent_LargePartitionPressure) {
+ scoped_feature_list_.InitAndEnableFeature(features::kStoragePressureEvent);
+ bool quota_change_dispatched = false;
+
+ SetQuotaChangeCallback(
+ base::BindLambdaForTesting([&] { quota_change_dispatched = true; }));
+ SetGetVolumeInfoFn([](const base::FilePath&) -> std::tuple<int64_t, int64_t> {
+ int64_t total = kGigabytes * 100;
+ int64_t available = kGigabytes * 2;
+ return std::make_tuple(total, available);
+ });
+ GetStorageCapacity();
+ task_environment_.RunUntilIdle();
+ EXPECT_FALSE(quota_change_dispatched);
+
+ SetGetVolumeInfoFn([](const base::FilePath&) -> std::tuple<int64_t, int64_t> {
+ int64_t total = kGigabytes * 100;
+ int64_t available = QuotaManagerImpl::kMBytes * 512;
+ return std::make_tuple(total, available);
+ });
+ GetStorageCapacity();
+ task_environment_.RunUntilIdle();
+ EXPECT_TRUE(quota_change_dispatched);
+}
+
+TEST_F(QuotaManagerImplTest, QuotaChangeEvent_SmallPartitionPressure) {
+ scoped_feature_list_.InitAndEnableFeature(features::kStoragePressureEvent);
+ bool quota_change_dispatched = false;
+
+ SetQuotaChangeCallback(
+ base::BindLambdaForTesting([&] { quota_change_dispatched = true; }));
+ SetGetVolumeInfoFn([](const base::FilePath&) -> std::tuple<int64_t, int64_t> {
+ int64_t total = kGigabytes * 10;
+ int64_t available = total * 2;
+ return std::make_tuple(total, available);
+ });
+ GetStorageCapacity();
+ task_environment_.RunUntilIdle();
+ EXPECT_FALSE(quota_change_dispatched);
+
+ SetGetVolumeInfoFn([](const base::FilePath&) -> std::tuple<int64_t, int64_t> {
+ // DetermineStoragePressure flow will trigger the storage pressure flow
+ // when available disk space is below 5% (+/- 0.25%) of total disk space.
+ // Available is 2% here to guarantee that it falls below the threshold.
+ int64_t total = kGigabytes * 10;
+ int64_t available = total * 0.02;
+ return std::make_tuple(total, available);
+ });
+ GetStorageCapacity();
+ task_environment_.RunUntilIdle();
+ EXPECT_TRUE(quota_change_dispatched);
+}
+
} // namespace storage
diff --git a/chromium/storage/browser/quota/quota_override_handle.cc b/chromium/storage/browser/quota/quota_override_handle.cc
index 5c9ab714678..6ff4125c171 100644
--- a/chromium/storage/browser/quota/quota_override_handle.cc
+++ b/chromium/storage/browser/quota/quota_override_handle.cc
@@ -6,14 +6,17 @@
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
+#include "base/threading/sequenced_task_runner_handle.h"
#include "storage/browser/quota/quota_manager_proxy.h"
namespace storage {
QuotaOverrideHandle::QuotaOverrideHandle(
- scoped_refptr<QuotaManagerProxy> quota_manager)
- : quota_manager_(quota_manager) {
- quota_manager_->GetOverrideHandleId(
+ scoped_refptr<QuotaManagerProxy> quota_manager_proxy)
+ : quota_manager_proxy_(std::move(quota_manager_proxy)) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ quota_manager_proxy_->GetOverrideHandleId(
+ base::SequencedTaskRunnerHandle::Get(),
base::BindOnce(&QuotaOverrideHandle::DidGetOverrideHandleId,
weak_ptr_factory_.GetWeakPtr()));
}
@@ -21,7 +24,7 @@ QuotaOverrideHandle::QuotaOverrideHandle(
QuotaOverrideHandle::~QuotaOverrideHandle() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (id_.has_value()) {
- quota_manager_->WithdrawOverridesForHandle(id_.value());
+ quota_manager_proxy_->WithdrawOverridesForHandle(id_.value());
}
}
@@ -39,8 +42,9 @@ void QuotaOverrideHandle::OverrideQuotaForOrigin(
origin, quota_size, std::move(callback)));
return;
}
- quota_manager_->OverrideQuotaForOrigin(id_.value(), origin, quota_size,
- std::move(callback));
+ quota_manager_proxy_->OverrideQuotaForOrigin(
+ id_.value(), origin, quota_size, base::SequencedTaskRunnerHandle::Get(),
+ std::move(callback));
}
void QuotaOverrideHandle::DidGetOverrideHandleId(int id) {
diff --git a/chromium/storage/browser/quota/quota_override_handle.h b/chromium/storage/browser/quota/quota_override_handle.h
index e7b6ec918f2..81f7ab9acbd 100644
--- a/chromium/storage/browser/quota/quota_override_handle.h
+++ b/chromium/storage/browser/quota/quota_override_handle.h
@@ -10,6 +10,7 @@
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
+#include "base/thread_annotations.h"
#include "url/origin.h"
namespace storage {
@@ -38,12 +39,16 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaOverrideHandle {
void DidGetUniqueId();
void DidGetOverrideHandleId(int id);
- base::Optional<int> id_;
- std::vector<base::OnceClosure> override_callback_queue_;
- scoped_refptr<QuotaManagerProxy> quota_manager_;
-
SEQUENCE_CHECKER(sequence_checker_);
- base::WeakPtrFactory<QuotaOverrideHandle> weak_ptr_factory_{this};
+
+ const scoped_refptr<QuotaManagerProxy> quota_manager_proxy_
+ GUARDED_BY_CONTEXT(sequence_checker_);
+ base::Optional<int> id_ GUARDED_BY_CONTEXT(sequence_checker_);
+ std::vector<base::OnceClosure> override_callback_queue_
+ GUARDED_BY_CONTEXT(sequence_checker_);
+
+ base::WeakPtrFactory<QuotaOverrideHandle> weak_ptr_factory_
+ GUARDED_BY_CONTEXT(sequence_checker_){this};
};
} // namespace storage
diff --git a/chromium/storage/browser/quota/quota_settings.cc b/chromium/storage/browser/quota/quota_settings.cc
index 4b8ac29b314..ebc116cd60b 100644
--- a/chromium/storage/browser/quota/quota_settings.cc
+++ b/chromium/storage/browser/quota/quota_settings.cc
@@ -27,7 +27,6 @@ namespace {
const int64_t kMBytes = 1024 * 1024;
const int kRandomizedPercentage = 10;
const double kDefaultPerHostRatio = 0.75;
-const double kDefaultPoolSizeRatio = 0.8;
const double kIncognitoQuotaRatioLowerBound = 0.15;
const double kIncognitoQuotaRatioUpperBound = 0.2;
@@ -68,7 +67,13 @@ base::Optional<QuotaSettings> CalculateNominalDynamicSettings(
// The fraction of the device's storage the browser is willing to use for
// temporary storage.
- const double kTemporaryPoolSizeRatio = kDefaultPoolSizeRatio;
+ const double kTemporaryPoolSizeRatio = features::kPoolSizeRatio.Get();
+
+ // The fixed size in bytes the browser is willing to use for temporary
+ // storage. If both the ratio and the absolute size are set, the lower value
+ // will be honored.
+ const int64_t kTemporaryPoolSizeFixed =
+ static_cast<int64_t>(features::kPoolSizeBytes.Get());
// The amount of the device's storage the browser attempts to
// keep free. If there is less than this amount of storage free
@@ -83,8 +88,10 @@ base::Optional<QuotaSettings> CalculateNominalDynamicSettings(
// * 64GB storage -- min(6GB,2GB) = 2GB
// * 16GB storage -- min(1.6GB,2GB) = 1.6GB
// * 8GB storage -- min(800MB,2GB) = 800MB
- const int64_t kShouldRemainAvailableFixed = 2048 * kMBytes; // 2GB
- const double kShouldRemainAvailableRatio = 0.1; // 10%
+ const int64_t kShouldRemainAvailableFixed =
+ static_cast<int64_t>(features::kShouldRemainAvailableBytes.Get());
+ const double kShouldRemainAvailableRatio =
+ features::kShouldRemainAvailableRatio.Get();
// The amount of the device's storage the browser attempts to
// keep free at all costs. Data will be aggressively evicted.
@@ -98,8 +105,10 @@ base::Optional<QuotaSettings> CalculateNominalDynamicSettings(
// * 64GB storage -- min(640MB,1GB) = 640MB
// * 16GB storage -- min(160MB,1GB) = 160MB
// * 8GB storage -- min(80MB,1GB) = 80MB
- const int64_t kMustRemainAvailableFixed = 1024 * kMBytes; // 1GB
- const double kMustRemainAvailableRatio = 0.01; // 1%
+ const int64_t kMustRemainAvailableFixed =
+ static_cast<int64_t>(features::kMustRemainAvailableBytes.Get());
+ const double kMustRemainAvailableRatio =
+ features::kMustRemainAvailableRatio.Get();
// The fraction of the temporary pool that can be utilized by a single host.
const double kPerHostTemporaryRatio = kDefaultPerHostRatio;
@@ -117,7 +126,13 @@ base::Optional<QuotaSettings> CalculateNominalDynamicSettings(
return base::nullopt;
}
- int64_t pool_size = total * kTemporaryPoolSizeRatio;
+ // Pool size calculated by ratio.
+ int64_t pool_size_by_ratio = total * kTemporaryPoolSizeRatio;
+
+ int64_t pool_size =
+ kTemporaryPoolSizeFixed > 0
+ ? std::min(kTemporaryPoolSizeFixed, pool_size_by_ratio)
+ : pool_size_by_ratio;
settings.pool_size = pool_size;
settings.should_remain_available =
diff --git a/chromium/storage/browser/quota/quota_settings_unittest.cc b/chromium/storage/browser/quota/quota_settings_unittest.cc
index 2654212f214..a2b2a564f1c 100644
--- a/chromium/storage/browser/quota/quota_settings_unittest.cc
+++ b/chromium/storage/browser/quota/quota_settings_unittest.cc
@@ -8,6 +8,8 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/files/scoped_temp_dir.h"
+#include "base/optional.h"
+#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
@@ -39,15 +41,28 @@ class QuotaSettingsTest : public testing::Test {
QuotaSettingsTest() = default;
void SetUp() override { ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); }
- protected:
- base::test::ScopedFeatureList scoped_feature_list_;
- base::test::TaskEnvironment task_environment_;
+ // Synchronous proxy to GetNominalDynamicSettings().
+ base::Optional<QuotaSettings> GetSettings(
+ bool is_incognito,
+ QuotaDeviceInfoHelper* device_info_helper) {
+ base::Optional<QuotaSettings> quota_settings;
+ base::RunLoop run_loop;
+ GetNominalDynamicSettings(
+ profile_path(), is_incognito, device_info_helper,
+ base::BindLambdaForTesting([&](base::Optional<QuotaSettings> settings) {
+ quota_settings = std::move(settings);
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ return quota_settings;
+ }
+
const base::FilePath& profile_path() const { return data_dir_.GetPath(); }
- private:
+ protected:
+ base::test::ScopedFeatureList scoped_feature_list_;
base::ScopedTempDir data_dir_;
- QuotaSettings quota_settings_;
- DISALLOW_COPY_AND_ASSIGN(QuotaSettingsTest);
+ base::test::TaskEnvironment task_environment_;
};
class QuotaSettingsIncognitoTest : public QuotaSettingsTest {
@@ -64,24 +79,15 @@ class QuotaSettingsIncognitoTest : public QuotaSettingsTest {
}
void GetAndTestSettings(const int64_t physical_memory_amount) {
- bool callback_executed = false;
- GetNominalDynamicSettings(
- profile_path(), true, device_info_helper(),
- base::BindLambdaForTesting([&](base::Optional<QuotaSettings> settings) {
- callback_executed = true;
- EXPECT_LE(physical_memory_amount *
- GetIncognitoQuotaRatioLowerBound_ForTesting(),
- settings->pool_size);
- EXPECT_GE(physical_memory_amount *
- GetIncognitoQuotaRatioUpperBound_ForTesting(),
- settings->pool_size);
- }));
- task_environment_.RunUntilIdle();
- EXPECT_TRUE(callback_executed);
- }
-
- MockQuotaDeviceInfoHelper* device_info_helper() {
- return &device_info_helper_;
+ base::Optional<QuotaSettings> settings =
+ GetSettings(true, &device_info_helper_);
+ ASSERT_TRUE(settings.has_value());
+ EXPECT_LE(
+ physical_memory_amount * GetIncognitoQuotaRatioLowerBound_ForTesting(),
+ settings->pool_size);
+ EXPECT_GE(
+ physical_memory_amount * GetIncognitoQuotaRatioUpperBound_ForTesting(),
+ settings->pool_size);
}
private:
@@ -93,19 +99,76 @@ TEST_F(QuotaSettingsTest, Default) {
ON_CALL(device_info_helper, AmountOfTotalDiskSpace(_))
.WillByDefault(::testing::Return(2000));
- bool callback_executed = false;
- GetNominalDynamicSettings(
- profile_path(), false, &device_info_helper,
- base::BindLambdaForTesting([&](base::Optional<QuotaSettings> settings) {
- callback_executed = true;
- ASSERT_NE(settings, base::nullopt);
- // 1600 = 2000 * default PoolSizeRatio (0.8)
- EXPECT_EQ(settings->pool_size, 1600);
- // 1200 = 1600 * default PerHostRatio (.75)
- EXPECT_EQ(settings->per_host_quota, 1200);
- }));
- task_environment_.RunUntilIdle();
- EXPECT_TRUE(callback_executed);
+ base::Optional<QuotaSettings> settings =
+ GetSettings(false, &device_info_helper);
+ ASSERT_TRUE(settings.has_value());
+ // 1600 = 2000 * default PoolSizeRatio (0.8)
+ EXPECT_EQ(settings->pool_size, 1600);
+ // 1200 = 1600 * default PerHostRatio (.75)
+ EXPECT_EQ(settings->per_host_quota, 1200);
+}
+
+TEST_F(QuotaSettingsTest, FeatureParamsWithLargeFixedQuota) {
+ scoped_feature_list_.InitAndEnableFeatureWithParameters(
+ features::kStorageQuotaSettings, {{"MustRemainAvailableBytes", "500"},
+ {"MustRemainAvailableRatio", "0.01"},
+ {"PoolSizeBytes", "2000"},
+ {"PoolSizeRatio", "0.8"},
+ {"ShouldRemainAvailableBytes", "600"},
+ {"ShouldRemainAvailableRatio", "0.1"}});
+
+ MockQuotaDeviceInfoHelper device_info_helper;
+ ON_CALL(device_info_helper, AmountOfTotalDiskSpace(_))
+ .WillByDefault(::testing::Return(2000));
+
+ base::Optional<QuotaSettings> settings =
+ GetSettings(false, &device_info_helper);
+ ASSERT_TRUE(settings.has_value());
+
+ EXPECT_EQ(settings->pool_size, 1600);
+ EXPECT_EQ(settings->must_remain_available, 20);
+ EXPECT_EQ(settings->should_remain_available, 200);
+}
+
+TEST_F(QuotaSettingsTest, FeatureParamsWithSmallFixedQuota) {
+ scoped_feature_list_.InitAndEnableFeatureWithParameters(
+ features::kStorageQuotaSettings, {{"MustRemainAvailableBytes", "5"},
+ {"MustRemainAvailableRatio", "0.01"},
+ {"PoolSizeBytes", "20"},
+ {"PoolSizeRatio", "0.8"},
+ {"ShouldRemainAvailableBytes", "60"},
+ {"ShouldRemainAvailableRatio", "0.1"}});
+
+ MockQuotaDeviceInfoHelper device_info_helper;
+ ON_CALL(device_info_helper, AmountOfTotalDiskSpace(_))
+ .WillByDefault(::testing::Return(2000));
+
+ base::Optional<QuotaSettings> settings =
+ GetSettings(false, &device_info_helper);
+ ASSERT_TRUE(settings.has_value());
+
+ EXPECT_EQ(settings->pool_size, 20);
+ EXPECT_EQ(settings->must_remain_available, 5);
+ EXPECT_EQ(settings->should_remain_available, 60);
+}
+
+TEST_F(QuotaSettingsTest, FeatureParamsWithoutFixedQuota) {
+ scoped_feature_list_.InitAndEnableFeatureWithParameters(
+ features::kStorageQuotaSettings, {{"MustRemainAvailableRatio", "0.01"},
+ {"PoolSizeRatio", "0.8"},
+ {"ShouldRemainAvailableRatio", "0.1"}});
+
+ MockQuotaDeviceInfoHelper device_info_helper;
+ ON_CALL(device_info_helper, AmountOfTotalDiskSpace(_))
+ .WillByDefault(::testing::Return(2000));
+
+ base::Optional<QuotaSettings> settings =
+ GetSettings(false, &device_info_helper);
+ ASSERT_TRUE(settings.has_value());
+
+ EXPECT_EQ(settings->pool_size, 1600);
+ EXPECT_EQ(settings->must_remain_available, 20);
+ EXPECT_EQ(settings->should_remain_available, 200);
}
TEST_F(QuotaSettingsIncognitoTest, IncognitoDynamicQuota_LowPhysicalMemory) {
diff --git a/chromium/storage/browser/quota/quota_task.cc b/chromium/storage/browser/quota/quota_task.cc
index ff0487573fe..24674ca68e6 100644
--- a/chromium/storage/browser/quota/quota_task.cc
+++ b/chromium/storage/browser/quota/quota_task.cc
@@ -8,9 +8,9 @@
#include <functional>
#include "base/bind.h"
+#include "base/containers/contains.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/threading/thread_task_runner_handle.h"
using base::TaskRunner;
diff --git a/chromium/storage/browser/quota/quota_task.h b/chromium/storage/browser/quota/quota_task.h
index 7ca4874bed8..49fe6cb75ed 100644
--- a/chromium/storage/browser/quota/quota_task.h
+++ b/chromium/storage/browser/quota/quota_task.h
@@ -30,6 +30,9 @@ class QuotaTaskObserver;
// TODO(kinuko): Revise this using base::OnceCallback.
class QuotaTask {
public:
+ QuotaTask(const QuotaTask&) = delete;
+ QuotaTask& operator=(const QuotaTask&) = delete;
+
void Start();
protected:
diff --git a/chromium/storage/browser/quota/quota_temporary_storage_evictor.cc b/chromium/storage/browser/quota/quota_temporary_storage_evictor.cc
index ba99181034e..90034aadf3a 100644
--- a/chromium/storage/browser/quota/quota_temporary_storage_evictor.cc
+++ b/chromium/storage/browser/quota/quota_temporary_storage_evictor.cc
@@ -11,7 +11,7 @@
#include "base/auto_reset.h"
#include "base/bind.h"
#include "storage/browser/quota/quota_macros.h"
-#include "storage/browser/quota/quota_manager.h"
+#include "storage/browser/quota/quota_manager_impl.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
#include "url/gurl.h"
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 2f1b729f32f..46154a0e245 100644
--- a/chromium/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc
+++ b/chromium/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc
@@ -11,12 +11,12 @@
#include "base/bind.h"
#include "base/callback.h"
+#include "base/containers/contains.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/test/task_environment.h"
-#include "storage/browser/quota/quota_manager.h"
+#include "storage/browser/quota/quota_manager_impl.h"
#include "storage/browser/quota/quota_temporary_storage_evictor.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
diff --git a/chromium/storage/browser/quota/storage_policy_observer.cc b/chromium/storage/browser/quota/storage_policy_observer.cc
new file mode 100644
index 00000000000..5fe45ed8ffe
--- /dev/null
+++ b/chromium/storage/browser/quota/storage_policy_observer.cc
@@ -0,0 +1,136 @@
+// Copyright 2021 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_policy_observer.h"
+
+#include <utility>
+
+#include "base/task/post_task.h"
+#include "url/origin.h"
+
+namespace storage {
+
+// A helper class that lives on the IO thread and registers with
+// SpecialStoragePolicy. It bounces back any OnPolicyChanged messages
+// to the StoragePolicyObserver on the provided `reply_task_runner`.
+class StoragePolicyObserverIOThread
+ : public storage::SpecialStoragePolicy::Observer {
+ public:
+ StoragePolicyObserverIOThread(
+ scoped_refptr<base::SequencedTaskRunner> reply_task_runner,
+ scoped_refptr<storage::SpecialStoragePolicy> storage_policy,
+ base::WeakPtr<StoragePolicyObserver> observer)
+ : reply_task_runner_(std::move(reply_task_runner)),
+ storage_policy_(std::move(storage_policy)),
+ observer_(std::move(observer)) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ storage_policy_->AddObserver(this);
+ }
+
+ ~StoragePolicyObserverIOThread() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ storage_policy_->RemoveObserver(this);
+ }
+
+ // storage::SpecialStoragePolicy::Observer implementation:
+ void OnPolicyChanged() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ reply_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&StoragePolicyObserver::OnPolicyChanged, observer_));
+ }
+
+ private:
+ scoped_refptr<base::SequencedTaskRunner> reply_task_runner_;
+ scoped_refptr<storage::SpecialStoragePolicy> storage_policy_;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+ base::WeakPtr<StoragePolicyObserver> observer_;
+};
+
+StoragePolicyObserver::StoragePolicyObserver(
+ ApplyPolicyUpdatesCallback callback,
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner,
+ scoped_refptr<storage::SpecialStoragePolicy> storage_policy)
+ : callback_(callback), storage_policy_(std::move(storage_policy)) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!storage_policy_)
+ return;
+
+ storage_policy_observer_ = base::SequenceBound<StoragePolicyObserverIOThread>(
+ std::move(io_task_runner), base::SequencedTaskRunnerHandle::Get(),
+ storage_policy_, weak_factory_.GetWeakPtr());
+}
+
+StoragePolicyObserver::~StoragePolicyObserver() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+void StoragePolicyObserver::StartTrackingOrigin(const url::Origin& origin) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ // If the origin exists, emplace fails, and its state is unchanged.
+ const GURL origin_url = GURL(origin.Serialize());
+ origin_state_.emplace(origin_url, OriginState());
+
+ OnPolicyChanged();
+}
+
+void StoragePolicyObserver::StartTrackingOrigins(
+ const std::vector<url::Origin>& origins) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ for (const auto& origin : origins) {
+ // If the origin exists, emplace fails, and its state is unchanged.
+ GURL origin_url = GURL(origin.Serialize());
+ origin_state_.emplace(std::move(origin_url), OriginState());
+ }
+
+ OnPolicyChanged();
+}
+
+void StoragePolicyObserver::StopTrackingOrigin(const url::Origin& origin) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ const GURL origin_url = GURL(origin.Serialize());
+ origin_state_.erase(origin_url);
+}
+
+void StoragePolicyObserver::OnPolicyChanged() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ std::vector<storage::mojom::StoragePolicyUpdatePtr> policy_updates;
+ for (auto& entry : origin_state_) {
+ const GURL& origin = entry.first;
+ OriginState& state = entry.second;
+ state.should_purge_on_shutdown = ShouldPurgeOnShutdown(origin);
+
+ if (state.should_purge_on_shutdown != state.will_purge_on_shutdown) {
+ state.will_purge_on_shutdown = state.should_purge_on_shutdown;
+ policy_updates.emplace_back(storage::mojom::StoragePolicyUpdate::New(
+ url::Origin::Create(origin), state.should_purge_on_shutdown));
+ }
+ }
+ if (policy_updates.empty())
+ return;
+ callback_.Run(std::move(policy_updates));
+}
+
+bool StoragePolicyObserver::ShouldPurgeOnShutdownForTesting(
+ const url::Origin& origin) {
+ const GURL origin_url = GURL(origin.Serialize());
+ return ShouldPurgeOnShutdown(origin_url);
+}
+
+bool StoragePolicyObserver::ShouldPurgeOnShutdown(const GURL& origin) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!storage_policy_)
+ return false;
+ if (!storage_policy_->IsStorageSessionOnly(origin))
+ return false;
+ if (storage_policy_->IsStorageProtected(origin))
+ return false;
+ return true;
+}
+
+} // namespace storage
diff --git a/chromium/storage/browser/quota/storage_policy_observer.h b/chromium/storage/browser/quota/storage_policy_observer.h
new file mode 100644
index 00000000000..01990226bb6
--- /dev/null
+++ b/chromium/storage/browser/quota/storage_policy_observer.h
@@ -0,0 +1,85 @@
+// Copyright 2021 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_POLICY_OBSERVER_H_
+#define STORAGE_BROWSER_QUOTA_STORAGE_POLICY_OBSERVER_H_
+
+#include <map>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/component_export.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
+#include "base/threading/sequence_bound.h"
+#include "components/services/storage/public/mojom/storage_policy_update.mojom.h"
+#include "storage/browser/quota/special_storage_policy.h"
+#include "url/gurl.h"
+
+namespace url {
+class Origin;
+}
+
+namespace storage {
+
+class StoragePolicyObserverIOThread;
+
+// A helper class that aggregates storage::mojom::StoragePolicyUpdate
+// changes for tracked origins. `StartTrackingOrigin()` adds an origin
+// to start tracking. When these origins have policy updates,
+// the provided `callback` will be called with the policy update deltas.
+class COMPONENT_EXPORT(STORAGE_BROWSER) StoragePolicyObserver {
+ public:
+ using ApplyPolicyUpdatesCallback = base::RepeatingCallback<void(
+ std::vector<storage::mojom::StoragePolicyUpdatePtr>)>;
+
+ StoragePolicyObserver(
+ ApplyPolicyUpdatesCallback callback,
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner,
+ scoped_refptr<storage::SpecialStoragePolicy> storage_policy);
+ ~StoragePolicyObserver();
+
+ StoragePolicyObserver(const StoragePolicyObserver&) = delete;
+ StoragePolicyObserver& operator=(const StoragePolicyObserver&) = delete;
+
+ // These methods are idempotent. Tracking an origin that is already
+ // tracked and stopping tracking an origin that is not being tracked
+ // are noops.
+ void StartTrackingOrigin(const url::Origin& origin);
+ void StartTrackingOrigins(const std::vector<url::Origin>& origins);
+ void StopTrackingOrigin(const url::Origin& origin);
+
+ // Called by StoragePolicyObserverIOThread.
+ void OnPolicyChanged();
+
+ bool ShouldPurgeOnShutdownForTesting(const url::Origin& origin);
+
+ private:
+ bool ShouldPurgeOnShutdown(const GURL& origin);
+
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ struct OriginState {
+ // Indicates that storage for this origin should be purged on shutdown.
+ bool should_purge_on_shutdown = false;
+ // Indicates the last value for `purge_on_shutdown` that was communicated.
+ bool will_purge_on_shutdown = false;
+ };
+ // NOTE: The GURL key is specifically an origin GURL.
+ // Special storage policy uses GURLs and not Origins, so it's simpler
+ // to store everything in GURL form.
+ std::map<GURL, OriginState> origin_state_;
+
+ const ApplyPolicyUpdatesCallback callback_;
+ const scoped_refptr<storage::SpecialStoragePolicy> storage_policy_;
+
+ base::SequenceBound<StoragePolicyObserverIOThread> storage_policy_observer_;
+
+ base::WeakPtrFactory<StoragePolicyObserver> weak_factory_{this};
+};
+
+} // namespace storage
+
+#endif // STORAGE_BROWSER_QUOTA_STORAGE_POLICY_OBSERVER_H_
diff --git a/chromium/storage/browser/quota/usage_tracker.cc b/chromium/storage/browser/quota/usage_tracker.cc
index 698f5e1abd1..af66268abeb 100644
--- a/chromium/storage/browser/quota/usage_tracker.cc
+++ b/chromium/storage/browser/quota/usage_tracker.cc
@@ -235,6 +235,9 @@ void UsageTracker::AccumulateClientHostUsage(base::OnceClosure callback,
case QuotaClientType::kBackgroundFetch:
info->usage_breakdown->backgroundFetch += usage;
break;
+ case QuotaClientType::kNativeIO:
+ info->usage_breakdown->fileSystem += usage;
+ break;
}
std::move(callback).Run();
diff --git a/chromium/storage/browser/quota/usage_tracker.h b/chromium/storage/browser/quota/usage_tracker.h
index 1c019126b5e..a2bdbf4c0b3 100644
--- a/chromium/storage/browser/quota/usage_tracker.h
+++ b/chromium/storage/browser/quota/usage_tracker.h
@@ -33,13 +33,15 @@ class ClientUsageTracker;
// A helper class that gathers and tracks the amount of data stored in
// all quota clients.
//
-// 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.
+// Ownership: Each QuotaManagerImpl 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:
+ // TODO(crbug.com/1163009): Switch the map key type in `client_types` to
+ // mojom::QuotaClient* after all QuotaClients have
+ // been mojofied.
UsageTracker(
const base::flat_map<QuotaClient*, QuotaClientType>& client_types,
blink::mojom::StorageType type,
diff --git a/chromium/storage/common/BUILD.gn b/chromium/storage/common/BUILD.gn
index 5e76c440e76..8fdf0dc0951 100644
--- a/chromium/storage/common/BUILD.gn
+++ b/chromium/storage/common/BUILD.gn
@@ -17,6 +17,8 @@ component("common") {
"file_system/file_system_types.h",
"file_system/file_system_util.cc",
"file_system/file_system_util.h",
+ "quota/padding_key.cc",
+ "quota/padding_key.h",
]
# TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
diff --git a/chromium/storage/common/database/database_identifier.cc b/chromium/storage/common/database/database_identifier.cc
index 26de8fe303b..0de222ada39 100644
--- a/chromium/storage/common/database/database_identifier.cc
+++ b/chromium/storage/common/database/database_identifier.cc
@@ -141,8 +141,8 @@ DatabaseIdentifier DatabaseIdentifier::Parse(const std::string& identifier) {
if (SchemeIsUnique(scheme))
return DatabaseIdentifier();
- base::StringPiece port_str(identifier.begin() + last_underscore + 1,
- identifier.end());
+ auto port_str = base::MakeStringPiece(
+ identifier.begin() + last_underscore + 1, identifier.end());
int port = 0;
if (!base::StringToInt(port_str, &port) || port < 0 || port >= 1 << 16)
return DatabaseIdentifier();
diff --git a/chromium/storage/common/file_system/file_system_types.h b/chromium/storage/common/file_system/file_system_types.h
index 26eac0f475a..c171e0f1ad5 100644
--- a/chromium/storage/common/file_system/file_system_types.h
+++ b/chromium/storage/common/file_system/file_system_types.h
@@ -54,14 +54,13 @@ enum FileSystemType {
// Should be used only for testing.
kFileSystemTypeTest,
- // Indicates a local filesystem where we can access files using native
- // local path.
- kFileSystemTypeNativeLocal,
+ // Indicates a local filesystem where we can access files using local path.
+ kFileSystemTypeLocal,
- // Indicates a local filesystem where we can access files using native
- // local path, but with restricted access.
- // Restricted native local file system is in read-only mode.
- kFileSystemTypeRestrictedNativeLocal,
+ // Indicates a local filesystem where we can access files using local path,
+ // but with restricted access.
+ // Restricted local file system is in read-only mode.
+ kFileSystemTypeRestrictedLocal,
// Indicates a transient, isolated file system for dragged files (which could
// contain multiple dragged paths in the virtual root).
@@ -69,7 +68,7 @@ enum FileSystemType {
// Indicates media filesystem which we can access with same manner to
// regular filesystem.
- kFileSystemTypeNativeMedia,
+ kFileSystemTypeLocalMedia,
// Indicates media filesystem to which we need special protocol to access,
// such as MTP or PTP.
@@ -88,9 +87,9 @@ enum FileSystemType {
// Indicates an external filesystem accessible by file paths from platform
// Apps. As of writing, on non Chrome OS platform, this is merely a
- // kFileSystemTypeNativeLocal. On Chrome OS, the path is parsed by
+ // kFileSystemTypeLocal. On Chrome OS, the path is parsed by
// the handlers of kFileSystemTypeExternal.
- kFileSystemTypeNativeForPlatformApp,
+ kFileSystemTypeLocalForPlatformApp,
// Indicates an isolated filesystem which is supposed to contain one
// temporary which is supposed to go away when the last reference of
diff --git a/chromium/storage/common/file_system/file_system_util.cc b/chromium/storage/common/file_system/file_system_util.cc
index 3bead664f78..77ac0532ea4 100644
--- a/chromium/storage/common/file_system/file_system_util.cc
+++ b/chromium/storage/common/file_system/file_system_util.cc
@@ -282,21 +282,21 @@ std::string GetFileSystemTypeString(FileSystemType type) {
return "External";
case kFileSystemTypeTest:
return "Test";
- case kFileSystemTypeNativeLocal:
- return "NativeLocal";
- case kFileSystemTypeRestrictedNativeLocal:
- return "RestrictedNativeLocal";
+ case kFileSystemTypeLocal:
+ return "Local";
+ case kFileSystemTypeRestrictedLocal:
+ return "RestrictedLocal";
case kFileSystemTypeDragged:
return "Dragged";
- case kFileSystemTypeNativeMedia:
- return "NativeMedia";
+ case kFileSystemTypeLocalMedia:
+ return "LocalMedia";
case kFileSystemTypeDeviceMedia:
return "DeviceMedia";
case kFileSystemTypeSyncable:
case kFileSystemTypeSyncableForInternalSync:
return "Syncable";
- case kFileSystemTypeNativeForPlatformApp:
- return "NativeForPlatformApp";
+ case kFileSystemTypeLocalForPlatformApp:
+ return "LocalForPlatformApp";
case kFileSystemTypeForTransientFile:
return "TransientFile";
case kFileSystemTypePluginPrivate:
@@ -327,16 +327,18 @@ std::string GetFileSystemTypeString(FileSystemType type) {
}
std::string FilePathToString(const base::FilePath& file_path) {
+ // TODO(pkasting): Probably this should use AsUTF8Unsafe() across platforms.
#if defined(OS_WIN)
- return base::UTF16ToUTF8(file_path.value());
+ return file_path.AsUTF8Unsafe();
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
return file_path.value();
#endif
}
base::FilePath StringToFilePath(const std::string& file_path_string) {
+ // TODO(pkasting): Probably this should use FromUTF8Unsafe() across platforms.
#if defined(OS_WIN)
- return base::FilePath(base::UTF8ToUTF16(file_path_string));
+ return base::FilePath::FromUTF8Unsafe(file_path_string);
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
return base::FilePath(file_path_string);
#endif
diff --git a/chromium/storage/browser/quota/padding_key.cc b/chromium/storage/common/quota/padding_key.cc
index 788f6f4634c..14abee0526a 100644
--- a/chromium/storage/browser/quota/padding_key.cc
+++ b/chromium/storage/common/quota/padding_key.cc
@@ -2,14 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "storage/browser/quota/padding_key.h"
+#include "storage/common/quota/padding_key.h"
+#include <inttypes.h>
#include <cstdint>
#include <vector>
-
#include "base/no_destructor.h"
+#include "base/strings/stringprintf.h"
+#include "base/time/time.h"
#include "crypto/hmac.h"
+#include "crypto/random.h"
+#include "crypto/symmetric_key.h"
+#include "net/base/schemeful_site.h"
#include "net/http/http_request_headers.h"
+#include "services/network/public/mojom/url_response_head.mojom-shared.h"
using crypto::SymmetricKey;
@@ -32,53 +38,44 @@ std::unique_ptr<SymmetricKey>* GetPaddingKeyInternal() {
} // namespace
-const SymmetricKey* GetDefaultPaddingKey() {
- return GetPaddingKeyInternal()->get();
-}
-
-std::unique_ptr<SymmetricKey> CopyDefaultPaddingKey() {
- return SymmetricKey::Import(kPaddingKeyAlgorithm,
- (*GetPaddingKeyInternal())->key());
+bool ShouldPadResponseType(network::mojom::FetchResponseType type) {
+ return type == network::mojom::FetchResponseType::kOpaque ||
+ type == network::mojom::FetchResponseType::kOpaqueRedirect;
}
-std::unique_ptr<SymmetricKey> DeserializePaddingKey(
- const std::string& raw_key) {
- return SymmetricKey::Import(kPaddingKeyAlgorithm, raw_key);
+int64_t ComputeRandomResponsePadding() {
+ uint64_t raw_random = 0;
+ crypto::RandBytes(&raw_random, sizeof(uint64_t));
+ return raw_random % kPaddingRange;
}
-std::string SerializeDefaultPaddingKey() {
- return (*GetPaddingKeyInternal())->key();
-}
-
-void ResetPaddingKeyForTesting() {
- *GetPaddingKeyInternal() =
- SymmetricKey::GenerateRandomKey(kPaddingKeyAlgorithm, 128);
-}
-
-int64_t ComputeResponsePadding(const std::string& response_url,
- const crypto::SymmetricKey* padding_key,
- bool has_metadata,
- bool loaded_with_credentials,
- const std::string& request_method) {
+int64_t ComputeStableResponsePadding(const url::Origin& origin,
+ const std::string& response_url,
+ const base::Time& response_time,
+ const std::string& request_method,
+ int64_t side_data_size) {
DCHECK(!response_url.empty());
- crypto::HMAC hmac(crypto::HMAC::SHA256);
- CHECK(hmac.Init(padding_key));
+ net::SchemefulSite site(origin);
- std::string key = response_url;
- if (has_metadata)
- key += "METADATA";
- if (loaded_with_credentials)
- key += "CREDENTIALED";
+ DCHECK_GT(response_time, base::Time::UnixEpoch());
+ int64_t microseconds =
+ (response_time - base::Time::UnixEpoch()).InMicroseconds();
// It should only be possible to have a CORS safelisted method here since
// the spec does not permit other methods for no-cors requests.
DCHECK(request_method == net::HttpRequestHeaders::kGetMethod ||
request_method == net::HttpRequestHeaders::kHeadMethod ||
request_method == net::HttpRequestHeaders::kPostMethod);
- key += request_method;
- uint64_t digest_start;
+ std::string key = base::StringPrintf(
+ "%s-%" PRId64 "-%s-%s-%" PRId64, response_url.c_str(), microseconds,
+ site.Serialize().c_str(), request_method.c_str(), side_data_size);
+
+ crypto::HMAC hmac(crypto::HMAC::SHA256);
+ CHECK(hmac.Init(GetPaddingKeyInternal()->get()));
+
+ uint64_t digest_start = 0;
CHECK(hmac.Sign(key, reinterpret_cast<uint8_t*>(&digest_start),
sizeof(digest_start)));
return digest_start % kPaddingRange;
diff --git a/chromium/storage/common/quota/padding_key.h b/chromium/storage/common/quota/padding_key.h
new file mode 100644
index 00000000000..58e9f0301e3
--- /dev/null
+++ b/chromium/storage/common/quota/padding_key.h
@@ -0,0 +1,51 @@
+// Copyright 2019 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_COMMON_QUOTA_PADDING_KEY_H_
+#define STORAGE_COMMON_QUOTA_PADDING_KEY_H_
+
+#include <memory>
+#include <string>
+
+#include "base/component_export.h"
+#include "services/network/public/mojom/url_response_head.mojom-shared.h"
+#include "url/gurl.h"
+
+namespace base {
+class Time;
+} // namespace base
+
+namespace url {
+class Origin;
+} // namespace url
+
+namespace storage {
+
+// Utility method to determine if a given type of response should be padded.
+COMPONENT_EXPORT(STORAGE_COMMON)
+bool ShouldPadResponseType(network::mojom::FetchResponseType type);
+
+// Compute a purely random padding size for a resource. A random padding is
+// preferred except in cases where a site could rapidly trigger a large number
+// of padded values for the same resource; e.g. from http cache.
+COMPONENT_EXPORT(STORAGE_COMMON)
+int64_t ComputeRandomResponsePadding();
+
+// Compute a stable padding value for a resource. This should be used for
+// cases where a site could trigger a large number of padding values to be
+// generated for the same resource; e.g. http cache. The |origin| is the
+// origin of the context that loaded the resource. Note, its important that the
+// |response_time| be the time stored in the cache and not just the current
+// time. The |side_data_size| should only be passed if padding is being
+// computed for a side data blob.
+COMPONENT_EXPORT(STORAGE_COMMON)
+int64_t ComputeStableResponsePadding(const url::Origin& origin,
+ const std::string& response_url,
+ const base::Time& response_time,
+ const std::string& request_method,
+ int64_t side_data_size = 0);
+
+} // namespace storage
+
+#endif // STORAGE_COMMON_QUOTA_PADDING_KEY_H_