diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/storage | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-c30a6232df03e1efbd9f3b226777b07e087a1122.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/storage')
55 files changed, 1005 insertions, 590 deletions
diff --git a/chromium/storage/DEPS b/chromium/storage/DEPS index 93263a109e9..5f114f4ebc7 100644 --- a/chromium/storage/DEPS +++ b/chromium/storage/DEPS @@ -1,5 +1,6 @@ include_rules = [ "+components/services/filesystem", + "+components/services/storage", "+crypto", "+mojo", "+net", diff --git a/chromium/storage/browser/BUILD.gn b/chromium/storage/browser/BUILD.gn index 4a47ff31e64..25d613e03d1 100644 --- a/chromium/storage/browser/BUILD.gn +++ b/chromium/storage/browser/BUILD.gn @@ -5,18 +5,6 @@ import("//build/config/jumbo.gni") import("//mojo/public/tools/bindings/mojom.gni") import("//testing/test.gni") -mojom("mojom") { - sources = [ "blob/mojom/blob_storage_context.mojom" ] - - public_deps = [ - "//mojo/public/mojom/base", - "//third_party/blink/public/mojom:mojom_core", - ] - - overridden_deps = [ "//third_party/blink/public/mojom:mojom_core" ] - component_deps = [ "//third_party/blink/public/common" ] -} - jumbo_component("browser") { output_name = "storage_browser" sources = [ @@ -227,8 +215,8 @@ jumbo_component("browser") { ] public_deps = [ - ":mojom", "//components/services/filesystem/public/mojom", + "//components/services/storage/public/mojom", "//storage/common", ] deps = [ @@ -328,7 +316,7 @@ source_set("unittests") { ":test_support", "//base/test:test_support", "//components/services/filesystem/public/mojom", - "//mojo/core/embedder", + "//mojo/public/cpp/system", "//net:test_support", "//services/network/public/cpp", "//services/network/public/mojom", @@ -387,8 +375,8 @@ jumbo_static_library("test_support") { deps = [ ":browser", - ":mojom", "//base/test:test_support", + "//components/services/storage/public/mojom", "//net:test_support", "//services/network:network_service", "//testing/gtest", diff --git a/chromium/storage/browser/blob/blob_data_builder.h b/chromium/storage/browser/blob/blob_data_builder.h index 50e0acbe042..a40f4ef4854 100644 --- a/chromium/storage/browser/blob/blob_data_builder.h +++ b/chromium/storage/browser/blob/blob_data_builder.h @@ -16,10 +16,10 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/numerics/checked_math.h" +#include "components/services/storage/public/mojom/blob_storage_context.mojom.h" #include "storage/browser/blob/blob_data_item.h" #include "storage/browser/blob/blob_data_snapshot.h" #include "storage/browser/blob/blob_entry.h" -#include "storage/browser/blob/mojom/blob_storage_context.mojom.h" #include "storage/browser/blob/shareable_blob_data_item.h" #include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/file_system/file_system_context.h" diff --git a/chromium/storage/browser/blob/blob_data_item.h b/chromium/storage/browser/blob/blob_data_item.h index 9ec2e5a9ae0..d40d1edf6c1 100644 --- a/chromium/storage/browser/blob/blob_data_item.h +++ b/chromium/storage/browser/blob/blob_data_item.h @@ -15,8 +15,8 @@ #include "base/containers/span.h" #include "base/files/file_path.h" #include "base/memory/ref_counted.h" +#include "components/services/storage/public/mojom/blob_storage_context.mojom.h" #include "net/base/io_buffer.h" -#include "storage/browser/blob/mojom/blob_storage_context.mojom.h" #include "storage/browser/blob/shareable_file_reference.h" #include "url/gurl.h" diff --git a/chromium/storage/browser/blob/blob_memory_controller.cc b/chromium/storage/browser/blob/blob_memory_controller.cc index e538ce2c181..d5166cc7fdc 100644 --- a/chromium/storage/browser/blob/blob_memory_controller.cc +++ b/chromium/storage/browser/blob/blob_memory_controller.cc @@ -14,6 +14,7 @@ #include "base/callback_helpers.h" #include "base/command_line.h" #include "base/containers/small_map.h" +#include "base/feature_list.h" #include "base/files/file_util.h" #include "base/guid.h" #include "base/location.h" @@ -40,6 +41,13 @@ using base::File; using base::FilePath; namespace storage { + +// static +const base::Feature + BlobMemoryController::kInhibitBlobMemoryControllerMemoryPressureResponse{ + "InhibitBlobMemoryControllerMemoryPressureResponse", + base::FEATURE_DISABLED_BY_DEFAULT}; + namespace { constexpr int64_t kUnknownDiskAvailability = -1ll; constexpr uint64_t kMegabyte = 1024ull * 1024; @@ -535,6 +543,7 @@ BlobMemoryController::BlobMemoryController( populated_memory_items_( base::MRUCache<uint64_t, ShareableBlobDataItem*>::NO_AUTO_EVICT), memory_pressure_listener_( + FROM_HERE, base::BindRepeating(&BlobMemoryController::OnMemoryPressure, base::Unretained(this))) {} @@ -1039,13 +1048,24 @@ void BlobMemoryController::OnEvictionComplete( void BlobMemoryController::OnMemoryPressure( base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { - // TODO(sebmarchand): Check if MEMORY_PRESSURE_LEVEL_MODERATE should also be - // ignored. + // Under critical memory pressure the system is probably already swapping out + // memory and making heavy use of IO. Adding to that is not desirable. + // Furthermore, scheduling a task to write files to disk risks paging-in + // memory that was already committed to disk which compounds the problem. Do + // not take any action on critical memory pressure. if (memory_pressure_level == - base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) { + base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) { return; } + if (base::FeatureList::IsEnabled( + kInhibitBlobMemoryControllerMemoryPressureResponse)) { + return; + } + + // TODO(crbug.com/1087530): Run trial to see if we should get rid of this + // whole intervention or leave it on for MEMORY_PRESSURE_LEVEL_MODERATE. + auto time_from_last_evicion = base::TimeTicks::Now() - last_eviction_time_; if (last_eviction_time_ != base::TimeTicks() && time_from_last_evicion.InSeconds() < kMinSecondsForPressureEvictions) { diff --git a/chromium/storage/browser/blob/blob_memory_controller.h b/chromium/storage/browser/blob/blob_memory_controller.h index 997fd9377f3..1293e42af10 100644 --- a/chromium/storage/browser/blob/blob_memory_controller.h +++ b/chromium/storage/browser/blob/blob_memory_controller.h @@ -20,6 +20,7 @@ #include "base/callback_helpers.h" #include "base/component_export.h" #include "base/containers/mru_cache.h" +#include "base/feature_list.h" #include "base/files/file.h" #include "base/files/file_path.h" #include "base/gtest_prod_util.h" @@ -54,6 +55,8 @@ class ShareableFileReference; // This class can only be interacted with on the IO thread. class COMPONENT_EXPORT(STORAGE_BROWSER) BlobMemoryController { public: + static const base::Feature kInhibitBlobMemoryControllerMemoryPressureResponse; + enum class Strategy { // We don't have enough memory for this blob. TOO_LARGE, diff --git a/chromium/storage/browser/blob/blob_memory_controller_unittest.cc b/chromium/storage/browser/blob/blob_memory_controller_unittest.cc index d376b24df84..89b811e7740 100644 --- a/chromium/storage/browser/blob/blob_memory_controller_unittest.cc +++ b/chromium/storage/browser/blob/blob_memory_controller_unittest.cc @@ -12,6 +12,7 @@ #include "base/system/sys_info.h" #include "base/test/task_environment.h" #include "base/test/test_simple_task_runner.h" +#include "base/test/with_feature_override.h" #include "base/threading/thread_restrictions.h" #include "base/threading/thread_task_runner_handle.h" #include "storage/browser/blob/blob_data_builder.h" @@ -47,9 +48,13 @@ int64_t FakeDiskSpaceMethod(const base::FilePath& path) { return sFakeDiskSpace; } -class BlobMemoryControllerTest : public testing::Test { +class BlobMemoryControllerTest : public base::test::WithFeatureOverride, + public testing::Test { protected: - BlobMemoryControllerTest() = default; + BlobMemoryControllerTest() + : base::test::WithFeatureOverride( + BlobMemoryController:: + kInhibitBlobMemoryControllerMemoryPressureResponse) {} void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); @@ -168,7 +173,7 @@ class BlobMemoryControllerTest : public testing::Test { base::test::SingleThreadTaskEnvironment task_environment_; }; -TEST_F(BlobMemoryControllerTest, Strategy) { +TEST_P(BlobMemoryControllerTest, Strategy) { { BlobMemoryController controller(temp_dir_.GetPath(), nullptr); SetTestMemoryLimits(&controller); @@ -226,7 +231,7 @@ TEST_F(BlobMemoryControllerTest, Strategy) { } } -TEST_F(BlobMemoryControllerTest, GrantMemory) { +TEST_P(BlobMemoryControllerTest, GrantMemory) { const std::string kId = "id"; BlobMemoryController controller(temp_dir_.GetPath(), file_runner_); SetTestMemoryLimits(&controller); @@ -249,7 +254,7 @@ TEST_F(BlobMemoryControllerTest, GrantMemory) { EXPECT_TRUE(HasMemoryAllocation(items[0].get())); } -TEST_F(BlobMemoryControllerTest, SimpleMemoryRequest) { +TEST_P(BlobMemoryControllerTest, SimpleMemoryRequest) { const std::string kId = "id"; BlobMemoryController controller(temp_dir_.GetPath(), file_runner_); SetTestMemoryLimits(&controller); @@ -275,7 +280,7 @@ TEST_F(BlobMemoryControllerTest, SimpleMemoryRequest) { EXPECT_EQ(0u, controller.memory_usage()); } -TEST_F(BlobMemoryControllerTest, PageToDisk) { +TEST_P(BlobMemoryControllerTest, PageToDisk) { const std::string kId = "id"; const std::string kId2 = "id2"; BlobMemoryController controller(temp_dir_.GetPath(), file_runner_); @@ -347,7 +352,7 @@ TEST_F(BlobMemoryControllerTest, PageToDisk) { EXPECT_EQ(0u, controller.disk_usage()); } -TEST_F(BlobMemoryControllerTest, NoDiskTooLarge) { +TEST_P(BlobMemoryControllerTest, NoDiskTooLarge) { BlobMemoryController controller(temp_dir_.GetPath(), nullptr); SetTestMemoryLimits(&controller); @@ -356,14 +361,14 @@ TEST_F(BlobMemoryControllerTest, NoDiskTooLarge) { 1)); } -TEST_F(BlobMemoryControllerTest, TooLargeForDisk) { +TEST_P(BlobMemoryControllerTest, TooLargeForDisk) { BlobMemoryController controller(temp_dir_.GetPath(), file_runner_); SetTestMemoryLimits(&controller); EXPECT_FALSE(controller.CanReserveQuota(kTestBlobStorageMaxDiskSpace + 1)); } -TEST_F(BlobMemoryControllerTest, CancelMemoryRequest) { +TEST_P(BlobMemoryControllerTest, CancelMemoryRequest) { const std::string kId = "id"; const std::string kId2 = "id2"; BlobMemoryController controller(temp_dir_.GetPath(), file_runner_); @@ -423,7 +428,7 @@ TEST_F(BlobMemoryControllerTest, CancelMemoryRequest) { EXPECT_EQ(0u, controller.disk_usage()); } -TEST_F(BlobMemoryControllerTest, FileRequest) { +TEST_P(BlobMemoryControllerTest, FileRequest) { const std::string kId = "id"; const size_t kBlobSize = kTestBlobStorageMaxBlobMemorySize + 1; @@ -479,7 +484,7 @@ TEST_F(BlobMemoryControllerTest, FileRequest) { EXPECT_EQ(0u, controller.disk_usage()); } -TEST_F(BlobMemoryControllerTest, CancelFileRequest) { +TEST_P(BlobMemoryControllerTest, CancelFileRequest) { const std::string kId = "id"; const size_t kBlobSize = kTestBlobStorageMaxBlobMemorySize + 1; @@ -512,7 +517,7 @@ TEST_F(BlobMemoryControllerTest, CancelFileRequest) { base::RunLoop().RunUntilIdle(); } -TEST_F(BlobMemoryControllerTest, MultipleFilesPaged) { +TEST_P(BlobMemoryControllerTest, MultipleFilesPaged) { const std::string kId1 = "id"; const size_t kSize1 = kTestBlobStorageMaxFileSizeBytes; char kData1[kSize1]; @@ -605,7 +610,7 @@ TEST_F(BlobMemoryControllerTest, MultipleFilesPaged) { EXPECT_EQ(0u, controller.disk_usage()); } -TEST_F(BlobMemoryControllerTest, FullEviction) { +TEST_P(BlobMemoryControllerTest, FullEviction) { BlobMemoryController controller(temp_dir_.GetPath(), file_runner_); SetTestMemoryLimits(&controller); AssertEnoughDiskSpace(); @@ -660,7 +665,7 @@ TEST_F(BlobMemoryControllerTest, FullEviction) { EXPECT_TRUE(memory_quota_result_); } -TEST_F(BlobMemoryControllerTest, PagingStopsWhenFull) { +TEST_P(BlobMemoryControllerTest, PagingStopsWhenFull) { BlobMemoryController controller(temp_dir_.GetPath(), file_runner_); SetTestMemoryLimits(&controller); AssertEnoughDiskSpace(); @@ -786,7 +791,7 @@ TEST_F(BlobMemoryControllerTest, PagingStopsWhenFull) { EXPECT_EQ(Strategy::TOO_LARGE, controller.DetermineStrategy(1u, 1ull)); } -TEST_F(BlobMemoryControllerTest, DisableDiskWithFileAndMemoryPending) { +TEST_P(BlobMemoryControllerTest, DisableDiskWithFileAndMemoryPending) { const std::string kFirstMemoryId = "id"; const uint64_t kFirstMemorySize = kTestBlobStorageMaxBlobMemorySize; const std::string kSecondMemoryId = "id2"; @@ -871,7 +876,7 @@ TEST_F(BlobMemoryControllerTest, DisableDiskWithFileAndMemoryPending) { EXPECT_EQ(0ull, controller.memory_usage()); } -TEST_F(BlobMemoryControllerTest, DiskSpaceTooSmallForItem) { +TEST_P(BlobMemoryControllerTest, DiskSpaceTooSmallForItem) { const std::string kFileId = "id2"; const uint64_t kFileBlobSize = kTestBlobStorageMaxBlobMemorySize; @@ -905,7 +910,7 @@ TEST_F(BlobMemoryControllerTest, DiskSpaceTooSmallForItem) { EXPECT_EQ(0ull, controller.memory_usage()); } -TEST_F(BlobMemoryControllerTest, DiskSpaceHitMinAvailable) { +TEST_P(BlobMemoryControllerTest, DiskSpaceHitMinAvailable) { const std::string kFileId = "id2"; const uint64_t kFileBlobSize = kTestBlobStorageMaxBlobMemorySize; @@ -947,7 +952,7 @@ TEST_F(BlobMemoryControllerTest, DiskSpaceHitMinAvailable) { EXPECT_EQ(0ull, controller.memory_usage()); } -TEST_F(BlobMemoryControllerTest, DiskSpaceBeforeMinAvailable) { +TEST_P(BlobMemoryControllerTest, DiskSpaceBeforeMinAvailable) { const std::string kFileId = "id2"; BlobMemoryController controller(temp_dir_.GetPath(), file_runner_); @@ -988,7 +993,7 @@ TEST_F(BlobMemoryControllerTest, DiskSpaceBeforeMinAvailable) { EXPECT_EQ(0ull, controller.memory_usage()); } -TEST_F(BlobMemoryControllerTest, DiskSpaceNearMinAvailable) { +TEST_P(BlobMemoryControllerTest, DiskSpaceNearMinAvailable) { const std::string kFileId = "id2"; BlobMemoryController controller(temp_dir_.GetPath(), file_runner_); @@ -1030,7 +1035,7 @@ TEST_F(BlobMemoryControllerTest, DiskSpaceNearMinAvailable) { EXPECT_EQ(0ull, controller.memory_usage()); } -TEST_F(BlobMemoryControllerTest, DiskSpaceResetAfterIncrease) { +TEST_P(BlobMemoryControllerTest, DiskSpaceResetAfterIncrease) { const std::string kFileId = "id2"; const uint64_t kFileBlobSize = kTestBlobStorageMaxBlobMemorySize; @@ -1098,7 +1103,7 @@ TEST_F(BlobMemoryControllerTest, DiskSpaceResetAfterIncrease) { EXPECT_EQ(0ull, controller.memory_usage()); } -TEST_F(BlobMemoryControllerTest, DiskSpaceUnknown) { +TEST_P(BlobMemoryControllerTest, DiskSpaceUnknown) { const std::string kFileId = "id2"; const uint64_t kFileBlobSize = kTestBlobStorageMaxBlobMemorySize; @@ -1127,7 +1132,7 @@ TEST_F(BlobMemoryControllerTest, DiskSpaceUnknown) { EXPECT_FALSE(controller.limits().IsDiskSpaceConstrained()); } -TEST_F(BlobMemoryControllerTest, OnMemoryPressure) { +TEST_P(BlobMemoryControllerTest, OnMemoryPressure) { BlobMemoryController controller(temp_dir_.GetPath(), file_runner_); SetTestMemoryLimits(&controller); AssertEnoughDiskSpace(); @@ -1154,24 +1159,36 @@ TEST_F(BlobMemoryControllerTest, OnMemoryPressure) { EXPECT_FALSE(file_runner_->HasPendingTask()); EXPECT_EQ(size_to_load, controller.memory_usage()); + const size_t memory_usage_before_eviction = controller.memory_usage(); + const size_t disk_usage_before_eviction = controller.disk_usage(); + controller.OnMemoryPressure( base::MemoryPressureListener::MemoryPressureLevel:: - MEMORY_PRESSURE_LEVEL_CRITICAL); + MEMORY_PRESSURE_LEVEL_MODERATE); - EXPECT_TRUE(file_runner_->HasPendingTask()); - RunFileThreadTasks(); + // Tasks are only posted if the memory pressure response is active. + const bool memory_pressure_response_active = !base::FeatureList::IsEnabled( + BlobMemoryController::kInhibitBlobMemoryControllerMemoryPressureResponse); + EXPECT_EQ(file_runner_->HasPendingTask(), memory_pressure_response_active); - base::RunLoop().RunUntilIdle(); + if (memory_pressure_response_active) { + RunFileThreadTasks(); - // 2 page files of size |kTestBlobStorageMaxBlobMemorySize * - // kTestMaxBlobInMemorySpaceUnderPressureRatio| should be evicted with 1 byte - // left in-memory. - EXPECT_EQ(1u, controller.memory_usage()); - EXPECT_EQ(size_to_load - 1, controller.disk_usage()); - return; + base::RunLoop().RunUntilIdle(); + + // 2 page files of size |kTestBlobStorageMaxBlobMemorySize * + // kTestMaxBlobInMemorySpaceUnderPressureRatio| should be evicted with 1 + // byte left in-memory. + EXPECT_EQ(1u, controller.memory_usage()); + EXPECT_EQ(size_to_load - 1, controller.disk_usage()); + } else { + // No intervention means the memory usage and disk usage is unchanged. + EXPECT_EQ(memory_usage_before_eviction, controller.memory_usage()); + EXPECT_EQ(disk_usage_before_eviction, controller.disk_usage()); + } } -TEST_F(BlobMemoryControllerTest, LowMemoryDevice) { +TEST_P(BlobMemoryControllerTest, LowMemoryDevice) { BlobMemoryController controller(temp_dir_.GetPath(), nullptr); // Make 1% of physical memory size just less than min_page_file_size controller.set_amount_of_physical_memory_for_testing( @@ -1182,4 +1199,6 @@ TEST_F(BlobMemoryControllerTest, LowMemoryDevice) { EXPECT_TRUE(controller.limits().IsValid()); } +INSTANTIATE_FEATURE_OVERRIDE_TEST_SUITE(BlobMemoryControllerTest); + } // namespace storage diff --git a/chromium/storage/browser/blob/blob_registry_impl_unittest.cc b/chromium/storage/browser/blob/blob_registry_impl_unittest.cc index cf58926cb84..3495bcaf310 100644 --- a/chromium/storage/browser/blob/blob_registry_impl_unittest.cc +++ b/chromium/storage/browser/blob/blob_registry_impl_unittest.cc @@ -21,13 +21,13 @@ #include "base/test/bind_test_util.h" #include "base/test/task_environment.h" #include "base/threading/thread_restrictions.h" -#include "mojo/core/embedder/embedder.h" #include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/associated_remote.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "mojo/public/cpp/system/data_pipe_utils.h" +#include "mojo/public/cpp/system/functions.h" #include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_data_handle.h" #include "storage/browser/blob/blob_storage_context.h" @@ -86,7 +86,7 @@ class BlobRegistryImplTest : public testing::Test { registry_impl_->Bind(registry_.BindNewPipeAndPassReceiver(), std::move(delegate)); - mojo::core::SetDefaultProcessErrorCallback(base::BindRepeating( + mojo::SetDefaultProcessErrorHandler(base::BindRepeating( &BlobRegistryImplTest::OnBadMessage, base::Unretained(this))); BlobStorageLimits limits; @@ -107,8 +107,7 @@ class BlobRegistryImplTest : public testing::Test { void TearDown() override { base::ThreadRestrictions::SetIOAllowed(true); - mojo::core::SetDefaultProcessErrorCallback( - mojo::core::ProcessErrorCallback()); + mojo::SetDefaultProcessErrorHandler(base::NullCallback()); } std::unique_ptr<BlobDataHandle> CreateBlobFromString( diff --git a/chromium/storage/browser/blob/blob_storage_context.h b/chromium/storage/browser/blob/blob_storage_context.h index 46297e542ff..575bcd3c129 100644 --- a/chromium/storage/browser/blob/blob_storage_context.h +++ b/chromium/storage/browser/blob/blob_storage_context.h @@ -21,6 +21,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/trace_event/memory_dump_provider.h" +#include "components/services/storage/public/mojom/blob_storage_context.mojom.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver_set.h" @@ -29,7 +30,6 @@ #include "storage/browser/blob/blob_memory_controller.h" #include "storage/browser/blob/blob_storage_constants.h" #include "storage/browser/blob/blob_storage_registry.h" -#include "storage/browser/blob/mojom/blob_storage_context.mojom.h" #include "third_party/blink/public/mojom/blob/blob.mojom.h" class GURL; 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 adb36e3e85d..cc8280fea3a 100644 --- a/chromium/storage/browser/blob/blob_storage_context_mojo_unittest.cc +++ b/chromium/storage/browser/blob/blob_storage_context_mojo_unittest.cc @@ -18,6 +18,7 @@ #include "base/test/task_environment.h" #include "base/test/test_simple_task_runner.h" #include "base/threading/thread_restrictions.h" +#include "components/services/storage/public/mojom/blob_storage_context.mojom.h" #include "mojo/public/cpp/base/big_buffer.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" @@ -26,7 +27,6 @@ #include "net/base/net_errors.h" #include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_impl.h" -#include "storage/browser/blob/mojom/blob_storage_context.mojom.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/blob/blob_utils.h" #include "third_party/blink/public/mojom/blob/blob.mojom.h" diff --git a/chromium/storage/browser/blob/blob_transport_strategy_unittest.cc b/chromium/storage/browser/blob/blob_transport_strategy_unittest.cc index adabe1f3831..b092056823f 100644 --- a/chromium/storage/browser/blob/blob_transport_strategy_unittest.cc +++ b/chromium/storage/browser/blob/blob_transport_strategy_unittest.cc @@ -11,6 +11,7 @@ #include <vector> #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/rand_util.h" @@ -20,8 +21,8 @@ #include "base/task/thread_pool.h" #include "base/test/task_environment.h" #include "base/threading/thread_restrictions.h" -#include "mojo/core/embedder/embedder.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" +#include "mojo/public/cpp/system/functions.h" #include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/test/mock_bytes_provider.h" #include "testing/gtest/include/gtest/gtest.h" @@ -69,7 +70,7 @@ class BlobTransportStrategyTest : public testing::Test { limits_.min_page_file_size = kTestBlobStorageMinFileSizeBytes; limits_.max_file_size = kTestBlobStorageMaxFileSizeBytes; - mojo::core::SetDefaultProcessErrorCallback(base::BindRepeating( + mojo::SetDefaultProcessErrorHandler(base::BindRepeating( &BlobTransportStrategyTest::OnBadMessage, base::Unretained(this))); // Disallow IO on the main loop. @@ -78,9 +79,7 @@ class BlobTransportStrategyTest : public testing::Test { void TearDown() override { base::ThreadRestrictions::SetIOAllowed(true); - - mojo::core::SetDefaultProcessErrorCallback( - mojo::core::ProcessErrorCallback()); + mojo::SetDefaultProcessErrorHandler(base::NullCallback()); } void OnBadMessage(const std::string& error) { diff --git a/chromium/storage/browser/blob/blob_url_loader.cc b/chromium/storage/browser/blob/blob_url_loader.cc index a2e31303d90..6b925d6f5af 100644 --- a/chromium/storage/browser/blob/blob_url_loader.cc +++ b/chromium/storage/browser/blob/blob_url_loader.cc @@ -212,10 +212,10 @@ void BlobURLLoader::HeadersCompleted( std::string mime_type; response->headers->GetMimeType(&mime_type); - // Match logic in StreamURLRequestJob::HeadersCompleted. if (mime_type.empty()) mime_type = "text/plain"; response->mime_type = mime_type; + response->headers->GetCharset(&response->charset); // TODO(jam): some of this code can be shared with // services/network/url_loader.h diff --git a/chromium/storage/browser/blob/blob_url_store_impl_unittest.cc b/chromium/storage/browser/blob/blob_url_store_impl_unittest.cc index 979e675fc51..8bf46428e21 100644 --- a/chromium/storage/browser/blob/blob_url_store_impl_unittest.cc +++ b/chromium/storage/browser/blob/blob_url_store_impl_unittest.cc @@ -5,10 +5,11 @@ #include "storage/browser/blob/blob_url_store_impl.h" #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/test/bind_test_util.h" #include "base/test/task_environment.h" -#include "mojo/core/embedder/embedder.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" +#include "mojo/public/cpp/system/functions.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "services/network/public/cpp/simple_url_loader.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" @@ -27,13 +28,12 @@ class BlobURLStoreImplTest : public testing::Test { void SetUp() override { context_ = std::make_unique<BlobStorageContext>(); - mojo::core::SetDefaultProcessErrorCallback(base::BindRepeating( + mojo::SetDefaultProcessErrorHandler(base::BindRepeating( &BlobURLStoreImplTest::OnBadMessage, base::Unretained(this))); } void TearDown() override { - mojo::core::SetDefaultProcessErrorCallback( - mojo::core::ProcessErrorCallback()); + mojo::SetDefaultProcessErrorHandler(base::NullCallback()); } void OnBadMessage(const std::string& error) { diff --git a/chromium/storage/browser/blob/mojom/OWNERS b/chromium/storage/browser/blob/mojom/OWNERS deleted file mode 100644 index 676a080c626..00000000000 --- a/chromium/storage/browser/blob/mojom/OWNERS +++ /dev/null @@ -1,5 +0,0 @@ -per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS - -# TEAM: storage-dev@chromium.org -# COMPONENT: Blink>Storage>FileAPI diff --git a/chromium/storage/browser/blob/mojom/blob_storage_context.mojom b/chromium/storage/browser/blob/mojom/blob_storage_context.mojom deleted file mode 100644 index 798a1083bfb..00000000000 --- a/chromium/storage/browser/blob/mojom/blob_storage_context.mojom +++ /dev/null @@ -1,88 +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. - -module storage.mojom; - -import "mojo/public/mojom/base/big_buffer.mojom"; -import "mojo/public/mojom/base/file_path.mojom"; -import "mojo/public/mojom/base/time.mojom"; -import "third_party/blink/public/mojom/blob/blob.mojom"; - -// A reader for the data and side data in a cache storage entry. -interface BlobDataItemReader { - // Causes a subrange of the contents of this entry to be written into the - // given data pipe. Returns the net::Error result. - Read(uint64 offset, uint64 length, handle<data_pipe_producer> pipe) - => (int32 success); - // Reads the side-data (if any) associated with this entry. Returns - // a net::Error result and the data, if any. - ReadSideData() => (int32 success, mojo_base.mojom.BigBuffer data); -}; - -// The type of BlobDataItem. Used for histograms. -enum BlobDataItemType { - kUnknown, // Type not known. - kCacheStorage, // Data comes from the cache storage system. - kIndexedDB, // Data comes from the IndexedDB storage system. -}; - -// A remote representation of a BlobDataItem::DataHandle for cache storage. -struct BlobDataItem { - BlobDataItemType type; - - // The size of the normal data. BlobDataItem::DataHandle needs this - // synchronously, which is why it is in a struct and not the interface. - uint64 size; - - // The size of the side data. If this is zero, reader.ReadSideData() - // should not be called, and there is no side data. - uint64 side_data_size; - - // The mime type of this data item. This is empty if unknown. - string content_type; - - // An interface to read the normal and side data of this entry. - pending_remote<BlobDataItemReader> reader; -}; - -// The result of writing a blob to disk. -enum WriteBlobToFileResult { - kError, // There was an error writing the blob to a file. - kBadPath, // The path given is not accessible or has references. - kInvalidBlob, // The blob is invalid and cannot be read. - kIOError, // Error writing bytes on disk. - kTimestampError, // Error writing the last modified timestamp. - kSuccess, -}; - -// This interface is the primary access point to the browser's blob system -// for chrome internals. This interface lives in the browser process. This is a -// simplified version of the blink.mojom.BlobRegistry interface. -// -// This interface has enhanced capabilities that should NOT be accessible to a -// renderer, which is why it is a separate interface. For example, -// WriteBlobToFile writes a blob to an arbitrary file path. -interface BlobStorageContext { - // Create a blob with a particular uuid and consisting of a single - // BlobDataItem::DataHandle constructed from |item|. - RegisterFromDataItem(pending_receiver<blink.mojom.Blob> blob, string uuid, - BlobDataItem item); - // Create a blob with a particular uuid whose contents are contained - // in |data|. - RegisterFromMemory(pending_receiver<blink.mojom.Blob> blob, string uuid, - mojo_base.mojom.BigBuffer data); - - // Writes the given blob to the given file path. If the given |path| is not - // under the blob storage context's profile directory or if it has references - // (like "..") then the implementation returns kBadPath. If the directory - // that contains the file at |path| does not exist, then this function will - // return kIOError. If a file already exists at |path| then it is - // overwritten. If |flush_on_write| is true, then Flush will be called on the - // new file before it is closed. - WriteBlobToFile(pending_remote<blink.mojom.Blob> blob, - mojo_base.mojom.FilePath path, - bool flush_on_write, - mojo_base.mojom.Time? last_modified) - => (WriteBlobToFileResult result); -}; diff --git a/chromium/storage/browser/blob/scoped_file.cc b/chromium/storage/browser/blob/scoped_file.cc index bf2571095c9..b1a01a1e23f 100644 --- a/chromium/storage/browser/blob/scoped_file.cc +++ b/chromium/storage/browser/blob/scoped_file.cc @@ -8,6 +8,7 @@ #include "base/callback.h" #include "base/files/file_util.h" #include "base/location.h" +#include "base/logging.h" #include "base/task_runner.h" #include "base/threading/thread_task_runner_handle.h" @@ -69,8 +70,7 @@ void ScopedFile::Reset() { if (scope_out_policy_ == DELETE_ON_SCOPE_OUT) { file_task_runner_->PostTask( - FROM_HERE, base::BindOnce(base::IgnoreResult(&base::DeleteFile), path_, - false /* recursive */)); + FROM_HERE, base::BindOnce(base::GetDeleteFileCallback(), path_)); } // Clear all fields. diff --git a/chromium/storage/browser/blob/shareable_file_reference.cc b/chromium/storage/browser/blob/shareable_file_reference.cc index 2e0de77611f..c126698482d 100644 --- a/chromium/storage/browser/blob/shareable_file_reference.cc +++ b/chromium/storage/browser/blob/shareable_file_reference.cc @@ -8,6 +8,7 @@ #include <utility> #include "base/lazy_instance.h" +#include "base/logging.h" #include "base/macros.h" #include "base/sequence_checker.h" #include "base/task_runner.h" diff --git a/chromium/storage/browser/blob/write_blob_to_file.h b/chromium/storage/browser/blob/write_blob_to_file.h index 0f0968bc398..2e1e8af3edc 100644 --- a/chromium/storage/browser/blob/write_blob_to_file.h +++ b/chromium/storage/browser/blob/write_blob_to_file.h @@ -8,10 +8,10 @@ #include "base/files/file_path.h" #include "base/optional.h" #include "base/time/time.h" +#include "components/services/storage/public/mojom/blob_storage_context.mojom.h" #include "mojo/public/cpp/bindings/remote.h" #include "storage/browser/blob/blob_data_handle.h" #include "storage/browser/blob/blob_entry.h" -#include "storage/browser/blob/mojom/blob_storage_context.mojom.h" namespace storage { diff --git a/chromium/storage/browser/database/database_quota_client.cc b/chromium/storage/browser/database/database_quota_client.cc index 3d2cd6d6436..1708eaabbee 100644 --- a/chromium/storage/browser/database/database_quota_client.cc +++ b/chromium/storage/browser/database/database_quota_client.cc @@ -98,10 +98,6 @@ DatabaseQuotaClient::~DatabaseQuotaClient() { } } -storage::QuotaClientType DatabaseQuotaClient::type() const { - return storage::QuotaClientType::kDatabase; -} - void DatabaseQuotaClient::OnQuotaManagerDestroyed() {} void DatabaseQuotaClient::GetOriginUsage(const url::Origin& origin, @@ -109,12 +105,7 @@ void DatabaseQuotaClient::GetOriginUsage(const url::Origin& origin, GetUsageCallback callback) { DCHECK(!callback.is_null()); DCHECK(db_tracker_.get()); - - // All databases are in the default bucket. - if (type != StorageType::kTemporary) { - std::move(callback).Run(0); - return; - } + DCHECK_EQ(type, StorageType::kTemporary); base::PostTaskAndReplyWithResult( db_tracker_->task_runner(), FROM_HERE, @@ -127,12 +118,7 @@ void DatabaseQuotaClient::GetOriginsForType(StorageType type, GetOriginsCallback callback) { DCHECK(!callback.is_null()); DCHECK(db_tracker_.get()); - - // All databases are in the default bucket. - if (type != StorageType::kTemporary) { - std::move(callback).Run(std::set<url::Origin>()); - return; - } + DCHECK_EQ(type, StorageType::kTemporary); std::set<url::Origin>* origins_ptr = new std::set<url::Origin>(); db_tracker_->task_runner()->PostTaskAndReply( @@ -148,12 +134,7 @@ void DatabaseQuotaClient::GetOriginsForHost(StorageType type, GetOriginsCallback callback) { DCHECK(!callback.is_null()); DCHECK(db_tracker_.get()); - - // All databases are in the default bucket. - if (type != StorageType::kTemporary) { - std::move(callback).Run(std::set<url::Origin>()); - return; - } + DCHECK_EQ(type, StorageType::kTemporary); std::set<url::Origin>* origins_ptr = new std::set<url::Origin>(); db_tracker_->task_runner()->PostTaskAndReply( @@ -170,12 +151,7 @@ void DatabaseQuotaClient::DeleteOriginData(const url::Origin& origin, DeletionCallback callback) { DCHECK(!callback.is_null()); DCHECK(db_tracker_.get()); - - // All databases are in the default bucket. - if (type != StorageType::kTemporary) { - std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk); - return; - } + DCHECK_EQ(type, StorageType::kTemporary); // DidDeleteOriginData() translates the net::Error response to a // blink::mojom::QuotaStatusCode if necessary, and no-ops as appropriate if @@ -195,11 +171,9 @@ void DatabaseQuotaClient::DeleteOriginData(const url::Origin& origin, void DatabaseQuotaClient::PerformStorageCleanup(blink::mojom::StorageType type, base::OnceClosure callback) { + DCHECK(!callback.is_null()); + DCHECK_EQ(type, StorageType::kTemporary); std::move(callback).Run(); } -bool DatabaseQuotaClient::DoesSupport(StorageType type) const { - return type == StorageType::kTemporary; -} - } // namespace storage diff --git a/chromium/storage/browser/database/database_quota_client.h b/chromium/storage/browser/database/database_quota_client.h index 12375de9b9e..1a64f083786 100644 --- a/chromium/storage/browser/database/database_quota_client.h +++ b/chromium/storage/browser/database/database_quota_client.h @@ -30,7 +30,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseQuotaClient explicit DatabaseQuotaClient(scoped_refptr<DatabaseTracker> tracker); // QuotaClient method overrides - storage::QuotaClientType type() const override; void OnQuotaManagerDestroyed() override; void GetOriginUsage(const url::Origin& origin, blink::mojom::StorageType type, @@ -45,7 +44,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseQuotaClient DeletionCallback callback) override; void PerformStorageCleanup(blink::mojom::StorageType type, base::OnceClosure callback) override; - bool DoesSupport(blink::mojom::StorageType type) const override; private: ~DatabaseQuotaClient() override; diff --git a/chromium/storage/browser/database/database_quota_client_unittest.cc b/chromium/storage/browser/database/database_quota_client_unittest.cc index b14a36dbaf1..d8420694d44 100644 --- a/chromium/storage/browser/database/database_quota_client_unittest.cc +++ b/chromium/storage/browser/database/database_quota_client_unittest.cc @@ -5,6 +5,7 @@ #include <stdint.h> #include <map> +#include <string> #include <utility> #include <vector> @@ -25,14 +26,15 @@ #include "storage/browser/database/database_util.h" #include "storage/common/database/database_identifier.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/mojom/quota/quota_types.mojom.h" +#include "url/gurl.h" +#include "url/origin.h" namespace storage { // Declared to shorten the line lengths. static const blink::mojom::StorageType kTemp = blink::mojom::StorageType::kTemporary; -static const blink::mojom::StorageType kPerm = - blink::mojom::StorageType::kPersistent; // Mock tracker class the mocks up those methods of the tracker // that are used by the QuotaClient. @@ -127,74 +129,75 @@ class DatabaseQuotaClientTest : public testing::Test { : kOriginA(url::Origin::Create(GURL("http://host"))), kOriginB(url::Origin::Create(GURL("http://host:8000"))), kOriginOther(url::Origin::Create(GURL("http://other"))), - usage_(0), mock_tracker_(new MockDatabaseTracker) {} - int64_t GetOriginUsage(scoped_refptr<QuotaClient> client, - const url::Origin& origin, - blink::mojom::StorageType type) { - usage_ = 0; - client->GetOriginUsage( - origin, type, - base::BindOnce(&DatabaseQuotaClientTest::OnGetOriginUsageComplete, - weak_factory_.GetWeakPtr())); - task_environment_.RunUntilIdle(); - return usage_; + static int64_t GetOriginUsage(scoped_refptr<QuotaClient> client, + const url::Origin& origin, + blink::mojom::StorageType type) { + int result = -1; + base::RunLoop loop; + client->GetOriginUsage(origin, type, + base::BindLambdaForTesting([&](int64_t usage) { + result = usage; + loop.Quit(); + })); + loop.Run(); + EXPECT_GT(result, -1); + return result; } - const std::set<url::Origin>& GetOriginsForType( + static std::set<url::Origin> GetOriginsForType( scoped_refptr<QuotaClient> client, blink::mojom::StorageType type) { - origins_.clear(); + std::set<url::Origin> result; + base::RunLoop loop; client->GetOriginsForType( - type, base::BindOnce(&DatabaseQuotaClientTest::OnGetOriginsComplete, - weak_factory_.GetWeakPtr())); - task_environment_.RunUntilIdle(); - return origins_; + type, + base::BindLambdaForTesting([&](const std::set<url::Origin>& origins) { + result = origins; + loop.Quit(); + })); + loop.Run(); + return result; } - const std::set<url::Origin>& GetOriginsForHost( + static std::set<url::Origin> GetOriginsForHost( scoped_refptr<QuotaClient> client, blink::mojom::StorageType type, const std::string& host) { - origins_.clear(); + std::set<url::Origin> result; + base::RunLoop loop; client->GetOriginsForHost( type, host, - base::BindOnce(&DatabaseQuotaClientTest::OnGetOriginsComplete, - weak_factory_.GetWeakPtr())); - task_environment_.RunUntilIdle(); - return origins_; + base::BindLambdaForTesting([&](const std::set<url::Origin>& origins) { + result = origins; + loop.Quit(); + })); + loop.Run(); + return result; } - bool DeleteOriginData(scoped_refptr<QuotaClient> client, - blink::mojom::StorageType type, - const url::Origin& origin) { - delete_status_ = blink::mojom::QuotaStatusCode::kUnknown; + static blink::mojom::QuotaStatusCode DeleteOriginData( + scoped_refptr<QuotaClient> client, + blink::mojom::StorageType type, + const url::Origin& origin) { + blink::mojom::QuotaStatusCode result = + blink::mojom::QuotaStatusCode::kUnknown; + base::RunLoop loop; client->DeleteOriginData( origin, type, - base::BindOnce(&DatabaseQuotaClientTest::OnDeleteOriginDataComplete, - weak_factory_.GetWeakPtr())); - task_environment_.RunUntilIdle(); - return delete_status_ == blink::mojom::QuotaStatusCode::kOk; + base::BindLambdaForTesting([&](blink::mojom::QuotaStatusCode code) { + result = code; + loop.Quit(); + })); + loop.Run(); + return result; } MockDatabaseTracker* mock_tracker() { return mock_tracker_.get(); } private: - void OnGetOriginUsageComplete(int64_t usage) { usage_ = usage; } - - void OnGetOriginsComplete(const std::set<url::Origin>& origins) { - origins_ = origins; - } - - void OnDeleteOriginDataComplete(blink::mojom::QuotaStatusCode status) { - delete_status_ = status; - } - base::test::TaskEnvironment task_environment_; - int64_t usage_; - std::set<url::Origin> origins_; - blink::mojom::QuotaStatusCode delete_status_; scoped_refptr<MockDatabaseTracker> mock_tracker_; base::WeakPtrFactory<DatabaseQuotaClientTest> weak_factory_{this}; }; @@ -203,13 +206,10 @@ TEST_F(DatabaseQuotaClientTest, GetOriginUsage) { auto client = base::MakeRefCounted<DatabaseQuotaClient>(mock_tracker()); EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kTemp)); - EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kPerm)); mock_tracker()->AddMockDatabase(kOriginA, "fooDB", 1000); EXPECT_EQ(1000, GetOriginUsage(client, kOriginA, kTemp)); - EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kPerm)); - EXPECT_EQ(0, GetOriginUsage(client, kOriginB, kPerm)); EXPECT_EQ(0, GetOriginUsage(client, kOriginB, kTemp)); } @@ -234,7 +234,6 @@ TEST_F(DatabaseQuotaClientTest, GetOriginsForHost) { EXPECT_TRUE(origins.find(kOriginA) != origins.end()); EXPECT_TRUE(origins.find(kOriginB) != origins.end()); - EXPECT_TRUE(GetOriginsForHost(client, kPerm, kOriginA.host()).empty()); EXPECT_TRUE(GetOriginsForHost(client, kTemp, kOriginOther.host()).empty()); } @@ -242,30 +241,24 @@ TEST_F(DatabaseQuotaClientTest, GetOriginsForType) { auto client = base::MakeRefCounted<DatabaseQuotaClient>(mock_tracker()); EXPECT_TRUE(GetOriginsForType(client, kTemp).empty()); - EXPECT_TRUE(GetOriginsForType(client, kPerm).empty()); mock_tracker()->AddMockDatabase(kOriginA, "fooDB", 1000); std::set<url::Origin> origins = GetOriginsForType(client, kTemp); EXPECT_EQ(origins.size(), 1ul); EXPECT_TRUE(origins.find(kOriginA) != origins.end()); - - EXPECT_TRUE(GetOriginsForType(client, kPerm).empty()); } TEST_F(DatabaseQuotaClientTest, DeleteOriginData) { auto client = base::MakeRefCounted<DatabaseQuotaClient>(mock_tracker()); - // Perm deletions are short circuited in the Client and - // should not reach the DatabaseTracker. - EXPECT_TRUE(DeleteOriginData(client, kPerm, kOriginA)); - EXPECT_EQ(0, mock_tracker()->delete_called_count()); - mock_tracker()->set_async_delete(false); - EXPECT_TRUE(DeleteOriginData(client, kTemp, kOriginA)); + EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, + DeleteOriginData(client, kTemp, kOriginA)); EXPECT_EQ(1, mock_tracker()->delete_called_count()); mock_tracker()->set_async_delete(true); - EXPECT_TRUE(DeleteOriginData(client, kTemp, kOriginA)); + EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, + DeleteOriginData(client, kTemp, kOriginA)); EXPECT_EQ(2, mock_tracker()->delete_called_count()); } diff --git a/chromium/storage/browser/database/database_tracker.cc b/chromium/storage/browser/database/database_tracker.cc index ecc6a0d2b8e..4f8cfb3eb34 100644 --- a/chromium/storage/browser/database/database_tracker.cc +++ b/chromium/storage/browser/database/database_tracker.cc @@ -22,6 +22,7 @@ #include "storage/browser/database/database_quota_client.h" #include "storage/browser/database/database_util.h" #include "storage/browser/database/databases_table.h" +#include "storage/browser/quota/quota_client_type.h" #include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/quota/special_storage_policy.h" #include "storage/common/database/database_identifier.h" @@ -101,7 +102,8 @@ DatabaseTracker::DatabaseTracker(const base::FilePath& profile_path, base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) { if (quota_manager_proxy) { quota_manager_proxy->RegisterClient( - base::MakeRefCounted<DatabaseQuotaClient>(this)); + base::MakeRefCounted<DatabaseQuotaClient>(this), + QuotaClientType::kDatabase, {blink::mojom::StorageType::kTemporary}); } } diff --git a/chromium/storage/browser/database/database_tracker_unittest.cc b/chromium/storage/browser/database/database_tracker_unittest.cc index 5293254e3fb..4a4edf9174b 100644 --- a/chromium/storage/browser/database/database_tracker_unittest.cc +++ b/chromium/storage/browser/database/database_tracker_unittest.cc @@ -22,6 +22,7 @@ #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" #include "storage/browser/database/database_tracker.h" +#include "storage/browser/quota/quota_client_type.h" #include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/test/mock_special_storage_policy.h" #include "storage/common/database/database_identifier.h" @@ -100,7 +101,10 @@ class TestQuotaManagerProxy : public QuotaManagerProxy { TestQuotaManagerProxy() : QuotaManagerProxy(nullptr, nullptr), registered_client_(nullptr) {} - void RegisterClient(scoped_refptr<QuotaClient> client) override { + void RegisterClient( + scoped_refptr<QuotaClient> client, + QuotaClientType client_type, + const std::vector<blink::mojom::StorageType>& storage_types) override { EXPECT_FALSE(registered_client_); registered_client_ = client; } diff --git a/chromium/storage/browser/file_system/file_stream_reader.h b/chromium/storage/browser/file_system/file_stream_reader.h index b3cfc7f751b..d9ac296c94a 100644 --- a/chromium/storage/browser/file_system/file_stream_reader.h +++ b/chromium/storage/browser/file_system/file_stream_reader.h @@ -60,6 +60,7 @@ class FileStreamReader { // ERR_UPLOAD_FILE_CHANGED error. COMPONENT_EXPORT(STORAGE_BROWSER) static std::unique_ptr<FileStreamReader> CreateForMemoryFile( + scoped_refptr<base::TaskRunner> task_runner, base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util, const base::FilePath& file_path, int64_t initial_offset, diff --git a/chromium/storage/browser/file_system/file_stream_test_utils.cc b/chromium/storage/browser/file_system/file_stream_test_utils.cc index 835a423c9c9..e66dfc716aa 100644 --- a/chromium/storage/browser/file_system/file_stream_test_utils.cc +++ b/chromium/storage/browser/file_system/file_stream_test_utils.cc @@ -40,6 +40,14 @@ void ReadFromReader(FileStreamReader* reader, } } +int64_t GetLengthFromReader(FileStreamReader* reader) { + EXPECT_NE(nullptr, reader); + net::TestInt64CompletionCallback callback; + + int rv = reader->GetLength(callback.callback()); + return callback.GetResult(rv); +} + int WriteStringToWriter(FileStreamWriter* writer, const std::string& data) { scoped_refptr<net::StringIOBuffer> buffer = base::MakeRefCounted<net::StringIOBuffer>(data); diff --git a/chromium/storage/browser/file_system/file_stream_test_utils.h b/chromium/storage/browser/file_system/file_stream_test_utils.h index 5714f7a1e7a..d6425f15af6 100644 --- a/chromium/storage/browser/file_system/file_stream_test_utils.h +++ b/chromium/storage/browser/file_system/file_stream_test_utils.h @@ -20,8 +20,12 @@ void ReadFromReader(FileStreamReader* reader, size_t size, int* result); -// Writes |data| to |writer|, an intialized FileStreamWriter. Returns net::OK if -// successful, otherwise a net error. +// Returns the length of the file if it could be successfully retrieved, +// otherwise a net error. +int64_t GetLengthFromReader(FileStreamReader* reader); + +// Writes |data| to |writer|, an initialized FileStreamWriter. Returns net::OK +// if successful, otherwise a net error. int WriteStringToWriter(FileStreamWriter* writer, const std::string& data); } // namespace storage diff --git a/chromium/storage/browser/file_system/file_stream_writer.h b/chromium/storage/browser/file_system/file_stream_writer.h index 2ddbecc6587..11ce21c64d9 100644 --- a/chromium/storage/browser/file_system/file_stream_writer.h +++ b/chromium/storage/browser/file_system/file_stream_writer.h @@ -48,10 +48,9 @@ class FileStreamWriter { // Creates a writer for the existing memory file in the path |file_path| // starting from |initial_offset|. - // TODO(mek): Remove or use |open_or_create| field here, as it is not - // currently used. https://crbug.com/1041048 COMPONENT_EXPORT(STORAGE_BROWSER) static std::unique_ptr<FileStreamWriter> CreateForMemoryFile( + scoped_refptr<base::TaskRunner> task_runner, base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util, const base::FilePath& file_path, int64_t initial_offset); diff --git a/chromium/storage/browser/file_system/file_system_context.cc b/chromium/storage/browser/file_system/file_system_context.cc index 84774d80b1a..553455ce2f5 100644 --- a/chromium/storage/browser/file_system/file_system_context.cc +++ b/chromium/storage/browser/file_system/file_system_context.cc @@ -40,6 +40,8 @@ #include "storage/browser/quota/special_storage_policy.h" #include "storage/common/file_system/file_system_info.h" #include "storage/common/file_system/file_system_util.h" +#include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h" +#include "third_party/blink/public/mojom/quota/quota_types.mojom.h" #include "third_party/leveldatabase/leveldb_chrome.h" namespace storage { @@ -189,7 +191,8 @@ FileSystemContext::FileSystemContext( if (quota_manager_proxy) { // Quota client assumes all backends have registered. quota_manager_proxy->RegisterClient( - base::MakeRefCounted<FileSystemQuotaClient>(this)); + base::MakeRefCounted<FileSystemQuotaClient>(this), + QuotaClientType::kFileSystem, QuotaManagedStorageTypes()); } sandbox_backend_->Initialize(this); @@ -508,6 +511,27 @@ FileSystemContext::~FileSystemContext() { env_override_.release(); } +std::vector<blink::mojom::StorageType> +FileSystemContext::QuotaManagedStorageTypes() { + std::vector<blink::mojom::StorageType> quota_storage_types; + for (const auto& file_system_type_and_backend : backend_map_) { + FileSystemType file_system_type = file_system_type_and_backend.first; + blink::mojom::StorageType storage_type = + FileSystemTypeToQuotaStorageType(file_system_type); + + // An more elegant way of filtering out non-quota-managed backends would be + // to call GetQuotaUtil() on backends. Unfortunately, the method assumes the + // backends are initialized. + if (storage_type == blink::mojom::StorageType::kUnknown || + storage_type == blink::mojom::StorageType::kQuotaNotManaged) { + continue; + } + + quota_storage_types.push_back(storage_type); + } + return quota_storage_types; +} + FileSystemOperation* FileSystemContext::CreateFileSystemOperation( const FileSystemURL& url, base::File::Error* error_code) { diff --git a/chromium/storage/browser/file_system/file_system_context.h b/chromium/storage/browser/file_system/file_system_context.h index dc900e70f85..1ad6daf3cd1 100644 --- a/chromium/storage/browser/file_system/file_system_context.h +++ b/chromium/storage/browser/file_system/file_system_context.h @@ -26,6 +26,7 @@ #include "storage/browser/file_system/sandbox_file_system_backend_delegate.h" #include "storage/browser/file_system/task_runner_bound_observer_list.h" #include "storage/common/file_system/file_system_types.h" +#include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h" #include "url/gurl.h" #include "url/origin.h" @@ -322,6 +323,12 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemContext friend class base::RefCountedDeleteOnSequence<FileSystemContext>; ~FileSystemContext(); + // The list of quota-managed storage types covered by file system backends. + // + // This is called during the constructor, before the file system backends are + // initialized. + std::vector<blink::mojom::StorageType> QuotaManagedStorageTypes(); + // Creates a new FileSystemOperation instance by getting an appropriate // FileSystemBackend for |url| and calling the backend's corresponding // CreateFileSystemOperation method. diff --git a/chromium/storage/browser/file_system/file_system_file_stream_reader.cc b/chromium/storage/browser/file_system/file_system_file_stream_reader.cc index 8a3b85166bf..9d37b807519 100644 --- a/chromium/storage/browser/file_system/file_system_file_stream_reader.cc +++ b/chromium/storage/browser/file_system/file_system_file_stream_reader.cc @@ -112,6 +112,7 @@ void FileSystemFileStreamReader::DidCreateSnapshot( file_system_context_->sandbox_delegate()->memory_file_util_delegate(); } file_reader_ = FileStreamReader::CreateForMemoryFile( + file_system_context_->default_file_task_runner(), memory_file_util_delegate, platform_path, initial_offset_, expected_modification_time_); } else { 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 66a3007178b..43eb353c08c 100644 --- a/chromium/storage/browser/file_system/file_system_quota_client.cc +++ b/chromium/storage/browser/file_system/file_system_quota_client.cc @@ -96,10 +96,6 @@ FileSystemQuotaClient::FileSystemQuotaClient( FileSystemQuotaClient::~FileSystemQuotaClient() = default; -QuotaClientType FileSystemQuotaClient::type() const { - return QuotaClientType::kFileSystem; -} - void FileSystemQuotaClient::GetOriginUsage(const url::Origin& origin, StorageType storage_type, GetUsageCallback callback) { @@ -176,12 +172,6 @@ void FileSystemQuotaClient::PerformStorageCleanup(StorageType type, std::move(callback)); } -bool FileSystemQuotaClient::DoesSupport(StorageType storage_type) const { - FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type); - DCHECK(type != kFileSystemTypeUnknown); - return file_system_context_->IsSandboxFileSystem(type); -} - base::SequencedTaskRunner* FileSystemQuotaClient::file_task_runner() const { return file_system_context_->default_file_task_runner(); } diff --git a/chromium/storage/browser/file_system/file_system_quota_client.h b/chromium/storage/browser/file_system/file_system_quota_client.h index 01afe9eb2b2..27ddaaed617 100644 --- a/chromium/storage/browser/file_system/file_system_quota_client.h +++ b/chromium/storage/browser/file_system/file_system_quota_client.h @@ -37,7 +37,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemQuotaClient explicit FileSystemQuotaClient(FileSystemContext* file_system_context); // QuotaClient methods. - QuotaClientType type() const override; void OnQuotaManagerDestroyed() override {} void GetOriginUsage(const url::Origin& origin, blink::mojom::StorageType type, @@ -52,7 +51,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemQuotaClient DeletionCallback callback) override; void PerformStorageCleanup(blink::mojom::StorageType type, base::OnceClosure callback) override; - bool DoesSupport(blink::mojom::StorageType type) const override; private: ~FileSystemQuotaClient() override; diff --git a/chromium/storage/browser/file_system/memory_file_stream_reader.cc b/chromium/storage/browser/file_system/memory_file_stream_reader.cc index f5d895c6cc9..0ca229bb8e8 100644 --- a/chromium/storage/browser/file_system/memory_file_stream_reader.cc +++ b/chromium/storage/browser/file_system/memory_file_stream_reader.cc @@ -8,68 +8,114 @@ #include <utility> #include "base/memory/ptr_util.h" +#include "base/task_runner_util.h" +#include "net/base/io_buffer.h" #include "net/base/net_errors.h" namespace storage { std::unique_ptr<FileStreamReader> FileStreamReader::CreateForMemoryFile( + scoped_refptr<base::TaskRunner> task_runner, base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util, const base::FilePath& file_path, int64_t initial_offset, const base::Time& expected_modification_time) { - return base::WrapUnique( - new MemoryFileStreamReader(std::move(memory_file_util), file_path, - initial_offset, expected_modification_time)); + return base::WrapUnique(new MemoryFileStreamReader( + std::move(task_runner), std::move(memory_file_util), file_path, + initial_offset, expected_modification_time)); } MemoryFileStreamReader::MemoryFileStreamReader( + scoped_refptr<base::TaskRunner> task_runner, base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util, const base::FilePath& file_path, int64_t initial_offset, const base::Time& expected_modification_time) : memory_file_util_(std::move(memory_file_util)), + task_runner_(std::move(task_runner)), file_path_(file_path), expected_modification_time_(expected_modification_time), offset_(initial_offset) { - DCHECK(memory_file_util_); + DCHECK(memory_file_util_.MaybeValid()); } MemoryFileStreamReader::~MemoryFileStreamReader() = default; int MemoryFileStreamReader::Read(net::IOBuffer* buf, int buf_len, - net::CompletionOnceCallback /*callback*/) { - base::File::Info file_info; - if (memory_file_util_->GetFileInfo(file_path_, &file_info) != - base::File::FILE_OK) { - return net::ERR_FILE_NOT_FOUND; - } - - if (!FileStreamReader::VerifySnapshotTime(expected_modification_time_, - file_info)) { - return net::ERR_UPLOAD_FILE_CHANGED; - } - - int result = memory_file_util_->ReadFile(file_path_, offset_, buf, buf_len); + net::CompletionOnceCallback callback) { + task_runner_->PostTaskAndReplyWithResult( + FROM_HERE, + base::BindOnce( + [](base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> util, + const base::FilePath& path, base::Time expected_modification_time, + int64_t offset, scoped_refptr<net::IOBuffer> buf, + int buf_len) -> int { + if (!util) + return net::ERR_FILE_NOT_FOUND; + base::File::Info file_info; + if (util->GetFileInfo(path, &file_info) != base::File::FILE_OK) + return net::ERR_FILE_NOT_FOUND; + + if (!FileStreamReader::VerifySnapshotTime( + expected_modification_time, file_info)) { + return net::ERR_UPLOAD_FILE_CHANGED; + } + + return util->ReadFile(path, offset, std::move(buf), buf_len); + }, + memory_file_util_, file_path_, expected_modification_time_, offset_, + base::WrapRefCounted(buf), buf_len), + base::BindOnce(&MemoryFileStreamReader::OnReadCompleted, + weak_factory_.GetWeakPtr(), std::move(callback))); + + return net::ERR_IO_PENDING; +} + +void MemoryFileStreamReader::OnReadCompleted( + net::CompletionOnceCallback callback, + int result) { if (result > 0) offset_ += result; - return result; + + std::move(callback).Run(result); } int64_t MemoryFileStreamReader::GetLength( - net::Int64CompletionOnceCallback /*callback*/) { - base::File::Info file_info; - if (memory_file_util_->GetFileInfo(file_path_, &file_info) != - base::File::FILE_OK) { - return net::ERR_FILE_NOT_FOUND; - } - - if (!FileStreamReader::VerifySnapshotTime(expected_modification_time_, - file_info)) { - return net::ERR_UPLOAD_FILE_CHANGED; - } - - return file_info.size; + net::Int64CompletionOnceCallback callback) { + task_runner_->PostTaskAndReplyWithResult( + FROM_HERE, + base::BindOnce( + [](base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> util, + const base::FilePath& path, + base::Time expected_modification_time) -> int64_t { + if (!util) + return net::ERR_FILE_NOT_FOUND; + base::File::Info file_info; + if (util->GetFileInfo(path, &file_info) != base::File::FILE_OK) { + return net::ERR_FILE_NOT_FOUND; + } + + if (!FileStreamReader::VerifySnapshotTime( + expected_modification_time, file_info)) { + return net::ERR_UPLOAD_FILE_CHANGED; + } + + return file_info.size; + }, + memory_file_util_, file_path_, expected_modification_time_), + // |callback| is not directly used to make sure that it is not called if + // stream is deleted while this function is in flight. + base::BindOnce(&MemoryFileStreamReader::OnGetLengthCompleted, + weak_factory_.GetWeakPtr(), std::move(callback))); + + return net::ERR_IO_PENDING; +} + +void MemoryFileStreamReader::OnGetLengthCompleted( + net::Int64CompletionOnceCallback callback, + int64_t result) { + std::move(callback).Run(result); } } // namespace storage diff --git a/chromium/storage/browser/file_system/memory_file_stream_reader.h b/chromium/storage/browser/file_system/memory_file_stream_reader.h index 909db6b1178..4f05d450522 100644 --- a/chromium/storage/browser/file_system/memory_file_stream_reader.h +++ b/chromium/storage/browser/file_system/memory_file_stream_reader.h @@ -32,17 +32,25 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) MemoryFileStreamReader friend class FileStreamReader; MemoryFileStreamReader( + scoped_refptr<base::TaskRunner> task_runner, base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util, const base::FilePath& file_path, int64_t initial_offset, const base::Time& expected_modification_time); + void OnReadCompleted(net::CompletionOnceCallback callback, int result); + void OnGetLengthCompleted(net::Int64CompletionOnceCallback callback, + int64_t result); + base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util_; + const scoped_refptr<base::TaskRunner> task_runner_; const base::FilePath file_path_; const base::Time expected_modification_time_; int64_t offset_; + base::WeakPtrFactory<MemoryFileStreamReader> weak_factory_{this}; + DISALLOW_COPY_AND_ASSIGN(MemoryFileStreamReader); }; diff --git a/chromium/storage/browser/file_system/memory_file_stream_reader_unittest.cc b/chromium/storage/browser/file_system/memory_file_stream_reader_unittest.cc index 7cbaf6e06f8..99bcfcbeb7e 100644 --- a/chromium/storage/browser/file_system/memory_file_stream_reader_unittest.cc +++ b/chromium/storage/browser/file_system/memory_file_stream_reader_unittest.cc @@ -17,6 +17,7 @@ #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/macros.h" +#include "base/test/task_environment.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "storage/browser/file_system/file_stream_reader.h" @@ -62,9 +63,9 @@ class MemoryFileStreamReaderTest : public testing::Test { const base::FilePath& path, int64_t initial_offset, const base::Time& expected_modification_time) { - return FileStreamReader::CreateForMemoryFile(file_util_->GetWeakPtr(), path, - initial_offset, - expected_modification_time); + return FileStreamReader::CreateForMemoryFile( + base::ThreadTaskRunnerHandle::Get(), file_util_->GetWeakPtr(), path, + initial_offset, expected_modification_time); } void TouchTestFile(base::TimeDelta delta) { @@ -83,6 +84,7 @@ class MemoryFileStreamReaderTest : public testing::Test { } private: + base::test::TaskEnvironment task_environment_; base::ScopedTempDir file_system_directory_; std::unique_ptr<ObfuscatedFileUtilMemoryDelegate> file_util_; base::Time test_file_modification_time_; @@ -113,14 +115,14 @@ TEST_F(MemoryFileStreamReaderTest, Empty) { ASSERT_EQ(net::OK, result); ASSERT_EQ(0U, data.size()); - int64_t length_result = reader->GetLength(base::DoNothing()); + int64_t length_result = GetLengthFromReader(reader.get()); ASSERT_EQ(0, length_result); } TEST_F(MemoryFileStreamReaderTest, GetLengthNormal) { std::unique_ptr<FileStreamReader> reader( CreateFileReader(test_path(), 0, test_file_modification_time())); - int64_t result = reader->GetLength(base::DoNothing()); + int64_t result = GetLengthFromReader(reader.get()); ASSERT_EQ(kTestDataSize, result); } @@ -131,7 +133,7 @@ TEST_F(MemoryFileStreamReaderTest, GetLengthAfterModified) { std::unique_ptr<FileStreamReader> reader( CreateFileReader(test_path(), 0, test_file_modification_time())); - int64_t result = reader->GetLength(base::DoNothing()); + int64_t result = GetLengthFromReader(reader.get()); ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result); } @@ -142,14 +144,14 @@ TEST_F(MemoryFileStreamReaderTest, GetLengthAfterModifiedWithNoExpectedTime) { std::unique_ptr<FileStreamReader> reader( CreateFileReader(test_path(), 0, base::Time())); - int64_t result = reader->GetLength(base::DoNothing()); + int64_t result = GetLengthFromReader(reader.get()); ASSERT_EQ(kTestDataSize, result); } TEST_F(MemoryFileStreamReaderTest, GetLengthWithOffset) { std::unique_ptr<FileStreamReader> reader( CreateFileReader(test_path(), 3, base::Time())); - int64_t result = reader->GetLength(base::DoNothing()); + int64_t result = GetLengthFromReader(reader.get()); // Initial offset does not affect the result of GetLength. ASSERT_EQ(kTestDataSize, result); } diff --git a/chromium/storage/browser/file_system/memory_file_stream_writer.cc b/chromium/storage/browser/file_system/memory_file_stream_writer.cc index 9c421145866..b36c4b5e4bb 100644 --- a/chromium/storage/browser/file_system/memory_file_stream_writer.cc +++ b/chromium/storage/browser/file_system/memory_file_stream_writer.cc @@ -8,43 +8,68 @@ #include <utility> #include "base/memory/ptr_util.h" +#include "base/task_runner_util.h" +#include "net/base/io_buffer.h" #include "net/base/net_errors.h" namespace storage { std::unique_ptr<FileStreamWriter> FileStreamWriter::CreateForMemoryFile( + scoped_refptr<base::TaskRunner> task_runner, base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util, const base::FilePath& file_path, int64_t initial_offset) { return base::WrapUnique(new MemoryFileStreamWriter( - std::move(memory_file_util), file_path, initial_offset)); + std::move(task_runner), std::move(memory_file_util), file_path, + initial_offset)); } MemoryFileStreamWriter::MemoryFileStreamWriter( + scoped_refptr<base::TaskRunner> task_runner, base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util, const base::FilePath& file_path, int64_t initial_offset) : memory_file_util_(std::move(memory_file_util)), + task_runner_(std::move(task_runner)), file_path_(file_path), offset_(initial_offset) { - DCHECK(memory_file_util_); + DCHECK(memory_file_util_.MaybeValid()); } MemoryFileStreamWriter::~MemoryFileStreamWriter() = default; int MemoryFileStreamWriter::Write(net::IOBuffer* buf, int buf_len, - net::CompletionOnceCallback /*callback*/) { - base::File::Info file_info; - if (memory_file_util_->GetFileInfo(file_path_, &file_info) != - base::File::FILE_OK) { - return net::ERR_FILE_NOT_FOUND; - } - - int result = memory_file_util_->WriteFile(file_path_, offset_, buf, buf_len); + net::CompletionOnceCallback callback) { + task_runner_->PostTaskAndReplyWithResult( + FROM_HERE, + base::BindOnce( + [](base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> util, + const base::FilePath& path, int64_t offset, + scoped_refptr<net::IOBuffer> buf, int buf_len) -> int { + if (!util) + return net::ERR_FILE_NOT_FOUND; + base::File::Info file_info; + if (util->GetFileInfo(path, &file_info) != base::File::FILE_OK) + return net::ERR_FILE_NOT_FOUND; + + return util->WriteFile(path, offset, std::move(buf), buf_len); + }, + memory_file_util_, file_path_, offset_, base::WrapRefCounted(buf), + buf_len), + base::BindOnce(&MemoryFileStreamWriter::OnWriteCompleted, + weak_factory_.GetWeakPtr(), std::move(callback))); + + return net::ERR_IO_PENDING; +} + +void MemoryFileStreamWriter::OnWriteCompleted( + net::CompletionOnceCallback callback, + int result) { if (result > 0) offset_ += result; - return result; + + std::move(callback).Run(result); } int MemoryFileStreamWriter::Cancel(net::CompletionOnceCallback /*callback*/) { diff --git a/chromium/storage/browser/file_system/memory_file_stream_writer.h b/chromium/storage/browser/file_system/memory_file_stream_writer.h index fe1c9d17932..74f6213f0f8 100644 --- a/chromium/storage/browser/file_system/memory_file_stream_writer.h +++ b/chromium/storage/browser/file_system/memory_file_stream_writer.h @@ -30,15 +30,21 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) MemoryFileStreamWriter private: friend class FileStreamWriter; MemoryFileStreamWriter( + scoped_refptr<base::TaskRunner> task_runner, base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util, const base::FilePath& file_path, int64_t initial_offset); + void OnWriteCompleted(net::CompletionOnceCallback callback, int result); + base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util_; + const scoped_refptr<base::TaskRunner> task_runner_; const base::FilePath file_path_; int64_t offset_; + base::WeakPtrFactory<MemoryFileStreamWriter> weak_factory_{this}; + DISALLOW_COPY_AND_ASSIGN(MemoryFileStreamWriter); }; diff --git a/chromium/storage/browser/file_system/memory_file_stream_writer_unittest.cc b/chromium/storage/browser/file_system/memory_file_stream_writer_unittest.cc index 7fcda3dfd5e..44342a33c66 100644 --- a/chromium/storage/browser/file_system/memory_file_stream_writer_unittest.cc +++ b/chromium/storage/browser/file_system/memory_file_stream_writer_unittest.cc @@ -13,6 +13,7 @@ #include "base/bind_helpers.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" +#include "base/test/task_environment.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "storage/browser/file_system/file_stream_test_utils.h" @@ -59,11 +60,13 @@ class MemoryFileStreamWriterTest : public testing::Test { std::unique_ptr<FileStreamWriter> CreateWriter(const base::FilePath& path, int64_t offset) { - return FileStreamWriter::CreateForMemoryFile(file_util_->GetWeakPtr(), path, - offset); + return FileStreamWriter::CreateForMemoryFile( + base::ThreadTaskRunnerHandle::Get(), file_util_->GetWeakPtr(), path, + offset); } private: + base::test::TaskEnvironment task_environment_; base::ScopedTempDir file_system_directory_; std::unique_ptr<ObfuscatedFileUtilMemoryDelegate> file_util_; }; 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 5919d1f1c2c..3a3d8563e3c 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 @@ -56,13 +56,17 @@ struct ObfuscatedFileUtilMemoryDelegate::DecomposedPath { ObfuscatedFileUtilMemoryDelegate::ObfuscatedFileUtilMemoryDelegate( const base::FilePath& file_system_directory) : root_(std::make_unique<Entry>(Entry::kDirectory)) { + DETACH_FROM_SEQUENCE(sequence_checker_); file_system_directory.GetComponents(&root_path_components_); } -ObfuscatedFileUtilMemoryDelegate::~ObfuscatedFileUtilMemoryDelegate() = default; +ObfuscatedFileUtilMemoryDelegate::~ObfuscatedFileUtilMemoryDelegate() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} base::Optional<ObfuscatedFileUtilMemoryDelegate::DecomposedPath> ObfuscatedFileUtilMemoryDelegate::ParsePath(const base::FilePath& path) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DecomposedPath dp; path.GetComponents(&dp.components); @@ -118,6 +122,7 @@ ObfuscatedFileUtilMemoryDelegate::ParsePath(const base::FilePath& path) { bool ObfuscatedFileUtilMemoryDelegate::DirectoryExists( const base::FilePath& path) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::Optional<DecomposedPath> dp = ParsePath(path); return dp && dp->entry && dp->entry->type == Entry::kDirectory; } @@ -126,6 +131,7 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::CreateDirectory( const base::FilePath& path, bool exclusive, bool recursive) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::Optional<DecomposedPath> dp = ParsePath(path); if (!dp) return base::File::FILE_ERROR_NOT_FOUND; @@ -169,6 +175,7 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::CreateDirectory( bool ObfuscatedFileUtilMemoryDelegate::DeleteFileOrDirectory( const base::FilePath& path, bool recursive) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::Optional<DecomposedPath> dp = ParsePath(path); if (!dp) return false; @@ -185,11 +192,13 @@ bool ObfuscatedFileUtilMemoryDelegate::DeleteFileOrDirectory( } bool ObfuscatedFileUtilMemoryDelegate::IsLink(const base::FilePath& file_path) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // In-memory file system does not support links. return false; } bool ObfuscatedFileUtilMemoryDelegate::PathExists(const base::FilePath& path) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::Optional<DecomposedPath> dp = ParsePath(path); return dp && dp->entry; } @@ -197,6 +206,7 @@ bool ObfuscatedFileUtilMemoryDelegate::PathExists(const base::FilePath& path) { base::File ObfuscatedFileUtilMemoryDelegate::CreateOrOpen( const base::FilePath& path, int file_flags) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // TODO:(https://crbug.com/936722): Once the output of this function is // changed to base::File::Error, it can use CreateOrOpenInternal to perform // the task and return the result. @@ -206,6 +216,7 @@ base::File ObfuscatedFileUtilMemoryDelegate::CreateOrOpen( void ObfuscatedFileUtilMemoryDelegate::CreateOrOpenInternal( const DecomposedPath& dp, int file_flags) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!dp.entry) { dp.parent->directory_content.emplace(dp.components.back(), Entry::kFile); return; @@ -221,6 +232,7 @@ void ObfuscatedFileUtilMemoryDelegate::CreateOrOpenInternal( base::File::Error ObfuscatedFileUtilMemoryDelegate::DeleteFile( const base::FilePath& path) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::Optional<DecomposedPath> dp = ParsePath(path); if (!dp || !dp->entry) return base::File::FILE_ERROR_NOT_FOUND; @@ -235,6 +247,7 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::DeleteFile( base::File::Error ObfuscatedFileUtilMemoryDelegate::EnsureFileExists( const base::FilePath& path, bool* created) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::Optional<DecomposedPath> dp = ParsePath(path); *created = false; if (!dp || !dp->parent) @@ -253,6 +266,7 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::EnsureFileExists( base::File::Error ObfuscatedFileUtilMemoryDelegate::GetFileInfo( const base::FilePath& path, base::File::Info* file_info) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::Optional<DecomposedPath> dp = ParsePath(path); if (!dp || !dp->entry) return base::File::FILE_ERROR_NOT_FOUND; @@ -272,6 +286,7 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::Touch( const base::FilePath& path, const base::Time& last_access_time, const base::Time& last_modified_time) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::Optional<DecomposedPath> dp = ParsePath(path); if (!dp || !dp->entry) return base::File::FILE_ERROR_FAILED; @@ -285,6 +300,7 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::Touch( base::File::Error ObfuscatedFileUtilMemoryDelegate::Truncate( const base::FilePath& path, int64_t length) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::Optional<DecomposedPath> dp = ParsePath(path); if (!dp || !dp->entry || dp->entry->type != Entry::kFile) return base::File::FILE_ERROR_NOT_FOUND; @@ -297,6 +313,7 @@ NativeFileUtil::CopyOrMoveMode ObfuscatedFileUtilMemoryDelegate::CopyOrMoveModeForDestination( const FileSystemURL& /*dest_url*/, bool copy) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return copy ? NativeFileUtil::CopyOrMoveMode::COPY_SYNC : NativeFileUtil::CopyOrMoveMode::MOVE; } @@ -306,6 +323,7 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::CopyOrMoveFile( const base::FilePath& dest_path, FileSystemOperation::CopyOrMoveOption option, NativeFileUtil::CopyOrMoveMode mode) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::Optional<DecomposedPath> src_dp = ParsePath(src_path); base::Optional<DecomposedPath> dest_dp = ParsePath(dest_path); @@ -361,6 +379,7 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::CopyOrMoveFile( bool ObfuscatedFileUtilMemoryDelegate::MoveDirectoryInternal( const DecomposedPath& src_dp, const DecomposedPath& dest_dp) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(src_dp.entry->type == Entry::kDirectory); if (!dest_dp.entry) { dest_dp.parent->directory_content.insert( @@ -379,6 +398,7 @@ bool ObfuscatedFileUtilMemoryDelegate::CopyOrMoveFileInternal( const DecomposedPath& src_dp, const DecomposedPath& dest_dp, bool move) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(src_dp.entry->type == Entry::kFile); if (dest_dp.entry) dest_dp.parent->directory_content.erase(dest_dp.components.back()); @@ -404,6 +424,7 @@ bool ObfuscatedFileUtilMemoryDelegate::CopyOrMoveFileInternal( size_t ObfuscatedFileUtilMemoryDelegate::ComputeDirectorySize( const base::FilePath& path) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::Optional<DecomposedPath> dp = ParsePath(path); if (!dp || !dp->entry || dp->entry->type != Entry::kDirectory) return 0; @@ -427,8 +448,9 @@ size_t ObfuscatedFileUtilMemoryDelegate::ComputeDirectorySize( int ObfuscatedFileUtilMemoryDelegate::ReadFile(const base::FilePath& path, int64_t offset, - net::IOBuffer* buf, + scoped_refptr<net::IOBuffer> buf, int buf_len) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::Optional<DecomposedPath> dp = ParsePath(path); if (!dp || dp->entry->type != Entry::kFile) return net::ERR_FILE_NOT_FOUND; @@ -445,13 +467,15 @@ int ObfuscatedFileUtilMemoryDelegate::ReadFile(const base::FilePath& path, return buf_len; } -int ObfuscatedFileUtilMemoryDelegate::WriteFile(const base::FilePath& path, - int64_t offset, - net::IOBuffer* buf, - int buf_len) { +int ObfuscatedFileUtilMemoryDelegate::WriteFile( + const base::FilePath& path, + int64_t offset, + scoped_refptr<net::IOBuffer> buf, + int buf_len) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::Optional<DecomposedPath> dp = ParsePath(path); - if (!dp || dp->entry->type != Entry::kFile) + if (!dp || !dp->entry || dp->entry->type != Entry::kFile) return net::ERR_FILE_NOT_FOUND; size_t offset_u = static_cast<size_t>(offset); @@ -479,6 +503,7 @@ int ObfuscatedFileUtilMemoryDelegate::WriteFile(const base::FilePath& path, base::File::Error ObfuscatedFileUtilMemoryDelegate::CreateFileForTesting( const base::FilePath& path, base::span<const char> content) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); bool created; base::File::Error result = EnsureFileExists(path, &created); if (result != base::File::FILE_OK) @@ -498,6 +523,7 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::CopyInForeignFile( const base::FilePath& dest_path, FileSystemOperation::CopyOrMoveOption /* option */, NativeFileUtil::CopyOrMoveMode /* mode */) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::Optional<DecomposedPath> dest_dp = ParsePath(dest_path); if (!dest_dp || !dest_dp->parent) diff --git a/chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate.h b/chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate.h index 4dd25b48aff..d1240511303 100644 --- a/chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate.h +++ b/chromium/storage/browser/file_system/obfuscated_file_util_memory_delegate.h @@ -88,7 +88,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) ObfuscatedFileUtilMemoryDelegate // bytes are returned. Otherwise a net::Error value is returned. int ReadFile(const base::FilePath& path, int64_t offset, - net::IOBuffer* buf, + scoped_refptr<net::IOBuffer> buf, int buf_len); // Writes |buf_len| bytes to the file at |path|, starting from |offset|. @@ -96,7 +96,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) ObfuscatedFileUtilMemoryDelegate // net::Error value is returned. int WriteFile(const base::FilePath& path, int64_t offset, - net::IOBuffer* buf, + scoped_refptr<net::IOBuffer> buf, int buf_len); base::File::Error CreateFileForTesting(const base::FilePath& path, @@ -126,6 +126,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) ObfuscatedFileUtilMemoryDelegate const DecomposedPath& dest_dp, bool move); + SEQUENCE_CHECKER(sequence_checker_); + // The root of the directory tree. std::unique_ptr<Entry> root_; diff --git a/chromium/storage/browser/file_system/quota/quota_reservation_buffer.cc b/chromium/storage/browser/file_system/quota/quota_reservation_buffer.cc index 2bc9f1ef757..d413bf53d33 100644 --- a/chromium/storage/browser/file_system/quota/quota_reservation_buffer.cc +++ b/chromium/storage/browser/file_system/quota/quota_reservation_buffer.cc @@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/callback.h" +#include "base/logging.h" #include "base/memory/ptr_util.h" #include "storage/browser/file_system/quota/open_file_handle.h" #include "storage/browser/file_system/quota/open_file_handle_context.h" 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 4e140b60827..ea0c93a6330 100644 --- a/chromium/storage/browser/file_system/sandbox_file_stream_writer.cc +++ b/chromium/storage/browser/file_system/sandbox_file_stream_writer.cc @@ -159,6 +159,7 @@ void SandboxFileStreamWriter::DidCreateSnapshotFile( file_system_context_->sandbox_delegate()->memory_file_util_delegate(); } file_writer_ = FileStreamWriter::CreateForMemoryFile( + file_system_context_->default_file_task_runner(), memory_file_util_delegate, platform_path, initial_offset_); } else { @@ -223,6 +224,10 @@ void SandboxFileStreamWriter::DidWrite(int write_response) { has_pending_operation_ = false; 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()); if (CancelIfRequested()) return; std::move(write_callback_).Run(write_response); diff --git a/chromium/storage/browser/quota/quota_client.h b/chromium/storage/browser/quota/quota_client.h index 642f52ea189..781e987fff1 100644 --- a/chromium/storage/browser/quota/quota_client.h +++ b/chromium/storage/browser/quota/quota_client.h @@ -36,8 +36,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaClient using DeletionCallback = base::OnceCallback<void(blink::mojom::QuotaStatusCode status)>; - virtual QuotaClientType type() const = 0; - // Called when the QuotaManager is destroyed. virtual void OnQuotaManagerDestroyed() = 0; @@ -74,8 +72,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaClient virtual void PerformStorageCleanup(blink::mojom::StorageType type, base::OnceClosure callback) = 0; - virtual bool DoesSupport(blink::mojom::StorageType type) const = 0; - protected: friend class RefCountedThreadSafe<QuotaClient>; diff --git a/chromium/storage/browser/quota/quota_client_type.cc b/chromium/storage/browser/quota/quota_client_type.cc index b9e9f62a6af..a2daaa23b5e 100644 --- a/chromium/storage/browser/quota/quota_client_type.cc +++ b/chromium/storage/browser/quota/quota_client_type.cc @@ -9,7 +9,7 @@ namespace storage { const QuotaClientTypes& AllQuotaClientTypes() { - static base::NoDestructor<QuotaClientTypes> all({ + static base::NoDestructor<QuotaClientTypes> all{{ QuotaClientType::kFileSystem, QuotaClientType::kDatabase, QuotaClientType::kAppcache, @@ -17,7 +17,7 @@ const QuotaClientTypes& AllQuotaClientTypes() { QuotaClientType::kServiceWorkerCache, QuotaClientType::kServiceWorker, QuotaClientType::kBackgroundFetch, - }); + }}; return *all; } diff --git a/chromium/storage/browser/quota/quota_device_info_helper.h b/chromium/storage/browser/quota/quota_device_info_helper.h index b534d70529c..5a2fdd17e1a 100644 --- a/chromium/storage/browser/quota/quota_device_info_helper.h +++ b/chromium/storage/browser/quota/quota_device_info_helper.h @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/component_export.h" +#include "base/macros.h" #include "base/no_destructor.h" #include "base/system/sys_info.h" diff --git a/chromium/storage/browser/quota/quota_features.cc b/chromium/storage/browser/quota/quota_features.cc index 7e3aae4ef6c..8e47aef9c49 100644 --- a/chromium/storage/browser/quota/quota_features.cc +++ b/chromium/storage/browser/quota/quota_features.cc @@ -17,13 +17,6 @@ constexpr base::FeatureParam<double> kExperimentalPoolSizeRatio{ constexpr base::FeatureParam<double> kPerHostRatio{&kQuotaExpandPoolSize, "PerHostRatio", 0.75}; -// StaticHostQuota enables a simpler per-host quota model, where the quota is -// only based on disk capacity (partition size). When the flag is disabled, the -// quota computation takes into account free disk space, in addition to the -// disk's total capacity. -const base::Feature kStaticHostQuota{"StaticHostQuota", - base::FEATURE_ENABLED_BY_DEFAULT}; - // QuotaUnlimitedPoolSize removes limitations around disk space consumption with // respect to client-side storage web platform APIs. When enabled, quota will // set no limit on how much space a single origin can consume, as well as diff --git a/chromium/storage/browser/quota/quota_features.h b/chromium/storage/browser/quota/quota_features.h index a55c2cb26b6..9ab69a6b955 100644 --- a/chromium/storage/browser/quota/quota_features.h +++ b/chromium/storage/browser/quota/quota_features.h @@ -19,9 +19,6 @@ extern const base::FeatureParam<double> kExperimentalPoolSizeRatio; extern const base::FeatureParam<double> kPerHostRatio; COMPONENT_EXPORT(STORAGE_BROWSER) -extern const base::Feature kStaticHostQuota; - -COMPONENT_EXPORT(STORAGE_BROWSER) extern const base::Feature kQuotaUnlimitedPoolSize; COMPONENT_EXPORT(STORAGE_BROWSER) diff --git a/chromium/storage/browser/quota/quota_manager.cc b/chromium/storage/browser/quota/quota_manager.cc index a84b117d1c1..cc5ff3f632b 100644 --- a/chromium/storage/browser/quota/quota_manager.cc +++ b/chromium/storage/browser/quota/quota_manager.cc @@ -42,6 +42,7 @@ #include "storage/browser/quota/quota_manager_proxy.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; @@ -55,7 +56,7 @@ const int64_t kReportHistogramInterval = 60 * 60 * 1000; // 1 hour // Take action on write errors if there is <= 2% disk space // available. -const double kStoragePressureThresholdRatio = 2; +constexpr double kStoragePressureThresholdPercent = 2; // Limit how frequently QuotaManager polls for free disk space when // only using that information to identify storage pressure. @@ -289,8 +290,6 @@ class QuotaManager::UsageAndQuotaInfoGatherer : public QuotaTask { if (host_quota > temp_pool_free_space) { if (is_unlimited_) { host_quota = available_space_ + host_usage_; - } else if (!base::FeatureList::IsEnabled(features::kStaticHostQuota)) { - host_quota = temp_pool_free_space + host_usage_; } } @@ -548,24 +547,29 @@ class QuotaManager::OriginDataDeleter : public QuotaTask { protected: void Run() override { - error_count_ = 0; - remaining_clients_ = manager()->clients_.size(); - for (const auto& client : manager()->clients_) { - if (quota_client_types_.contains(client->type())) { + 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_type", client_type, "origin", origin_.Serialize()); client->DeleteOriginData( origin_, type_, base::BindOnce(&OriginDataDeleter::DidDeleteOriginData, weak_factory_.GetWeakPtr(), tracing_id)); } else { ++skipped_clients_; - if (--remaining_clients_ == 0) - CallCompleted(); + --remaining_clients_; } } + + if (remaining_clients_ == 0) + CallCompleted(); } void Completed() override { @@ -635,10 +639,11 @@ class QuotaManager::HostDataDeleter : public QuotaTask { protected: void Run() override { - error_count_ = 0; - remaining_clients_ = manager()->clients_.size(); - for (const auto& client : manager()->clients_) { - client->GetOriginsForHost( + 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())); @@ -722,19 +727,24 @@ class QuotaManager::StorageCleanupHelper : public QuotaTask { : QuotaTask(manager), type_(type), quota_client_types_(std::move(quota_client_types)), - callback_(std::move(callback)) {} + 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()->clients_.size(), + 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 : manager()->clients_) { - if (quota_client_types_.contains(client->type())) { + 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(); @@ -1068,7 +1078,9 @@ void QuotaManager::DeleteHostData(const std::string& host, StatusCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); LazyInitialize(); - if (host.empty() || clients_.empty()) { + + DCHECK(client_types_.contains(type)); + if (host.empty() || client_types_[type].empty()) { std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk); return; } @@ -1213,18 +1225,18 @@ bool QuotaManager::ResetUsageTracker(StorageType type) { 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_.reset(new UsageTracker( - clients_, StorageType::kTemporary, special_storage_policy_.get())); + temporary_usage_tracker_ = std::move(usage_tracker); return true; case StorageType::kPersistent: - persistent_usage_tracker_.reset(new UsageTracker( - clients_, StorageType::kPersistent, special_storage_policy_.get())); + persistent_usage_tracker_ = std::move(usage_tracker); return true; case StorageType::kSyncable: - syncable_usage_tracker_.reset(new UsageTracker( - clients_, StorageType::kSyncable, special_storage_policy_.get())); + syncable_usage_tracker_ = std::move(usage_tracker); return true; default: NOTREACHED(); @@ -1234,8 +1246,12 @@ bool QuotaManager::ResetUsageTracker(StorageType type) { QuotaManager::~QuotaManager() { proxy_->manager_ = nullptr; - for (const auto& client : clients_) + + // 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()); } @@ -1253,16 +1269,20 @@ void QuotaManager::LazyInitialize() { return; } - // Use an empty path to open an in-memory only databse for incognito. - database_.reset(new QuotaDatabase(is_incognito_ ? base::FilePath() : - profile_path_.AppendASCII(kDatabaseName))); + // 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_.reset(new UsageTracker( - clients_, StorageType::kTemporary, special_storage_policy_.get())); - persistent_usage_tracker_.reset(new UsageTracker( - clients_, StorageType::kPersistent, special_storage_policy_.get())); - syncable_usage_tracker_.reset(new UsageTracker( - clients_, StorageType::kSyncable, special_storage_policy_.get())); + 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( @@ -1309,10 +1329,18 @@ void QuotaManager::DidBootstrapDatabase( GetLRUOrigin(StorageType::kTemporary, std::move(did_get_origin_callback)); } -void QuotaManager::RegisterClient(scoped_refptr<QuotaClient> client) { +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()); - clients_.push_back(std::move(client)); + 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 { @@ -1409,8 +1437,8 @@ void QuotaManager::StartEviction() { DCHECK(!temporary_storage_evictor_.get()); if (eviction_disabled_) return; - temporary_storage_evictor_.reset(new QuotaTemporaryStorageEvictor( - this, kEvictionIntervalInMilliSeconds)); + temporary_storage_evictor_ = std::make_unique<QuotaTemporaryStorageEvictor>( + this, kEvictionIntervalInMilliSeconds); temporary_storage_evictor_->Start(); } @@ -1451,11 +1479,6 @@ void QuotaManager::DeleteOriginDataInternal(const url::Origin& origin, DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); LazyInitialize(); - if (clients_.empty()) { - std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk); - return; - } - OriginDataDeleter* deleter = new OriginDataDeleter(this, origin, type, std::move(quota_client_types), is_eviction, std::move(callback)); @@ -1477,7 +1500,8 @@ void QuotaManager::MaybeRunStoragePressureCallback(const url::Origin& origin, origin_for_pending_storage_pressure_callback_ = std::move(origin); return; } - if (100 * (available_space / total_space) < kStoragePressureThresholdRatio) { + + if (100 * available_space < kStoragePressureThresholdPercent * total_space) { storage_pressure_callback_.Run(std::move(origin)); } } diff --git a/chromium/storage/browser/quota/quota_manager.h b/chromium/storage/browser/quota/quota_manager.h index 7554d3615d6..5d7458b6046 100644 --- a/chromium/storage/browser/quota/quota_manager.h +++ b/chromium/storage/browser/quota/quota_manager.h @@ -150,36 +150,40 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager blink::mojom::StorageType type, UsageAndQuotaWithBreakdownCallback callback); - // Called by StorageClients. - // This method is declared as virtual to allow test code to override it. + // 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. + // 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 clients via proxy. - // Client storage should call this method when storage is accessed. - // Used to maintain LRU ordering. + // 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 clients via proxy. - // Client storage must call this method whenever they have made any - // modifications that change the amount of data stored in their storage. + // 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 clients via proxy. - // This method is declared as virtual to allow test code to override it. + // 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. @@ -315,10 +319,10 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager StatusCallback evict_origin_data_callback; }; - // This initialization method is 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 RegisterStorage. + // 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, @@ -329,7 +333,10 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager // Called by clients via proxy. // Registers a quota client to the manager. - void RegisterClient(scoped_refptr<QuotaClient> client); + void RegisterClient( + scoped_refptr<QuotaClient> client, + QuotaClientType client_type, + const std::vector<blink::mojom::StorageType>& storage_types); UsageTracker* GetUsageTracker(blink::mojom::StorageType type) const; @@ -455,7 +462,18 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager GetOriginCallback lru_origin_callback_; std::set<url::Origin> access_notified_origins_; - std::vector<scoped_refptr<QuotaClient>> clients_; + // 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_; diff --git a/chromium/storage/browser/quota/quota_manager_proxy.cc b/chromium/storage/browser/quota/quota_manager_proxy.cc index 892566064d7..1cb5cd62b7a 100644 --- a/chromium/storage/browser/quota/quota_manager_proxy.cc +++ b/chromium/storage/browser/quota/quota_manager_proxy.cc @@ -13,6 +13,7 @@ #include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/task_runner_util.h" +#include "storage/browser/quota/quota_client_type.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" namespace storage { @@ -36,18 +37,23 @@ void DidGetUsageAndQuota(base::SequencedTaskRunner* original_task_runner, } // namespace -void QuotaManagerProxy::RegisterClient(scoped_refptr<QuotaClient> client) { +void QuotaManagerProxy::RegisterClient( + scoped_refptr<QuotaClient> client, + QuotaClientType client_type, + const std::vector<blink::mojom::StorageType>& storage_types) { if (!io_thread_->BelongsToCurrentThread() && io_thread_->PostTask( - FROM_HERE, base::BindOnce(&QuotaManagerProxy::RegisterClient, this, - std::move(client)))) { + FROM_HERE, + base::BindOnce(&QuotaManagerProxy::RegisterClient, this, + std::move(client), client_type, storage_types))) { return; } - if (manager_) - manager_->RegisterClient(std::move(client)); - else + if (manager_) { + manager_->RegisterClient(std::move(client), client_type, storage_types); + } else { client->OnQuotaManagerDestroyed(); + } } void QuotaManagerProxy::NotifyStorageAccessed(const url::Origin& origin, diff --git a/chromium/storage/browser/quota/quota_manager_proxy.h b/chromium/storage/browser/quota/quota_manager_proxy.h index 2d1cfee778a..235ee5a784c 100644 --- a/chromium/storage/browser/quota/quota_manager_proxy.h +++ b/chromium/storage/browser/quota/quota_manager_proxy.h @@ -8,6 +8,7 @@ #include <stdint.h> #include <memory> +#include <vector> #include "base/callback.h" #include "base/component_export.h" @@ -18,6 +19,7 @@ #include "base/sequenced_task_runner_helpers.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_task.h" @@ -38,7 +40,10 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerProxy public: using UsageAndQuotaCallback = QuotaManager::UsageAndQuotaCallback; - virtual void RegisterClient(scoped_refptr<QuotaClient> client); + virtual void RegisterClient( + scoped_refptr<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, diff --git a/chromium/storage/browser/quota/quota_manager_unittest.cc b/chromium/storage/browser/quota/quota_manager_unittest.cc index e64135a246c..947c2533ed7 100644 --- a/chromium/storage/browser/quota/quota_manager_unittest.cc +++ b/chromium/storage/browser/quota/quota_manager_unittest.cc @@ -18,6 +18,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" @@ -35,6 +36,7 @@ #include "storage/browser/test/mock_quota_client.h" #include "storage/browser/test/mock_special_storage_policy.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h" #include "url/gurl.h" #include "url/origin.h" @@ -86,7 +88,8 @@ class QuotaManagerTest : public testing::Test { void SetUp() override { ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); - mock_special_storage_policy_ = new MockSpecialStoragePolicy; + mock_special_storage_policy_ = + base::MakeRefCounted<MockSpecialStoragePolicy>(); ResetQuotaManager(false /* is_incognito */); } @@ -98,10 +101,10 @@ class QuotaManagerTest : public testing::Test { protected: void ResetQuotaManager(bool is_incognito) { - quota_manager_ = new QuotaManager(is_incognito, data_dir_.GetPath(), - base::ThreadTaskRunnerHandle::Get().get(), - mock_special_storage_policy_.get(), - GetQuotaSettingsFunc()); + quota_manager_ = base::MakeRefCounted<QuotaManager>( + is_incognito, data_dir_.GetPath(), + base::ThreadTaskRunnerHandle::Get().get(), + mock_special_storage_policy_.get(), GetQuotaSettingsFunc()); SetQuotaSettings(kDefaultPoolSize, kDefaultPerHostQuota, is_incognito ? INT64_C(0) : kMustRemainAvailableForSystem); @@ -112,12 +115,14 @@ class QuotaManagerTest : public testing::Test { additional_callback_count_ = 0; } - MockQuotaClient* CreateAndRegisterClient( + scoped_refptr<MockQuotaClient> CreateAndRegisterClient( base::span<const MockOriginData> mock_data, - QuotaClientType client_type) { - MockQuotaClient* client = - new MockQuotaClient(quota_manager_->proxy(), mock_data, client_type); - quota_manager_->proxy()->RegisterClient(client); + 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; } @@ -421,6 +426,17 @@ class QuotaManagerTest : public testing::Test { void GetUsage_WithModifyTestBody(const StorageType type); + void SetStoragePressureCallback( + base::RepeatingCallback<void(url::Origin)> callback) { + quota_manager_->SetStoragePressureCallback(std::move(callback)); + } + + void MaybeRunStoragePressureCallback(const url::Origin& origin, + int64_t total, + int64_t available) { + quota_manager_->MaybeRunStoragePressureCallback(origin, total, available); + } + void set_additional_callback_count(int c) { additional_callback_count_ = c; } int additional_callback_count() const { return additional_callback_count_; } void DidGetUsageAndQuotaAdditional(QuotaStatusCode status, @@ -522,8 +538,12 @@ TEST_F(QuotaManagerTest, GetUsageInfo) { { "http://bar.com/", kPerm, 40 }, { "http://example.com/", kPerm, 40 }, }; - CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem); - CreateAndRegisterClient(kData2, QuotaClientType::kDatabase); + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); + CreateAndRegisterClient(kData2, QuotaClientType::kDatabase, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); GetUsageInfo(); task_environment_.RunUntilIdle(); @@ -550,7 +570,9 @@ TEST_F(QuotaManagerTest, GetUsageAndQuota_Simple) { { "http://foo.com/", kTemp, 10 }, { "http://foo.com/", kPerm, 80 }, }; - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); task_environment_.RunUntilIdle(); @@ -604,7 +626,9 @@ TEST_F(QuotaManagerTest, GetUsage_NoClient) { TEST_F(QuotaManagerTest, GetUsage_EmptyClient) { CreateAndRegisterClient(base::span<MockOriginData>(), - QuotaClientType::kFileSystem); + QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); @@ -643,7 +667,9 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_MultiOrigins) { { "http://baz.com/", kTemp, 30 }, { "http://foo.com/", kPerm, 40 }, }; - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); // This time explicitly sets a temporary global quota. const int kPoolSize = 100; @@ -680,8 +706,12 @@ TEST_F(QuotaManagerTest, GetUsage_MultipleClients) { }; mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/")); GetStorageCapacity(); - CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem); - CreateAndRegisterClient(kData2, QuotaClientType::kDatabase); + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); + CreateAndRegisterClient(kData2, QuotaClientType::kDatabase, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); const int64_t kPoolSize = GetAvailableDiskSpaceForTest(); const int64_t kPerHostQuota = kPoolSize / 5; @@ -736,9 +766,13 @@ TEST_F(QuotaManagerTest, GetUsageWithBreakdown_Simple) { static const MockOriginData kData3[] = { {"http://foo.com/", kTemp, 8}, }; - CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem); - CreateAndRegisterClient(kData2, QuotaClientType::kDatabase); - CreateAndRegisterClient(kData3, QuotaClientType::kAppcache); + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); + CreateAndRegisterClient(kData2, QuotaClientType::kDatabase, + {blink::mojom::StorageType::kTemporary}); + CreateAndRegisterClient(kData3, QuotaClientType::kAppcache, + {blink::mojom::StorageType::kTemporary}); GetUsageAndQuotaWithBreakdown(ToOrigin("http://foo.com/"), kPerm); task_environment_.RunUntilIdle(); @@ -803,7 +837,9 @@ TEST_F(QuotaManagerTest, GetUsageWithBreakdown_MultiOrigins) { {"http://bar.com/", kTemp, 5}, {"https://bar.com/", kTemp, 7}, {"http://baz.com/", kTemp, 30}, {"http://foo.com/", kPerm, 40}, }; - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); GetUsageAndQuotaWithBreakdown(ToOrigin("http://foo.com/"), kTemp); task_environment_.RunUntilIdle(); @@ -835,8 +871,12 @@ TEST_F(QuotaManagerTest, GetUsageWithBreakdown_MultipleClients) { {"http://unlimited/", kTemp, 512}, }; mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/")); - CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem); - CreateAndRegisterClient(kData2, QuotaClientType::kDatabase); + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); + CreateAndRegisterClient(kData2, QuotaClientType::kDatabase, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); GetUsageAndQuotaWithBreakdown(ToOrigin("http://foo.com/"), kTemp); task_environment_.RunUntilIdle(); @@ -876,8 +916,8 @@ void QuotaManagerTest::GetUsage_WithModifyTestBody(const StorageType type) { { "http://foo.com/", type, 10 }, { "http://foo.com:1/", type, 20 }, }; - MockQuotaClient* client = - CreateAndRegisterClient(data, QuotaClientType::kFileSystem); + scoped_refptr<MockQuotaClient> client = + CreateAndRegisterClient(data, QuotaClientType::kFileSystem, {type}); GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), type); task_environment_.RunUntilIdle(); @@ -917,7 +957,9 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_WithAdditionalTasks) { { "http://bar.com/", kTemp, 13 }, { "http://foo.com/", kPerm, 40 }, }; - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); const int kPoolSize = 100; const int kPerHostQuota = 20; @@ -949,7 +991,9 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_NukeManager) { { "http://bar.com/", kTemp, 13 }, { "http://foo.com/", kPerm, 40 }, }; - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); const int kPoolSize = 100; const int kPerHostQuota = 20; SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem); @@ -974,7 +1018,8 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Overbudget) { { "http://usage10/", kTemp, 10 }, { "http://usage200/", kTemp, 200 }, }; - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary}); const int kPoolSize = 100; const int kPerHostQuota = 20; SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem); @@ -1013,7 +1058,8 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Unlimited) { }; mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/")); GetStorageCapacity(); - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary}); // Test when not overbugdet. const int kPerHostQuotaFor1000 = 200; @@ -1133,7 +1179,9 @@ TEST_F(QuotaManagerTest, OriginInUse) { TEST_F(QuotaManagerTest, GetAndSetPerststentHostQuota) { CreateAndRegisterClient(base::span<MockOriginData>(), - QuotaClientType::kFileSystem); + QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); GetPersistentHostQuota("foo.com"); task_environment_.RunUntilIdle(); @@ -1162,7 +1210,9 @@ TEST_F(QuotaManagerTest, GetAndSetPerststentHostQuota) { TEST_F(QuotaManagerTest, GetAndSetPersistentUsageAndQuota) { GetStorageCapacity(); CreateAndRegisterClient(base::span<MockOriginData>(), - QuotaClientType::kFileSystem); + QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); task_environment_.RunUntilIdle(); @@ -1197,7 +1247,8 @@ TEST_F(QuotaManagerTest, GetQuotaLowAvailableDiskSpace) { {"http://unlimited/", kTemp, 4000000}, }; - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary}); const int kPoolSize = 10000000; const int kPerHostQuota = kPoolSize / 5; @@ -1217,42 +1268,11 @@ TEST_F(QuotaManagerTest, GetQuotaLowAvailableDiskSpace) { EXPECT_EQ(kPerHostQuota, quota()); } -TEST_F(QuotaManagerTest, - GetQuotaLowAvailableDiskSpace_StaticHostQuotaDisabled) { - // This test is the same as the previous but with the kStaticHostQuota Finch - // feature disabled. - // Simulating a low available disk space scenario by making - // kMustRemainAvailable 64KB less than GetAvailableDiskSpaceForTest(), which - // means there is 64KB of storage quota that can be used before triggering - // the low available space logic branch in quota_manager.cc. From the - // perspective of QuotaManager, there are 64KB of free space in the temporary - // pool, so it should return (64KB + usage) as quota since the sum is less - // than the default host quota. - scoped_feature_list_.InitAndDisableFeature(features::kStaticHostQuota); - static const MockOriginData kData[] = { - {"http://foo.com/", kTemp, 100000}, - {"http://unlimited/", kTemp, 4000000}, - }; - - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); - - const int kPoolSize = 10000000; - const int kPerHostQuota = kPoolSize / 5; - const int kMustRemainAvailable = - static_cast<int>(GetAvailableDiskSpaceForTest() - 65536); - SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailable); - - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); - task_environment_.RunUntilIdle(); - EXPECT_EQ(QuotaStatusCode::kOk, status()); - EXPECT_EQ(100000, usage()); - EXPECT_GT(kPerHostQuota, quota()); - EXPECT_EQ(65536 + usage(), quota()); -} - TEST_F(QuotaManagerTest, GetSyncableQuota) { CreateAndRegisterClient(base::span<MockOriginData>(), - QuotaClientType::kFileSystem); + QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kSyncable}); // Pre-condition check: available disk space (for testing) is less than // the default quota for syncable storage. @@ -1284,7 +1304,9 @@ TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_MultiOrigins) { { "http://baz.com/", kPerm, 30 }, { "http://foo.com/", kTemp, 40 }, }; - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); SetPersistentHostQuota("foo.com", 100); GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); @@ -1305,7 +1327,9 @@ TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_WithAdditionalTasks) { { "http://bar.com/", kPerm, 13 }, { "http://foo.com/", kTemp, 40 }, }; - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); SetPersistentHostQuota("foo.com", 100); GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); @@ -1333,7 +1357,9 @@ TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_NukeManager) { { "http://bar.com/", kPerm, 13 }, { "http://foo.com/", kTemp, 40 }, }; - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); SetPersistentHostQuota("foo.com", 100); set_additional_callback_count(0); @@ -1357,7 +1383,9 @@ TEST_F(QuotaManagerTest, GetUsage_Simple) { { "http://bar.com:1/", kPerm, 600000 }, { "http://foo.com/", kTemp, 7000000 }, }; - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); GetGlobalUsage(kPerm); task_environment_.RunUntilIdle(); @@ -1389,8 +1417,10 @@ TEST_F(QuotaManagerTest, GetUsage_WithModification) { { "http://foo.com/", kTemp, 7000000 }, }; - MockQuotaClient* client = - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + scoped_refptr<MockQuotaClient> client = + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); GetGlobalUsage(kPerm); task_environment_.RunUntilIdle(); @@ -1434,8 +1464,10 @@ TEST_F(QuotaManagerTest, GetUsage_WithDeleteOrigin) { { "http://foo.com/", kPerm, 300 }, { "http://bar.com/", kTemp, 4000 }, }; - MockQuotaClient* client = - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + scoped_refptr<MockQuotaClient> client = + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); GetGlobalUsage(kTemp); task_environment_.RunUntilIdle(); @@ -1449,7 +1481,7 @@ TEST_F(QuotaManagerTest, GetUsage_WithDeleteOrigin) { task_environment_.RunUntilIdle(); int64_t predelete_host_pers = usage(); - DeleteClientOriginData(client, ToOrigin("http://foo.com/"), kTemp); + DeleteClientOriginData(client.get(), ToOrigin("http://foo.com/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); @@ -1487,8 +1519,12 @@ TEST_F(QuotaManagerTest, EvictOriginData) { { "https://foo.com/", kTemp, 80 }, { "http://bar.com/", kTemp, 9 }, }; - CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem); - CreateAndRegisterClient(kData2, QuotaClientType::kDatabase); + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); + CreateAndRegisterClient(kData2, QuotaClientType::kDatabase, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); GetGlobalUsage(kTemp); task_environment_.RunUntilIdle(); @@ -1543,8 +1579,9 @@ TEST_F(QuotaManagerTest, EvictOriginDataHistogram) { }; base::HistogramTester histograms; - MockQuotaClient* client = - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + scoped_refptr<MockQuotaClient> client = + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary}); GetGlobalUsage(kTemp); task_environment_.RunUntilIdle(); @@ -1608,8 +1645,10 @@ TEST_F(QuotaManagerTest, EvictOriginDataWithDeletionError) { { "http://bar.com/", kTemp, 4000 }, }; static const int kNumberOfTemporaryOrigins = 3; - MockQuotaClient* client = - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + scoped_refptr<MockQuotaClient> client = + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); GetGlobalUsage(kTemp); task_environment_.RunUntilIdle(); @@ -1690,7 +1729,9 @@ TEST_F(QuotaManagerTest, GetEvictionRoundInfo) { }; mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/")); - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); const int kPoolSize = 10000000; const int kPerHostQuota = kPoolSize / 5; @@ -1704,11 +1745,19 @@ TEST_F(QuotaManagerTest, GetEvictionRoundInfo) { EXPECT_LE(0, available_space()); } +TEST_F(QuotaManagerTest, DeleteHostDataNoClients) { + DeleteHostData(std::string(), kTemp, AllQuotaClientTypes()); + task_environment_.RunUntilIdle(); + EXPECT_EQ(QuotaStatusCode::kOk, status()); +} + TEST_F(QuotaManagerTest, DeleteHostDataSimple) { static const MockOriginData kData[] = { { "http://foo.com/", kTemp, 1 }, }; - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); GetGlobalUsage(kTemp); task_environment_.RunUntilIdle(); @@ -1769,8 +1818,12 @@ TEST_F(QuotaManagerTest, DeleteHostDataMultiple) { { "https://foo.com/", kTemp, 80 }, { "http://bar.com/", kTemp, 9 }, }; - CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem); - CreateAndRegisterClient(kData2, QuotaClientType::kDatabase); + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); + CreateAndRegisterClient(kData2, QuotaClientType::kDatabase, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); GetGlobalUsage(kTemp); task_environment_.RunUntilIdle(); @@ -1835,6 +1888,101 @@ TEST_F(QuotaManagerTest, DeleteHostDataMultiple) { EXPECT_EQ(predelete_bar_pers, usage()); } +TEST_F(QuotaManagerTest, DeleteHostDataMultipleClientsDifferentTypes) { + static const MockOriginData kData1[] = { + {"http://foo.com/", kPerm, 1}, + {"http://foo.com:1/", kPerm, 10}, + {"http://foo.com/", kTemp, 100}, + {"http://bar.com/", kPerm, 1000}, + }; + static const MockOriginData kData2[] = { + {"http://foo.com/", kTemp, 10000}, + {"http://foo.com:1/", kTemp, 100000}, + {"https://foo.com/", kTemp, 1000000}, + {"http://bar.com/", kTemp, 10000000}, + }; + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); + CreateAndRegisterClient(kData2, QuotaClientType::kDatabase, + {blink::mojom::StorageType::kTemporary}); + + GetGlobalUsage(kTemp); + task_environment_.RunUntilIdle(); + const int64_t predelete_global_tmp = usage(); + + GetHostUsageBreakdown("foo.com", kTemp); + task_environment_.RunUntilIdle(); + const int64_t predelete_foo_tmp = usage(); + + GetHostUsageBreakdown("bar.com", kTemp); + task_environment_.RunUntilIdle(); + const int64_t predelete_bar_tmp = usage(); + + GetGlobalUsage(kPerm); + task_environment_.RunUntilIdle(); + const int64_t predelete_global_pers = usage(); + + GetHostUsageBreakdown("foo.com", kPerm); + task_environment_.RunUntilIdle(); + const int64_t predelete_foo_pers = usage(); + + GetHostUsageBreakdown("bar.com", kPerm); + task_environment_.RunUntilIdle(); + const int64_t predelete_bar_pers = usage(); + + reset_status_callback_count(); + DeleteHostData("foo.com", kPerm, AllQuotaClientTypes()); + DeleteHostData("bar.com", kPerm, AllQuotaClientTypes()); + task_environment_.RunUntilIdle(); + + EXPECT_EQ(2, status_callback_count()); + + DumpOriginInfoTable(); + task_environment_.RunUntilIdle(); + + for (const auto& entry : origin_info_entries()) { + if (entry.type != kTemp) + continue; + + EXPECT_NE(std::string("http://foo.com/"), entry.origin.GetURL().spec()); + EXPECT_NE(std::string("http://foo.com:1/"), entry.origin.GetURL().spec()); + EXPECT_NE(std::string("https://foo.com/"), entry.origin.GetURL().spec()); + EXPECT_NE(std::string("http://bar.com/"), entry.origin.GetURL().spec()); + } + + GetGlobalUsage(kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_global_tmp, usage()); + + GetHostUsageBreakdown("foo.com", kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_foo_tmp, usage()); + + GetHostUsageBreakdown("bar.com", kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_bar_tmp, usage()); + + GetGlobalUsage(kPerm); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_global_pers - (1 + 10 + 1000), usage()); + + GetHostUsageBreakdown("foo.com", kPerm); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_foo_pers - (1 + 10), usage()); + + GetHostUsageBreakdown("bar.com", kPerm); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_bar_pers - 1000, usage()); +} + +TEST_F(QuotaManagerTest, DeleteOriginDataNoClients) { + DeleteOriginData(url::Origin::Create(GURL("http://foo.com/")), kTemp, + AllQuotaClientTypes()); + task_environment_.RunUntilIdle(); + EXPECT_EQ(QuotaStatusCode::kOk, status()); +} + // Single-run DeleteOriginData cases must be well covered by // EvictOriginData tests. TEST_F(QuotaManagerTest, DeleteOriginDataMultiple) { @@ -1851,8 +1999,12 @@ TEST_F(QuotaManagerTest, DeleteOriginDataMultiple) { { "https://foo.com/", kTemp, 80 }, { "http://bar.com/", kTemp, 9 }, }; - CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem); - CreateAndRegisterClient(kData2, QuotaClientType::kDatabase); + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); + CreateAndRegisterClient(kData2, QuotaClientType::kDatabase, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); GetGlobalUsage(kTemp); task_environment_.RunUntilIdle(); @@ -1924,6 +2076,102 @@ TEST_F(QuotaManagerTest, DeleteOriginDataMultiple) { EXPECT_EQ(predelete_bar_pers, usage()); } +TEST_F(QuotaManagerTest, DeleteOriginDataMultipleClientsDifferentTypes) { + static const MockOriginData kData1[] = { + {"http://foo.com/", kPerm, 1}, + {"http://foo.com:1/", kPerm, 10}, + {"http://foo.com/", kTemp, 100}, + {"http://bar.com/", kPerm, 1000}, + }; + static const MockOriginData kData2[] = { + {"http://foo.com/", kTemp, 10000}, + {"http://foo.com:1/", kTemp, 100000}, + {"https://foo.com/", kTemp, 1000000}, + {"http://bar.com/", kTemp, 10000000}, + }; + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); + CreateAndRegisterClient(kData2, QuotaClientType::kDatabase, + {blink::mojom::StorageType::kTemporary}); + + GetGlobalUsage(kTemp); + task_environment_.RunUntilIdle(); + const int64_t predelete_global_tmp = usage(); + + GetHostUsageBreakdown("foo.com", kTemp); + task_environment_.RunUntilIdle(); + const int64_t predelete_foo_tmp = usage(); + + GetHostUsageBreakdown("bar.com", kTemp); + task_environment_.RunUntilIdle(); + const int64_t predelete_bar_tmp = usage(); + + GetGlobalUsage(kPerm); + task_environment_.RunUntilIdle(); + const int64_t predelete_global_pers = usage(); + + GetHostUsageBreakdown("foo.com", kPerm); + task_environment_.RunUntilIdle(); + const int64_t predelete_foo_pers = usage(); + + GetHostUsageBreakdown("bar.com", kPerm); + task_environment_.RunUntilIdle(); + const int64_t predelete_bar_pers = usage(); + + for (const MockOriginData& data : kData1) { + quota_manager()->NotifyStorageAccessed( + url::Origin::Create(GURL(data.origin)), data.type); + } + for (const MockOriginData& data : kData2) { + quota_manager()->NotifyStorageAccessed( + url::Origin::Create(GURL(data.origin)), data.type); + } + task_environment_.RunUntilIdle(); + + reset_status_callback_count(); + DeleteOriginData(ToOrigin("http://foo.com/"), kPerm, AllQuotaClientTypes()); + DeleteOriginData(ToOrigin("http://bar.com/"), kPerm, AllQuotaClientTypes()); + task_environment_.RunUntilIdle(); + + EXPECT_EQ(2, status_callback_count()); + + DumpOriginInfoTable(); + task_environment_.RunUntilIdle(); + + for (const auto& entry : origin_info_entries()) { + if (entry.type != kPerm) + continue; + + EXPECT_NE(std::string("http://foo.com/"), entry.origin.GetURL().spec()); + EXPECT_NE(std::string("http://bar.com/"), entry.origin.GetURL().spec()); + } + + GetGlobalUsage(kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_global_tmp, usage()); + + GetHostUsageBreakdown("foo.com", kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_foo_tmp, usage()); + + GetHostUsageBreakdown("bar.com", kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_bar_tmp, usage()); + + GetGlobalUsage(kPerm); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_global_pers - (1 + 1000), usage()); + + GetHostUsageBreakdown("foo.com", kPerm); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_foo_pers - 1, usage()); + + GetHostUsageBreakdown("bar.com", kPerm); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_bar_pers - 1000, usage()); +} + TEST_F(QuotaManagerTest, GetCachedOrigins) { static const MockOriginData kData[] = { { "http://a.com/", kTemp, 1 }, @@ -1931,7 +2179,9 @@ TEST_F(QuotaManagerTest, GetCachedOrigins) { { "http://b.com/", kPerm, 300 }, { "http://c.com/", kTemp, 4000 }, }; - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); // TODO(kinuko): Be careful when we add cache pruner. @@ -1975,7 +2225,9 @@ TEST_F(QuotaManagerTest, NotifyAndLRUOrigin) { { "http://b.com/", kPerm, 0 }, // persistent { "http://c.com/", kTemp, 0 }, }; - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); GURL origin; GetEvictionOrigin(kTemp); @@ -2013,7 +2265,9 @@ TEST_F(QuotaManagerTest, GetLRUOriginWithOriginInUse) { { "http://b.com/", kPerm, 0 }, // persistent { "http://c.com/", kTemp, 0 }, }; - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); GURL origin; GetEvictionOrigin(kTemp); @@ -2066,8 +2320,10 @@ TEST_F(QuotaManagerTest, GetOriginsModifiedSince) { { "http://b.com/", kPerm, 0 }, // persistent { "http://c.com/", kTemp, 0 }, }; - MockQuotaClient* client = - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + scoped_refptr<MockQuotaClient> client = + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); GetOriginsModifiedSince(kTemp, base::Time()); task_environment_.RunUntilIdle(); @@ -2192,10 +2448,14 @@ TEST_F(QuotaManagerTest, DeleteSpecificClientTypeSingleOrigin) { static const MockOriginData kData4[] = { { "http://foo.com/", kTemp, 8 }, }; - CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem); - CreateAndRegisterClient(kData2, QuotaClientType::kAppcache); - CreateAndRegisterClient(kData3, QuotaClientType::kDatabase); - CreateAndRegisterClient(kData4, QuotaClientType::kIndexedDatabase); + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary}); + CreateAndRegisterClient(kData2, QuotaClientType::kAppcache, + {blink::mojom::StorageType::kTemporary}); + CreateAndRegisterClient(kData3, QuotaClientType::kDatabase, + {blink::mojom::StorageType::kTemporary}); + CreateAndRegisterClient(kData4, QuotaClientType::kIndexedDatabase, + {blink::mojom::StorageType::kTemporary}); GetHostUsage("foo.com", kTemp); task_environment_.RunUntilIdle(); @@ -2243,10 +2503,14 @@ TEST_F(QuotaManagerTest, DeleteSpecificClientTypeSingleHost) { static const MockOriginData kData4[] = { { "http://foo.com:4444/", kTemp, 8 }, }; - CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem); - CreateAndRegisterClient(kData2, QuotaClientType::kAppcache); - CreateAndRegisterClient(kData3, QuotaClientType::kDatabase); - CreateAndRegisterClient(kData4, QuotaClientType::kIndexedDatabase); + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary}); + CreateAndRegisterClient(kData2, QuotaClientType::kAppcache, + {blink::mojom::StorageType::kTemporary}); + CreateAndRegisterClient(kData3, QuotaClientType::kDatabase, + {blink::mojom::StorageType::kTemporary}); + CreateAndRegisterClient(kData4, QuotaClientType::kIndexedDatabase, + {blink::mojom::StorageType::kTemporary}); GetHostUsage("foo.com", kTemp); task_environment_.RunUntilIdle(); @@ -2290,10 +2554,14 @@ TEST_F(QuotaManagerTest, DeleteMultipleClientTypesSingleOrigin) { static const MockOriginData kData4[] = { { "http://foo.com/", kTemp, 8 }, }; - CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem); - CreateAndRegisterClient(kData2, QuotaClientType::kAppcache); - CreateAndRegisterClient(kData3, QuotaClientType::kDatabase); - CreateAndRegisterClient(kData4, QuotaClientType::kIndexedDatabase); + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary}); + CreateAndRegisterClient(kData2, QuotaClientType::kAppcache, + {blink::mojom::StorageType::kTemporary}); + CreateAndRegisterClient(kData3, QuotaClientType::kDatabase, + {blink::mojom::StorageType::kTemporary}); + CreateAndRegisterClient(kData4, QuotaClientType::kIndexedDatabase, + {blink::mojom::StorageType::kTemporary}); GetHostUsage("foo.com", kTemp); task_environment_.RunUntilIdle(); @@ -2328,10 +2596,14 @@ TEST_F(QuotaManagerTest, DeleteMultipleClientTypesSingleHost) { static const MockOriginData kData4[] = { { "http://foo.com:4444/", kTemp, 8 }, }; - CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem); - CreateAndRegisterClient(kData2, QuotaClientType::kAppcache); - CreateAndRegisterClient(kData3, QuotaClientType::kDatabase); - CreateAndRegisterClient(kData4, QuotaClientType::kIndexedDatabase); + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary}); + CreateAndRegisterClient(kData2, QuotaClientType::kAppcache, + {blink::mojom::StorageType::kTemporary}); + CreateAndRegisterClient(kData3, QuotaClientType::kDatabase, + {blink::mojom::StorageType::kTemporary}); + CreateAndRegisterClient(kData4, QuotaClientType::kIndexedDatabase, + {blink::mojom::StorageType::kTemporary}); GetHostUsage("foo.com", kTemp); task_environment_.RunUntilIdle(); @@ -2360,7 +2632,9 @@ TEST_F(QuotaManagerTest, GetUsageAndQuota_Incognito) { { "http://foo.com/", kTemp, 10 }, { "http://foo.com/", kPerm, 80 }, }; - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem); + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); // Query global usage to warmup the usage tracker caching. GetGlobalUsage(kTemp); @@ -2415,4 +2689,22 @@ TEST_F(QuotaManagerTest, GetUsageAndQuota_SessionOnly) { EXPECT_EQ(0, quota()); } +TEST_F(QuotaManagerTest, MaybeRunStoragePressureCallback) { + bool callback_ran = false; + auto cb = base::BindRepeating( + [](bool* callback_ran, url::Origin origin) { *callback_ran = true; }, + &callback_ran); + + SetStoragePressureCallback(std::move(cb)); + + const int64_t kGBytes = 1024 * 1024 * 1024; + MaybeRunStoragePressureCallback(url::Origin(), 100 * kGBytes, 2 * kGBytes); + task_environment_.RunUntilIdle(); + EXPECT_FALSE(callback_ran); + + MaybeRunStoragePressureCallback(url::Origin(), 100 * kGBytes, kGBytes); + task_environment_.RunUntilIdle(); + EXPECT_TRUE(callback_ran); +} + } // namespace storage diff --git a/chromium/storage/browser/quota/usage_tracker.cc b/chromium/storage/browser/quota/usage_tracker.cc index 319dece4680..3ad871707ad 100644 --- a/chromium/storage/browser/quota/usage_tracker.cc +++ b/chromium/storage/browser/quota/usage_tracker.cc @@ -12,6 +12,7 @@ #include "base/barrier_closure.h" #include "base/bind.h" #include "storage/browser/quota/client_usage_tracker.h" +#include "storage/browser/quota/quota_client_type.h" namespace storage { @@ -44,17 +45,21 @@ struct UsageTracker::AccumulateInfo { }; UsageTracker::UsageTracker( - const std::vector<scoped_refptr<QuotaClient>>& clients, + const base::flat_map<QuotaClient*, QuotaClientType>& client_types, blink::mojom::StorageType type, SpecialStoragePolicy* special_storage_policy) : type_(type) { - for (const auto& client : clients) { - if (client->DoesSupport(type)) { - client_tracker_map_[client->type()] = - std::make_unique<ClientUsageTracker>(this, client, type, - special_storage_policy); - } + size_t client_count = 0; + + for (const auto& client_and_type : client_types) { + QuotaClient* client = client_and_type.first; + QuotaClientType client_type = client_and_type.second; + client_tracker_map_[client_type].push_back( + std::make_unique<ClientUsageTracker>(this, client, type, + special_storage_policy)); + ++client_count; } + client_count_ = client_count; } UsageTracker::~UsageTracker() { @@ -86,8 +91,10 @@ void UsageTracker::GetGlobalLimitedUsage(UsageCallback callback) { base::BindRepeating(&UsageTracker::AccumulateClientGlobalLimitedUsage, weak_factory_.GetWeakPtr(), base::Owned(info)); - for (const auto& client_type_and_tracker : client_tracker_map_) - client_type_and_tracker.second->GetGlobalLimitedUsage(accumulator); + for (const auto& client_type_and_trackers : client_tracker_map_) { + for (const auto& client_tracker : client_type_and_trackers.second) + client_tracker->GetGlobalLimitedUsage(accumulator); + } // Fire the sentinel as we've now called GetGlobalUsage for all clients. accumulator.Run(0); @@ -112,8 +119,10 @@ void UsageTracker::GetGlobalUsage(GlobalUsageCallback callback) { base::BindRepeating(&UsageTracker::AccumulateClientGlobalUsage, weak_factory_.GetWeakPtr(), base::Owned(info)); - for (const auto& client_type_and_tracker : client_tracker_map_) - client_type_and_tracker.second->GetGlobalUsage(accumulator); + for (const auto& client_type_and_trackers : client_tracker_map_) { + for (const auto& client_tracker : client_type_and_trackers.second) + client_tracker->GetGlobalUsage(accumulator); + } // Fire the sentinel as we've now called GetGlobalUsage for all clients. accumulator.Run(0, 0); @@ -144,11 +153,13 @@ void UsageTracker::GetHostUsageWithBreakdown( base::BindOnce(&UsageTracker::FinallySendHostUsageWithBreakdown, weak_factory_.GetWeakPtr(), base::Owned(info), host)); - for (const auto& client_type_and_tracker : client_tracker_map_) { - client_type_and_tracker.second->GetHostUsage( - host, base::BindOnce(&UsageTracker::AccumulateClientHostUsage, - weak_factory_.GetWeakPtr(), barrier, info, host, - client_type_and_tracker.first)); + for (const auto& client_type_and_trackers : client_tracker_map_) { + for (const auto& client_tracker : client_type_and_trackers.second) { + client_tracker->GetHostUsage( + host, base::BindOnce(&UsageTracker::AccumulateClientHostUsage, + weak_factory_.GetWeakPtr(), barrier, info, host, + client_type_and_trackers.first)); + } } } @@ -157,26 +168,30 @@ void UsageTracker::UpdateUsageCache(QuotaClientType client_type, int64_t delta) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(client_tracker_map_.count(client_type)); - ClientUsageTracker* client_tracker = client_tracker_map_[client_type].get(); - client_tracker->UpdateUsageCache(origin, delta); + for (const auto& client_tracker : client_tracker_map_[client_type]) + client_tracker->UpdateUsageCache(origin, delta); } int64_t UsageTracker::GetCachedUsage() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); int64_t usage = 0; - for (const auto& client_type_and_tracker : client_tracker_map_) - usage += client_type_and_tracker.second->GetCachedUsage(); + for (const auto& client_type_and_trackers : client_tracker_map_) { + for (const auto& client_tracker : client_type_and_trackers.second) + usage += client_tracker->GetCachedUsage(); + } return usage; } std::map<std::string, int64_t> UsageTracker::GetCachedHostsUsage() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); std::map<std::string, int64_t> host_usage; - for (const auto& client_type_and_tracker : client_tracker_map_) { - std::map<std::string, int64_t> client_host_usage = - client_type_and_tracker.second->GetCachedHostsUsage(); - for (const auto& host_and_usage : client_host_usage) - host_usage[host_and_usage.first] += host_and_usage.second; + for (const auto& client_type_and_trackers : client_tracker_map_) { + for (const auto& client_tracker : client_type_and_trackers.second) { + std::map<std::string, int64_t> client_host_usage = + client_tracker->GetCachedHostsUsage(); + for (const auto& host_and_usage : client_host_usage) + host_usage[host_and_usage.first] += host_and_usage.second; + } } return host_usage; } @@ -184,11 +199,13 @@ std::map<std::string, int64_t> UsageTracker::GetCachedHostsUsage() const { std::map<url::Origin, int64_t> UsageTracker::GetCachedOriginsUsage() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); std::map<url::Origin, int64_t> origin_usage; - for (const auto& client_type_and_tracker : client_tracker_map_) { - std::map<url::Origin, int64_t> client_origin_usage = - client_type_and_tracker.second->GetCachedOriginsUsage(); - for (const auto& origin_and_usage : client_origin_usage) - origin_usage[origin_and_usage.first] += origin_and_usage.second; + for (const auto& client_type_and_trackers : client_tracker_map_) { + for (const auto& client_tracker : client_type_and_trackers.second) { + std::map<url::Origin, int64_t> client_origin_usage = + client_tracker->GetCachedOriginsUsage(); + for (const auto& origin_and_usage : client_origin_usage) + origin_usage[origin_and_usage.first] += origin_and_usage.second; + } } return origin_usage; } @@ -196,11 +213,12 @@ std::map<url::Origin, int64_t> UsageTracker::GetCachedOriginsUsage() const { std::set<url::Origin> UsageTracker::GetCachedOrigins() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); std::set<url::Origin> origins; - for (const auto& client_type_and_tracker : client_tracker_map_) { - std::set<url::Origin> client_origins = - client_type_and_tracker.second->GetCachedOrigins(); - for (const auto& client_origin : client_origins) - origins.insert(client_origin); + for (const auto& client_type_and_trackers : client_tracker_map_) { + for (const auto& client_tracker : client_type_and_trackers.second) { + std::set<url::Origin> client_origins = client_tracker->GetCachedOrigins(); + for (const auto& client_origin : client_origins) + origins.insert(client_origin); + } } return origins; } @@ -210,9 +228,8 @@ void UsageTracker::SetUsageCacheEnabled(QuotaClientType client_type, bool enabled) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(client_tracker_map_.count(client_type)); - ClientUsageTracker* client_tracker = client_tracker_map_[client_type].get(); - - client_tracker->SetUsageCacheEnabled(origin, enabled); + for (const auto& client_tracker : client_tracker_map_[client_type]) + client_tracker->SetUsageCacheEnabled(origin, enabled); } void UsageTracker::AccumulateClientGlobalLimitedUsage(AccumulateInfo* info, diff --git a/chromium/storage/browser/quota/usage_tracker.h b/chromium/storage/browser/quota/usage_tracker.h index dc5446f9eab..aae13835c90 100644 --- a/chromium/storage/browser/quota/usage_tracker.h +++ b/chromium/storage/browser/quota/usage_tracker.h @@ -15,10 +15,12 @@ #include "base/callback.h" #include "base/component_export.h" +#include "base/containers/flat_map.h" #include "base/macros.h" #include "base/sequence_checker.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_task.h" #include "storage/browser/quota/special_storage_policy.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" @@ -38,9 +40,10 @@ class ClientUsageTracker; class COMPONENT_EXPORT(STORAGE_BROWSER) UsageTracker : public QuotaTaskObserver { public: - UsageTracker(const std::vector<scoped_refptr<QuotaClient>>& clients, - blink::mojom::StorageType type, - SpecialStoragePolicy* special_storage_policy); + UsageTracker( + const base::flat_map<QuotaClient*, QuotaClientType>& client_types, + blink::mojom::StorageType type, + SpecialStoragePolicy* special_storage_policy); ~UsageTracker() override; blink::mojom::StorageType type() const { @@ -87,8 +90,10 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) UsageTracker const std::string& host); const blink::mojom::StorageType type_; - std::map<QuotaClientType, std::unique_ptr<ClientUsageTracker>> + base::flat_map<QuotaClientType, + std::vector<std::unique_ptr<ClientUsageTracker>>> client_tracker_map_; + size_t client_count_; std::vector<UsageCallback> global_limited_usage_callbacks_; std::vector<GlobalUsageCallback> global_usage_callbacks_; diff --git a/chromium/storage/browser/quota/usage_tracker_unittest.cc b/chromium/storage/browser/quota/usage_tracker_unittest.cc index 1b07b48c97b..d734070963d 100644 --- a/chromium/storage/browser/quota/usage_tracker_unittest.cc +++ b/chromium/storage/browser/quota/usage_tracker_unittest.cc @@ -48,8 +48,6 @@ class UsageTrackerTestQuotaClient : public QuotaClient { public: UsageTrackerTestQuotaClient() = default; - QuotaClientType type() const override { return QuotaClientType::kFileSystem; } - void OnQuotaManagerDestroyed() override {} void GetOriginUsage(const url::Origin& origin, @@ -98,10 +96,6 @@ class UsageTrackerTestQuotaClient : public QuotaClient { std::move(callback).Run(); } - bool DoesSupport(StorageType type) const override { - return type == StorageType::kTemporary; - } - int64_t GetUsage(const url::Origin& origin) { auto found = origin_usage_map_.find(origin); if (found == origin_usage_map_.end()) @@ -132,7 +126,7 @@ class UsageTrackerTest : public testing::Test { UsageTrackerTest() : storage_policy_(new MockSpecialStoragePolicy()), quota_client_(base::MakeRefCounted<UsageTrackerTestQuotaClient>()), - usage_tracker_(GetUsageTrackerList(), + usage_tracker_(GetQuotaClientMap(), StorageType::kTemporary, storage_policy_.get()) {} @@ -156,7 +150,8 @@ class UsageTrackerTest : public testing::Test { void UpdateUsage(const url::Origin& origin, int64_t delta) { quota_client_->UpdateUsage(origin, delta); - usage_tracker_.UpdateUsageCache(quota_client_->type(), origin, delta); + usage_tracker_.UpdateUsageCache(QuotaClientType::kFileSystem, origin, + delta); base::RunLoop().RunUntilIdle(); } @@ -223,14 +218,16 @@ class UsageTrackerTest : public testing::Test { } void SetUsageCacheEnabled(const url::Origin& origin, bool enabled) { - usage_tracker_.SetUsageCacheEnabled(quota_client_->type(), origin, enabled); + usage_tracker_.SetUsageCacheEnabled(QuotaClientType::kFileSystem, origin, + enabled); } private: - std::vector<scoped_refptr<QuotaClient>> GetUsageTrackerList() { - std::vector<scoped_refptr<QuotaClient>> client_list; - client_list.push_back(quota_client_); - return client_list; + base::flat_map<QuotaClient*, QuotaClientType> GetQuotaClientMap() { + base::flat_map<QuotaClient*, QuotaClientType> client_map; + client_map.insert( + std::make_pair(quota_client_.get(), QuotaClientType::kFileSystem)); + return client_map; } base::test::TaskEnvironment task_environment_; |