diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-10-26 13:57:00 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-11-02 11:31:01 +0000 |
commit | 1943b3c2a1dcee36c233724fc4ee7613d71b9cf6 (patch) | |
tree | 8c1b5f12357025c197da5427ae02cfdc2f3570d6 /chromium/storage | |
parent | 21ba0c5d4bf8fba15dddd97cd693bad2358b77fd (diff) | |
download | qtwebengine-chromium-1943b3c2a1dcee36c233724fc4ee7613d71b9cf6.tar.gz |
BASELINE: Update Chromium to 94.0.4606.111
Change-Id: I924781584def20fc800bedf6ff41fdb96c438193
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/storage')
145 files changed, 5632 insertions, 4492 deletions
diff --git a/chromium/storage/DIR_METADATA b/chromium/storage/DIR_METADATA index f9e9509fabc..150afdb2799 100644 --- a/chromium/storage/DIR_METADATA +++ b/chromium/storage/DIR_METADATA @@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Blink>Storage" diff --git a/chromium/storage/browser/BUILD.gn b/chromium/storage/browser/BUILD.gn index 025683c50d7..7013c7b14ee 100644 --- a/chromium/storage/browser/BUILD.gn +++ b/chromium/storage/browser/BUILD.gn @@ -109,6 +109,8 @@ component("browser") { "file_system/file_system_url.h", "file_system/file_system_usage_cache.cc", "file_system/file_system_usage_cache.h", + "file_system/file_system_util.cc", + "file_system/file_system_util.h", "file_system/file_writer_delegate.cc", "file_system/file_writer_delegate.h", "file_system/filesystem_proxy_file_stream_reader.cc", @@ -180,10 +182,7 @@ component("browser") { "file_system/watcher_manager.h", "quota/client_usage_tracker.cc", "quota/client_usage_tracker.h", - "quota/mojo_quota_client_wrapper.cc", - "quota/mojo_quota_client_wrapper.h", "quota/quota_callbacks.h", - "quota/quota_client.h", "quota/quota_client_type.cc", "quota/quota_client_type.h", "quota/quota_database.cc", @@ -234,12 +233,14 @@ component("browser") { "//base/third_party/dynamic_annotations", "//build:chromeos_buildflags", "//components/services/storage/public/cpp", + "//components/services/storage/public/cpp/filesystem", "//mojo/public/cpp/bindings", "//net", "//services/network:network_service", "//services/network/public/cpp", "//services/network/public/mojom", "//sql", + "//third_party/blink/public/common", "//third_party/leveldatabase", "//third_party/sqlite", "//url", @@ -342,6 +343,7 @@ source_set("unittests") { "//services/network/public/mojom", "//sql:test_support", "//testing/gtest", + "//third_party/blink/public/common", "//third_party/leveldatabase", "//third_party/sqlite", ] diff --git a/chromium/storage/browser/blob/DIR_METADATA b/chromium/storage/browser/blob/DIR_METADATA index 19266882c43..30c02fb2b1a 100644 --- a/chromium/storage/browser/blob/DIR_METADATA +++ b/chromium/storage/browser/blob/DIR_METADATA @@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Blink>Storage>FileAPI" diff --git a/chromium/storage/browser/blob/blob_entry.h b/chromium/storage/browser/blob/blob_entry.h index 317e4050c8e..51e0e289fe1 100644 --- a/chromium/storage/browser/blob/blob_entry.h +++ b/chromium/storage/browser/blob/blob_entry.h @@ -17,7 +17,6 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "storage/browser/blob/blob_memory_controller.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace storage { class BlobDataHandle; diff --git a/chromium/storage/browser/blob/blob_impl.cc b/chromium/storage/browser/blob/blob_impl.cc index d366316e02b..141fcd8722f 100644 --- a/chromium/storage/browser/blob/blob_impl.cc +++ b/chromium/storage/browser/blob/blob_impl.cc @@ -231,7 +231,8 @@ void BlobImpl::CaptureSnapshot(CaptureSnapshotCallback callback) { base::File::Info info; if (!base::GetFileInfo(path, &info)) return SizeAndTime{0, absl::nullopt}; - return SizeAndTime{info.size, info.last_modified}; + return SizeAndTime{static_cast<uint64_t>(info.size), + info.last_modified}; }, item->path()), base::BindOnce( diff --git a/chromium/storage/browser/blob/blob_memory_controller.cc b/chromium/storage/browser/blob/blob_memory_controller.cc index e070b09c27d..617dfb4d412 100644 --- a/chromium/storage/browser/blob/blob_memory_controller.cc +++ b/chromium/storage/browser/blob/blob_memory_controller.cc @@ -23,7 +23,6 @@ #include "base/numerics/safe_conversions.h" #include "base/numerics/safe_math.h" #include "base/single_thread_task_runner.h" -#include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/system/sys_info.h" #include "base/task_runner.h" diff --git a/chromium/storage/browser/blob/blob_memory_controller_unittest.cc b/chromium/storage/browser/blob/blob_memory_controller_unittest.cc index 324d44990b2..159021a7312 100644 --- a/chromium/storage/browser/blob/blob_memory_controller_unittest.cc +++ b/chromium/storage/browser/blob/blob_memory_controller_unittest.cc @@ -19,6 +19,7 @@ #include "storage/browser/blob/blob_data_item.h" #include "storage/browser/blob/shareable_blob_data_item.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace storage { @@ -58,7 +59,7 @@ class BlobMemoryControllerTest : public base::test::WithFeatureOverride, void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - base::ThreadRestrictions::SetIOAllowed(false); + disallow_blocking_.emplace(); } void TearDown() override { @@ -67,16 +68,15 @@ class BlobMemoryControllerTest : public base::test::WithFeatureOverride, base::RunLoop().RunUntilIdle(); RunFileThreadTasks(); base::RunLoop().RunUntilIdle(); - base::ThreadRestrictions::SetIOAllowed(true); + disallow_blocking_.reset(); ASSERT_TRUE(temp_dir_.Delete()); } void AssertEnoughDiskSpace() { - base::ThreadRestrictions::SetIOAllowed(true); + base::ScopedAllowBlockingForTesting allow_blocking; ASSERT_GT(base::SysInfo::AmountOfFreeDiskSpace(temp_dir_.GetPath()), static_cast<int64_t>(kTestBlobStorageMaxDiskSpace)) << "Bot doesn't have enough disk space to run these tests."; - base::ThreadRestrictions::SetIOAllowed(false); } std::vector<scoped_refptr<ShareableBlobDataItem>> CreateSharedDataItems( @@ -147,9 +147,8 @@ class BlobMemoryControllerTest : public base::test::WithFeatureOverride, } void RunFileThreadTasks() { - base::ThreadRestrictions::SetIOAllowed(true); + base::ScopedAllowBlockingForTesting allow_blocking; file_runner_->RunPendingTasks(); - base::ThreadRestrictions::SetIOAllowed(false); } bool HasMemoryAllocation(ShareableBlobDataItem* item) { @@ -171,6 +170,8 @@ class BlobMemoryControllerTest : public base::test::WithFeatureOverride, scoped_refptr<TestSimpleTaskRunner> file_runner_ = new TestSimpleTaskRunner(); base::test::TaskEnvironment task_environment_; + + absl::optional<base::ScopedDisallowBlocking> disallow_blocking_; }; TEST_P(BlobMemoryControllerTest, Strategy) { @@ -469,9 +470,10 @@ TEST_P(BlobMemoryControllerTest, FileRequest) { EXPECT_EQ(1u, files_created_.size()); EXPECT_TRUE(future_file.Populate(std::move(files_created_[0].file_reference), files_created_[0].last_modified)); - base::ThreadRestrictions::SetIOAllowed(true); - files_created_.clear(); - base::ThreadRestrictions::SetIOAllowed(false); + { + base::ScopedAllowBlockingForTesting allow_blocking; + files_created_.clear(); + } EXPECT_EQ(BlobDataItem::Type::kFile, items[0]->item()->type()); EXPECT_FALSE(items[0]->item()->IsFutureFileItem()); diff --git a/chromium/storage/browser/blob/blob_reader.cc b/chromium/storage/browser/blob/blob_reader.cc index b004bf3a26f..78a6fbd2fe2 100644 --- a/chromium/storage/browser/blob/blob_reader.cc +++ b/chromium/storage/browser/blob/blob_reader.cc @@ -576,8 +576,9 @@ BlobReader::Status BlobReader::ReadFileItem(FileStreamReader* reader, return Status::DONE; } if (result == net::ERR_IO_PENDING) { - TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobReader::ReadFileItem", this, "uuid", - blob_data_->uuid()); + TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("Blob", "BlobReader::ReadFileItem", + TRACE_ID_LOCAL(this), "uuid", + blob_data_->uuid()); io_pending_ = true; return Status::IO_PENDING; } @@ -586,8 +587,9 @@ BlobReader::Status BlobReader::ReadFileItem(FileStreamReader* reader, void BlobReader::DidReadFile(int result) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - TRACE_EVENT_ASYNC_END1("Blob", "BlobReader::ReadFileItem", this, "uuid", - blob_data_->uuid()); + TRACE_EVENT_NESTABLE_ASYNC_END1("Blob", "BlobReader::ReadFileItem", + TRACE_ID_LOCAL(this), "uuid", + blob_data_->uuid()); DidReadItem(result); } @@ -636,8 +638,9 @@ BlobReader::Status BlobReader::ReadReadableDataHandle(const BlobDataItem& item, return Status::DONE; } if (result == net::ERR_IO_PENDING) { - TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobReader::ReadReadableDataHandle", this, - "uuid", blob_data_->uuid()); + TRACE_EVENT_NESTABLE_ASYNC_BEGIN1( + "Blob", "BlobReader::ReadReadableDataHandle", TRACE_ID_LOCAL(this), + "uuid", blob_data_->uuid()); io_pending_ = true; return Status::IO_PENDING; } @@ -646,8 +649,9 @@ BlobReader::Status BlobReader::ReadReadableDataHandle(const BlobDataItem& item, void BlobReader::DidReadReadableDataHandle(int result) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - TRACE_EVENT_ASYNC_END1("Blob", "BlobReader::ReadReadableDataHandle", this, - "uuid", blob_data_->uuid()); + TRACE_EVENT_NESTABLE_ASYNC_END1("Blob", "BlobReader::ReadReadableDataHandle", + TRACE_ID_LOCAL(this), "uuid", + blob_data_->uuid()); RecordBytesReadFromDataHandle(current_item_index_, result); DidReadItem(result); } diff --git a/chromium/storage/browser/blob/blob_reader.h b/chromium/storage/browser/blob/blob_reader.h index b8c71d5a3cb..017f6f2b028 100644 --- a/chromium/storage/browser/blob/blob_reader.h +++ b/chromium/storage/browser/blob/blob_reader.h @@ -22,6 +22,7 @@ #include "net/base/completion_once_callback.h" #include "services/network/public/cpp/data_pipe_to_source_stream.h" #include "storage/browser/blob/blob_storage_constants.h" +#include "third_party/abseil-cpp/absl/types/optional.h" class GURL; diff --git a/chromium/storage/browser/blob/blob_reader_unittest.cc b/chromium/storage/browser/blob/blob_reader_unittest.cc index 6d978e74714..1e63b33444a 100644 --- a/chromium/storage/browser/blob/blob_reader_unittest.cc +++ b/chromium/storage/browser/blob/blob_reader_unittest.cc @@ -37,6 +37,7 @@ #include "storage/browser/file_system/file_stream_reader.h" #include "storage/browser/file_system/file_system_context.h" #include "storage/browser/file_system/file_system_file_util.h" +#include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/test/async_file_test_helper.h" #include "storage/browser/test/fake_blob_data_handle.h" #include "storage/browser/test/test_file_system_context.h" @@ -207,8 +208,8 @@ class BlobReaderTest : public ::testing::Test { ~BlobReaderTest() override = default; void SetUp() override { - file_system_context_ = - CreateFileSystemContextForTesting(nullptr, base::FilePath()); + file_system_context_ = CreateFileSystemContextForTesting( + /*quota_manager_proxy=*/nullptr, base::FilePath()); } void TearDown() override { @@ -356,8 +357,9 @@ TEST_F(BlobReaderTest, BasicFileSystem) { const GURL kURL("filesystem:http://example.com/temporary/test_file/here.txt"); const std::string kData = "FileData!!!"; const base::Time kTime = base::Time::Now(); - b->AppendFileSystemFile(file_system_context_->CrackURL(kURL), 0, kData.size(), - kTime, file_system_context_); + b->AppendFileSystemFile( + file_system_context_->CrackURLInFirstPartyContext(kURL), 0, kData.size(), + kTime, file_system_context_); this->InitializeReader(std::move(b)); // Non-async reader. ExpectFileSystemCall(kURL, 0, kData.size(), kTime, @@ -619,8 +621,9 @@ TEST_F(BlobReaderTest, FileSystemAsync) { const GURL kURL("filesystem:http://example.com/temporary/test_file/here.txt"); const std::string kData = "FileData!!!"; const base::Time kTime = base::Time::Now(); - b->AppendFileSystemFile(file_system_context_->CrackURL(kURL), 0, kData.size(), - kTime, file_system_context_); + b->AppendFileSystemFile( + file_system_context_->CrackURLInFirstPartyContext(kURL), 0, kData.size(), + kTime, file_system_context_); this->InitializeReader(std::move(b)); std::unique_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(kData)); diff --git a/chromium/storage/browser/blob/blob_registry_impl.cc b/chromium/storage/browser/blob/blob_registry_impl.cc index 90753d9337a..ac131afb5e5 100644 --- a/chromium/storage/browser/blob/blob_registry_impl.cc +++ b/chromium/storage/browser/blob/blob_registry_impl.cc @@ -15,6 +15,7 @@ #include "storage/browser/blob/blob_storage_context.h" #include "storage/browser/blob/blob_transport_strategy.h" #include "storage/browser/blob/blob_url_store_impl.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/blob/data_element.mojom.h" #include "third_party/blink/public/mojom/blob/serialized_blob.mojom.h" @@ -396,32 +397,37 @@ void BlobRegistryImpl::BlobUnderConstruction::ResolvedAllBlobDependencies() { } } - auto callback = - base::BindRepeating(&BlobUnderConstruction::OnReadyForTransport, - weak_ptr_factory_.GetWeakPtr()); - + // BuildPreregisterdBlob might delete `this`, so store some members in local + // variables before calling that method. + auto weak_this = weak_ptr_factory_.GetWeakPtr(); auto blob_impl = std::move(blob_impl_); // OnReadyForTransport can be called synchronously, which can call // MarkAsFinishedAndDeleteSelf synchronously, so don't access any members // after this call. std::unique_ptr<BlobDataHandle> new_handle = - context()->BuildPreregisteredBlob(std::move(builder_), callback); + context()->BuildPreregisteredBlob( + std::move(builder_), + base::BindOnce(&BlobUnderConstruction::OnReadyForTransport, + weak_ptr_factory_.GetWeakPtr())); - bool is_being_built = new_handle->IsBeingBuilt(); - auto blob_status = new_handle->GetBlobStatus(); + // BuildPreregisteredBlob might or might not have called the callback if + // it finished synchronously. Additionally even if the blob didn't finish + // synchronously, the callback might end up never being called, for example + // if no transport of bytes will be needed. To make sure `this` will get + // cleaned up regardless of how construction completes, add a + // OnConstructionComplete callback. + if (weak_this) { + new_handle->RunOnConstructionComplete(base::BindOnce( + [](base::WeakPtr<BlobUnderConstruction> blob, BlobStatus) { + if (blob) + blob->MarkAsFinishedAndDeleteSelf(); + }, + std::move(weak_this))); + } if (blob_impl) blob_impl->UpdateHandle(std::move(new_handle)); - - // BuildPreregisteredBlob might or might not have called the callback if - // it finished synchronously, so call the callback directly. If it was - // already called |this| would have been deleted making calling the - // callback a no-op. - if (!is_being_built) { - callback.Run(blob_status, - std::vector<BlobMemoryController::FileCreationInfo>()); - } } void BlobRegistryImpl::BlobUnderConstruction::OnReadyForTransport( @@ -548,8 +554,13 @@ void BlobRegistryImpl::Register( return; } } else if (entry.element->is_file_filesystem()) { - entry.filesystem_url = file_system_context_->CrackURL( - entry.element->get_file_filesystem()->url); + const GURL crack_url = entry.element->get_file_filesystem()->url; + // TODO(https://crbug.com/1221308): determine whether StorageKey should be + // replaced with a more meaningful value + const blink::StorageKey crack_storage_key = + blink::StorageKey(url::Origin::Create(crack_url)); + entry.filesystem_url = + file_system_context_->CrackURL(crack_url, crack_storage_key); if (!entry.filesystem_url.is_valid() || !file_system_context_->GetFileSystemBackend( entry.filesystem_url.type()) || diff --git a/chromium/storage/browser/blob/blob_registry_impl_unittest.cc b/chromium/storage/browser/blob/blob_registry_impl_unittest.cc index 6a4431d68fd..76af9d4c0e3 100644 --- a/chromium/storage/browser/blob/blob_registry_impl_unittest.cc +++ b/chromium/storage/browser/blob/blob_registry_impl_unittest.cc @@ -32,12 +32,15 @@ #include "storage/browser/blob/blob_data_handle.h" #include "storage/browser/blob/blob_storage_context.h" #include "storage/browser/blob/blob_url_registry.h" +#include "storage/browser/file_system/external_mount_points.h" +#include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/test/fake_blob.h" #include "storage/browser/test/fake_progress_client.h" #include "storage/browser/test/mock_blob_registry_delegate.h" #include "storage/browser/test/mock_bytes_provider.h" #include "storage/browser/test/mock_special_storage_policy.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/mojom/blob/data_element.mojom.h" #include "third_party/blink/public/mojom/blob/serialized_blob.mojom.h" @@ -70,15 +73,15 @@ class BlobRegistryImplTest : public testing::Test { data_dir_.GetPath(), data_dir_.GetPath(), base::ThreadPool::CreateTaskRunner({base::MayBlock()})); auto storage_policy = base::MakeRefCounted<MockSpecialStoragePolicy>(); - file_system_context_ = base::MakeRefCounted<FileSystemContext>( - base::ThreadTaskRunnerHandle::Get().get(), - base::ThreadTaskRunnerHandle::Get().get(), - nullptr /* external_mount_points */, storage_policy.get(), - nullptr /* quota_manager_proxy */, + file_system_context_ = FileSystemContext::Create( + base::ThreadTaskRunnerHandle::Get(), + base::ThreadTaskRunnerHandle::Get(), + /*external_mount_points=*/nullptr, std::move(storage_policy), + /*quota_manager_proxy=*/nullptr, std::vector<std::unique_ptr<FileSystemBackend>>(), std::vector<URLRequestAutoMountHandler>(), data_dir_.GetPath(), FileSystemOptions(FileSystemOptions::PROFILE_MODE_INCOGNITO, - false /* force_in_memory */, + /*force_in_memory=*/false, std::vector<std::string>())); registry_impl_ = std::make_unique<BlobRegistryImpl>( context_->AsWeakPtr(), url_registry_.AsWeakPtr(), file_system_context_); @@ -102,12 +105,10 @@ class BlobRegistryImplTest : public testing::Test { context_->mutable_memory_controller()->set_limits_for_testing(limits); // Disallow IO on the main loop. - base::ThreadRestrictions::SetIOAllowed(false); + disallow_blocking_.emplace(); } void TearDown() override { - base::ThreadRestrictions::SetIOAllowed(true); - mojo::SetDefaultProcessErrorHandler(base::NullCallback()); } @@ -189,6 +190,7 @@ class BlobRegistryImplTest : public testing::Test { protected: base::ScopedTempDir data_dir_; base::test::TaskEnvironment task_environment_; + absl::optional<base::ScopedDisallowBlocking> disallow_blocking_; std::unique_ptr<BlobStorageContext> context_; scoped_refptr<FileSystemContext> file_system_context_; BlobUrlRegistry url_registry_; @@ -525,6 +527,55 @@ TEST_F(BlobRegistryImplTest, Register_ValidBlobReferences) { EXPECT_EQ(0u, BlobsUnderConstruction()); } +TEST_F(BlobRegistryImplTest, Register_BlobReferencingPendingBlob) { + // Create a blob that is pending population of its data. + const std::string kId1 = "id1"; + const std::string kBlob1Data = "foobar"; + auto builder = std::make_unique<BlobDataBuilder>(kId1); + builder->set_content_type("text/plain"); + BlobDataBuilder::FutureData future_data = + builder->AppendFutureData(kBlob1Data.length()); + std::unique_ptr<BlobDataHandle> handle = + context_->BuildBlob(std::move(builder), base::DoNothing()); + + mojo::PendingRemote<blink::mojom::Blob> blob1_remote; + mojo::MakeSelfOwnedReceiver(std::make_unique<FakeBlob>(kId1), + blob1_remote.InitWithNewPipeAndPassReceiver()); + + // Now create a blob referencing the pending blob above. + std::vector<blink::mojom::DataElementPtr> elements; + elements.push_back( + blink::mojom::DataElement::NewBlob(blink::mojom::DataElementBlob::New( + std::move(blob1_remote), 0, kBlob1Data.length()))); + + mojo::PendingRemote<blink::mojom::Blob> final_blob; + const std::string kId2 = "id2"; + EXPECT_TRUE(registry_->Register(final_blob.InitWithNewPipeAndPassReceiver(), + kId2, "", "", std::move(elements))); + + // Run the runloop to make sure registration of blob kId2 gets far enough + // before blob kId1 is populated. + base::RunLoop().RunUntilIdle(); + + // Populate the data for the first blob. + future_data.Populate(base::as_bytes(base::make_span(kBlob1Data))); + context_->NotifyTransportComplete(kId1); + + // Wait for kId2 to also complete. + std::unique_ptr<BlobDataHandle> handle2 = context_->GetBlobDataFromUUID(kId2); + WaitForBlobCompletion(handle2.get()); + + // Make sure blob was constructed correctly. + EXPECT_FALSE(handle2->IsBroken()); + ASSERT_EQ(BlobStatus::DONE, handle2->GetBlobStatus()); + BlobDataBuilder expected_blob_data(kId2); + expected_blob_data.AppendData(kBlob1Data); + EXPECT_EQ(expected_blob_data, *handle2->CreateSnapshot()); + + // And make sure we're not leaking any under construction blobs. + EXPECT_EQ(0u, BlobsUnderConstruction()); +} + TEST_F(BlobRegistryImplTest, Register_UnreadableFile) { delegate_ptr_->can_read_file_result = false; @@ -599,7 +650,7 @@ TEST_F(BlobRegistryImplTest, Register_FileSystemFile_InvalidScheme) { EXPECT_EQ(0u, BlobsUnderConstruction()); } -TEST_F(BlobRegistryImplTest, Register_FileSystemFile_UnreadablFile) { +TEST_F(BlobRegistryImplTest, Register_FileSystemFile_UnreadableFile) { delegate_ptr_->can_read_file_system_file_result = false; const std::string kId = "id"; @@ -645,9 +696,9 @@ TEST_F(BlobRegistryImplTest, Register_FileSystemFile_Valid) { ASSERT_EQ(BlobStatus::DONE, handle->GetBlobStatus()); BlobDataBuilder expected_blob_data(kId); - expected_blob_data.AppendFileSystemFile(file_system_context_->CrackURL(url), - 0, 16, base::Time(), - file_system_context_); + expected_blob_data.AppendFileSystemFile( + file_system_context_->CrackURLInFirstPartyContext(url), 0, 16, + base::Time(), file_system_context_); EXPECT_EQ(expected_blob_data, *handle->CreateSnapshot()); EXPECT_EQ(0u, BlobsUnderConstruction()); diff --git a/chromium/storage/browser/blob/blob_storage_constants.cc b/chromium/storage/browser/blob/blob_storage_constants.cc index 96143d9b4f9..ba9c728f961 100644 --- a/chromium/storage/browser/blob/blob_storage_constants.cc +++ b/chromium/storage/browser/blob/blob_storage_constants.cc @@ -4,6 +4,8 @@ #include "storage/browser/blob/blob_storage_constants.h" +#include <ostream> + #include "base/check.h" #include "base/command_line.h" #include "base/strings/string_number_conversions.h" 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 4f373a6af20..b911200bad4 100644 --- a/chromium/storage/browser/blob/blob_storage_context_mojo_unittest.cc +++ b/chromium/storage/browser/blob/blob_storage_context_mojo_unittest.cc @@ -66,12 +66,12 @@ class BlobStorageContextMojoTest : public testing::Test { void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - base::ThreadRestrictions::SetIOAllowed(false); + disallow_blocking_.emplace(); } void TearDown() override { task_environment_.RunUntilIdle(); - base::ThreadRestrictions::SetIOAllowed(true); + disallow_blocking_.reset(); ASSERT_TRUE(!temp_dir_.IsValid() || temp_dir_.Delete()); } @@ -134,6 +134,7 @@ class BlobStorageContextMojoTest : public testing::Test { base::test::TaskEnvironment::MainThreadType::IO}; scoped_refptr<base::SequencedTaskRunner> file_runner_; std::unique_ptr<BlobStorageContext> context_; + absl::optional<base::ScopedDisallowBlocking> disallow_blocking_; }; TEST_F(BlobStorageContextMojoTest, BasicBlobCreation) { @@ -181,7 +182,7 @@ TEST_F(BlobStorageContextMojoTest, SaveBlobToFile) { })); loop.Run(); - base::ThreadRestrictions::SetIOAllowed(true); + base::ScopedAllowBlockingForTesting allow_blocking; std::string file_contents; EXPECT_TRUE(base::ReadFileToString(file_path, &file_contents)); EXPECT_EQ(file_contents, kData); @@ -218,7 +219,7 @@ TEST_F(BlobStorageContextMojoTest, SaveBlobToFileNoDate) { })); loop.Run(); - base::ThreadRestrictions::SetIOAllowed(true); + base::ScopedAllowBlockingForTesting allow_blocking; std::string file_contents; EXPECT_TRUE(base::ReadFileToString(file_path, &file_contents)); EXPECT_EQ(file_contents, kData); @@ -249,7 +250,7 @@ TEST_F(BlobStorageContextMojoTest, SaveEmptyBlobToFile) { })); loop.Run(); - base::ThreadRestrictions::SetIOAllowed(true); + base::ScopedAllowBlockingForTesting allow_blocking; std::string file_contents; EXPECT_TRUE(base::ReadFileToString(file_path, &file_contents)); EXPECT_EQ(file_contents, std::string("")); @@ -301,7 +302,7 @@ TEST_F(BlobStorageContextMojoTest, FileCopyOptimization) { })); loop.Run(); - base::ThreadRestrictions::SetIOAllowed(true); + base::ScopedAllowBlockingForTesting allow_blocking; std::string file_contents; EXPECT_TRUE(base::ReadFileToString(file_path, &file_contents)); EXPECT_EQ(file_contents, kData); @@ -354,7 +355,7 @@ TEST_F(BlobStorageContextMojoTest, FileCopyOptimizationOffsetSize) { })); loop.Run(); - base::ThreadRestrictions::SetIOAllowed(true); + base::ScopedAllowBlockingForTesting allow_blocking; std::string file_contents; EXPECT_TRUE(base::ReadFileToString(file_path, &file_contents)); EXPECT_EQ(file_contents, kData.substr(kOffset, kSize)); @@ -405,7 +406,7 @@ TEST_F(BlobStorageContextMojoTest, FileCopyEmptyFile) { })); loop.Run(); - base::ThreadRestrictions::SetIOAllowed(true); + base::ScopedAllowBlockingForTesting allow_blocking; std::string file_contents; EXPECT_TRUE(base::ReadFileToString(file_path, &file_contents)); EXPECT_EQ(file_contents, std::string("")); @@ -457,7 +458,7 @@ TEST_F(BlobStorageContextMojoTest, InvalidInputFileSize) { })); loop.Run(); - base::ThreadRestrictions::SetIOAllowed(true); + base::ScopedAllowBlockingForTesting allow_blocking; base::DeleteFile(file_path); ASSERT_TRUE(temp_dir_.Delete()); } @@ -498,7 +499,7 @@ TEST_F(BlobStorageContextMojoTest, InvalidInputFileTimeModified) { })); loop.Run(); - base::ThreadRestrictions::SetIOAllowed(true); + base::ScopedAllowBlockingForTesting allow_blocking; base::DeleteFile(file_path); ASSERT_TRUE(temp_dir_.Delete()); } @@ -593,7 +594,7 @@ TEST_F(BlobStorageContextMojoTest, SaveBlobToFileNoDirectory) { })); loop.Run(); - base::ThreadRestrictions::SetIOAllowed(true); + base::ScopedAllowBlockingForTesting allow_blocking; EXPECT_FALSE(base::PathExists(file_path)); ASSERT_TRUE(temp_dir_.Delete()); } @@ -632,7 +633,7 @@ TEST_F(BlobStorageContextMojoTest, SaveOptimizedBlobToFileNoDirectory) { })); loop.Run(); - base::ThreadRestrictions::SetIOAllowed(true); + base::ScopedAllowBlockingForTesting allow_blocking; EXPECT_FALSE(base::PathExists(file_path)); ASSERT_TRUE(temp_dir_.Delete()); } @@ -670,7 +671,7 @@ TEST_F(BlobStorageContextMojoTest, SaveOptimizedBlobNoFileSize) { })); loop.Run(); - base::ThreadRestrictions::SetIOAllowed(true); + base::ScopedAllowBlockingForTesting allow_blocking; std::string file_contents; EXPECT_TRUE(base::ReadFileToString(file_path, &file_contents)); EXPECT_EQ(file_contents, kData); diff --git a/chromium/storage/browser/blob/blob_storage_context_unittest.cc b/chromium/storage/browser/blob/blob_storage_context_unittest.cc index 42e7c34c7bb..6b9fb19789a 100644 --- a/chromium/storage/browser/blob/blob_storage_context_unittest.cc +++ b/chromium/storage/browser/blob/blob_storage_context_unittest.cc @@ -31,6 +31,7 @@ #include "storage/browser/blob/blob_data_item.h" #include "storage/browser/blob/blob_data_snapshot.h" #include "storage/browser/blob/blob_impl.h" +#include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/test/fake_blob_data_handle.h" #include "storage/browser/test/test_file_system_context.h" #include "testing/gtest/include/gtest/gtest.h" @@ -80,8 +81,8 @@ class BlobStorageContextTest : public testing::Test { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); base::ThreadRestrictions::SetIOAllowed(false); context_ = std::make_unique<BlobStorageContext>(); - file_system_context_ = - CreateFileSystemContextForTesting(nullptr, base::FilePath()); + file_system_context_ = CreateFileSystemContextForTesting( + /*quota_manager_proxy=*/nullptr, base::FilePath()); } void TearDown() override { diff --git a/chromium/storage/browser/blob/blob_transport_strategy_unittest.cc b/chromium/storage/browser/blob/blob_transport_strategy_unittest.cc index 9a08c025b74..e29f1048d9b 100644 --- a/chromium/storage/browser/blob/blob_transport_strategy_unittest.cc +++ b/chromium/storage/browser/blob/blob_transport_strategy_unittest.cc @@ -26,6 +26,7 @@ #include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/test/mock_bytes_provider.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/mojom/blob/data_element.mojom.h" namespace storage { @@ -74,11 +75,10 @@ class BlobTransportStrategyTest : public testing::Test { &BlobTransportStrategyTest::OnBadMessage, base::Unretained(this))); // Disallow IO on the main loop. - base::ThreadRestrictions::SetIOAllowed(false); + disallow_blocking_.emplace(); } void TearDown() override { - base::ThreadRestrictions::SetIOAllowed(true); mojo::SetDefaultProcessErrorHandler(base::NullCallback()); } @@ -106,6 +106,8 @@ class BlobTransportStrategyTest : public testing::Test { base::Time mock_time_; BlobStorageLimits limits_; + absl::optional<base::ScopedDisallowBlocking> disallow_blocking_; + std::vector<std::string> bad_messages_; size_t reply_request_count_ = 0; diff --git a/chromium/storage/browser/blob/blob_url_loader.cc b/chromium/storage/browser/blob/blob_url_loader.cc index 72325e7cc96..b2e061c4e11 100644 --- a/chromium/storage/browser/blob/blob_url_loader.cc +++ b/chromium/storage/browser/blob/blob_url_loader.cc @@ -25,9 +25,12 @@ #include "net/http/http_util.h" #include "net/url_request/url_request.h" #include "services/network/public/cpp/constants.h" +#include "services/network/public/cpp/features.h" +#include "services/network/public/cpp/resource_request.h" #include "services/network/public/mojom/url_response_head.mojom.h" #include "storage/browser/blob/blob_data_handle.h" #include "storage/browser/blob/mojo_blob_reader.h" +#include "third_party/blink/public/common/blob/blob_utils.h" namespace storage { @@ -154,7 +157,8 @@ void BlobURLLoader::Start(const std::string& method, options.struct_size = sizeof(MojoCreateDataPipeOptions); options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE; options.element_num_bytes = 1; - options.capacity_num_bytes = network::kDataPipeDefaultAllocationSize; + options.capacity_num_bytes = + blink::BlobUtils::GetDataPipeCapacity(blob_handle_->size()); if (mojo::CreateDataPipe(&options, producer_handle, consumer_handle) != MOJO_RESULT_OK) { OnComplete(net::ERR_INSUFFICIENT_RESOURCES, 0); diff --git a/chromium/storage/browser/blob/blob_url_loader.h b/chromium/storage/browser/blob/blob_url_loader.h index 1ea8a497875..325d2968556 100644 --- a/chromium/storage/browser/blob/blob_url_loader.h +++ b/chromium/storage/browser/blob/blob_url_loader.h @@ -17,6 +17,7 @@ #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" #include "net/http/http_status_code.h" +#include "services/network/public/cpp/resource_request.h" #include "services/network/public/mojom/url_loader.mojom.h" #include "storage/browser/blob/mojo_blob_reader.h" diff --git a/chromium/storage/browser/blob/blob_url_loader_factory.cc b/chromium/storage/browser/blob/blob_url_loader_factory.cc index a6ac1405207..bddf0a2eab3 100644 --- a/chromium/storage/browser/blob/blob_url_loader_factory.cc +++ b/chromium/storage/browser/blob/blob_url_loader_factory.cc @@ -7,6 +7,7 @@ #include "base/bind.h" #include "mojo/public/cpp/bindings/callback_helpers.h" #include "mojo/public/cpp/bindings/remote.h" +#include "services/network/public/cpp/resource_request.h" #include "services/network/public/mojom/url_loader.mojom.h" #include "storage/browser/blob/blob_url_registry.h" diff --git a/chromium/storage/browser/blob/blob_url_registry.cc b/chromium/storage/browser/blob/blob_url_registry.cc index c0cea83e1fc..d658e7e901e 100644 --- a/chromium/storage/browser/blob/blob_url_registry.cc +++ b/chromium/storage/browser/blob/blob_url_registry.cc @@ -19,11 +19,14 @@ BlobUrlRegistry::~BlobUrlRegistry() { bool BlobUrlRegistry::AddUrlMapping( const GURL& blob_url, - mojo::PendingRemote<blink::mojom::Blob> blob) { + mojo::PendingRemote<blink::mojom::Blob> blob, + // TODO(https://crbug.com/1224926): Remove this once experiment is over. + const base::UnguessableToken& unsafe_agent_cluster_id) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!BlobUrlUtils::UrlHasFragment(blob_url)); if (IsUrlMapped(blob_url)) return false; + url_to_unsafe_agent_cluster_id_[blob_url] = unsafe_agent_cluster_id; url_to_blob_[blob_url] = std::move(blob); return true; } @@ -31,10 +34,14 @@ bool BlobUrlRegistry::AddUrlMapping( bool BlobUrlRegistry::RemoveUrlMapping(const GURL& blob_url) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!BlobUrlUtils::UrlHasFragment(blob_url)); - auto it = url_to_blob_.find(blob_url); - if (it == url_to_blob_.end()) + auto blob_it = url_to_blob_.find(blob_url); + auto agent_it = url_to_unsafe_agent_cluster_id_.find(blob_url); + if (blob_it == url_to_blob_.end() || + agent_it == url_to_unsafe_agent_cluster_id_.end()) { return false; - url_to_blob_.erase(it); + } + url_to_blob_.erase(blob_it); + url_to_unsafe_agent_cluster_id_.erase(agent_it); return true; } @@ -47,6 +54,18 @@ bool BlobUrlRegistry::IsUrlMapped(const GURL& blob_url) const { return false; } +// TODO(https://crbug.com/1224926): Remove this once experiment is over. +absl::optional<base::UnguessableToken> BlobUrlRegistry::GetUnsafeAgentClusterID( + const GURL& blob_url) const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + auto it = url_to_unsafe_agent_cluster_id_.find(blob_url); + if (it != url_to_unsafe_agent_cluster_id_.end()) + return it->second; + if (fallback_) + return fallback_->GetUnsafeAgentClusterID(blob_url); + return absl::nullopt; +} + mojo::PendingRemote<blink::mojom::Blob> BlobUrlRegistry::GetBlobFromUrl( const GURL& url) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); diff --git a/chromium/storage/browser/blob/blob_url_registry.h b/chromium/storage/browser/blob/blob_url_registry.h index e2ba6707019..104cf9c050a 100644 --- a/chromium/storage/browser/blob/blob_url_registry.h +++ b/chromium/storage/browser/blob/blob_url_registry.h @@ -28,8 +28,11 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobUrlRegistry { // Creates a url mapping from blob to the given url. Returns false if // there already is a map for the URL. - bool AddUrlMapping(const GURL& url, - mojo::PendingRemote<blink::mojom::Blob> blob); + bool AddUrlMapping( + const GURL& url, + mojo::PendingRemote<blink::mojom::Blob> blob, + // TODO(https://crbug.com/1224926): Remove this once experiment is over. + const base::UnguessableToken& unsafe_agent_cluster_id); // Removes the given URL mapping. Returns false if the url wasn't mapped. bool RemoveUrlMapping(const GURL& url); @@ -37,6 +40,10 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobUrlRegistry { // Returns if the url is mapped to a blob. bool IsUrlMapped(const GURL& blob_url) const; + // TODO(https://crbug.com/1224926): Remove this once experiment is over. + absl::optional<base::UnguessableToken> GetUnsafeAgentClusterID( + const GURL& blob_url) const; + // Returns the blob from the given url. Returns a null remote if the mapping // doesn't exist. mojo::PendingRemote<blink::mojom::Blob> GetBlobFromUrl(const GURL& url); @@ -65,6 +72,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobUrlRegistry { base::WeakPtr<BlobUrlRegistry> fallback_; std::map<GURL, mojo::PendingRemote<blink::mojom::Blob>> url_to_blob_; + // TODO(https://crbug.com/1224926): Remove this once experiment is over. + std::map<GURL, base::UnguessableToken> url_to_unsafe_agent_cluster_id_; std::map<base::UnguessableToken, std::pair<GURL, mojo::PendingRemote<blink::mojom::Blob>>> token_to_url_and_blob_; diff --git a/chromium/storage/browser/blob/blob_url_registry_unittest.cc b/chromium/storage/browser/blob/blob_url_registry_unittest.cc index 7ddd9fbe7b0..0795ecaf080 100644 --- a/chromium/storage/browser/blob/blob_url_registry_unittest.cc +++ b/chromium/storage/browser/blob/blob_url_registry_unittest.cc @@ -7,6 +7,7 @@ #include "base/callback.h" #include "base/run_loop.h" #include "base/test/task_environment.h" +#include "base/unguessable_token.h" #include "storage/browser/test/fake_blob.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -35,8 +36,10 @@ TEST(BlobUrlRegistry, URLRegistration) { const std::string kType = "type1"; const std::string kDisposition = "disp1"; const std::string kBlobId2 = "Blob2"; - const GURL kURL = GURL("blob://Blob1"); + const GURL kURL1 = GURL("blob://Blob1"); const GURL kURL2 = GURL("blob://Blob2"); + base::UnguessableToken kTokenId1 = base::UnguessableToken::Create(); + base::UnguessableToken kTokenId2 = base::UnguessableToken::Create(); base::test::SingleThreadTaskEnvironment task_environment_; @@ -44,26 +47,30 @@ TEST(BlobUrlRegistry, URLRegistration) { FakeBlob blob2(kBlobId2); BlobUrlRegistry registry; - EXPECT_FALSE(registry.IsUrlMapped(kURL)); - EXPECT_FALSE(registry.GetBlobFromUrl(kURL)); - EXPECT_FALSE(registry.RemoveUrlMapping(kURL)); + EXPECT_FALSE(registry.IsUrlMapped(kURL1)); + EXPECT_FALSE(registry.GetBlobFromUrl(kURL1)); + EXPECT_FALSE(registry.RemoveUrlMapping(kURL1)); EXPECT_EQ(0u, registry.url_count()); - EXPECT_TRUE(registry.AddUrlMapping(kURL, blob1.Clone())); - EXPECT_FALSE(registry.AddUrlMapping(kURL, blob2.Clone())); + EXPECT_TRUE(registry.AddUrlMapping(kURL1, blob1.Clone(), kTokenId1)); + EXPECT_FALSE(registry.AddUrlMapping(kURL1, blob2.Clone(), kTokenId1)); + EXPECT_EQ(kTokenId1, registry.GetUnsafeAgentClusterID(kURL1)); - EXPECT_TRUE(registry.IsUrlMapped(kURL)); - EXPECT_EQ(kBlobId1, UuidFromBlob(registry.GetBlobFromUrl(kURL))); + EXPECT_TRUE(registry.IsUrlMapped(kURL1)); + EXPECT_EQ(kBlobId1, UuidFromBlob(registry.GetBlobFromUrl(kURL1))); EXPECT_EQ(1u, registry.url_count()); - EXPECT_TRUE(registry.AddUrlMapping(kURL2, blob2.Clone())); + EXPECT_TRUE(registry.AddUrlMapping(kURL2, blob2.Clone(), kTokenId2)); + EXPECT_EQ(kTokenId2, registry.GetUnsafeAgentClusterID(kURL2)); EXPECT_EQ(2u, registry.url_count()); EXPECT_TRUE(registry.RemoveUrlMapping(kURL2)); EXPECT_FALSE(registry.IsUrlMapped(kURL2)); + EXPECT_EQ(absl::nullopt, registry.GetUnsafeAgentClusterID(kURL2)); // Both urls point to the same blob. - EXPECT_TRUE(registry.AddUrlMapping(kURL2, blob1.Clone())); - EXPECT_EQ(UuidFromBlob(registry.GetBlobFromUrl(kURL)), + EXPECT_TRUE(registry.AddUrlMapping(kURL2, blob1.Clone(), kTokenId2)); + EXPECT_EQ(kTokenId2, registry.GetUnsafeAgentClusterID(kURL2)); + EXPECT_EQ(UuidFromBlob(registry.GetBlobFromUrl(kURL1)), UuidFromBlob(registry.GetBlobFromUrl(kURL2))); } diff --git a/chromium/storage/browser/blob/blob_url_store_impl.cc b/chromium/storage/browser/blob/blob_url_store_impl.cc index b46ee60849c..09a93bcf4e1 100644 --- a/chromium/storage/browser/blob/blob_url_store_impl.cc +++ b/chromium/storage/browser/blob/blob_url_store_impl.cc @@ -69,9 +69,12 @@ BlobURLStoreImpl::~BlobURLStoreImpl() { } } -void BlobURLStoreImpl::Register(mojo::PendingRemote<blink::mojom::Blob> blob, - const GURL& url, - RegisterCallback callback) { +void BlobURLStoreImpl::Register( + mojo::PendingRemote<blink::mojom::Blob> blob, + const GURL& url, + // TODO(https://crbug.com/1224926): Remove this once experiment is over. + const base::UnguessableToken& unsafe_agent_cluster_id, + RegisterCallback callback) { if (!url.SchemeIsBlob()) { mojo::ReportBadMessage("Invalid scheme passed to BlobURLStore::Register"); std::move(callback).Run(); @@ -91,7 +94,7 @@ void BlobURLStoreImpl::Register(mojo::PendingRemote<blink::mojom::Blob> blob, } if (registry_) - registry_->AddUrlMapping(url, std::move(blob)); + registry_->AddUrlMapping(url, std::move(blob), unsafe_agent_cluster_id); urls_.insert(url); std::move(callback).Run(); } @@ -118,30 +121,39 @@ void BlobURLStoreImpl::Revoke(const GURL& url) { void BlobURLStoreImpl::Resolve(const GURL& url, ResolveCallback callback) { if (!registry_) { - std::move(callback).Run(mojo::NullRemote()); + std::move(callback).Run(mojo::NullRemote(), absl::nullopt); return; } mojo::PendingRemote<blink::mojom::Blob> blob = registry_->GetBlobFromUrl(url); - std::move(callback).Run(std::move(blob)); + std::move(callback).Run(std::move(blob), + registry_->GetUnsafeAgentClusterID(url)); } void BlobURLStoreImpl::ResolveAsURLLoaderFactory( const GURL& url, - mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) { + mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver, + ResolveAsURLLoaderFactoryCallback callback) { BlobURLLoaderFactory::Create( registry_ ? registry_->GetBlobFromUrl(url) : mojo::NullRemote(), url, std::move(receiver)); + std::move(callback).Run(registry_->GetUnsafeAgentClusterID(url)); } void BlobURLStoreImpl::ResolveForNavigation( const GURL& url, - mojo::PendingReceiver<blink::mojom::BlobURLToken> token) { - if (!registry_) + mojo::PendingReceiver<blink::mojom::BlobURLToken> token, + ResolveForNavigationCallback callback) { + if (!registry_) { + std::move(callback).Run(absl::nullopt); return; + } mojo::PendingRemote<blink::mojom::Blob> blob = registry_->GetBlobFromUrl(url); - if (!blob) + if (!blob) { + std::move(callback).Run(absl::nullopt); return; + } new BlobURLTokenImpl(registry_, url, std::move(blob), std::move(token)); + std::move(callback).Run(registry_->GetUnsafeAgentClusterID(url)); } } // namespace storage diff --git a/chromium/storage/browser/blob/blob_url_store_impl.h b/chromium/storage/browser/blob/blob_url_store_impl.h index 6b4a738a464..9c6d3bfdc6a 100644 --- a/chromium/storage/browser/blob/blob_url_store_impl.h +++ b/chromium/storage/browser/blob/blob_url_store_impl.h @@ -8,6 +8,7 @@ #include <memory> #include "base/component_export.h" +#include "base/unguessable_token.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" @@ -25,18 +26,22 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobURLStoreImpl BlobRegistryImpl::Delegate* delegate); ~BlobURLStoreImpl() override; - void Register(mojo::PendingRemote<blink::mojom::Blob> blob, - const GURL& url, - RegisterCallback callback) override; + void Register( + mojo::PendingRemote<blink::mojom::Blob> blob, + const GURL& url, + // TODO(https://crbug.com/1224926): Remove this once experiment is over. + const base::UnguessableToken& unsafe_agent_cluster_id, + RegisterCallback callback) override; void Revoke(const GURL& url) override; void Resolve(const GURL& url, ResolveCallback callback) override; void ResolveAsURLLoaderFactory( const GURL& url, - mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) - override; + mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver, + ResolveAsURLLoaderFactoryCallback callback) override; void ResolveForNavigation( const GURL& url, - mojo::PendingReceiver<blink::mojom::BlobURLToken> token) override; + mojo::PendingReceiver<blink::mojom::BlobURLToken> token, + ResolveForNavigationCallback callback) override; private: base::WeakPtr<BlobUrlRegistry> registry_; 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 69428d0adeb..daf2ea331ac 100644 --- a/chromium/storage/browser/blob/blob_url_store_impl_unittest.cc +++ b/chromium/storage/browser/blob/blob_url_store_impl_unittest.cc @@ -8,9 +8,11 @@ #include "base/callback_helpers.h" #include "base/test/bind.h" #include "base/test/task_environment.h" +#include "base/unguessable_token.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/resource_request.h" #include "services/network/public/cpp/simple_url_loader.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" #include "storage/browser/blob/blob_data_builder.h" @@ -28,6 +30,7 @@ class BlobURLStoreImplTest : public testing::Test { public: void SetUp() override { context_ = std::make_unique<BlobStorageContext>(); + agent_cluster_id_ = base::UnguessableToken::Create(); mojo::SetDefaultProcessErrorHandler(base::BindRepeating( &BlobURLStoreImplTest::OnBadMessage, base::Unretained(this))); @@ -79,7 +82,8 @@ class BlobURLStoreImplTest : public testing::Test { mojo::PendingRemote<blink::mojom::Blob> blob, const GURL& url) { base::RunLoop loop; - store->Register(std::move(blob), url, loop.QuitClosure()); + store->Register(std::move(blob), url, agent_cluster_id_, + loop.QuitClosure()); loop.Run(); } @@ -91,11 +95,16 @@ class BlobURLStoreImplTest : public testing::Test { base::BindOnce( [](base::OnceClosure done, mojo::PendingRemote<blink::mojom::Blob>* blob_out, - mojo::PendingRemote<blink::mojom::Blob> blob) { + const base::UnguessableToken& agent_registered, + mojo::PendingRemote<blink::mojom::Blob> blob, + const absl::optional<base::UnguessableToken>& + unsafe_agent_cluster_id) { + if (blob) + EXPECT_EQ(agent_registered, unsafe_agent_cluster_id); *blob_out = std::move(blob); std::move(done).Run(); }, - loop.QuitClosure(), &result)); + loop.QuitClosure(), &result, agent_cluster_id_)); loop.Run(); return result; } @@ -111,6 +120,7 @@ class BlobURLStoreImplTest : public testing::Test { BlobUrlRegistry url_registry_; MockBlobRegistryDelegate delegate_; std::vector<std::string> bad_messages_; + base::UnguessableToken agent_cluster_id_; }; TEST_F(BlobURLStoreImplTest, BasicRegisterRevoke) { @@ -269,22 +279,33 @@ TEST_F(BlobURLStoreImplTest, ResolveAsURLLoaderFactory) { RegisterURL(&url_store, std::move(blob), kValidUrl); mojo::Remote<network::mojom::URLLoaderFactory> factory; - url_store.ResolveAsURLLoaderFactory(kValidUrl, - factory.BindNewPipeAndPassReceiver()); + base::RunLoop resolve_loop; + url_store.ResolveAsURLLoaderFactory( + kValidUrl, factory.BindNewPipeAndPassReceiver(), + base::BindOnce( + [](base::OnceClosure done, + const base::UnguessableToken& agent_registered, + const absl::optional<base::UnguessableToken>& + unsafe_agent_cluster_id) { + EXPECT_EQ(agent_registered, unsafe_agent_cluster_id); + std::move(done).Run(); + }, + resolve_loop.QuitClosure(), agent_cluster_id_)); + resolve_loop.Run(); auto request = std::make_unique<network::ResourceRequest>(); request->url = kValidUrl; auto loader = network::SimpleURLLoader::Create(std::move(request), TRAFFIC_ANNOTATION_FOR_TESTS); - base::RunLoop loop; + base::RunLoop download_loop; loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie( factory.get(), base::BindLambdaForTesting( [&](std::unique_ptr<std::string> response_body) { - loop.Quit(); + download_loop.Quit(); ASSERT_TRUE(response_body); EXPECT_EQ("hello world", *response_body); })); - loop.Run(); + download_loop.Run(); } TEST_F(BlobURLStoreImplTest, ResolveForNavigation) { @@ -294,9 +315,20 @@ TEST_F(BlobURLStoreImplTest, ResolveForNavigation) { BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_); RegisterURL(&url_store, std::move(blob), kValidUrl); + base::RunLoop loop0; mojo::Remote<blink::mojom::BlobURLToken> token_remote; - url_store.ResolveForNavigation(kValidUrl, - token_remote.BindNewPipeAndPassReceiver()); + url_store.ResolveForNavigation( + kValidUrl, token_remote.BindNewPipeAndPassReceiver(), + base::BindOnce( + [](base::OnceClosure done, + const base::UnguessableToken& agent_registered, + const absl::optional<base::UnguessableToken>& + unsafe_agent_cluster_id) { + EXPECT_EQ(agent_registered, unsafe_agent_cluster_id); + std::move(done).Run(); + }, + loop0.QuitClosure(), agent_cluster_id_)); + loop0.Run(); base::UnguessableToken token; base::RunLoop loop; diff --git a/chromium/storage/browser/blob/blob_url_utils.h b/chromium/storage/browser/blob/blob_url_utils.h index 4c125ecf59b..de742e2485a 100644 --- a/chromium/storage/browser/blob/blob_url_utils.h +++ b/chromium/storage/browser/blob/blob_url_utils.h @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifndef STORAGE_BROWSER_BLOB_BLOB_URL_UTILS_H_ +#define STORAGE_BROWSER_BLOB_BLOB_URL_UTILS_H_ + #include "url/gurl.h" namespace storage { @@ -21,3 +24,5 @@ GURL ClearUrlFragment(const GURL& url); } // namespace BlobUrlUtils } // namespace storage + +#endif // STORAGE_BROWSER_BLOB_BLOB_URL_UTILS_H_
\ No newline at end of file diff --git a/chromium/storage/browser/blob/mojo_blob_reader.cc b/chromium/storage/browser/blob/mojo_blob_reader.cc index 2b201986cb0..d5f4c9e9b4b 100644 --- a/chromium/storage/browser/blob/mojo_blob_reader.cc +++ b/chromium/storage/browser/blob/mojo_blob_reader.cc @@ -38,7 +38,8 @@ MojoBlobReader::MojoBlobReader( peer_closed_handle_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL, base::SequencedTaskRunnerHandle::Get()) { - TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobReader", this, "uuid", handle->uuid()); + TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("Blob", "BlobReader", TRACE_ID_LOCAL(this), + "uuid", handle->uuid()); DCHECK(delegate_); base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, @@ -47,8 +48,8 @@ MojoBlobReader::MojoBlobReader( MojoBlobReader::~MojoBlobReader() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - TRACE_EVENT_ASYNC_END1("Blob", "BlobReader", this, "bytes_written", - total_written_bytes_); + TRACE_EVENT_NESTABLE_ASYNC_END1("Blob", "BlobReader", TRACE_ID_LOCAL(this), + "bytes_written", total_written_bytes_); } void MojoBlobReader::Start() { @@ -59,13 +60,14 @@ void MojoBlobReader::Start() { return; } - TRACE_EVENT_ASYNC_BEGIN0("Blob", "BlobReader::CountSize", this); + TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("Blob", "BlobReader::CountSize", + TRACE_ID_LOCAL(this)); BlobReader::Status size_status = blob_reader_->CalculateSize(base::BindOnce( &MojoBlobReader::DidCalculateSize, base::Unretained(this))); switch (size_status) { case BlobReader::Status::NET_ERROR: - TRACE_EVENT_ASYNC_END1("Blob", "BlobReader::CountSize", this, "result", - "error"); + TRACE_EVENT_NESTABLE_ASYNC_END1("Blob", "BlobReader::CountSize", + TRACE_ID_LOCAL(this), "result", "error"); NotifyCompletedAndDeleteIfNeeded(blob_reader_->net_error()); return; case BlobReader::Status::IO_PENDING: @@ -100,14 +102,15 @@ void MojoBlobReader::DidCalculateSize(int result) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (result != net::OK) { - TRACE_EVENT_ASYNC_END1("Blob", "BlobReader::CountSize", this, "result", - "error"); + TRACE_EVENT_NESTABLE_ASYNC_END1("Blob", "BlobReader::CountSize", + TRACE_ID_LOCAL(this), "result", "error"); NotifyCompletedAndDeleteIfNeeded(result); return; } - TRACE_EVENT_ASYNC_END2("Blob", "BlobReader::CountSize", this, "result", - "success", "size", blob_reader_->total_size()); + TRACE_EVENT_NESTABLE_ASYNC_END2("Blob", "BlobReader::CountSize", + TRACE_ID_LOCAL(this), "result", "success", + "size", blob_reader_->total_size()); // Apply the range requirement. if (!byte_range_.ComputeBounds(blob_reader_->total_size())) { @@ -219,7 +222,8 @@ void MojoBlobReader::ReadMore() { num_bytes = std::min(num_bytes, blink::BlobUtils::GetDataPipeChunkSize()); - TRACE_EVENT_ASYNC_BEGIN0("Blob", "BlobReader::ReadMore", this); + TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("Blob", "BlobReader::ReadMore", + TRACE_ID_LOCAL(this)); CHECK_GT(static_cast<uint32_t>(std::numeric_limits<int>::max()), num_bytes); DCHECK(pending_write_); auto buf = @@ -245,8 +249,9 @@ void MojoBlobReader::DidRead(bool completed_synchronously, int num_bytes) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (num_bytes < 0) { - TRACE_EVENT_ASYNC_END2("Blob", "BlobReader::ReadMore", this, "result", - "error", "net_error", num_bytes); + TRACE_EVENT_NESTABLE_ASYNC_END2("Blob", "BlobReader::ReadMore", + TRACE_ID_LOCAL(this), "result", "error", + "net_error", num_bytes); writable_handle_watcher_.Cancel(); pending_write_->Complete(0); pending_write_ = nullptr; // This closes the data pipe. @@ -255,8 +260,9 @@ void MojoBlobReader::DidRead(bool completed_synchronously, int num_bytes) { } if (num_bytes > 0) delegate_->DidRead(num_bytes); - TRACE_EVENT_ASYNC_END2("Blob", "BlobReader::ReadMore", this, "result", - "success", "num_bytes", num_bytes); + TRACE_EVENT_NESTABLE_ASYNC_END2("Blob", "BlobReader::ReadMore", + TRACE_ID_LOCAL(this), "result", "success", + "num_bytes", num_bytes); response_body_stream_ = pending_write_->Complete(num_bytes); total_written_bytes_ += num_bytes; pending_write_ = nullptr; diff --git a/chromium/storage/browser/blob/mojo_blob_reader.h b/chromium/storage/browser/blob/mojo_blob_reader.h index 96b3b0e08e9..f2c88b4b4b9 100644 --- a/chromium/storage/browser/blob/mojo_blob_reader.h +++ b/chromium/storage/browser/blob/mojo_blob_reader.h @@ -15,6 +15,7 @@ #include "net/base/net_errors.h" #include "net/http/http_byte_range.h" #include "storage/browser/blob/blob_reader.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace network { class NetToMojoPendingBuffer; diff --git a/chromium/storage/browser/database/DIR_METADATA b/chromium/storage/browser/database/DIR_METADATA index 67bdd01e3be..5bb86736d89 100644 --- a/chromium/storage/browser/database/DIR_METADATA +++ b/chromium/storage/browser/database/DIR_METADATA @@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Blink>Storage>WebSQL" diff --git a/chromium/storage/browser/database/database_quota_client.cc b/chromium/storage/browser/database/database_quota_client.cc index c297fb3e228..da8579fead9 100644 --- a/chromium/storage/browser/database/database_quota_client.cc +++ b/chromium/storage/browser/database/database_quota_client.cc @@ -24,144 +24,100 @@ #include "storage/browser/database/database_util.h" #include "storage/browser/quota/quota_client_type.h" #include "storage/common/database/database_identifier.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" #include "url/origin.h" -using blink::mojom::StorageType; +using ::blink::StorageKey; +using ::blink::mojom::StorageType; namespace storage { -namespace { - -int64_t GetOriginUsageOnDBThread(DatabaseTracker* db_tracker, - const url::Origin& origin) { - OriginInfo info; - if (db_tracker->GetOriginInfo(GetIdentifierFromOrigin(origin), &info)) - return info.TotalSize(); - return 0; -} - -std::vector<url::Origin> GetOriginsOnDBThread(DatabaseTracker* db_tracker) { - std::vector<url::Origin> all_origins; - std::vector<std::string> origin_identifiers; - if (db_tracker->GetAllOriginIdentifiers(&origin_identifiers)) { - all_origins.reserve(origin_identifiers.size()); - for (const auto& identifier : origin_identifiers) { - all_origins.push_back(GetOriginFromIdentifier(identifier)); - } - } - return all_origins; -} - -std::vector<url::Origin> GetOriginsForHostOnDBThread( - DatabaseTracker* db_tracker, - const std::string& host) { - std::vector<url::Origin> host_origins; - // In the vast majority of cases, this vector will end up with exactly one - // origin. The origin will be https://host or http://host. - host_origins.reserve(1); - - std::vector<std::string> origin_identifiers; - if (db_tracker->GetAllOriginIdentifiers(&origin_identifiers)) { - for (const auto& identifier : origin_identifiers) { - url::Origin origin = GetOriginFromIdentifier(identifier); - if (host == origin.host()) - host_origins.push_back(std::move(origin)); - } - } - return host_origins; -} - -void DidDeleteOriginData( - scoped_refptr<base::SequencedTaskRunner> original_task_runner, - QuotaClient::DeleteOriginDataCallback callback, - int result) { - blink::mojom::QuotaStatusCode status; - if (result == net::OK) - status = blink::mojom::QuotaStatusCode::kOk; - else - status = blink::mojom::QuotaStatusCode::kUnknown; - - original_task_runner->PostTask(FROM_HERE, - base::BindOnce(std::move(callback), status)); -} - -} // namespace - -DatabaseQuotaClient::DatabaseQuotaClient( - scoped_refptr<DatabaseTracker> db_tracker) - : db_tracker_(std::move(db_tracker)) { - DCHECK(db_tracker_.get()); - +DatabaseQuotaClient::DatabaseQuotaClient(DatabaseTracker& db_tracker) + : db_tracker_(db_tracker) { DETACH_FROM_SEQUENCE(sequence_checker_); } DatabaseQuotaClient::~DatabaseQuotaClient() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!db_tracker_->task_runner()->RunsTasksInCurrentSequence()) { - db_tracker_->task_runner()->ReleaseSoon(FROM_HERE, std::move(db_tracker_)); - } -} - -void DatabaseQuotaClient::OnQuotaManagerDestroyed() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); } -void DatabaseQuotaClient::GetOriginUsage(const url::Origin& origin, - StorageType type, - GetOriginUsageCallback callback) { +void DatabaseQuotaClient::GetStorageKeyUsage( + const StorageKey& storage_key, + StorageType type, + GetStorageKeyUsageCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!callback.is_null()); DCHECK_EQ(type, StorageType::kTemporary); - db_tracker_->task_runner()->PostTaskAndReplyWithResult( - FROM_HERE, - base::BindOnce(&GetOriginUsageOnDBThread, base::RetainedRef(db_tracker_), - origin), - std::move(callback)); + OriginInfo info; + if (db_tracker_.GetOriginInfo(GetIdentifierFromOrigin(storage_key.origin()), + &info)) { + std::move(callback).Run(info.TotalSize()); + } else { + std::move(callback).Run(0); + } } -void DatabaseQuotaClient::GetOriginsForType( +void DatabaseQuotaClient::GetStorageKeysForType( StorageType type, - GetOriginsForTypeCallback callback) { + GetStorageKeysForTypeCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!callback.is_null()); DCHECK_EQ(type, StorageType::kTemporary); - db_tracker_->task_runner()->PostTaskAndReplyWithResult( - FROM_HERE, - base::BindOnce(&GetOriginsOnDBThread, base::RetainedRef(db_tracker_)), - std::move(callback)); + std::vector<StorageKey> all_storage_keys; + std::vector<std::string> origin_identifiers; + if (db_tracker_.GetAllOriginIdentifiers(&origin_identifiers)) { + all_storage_keys.reserve(origin_identifiers.size()); + for (const auto& identifier : origin_identifiers) + all_storage_keys.emplace_back( + StorageKey(GetOriginFromIdentifier(identifier))); + } + std::move(callback).Run(all_storage_keys); } -void DatabaseQuotaClient::GetOriginsForHost( +void DatabaseQuotaClient::GetStorageKeysForHost( StorageType type, const std::string& host, - GetOriginsForHostCallback callback) { + GetStorageKeysForHostCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!callback.is_null()); DCHECK_EQ(type, StorageType::kTemporary); - db_tracker_->task_runner()->PostTaskAndReplyWithResult( - FROM_HERE, - base::BindOnce(&GetOriginsForHostOnDBThread, - base::RetainedRef(db_tracker_), host), - std::move(callback)); + std::vector<StorageKey> host_storage_keys; + // In the vast majority of cases, this vector will end up with exactly one + // storage key. The storage key will be https://host or http://host. + host_storage_keys.reserve(1); + + std::vector<std::string> origin_identifiers; + if (db_tracker_.GetAllOriginIdentifiers(&origin_identifiers)) { + for (const auto& identifier : origin_identifiers) { + StorageKey storage_key = StorageKey(GetOriginFromIdentifier(identifier)); + if (host == storage_key.origin().host()) + host_storage_keys.push_back(std::move(storage_key)); + } + } + std::move(callback).Run(host_storage_keys); } -void DatabaseQuotaClient::DeleteOriginData(const url::Origin& origin, - StorageType type, - DeleteOriginDataCallback callback) { +void DatabaseQuotaClient::DeleteStorageKeyData( + const StorageKey& storage_key, + StorageType type, + DeleteStorageKeyDataCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!callback.is_null()); DCHECK_EQ(type, StorageType::kTemporary); - db_tracker_->task_runner()->PostTask( - FROM_HERE, - base::BindOnce(&DatabaseTracker::DeleteDataForOrigin, db_tracker_, origin, - base::BindOnce(&DidDeleteOriginData, - base::SequencedTaskRunnerHandle::Get(), - std::move(callback)))); + db_tracker_.DeleteDataForOrigin( + storage_key.origin(), + base::BindOnce( + [](DeleteStorageKeyDataCallback callback, int result) { + std::move(callback).Run( + (result == net::OK) ? blink::mojom::QuotaStatusCode::kOk + : blink::mojom::QuotaStatusCode::kUnknown); + }, + std::move(callback))); } void DatabaseQuotaClient::PerformStorageCleanup( diff --git a/chromium/storage/browser/database/database_quota_client.h b/chromium/storage/browser/database/database_quota_client.h index f098ee618c9..2a43801d2a2 100644 --- a/chromium/storage/browser/database/database_quota_client.h +++ b/chromium/storage/browser/database/database_quota_client.h @@ -14,10 +14,13 @@ #include "base/sequence_checker.h" #include "base/single_thread_task_runner.h" #include "base/thread_annotations.h" -#include "storage/browser/quota/quota_client.h" +#include "components/services/storage/public/cpp/storage_key_quota_client.h" #include "storage/browser/quota/quota_client_type.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" -#include "url/origin.h" + +namespace blink { +class StorageKey; +} // namespace blink namespace storage { @@ -27,39 +30,35 @@ class DatabaseTracker; // // This interface is used on the IO thread by the quota manager. class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseQuotaClient - : public QuotaClient { + : public StorageKeyQuotaClient { public: - explicit DatabaseQuotaClient(scoped_refptr<DatabaseTracker> tracker); + explicit DatabaseQuotaClient(DatabaseTracker& tracker); DatabaseQuotaClient(const DatabaseQuotaClient&) = delete; DatabaseQuotaClient& operator=(const DatabaseQuotaClient&) = delete; - // QuotaClient method overrides - void OnQuotaManagerDestroyed() override; - void GetOriginUsage(const url::Origin& origin, - blink::mojom::StorageType type, - GetOriginUsageCallback callback) override; - void GetOriginsForType(blink::mojom::StorageType type, - GetOriginsForTypeCallback callback) override; - void GetOriginsForHost(blink::mojom::StorageType type, - const std::string& host, - GetOriginsForHostCallback callback) override; - void DeleteOriginData(const url::Origin& origin, - blink::mojom::StorageType type, - DeleteOriginDataCallback callback) override; + ~DatabaseQuotaClient() override; + + // StorageKeyQuotaClient method overrides. + void GetStorageKeyUsage(const blink::StorageKey& storage_key, + blink::mojom::StorageType type, + GetStorageKeyUsageCallback callback) override; + void GetStorageKeysForType(blink::mojom::StorageType type, + GetStorageKeysForTypeCallback callback) override; + void GetStorageKeysForHost(blink::mojom::StorageType type, + const std::string& host, + GetStorageKeysForHostCallback callback) override; + void DeleteStorageKeyData(const blink::StorageKey& storage_key, + blink::mojom::StorageType type, + DeleteStorageKeyDataCallback callback) override; void PerformStorageCleanup(blink::mojom::StorageType type, PerformStorageCleanupCallback callback) override; private: - ~DatabaseQuotaClient() override; - SEQUENCE_CHECKER(sequence_checker_); - // The scoped_refptr is only be dereferenced on the QuotaClient's sequence. - // However, the DatabaseTracker it points to must only be used on the database - // sequence. - scoped_refptr<DatabaseTracker> db_tracker_ - GUARDED_BY_CONTEXT(sequence_checker_); + // Reference use is safe here because the DatabaseTracker owns this. + DatabaseTracker& db_tracker_ GUARDED_BY_CONTEXT(sequence_checker_); }; } // namespace storage diff --git a/chromium/storage/browser/database/database_quota_client_unittest.cc b/chromium/storage/browser/database/database_quota_client_unittest.cc index 203e3541364..88fa9575363 100644 --- a/chromium/storage/browser/database/database_quota_client_unittest.cc +++ b/chromium/storage/browser/database/database_quota_client_unittest.cc @@ -21,15 +21,18 @@ #include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/threading/sequenced_task_runner_handle.h" +#include "components/services/storage/public/mojom/quota_client.mojom.h" #include "net/base/completion_once_callback.h" #include "net/base/net_errors.h" #include "storage/browser/database/database_quota_client.h" #include "storage/browser/database/database_tracker.h" #include "storage/browser/database/database_util.h" -#include "storage/browser/quota/quota_client.h" +#include "storage/browser/quota/quota_manager_proxy.h" +#include "storage/browser/quota/special_storage_policy.h" #include "storage/common/database/database_identifier.h" #include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" #include "url/gurl.h" #include "url/origin.h" @@ -40,12 +43,15 @@ namespace storage { static const blink::mojom::StorageType kTemp = blink::mojom::StorageType::kTemporary; -// Mock tracker class the mocks up those methods of the tracker -// that are used by the QuotaClient. +// Mocks DatabaseTracker methods used by DatabaseQuotaClient. class MockDatabaseTracker : public DatabaseTracker { public: MockDatabaseTracker() - : DatabaseTracker(base::FilePath(), false, nullptr, nullptr) {} + : DatabaseTracker(base::FilePath(), + /*is_incognito=*/false, + /*special_storage_policy=*/nullptr, + /*quota_manager_proxy=*/nullptr, + DatabaseTracker::CreatePassKey()) {} bool GetOriginInfo(const std::string& origin_identifier, OriginInfo* info) override { @@ -88,7 +94,7 @@ class MockDatabaseTracker : public DatabaseTracker { } void AddMockDatabase(const url::Origin& origin, const char* name, int size) { - MockOriginInfo& info = mock_origin_infos_[origin]; + MockStorageKeyInfo& info = mock_origin_infos_[origin]; info.set_origin(GetIdentifierFromOrigin(origin)); info.AddMockDatabase(base::ASCIIToUTF16(name), size); } @@ -101,7 +107,7 @@ class MockDatabaseTracker : public DatabaseTracker { ~MockDatabaseTracker() override = default; private: - class MockOriginInfo : public OriginInfo { + class MockStorageKeyInfo : public OriginInfo { public: void set_origin(const std::string& origin_identifier) { origin_identifier_ = origin_identifier; @@ -116,77 +122,91 @@ class MockDatabaseTracker : public DatabaseTracker { int delete_called_count_ = 0; bool async_delete_ = false; - std::map<url::Origin, MockOriginInfo> mock_origin_infos_; + std::map<url::Origin, MockStorageKeyInfo> mock_origin_infos_; }; // Base class for our test fixtures. class DatabaseQuotaClientTest : public testing::Test { public: - const url::Origin kOriginA; - const url::Origin kOriginB; - const url::Origin kOriginOther; + const blink::StorageKey kStorageKeyA; + const blink::StorageKey kStorageKeyB; + const blink::StorageKey kStorageKeyOther; DatabaseQuotaClientTest() - : kOriginA(url::Origin::Create(GURL("http://host"))), - kOriginB(url::Origin::Create(GURL("http://host:8000"))), - kOriginOther(url::Origin::Create(GURL("http://other"))), + : kStorageKeyA( + blink::StorageKey::CreateFromStringForTesting("http://host")), + kStorageKeyB( + blink::StorageKey::CreateFromStringForTesting("http://host:8000")), + kStorageKeyOther( + blink::StorageKey::CreateFromStringForTesting("http://other")), mock_tracker_(base::MakeRefCounted<MockDatabaseTracker>()) {} - static int64_t GetOriginUsage(QuotaClient& client, - const url::Origin& origin, - blink::mojom::StorageType type) { + void TearDown() override { + base::RunLoop run_loop; + mock_tracker_->task_runner()->PostTask(FROM_HERE, + base::BindLambdaForTesting([&]() { + mock_tracker_->Shutdown(); + run_loop.Quit(); + })); + run_loop.Run(); + } + + static int64_t GetStorageKeyUsage(mojom::QuotaClient& client, + const blink::StorageKey& storage_key, + blink::mojom::StorageType type) { int result = -1; base::RunLoop loop; - client.GetOriginUsage(origin, type, - base::BindLambdaForTesting([&](int64_t usage) { - result = usage; - loop.Quit(); - })); + client.GetStorageKeyUsage(storage_key, type, + base::BindLambdaForTesting([&](int64_t usage) { + result = usage; + loop.Quit(); + })); loop.Run(); EXPECT_GT(result, -1); return result; } - static std::vector<url::Origin> GetOriginsForType( - QuotaClient& client, + static std::vector<blink::StorageKey> GetStorageKeysForType( + mojom::QuotaClient& client, blink::mojom::StorageType type) { - std::vector<url::Origin> result; + std::vector<blink::StorageKey> result; base::RunLoop loop; - client.GetOriginsForType(type, - base::BindLambdaForTesting( - [&](const std::vector<url::Origin>& origins) { - result = origins; - loop.Quit(); - })); + client.GetStorageKeysForType( + type, base::BindLambdaForTesting( + [&](const std::vector<blink::StorageKey>& storage_keys) { + result = storage_keys; + loop.Quit(); + })); loop.Run(); return result; } - static std::vector<url::Origin> GetOriginsForHost( - QuotaClient& client, + static std::vector<blink::StorageKey> GetStorageKeysForHost( + mojom::QuotaClient& client, blink::mojom::StorageType type, const std::string& host) { - std::vector<url::Origin> result; + std::vector<blink::StorageKey> result; base::RunLoop loop; - client.GetOriginsForHost(type, host, - base::BindLambdaForTesting( - [&](const std::vector<url::Origin>& origins) { - result = origins; - loop.Quit(); - })); + client.GetStorageKeysForHost( + type, host, + base::BindLambdaForTesting( + [&](const std::vector<blink::StorageKey>& storage_keys) { + result = storage_keys; + loop.Quit(); + })); loop.Run(); return result; } - static blink::mojom::QuotaStatusCode DeleteOriginData( - QuotaClient& client, + static blink::mojom::QuotaStatusCode DeleteStorageKeyData( + mojom::QuotaClient& client, blink::mojom::StorageType type, - const url::Origin& origin) { + const blink::StorageKey& storage_key) { blink::mojom::QuotaStatusCode result = blink::mojom::QuotaStatusCode::kUnknown; base::RunLoop loop; - client.DeleteOriginData( - origin, type, + client.DeleteStorageKeyData( + storage_key, type, base::BindLambdaForTesting([&](blink::mojom::QuotaStatusCode code) { result = code; loop.Quit(); @@ -200,63 +220,68 @@ class DatabaseQuotaClientTest : public testing::Test { base::WeakPtrFactory<DatabaseQuotaClientTest> weak_factory_{this}; }; -TEST_F(DatabaseQuotaClientTest, GetOriginUsage) { - auto client = base::MakeRefCounted<DatabaseQuotaClient>(mock_tracker_); +TEST_F(DatabaseQuotaClientTest, GetStorageKeyUsage) { + DatabaseQuotaClient client(*mock_tracker_); - EXPECT_EQ(0, GetOriginUsage(*client, kOriginA, kTemp)); + EXPECT_EQ(0, GetStorageKeyUsage(client, kStorageKeyA, kTemp)); - mock_tracker_->AddMockDatabase(kOriginA, "fooDB", 1000); - EXPECT_EQ(1000, GetOriginUsage(*client, kOriginA, kTemp)); + mock_tracker_->AddMockDatabase(kStorageKeyA.origin(), "fooDB", 1000); + EXPECT_EQ(1000, GetStorageKeyUsage(client, kStorageKeyA, kTemp)); - EXPECT_EQ(0, GetOriginUsage(*client, kOriginB, kTemp)); + EXPECT_EQ(0, GetStorageKeyUsage(client, kStorageKeyB, kTemp)); } -TEST_F(DatabaseQuotaClientTest, GetOriginsForHost) { - auto client = base::MakeRefCounted<DatabaseQuotaClient>(mock_tracker_); +TEST_F(DatabaseQuotaClientTest, GetStorageKeysForHost) { + DatabaseQuotaClient client(*mock_tracker_); - EXPECT_EQ(kOriginA.host(), kOriginB.host()); - EXPECT_NE(kOriginA.host(), kOriginOther.host()); + EXPECT_EQ(kStorageKeyA.origin().host(), kStorageKeyB.origin().host()); + EXPECT_NE(kStorageKeyA.origin().host(), kStorageKeyOther.origin().host()); - std::vector<url::Origin> origins = - GetOriginsForHost(*client, kTemp, kOriginA.host()); - EXPECT_TRUE(origins.empty()); + std::vector<blink::StorageKey> storage_keys = + GetStorageKeysForHost(client, kTemp, kStorageKeyA.origin().host()); + EXPECT_TRUE(storage_keys.empty()); - mock_tracker_->AddMockDatabase(kOriginA, "fooDB", 1000); - origins = GetOriginsForHost(*client, kTemp, kOriginA.host()); - EXPECT_EQ(origins.size(), 1ul); - EXPECT_THAT(origins, testing::Contains(kOriginA)); + mock_tracker_->AddMockDatabase(kStorageKeyA.origin(), "fooDB", 1000); + storage_keys = + GetStorageKeysForHost(client, kTemp, kStorageKeyA.origin().host()); + EXPECT_EQ(storage_keys.size(), 1ul); + EXPECT_THAT(storage_keys, testing::Contains(kStorageKeyA)); - mock_tracker_->AddMockDatabase(kOriginB, "barDB", 1000); - origins = GetOriginsForHost(*client, kTemp, kOriginA.host()); - EXPECT_EQ(origins.size(), 2ul); - EXPECT_THAT(origins, testing::Contains(kOriginA)); - EXPECT_THAT(origins, testing::Contains(kOriginB)); + mock_tracker_->AddMockDatabase(kStorageKeyB.origin(), "barDB", 1000); + storage_keys = + GetStorageKeysForHost(client, kTemp, kStorageKeyA.origin().host()); + EXPECT_EQ(storage_keys.size(), 2ul); + EXPECT_THAT(storage_keys, testing::Contains(kStorageKeyA)); + EXPECT_THAT(storage_keys, testing::Contains(kStorageKeyB)); - EXPECT_TRUE(GetOriginsForHost(*client, kTemp, kOriginOther.host()).empty()); + EXPECT_TRUE( + GetStorageKeysForHost(client, kTemp, kStorageKeyOther.origin().host()) + .empty()); } -TEST_F(DatabaseQuotaClientTest, GetOriginsForType) { - auto client = base::MakeRefCounted<DatabaseQuotaClient>(mock_tracker_); +TEST_F(DatabaseQuotaClientTest, GetStorageKeysForType) { + DatabaseQuotaClient client(*mock_tracker_); - EXPECT_TRUE(GetOriginsForType(*client, kTemp).empty()); + EXPECT_TRUE(GetStorageKeysForType(client, kTemp).empty()); - mock_tracker_->AddMockDatabase(kOriginA, "fooDB", 1000); - std::vector<url::Origin> origins = GetOriginsForType(*client, kTemp); - EXPECT_EQ(origins.size(), 1ul); - EXPECT_THAT(origins, testing::Contains(kOriginA)); + mock_tracker_->AddMockDatabase(kStorageKeyA.origin(), "fooDB", 1000); + std::vector<blink::StorageKey> storage_keys = + GetStorageKeysForType(client, kTemp); + EXPECT_EQ(storage_keys.size(), 1ul); + EXPECT_THAT(storage_keys, testing::Contains(kStorageKeyA)); } -TEST_F(DatabaseQuotaClientTest, DeleteOriginData) { - auto client = base::MakeRefCounted<DatabaseQuotaClient>(mock_tracker_); +TEST_F(DatabaseQuotaClientTest, DeleteStorageKeyData) { + DatabaseQuotaClient client(*mock_tracker_); mock_tracker_->set_async_delete(false); EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, - DeleteOriginData(*client, kTemp, kOriginA)); + DeleteStorageKeyData(client, kTemp, kStorageKeyA)); EXPECT_EQ(1, mock_tracker_->delete_called_count()); mock_tracker_->set_async_delete(true); EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, - DeleteOriginData(*client, kTemp, kOriginA)); + DeleteStorageKeyData(client, kTemp, kStorageKeyA)); 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 2bdd932ceb3..c96e3fad1a7 100644 --- a/chromium/storage/browser/database/database_tracker.cc +++ b/chromium/storage/browser/database/database_tracker.cc @@ -8,17 +8,28 @@ #include <algorithm> #include <memory> +#include <string> +#include <utility> +#include <vector> #include "base/bind.h" #include "base/callback_helpers.h" #include "base/files/file_enumerator.h" +#include "base/files/file_path.h" #include "base/files/file_util.h" +#include "base/location.h" +#include "base/memory/scoped_refptr.h" #include "base/metrics/user_metrics.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" #include "base/task/thread_pool.h" #include "base/time/time.h" +#include "base/types/pass_key.h" +#include "components/services/storage/public/cpp/quota_client_callback_wrapper.h" +#include "components/services/storage/public/mojom/quota_client.mojom.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "net/base/net_errors.h" #include "sql/database.h" #include "sql/meta_table.h" @@ -30,8 +41,10 @@ #include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/quota/special_storage_policy.h" #include "storage/common/database/database_identifier.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" #include "third_party/sqlite/sqlite3.h" +#include "url/gurl.h" #include "url/origin.h" namespace storage { @@ -73,32 +86,84 @@ int64_t OriginInfo::GetDatabaseSize(const std::u16string& database_name) const { OriginInfo::OriginInfo(const std::string& origin_identifier, int64_t total_size) : origin_identifier_(origin_identifier), total_size_(total_size) {} -DatabaseTracker::DatabaseTracker(const base::FilePath& profile_path, - bool is_incognito, - SpecialStoragePolicy* special_storage_policy, - QuotaManagerProxy* quota_manager_proxy) +scoped_refptr<DatabaseTracker> DatabaseTracker::Create( + const base::FilePath& profile_path, + bool is_incognito, + scoped_refptr<SpecialStoragePolicy> special_storage_policy, + scoped_refptr<QuotaManagerProxy> quota_manager_proxy) { + auto database_tracker = base::MakeRefCounted<DatabaseTracker>( + profile_path, is_incognito, std::move(special_storage_policy), + std::move(quota_manager_proxy), base::PassKey<DatabaseTracker>()); + database_tracker->RegisterQuotaClient(); + return database_tracker; +} + +DatabaseTracker::DatabaseTracker( + const base::FilePath& profile_path, + bool is_incognito, + scoped_refptr<SpecialStoragePolicy> special_storage_policy, + scoped_refptr<QuotaManagerProxy> quota_manager_proxy, + base::PassKey<DatabaseTracker>) : is_incognito_(is_incognito), profile_path_(profile_path), db_dir_(is_incognito_ ? profile_path_.Append(kIncognitoDatabaseDirectoryName) : profile_path_.Append(kDatabaseDirectoryName)), - db_(std::make_unique<sql::Database>()), - special_storage_policy_(special_storage_policy), - quota_manager_proxy_(quota_manager_proxy), + db_(std::make_unique<sql::Database>(sql::DatabaseOptions{ + .exclusive_locking = true, + .page_size = 4096, + .cache_size = 500, + })), + special_storage_policy_(std::move(special_storage_policy)), + quota_manager_proxy_(std::move(quota_manager_proxy)), task_runner_(base::ThreadPool::CreateSequencedTaskRunner( {base::MayBlock(), base::TaskPriority::USER_VISIBLE, - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) { - if (quota_manager_proxy) { - // TODO(crbug.com/1163048): Use mojo and switch to RegisterClient(). - quota_manager_proxy->RegisterLegacyClient( - base::MakeRefCounted<DatabaseQuotaClient>(this), - QuotaClientType::kDatabase, {blink::mojom::StorageType::kTemporary}); - } -} + // SKIP_ON_SHUTDOWN cannot be used because Shutdown() needs to run + // before the destructor, and Shutdown() is ran by PostTask()ing to + // this sequence. See https://crbug.com/1220191. + // + // We may be able to switch to SKIP_ON_SHUTDOWN if we get + // DatabaseTracker to be used entirely on the database sequence, so + // the destructor can absorb the logic that is currently in + // Shutdown(). + base::TaskShutdownBehavior::BLOCK_SHUTDOWN})), + quota_client_(std::make_unique<DatabaseQuotaClient>(*this)), + quota_client_wrapper_( + std::make_unique<QuotaClientCallbackWrapper>(quota_client_.get())), + quota_client_receiver_(quota_client_wrapper_.get()) {} DatabaseTracker::~DatabaseTracker() { + // base::RefCountedThreadSafe inserts the appropriate barriers to ensure + // member access in the destructor does not introduce data races. DCHECK(dbs_to_be_deleted_.empty()); DCHECK(deletion_callbacks_.empty()); + + DCHECK(!quota_client_); + DCHECK(!quota_client_wrapper_); + DCHECK(!quota_client_receiver_.is_bound()); +} + +void DatabaseTracker::RegisterQuotaClient() { + if (!quota_manager_proxy_) + return; + + // QuotaManagerProxy::RegisterClient() must be called synchronously during + // DatabaseTracker creation until crbug.com/1182630 is fixed. + mojo::PendingRemote<storage::mojom::QuotaClient> quota_client_remote; + mojo::PendingReceiver<storage::mojom::QuotaClient> quota_client_receiver = + quota_client_remote.InitWithNewPipeAndPassReceiver(); + quota_manager_proxy_->RegisterClient(std::move(quota_client_remote), + storage::QuotaClientType::kDatabase, + {blink::mojom::StorageType::kTemporary}); + + task_runner_->PostTask( + FROM_HERE, + base::BindOnce( + [](scoped_refptr<DatabaseTracker> self, + mojo::PendingReceiver<storage::mojom::QuotaClient> receiver) { + self->quota_client_receiver_.Bind(std::move(receiver)); + }, + base::RetainedRef(this), std::move(quota_client_receiver))); } void DatabaseTracker::DatabaseOpened(const std::string& origin_identifier, @@ -113,7 +178,7 @@ void DatabaseTracker::DatabaseOpened(const std::string& origin_identifier, if (quota_manager_proxy_.get()) quota_manager_proxy_->NotifyStorageAccessed( - GetOriginFromIdentifier(origin_identifier), + blink::StorageKey(GetOriginFromIdentifier(origin_identifier)), blink::mojom::StorageType::kTemporary, base::Time::Now()); InsertOrUpdateDatabaseDetails(origin_identifier, database_name, @@ -149,7 +214,7 @@ void DatabaseTracker::DatabaseClosed(const std::string& origin_identifier, // closed because we don't call it for read while open. if (quota_manager_proxy_.get()) quota_manager_proxy_->NotifyStorageAccessed( - GetOriginFromIdentifier(origin_identifier), + blink::StorageKey(GetOriginFromIdentifier(origin_identifier)), blink::mojom::StorageType::kTemporary, base::Time::Now()); UpdateOpenDatabaseSizeAndNotify(origin_identifier, database_name); @@ -358,7 +423,8 @@ bool DatabaseTracker::DeleteClosedDatabase( if (quota_manager_proxy_.get() && db_file_size) quota_manager_proxy_->NotifyStorageModified( - QuotaClientType::kDatabase, GetOriginFromIdentifier(origin_identifier), + QuotaClientType::kDatabase, + blink::StorageKey(GetOriginFromIdentifier(origin_identifier)), blink::mojom::StorageType::kTemporary, -db_file_size, base::Time::Now()); @@ -436,7 +502,8 @@ bool DatabaseTracker::DeleteOrigin(const std::string& origin_identifier, if (quota_manager_proxy_.get() && deleted_size) { quota_manager_proxy_->NotifyStorageModified( - QuotaClientType::kDatabase, GetOriginFromIdentifier(origin_identifier), + QuotaClientType::kDatabase, + blink::StorageKey(GetOriginFromIdentifier(origin_identifier)), blink::mojom::StorageType::kTemporary, -deleted_size, base::Time::Now()); } @@ -634,7 +701,8 @@ int64_t DatabaseTracker::UpdateOpenDatabaseInfoAndNotify( info->SetDatabaseSize(name, new_size); if (quota_manager_proxy_.get()) quota_manager_proxy_->NotifyStorageModified( - QuotaClientType::kDatabase, GetOriginFromIdentifier(origin_id), + QuotaClientType::kDatabase, + blink::StorageKey(GetOriginFromIdentifier(origin_id)), blink::mojom::StorageType::kTemporary, new_size - old_size, base::Time::Now()); for (auto& observer : observers_) @@ -660,8 +728,7 @@ void DatabaseTracker::ScheduleDatabasesForDeletion( DCHECK(!databases.empty()); if (!callback.is_null()) - deletion_callbacks_.push_back( - std::make_pair(std::move(callback), databases)); + deletion_callbacks_.emplace_back(std::move(callback), databases); for (const auto& origin_dbs : databases) { for (const std::u16string& db : origin_dbs.second) ScheduleDatabaseForDeletion(origin_dbs.first, db); @@ -895,6 +962,13 @@ void DatabaseTracker::Shutdown() { return; } shutting_down_ = true; + + // The mojo receiver must be reset before the instance it calls into is + // destroyed. + quota_client_receiver_.reset(); + quota_client_wrapper_.reset(); + quota_client_.reset(); + if (is_incognito_) DeleteIncognitoDBDirectory(); else if (!force_keep_session_state_) diff --git a/chromium/storage/browser/database/database_tracker.h b/chromium/storage/browser/database/database_tracker.h index b8cf34923fa..eb52fa940e1 100644 --- a/chromium/storage/browser/database/database_tracker.h +++ b/chromium/storage/browser/database/database_tracker.h @@ -19,10 +19,14 @@ #include "base/files/file_path.h" #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_refptr.h" #include "base/observer_list.h" #include "base/sequenced_task_runner.h" #include "base/strings/string_util.h" #include "base/time/time.h" +#include "base/types/pass_key.h" +#include "components/services/storage/public/mojom/quota_client.mojom.h" +#include "mojo/public/cpp/bindings/receiver.h" #include "net/base/completion_once_callback.h" #include "storage/browser/database/database_connections.h" #include "url/origin.h" @@ -34,6 +38,8 @@ class MetaTable; namespace storage { +class DatabaseQuotaClient; +class QuotaClientCallbackWrapper; class QuotaManagerProxy; class SpecialStoragePolicy; @@ -69,12 +75,14 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) OriginInfo { // This class manages the main database and keeps track of open databases. // // The data in this class is not thread-safe, so all methods of this class -// should be called on the task runner returned by |task_runner()|. The only -// exceptions are the ctor(), the dtor() and the database_directory() and -// quota_manager_proxy() getters. +// should be called on the task runner returned by task_runner(). The only +// exceptions are the constructor, the destructor, and the getters explicitly +// marked as thread-safe. class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseTracker : public base::RefCountedThreadSafe<DatabaseTracker> { public: + REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE(); + class Observer { public: virtual void OnDatabaseSizeChanged(const std::string& origin_identifier, @@ -88,10 +96,26 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseTracker virtual ~Observer() = default; }; + static scoped_refptr<DatabaseTracker> Create( + const base::FilePath& profile_path, + bool is_incognito, + scoped_refptr<SpecialStoragePolicy> special_storage_policy, + scoped_refptr<QuotaManagerProxy> quota_manager_proxy); + + // Exposed for base::MakeRefCounted. Users should call Create(). DatabaseTracker(const base::FilePath& profile_path, bool is_incognito, - SpecialStoragePolicy* special_storage_policy, - QuotaManagerProxy* quota_manager_proxy); + scoped_refptr<SpecialStoragePolicy> special_storage_policy, + scoped_refptr<QuotaManagerProxy> quota_manager_proxy, + base::PassKey<DatabaseTracker>); + + DatabaseTracker(const DatabaseTracker&) = delete; + DatabaseTracker& operator=(const DatabaseTracker&) = delete; + + // Methods not explicity marked thread-safe must be called on this sequence. + // + // Thread-safe getter. + base::SequencedTaskRunner* task_runner() { return task_runner_.get(); } void DatabaseOpened(const std::string& origin_identifier, const std::u16string& database_name, @@ -175,7 +199,11 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseTracker // Disables the exit-time deletion of session-only data. void SetForceKeepSessionState(); - base::SequencedTaskRunner* task_runner() const { return task_runner_.get(); } + protected: + // Subclasses need PassKeys to call the constructor. + static base::PassKey<DatabaseTracker> CreatePassKey() { + return base::PassKey<DatabaseTracker>(); + } private: friend class base::RefCountedThreadSafe<DatabaseTracker>; @@ -209,9 +237,11 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseTracker } }; - // virtual for unit-testing only. virtual ~DatabaseTracker(); + // Registers WebSQL's QuotaClient with the QuotaManager. + void RegisterQuotaClient(); + // Deletes the directory that stores all DBs in Incognito mode, if it // exists. void DeleteIncognitoDBDirectory(); @@ -300,8 +330,11 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseTracker // Thread-safety argument: The reference is immutable. const scoped_refptr<QuotaManagerProxy> quota_manager_proxy_; - // The database tracker thread we're supposed to run file IO on. - scoped_refptr<base::SequencedTaskRunner> task_runner_; + // Sequence where file I/O is allowed. + const scoped_refptr<base::SequencedTaskRunner> task_runner_; + + std::unique_ptr<DatabaseQuotaClient> quota_client_; + std::unique_ptr<storage::QuotaClientCallbackWrapper> quota_client_wrapper_; // When in Incognito mode, store a DELETE_ON_CLOSE handle to each // main DB and journal file that was accessed. When the Incognito profile @@ -318,6 +351,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) DatabaseTracker std::map<std::string, std::u16string> incognito_origin_directories_; int incognito_origin_directories_generator_ = 0; + mojo::Receiver<mojom::QuotaClient> quota_client_receiver_; + FRIEND_TEST_ALL_PREFIXES(DatabaseTracker, TestHelper); }; diff --git a/chromium/storage/browser/database/database_tracker_unittest.cc b/chromium/storage/browser/database/database_tracker_unittest.cc index b4a517f4e47..f269067c02b 100644 --- a/chromium/storage/browser/database/database_tracker_unittest.cc +++ b/chromium/storage/browser/database/database_tracker_unittest.cc @@ -14,8 +14,8 @@ #include "base/files/scoped_temp_dir.h" #include "base/memory/ptr_util.h" #include "base/memory/scoped_refptr.h" -#include "base/notreached.h" #include "base/run_loop.h" +#include "base/sequenced_task_runner.h" #include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/threading/sequenced_task_runner_handle.h" @@ -95,37 +95,32 @@ void CheckNotificationReceived(TestObserver* observer, EXPECT_EQ(expected_database_size, observer->GetNotificationDatabaseSize()); } +// Must be destroyed on the sequence that called RegisterClient() most recently. class TestQuotaManagerProxy : public QuotaManagerProxy { public: TestQuotaManagerProxy() - : QuotaManagerProxy(nullptr, base::SequencedTaskRunnerHandle::Get()), - registered_client_(nullptr) {} - - void RegisterLegacyClient( - scoped_refptr<QuotaClient> client, - QuotaClientType client_type, - const std::vector<blink::mojom::StorageType>& storage_types) override { - EXPECT_FALSE(registered_client_); - registered_client_ = client; - } + : QuotaManagerProxy( + /*quota_manager_impl=*/nullptr, + base::SequencedTaskRunnerHandle::Get()) {} void RegisterClient( mojo::PendingRemote<mojom::QuotaClient> client, QuotaClientType client_type, const std::vector<blink::mojom::StorageType>& storage_types) override { - NOTREACHED(); + EXPECT_FALSE(registered_client_); + registered_client_.Bind(std::move(client)); } - void NotifyStorageAccessed(const url::Origin& origin, + void NotifyStorageAccessed(const blink::StorageKey& storage_key, blink::mojom::StorageType type, base::Time access_time) override { EXPECT_EQ(blink::mojom::StorageType::kTemporary, type); - accesses_[origin] += 1; + accesses_[storage_key] += 1; } void NotifyStorageModified( QuotaClientType client_id, - const url::Origin& origin, + const blink::StorageKey& storage_key, blink::mojom::StorageType type, int64_t delta, base::Time modification_time, @@ -133,56 +128,48 @@ class TestQuotaManagerProxy : public QuotaManagerProxy { base::OnceClosure callback) override { EXPECT_EQ(QuotaClientType::kDatabase, client_id); EXPECT_EQ(blink::mojom::StorageType::kTemporary, type); - modifications_[origin].first += 1; - modifications_[origin].second += delta; + modifications_[storage_key].first += 1; + modifications_[storage_key].second += delta; if (callback) callback_task_runner->PostTask(FROM_HERE, std::move(callback)); } // Not needed for our tests. - void NotifyOriginInUse(const url::Origin& origin) override {} - void NotifyOriginNoLongerInUse(const url::Origin& origin) override {} void SetUsageCacheEnabled(QuotaClientType client_id, - const url::Origin& origin, + const blink::StorageKey& storage_key, blink::mojom::StorageType type, bool enabled) override {} void GetUsageAndQuota( - const url::Origin& origin, + const blink::StorageKey& storage_key, blink::mojom::StorageType type, scoped_refptr<base::SequencedTaskRunner> callback_task_runner, UsageAndQuotaCallback callback) override {} - void SimulateQuotaManagerDestroyed() { - if (registered_client_) { - registered_client_->OnQuotaManagerDestroyed(); - registered_client_ = nullptr; - } - } - - bool WasAccessNotified(const url::Origin& origin) { - return accesses_[origin] != 0; + bool WasAccessNotified(const blink::StorageKey& storage_key) { + return accesses_[storage_key] != 0; } - bool WasModificationNotified(const url::Origin& origin, int64_t amount) { - return modifications_[origin].first != 0 && - modifications_[origin].second == amount; + bool WasModificationNotified(const blink::StorageKey& storage_key, + int64_t amount) { + return modifications_[storage_key].first != 0 && + modifications_[storage_key].second == amount; } - void reset() { + void ResetRecordedTestState() { accesses_.clear(); modifications_.clear(); } - scoped_refptr<QuotaClient> registered_client_; + mojo::Remote<mojom::QuotaClient> registered_client_; - // Map from origin to count of access notifications. - std::map<url::Origin, int> accesses_; + // Map from storage key to count of access notifications. + std::map<blink::StorageKey, int> accesses_; - // Map from origin to <count, sum of deltas> - std::map<url::Origin, std::pair<int, int64_t>> modifications_; + // Map from storage key to <count, sum of deltas> + std::map<blink::StorageKey, std::pair<int, int64_t>> modifications_; protected: - ~TestQuotaManagerProxy() override { EXPECT_FALSE(registered_client_); } + ~TestQuotaManagerProxy() override = default; }; bool EnsureFileOfSize(const base::FilePath& file_path, int64_t length) { @@ -205,13 +192,12 @@ class DatabaseTracker_TestHelper_Test { base::test::TaskEnvironment task_environment; base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - scoped_refptr<MockSpecialStoragePolicy> special_storage_policy = - new MockSpecialStoragePolicy; + auto special_storage_policy = + base::MakeRefCounted<MockSpecialStoragePolicy>(); special_storage_policy->AddProtected(GURL(kOrigin2Url)); - scoped_refptr<DatabaseTracker> tracker( - base::MakeRefCounted<DatabaseTracker>( - temp_dir.GetPath(), incognito_mode, special_storage_policy.get(), - nullptr)); + scoped_refptr<DatabaseTracker> tracker = DatabaseTracker::Create( + temp_dir.GetPath(), incognito_mode, std::move(special_storage_policy), + /*quota_manager_proxy=*/nullptr); base::RunLoop run_loop; tracker->task_runner()->PostTask( @@ -303,6 +289,8 @@ class DatabaseTracker_TestHelper_Test { tracker->DatabaseClosed(kOrigin2, kDB3); tracker->RemoveObserver(&observer); + + tracker->Shutdown(); })); run_loop.Run(); } @@ -312,13 +300,12 @@ class DatabaseTracker_TestHelper_Test { base::test::TaskEnvironment task_environment; base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - scoped_refptr<MockSpecialStoragePolicy> special_storage_policy = - new MockSpecialStoragePolicy; + auto special_storage_policy = + base::MakeRefCounted<MockSpecialStoragePolicy>(); special_storage_policy->AddProtected(GURL(kOrigin2Url)); - scoped_refptr<DatabaseTracker> tracker( - base::MakeRefCounted<DatabaseTracker>( - temp_dir.GetPath(), incognito_mode, special_storage_policy.get(), - nullptr)); + scoped_refptr<DatabaseTracker> tracker = DatabaseTracker::Create( + temp_dir.GetPath(), incognito_mode, std::move(special_storage_policy), + /*quota_manager_proxy=*/nullptr); base::RunLoop run_loop; tracker->task_runner()->PostTask( @@ -450,13 +437,16 @@ class DatabaseTracker_TestHelper_Test { origin1_info = tracker->GetCachedOriginInfo(kOrigin1); EXPECT_TRUE(origin1_info); EXPECT_EQ(0, origin1_info->TotalSize()); + + tracker->Shutdown(); })); run_loop.Run(); } static void DatabaseTrackerQuotaIntegration(bool incognito_mode) { - const url::Origin kOrigin(url::Origin::Create(GURL(kOrigin1Url))); - const std::string kOriginId = GetIdentifierFromOrigin(kOrigin); + const blink::StorageKey kStorageKey = + blink::StorageKey::CreateFromStringForTesting(kOrigin1Url); + const std::string kOriginId = GetIdentifierFromOrigin(kStorageKey.origin()); const std::u16string kName = u"name"; const std::u16string kDescription = u"description"; @@ -465,12 +455,10 @@ class DatabaseTracker_TestHelper_Test { ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); // Initialize the tracker with a QuotaManagerProxy - scoped_refptr<TestQuotaManagerProxy> test_quota_proxy( - new TestQuotaManagerProxy); - scoped_refptr<DatabaseTracker> tracker( - base::MakeRefCounted<DatabaseTracker>(temp_dir.GetPath(), - incognito_mode, nullptr, - test_quota_proxy.get())); + auto test_quota_proxy = base::MakeRefCounted<TestQuotaManagerProxy>(); + scoped_refptr<DatabaseTracker> tracker = DatabaseTracker::Create( + temp_dir.GetPath(), incognito_mode, + /*special_storage_policy=*/nullptr, test_quota_proxy); base::RunLoop run_loop; tracker->task_runner()->PostTask( FROM_HERE, base::BindLambdaForTesting([&]() { @@ -485,8 +473,8 @@ class DatabaseTracker_TestHelper_Test { int64_t database_size = 0; tracker->DatabaseOpened(kOriginId, kName, kDescription, &database_size); - EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin)); - test_quota_proxy->reset(); + EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kStorageKey)); + test_quota_proxy->ResetRecordedTestState(); base::FilePath db_file(tracker->GetFullDBFilePath(kOriginId, kName)); EXPECT_FALSE( @@ -495,23 +483,26 @@ class DatabaseTracker_TestHelper_Test { EXPECT_TRUE(EnsureFileOfSize(db_file, 10)); EXPECT_TRUE(base::PathExists(tracker->GetOriginDirectory(kOriginId))); tracker->DatabaseModified(kOriginId, kName); - EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, 10)); - test_quota_proxy->reset(); + EXPECT_TRUE( + test_quota_proxy->WasModificationNotified(kStorageKey, 10)); + test_quota_proxy->ResetRecordedTestState(); EXPECT_TRUE(EnsureFileOfSize(db_file, 100)); tracker->DatabaseModified(kOriginId, kName); - EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, 90)); - test_quota_proxy->reset(); + EXPECT_TRUE( + test_quota_proxy->WasModificationNotified(kStorageKey, 90)); + test_quota_proxy->ResetRecordedTestState(); tracker->DatabaseClosed(kOriginId, kName); - EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin)); + EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kStorageKey)); net::TestCompletionCallback delete_database_callback; tracker->DeleteDatabase(kOriginId, kName, delete_database_callback.callback()); EXPECT_TRUE(delete_database_callback.have_result()); EXPECT_EQ(net::OK, delete_database_callback.WaitForResult()); - EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, -100)); - test_quota_proxy->reset(); + EXPECT_TRUE( + test_quota_proxy->WasModificationNotified(kStorageKey, -100)); + test_quota_proxy->ResetRecordedTestState(); EXPECT_FALSE( base::PathExists(tracker->GetOriginDirectory(kOriginId))); @@ -522,8 +513,8 @@ class DatabaseTracker_TestHelper_Test { tracker->DatabaseOpened(kOriginId, kName, kDescription, &database_size); - EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin)); - test_quota_proxy->reset(); + EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kStorageKey)); + test_quota_proxy->ResetRecordedTestState(); db_file = tracker->GetFullDBFilePath(kOriginId, kName); EXPECT_FALSE( @@ -532,25 +523,27 @@ class DatabaseTracker_TestHelper_Test { EXPECT_TRUE(EnsureFileOfSize(db_file, 100)); EXPECT_TRUE(base::PathExists(tracker->GetOriginDirectory(kOriginId))); tracker->DatabaseModified(kOriginId, kName); - EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, 100)); - test_quota_proxy->reset(); + EXPECT_TRUE( + test_quota_proxy->WasModificationNotified(kStorageKey, 100)); + test_quota_proxy->ResetRecordedTestState(); net::TestCompletionCallback delete_database_callback2; tracker->DeleteDatabase(kOriginId, kName, delete_database_callback2.callback()); EXPECT_FALSE(delete_database_callback2.have_result()); EXPECT_FALSE( - test_quota_proxy->WasModificationNotified(kOrigin, -100)); + test_quota_proxy->WasModificationNotified(kStorageKey, -100)); EXPECT_TRUE(base::PathExists(tracker->GetOriginDirectory(kOriginId))); tracker->DatabaseClosed(kOriginId, kName); - EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin)); - EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, -100)); + EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kStorageKey)); + EXPECT_TRUE( + test_quota_proxy->WasModificationNotified(kStorageKey, -100)); EXPECT_FALSE( base::PathExists(tracker->GetOriginDirectory(kOriginId))); EXPECT_TRUE(delete_database_callback2.have_result()); EXPECT_EQ(net::OK, delete_database_callback2.WaitForResult()); - test_quota_proxy->reset(); + test_quota_proxy->ResetRecordedTestState(); // Create a database and up the file size without telling // the tracker about the modification, than simulate a @@ -559,8 +552,8 @@ class DatabaseTracker_TestHelper_Test { tracker->DatabaseOpened(kOriginId, kName, kDescription, &database_size); - EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin)); - test_quota_proxy->reset(); + EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kStorageKey)); + test_quota_proxy->ResetRecordedTestState(); db_file = tracker->GetFullDBFilePath(kOriginId, kName); EXPECT_FALSE( base::PathExists(tracker->GetOriginDirectory(kOriginId))); @@ -569,13 +562,15 @@ class DatabaseTracker_TestHelper_Test { EXPECT_TRUE(EnsureFileOfSize(db_file, 100)); DatabaseConnections crashed_renderer_connections; crashed_renderer_connections.AddConnection(kOriginId, kName); - EXPECT_FALSE(test_quota_proxy->WasModificationNotified(kOrigin, 100)); + EXPECT_FALSE( + test_quota_proxy->WasModificationNotified(kStorageKey, 100)); tracker->CloseDatabases(crashed_renderer_connections); - EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, 100)); + EXPECT_TRUE( + test_quota_proxy->WasModificationNotified(kStorageKey, 100)); // Cleanup. crashed_renderer_connections.RemoveAllConnections(); - test_quota_proxy->SimulateQuotaManagerDestroyed(); + tracker->Shutdown(); })); run_loop.Run(); } @@ -595,13 +590,12 @@ class DatabaseTracker_TestHelper_Test { base::FilePath origin1_db_dir; base::FilePath origin2_db_dir; { - scoped_refptr<MockSpecialStoragePolicy> special_storage_policy = - new MockSpecialStoragePolicy; + auto special_storage_policy = + base::MakeRefCounted<MockSpecialStoragePolicy>(); special_storage_policy->AddSessionOnly(GURL(kOrigin2Url)); - scoped_refptr<DatabaseTracker> tracker( - base::MakeRefCounted<DatabaseTracker>(temp_dir.GetPath(), false, - special_storage_policy.get(), - nullptr)); + scoped_refptr<DatabaseTracker> tracker = DatabaseTracker::Create( + temp_dir.GetPath(), false, std::move(special_storage_policy), + /*quota_manager_proxy=*/nullptr); base::RunLoop run_loop; tracker->task_runner()->PostTask( FROM_HERE, base::BindLambdaForTesting([&]() { @@ -646,9 +640,9 @@ class DatabaseTracker_TestHelper_Test { } // At this point, the database tracker should be gone. Create a new one. - scoped_refptr<DatabaseTracker> tracker( - base::MakeRefCounted<DatabaseTracker>(temp_dir.GetPath(), false, - nullptr, nullptr)); + scoped_refptr<DatabaseTracker> tracker = DatabaseTracker::Create( + temp_dir.GetPath(), /*is_incognito=*/false, + /*special_storage_policy=*/nullptr, /*quota_manager_proxy=*/nullptr); base::RunLoop run_loop; tracker->task_runner()->PostTask( FROM_HERE, base::BindLambdaForTesting([&]() { @@ -671,6 +665,8 @@ class DatabaseTracker_TestHelper_Test { // of kOrigin2 is deleted. EXPECT_TRUE(base::PathExists(origin1_db_dir)); EXPECT_FALSE(base::PathExists(origin2_db_dir)); + + tracker->Shutdown(); })); run_loop.Run(); } @@ -690,13 +686,12 @@ class DatabaseTracker_TestHelper_Test { base::FilePath origin1_db_dir; base::FilePath origin2_db_dir; { - scoped_refptr<MockSpecialStoragePolicy> special_storage_policy = - new MockSpecialStoragePolicy; + auto special_storage_policy = + base::MakeRefCounted<MockSpecialStoragePolicy>(); special_storage_policy->AddSessionOnly(GURL(kOrigin2Url)); - scoped_refptr<DatabaseTracker> tracker( - base::MakeRefCounted<DatabaseTracker>(temp_dir.GetPath(), false, - special_storage_policy.get(), - nullptr)); + scoped_refptr<DatabaseTracker> tracker = DatabaseTracker::Create( + temp_dir.GetPath(), false, std::move(special_storage_policy), + /*quota_manager_proxy=*/nullptr); base::RunLoop run_loop; tracker->task_runner()->PostTask( FROM_HERE, base::BindLambdaForTesting([&]() { @@ -743,9 +738,9 @@ class DatabaseTracker_TestHelper_Test { } // At this point, the database tracker should be gone. Create a new one. - scoped_refptr<DatabaseTracker> tracker( - base::MakeRefCounted<DatabaseTracker>(temp_dir.GetPath(), false, - nullptr, nullptr)); + scoped_refptr<DatabaseTracker> tracker = DatabaseTracker::Create( + temp_dir.GetPath(), false, /*special_storage_policy=*/nullptr, + /*quota_manager_proxy=*/nullptr); base::RunLoop run_loop; tracker->task_runner()->PostTask( FROM_HERE, base::BindLambdaForTesting([&]() { @@ -764,6 +759,8 @@ class DatabaseTracker_TestHelper_Test { EXPECT_TRUE(base::PathExists(origin1_db_dir)); EXPECT_TRUE(base::PathExists(origin2_db_dir)); + + tracker->Shutdown(); })); run_loop.Run(); } @@ -780,9 +777,9 @@ class DatabaseTracker_TestHelper_Test { base::test::TaskEnvironment task_environment; base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - scoped_refptr<DatabaseTracker> tracker( - base::MakeRefCounted<DatabaseTracker>( - temp_dir.GetPath(), kUseInMemoryTrackerDatabase, nullptr, nullptr)); + scoped_refptr<DatabaseTracker> tracker = DatabaseTracker::Create( + temp_dir.GetPath(), kUseInMemoryTrackerDatabase, + /*special_storage_policy=*/nullptr, /*quota_manager_proxy=*/nullptr); base::RunLoop run_loop; tracker->task_runner()->PostTask( FROM_HERE, base::BindLambdaForTesting([&]() { @@ -821,6 +818,8 @@ class DatabaseTracker_TestHelper_Test { infos.clear(); EXPECT_TRUE(tracker->GetAllOriginsInfo(&infos)); EXPECT_TRUE(infos.empty()); + + tracker->Shutdown(); })); run_loop.Run(); } @@ -836,9 +835,9 @@ class DatabaseTracker_TestHelper_Test { base::test::TaskEnvironment task_environment; base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - scoped_refptr<DatabaseTracker> tracker( - base::MakeRefCounted<DatabaseTracker>( - temp_dir.GetPath(), kUseInMemoryTrackerDatabase, nullptr, nullptr)); + scoped_refptr<DatabaseTracker> tracker = DatabaseTracker::Create( + temp_dir.GetPath(), kUseInMemoryTrackerDatabase, + /*special_storage_policy=*/nullptr, /*quota_manager_proxy=*/nullptr); base::RunLoop run_loop; tracker->task_runner()->PostTask( FROM_HERE, base::BindLambdaForTesting([&]() { @@ -909,6 +908,8 @@ class DatabaseTracker_TestHelper_Test { EXPECT_FALSE(base::PathExists(spoof_db_file2)); tracker->RemoveObserver(&observer); + + tracker->Shutdown(); })); run_loop.Run(); } diff --git a/chromium/storage/browser/database/vfs_backend.cc b/chromium/storage/browser/database/vfs_backend.cc index 35cb25549f2..598064ec64b 100644 --- a/chromium/storage/browser/database/vfs_backend.cc +++ b/chromium/storage/browser/database/vfs_backend.cc @@ -157,12 +157,6 @@ uint32_t VfsBackend::GetFileAttributes(const base::FilePath& file_path) { } // static -int64_t VfsBackend::GetFileSize(const base::FilePath& file_path) { - int64_t size = 0; - return (base::GetFileSize(file_path, &size) ? size : 0); -} - -// static bool VfsBackend::SetFileSize(const base::FilePath& file_path, int64_t size) { int flags = 0; flags |= base::File::FLAG_READ; diff --git a/chromium/storage/browser/database/vfs_backend.h b/chromium/storage/browser/database/vfs_backend.h index 16277273364..3ac86a35c72 100644 --- a/chromium/storage/browser/database/vfs_backend.h +++ b/chromium/storage/browser/database/vfs_backend.h @@ -29,8 +29,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) VfsBackend { static uint32_t GetFileAttributes(const base::FilePath& file_path); - static int64_t GetFileSize(const base::FilePath& file_path); - static bool SetFileSize(const base::FilePath& file_path, int64_t size); // Used to make decisions in the DatabaseDispatcherHost. diff --git a/chromium/storage/browser/file_system/DIR_METADATA b/chromium/storage/browser/file_system/DIR_METADATA index a32478d8fb0..a6d562a2d2b 100644 --- a/chromium/storage/browser/file_system/DIR_METADATA +++ b/chromium/storage/browser/file_system/DIR_METADATA @@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Blink>Storage>FileSystem" diff --git a/chromium/storage/browser/file_system/async_file_util.h b/chromium/storage/browser/file_system/async_file_util.h index a5ef84d7783..2d89171abad 100644 --- a/chromium/storage/browser/file_system/async_file_util.h +++ b/chromium/storage/browser/file_system/async_file_util.h @@ -13,7 +13,6 @@ #include "base/callback_forward.h" #include "base/component_export.h" #include "base/files/file.h" -#include "base/macros.h" #include "components/services/filesystem/public/mojom/types.mojom.h" #include "storage/browser/file_system/file_system_operation.h" @@ -85,8 +84,10 @@ class AsyncFileUtil { COMPONENT_EXPORT(STORAGE_BROWSER) static AsyncFileUtil* CreateForLocalFileSystem(); - AsyncFileUtil() {} - virtual ~AsyncFileUtil() {} + AsyncFileUtil() = default; + AsyncFileUtil(const AsyncFileUtil&) = delete; + AsyncFileUtil& operator=(const AsyncFileUtil&) = delete; + virtual ~AsyncFileUtil() = default; // Creates or opens a file with the given flags. // If File::FLAG_CREATE is set in |file_flags| it always tries to create @@ -350,9 +351,6 @@ class AsyncFileUtil { std::unique_ptr<FileSystemOperationContext> context, const FileSystemURL& url, CreateSnapshotFileCallback callback) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(AsyncFileUtil); }; } // namespace storage diff --git a/chromium/storage/browser/file_system/copy_or_move_file_validator.h b/chromium/storage/browser/file_system/copy_or_move_file_validator.h index 8fef1832ce6..0ff66272e17 100644 --- a/chromium/storage/browser/file_system/copy_or_move_file_validator.h +++ b/chromium/storage/browser/file_system/copy_or_move_file_validator.h @@ -23,7 +23,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) CopyOrMoveFileValidator { // base::File::FILE_OK means the file validated. using ResultCallback = base::OnceCallback<void(base::File::Error result)>; - virtual ~CopyOrMoveFileValidator() {} + CopyOrMoveFileValidator(const CopyOrMoveFileValidator&) = delete; + CopyOrMoveFileValidator& operator=(const CopyOrMoveFileValidator&) = delete; + virtual ~CopyOrMoveFileValidator() = default; // Called on a source file before copying or moving to the final // destination. @@ -34,11 +36,18 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) CopyOrMoveFileValidator { virtual void StartPostWriteValidation( const base::FilePath& dest_platform_path, ResultCallback result_callback) = 0; + + protected: + CopyOrMoveFileValidator() = default; }; class CopyOrMoveFileValidatorFactory { public: - virtual ~CopyOrMoveFileValidatorFactory() {} + CopyOrMoveFileValidatorFactory(const CopyOrMoveFileValidatorFactory&) = + delete; + CopyOrMoveFileValidatorFactory& operator=( + const CopyOrMoveFileValidatorFactory&) = delete; + virtual ~CopyOrMoveFileValidatorFactory() = default; // This method must always return a non-null validator. |src_url| is needed // in addition to |platform_path| because in the obfuscated file system @@ -46,6 +55,9 @@ class CopyOrMoveFileValidatorFactory { virtual CopyOrMoveFileValidator* CreateCopyOrMoveFileValidator( const FileSystemURL& src_url, const base::FilePath& platform_path) = 0; + + protected: + CopyOrMoveFileValidatorFactory() = default; }; } // namespace storage diff --git a/chromium/storage/browser/file_system/copy_or_move_file_validator_unittest.cc b/chromium/storage/browser/file_system/copy_or_move_file_validator_unittest.cc index d0dbaf018b7..011d6367c72 100644 --- a/chromium/storage/browser/file_system/copy_or_move_file_validator_unittest.cc +++ b/chromium/storage/browser/file_system/copy_or_move_file_validator_unittest.cc @@ -25,12 +25,15 @@ #include "storage/browser/file_system/file_system_context.h" #include "storage/browser/file_system/file_system_url.h" #include "storage/browser/file_system/isolated_context.h" +#include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/test/async_file_test_helper.h" #include "storage/browser/test/mock_special_storage_policy.h" #include "storage/browser/test/test_file_system_backend.h" #include "storage/browser/test/test_file_system_context.h" #include "storage/common/file_system/file_system_util.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" +#include "url/gurl.h" #include "url/origin.h" namespace storage { @@ -64,7 +67,8 @@ class CopyOrMoveFileValidatorTestHelper { ASSERT_TRUE(base_.CreateUniqueTempDir()); base::FilePath base_dir = base_.GetPath(); - file_system_context_ = CreateFileSystemContextForTesting(nullptr, base_dir); + file_system_context_ = CreateFileSystemContextForTesting( + /*quota_manager_proxy=*/nullptr, base_dir); // Set up TestFileSystemBackend to require CopyOrMoveFileValidator. FileSystemBackend* test_file_system_backend = @@ -76,7 +80,8 @@ class CopyOrMoveFileValidatorTestHelper { FileSystemBackend* src_file_system_backend = file_system_context_->GetFileSystemBackend(src_type_); src_file_system_backend->ResolveURL( - FileSystemURL::CreateForTest(origin_, src_type_, base::FilePath()), + FileSystemURL::CreateForTest(blink::StorageKey(url::Origin(origin_)), + src_type_, base::FilePath()), OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, base::BindOnce(&ExpectOk)); base::RunLoop().RunUntilIdle(); ASSERT_EQ(base::File::FILE_OK, CreateDirectory(SourceURL(""))); @@ -139,13 +144,13 @@ class CopyOrMoveFileValidatorTestHelper { private: FileSystemURL SourceURL(const std::string& path) { return file_system_context_->CreateCrackedFileSystemURL( - origin_, src_type_, + blink::StorageKey(origin_), src_type_, base::FilePath().AppendASCII("src").AppendASCII(path)); } FileSystemURL DestURL(const std::string& path) { return file_system_context_->CreateCrackedFileSystemURL( - origin_, dest_type_, + blink::StorageKey(origin_), dest_type_, base::FilePath().AppendASCII("dest").AppendASCII(path)); } diff --git a/chromium/storage/browser/file_system/copy_or_move_operation_delegate.cc b/chromium/storage/browser/file_system/copy_or_move_operation_delegate.cc index 581c1ea4373..db41f174a58 100644 --- a/chromium/storage/browser/file_system/copy_or_move_operation_delegate.cc +++ b/chromium/storage/browser/file_system/copy_or_move_operation_delegate.cc @@ -1097,7 +1097,7 @@ FileSystemURL CopyOrMoveOperationDelegate::CreateDestURL( src_root_.virtual_path().AppendRelativePath(src_url.virtual_path(), &relative); return file_system_context()->CreateCrackedFileSystemURL( - dest_root_.origin(), dest_root_.mount_type(), relative); + dest_root_.storage_key(), dest_root_.mount_type(), relative); } } // namespace storage diff --git a/chromium/storage/browser/file_system/copy_or_move_operation_delegate_unittest.cc b/chromium/storage/browser/file_system/copy_or_move_operation_delegate_unittest.cc index acfba01ef76..b666bcd8dbd 100644 --- a/chromium/storage/browser/file_system/copy_or_move_operation_delegate_unittest.cc +++ b/chromium/storage/browser/file_system/copy_or_move_operation_delegate_unittest.cc @@ -32,6 +32,7 @@ #include "storage/browser/file_system/file_system_context.h" #include "storage/browser/file_system/file_system_operation.h" #include "storage/browser/file_system/file_system_url.h" +#include "storage/browser/file_system/file_system_util.h" #include "storage/browser/quota/quota_manager.h" #include "storage/browser/test/async_file_test_helper.h" #include "storage/browser/test/file_system_test_file_set.h" @@ -42,6 +43,8 @@ #include "storage/common/file_system/file_system_mount_option.h" #include "storage/common/file_system/file_system_util.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" +#include "url/gurl.h" #include "url/origin.h" namespace storage { @@ -178,7 +181,6 @@ class CopyOrMoveOperationTestHelper { ~CopyOrMoveOperationTestHelper() { file_system_context_ = nullptr; - quota_manager_proxy_->SimulateQuotaManagerDestroyed(); quota_manager_ = nullptr; quota_manager_proxy_ = nullptr; task_environment_.RunUntilIdle(); @@ -205,7 +207,8 @@ class CopyOrMoveOperationTestHelper { FileSystemBackend* backend = file_system_context_->GetFileSystemBackend(src_type_); backend->ResolveURL( - FileSystemURL::CreateForTest(origin_, src_type_, base::FilePath()), + FileSystemURL::CreateForTest(blink::StorageKey(url::Origin(origin_)), + src_type_, base::FilePath()), OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, base::BindOnce(&ExpectOk)); backend = file_system_context_->GetFileSystemBackend(dest_type_); if (dest_type_ == kFileSystemTypeTest) { @@ -219,15 +222,18 @@ class CopyOrMoveOperationTestHelper { std::move(factory)); } backend->ResolveURL( - FileSystemURL::CreateForTest(origin_, dest_type_, base::FilePath()), + FileSystemURL::CreateForTest(blink::StorageKey(url::Origin(origin_)), + dest_type_, base::FilePath()), OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, base::BindOnce(&ExpectOk)); task_environment_.RunUntilIdle(); // Grant relatively big quota initially. - quota_manager_->SetQuota( - origin_, FileSystemTypeToQuotaStorageType(src_type_), 1024 * 1024); - quota_manager_->SetQuota( - origin_, FileSystemTypeToQuotaStorageType(dest_type_), 1024 * 1024); + quota_manager_->SetQuota(blink::StorageKey(origin_), + FileSystemTypeToQuotaStorageType(src_type_), + 1024 * 1024); + quota_manager_->SetQuota(blink::StorageKey(origin_), + FileSystemTypeToQuotaStorageType(dest_type_), + 1024 * 1024); } int64_t GetSourceUsage() { @@ -244,12 +250,14 @@ class CopyOrMoveOperationTestHelper { FileSystemURL SourceURL(const std::string& path) { return file_system_context_->CreateCrackedFileSystemURL( - origin_, src_type_, base::FilePath::FromUTF8Unsafe(path)); + blink::StorageKey(origin_), src_type_, + base::FilePath::FromUTF8Unsafe(path)); } FileSystemURL DestURL(const std::string& path) { return file_system_context_->CreateCrackedFileSystemURL( - origin_, dest_type_, base::FilePath::FromUTF8Unsafe(path)); + blink::StorageKey(origin_), dest_type_, + base::FilePath::FromUTF8Unsafe(path)); } base::File::Error Copy(const FileSystemURL& src, const FileSystemURL& dest) { @@ -286,7 +294,7 @@ class CopyOrMoveOperationTestHelper { for (size_t i = 0; i < test_case_size; ++i) { const FileSystemTestCaseRecord& test_case = test_cases[i]; FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL( - root.origin(), root.mount_type(), + root.storage_key(), root.mount_type(), root.virtual_path().Append(test_case.path)); if (test_case.is_directory) result = CreateDirectory(url); @@ -317,7 +325,7 @@ class CopyOrMoveOperationTestHelper { ASSERT_EQ(base::File::FILE_OK, ReadDirectory(dir, &entries)); for (const filesystem::mojom::DirectoryEntry& entry : entries) { FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL( - dir.origin(), dir.mount_type(), + dir.storage_key(), dir.mount_type(), dir.virtual_path().Append(entry.name)); base::FilePath relative; root.virtual_path().AppendRelativePath(url.virtual_path(), &relative); diff --git a/chromium/storage/browser/file_system/dragged_file_util_unittest.cc b/chromium/storage/browser/file_system/dragged_file_util_unittest.cc index 9b07aaa1011..0fcdc2ed7b0 100644 --- a/chromium/storage/browser/file_system/dragged_file_util_unittest.cc +++ b/chromium/storage/browser/file_system/dragged_file_util_unittest.cc @@ -12,11 +12,11 @@ #include "base/check.h" #include "base/containers/queue.h" +#include "base/cxx17_backports.h" #include "base/files/file_enumerator.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/macros.h" -#include "base/stl_util.h" #include "base/test/task_environment.h" #include "base/time/time.h" #include "build/build_config.h" @@ -27,13 +27,14 @@ #include "storage/browser/file_system/isolated_context.h" #include "storage/browser/file_system/local_file_util.h" #include "storage/browser/file_system/native_file_util.h" +#include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/test/async_file_test_helper.h" #include "storage/browser/test/file_system_test_file_set.h" #include "storage/browser/test/test_file_system_context.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "url/gurl.h" -#include "url/origin.h" namespace storage { @@ -68,7 +69,7 @@ FileSystemURL GetEntryURL(FileSystemContext* file_system_context, const FileSystemURL& dir, const base::FilePath::StringType& name) { return file_system_context->CreateCrackedFileSystemURL( - dir.origin(), dir.mount_type(), dir.virtual_path().Append(name)); + dir.storage_key(), dir.mount_type(), dir.virtual_path().Append(name)); } base::FilePath GetRelativeVirtualPath(const FileSystemURL& root, @@ -87,7 +88,7 @@ FileSystemURL GetOtherURL(FileSystemContext* file_system_context, const FileSystemURL& other_root, const FileSystemURL& url) { return file_system_context->CreateCrackedFileSystemURL( - other_root.origin(), other_root.mount_type(), + other_root.storage_key(), other_root.mount_type(), other_root.virtual_path().Append(GetRelativeVirtualPath(root, url))); } @@ -107,7 +108,7 @@ class DraggedFileUtilTest : public testing::Test { SimulateDropFiles(); file_system_context_ = CreateFileSystemContextForTesting( - nullptr /* quota_manager */, partition_dir_.GetPath()); + /*quota_manager_proxy=*/nullptr, partition_dir_.GetPath()); isolated_context()->AddReference(filesystem_id_); } @@ -145,13 +146,13 @@ class DraggedFileUtilTest : public testing::Test { base::FilePath virtual_path = isolated_context()->CreateVirtualRootPath(filesystem_id()).Append(path); return file_system_context_->CreateCrackedFileSystemURL( - url::Origin::Create(GURL("http://example.com")), + blink::StorageKey::CreateFromStringForTesting("http://example.com"), kFileSystemTypeIsolated, virtual_path); } FileSystemURL GetOtherFileSystemURL(const base::FilePath& path) const { return file_system_context()->CreateCrackedFileSystemURL( - url::Origin::Create(GURL("http://example.com")), + blink::StorageKey::CreateFromStringForTesting("http://example.com"), kFileSystemTypeTemporary, base::FilePath().AppendASCII("dest").Append(path)); } diff --git a/chromium/storage/browser/file_system/external_mount_points.cc b/chromium/storage/browser/file_system/external_mount_points.cc index 985a050e1eb..ade12800564 100644 --- a/chromium/storage/browser/file_system/external_mount_points.cc +++ b/chromium/storage/browser/file_system/external_mount_points.cc @@ -12,6 +12,7 @@ #include "base/macros.h" #include "build/chromeos_buildflags.h" #include "storage/browser/file_system/file_system_url.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" namespace storage { @@ -186,8 +187,11 @@ bool ExternalMountPoints::CrackVirtualPath( return true; } +// TODO(https://crbug.com/1221308): conversion of the URL to origin is +// temporary; function will have StorageKey parameter in future CL FileSystemURL ExternalMountPoints::CrackURL(const GURL& url) const { - FileSystemURL filesystem_url = FileSystemURL(url); + FileSystemURL filesystem_url = + FileSystemURL(url, blink::StorageKey(url::Origin::Create(url))); if (!filesystem_url.is_valid()) return FileSystemURL(); return CrackFileSystemURL(filesystem_url); @@ -197,7 +201,10 @@ FileSystemURL ExternalMountPoints::CreateCrackedFileSystemURL( const url::Origin& origin, FileSystemType type, const base::FilePath& virtual_path) const { - return CrackFileSystemURL(FileSystemURL(origin, type, virtual_path)); + // TODO(https://crbug.com/1221308): function will have StorageKey param in + // future CL; conversion from url::Origin is temporary + const blink::StorageKey storage_key = blink::StorageKey(origin); + return CrackFileSystemURL(FileSystemURL(storage_key, type, virtual_path)); } void ExternalMountPoints::AddMountPointInfosTo( @@ -271,9 +278,10 @@ FileSystemURL ExternalMountPoints::CrackFileSystemURL( return FileSystemURL(); #else // On other OS, it is simply a native local path. - return FileSystemURL(url.origin(), url.mount_type(), url.virtual_path(), - url.mount_filesystem_id(), kFileSystemTypeLocal, - url.path(), url.filesystem_id(), url.mount_option()); + return FileSystemURL(url.storage_key(), url.mount_type(), + url.virtual_path(), url.mount_filesystem_id(), + kFileSystemTypeLocal, url.path(), url.filesystem_id(), + url.mount_option()); #endif } @@ -289,7 +297,7 @@ FileSystemURL ExternalMountPoints::CrackFileSystemURL( } return FileSystemURL( - url.origin(), url.mount_type(), url.virtual_path(), + url.storage_key(), url.mount_type(), url.virtual_path(), !url.filesystem_id().empty() ? url.filesystem_id() : mount_name, cracked_type, cracked_path, cracked_id.empty() ? mount_name : cracked_id, cracked_mount_option); diff --git a/chromium/storage/browser/file_system/external_mount_points_unittest.cc b/chromium/storage/browser/file_system/external_mount_points_unittest.cc index e3df98989c5..f1cc824674e 100644 --- a/chromium/storage/browser/file_system/external_mount_points_unittest.cc +++ b/chromium/storage/browser/file_system/external_mount_points_unittest.cc @@ -8,9 +8,9 @@ #include <string> +#include "base/cxx17_backports.h" #include "base/files/file_path.h" #include "base/macros.h" -#include "base/stl_util.h" #include "storage/browser/file_system/file_system_url.h" #include "storage/common/file_system/file_system_mount_option.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chromium/storage/browser/file_system/file_observers.h b/chromium/storage/browser/file_system/file_observers.h index 7384cc54c12..847e2d312ea 100644 --- a/chromium/storage/browser/file_system/file_observers.h +++ b/chromium/storage/browser/file_system/file_observers.h @@ -8,7 +8,6 @@ #include <stdint.h> #include "base/component_export.h" -#include "base/macros.h" // TODO(kinuko): Split this file into per-observer multiple files. @@ -31,15 +30,14 @@ class FileSystemURL; // sandboxed files (where usage is tracked). class COMPONENT_EXPORT(STORAGE_BROWSER) FileUpdateObserver { public: - FileUpdateObserver() {} - virtual ~FileUpdateObserver() {} + FileUpdateObserver() = default; + FileUpdateObserver(const FileUpdateObserver&) = delete; + FileUpdateObserver& operator=(const FileUpdateObserver&) = delete; + virtual ~FileUpdateObserver() = default; virtual void OnStartUpdate(const FileSystemURL& url) = 0; virtual void OnUpdate(const FileSystemURL& url, int64_t delta) = 0; virtual void OnEndUpdate(const FileSystemURL& url) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(FileUpdateObserver); }; // An abstract interface to observe file access. @@ -48,13 +46,12 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileUpdateObserver { // is recursive or not) class COMPONENT_EXPORT(STORAGE_BROWSER) FileAccessObserver { public: - FileAccessObserver() {} - virtual ~FileAccessObserver() {} + FileAccessObserver() = default; + FileAccessObserver(const FileAccessObserver&) = delete; + FileAccessObserver& operator=(const FileAccessObserver&) = delete; + virtual ~FileAccessObserver() = default; virtual void OnAccess(const FileSystemURL& url) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(FileAccessObserver); }; // An abstract interface to observe file changes. @@ -64,8 +61,10 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileAccessObserver { // by the local sandbox file system. class COMPONENT_EXPORT(STORAGE_BROWSER) FileChangeObserver { public: - FileChangeObserver() {} - virtual ~FileChangeObserver() {} + FileChangeObserver() = default; + FileChangeObserver(const FileChangeObserver&) = delete; + FileChangeObserver& operator=(const FileChangeObserver&) = delete; + virtual ~FileChangeObserver() = default; virtual void OnCreateFile(const FileSystemURL& url) = 0; virtual void OnCreateFileFrom(const FileSystemURL& url, @@ -75,9 +74,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileChangeObserver { virtual void OnCreateDirectory(const FileSystemURL& url) = 0; virtual void OnRemoveDirectory(const FileSystemURL& url) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(FileChangeObserver); }; } // 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 7c414264e34..7e3c8ecffcf 100644 --- a/chromium/storage/browser/file_system/file_stream_writer.h +++ b/chromium/storage/browser/file_system/file_stream_writer.h @@ -42,9 +42,11 @@ class FileStreamWriter { int64_t initial_offset, OpenOrCreate open_or_create); + FileStreamWriter(const FileStreamWriter&) = delete; + FileStreamWriter& operator=(const FileStreamWriter&) = delete; // Closes the file. If there's an in-flight operation, it is canceled (i.e., // the callback function associated with the operation is not called). - virtual ~FileStreamWriter() {} + virtual ~FileStreamWriter() = default; // Writes to the current cursor position asynchronously. // @@ -94,6 +96,9 @@ class FileStreamWriter { // // It is invalid to call Flush while there is an in-flight async operation. virtual int Flush(net::CompletionOnceCallback callback) = 0; + + protected: + FileStreamWriter() = default; }; } // namespace storage diff --git a/chromium/storage/browser/file_system/file_system_backend.h b/chromium/storage/browser/file_system/file_system_backend.h index 44bc0687471..ead78eb0375 100644 --- a/chromium/storage/browser/file_system/file_system_backend.h +++ b/chromium/storage/browser/file_system/file_system_backend.h @@ -20,6 +20,7 @@ #include "storage/browser/file_system/open_file_system_mode.h" #include "storage/browser/file_system/task_runner_bound_observer_list.h" #include "storage/common/file_system/file_system_types.h" +#include "url/origin.h" class GURL; @@ -167,12 +168,11 @@ class ExternalFileSystemBackend : public FileSystemBackend { // provider. This list is used to set appropriate child process file access // permissions. virtual std::vector<base::FilePath> GetRootDirectories() const = 0; - // Grants access to |virtual_path| from |origin_url|. - virtual void GrantFileAccessToExtension( - const std::string& extension_id, - const base::FilePath& virtual_path) = 0; - // Revokes file access from extension identified with |extension_id|. - virtual void RevokeAccessForExtension(const std::string& extension_id) = 0; + // Grants access to |virtual_path| from |origin| URL. + virtual void GrantFileAccessToOrigin(const url::Origin& origin, + const base::FilePath& virtual_path) = 0; + // Revokes file access from origin identified with |origin|. + virtual void RevokeAccessForOrigin(const url::Origin& origin) = 0; // Gets virtual path by known filesystem path. Returns false when filesystem // path is not exposed by this provider. virtual bool GetVirtualPath(const base::FilePath& file_system_path, diff --git a/chromium/storage/browser/file_system/file_system_context.cc b/chromium/storage/browser/file_system/file_system_context.cc index 06fbf60cc1d..a9dff4886dc 100644 --- a/chromium/storage/browser/file_system/file_system_context.cc +++ b/chromium/storage/browser/file_system/file_system_context.cc @@ -13,12 +13,19 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/containers/contains.h" +#include "base/feature_list.h" #include "base/macros.h" #include "base/memory/ptr_util.h" +#include "base/memory/scoped_refptr.h" #include "base/single_thread_task_runner.h" #include "base/task_runner_util.h" #include "base/threading/thread_task_runner_handle.h" #include "base/types/pass_key.h" +#include "components/services/storage/public/cpp/quota_client_callback_wrapper.h" +#include "components/services/storage/public/mojom/quota_client.mojom.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/receiver.h" #include "net/url_request/url_request.h" #include "storage/browser/file_system/copy_or_move_file_validator.h" #include "storage/browser/file_system/external_mount_points.h" @@ -31,6 +38,7 @@ #include "storage/browser/file_system/file_system_operation_runner.h" #include "storage/browser/file_system/file_system_options.h" #include "storage/browser/file_system/file_system_quota_client.h" +#include "storage/browser/file_system/file_system_util.h" #include "storage/browser/file_system/isolated_context.h" #include "storage/browser/file_system/isolated_file_system_backend.h" #include "storage/browser/file_system/mount_points.h" @@ -40,9 +48,12 @@ #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/common/storage_key/storage_key.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" +#include "url/gurl.h" +#include "url/origin.h" namespace storage { @@ -92,7 +103,6 @@ int FileSystemContext::GetPermissionPolicy(FileSystemType type) { case kFileSystemTypeLocalForPlatformApp: case kFileSystemTypeLocal: - case kFileSystemTypeCloudDevice: case kFileSystemTypeProvided: case kFileSystemTypeDeviceMediaAsFileStorage: case kFileSystemTypeDriveFs: @@ -133,26 +143,60 @@ int FileSystemContext::GetPermissionPolicy(FileSystemType type) { return FILE_PERMISSION_ALWAYS_DENY; } +scoped_refptr<FileSystemContext> FileSystemContext::Create( + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, + scoped_refptr<base::SequencedTaskRunner> file_task_runner, + scoped_refptr<ExternalMountPoints> external_mount_points, + scoped_refptr<SpecialStoragePolicy> special_storage_policy, + scoped_refptr<QuotaManagerProxy> quota_manager_proxy, + std::vector<std::unique_ptr<FileSystemBackend>> additional_backends, + const std::vector<URLRequestAutoMountHandler>& auto_mount_handlers, + const base::FilePath& partition_path, + const FileSystemOptions& options) { + bool force_override_incognito = base::FeatureList::IsEnabled( + features::kIncognitoFileSystemContextForTesting); + FileSystemOptions maybe_overridden_options = + force_override_incognito + ? FileSystemOptions(FileSystemOptions::PROFILE_MODE_INCOGNITO, + /*force_in_memory=*/true, + options.additional_allowed_schemes()) + : options; + + auto context = base::MakeRefCounted<FileSystemContext>( + std::move(io_task_runner), std::move(file_task_runner), + std::move(external_mount_points), std::move(special_storage_policy), + std::move(quota_manager_proxy), std::move(additional_backends), + auto_mount_handlers, partition_path, maybe_overridden_options, + base::PassKey<FileSystemContext>()); + context->Initialize(); + return context; +} + FileSystemContext::FileSystemContext( - base::SingleThreadTaskRunner* io_task_runner, - base::SequencedTaskRunner* file_task_runner, - ExternalMountPoints* external_mount_points, - SpecialStoragePolicy* special_storage_policy, - QuotaManagerProxy* quota_manager_proxy, + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, + scoped_refptr<base::SequencedTaskRunner> file_task_runner, + scoped_refptr<ExternalMountPoints> external_mount_points, + scoped_refptr<SpecialStoragePolicy> special_storage_policy, + scoped_refptr<QuotaManagerProxy> quota_manager_proxy, std::vector<std::unique_ptr<FileSystemBackend>> additional_backends, const std::vector<URLRequestAutoMountHandler>& auto_mount_handlers, const base::FilePath& partition_path, - const FileSystemOptions& options) + const FileSystemOptions& options, + base::PassKey<FileSystemContext>) : base::RefCountedDeleteOnSequence<FileSystemContext>(io_task_runner), env_override_(options.is_in_memory() ? leveldb_chrome::NewMemEnv("FileSystem") : nullptr), - io_task_runner_(io_task_runner), - default_file_task_runner_(file_task_runner), - quota_manager_proxy_(quota_manager_proxy), + io_task_runner_(std::move(io_task_runner)), + default_file_task_runner_(std::move(file_task_runner)), + quota_manager_proxy_(std::move(quota_manager_proxy)), + quota_client_(std::make_unique<FileSystemQuotaClient>(this)), + quota_client_wrapper_( + std::make_unique<storage::QuotaClientCallbackWrapper>( + quota_client_.get())), sandbox_delegate_(std::make_unique<SandboxFileSystemBackendDelegate>( - quota_manager_proxy, - file_task_runner, + quota_manager_proxy_.get(), + default_file_task_runner_.get(), partition_path, special_storage_policy, options, @@ -160,19 +204,22 @@ FileSystemContext::FileSystemContext( sandbox_backend_( std::make_unique<SandboxFileSystemBackend>(sandbox_delegate_.get())), plugin_private_backend_(std::make_unique<PluginPrivateFileSystemBackend>( - file_task_runner, + default_file_task_runner_, partition_path, - special_storage_policy, + std::move(special_storage_policy), options, env_override_.get())), additional_backends_(std::move(additional_backends)), auto_mount_handlers_(auto_mount_handlers), - external_mount_points_(external_mount_points), + external_mount_points_(std::move(external_mount_points)), partition_path_(partition_path), is_incognito_(options.is_incognito()), operation_runner_(std::make_unique<FileSystemOperationRunner>( base::PassKey<FileSystemContext>(), - this)) { + this)), + quota_client_receiver_( + std::make_unique<mojo::Receiver<mojom::QuotaClient>>( + quota_client_wrapper_.get())) { RegisterBackend(sandbox_backend_.get()); RegisterBackend(plugin_private_backend_.get()); @@ -188,15 +235,9 @@ FileSystemContext::FileSystemContext( !base::Contains(backend_map_, kFileSystemTypeLocal), !base::Contains(backend_map_, kFileSystemTypeLocalForPlatformApp)); RegisterBackend(isolated_backend_.get()); +} - if (quota_manager_proxy) { - // Quota client assumes all backends have registered. - // TODO(crbug.com/1163048): Use mojo and switch to RegisterClient(). - quota_manager_proxy->RegisterLegacyClient( - base::MakeRefCounted<FileSystemQuotaClient>(this), - QuotaClientType::kFileSystem, QuotaManagedStorageTypes()); - } - +void FileSystemContext::Initialize() { sandbox_backend_->Initialize(this); isolated_backend_->Initialize(this); plugin_private_backend_->Initialize(this); @@ -205,10 +246,37 @@ FileSystemContext::FileSystemContext( // Additional mount points must be added before regular system-wide // mount points. - if (external_mount_points) - url_crackers_.push_back(external_mount_points); + if (external_mount_points_) + url_crackers_.push_back(external_mount_points_.get()); url_crackers_.push_back(ExternalMountPoints::GetSystemInstance()); url_crackers_.push_back(IsolatedContext::GetInstance()); + + if (!quota_manager_proxy_) + return; + + // QuotaManagerProxy::RegisterClient() must be called synchronously during + // DatabaseTracker creation until crbug.com/1182630 is fixed. + mojo::PendingRemote<storage::mojom::QuotaClient> quota_client_remote; + mojo::PendingReceiver<storage::mojom::QuotaClient> quota_client_receiver = + quota_client_remote.InitWithNewPipeAndPassReceiver(); + quota_manager_proxy_->RegisterClient(std::move(quota_client_remote), + storage::QuotaClientType::kFileSystem, + QuotaManagedStorageTypes()); + + io_task_runner_->PostTask( + FROM_HERE, + base::BindOnce( + [](scoped_refptr<FileSystemContext> self, + mojo::PendingReceiver<storage::mojom::QuotaClient> receiver) { + if (!self->quota_client_receiver_) { + // Shutdown() may be called directly on the IO sequence. If that + // happens, `quota_client_receiver_` may get reset before this + // task runs. + return; + } + self->quota_client_receiver_->Bind(std::move(receiver)); + }, + base::RetainedRef(this), std::move(quota_client_receiver))); } bool FileSystemContext::DeleteDataForOriginOnFileTaskRunner( @@ -251,6 +319,13 @@ void FileSystemContext::Shutdown() { base::WrapRefCounted(this))); return; } + + // The mojo receiver must be destroyed before the instance it calls into is + // destroyed. + quota_client_receiver_.reset(); + quota_client_wrapper_.reset(); + quota_client_.reset(); + operation_runner_->Shutdown(); } @@ -334,7 +409,7 @@ ExternalFileSystemBackend* FileSystemContext::external_backend() const { GetFileSystemBackend(kFileSystemTypeExternal)); } -void FileSystemContext::OpenFileSystem(const url::Origin& origin, +void FileSystemContext::OpenFileSystem(const blink::StorageKey& storage_key, FileSystemType type, OpenFileSystemMode mode, OpenFileSystemCallback callback) { @@ -356,7 +431,7 @@ void FileSystemContext::OpenFileSystem(const url::Origin& origin, } backend->ResolveURL( - CreateCrackedFileSystemURL(origin, type, base::FilePath()), mode, + CreateCrackedFileSystemURL(storage_key, type, base::FilePath()), mode, std::move(callback)); } @@ -392,7 +467,11 @@ void FileSystemContext::ResolveURL(const FileSystemURL& url, void FileSystemContext::AttemptAutoMountForURLRequest( const FileSystemRequestInfo& request_info, StatusCallback callback) { - const FileSystemURL filesystem_url(request_info.url); + // TODO(https://crbug.com/1221308): function will use StorageKey for the + // receiver frame/worker in future CL + const FileSystemURL filesystem_url( + request_info.url, + blink::StorageKey(url::Origin::Create(request_info.url))); if (filesystem_url.type() == kFileSystemTypeExternal) { for (auto& handler : auto_mount_handlers_) { auto split_callback = base::SplitOnceCallback(std::move(callback)); @@ -473,15 +552,23 @@ FileSystemContext::CreateSequenceBoundFileSystemOperationRunner() { base::WrapRefCounted(this)); } -FileSystemURL FileSystemContext::CrackURL(const GURL& url) const { - return CrackFileSystemURL(FileSystemURL(url)); +FileSystemURL FileSystemContext::CrackURL( + const GURL& url, + const blink::StorageKey& storage_key) const { + return CrackFileSystemURL(FileSystemURL(url, storage_key)); +} + +FileSystemURL FileSystemContext::CrackURLInFirstPartyContext( + const GURL& url) const { + return CrackFileSystemURL( + FileSystemURL(url, blink::StorageKey(url::Origin::Create(url)))); } FileSystemURL FileSystemContext::CreateCrackedFileSystemURL( - const url::Origin& origin, + const blink::StorageKey& storage_key, FileSystemType type, const base::FilePath& path) const { - return CrackFileSystemURL(FileSystemURL(origin, type, path)); + return CrackFileSystemURL(FileSystemURL(storage_key, type, path)); } bool FileSystemContext::CanServeURLRequest(const FileSystemURL& url) const { @@ -575,10 +662,10 @@ FileSystemURL FileSystemContext::CrackFileSystemURL( // top of an external filesystem). Hence cracking needs to be iterated. for (;;) { FileSystemURL cracked = current; - for (size_t i = 0; i < url_crackers_.size(); ++i) { - if (!url_crackers_[i]->HandlesFileSystemMountType(current.type())) + for (MountPoints* url_cracker : url_crackers_) { + if (!url_cracker->HandlesFileSystemMountType(current.type())) continue; - cracked = url_crackers_[i]->CrackFileSystemURL(current); + cracked = url_cracker->CrackFileSystemURL(current); if (cracked.is_valid()) break; } @@ -633,7 +720,8 @@ void FileSystemContext::DidOpenFileSystemForResolveURL( FileSystemInfo info(filesystem_name, filesystem_root, url.mount_type()); // Extract the virtual path not containing a filesystem type part from |url|. - base::FilePath parent = CrackURL(filesystem_root).virtual_path(); + base::FilePath parent = + CrackURLInFirstPartyContext(filesystem_root).virtual_path(); base::FilePath child = url.virtual_path(); base::FilePath path; diff --git a/chromium/storage/browser/file_system/file_system_context.h b/chromium/storage/browser/file_system/file_system_context.h index 1ad6daf3cd1..49d34aaf8a4 100644 --- a/chromium/storage/browser/file_system/file_system_context.h +++ b/chromium/storage/browser/file_system/file_system_context.h @@ -17,9 +17,13 @@ #include "base/files/file.h" #include "base/macros.h" #include "base/memory/ref_counted_delete_on_sequence.h" +#include "base/memory/scoped_refptr.h" #include "base/sequenced_task_runner_helpers.h" #include "base/threading/sequence_bound.h" +#include "base/types/pass_key.h" #include "build/build_config.h" +#include "components/services/storage/public/mojom/quota_client.mojom.h" +#include "mojo/public/cpp/bindings/receiver.h" #include "storage/browser/file_system/file_system_url.h" #include "storage/browser/file_system/open_file_system_mode.h" #include "storage/browser/file_system/plugin_private_file_system_backend.h" @@ -36,6 +40,10 @@ class SequencedTaskRunner; class SingleThreadTaskRunner; } // namespace base +namespace blink { +class StorageKey; +} + namespace leveleb { class Env; } @@ -52,10 +60,12 @@ class FileSystemBackend; class FileSystemOperation; class FileSystemOperationRunner; class FileSystemOptions; +class FileSystemQuotaClient; class FileSystemQuotaUtil; class FileSystemURL; class IsolatedFileSystemBackend; class MountPoints; +class QuotaClientCallbackWrapper; class QuotaManagerProxy; class QuotaReservation; class SandboxFileSystemBackend; @@ -87,6 +97,8 @@ using URLRequestAutoMountHandler = base::RepeatingCallback<bool( class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemContext : public base::RefCountedDeleteOnSequence<FileSystemContext> { public: + REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE(); + // Returns file permission policy we should apply for the given |type|. // The return value must be bitwise-or'd of FilePermissionPolicy. // @@ -116,17 +128,31 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemContext // |auto_mount_handlers| are used to resolve calls to // AttemptAutoMountForURLRequest. Only external filesystems are auto mounted // when a filesystem: URL request is made. - FileSystemContext( - base::SingleThreadTaskRunner* io_task_runner, - base::SequencedTaskRunner* file_task_runner, - ExternalMountPoints* external_mount_points, - SpecialStoragePolicy* special_storage_policy, - QuotaManagerProxy* quota_manager_proxy, + static scoped_refptr<FileSystemContext> Create( + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, + scoped_refptr<base::SequencedTaskRunner> file_task_runner, + scoped_refptr<ExternalMountPoints> external_mount_points, + scoped_refptr<SpecialStoragePolicy> special_storage_policy, + scoped_refptr<QuotaManagerProxy> quota_manager_proxy, std::vector<std::unique_ptr<FileSystemBackend>> additional_backends, const std::vector<URLRequestAutoMountHandler>& auto_mount_handlers, const base::FilePath& partition_path, const FileSystemOptions& options); + // Exposed for base::MakeRefCounted(). Instances should be obtained from the + // factory method Create(). + FileSystemContext( + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, + scoped_refptr<base::SequencedTaskRunner> file_task_runner, + scoped_refptr<ExternalMountPoints> external_mount_points, + scoped_refptr<SpecialStoragePolicy> special_storage_policy, + scoped_refptr<QuotaManagerProxy> quota_manager_proxy, + std::vector<std::unique_ptr<FileSystemBackend>> additional_backends, + const std::vector<URLRequestAutoMountHandler>& auto_mount_handlers, + const base::FilePath& partition_path, + const FileSystemOptions& options, + base::PassKey<FileSystemContext>); + bool DeleteDataForOriginOnFileTaskRunner(const url::Origin& origin); // Creates a new QuotaReservation for the given |origin| and |type|. @@ -208,12 +234,12 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemContext // Used for DeleteFileSystem and OpenPluginPrivateFileSystem. using StatusCallback = base::OnceCallback<void(base::File::Error result)>; - // Opens the filesystem for the given |origin_url| and |type|, and dispatches - // |callback| on completion. - // If |create| is true this may actually set up a filesystem instance + // Opens the filesystem for the given `storage_key` and `type`, and dispatches + // `callback` on completion. + // If `create` is true this may actually set up a filesystem instance // (e.g. by creating the root directory or initializing the database // entry etc). - void OpenFileSystem(const url::Origin& origin, + void OpenFileSystem(const blink::StorageKey& storage_key, FileSystemType type, OpenFileSystemMode mode, OpenFileSystemCallback callback); @@ -280,11 +306,21 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemContext const base::FilePath& partition_path() const { return partition_path_; } - // Same as |CrackFileSystemURL|, but cracks FileSystemURL created from |url|. - FileSystemURL CrackURL(const GURL& url) const; - // Same as |CrackFileSystemURL|, but cracks FileSystemURL created from method + // Same as `CrackFileSystemURL`, but cracks FileSystemURL created from `url` + // and `storage_key`. + FileSystemURL CrackURL(const GURL& url, + const blink::StorageKey& storage_key) const; + + // Same as `CrackFileSystemURL`, but cracks FileSystemURL created from `url` + // and a blink::StorageKey it derives from `url`. Note: never use this + // function to crack URLs received from web contents. For all web-exposed + // URLs, use the CrackURL function above and pass in the StorageKey of the + // frame or worker that provided the URL. + FileSystemURL CrackURLInFirstPartyContext(const GURL& url) const; + + // Same as `CrackFileSystemURL`, but cracks FileSystemURL created from method // arguments. - FileSystemURL CreateCrackedFileSystemURL(const url::Origin& origin, + FileSystemURL CreateCrackedFileSystemURL(const blink::StorageKey& storage_key, FileSystemType type, const base::FilePath& path) const; @@ -318,11 +354,13 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemContext friend class PluginPrivateFileSystemBackendTest; // Deleters. - friend struct DefaultContextDeleter; friend class base::DeleteHelper<FileSystemContext>; friend class base::RefCountedDeleteOnSequence<FileSystemContext>; ~FileSystemContext(); + // Must be called after creating the FileSystemContext. + void Initialize(); + // The list of quota-managed storage types covered by file system backends. // // This is called during the constructor, before the file system backends are @@ -371,20 +409,22 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemContext // Override the default leveldb Env with |env_override_| if set. std::unique_ptr<leveldb::Env> env_override_; - scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; - scoped_refptr<base::SequencedTaskRunner> default_file_task_runner_; + const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; + const scoped_refptr<base::SequencedTaskRunner> default_file_task_runner_; - scoped_refptr<QuotaManagerProxy> quota_manager_proxy_; + const scoped_refptr<QuotaManagerProxy> quota_manager_proxy_; + std::unique_ptr<FileSystemQuotaClient> quota_client_; + std::unique_ptr<storage::QuotaClientCallbackWrapper> quota_client_wrapper_; - std::unique_ptr<SandboxFileSystemBackendDelegate> sandbox_delegate_; + const std::unique_ptr<SandboxFileSystemBackendDelegate> sandbox_delegate_; // Regular file system backends. - std::unique_ptr<SandboxFileSystemBackend> sandbox_backend_; + const std::unique_ptr<SandboxFileSystemBackend> sandbox_backend_; std::unique_ptr<IsolatedFileSystemBackend> isolated_backend_; // Additional file system backends. - std::unique_ptr<PluginPrivateFileSystemBackend> plugin_private_backend_; - std::vector<std::unique_ptr<FileSystemBackend>> additional_backends_; + const std::unique_ptr<PluginPrivateFileSystemBackend> plugin_private_backend_; + const std::vector<std::unique_ptr<FileSystemBackend>> additional_backends_; std::vector<URLRequestAutoMountHandler> auto_mount_handlers_; @@ -398,7 +438,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemContext // External mount points visible in the file system context (excluding system // external mount points). - scoped_refptr<ExternalMountPoints> external_mount_points_; + const scoped_refptr<ExternalMountPoints> external_mount_points_; // MountPoints used to crack FileSystemURLs. The MountPoints are ordered // in order they should try to crack a FileSystemURL. @@ -407,9 +447,11 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemContext // The base path of the storage partition for this context. const base::FilePath partition_path_; - bool is_incognito_; + const bool is_incognito_; + + const std::unique_ptr<FileSystemOperationRunner> operation_runner_; - std::unique_ptr<FileSystemOperationRunner> operation_runner_; + std::unique_ptr<mojo::Receiver<mojom::QuotaClient>> quota_client_receiver_; DISALLOW_IMPLICIT_CONSTRUCTORS(FileSystemContext); }; diff --git a/chromium/storage/browser/file_system/file_system_context_unittest.cc b/chromium/storage/browser/file_system/file_system_context_unittest.cc index 76aa905b046..26c4da3e222 100644 --- a/chromium/storage/browser/file_system/file_system_context_unittest.cc +++ b/chromium/storage/browser/file_system/file_system_context_unittest.cc @@ -6,10 +6,10 @@ #include <stddef.h> +#include "base/cxx17_backports.h" #include "base/files/scoped_temp_dir.h" #include "base/macros.h" #include "base/memory/scoped_refptr.h" -#include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "base/test/task_environment.h" #include "base/threading/thread_task_runner_handle.h" @@ -18,6 +18,7 @@ #include "storage/browser/file_system/external_mount_points.h" #include "storage/browser/file_system/file_system_backend.h" #include "storage/browser/file_system/isolated_context.h" +#include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/test/mock_quota_manager.h" #include "storage/browser/test/mock_special_storage_policy.h" #include "storage/browser/test/test_file_system_options.h" @@ -60,12 +61,12 @@ class FileSystemContextTest : public testing::Test { } protected: - FileSystemContext* CreateFileSystemContextForTest( - ExternalMountPoints* external_mount_points) { - return new FileSystemContext( - base::ThreadTaskRunnerHandle::Get().get(), - base::ThreadTaskRunnerHandle::Get().get(), external_mount_points, - storage_policy_.get(), mock_quota_manager_->proxy(), + scoped_refptr<FileSystemContext> CreateFileSystemContextForTest( + scoped_refptr<ExternalMountPoints> external_mount_points) { + return FileSystemContext::Create( + base::ThreadTaskRunnerHandle::Get(), + base::ThreadTaskRunnerHandle::Get(), std::move(external_mount_points), + storage_policy_, mock_quota_manager_->proxy(), std::vector<std::unique_ptr<FileSystemBackend>>(), std::vector<URLRequestAutoMountHandler>(), data_dir_.GetPath(), CreateAllowFileAccessOptions()); @@ -100,8 +101,8 @@ class FileSystemContextTest : public testing::Test { // ChromeOS. #if !BUILDFLAG(IS_CHROMEOS_ASH) TEST_F(FileSystemContextTest, NullExternalMountPoints) { - scoped_refptr<FileSystemContext> file_system_context( - CreateFileSystemContextForTest(nullptr)); + scoped_refptr<FileSystemContext> file_system_context = + CreateFileSystemContextForTest(/*external_mount_points=*/nullptr); // Cracking system external mount and isolated mount points should work. std::string isolated_name = "root"; @@ -115,8 +116,9 @@ TEST_F(FileSystemContextTest, NullExternalMountPoints) { "system", kFileSystemTypeLocal, FileSystemMountOption(), base::FilePath(DRIVE FPL("/test/sys/")))); - FileSystemURL cracked_isolated = file_system_context->CrackURL( - CreateRawFileSystemURL("isolated", isolated_id)); + FileSystemURL cracked_isolated = + file_system_context->CrackURLInFirstPartyContext( + CreateRawFileSystemURL("isolated", isolated_id)); ExpectFileSystemURLMatches( cracked_isolated, GURL(kTestOrigin), kFileSystemTypeIsolated, @@ -128,8 +130,9 @@ TEST_F(FileSystemContextTest, NullExternalMountPoints) { .NormalizePathSeparators(), isolated_id); - FileSystemURL cracked_external = file_system_context->CrackURL( - CreateRawFileSystemURL("external", "system")); + FileSystemURL cracked_external = + file_system_context->CrackURLInFirstPartyContext( + CreateRawFileSystemURL("external", "system")); ExpectFileSystemURLMatches( cracked_external, GURL(kTestOrigin), kFileSystemTypeExternal, @@ -153,16 +156,14 @@ TEST_F(FileSystemContextTest, FileSystemContextKeepsMountPointsAlive) { "system", kFileSystemTypeLocal, FileSystemMountOption(), base::FilePath(DRIVE FPL("/test/sys/")))); - scoped_refptr<FileSystemContext> file_system_context( - CreateFileSystemContextForTest(mount_points.get())); - - // Release a MountPoints reference created in the test. - mount_points = nullptr; + scoped_refptr<FileSystemContext> file_system_context = + CreateFileSystemContextForTest(std::move(mount_points)); // FileSystemContext should keep a reference to the |mount_points|, so it // should be able to resolve the URL. - FileSystemURL cracked_external = file_system_context->CrackURL( - CreateRawFileSystemURL("external", "system")); + FileSystemURL cracked_external = + file_system_context->CrackURLInFirstPartyContext( + CreateRawFileSystemURL("external", "system")); ExpectFileSystemURLMatches( cracked_external, GURL(kTestOrigin), kFileSystemTypeExternal, @@ -177,10 +178,10 @@ TEST_F(FileSystemContextTest, FileSystemContextKeepsMountPointsAlive) { } TEST_F(FileSystemContextTest, CrackFileSystemURL) { - scoped_refptr<ExternalMountPoints> external_mount_points( - ExternalMountPoints::CreateRefCounted()); - scoped_refptr<FileSystemContext> file_system_context( - CreateFileSystemContextForTest(external_mount_points.get())); + scoped_refptr<ExternalMountPoints> external_mount_points = + ExternalMountPoints::CreateRefCounted(); + scoped_refptr<FileSystemContext> file_system_context = + CreateFileSystemContextForTest(external_mount_points); // Register an isolated mount point. std::string isolated_file_system_name = "root"; @@ -268,7 +269,8 @@ TEST_F(FileSystemContextTest, CrackFileSystemURL) { GURL raw_url = CreateRawFileSystemURL(kTestCases[i].type_str, kTestCases[i].root); - FileSystemURL cracked_url = file_system_context->CrackURL(raw_url); + FileSystemURL cracked_url = + file_system_context->CrackURLInFirstPartyContext(raw_url); SCOPED_TRACE(testing::Message() << "Test case " << i << ": " << "Cracking URL: " << raw_url); @@ -294,14 +296,14 @@ TEST_F(FileSystemContextTest, CrackFileSystemURL) { } TEST_F(FileSystemContextTest, CanServeURLRequest) { - scoped_refptr<ExternalMountPoints> external_mount_points( - ExternalMountPoints::CreateRefCounted()); - scoped_refptr<FileSystemContext> context( - CreateFileSystemContextForTest(external_mount_points.get())); + scoped_refptr<ExternalMountPoints> external_mount_points = + ExternalMountPoints::CreateRefCounted(); + scoped_refptr<FileSystemContext> context = + CreateFileSystemContextForTest(std::move(external_mount_points)); // A request for a sandbox mount point should be served. - FileSystemURL cracked_url = - context->CrackURL(CreateRawFileSystemURL("persistent", "pers_mount")); + FileSystemURL cracked_url = context->CrackURLInFirstPartyContext( + CreateRawFileSystemURL("persistent", "pers_mount")); EXPECT_EQ(kFileSystemTypePersistent, cracked_url.mount_type()); EXPECT_TRUE(context->CanServeURLRequest(cracked_url)); @@ -312,8 +314,8 @@ TEST_F(FileSystemContextTest, CanServeURLRequest) { kFileSystemTypeLocal, std::string(), base::FilePath(DRIVE FPL("/test/isolated/root")), &isolated_fs_name); std::string isolated_fs_id = isolated_fs.id(); - cracked_url = - context->CrackURL(CreateRawFileSystemURL("isolated", isolated_fs_id)); + cracked_url = context->CrackURLInFirstPartyContext( + CreateRawFileSystemURL("isolated", isolated_fs_id)); EXPECT_EQ(kFileSystemTypeIsolated, cracked_url.mount_type()); EXPECT_FALSE(context->CanServeURLRequest(cracked_url)); @@ -322,8 +324,8 @@ TEST_F(FileSystemContextTest, CanServeURLRequest) { ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( kExternalMountName, kFileSystemTypeLocal, FileSystemMountOption(), base::FilePath())); - cracked_url = - context->CrackURL(CreateRawFileSystemURL("external", kExternalMountName)); + cracked_url = context->CrackURLInFirstPartyContext( + CreateRawFileSystemURL("external", kExternalMountName)); EXPECT_EQ(kFileSystemTypeExternal, cracked_url.mount_type()); EXPECT_TRUE(context->CanServeURLRequest(cracked_url)); @@ -337,8 +339,8 @@ TEST_F(FileSystemContextTest, CanServeURLRequest) { TEST_F(FileSystemContextTest, IsolatedFileSystemsTypesHandled) { // This does not provide any "additional" file system handlers. In particular, // on Chrome OS it does not provide chromeos::FileSystemBackend. - scoped_refptr<FileSystemContext> file_system_context( - CreateFileSystemContextForTest(nullptr)); + scoped_refptr<FileSystemContext> file_system_context = + CreateFileSystemContextForTest(/*external_mount_points=*/nullptr); // Isolated file system types are handled. EXPECT_TRUE( diff --git a/chromium/storage/browser/file_system/file_system_features.cc b/chromium/storage/browser/file_system/file_system_features.cc index d8472bd470d..102fb326ce4 100644 --- a/chromium/storage/browser/file_system/file_system_features.cc +++ b/chromium/storage/browser/file_system/file_system_features.cc @@ -11,6 +11,12 @@ namespace features { // Enables persistent Filesystem API in incognito mode. const base::Feature kEnablePersistentFilesystemInIncognito{ "EnablePersistentFilesystemInIncognito", base::FEATURE_ENABLED_BY_DEFAULT}; + +// Creates FileSystemContexts in incognito mode. This is used to run web tests +// in incognito mode to ensure feature parity for FileSystemAccessAccessHandles. +const base::Feature kIncognitoFileSystemContextForTesting{ + "IncognitoFileSystemContextForTesting", base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace features } // namespace storage
\ No newline at end of file diff --git a/chromium/storage/browser/file_system/file_system_features.h b/chromium/storage/browser/file_system/file_system_features.h index 88d9c8662b4..94e9cb29b5c 100644 --- a/chromium/storage/browser/file_system/file_system_features.h +++ b/chromium/storage/browser/file_system/file_system_features.h @@ -15,6 +15,9 @@ namespace features { COMPONENT_EXPORT(STORAGE_BROWSER) extern const base::Feature kEnablePersistentFilesystemInIncognito; +COMPONENT_EXPORT(STORAGE_BROWSER) +extern const base::Feature kIncognitoFileSystemContextForTesting; + } // namespace features } // namespace storage diff --git a/chromium/storage/browser/file_system/file_system_file_util.h b/chromium/storage/browser/file_system/file_system_file_util.h index 1d855bad7dd..fbd0ee83d65 100644 --- a/chromium/storage/browser/file_system/file_system_file_util.h +++ b/chromium/storage/browser/file_system/file_system_file_util.h @@ -12,7 +12,6 @@ #include "base/component_export.h" #include "base/files/file.h" #include "base/files/file_path.h" -#include "base/macros.h" #include "storage/browser/blob/scoped_file.h" #include "storage/browser/file_system/file_system_operation.h" @@ -59,6 +58,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemFileUtil { bool IsDirectory() override; }; + FileSystemFileUtil(const FileSystemFileUtil&) = delete; + FileSystemFileUtil& operator=(const FileSystemFileUtil&) = delete; virtual ~FileSystemFileUtil() = default; // Creates or opens a file with the given flags. @@ -176,10 +177,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemFileUtil { base::FilePath* platform_path) = 0; protected: - FileSystemFileUtil() {} - - private: - DISALLOW_COPY_AND_ASSIGN(FileSystemFileUtil); + FileSystemFileUtil() = default; }; } // namespace storage diff --git a/chromium/storage/browser/file_system/file_system_operation.h b/chromium/storage/browser/file_system/file_system_operation.h index 18e98cf2d4a..89ee141c3e3 100644 --- a/chromium/storage/browser/file_system/file_system_operation.h +++ b/chromium/storage/browser/file_system/file_system_operation.h @@ -62,7 +62,9 @@ class FileSystemOperation { FileSystemContext* file_system_context, std::unique_ptr<FileSystemOperationContext> operation_context); - virtual ~FileSystemOperation() {} + FileSystemOperation(const FileSystemOperation&) = delete; + FileSystemOperation& operator=(const FileSystemOperation&) = delete; + virtual ~FileSystemOperation() = default; // Used for CreateFile(), etc. |result| is the return code of the operation. using StatusCallback = base::OnceCallback<void(base::File::Error result)>; @@ -546,6 +548,8 @@ class FileSystemOperation { kOperationGetLocalPath, kOperationCancel, }; + + FileSystemOperation() = default; }; } // namespace storage diff --git a/chromium/storage/browser/file_system/file_system_operation_impl.cc b/chromium/storage/browser/file_system/file_system_operation_impl.cc index fa53a2e2754..70ad2fe3526 100644 --- a/chromium/storage/browser/file_system/file_system_operation_impl.cc +++ b/chromium/storage/browser/file_system/file_system_operation_impl.cc @@ -25,11 +25,13 @@ #include "storage/browser/file_system/file_system_backend.h" #include "storage/browser/file_system/file_system_context.h" #include "storage/browser/file_system/file_system_file_util.h" +#include "storage/browser/file_system/file_system_util.h" #include "storage/browser/file_system/remove_operation_delegate.h" #include "storage/browser/file_system/sandbox_file_system_backend.h" #include "storage/browser/quota/quota_manager_proxy.h" #include "storage/common/file_system/file_system_types.h" #include "storage/common/file_system/file_system_util.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" namespace storage { @@ -417,7 +419,8 @@ void FileSystemOperationImpl::GetUsageAndQuotaThenRunTask( DCHECK(quota_manager_proxy); quota_manager_proxy->GetUsageAndQuota( - url.origin(), FileSystemTypeToQuotaStorageType(url.type()), + blink::StorageKey(url.origin()), + FileSystemTypeToQuotaStorageType(url.type()), base::SequencedTaskRunnerHandle::Get(), base::BindOnce(&FileSystemOperationImpl::DidGetUsageAndQuotaAndRunTask, weak_ptr_, std::move(task), std::move(error_callback))); diff --git a/chromium/storage/browser/file_system/file_system_operation_impl_unittest.cc b/chromium/storage/browser/file_system/file_system_operation_impl_unittest.cc index 13f885ff576..65a31f6ad3f 100644 --- a/chromium/storage/browser/file_system/file_system_operation_impl_unittest.cc +++ b/chromium/storage/browser/file_system/file_system_operation_impl_unittest.cc @@ -12,6 +12,7 @@ #include <utility> #include "base/bind.h" +#include "base/cxx17_backports.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/macros.h" @@ -19,7 +20,6 @@ #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/run_loop.h" -#include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "base/test/task_environment.h" #include "base/threading/thread_task_runner_handle.h" @@ -40,7 +40,7 @@ #include "storage/browser/test/sandbox_file_system_test_helper.h" #include "storage/common/file_system/file_system_util.h" #include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" namespace storage { @@ -70,11 +70,10 @@ class FileSystemOperationImplTest : public testing::Test { } void TearDown() override { - // Let the client go away before dropping a ref of the quota manager proxy. - quota_manager_proxy()->SimulateQuotaManagerDestroyed(); quota_manager_ = nullptr; quota_manager_proxy_ = nullptr; sandbox_file_system_.TearDown(); + task_environment_.RunUntilIdle(); } FileSystemOperationRunner* operation_runner() { @@ -258,7 +257,7 @@ class FileSystemOperationImplTest : public testing::Test { void GrantQuotaForCurrentUsage() { int64_t usage; GetUsageAndQuota(&usage, nullptr); - quota_manager()->SetQuota(sandbox_file_system_.origin(), + quota_manager()->SetQuota(blink::StorageKey(sandbox_file_system_.origin()), sandbox_file_system_.storage_type(), usage); } @@ -271,7 +270,7 @@ class FileSystemOperationImplTest : public testing::Test { void AddQuota(int64_t quota_delta) { int64_t quota; GetUsageAndQuota(nullptr, "a); - quota_manager()->SetQuota(sandbox_file_system_.origin(), + quota_manager()->SetQuota(blink::StorageKey(sandbox_file_system_.origin()), sandbox_file_system_.storage_type(), quota + quota_delta); } diff --git a/chromium/storage/browser/file_system/file_system_operation_impl_write_unittest.cc b/chromium/storage/browser/file_system/file_system_operation_impl_write_unittest.cc index 987ff4fd608..9186550edf7 100644 --- a/chromium/storage/browser/file_system/file_system_operation_impl_write_unittest.cc +++ b/chromium/storage/browser/file_system/file_system_operation_impl_write_unittest.cc @@ -22,7 +22,9 @@ #include "storage/browser/file_system/file_system_file_util.h" #include "storage/browser/file_system/file_system_operation_context.h" #include "storage/browser/file_system/file_system_operation_runner.h" +#include "storage/browser/file_system/file_system_util.h" #include "storage/browser/file_system/local_file_util.h" +#include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/test/mock_blob_util.h" #include "storage/browser/test/mock_file_change_observer.h" #include "storage/browser/test/mock_quota_manager.h" @@ -30,6 +32,7 @@ #include "storage/browser/test/test_file_system_context.h" #include "storage/common/file_system/file_system_util.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "url/gurl.h" #include "url/origin.h" @@ -104,7 +107,8 @@ class FileSystemOperationImplWriteTest : public testing::Test { FileSystemURL URLForPath(const base::FilePath& path) const { return file_system_context_->CreateCrackedFileSystemURL( - url::Origin::Create(GURL(kOrigin)), kFileSystemType, path); + blink::StorageKey::CreateFromStringForTesting(kOrigin), kFileSystemType, + path); } // Callback function for recording test results. @@ -248,9 +252,9 @@ TEST_F(FileSystemOperationImplWriteTest, TestWriteDir) { TEST_F(FileSystemOperationImplWriteTest, TestWriteFailureByQuota) { ScopedTextBlob blob(blob_storage_context(), "blob:success", "Hello, world!\n"); - quota_manager_->SetQuota(url::Origin::Create(GURL(kOrigin)), - FileSystemTypeToQuotaStorageType(kFileSystemType), - 10); + quota_manager_->SetQuota( + blink::StorageKey::CreateFromStringForTesting(kOrigin), + FileSystemTypeToQuotaStorageType(kFileSystemType), 10); file_system_context_->operation_runner()->Write(URLForPath(virtual_path_), blob.GetBlobDataHandle(), 0, RecordWriteCallback()); diff --git a/chromium/storage/browser/file_system/file_system_operation_runner.h b/chromium/storage/browser/file_system/file_system_operation_runner.h index 74cd2c1dd6f..8dafbc20962 100644 --- a/chromium/storage/browser/file_system/file_system_operation_runner.h +++ b/chromium/storage/browser/file_system/file_system_operation_runner.h @@ -154,13 +154,10 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemOperationRunner { const base::Time& last_modified_time, StatusCallback callback); - // Opens a file at |url| with |file_flags|, where flags are OR'ed - // values of base::PlatformFileFlags. - // - // |peer_handle| is the process handle of a pepper plugin process, which - // is necessary for underlying IPC calls with Pepper plugins. - // - // This function is used only by Pepper as of writing. + // Opens a file at |url| with |file_flags|, where flags are OR'ed values of + // base::File::Flags. This operation is not supported on all filesystems or + // all situation e.g. it will always fail for the sandboxed system when in + // Incognito mode. OperationID OpenFile(const FileSystemURL& url, int file_flags, OpenFileCallback callback); 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 ee87ffb244d..0e6e601ec18 100644 --- a/chromium/storage/browser/file_system/file_system_quota_client.cc +++ b/chromium/storage/browser/file_system/file_system_quota_client.cc @@ -4,66 +4,75 @@ #include "storage/browser/file_system/file_system_quota_client.h" -#include <algorithm> -#include <memory> +#include <string> +#include <utility> #include <vector> #include "base/bind.h" #include "base/check.h" -#include "base/files/file_util.h" +#include "base/files/file.h" #include "base/location.h" +#include "base/sequence_checker.h" #include "base/sequenced_task_runner.h" -#include "base/single_thread_task_runner.h" -#include "base/task_runner_util.h" +#include "storage/browser/file_system/file_system_backend.h" #include "storage/browser/file_system/file_system_context.h" -#include "storage/browser/file_system/file_system_usage_cache.h" -#include "storage/browser/file_system/sandbox_file_system_backend.h" +#include "storage/common/file_system/file_system_types.h" #include "storage/common/file_system/file_system_util.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" -#include "url/gurl.h" #include "url/origin.h" -using blink::mojom::StorageType; - namespace storage { namespace { -std::vector<url::Origin> GetOriginsForTypeOnFileTaskRunner( +std::vector<blink::StorageKey> ToStorageKeys( + const std::vector<url::Origin>& origins) { + std::vector<blink::StorageKey> storage_keys; + storage_keys.reserve(origins.size()); + for (const url::Origin& origin : origins) + storage_keys.emplace_back(blink::StorageKey(origin)); + return storage_keys; +} + +std::vector<blink::StorageKey> GetStorageKeysForTypeOnFileTaskRunner( FileSystemContext* context, - StorageType storage_type) { - FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type); + blink::mojom::StorageType storage_type) { + FileSystemType type = + FileSystemQuotaClient::QuotaStorageTypeToFileSystemType(storage_type); DCHECK(type != kFileSystemTypeUnknown); FileSystemQuotaUtil* quota_util = context->GetQuotaUtil(type); if (!quota_util) return {}; - return quota_util->GetOriginsForTypeOnFileTaskRunner(type); + return ToStorageKeys(quota_util->GetOriginsForTypeOnFileTaskRunner(type)); } -std::vector<url::Origin> GetOriginsForHostOnFileTaskRunner( +std::vector<blink::StorageKey> GetStorageKeysForHostOnFileTaskRunner( FileSystemContext* context, - StorageType storage_type, + blink::mojom::StorageType storage_type, const std::string& host) { - FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type); + FileSystemType type = + FileSystemQuotaClient::QuotaStorageTypeToFileSystemType(storage_type); DCHECK(type != kFileSystemTypeUnknown); FileSystemQuotaUtil* quota_util = context->GetQuotaUtil(type); if (!quota_util) return {}; - return quota_util->GetOriginsForHostOnFileTaskRunner(type, host); + return ToStorageKeys( + quota_util->GetOriginsForHostOnFileTaskRunner(type, host)); } -blink::mojom::QuotaStatusCode DeleteOriginOnFileTaskRunner( +blink::mojom::QuotaStatusCode DeleteStorageKeyOnFileTaskRunner( FileSystemContext* context, - const url::Origin& origin, + const blink::StorageKey& storage_key, FileSystemType type) { FileSystemBackend* provider = context->GetFileSystemBackend(type); if (!provider || !provider->GetQuotaUtil()) return blink::mojom::QuotaStatusCode::kErrorNotSupported; base::File::Error result = provider->GetQuotaUtil()->DeleteOriginDataOnFileTaskRunner( - context, context->quota_manager_proxy(), origin, type); + context, context->quota_manager_proxy(), storage_key.origin(), type); if (result == base::File::FILE_OK) return blink::mojom::QuotaStatusCode::kOk; return blink::mojom::QuotaStatusCode::kErrorInvalidModification; @@ -82,16 +91,24 @@ void PerformStorageCleanupOnFileTaskRunner(FileSystemContext* context, FileSystemQuotaClient::FileSystemQuotaClient( FileSystemContext* file_system_context) - : file_system_context_(file_system_context) {} + : file_system_context_(file_system_context) { + DCHECK(file_system_context_); + DETACH_FROM_SEQUENCE(sequence_checker_); +} -FileSystemQuotaClient::~FileSystemQuotaClient() = default; +FileSystemQuotaClient::~FileSystemQuotaClient() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} -void FileSystemQuotaClient::GetOriginUsage(const url::Origin& origin, - StorageType storage_type, - GetOriginUsageCallback callback) { +void FileSystemQuotaClient::GetStorageKeyUsage( + const blink::StorageKey& storage_key, + blink::mojom::StorageType storage_type, + GetStorageKeyUsageCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!callback.is_null()); - FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type); + FileSystemType type = + FileSystemQuotaClient::QuotaStorageTypeToFileSystemType(storage_type); DCHECK(type != kFileSystemTypeUnknown); FileSystemQuotaUtil* quota_util = file_system_context_->GetQuotaUtil(type); @@ -100,58 +117,68 @@ void FileSystemQuotaClient::GetOriginUsage(const url::Origin& origin, return; } - base::PostTaskAndReplyWithResult( - file_task_runner(), FROM_HERE, + file_task_runner()->PostTaskAndReplyWithResult( + FROM_HERE, // It is safe to pass Unretained(quota_util) since context owns it. base::BindOnce(&FileSystemQuotaUtil::GetOriginUsageOnFileTaskRunner, base::Unretained(quota_util), - base::RetainedRef(file_system_context_), origin, type), + base::RetainedRef(file_system_context_), + storage_key.origin(), type), std::move(callback)); } -void FileSystemQuotaClient::GetOriginsForType( - StorageType storage_type, - GetOriginsForTypeCallback callback) { +void FileSystemQuotaClient::GetStorageKeysForType( + blink::mojom::StorageType storage_type, + GetStorageKeysForTypeCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!callback.is_null()); file_task_runner()->PostTaskAndReplyWithResult( FROM_HERE, - base::BindOnce(&GetOriginsForTypeOnFileTaskRunner, + base::BindOnce(&GetStorageKeysForTypeOnFileTaskRunner, base::RetainedRef(file_system_context_), storage_type), std::move(callback)); } -void FileSystemQuotaClient::GetOriginsForHost( - StorageType storage_type, +void FileSystemQuotaClient::GetStorageKeysForHost( + blink::mojom::StorageType storage_type, const std::string& host, - GetOriginsForHostCallback callback) { + GetStorageKeysForHostCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!callback.is_null()); file_task_runner()->PostTaskAndReplyWithResult( FROM_HERE, - base::BindOnce(&GetOriginsForHostOnFileTaskRunner, + base::BindOnce(&GetStorageKeysForHostOnFileTaskRunner, base::RetainedRef(file_system_context_), storage_type, host), std::move(callback)); } -void FileSystemQuotaClient::DeleteOriginData( - const url::Origin& origin, - StorageType type, - DeleteOriginDataCallback callback) { +void FileSystemQuotaClient::DeleteStorageKeyData( + const blink::StorageKey& storage_key, + blink::mojom::StorageType type, + DeleteStorageKeyDataCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!callback.is_null()); + FileSystemType fs_type = QuotaStorageTypeToFileSystemType(type); DCHECK(fs_type != kFileSystemTypeUnknown); - base::PostTaskAndReplyWithResult( - file_task_runner(), FROM_HERE, - base::BindOnce(&DeleteOriginOnFileTaskRunner, - base::RetainedRef(file_system_context_), origin, fs_type), + file_task_runner()->PostTaskAndReplyWithResult( + FROM_HERE, + base::BindOnce(&DeleteStorageKeyOnFileTaskRunner, + base::RetainedRef(file_system_context_), storage_key, + fs_type), std::move(callback)); } void FileSystemQuotaClient::PerformStorageCleanup( - StorageType type, + blink::mojom::StorageType type, PerformStorageCleanupCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!callback.is_null()); + FileSystemType fs_type = QuotaStorageTypeToFileSystemType(type); DCHECK(fs_type != kFileSystemTypeUnknown); file_task_runner()->PostTaskAndReply( @@ -161,7 +188,25 @@ void FileSystemQuotaClient::PerformStorageCleanup( std::move(callback)); } +// static +FileSystemType FileSystemQuotaClient::QuotaStorageTypeToFileSystemType( + blink::mojom::StorageType storage_type) { + switch (storage_type) { + case blink::mojom::StorageType::kTemporary: + return kFileSystemTypeTemporary; + case blink::mojom::StorageType::kPersistent: + return kFileSystemTypePersistent; + case blink::mojom::StorageType::kSyncable: + return kFileSystemTypeSyncable; + case blink::mojom::StorageType::kQuotaNotManaged: + case blink::mojom::StorageType::kUnknown: + return kFileSystemTypeUnknown; + } + return kFileSystemTypeUnknown; +} + base::SequencedTaskRunner* FileSystemQuotaClient::file_task_runner() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 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 6ca864b4281..fee07e696b2 100644 --- a/chromium/storage/browser/file_system/file_system_quota_client.h +++ b/chromium/storage/browser/file_system/file_system_quota_client.h @@ -5,25 +5,26 @@ #ifndef STORAGE_BROWSER_FILE_SYSTEM_FILE_SYSTEM_QUOTA_CLIENT_H_ #define STORAGE_BROWSER_FILE_SYSTEM_FILE_SYSTEM_QUOTA_CLIENT_H_ -#include <set> #include <string> -#include <utility> -#include "base/compiler_specific.h" #include "base/component_export.h" -#include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/sequence_checker.h" +#include "base/thread_annotations.h" +#include "components/services/storage/public/cpp/storage_key_quota_client.h" #include "storage/browser/file_system/file_system_quota_util.h" -#include "storage/browser/quota/quota_client.h" #include "storage/browser/quota/quota_client_type.h" #include "storage/common/file_system/file_system_types.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" -#include "url/origin.h" namespace base { class SequencedTaskRunner; } +namespace blink { +class StorageKey; +} // namespace blink + namespace storage { class FileSystemContext; @@ -31,34 +32,55 @@ class FileSystemContext; // All of the public methods of this class are called by the quota manager // (except for the constructor/destructor). class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemQuotaClient - : public QuotaClient { + : public StorageKeyQuotaClient { public: explicit FileSystemQuotaClient(FileSystemContext* file_system_context); + ~FileSystemQuotaClient() override; + + FileSystemQuotaClient(const FileSystemQuotaClient&) = delete; + FileSystemQuotaClient& operator=(const FileSystemQuotaClient&) = delete; // QuotaClient methods. - void OnQuotaManagerDestroyed() override {} - void GetOriginUsage(const url::Origin& origin, - blink::mojom::StorageType type, - GetOriginUsageCallback callback) override; - void GetOriginsForType(blink::mojom::StorageType type, - GetOriginsForTypeCallback callback) override; - void GetOriginsForHost(blink::mojom::StorageType type, - const std::string& host, - GetOriginsForHostCallback callback) override; - void DeleteOriginData(const url::Origin& origin, - blink::mojom::StorageType type, - DeleteOriginDataCallback callback) override; + void GetStorageKeyUsage(const blink::StorageKey& storage_key, + blink::mojom::StorageType type, + GetStorageKeyUsageCallback callback) override; + void GetStorageKeysForType(blink::mojom::StorageType type, + GetStorageKeysForTypeCallback callback) override; + void GetStorageKeysForHost(blink::mojom::StorageType type, + const std::string& host, + GetStorageKeysForHostCallback callback) override; + void DeleteStorageKeyData(const blink::StorageKey& storage_key, + blink::mojom::StorageType type, + DeleteStorageKeyDataCallback callback) override; void PerformStorageCleanup(blink::mojom::StorageType type, PerformStorageCleanupCallback callback) override; - private: - ~FileSystemQuotaClient() override; + // Converts FileSystemType `type` to/from the StorageType `storage_type` that + // is used for the unified quota system. + // (Basically this naively maps TEMPORARY storage type to TEMPORARY filesystem + // type, PERSISTENT storage type to PERSISTENT filesystem type and vice + // versa.) + static FileSystemType QuotaStorageTypeToFileSystemType( + blink::mojom::StorageType storage_type); + private: base::SequencedTaskRunner* file_task_runner() const; - scoped_refptr<FileSystemContext> file_system_context_; + SEQUENCE_CHECKER(sequence_checker_); - DISALLOW_COPY_AND_ASSIGN(FileSystemQuotaClient); + // Raw pointer usage is safe because `file_system_context_` owns this. + // + // The FileSystemQuotaClient implementation mints scoped_refptrs from this + // raw pointer in order to ensure that the FileSystemContext remains alive + // while tasks are posted to the FileSystemContext's file sequence. + // + // So, it would be tempting to use scoped_refptr<FileSystemContext> here. + // However, using scoped_refptr here creates a cycle, because + // `file_system_context_` owns this. We could break the cycle in + // FileSystemContext::Shutdown(), but then we would have to ensure that + // Shutdown() is called by all FileSystemContext users. + FileSystemContext* const file_system_context_ + GUARDED_BY_CONTEXT(sequence_checker_); }; } // namespace storage diff --git a/chromium/storage/browser/file_system/file_system_quota_client_unittest.cc b/chromium/storage/browser/file_system/file_system_quota_client_unittest.cc index dcba590fb00..cb8bdfd5088 100644 --- a/chromium/storage/browser/file_system/file_system_quota_client_unittest.cc +++ b/chromium/storage/browser/file_system/file_system_quota_client_unittest.cc @@ -8,27 +8,32 @@ #include <vector> #include "base/bind.h" +#include "base/cxx17_backports.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/macros.h" #include "base/run_loop.h" -#include "base/stl_util.h" #include "base/test/task_environment.h" +#include "components/services/storage/public/mojom/quota_client.mojom.h" #include "storage/browser/file_system/file_system_context.h" #include "storage/browser/file_system/file_system_quota_client.h" #include "storage/browser/file_system/file_system_usage_cache.h" +#include "storage/browser/file_system/file_system_util.h" #include "storage/browser/file_system/obfuscated_file_util.h" +#include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/test/async_file_test_helper.h" #include "storage/browser/test/test_file_system_context.h" #include "storage/common/file_system/file_system_types.h" #include "storage/common/file_system/file_system_util.h" #include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" #include "url/gurl.h" #include "url/origin.h" -using blink::mojom::StorageType; +using ::blink::StorageKey; +using ::blink::mojom::StorageType; namespace storage { namespace { @@ -50,8 +55,8 @@ class FileSystemQuotaClientTest : public testing::Test { void SetUp() override { ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); - file_system_context_ = - CreateFileSystemContextForTesting(nullptr, data_dir_.GetPath()); + file_system_context_ = CreateFileSystemContextForTesting( + /*quota_manager_proxy=*/nullptr, data_dir_.GetPath()); } struct TestFile { @@ -59,71 +64,71 @@ class FileSystemQuotaClientTest : public testing::Test { const char* name; int64_t size; const char* origin_url; - StorageType type; + FileSystemType type; }; protected: - scoped_refptr<FileSystemQuotaClient> NewQuotaClient() { - return base::MakeRefCounted<FileSystemQuotaClient>( - file_system_context_.get()); + storage::FileSystemContext* GetFileSystemContext() { + return file_system_context_.get(); } - void GetOriginUsageAsync(FileSystemQuotaClient* quota_client, - const std::string& origin_url, - StorageType type) { - quota_client->GetOriginUsage( - url::Origin::Create(GURL(origin_url)), type, + void GetStorageKeyUsageAsync(storage::mojom::QuotaClient& quota_client, + const std::string& origin_url, + StorageType type) { + quota_client.GetStorageKeyUsage( + StorageKey::CreateFromStringForTesting(origin_url), type, base::BindOnce(&FileSystemQuotaClientTest::OnGetUsage, weak_factory_.GetWeakPtr())); } - int64_t GetOriginUsage(FileSystemQuotaClient* quota_client, - const std::string& origin_url, - StorageType type) { - GetOriginUsageAsync(quota_client, origin_url, type); + int64_t GetStorageKeyUsage(storage::mojom::QuotaClient& quota_client, + const std::string& origin_url, + StorageType type) { + GetStorageKeyUsageAsync(quota_client, origin_url, type); base::RunLoop().RunUntilIdle(); return usage_; } - const std::vector<url::Origin>& GetOriginsForType( - FileSystemQuotaClient* quota_client, + const std::vector<StorageKey>& GetStorageKeysForType( + storage::mojom::QuotaClient& quota_client, StorageType type) { - origins_.clear(); - quota_client->GetOriginsForType( - type, base::BindOnce(&FileSystemQuotaClientTest::OnGetOrigins, + storage_keys_.clear(); + quota_client.GetStorageKeysForType( + type, base::BindOnce(&FileSystemQuotaClientTest::OnGetStorageKeys, weak_factory_.GetWeakPtr())); base::RunLoop().RunUntilIdle(); - return origins_; + return storage_keys_; } - const std::vector<url::Origin>& GetOriginsForHost( - FileSystemQuotaClient* quota_client, + const std::vector<StorageKey>& GetStorageKeysForHost( + storage::mojom::QuotaClient& quota_client, StorageType type, const std::string& host) { - origins_.clear(); - quota_client->GetOriginsForHost( + storage_keys_.clear(); + quota_client.GetStorageKeysForHost( type, host, - base::BindOnce(&FileSystemQuotaClientTest::OnGetOrigins, + base::BindOnce(&FileSystemQuotaClientTest::OnGetStorageKeys, weak_factory_.GetWeakPtr())); base::RunLoop().RunUntilIdle(); - return origins_; + return storage_keys_; } - void RunAdditionalOriginUsageTask(FileSystemQuotaClient* quota_client, - const std::string& origin_url, - StorageType type) { - quota_client->GetOriginUsage( - url::Origin::Create(GURL(origin_url)), type, + void RunAdditionalStorageKeyUsageTask( + storage::mojom::QuotaClient& quota_client, + const std::string& origin_url, + StorageType type) { + quota_client.GetStorageKeyUsage( + StorageKey::CreateFromStringForTesting(origin_url), type, base::BindOnce(&FileSystemQuotaClientTest::OnGetAdditionalUsage, weak_factory_.GetWeakPtr())); } bool CreateFileSystemDirectory(const base::FilePath& file_path, const std::string& origin_url, - StorageType storage_type) { - FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type); + FileSystemType type) { FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL( - url::Origin::Create(GURL(origin_url)), type, file_path); + blink::StorageKey::CreateFromStringForTesting(origin_url), type, + file_path); base::File::Error result = AsyncFileTestHelper::CreateDirectory(file_system_context_.get(), url); @@ -133,13 +138,13 @@ class FileSystemQuotaClientTest : public testing::Test { bool CreateFileSystemFile(const base::FilePath& file_path, int64_t file_size, const std::string& origin_url, - StorageType storage_type) { + FileSystemType type) { if (file_path.empty()) return false; - FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type); FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL( - url::Origin::Create(GURL(origin_url)), type, file_path); + blink::StorageKey::CreateFromStringForTesting(origin_url), type, + file_path); base::File::Error result = AsyncFileTestHelper::CreateFile(file_system_context_.get(), url); @@ -151,26 +156,26 @@ class FileSystemQuotaClientTest : public testing::Test { return result == base::File::FILE_OK; } - void InitializeOriginFiles(FileSystemQuotaClient* quota_client, - const TestFile* files, - int num_files) { - for (int i = 0; i < num_files; i++) { - base::FilePath path = base::FilePath().AppendASCII(files[i].name); - if (files[i].isDirectory) { - ASSERT_TRUE(CreateFileSystemDirectory(path, files[i].origin_url, - files[i].type)); + void InitializeOriginFiles(storage::mojom::QuotaClient& quota_client, + const std::vector<TestFile>& files) { + for (const TestFile& file : files) { + base::FilePath path = base::FilePath().AppendASCII(file.name); + if (file.isDirectory) { + ASSERT_TRUE( + CreateFileSystemDirectory(path, file.origin_url, file.type)); if (path.empty()) { // Create the usage cache. // HACK--we always create the root [an empty path] first. If we // create it later, this will fail due to a quota mismatch. If we // call this before we create the root, it succeeds, but hasn't // actually created the cache. - ASSERT_EQ(0, GetOriginUsage(quota_client, files[i].origin_url, - files[i].type)); + ASSERT_EQ(0, GetStorageKeyUsage( + quota_client, file.origin_url, + FileSystemTypeToQuotaStorageType(file.type))); } } else { - ASSERT_TRUE(CreateFileSystemFile(path, files[i].size, - files[i].origin_url, files[i].type)); + ASSERT_TRUE( + CreateFileSystemFile(path, file.size, file.origin_url, file.type)); } } } @@ -179,15 +184,14 @@ class FileSystemQuotaClientTest : public testing::Test { // directory before adding a file or directory to it, so that we can just // count the basename of each addition. A recursive creation of a path, which // created more than one directory in a single shot, would break this. - int64_t ComputeFilePathsCostForOriginAndType(const TestFile* files, - int num_files, - const std::string& origin_url, - StorageType type) { + int64_t ComputeFilePathsCostForOriginAndType( + const base::span<const TestFile> files, + const std::string& origin_url, + FileSystemType type) { int64_t file_paths_cost = 0; - for (int i = 0; i < num_files; i++) { - if (files[i].type == type && - GURL(files[i].origin_url) == GURL(origin_url)) { - base::FilePath path = base::FilePath().AppendASCII(files[i].name); + for (const TestFile& file : files) { + if (file.type == type && GURL(file.origin_url) == GURL(origin_url)) { + base::FilePath path = base::FilePath().AppendASCII(file.name); if (!path.empty()) { file_paths_cost += ObfuscatedFileUtil::ComputeFilePathCost(path); } @@ -196,13 +200,13 @@ class FileSystemQuotaClientTest : public testing::Test { return file_paths_cost; } - void DeleteOriginData(FileSystemQuotaClient* quota_client, - const std::string& origin, - StorageType type) { + void DeleteStorageKeyData(FileSystemQuotaClient* quota_client, + const std::string& origin, + StorageType type) { deletion_status_ = blink::mojom::QuotaStatusCode::kUnknown; - quota_client->DeleteOriginData( - url::Origin::Create(GURL(origin)), type, - base::BindOnce(&FileSystemQuotaClientTest::OnDeleteOrigin, + quota_client->DeleteStorageKeyData( + StorageKey::CreateFromStringForTesting(origin), type, + base::BindOnce(&FileSystemQuotaClientTest::OnDeleteStorageKey, weak_factory_.GetWeakPtr())); } @@ -216,15 +220,15 @@ class FileSystemQuotaClientTest : public testing::Test { private: void OnGetUsage(int64_t usage) { usage_ = usage; } - void OnGetOrigins(const std::vector<url::Origin>& origins) { - origins_ = origins; + void OnGetStorageKeys(const std::vector<StorageKey>& storage_keys) { + storage_keys_ = storage_keys; } void OnGetAdditionalUsage(int64_t usage_unused) { ++additional_callback_count_; } - void OnDeleteOrigin(blink::mojom::QuotaStatusCode status) { + void OnDeleteStorageKey(blink::mojom::QuotaStatusCode status) { deletion_status_ = status; } @@ -233,315 +237,302 @@ class FileSystemQuotaClientTest : public testing::Test { scoped_refptr<FileSystemContext> file_system_context_; int64_t usage_ = 0; int additional_callback_count_ = 0; - std::vector<url::Origin> origins_; + std::vector<StorageKey> storage_keys_; blink::mojom::QuotaStatusCode deletion_status_ = blink::mojom::QuotaStatusCode::kUnknown; base::WeakPtrFactory<FileSystemQuotaClientTest> weak_factory_{this}; }; TEST_F(FileSystemQuotaClientTest, NoFileSystemTest) { - auto quota_client = NewQuotaClient(); + FileSystemQuotaClient quota_client(GetFileSystemContext()); - EXPECT_EQ(0, GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary)); + EXPECT_EQ(0, GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary)); } TEST_F(FileSystemQuotaClientTest, NoFileTest) { - auto quota_client = NewQuotaClient(); - const TestFile kFiles[] = { - {true, "", 0, kDummyURL1, kTemporary}, - }; - InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles)); + FileSystemQuotaClient quota_client(GetFileSystemContext()); + + InitializeOriginFiles(quota_client, + {{true, "", 0, kDummyURL1, kFileSystemTypeTemporary}}); for (int i = 0; i < 2; i++) { - EXPECT_EQ(0, GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary)); + EXPECT_EQ(0, GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary)); } } TEST_F(FileSystemQuotaClientTest, OneFileTest) { - auto quota_client = NewQuotaClient(); - const TestFile kFiles[] = { - {true, "", 0, kDummyURL1, kTemporary}, - {false, "foo", 4921, kDummyURL1, kTemporary}, + FileSystemQuotaClient quota_client(GetFileSystemContext()); + const std::vector<TestFile> kFiles = { + {true, "", 0, kDummyURL1, kFileSystemTypeTemporary}, + {false, "foo", 4921, kDummyURL1, kFileSystemTypeTemporary}, }; - InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles)); + InitializeOriginFiles(quota_client, kFiles); const int64_t file_paths_cost = ComputeFilePathsCostForOriginAndType( - kFiles, base::size(kFiles), kDummyURL1, kTemporary); + kFiles, kDummyURL1, kFileSystemTypeTemporary); for (int i = 0; i < 2; i++) { EXPECT_EQ(4921 + file_paths_cost, - GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary)); + GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary)); } } TEST_F(FileSystemQuotaClientTest, TwoFilesTest) { - auto quota_client = NewQuotaClient(); - const TestFile kFiles[] = { - {true, "", 0, kDummyURL1, kTemporary}, - {false, "foo", 10310, kDummyURL1, kTemporary}, - {false, "bar", 41, kDummyURL1, kTemporary}, + FileSystemQuotaClient quota_client(GetFileSystemContext()); + const std::vector<TestFile> kFiles = { + {true, "", 0, kDummyURL1, kFileSystemTypeTemporary}, + {false, "foo", 10310, kDummyURL1, kFileSystemTypeTemporary}, + {false, "bar", 41, kDummyURL1, kFileSystemTypeTemporary}, }; - InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles)); + InitializeOriginFiles(quota_client, kFiles); const int64_t file_paths_cost = ComputeFilePathsCostForOriginAndType( - kFiles, base::size(kFiles), kDummyURL1, kTemporary); + kFiles, kDummyURL1, kFileSystemTypeTemporary); for (int i = 0; i < 2; i++) { EXPECT_EQ(10310 + 41 + file_paths_cost, - GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary)); + GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary)); } } TEST_F(FileSystemQuotaClientTest, EmptyFilesTest) { - auto quota_client = NewQuotaClient(); - const TestFile kFiles[] = { - {true, "", 0, kDummyURL1, kTemporary}, - {false, "foo", 0, kDummyURL1, kTemporary}, - {false, "bar", 0, kDummyURL1, kTemporary}, - {false, "baz", 0, kDummyURL1, kTemporary}, + FileSystemQuotaClient quota_client(GetFileSystemContext()); + const std::vector<TestFile> kFiles = { + {true, "", 0, kDummyURL1, kFileSystemTypeTemporary}, + {false, "foo", 0, kDummyURL1, kFileSystemTypeTemporary}, + {false, "bar", 0, kDummyURL1, kFileSystemTypeTemporary}, + {false, "baz", 0, kDummyURL1, kFileSystemTypeTemporary}, }; - InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles)); + InitializeOriginFiles(quota_client, kFiles); const int64_t file_paths_cost = ComputeFilePathsCostForOriginAndType( - kFiles, base::size(kFiles), kDummyURL1, kTemporary); + kFiles, kDummyURL1, kFileSystemTypeTemporary); for (int i = 0; i < 2; i++) { EXPECT_EQ(file_paths_cost, - GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary)); + GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary)); } } TEST_F(FileSystemQuotaClientTest, SubDirectoryTest) { - auto quota_client = NewQuotaClient(); - const TestFile kFiles[] = { - {true, "", 0, kDummyURL1, kTemporary}, - {true, "dirtest", 0, kDummyURL1, kTemporary}, - {false, "dirtest/foo", 11921, kDummyURL1, kTemporary}, - {false, "bar", 4814, kDummyURL1, kTemporary}, + FileSystemQuotaClient quota_client(GetFileSystemContext()); + const std::vector<TestFile> kFiles = { + {true, "", 0, kDummyURL1, kFileSystemTypeTemporary}, + {true, "dirtest", 0, kDummyURL1, kFileSystemTypeTemporary}, + {false, "dirtest/foo", 11921, kDummyURL1, kFileSystemTypeTemporary}, + {false, "bar", 4814, kDummyURL1, kFileSystemTypeTemporary}, }; - InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles)); + InitializeOriginFiles(quota_client, kFiles); const int64_t file_paths_cost = ComputeFilePathsCostForOriginAndType( - kFiles, base::size(kFiles), kDummyURL1, kTemporary); + kFiles, kDummyURL1, kFileSystemTypeTemporary); for (int i = 0; i < 2; i++) { EXPECT_EQ(11921 + 4814 + file_paths_cost, - GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary)); + GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary)); } } TEST_F(FileSystemQuotaClientTest, MultiTypeTest) { - auto quota_client = NewQuotaClient(); - const TestFile kFiles[] = { - {true, "", 0, kDummyURL1, kTemporary}, - {true, "dirtest", 0, kDummyURL1, kTemporary}, - {false, "dirtest/foo", 133, kDummyURL1, kTemporary}, - {false, "bar", 14, kDummyURL1, kTemporary}, - {true, "", 0, kDummyURL1, kPersistent}, - {true, "dirtest", 0, kDummyURL1, kPersistent}, - {false, "dirtest/foo", 193, kDummyURL1, kPersistent}, - {false, "bar", 9, kDummyURL1, kPersistent}, + FileSystemQuotaClient quota_client(GetFileSystemContext()); + const std::vector<TestFile> kFiles = { + {true, "", 0, kDummyURL1, kFileSystemTypeTemporary}, + {true, "dirtest", 0, kDummyURL1, kFileSystemTypeTemporary}, + {false, "dirtest/foo", 133, kDummyURL1, kFileSystemTypeTemporary}, + {false, "bar", 14, kDummyURL1, kFileSystemTypeTemporary}, + {true, "", 0, kDummyURL1, kFileSystemTypePersistent}, + {true, "dirtest", 0, kDummyURL1, kFileSystemTypePersistent}, + {false, "dirtest/foo", 193, kDummyURL1, kFileSystemTypePersistent}, + {false, "bar", 9, kDummyURL1, kFileSystemTypePersistent}, }; - InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles)); + InitializeOriginFiles(quota_client, kFiles); const int64_t file_paths_cost_temporary = - ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles), - kDummyURL1, kTemporary); + ComputeFilePathsCostForOriginAndType(kFiles, kDummyURL1, + kFileSystemTypeTemporary); const int64_t file_paths_cost_persistent = - ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles), - kDummyURL1, kTemporary); + ComputeFilePathsCostForOriginAndType(kFiles, kDummyURL1, + kFileSystemTypePersistent); for (int i = 0; i < 2; i++) { EXPECT_EQ(133 + 14 + file_paths_cost_temporary, - GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary)); + GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary)); EXPECT_EQ(193 + 9 + file_paths_cost_persistent, - GetOriginUsage(quota_client.get(), kDummyURL1, kPersistent)); + GetStorageKeyUsage(quota_client, kDummyURL1, kPersistent)); } } TEST_F(FileSystemQuotaClientTest, MultiDomainTest) { - auto quota_client = NewQuotaClient(); - const TestFile kFiles[] = { - {true, "", 0, kDummyURL1, kTemporary}, - {true, "dir1", 0, kDummyURL1, kTemporary}, - {false, "dir1/foo", 1331, kDummyURL1, kTemporary}, - {false, "bar", 134, kDummyURL1, kTemporary}, - {true, "", 0, kDummyURL1, kPersistent}, - {true, "dir2", 0, kDummyURL1, kPersistent}, - {false, "dir2/foo", 1903, kDummyURL1, kPersistent}, - {false, "bar", 19, kDummyURL1, kPersistent}, - {true, "", 0, kDummyURL2, kTemporary}, - {true, "dom", 0, kDummyURL2, kTemporary}, - {false, "dom/fan", 1319, kDummyURL2, kTemporary}, - {false, "bar", 113, kDummyURL2, kTemporary}, - {true, "", 0, kDummyURL2, kPersistent}, - {true, "dom", 0, kDummyURL2, kPersistent}, - {false, "dom/fan", 2013, kDummyURL2, kPersistent}, - {false, "baz", 18, kDummyURL2, kPersistent}, + FileSystemQuotaClient quota_client(GetFileSystemContext()); + const std::vector<TestFile> kFiles = { + {true, "", 0, kDummyURL1, kFileSystemTypeTemporary}, + {true, "dir1", 0, kDummyURL1, kFileSystemTypeTemporary}, + {false, "dir1/foo", 1331, kDummyURL1, kFileSystemTypeTemporary}, + {false, "bar", 134, kDummyURL1, kFileSystemTypeTemporary}, + {true, "", 0, kDummyURL1, kFileSystemTypePersistent}, + {true, "dir2", 0, kDummyURL1, kFileSystemTypePersistent}, + {false, "dir2/foo", 1903, kDummyURL1, kFileSystemTypePersistent}, + {false, "bar", 19, kDummyURL1, kFileSystemTypePersistent}, + {true, "", 0, kDummyURL2, kFileSystemTypeTemporary}, + {true, "dom", 0, kDummyURL2, kFileSystemTypeTemporary}, + {false, "dom/fan", 1319, kDummyURL2, kFileSystemTypeTemporary}, + {false, "bar", 113, kDummyURL2, kFileSystemTypeTemporary}, + {true, "", 0, kDummyURL2, kFileSystemTypePersistent}, + {true, "dom", 0, kDummyURL2, kFileSystemTypePersistent}, + {false, "dom/fan", 2013, kDummyURL2, kFileSystemTypePersistent}, + {false, "baz", 18, kDummyURL2, kFileSystemTypePersistent}, }; - InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles)); + InitializeOriginFiles(quota_client, kFiles); const int64_t file_paths_cost_temporary1 = - ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles), - kDummyURL1, kTemporary); + ComputeFilePathsCostForOriginAndType(kFiles, kDummyURL1, + kFileSystemTypeTemporary); const int64_t file_paths_cost_persistent1 = - ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles), - kDummyURL1, kPersistent); + ComputeFilePathsCostForOriginAndType(kFiles, kDummyURL1, + kFileSystemTypePersistent); const int64_t file_paths_cost_temporary2 = - ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles), - kDummyURL2, kTemporary); + ComputeFilePathsCostForOriginAndType(kFiles, kDummyURL2, + kFileSystemTypeTemporary); const int64_t file_paths_cost_persistent2 = - ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles), - kDummyURL2, kPersistent); + ComputeFilePathsCostForOriginAndType(kFiles, kDummyURL2, + kFileSystemTypePersistent); for (int i = 0; i < 2; i++) { EXPECT_EQ(1331 + 134 + file_paths_cost_temporary1, - GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary)); + GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary)); EXPECT_EQ(1903 + 19 + file_paths_cost_persistent1, - GetOriginUsage(quota_client.get(), kDummyURL1, kPersistent)); + GetStorageKeyUsage(quota_client, kDummyURL1, kPersistent)); EXPECT_EQ(1319 + 113 + file_paths_cost_temporary2, - GetOriginUsage(quota_client.get(), kDummyURL2, kTemporary)); + GetStorageKeyUsage(quota_client, kDummyURL2, kTemporary)); EXPECT_EQ(2013 + 18 + file_paths_cost_persistent2, - GetOriginUsage(quota_client.get(), kDummyURL2, kPersistent)); + GetStorageKeyUsage(quota_client, kDummyURL2, kPersistent)); } } TEST_F(FileSystemQuotaClientTest, GetUsage_MultipleTasks) { - auto quota_client = NewQuotaClient(); - const TestFile kFiles[] = { - {true, "", 0, kDummyURL1, kTemporary}, - {false, "foo", 11, kDummyURL1, kTemporary}, - {false, "bar", 22, kDummyURL1, kTemporary}, + FileSystemQuotaClient quota_client(GetFileSystemContext()); + const std::vector<TestFile> kFiles = { + {true, "", 0, kDummyURL1, kFileSystemTypeTemporary}, + {false, "foo", 11, kDummyURL1, kFileSystemTypeTemporary}, + {false, "bar", 22, kDummyURL1, kFileSystemTypeTemporary}, }; - InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles)); + InitializeOriginFiles(quota_client, kFiles); const int64_t file_paths_cost = ComputeFilePathsCostForOriginAndType( - kFiles, base::size(kFiles), kDummyURL1, kTemporary); + kFiles, kDummyURL1, kFileSystemTypeTemporary); // Dispatching three GetUsage tasks. set_additional_callback_count(0); - GetOriginUsageAsync(quota_client.get(), kDummyURL1, kTemporary); - RunAdditionalOriginUsageTask(quota_client.get(), kDummyURL1, kTemporary); - RunAdditionalOriginUsageTask(quota_client.get(), kDummyURL1, kTemporary); + GetStorageKeyUsageAsync(quota_client, kDummyURL1, kTemporary); + RunAdditionalStorageKeyUsageTask(quota_client, kDummyURL1, kTemporary); + RunAdditionalStorageKeyUsageTask(quota_client, kDummyURL1, kTemporary); base::RunLoop().RunUntilIdle(); EXPECT_EQ(11 + 22 + file_paths_cost, usage()); EXPECT_EQ(2, additional_callback_count()); // Once more, in a different order. set_additional_callback_count(0); - RunAdditionalOriginUsageTask(quota_client.get(), kDummyURL1, kTemporary); - GetOriginUsageAsync(quota_client.get(), kDummyURL1, kTemporary); - RunAdditionalOriginUsageTask(quota_client.get(), kDummyURL1, kTemporary); + RunAdditionalStorageKeyUsageTask(quota_client, kDummyURL1, kTemporary); + GetStorageKeyUsageAsync(quota_client, kDummyURL1, kTemporary); + RunAdditionalStorageKeyUsageTask(quota_client, kDummyURL1, kTemporary); base::RunLoop().RunUntilIdle(); EXPECT_EQ(11 + 22 + file_paths_cost, usage()); EXPECT_EQ(2, additional_callback_count()); } -TEST_F(FileSystemQuotaClientTest, GetOriginsForType) { - auto quota_client = NewQuotaClient(); - const TestFile kFiles[] = { - {true, "", 0, kDummyURL1, kTemporary}, - {true, "", 0, kDummyURL2, kTemporary}, - {true, "", 0, kDummyURL3, kPersistent}, - }; - InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles)); - - std::vector<url::Origin> origins = - GetOriginsForType(quota_client.get(), kTemporary); - EXPECT_EQ(2U, origins.size()); - EXPECT_THAT(origins, - testing::Contains(url::Origin::Create(GURL(kDummyURL1)))); - EXPECT_THAT(origins, - testing::Contains(url::Origin::Create(GURL(kDummyURL2)))); - EXPECT_THAT( - origins, - testing::Not(testing::Contains(url::Origin::Create(GURL(kDummyURL3))))); +TEST_F(FileSystemQuotaClientTest, GetStorageKeysForType) { + FileSystemQuotaClient quota_client(GetFileSystemContext()); + InitializeOriginFiles( + quota_client, { + {true, "", 0, kDummyURL1, kFileSystemTypeTemporary}, + {true, "", 0, kDummyURL2, kFileSystemTypeTemporary}, + {true, "", 0, kDummyURL3, kFileSystemTypePersistent}, + }); + + EXPECT_THAT(GetStorageKeysForType(quota_client, kTemporary), + testing::UnorderedElementsAre( + StorageKey::CreateFromStringForTesting(kDummyURL1), + StorageKey::CreateFromStringForTesting(kDummyURL2))); } -TEST_F(FileSystemQuotaClientTest, GetOriginsForHost) { - auto quota_client = NewQuotaClient(); +TEST_F(FileSystemQuotaClientTest, GetStorageKeysForHost) { + FileSystemQuotaClient quota_client(GetFileSystemContext()); const char* kURL1 = "http://foo.com/"; const char* kURL2 = "https://foo.com/"; const char* kURL3 = "http://foo.com:1/"; const char* kURL4 = "http://foo2.com/"; const char* kURL5 = "http://foo.com:2/"; - const TestFile kFiles[] = { - {true, "", 0, kURL1, kTemporary}, {true, "", 0, kURL2, kTemporary}, - {true, "", 0, kURL3, kTemporary}, {true, "", 0, kURL4, kTemporary}, - {true, "", 0, kURL5, kPersistent}, - }; - InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles)); - - std::vector<url::Origin> origins = - GetOriginsForHost(quota_client.get(), kTemporary, "foo.com"); - EXPECT_EQ(3U, origins.size()); - EXPECT_THAT(origins, testing::Contains(url::Origin::Create(GURL(kURL1)))); - EXPECT_THAT(origins, testing::Contains(url::Origin::Create(GURL(kURL2)))); - EXPECT_THAT(origins, testing::Contains(url::Origin::Create(GURL(kURL3)))); - EXPECT_THAT(origins, testing::Not(testing::Contains(url::Origin::Create( - GURL(kURL4))))); // Different host. - EXPECT_THAT(origins, testing::Not(testing::Contains(url::Origin::Create( - GURL(kURL5))))); // Different type. + InitializeOriginFiles(quota_client, + { + {true, "", 0, kURL1, kFileSystemTypeTemporary}, + {true, "", 0, kURL2, kFileSystemTypeTemporary}, + {true, "", 0, kURL3, kFileSystemTypeTemporary}, + {true, "", 0, kURL4, kFileSystemTypeTemporary}, + {true, "", 0, kURL5, kFileSystemTypePersistent}, + }); + + EXPECT_THAT(GetStorageKeysForHost(quota_client, kTemporary, "foo.com"), + testing::UnorderedElementsAre( + StorageKey::CreateFromStringForTesting(kURL1), + StorageKey::CreateFromStringForTesting(kURL2), + StorageKey::CreateFromStringForTesting(kURL3))); } TEST_F(FileSystemQuotaClientTest, DeleteOriginTest) { - auto quota_client = NewQuotaClient(); - const TestFile kFiles[] = { - {true, "", 0, "http://foo.com/", kTemporary}, - {false, "a", 1, "http://foo.com/", kTemporary}, - {true, "", 0, "https://foo.com/", kTemporary}, - {false, "b", 2, "https://foo.com/", kTemporary}, - {true, "", 0, "http://foo.com/", kPersistent}, - {false, "c", 4, "http://foo.com/", kPersistent}, - {true, "", 0, "http://bar.com/", kTemporary}, - {false, "d", 8, "http://bar.com/", kTemporary}, - {true, "", 0, "http://bar.com/", kPersistent}, - {false, "e", 16, "http://bar.com/", kPersistent}, - {true, "", 0, "https://bar.com/", kPersistent}, - {false, "f", 32, "https://bar.com/", kPersistent}, - {true, "", 0, "https://bar.com/", kTemporary}, - {false, "g", 64, "https://bar.com/", kTemporary}, + FileSystemQuotaClient quota_client(GetFileSystemContext()); + const std::vector<TestFile> kFiles = { + {true, "", 0, "http://foo.com/", kFileSystemTypeTemporary}, + {false, "a", 1, "http://foo.com/", kFileSystemTypeTemporary}, + {true, "", 0, "https://foo.com/", kFileSystemTypeTemporary}, + {false, "b", 2, "https://foo.com/", kFileSystemTypeTemporary}, + {true, "", 0, "http://foo.com/", kFileSystemTypePersistent}, + {false, "c", 4, "http://foo.com/", kFileSystemTypePersistent}, + {true, "", 0, "http://bar.com/", kFileSystemTypeTemporary}, + {false, "d", 8, "http://bar.com/", kFileSystemTypeTemporary}, + {true, "", 0, "http://bar.com/", kFileSystemTypePersistent}, + {false, "e", 16, "http://bar.com/", kFileSystemTypePersistent}, + {true, "", 0, "https://bar.com/", kFileSystemTypePersistent}, + {false, "f", 32, "https://bar.com/", kFileSystemTypePersistent}, + {true, "", 0, "https://bar.com/", kFileSystemTypeTemporary}, + {false, "g", 64, "https://bar.com/", kFileSystemTypeTemporary}, }; - InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles)); + InitializeOriginFiles(quota_client, kFiles); const int64_t file_paths_cost_temporary_foo_https = - ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles), - "https://foo.com/", kTemporary); + ComputeFilePathsCostForOriginAndType(kFiles, "https://foo.com/", + kFileSystemTypeTemporary); const int64_t file_paths_cost_persistent_foo = - ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles), - "http://foo.com/", kPersistent); + ComputeFilePathsCostForOriginAndType(kFiles, "http://foo.com/", + kFileSystemTypePersistent); const int64_t file_paths_cost_temporary_bar = - ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles), - "http://bar.com/", kTemporary); + ComputeFilePathsCostForOriginAndType(kFiles, "http://bar.com/", + kFileSystemTypeTemporary); const int64_t file_paths_cost_temporary_bar_https = - ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles), - "https://bar.com/", kTemporary); + ComputeFilePathsCostForOriginAndType(kFiles, "https://bar.com/", + kFileSystemTypeTemporary); const int64_t file_paths_cost_persistent_bar_https = - ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles), - "https://bar.com/", kPersistent); + ComputeFilePathsCostForOriginAndType(kFiles, "https://bar.com/", + kFileSystemTypePersistent); - DeleteOriginData(quota_client.get(), "http://foo.com/", kTemporary); + DeleteStorageKeyData("a_client, "http://foo.com/", kTemporary); base::RunLoop().RunUntilIdle(); EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, status()); - DeleteOriginData(quota_client.get(), "http://bar.com/", kPersistent); + DeleteStorageKeyData("a_client, "http://bar.com/", kPersistent); base::RunLoop().RunUntilIdle(); EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, status()); - DeleteOriginData(quota_client.get(), "http://buz.com/", kTemporary); + DeleteStorageKeyData("a_client, "http://buz.com/", kTemporary); base::RunLoop().RunUntilIdle(); EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, status()); + EXPECT_EQ(0, GetStorageKeyUsage(quota_client, "http://foo.com/", kTemporary)); EXPECT_EQ(0, - GetOriginUsage(quota_client.get(), "http://foo.com/", kTemporary)); - EXPECT_EQ(0, - GetOriginUsage(quota_client.get(), "http://bar.com/", kPersistent)); - EXPECT_EQ(0, - GetOriginUsage(quota_client.get(), "http://buz.com/", kTemporary)); + GetStorageKeyUsage(quota_client, "http://bar.com/", kPersistent)); + EXPECT_EQ(0, GetStorageKeyUsage(quota_client, "http://buz.com/", kTemporary)); EXPECT_EQ(2 + file_paths_cost_temporary_foo_https, - GetOriginUsage(quota_client.get(), "https://foo.com/", kTemporary)); + GetStorageKeyUsage(quota_client, "https://foo.com/", kTemporary)); EXPECT_EQ(4 + file_paths_cost_persistent_foo, - GetOriginUsage(quota_client.get(), "http://foo.com/", kPersistent)); + GetStorageKeyUsage(quota_client, "http://foo.com/", kPersistent)); EXPECT_EQ(8 + file_paths_cost_temporary_bar, - GetOriginUsage(quota_client.get(), "http://bar.com/", kTemporary)); - EXPECT_EQ( - 32 + file_paths_cost_persistent_bar_https, - GetOriginUsage(quota_client.get(), "https://bar.com/", kPersistent)); + GetStorageKeyUsage(quota_client, "http://bar.com/", kTemporary)); + EXPECT_EQ(32 + file_paths_cost_persistent_bar_https, + GetStorageKeyUsage(quota_client, "https://bar.com/", kPersistent)); EXPECT_EQ(64 + file_paths_cost_temporary_bar_https, - GetOriginUsage(quota_client.get(), "https://bar.com/", kTemporary)); + GetStorageKeyUsage(quota_client, "https://bar.com/", kTemporary)); } } // namespace storage diff --git a/chromium/storage/browser/file_system/file_system_url.cc b/chromium/storage/browser/file_system/file_system_url.cc index 3aac33f3ad0..a7eb2331c5c 100644 --- a/chromium/storage/browser/file_system/file_system_url.cc +++ b/chromium/storage/browser/file_system/file_system_url.cc @@ -10,6 +10,8 @@ #include "base/strings/string_util.h" #include "net/base/escape.h" #include "storage/common/file_system/file_system_util.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" +#include "url/origin.h" namespace storage { @@ -22,27 +24,29 @@ FileSystemURL::FileSystemURL() type_(kFileSystemTypeUnknown), mount_option_(FlushPolicy::NO_FLUSH_ON_COMPLETION) {} -FileSystemURL::FileSystemURL(const FileSystemURL& other) = default; +FileSystemURL::FileSystemURL(const FileSystemURL&) = default; -FileSystemURL::FileSystemURL(FileSystemURL&& other) = default; +FileSystemURL::FileSystemURL(FileSystemURL&&) noexcept = default; -FileSystemURL& FileSystemURL::operator=(FileSystemURL&& rhs) = default; +FileSystemURL& FileSystemURL::operator=(const FileSystemURL&) = default; -FileSystemURL& FileSystemURL::operator=(const FileSystemURL& rhs) = default; +FileSystemURL& FileSystemURL::operator=(FileSystemURL&&) noexcept = default; + +FileSystemURL::~FileSystemURL() = default; // static FileSystemURL FileSystemURL::CreateForTest(const GURL& url) { - return FileSystemURL(url); + return FileSystemURL(url, blink::StorageKey(url::Origin::Create(url))); } -FileSystemURL FileSystemURL::CreateForTest(const url::Origin& origin, +FileSystemURL FileSystemURL::CreateForTest(const blink::StorageKey& storage_key, FileSystemType mount_type, const base::FilePath& virtual_path) { - return FileSystemURL(origin, mount_type, virtual_path); + return FileSystemURL(storage_key, mount_type, virtual_path); } FileSystemURL FileSystemURL::CreateForTest( - const url::Origin& origin, + const blink::StorageKey& storage_key, FileSystemType mount_type, const base::FilePath& virtual_path, const std::string& mount_filesystem_id, @@ -50,11 +54,13 @@ FileSystemURL FileSystemURL::CreateForTest( const base::FilePath& cracked_path, const std::string& filesystem_id, const FileSystemMountOption& mount_option) { - return FileSystemURL(origin, mount_type, virtual_path, mount_filesystem_id, - cracked_type, cracked_path, filesystem_id, mount_option); + return FileSystemURL(storage_key, mount_type, virtual_path, + mount_filesystem_id, cracked_type, cracked_path, + filesystem_id, mount_option); } -FileSystemURL::FileSystemURL(const GURL& url) +FileSystemURL::FileSystemURL(const GURL& url, + const blink::StorageKey& storage_key) : is_null_(false), mount_type_(kFileSystemTypeUnknown), type_(kFileSystemTypeUnknown), @@ -62,24 +68,28 @@ FileSystemURL::FileSystemURL(const GURL& url) GURL origin_url; is_valid_ = ParseFileSystemSchemeURL(url, &origin_url, &mount_type_, &virtual_path_); - origin_ = url::Origin::Create(origin_url); + if (is_valid_) { + DCHECK( + storage_key.origin().IsSameOriginWith(url::Origin::Create(origin_url))); + } + storage_key_ = storage_key; path_ = virtual_path_; type_ = mount_type_; } -FileSystemURL::FileSystemURL(const url::Origin& origin, +FileSystemURL::FileSystemURL(const blink::StorageKey& storage_key, FileSystemType mount_type, const base::FilePath& virtual_path) : is_null_(false), is_valid_(true), - origin_(origin), + storage_key_(storage_key), mount_type_(mount_type), virtual_path_(virtual_path.NormalizePathSeparators()), type_(mount_type), path_(virtual_path.NormalizePathSeparators()), mount_option_(FlushPolicy::NO_FLUSH_ON_COMPLETION) {} -FileSystemURL::FileSystemURL(const url::Origin& origin, +FileSystemURL::FileSystemURL(const blink::StorageKey& storage_key, FileSystemType mount_type, const base::FilePath& virtual_path, const std::string& mount_filesystem_id, @@ -89,7 +99,7 @@ FileSystemURL::FileSystemURL(const url::Origin& origin, const FileSystemMountOption& mount_option) : is_null_(false), is_valid_(true), - origin_(origin), + storage_key_(storage_key), mount_type_(mount_type), virtual_path_(virtual_path.NormalizePathSeparators()), mount_filesystem_id_(mount_filesystem_id), @@ -98,13 +108,12 @@ FileSystemURL::FileSystemURL(const url::Origin& origin, filesystem_id_(filesystem_id), mount_option_(mount_option) {} -FileSystemURL::~FileSystemURL() = default; - GURL FileSystemURL::ToGURL() const { if (!is_valid_) return GURL(); - std::string url = GetFileSystemRootURI(origin_.GetURL(), mount_type_).spec(); + std::string url = + GetFileSystemRootURI(storage_key_.origin().GetURL(), mount_type_).spec(); if (url.empty()) return GURL(); @@ -125,7 +134,7 @@ std::string FileSystemURL::DebugString() const { if (!is_valid_) return "invalid filesystem: URL"; std::ostringstream ss; - ss << GetFileSystemRootURI(origin_.GetURL(), mount_type_); + ss << GetFileSystemRootURI(storage_key_.origin().GetURL(), mount_type_); // filesystem_id_ will be non empty for (and only for) cracked URLs. if (!filesystem_id_.empty()) { @@ -153,7 +162,7 @@ bool FileSystemURL::operator==(const FileSystemURL& that) const { if (is_null_ && that.is_null_) { return true; } else { - return origin_ == that.origin_ && type_ == that.type_ && + return storage_key() == that.storage_key() && type_ == that.type_ && path_ == that.path_ && filesystem_id_ == that.filesystem_id_ && is_valid_ == that.is_valid_; } @@ -162,8 +171,8 @@ bool FileSystemURL::operator==(const FileSystemURL& that) const { bool FileSystemURL::Comparator::operator()(const FileSystemURL& lhs, const FileSystemURL& rhs) const { DCHECK(lhs.is_valid_ && rhs.is_valid_); - if (lhs.origin_ != rhs.origin_) - return lhs.origin_ < rhs.origin_; + if (lhs.storage_key() != rhs.storage_key()) + return lhs.storage_key() < rhs.storage_key(); if (lhs.type_ != rhs.type_) return lhs.type_ < rhs.type_; if (lhs.filesystem_id_ != rhs.filesystem_id_) diff --git a/chromium/storage/browser/file_system/file_system_url.h b/chromium/storage/browser/file_system/file_system_url.h index b88ece0efb2..e29a3306cfc 100644 --- a/chromium/storage/browser/file_system/file_system_url.h +++ b/chromium/storage/browser/file_system/file_system_url.h @@ -12,8 +12,8 @@ #include "base/files/file_path.h" #include "storage/common/file_system/file_system_mount_option.h" #include "storage/common/file_system/file_system_types.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "url/gurl.h" -#include "url/origin.h" namespace storage { @@ -79,25 +79,21 @@ namespace storage { class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemURL { public: FileSystemURL(); - FileSystemURL(const FileSystemURL& other); - // Constructs FileSystemURL with the contents of |other|, which is left in - // valid but unspecified state. - FileSystemURL(FileSystemURL&& other); - ~FileSystemURL(); - // Replaces the contents with those of |rhs|, which is left in valid but - // unspecified state. - FileSystemURL& operator=(FileSystemURL&& rhs); + FileSystemURL(const FileSystemURL&); + FileSystemURL(FileSystemURL&&) noexcept; + FileSystemURL& operator=(const FileSystemURL&); + FileSystemURL& operator=(FileSystemURL&&) noexcept; - FileSystemURL& operator=(const FileSystemURL& rhs); + ~FileSystemURL(); // Methods for creating FileSystemURL without attempting to crack them. // Should be used only in tests. static FileSystemURL CreateForTest(const GURL& url); - static FileSystemURL CreateForTest(const url::Origin& origin, + static FileSystemURL CreateForTest(const blink::StorageKey& storage_key, FileSystemType mount_type, const base::FilePath& virtual_path); - static FileSystemURL CreateForTest(const url::Origin& origin, + static FileSystemURL CreateForTest(const blink::StorageKey& storage_key, FileSystemType mount_type, const base::FilePath& virtual_path, const std::string& mount_filesystem_id, @@ -109,8 +105,11 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemURL { // Returns true if this instance represents a valid FileSystem URL. bool is_valid() const { return is_valid_; } + // Returns the storage key. See the class comment for details. + const blink::StorageKey& storage_key() const { return storage_key_; } + // Returns the origin part of this URL. See the class comment for details. - const url::Origin& origin() const { return origin_; } + const url::Origin& origin() const { return storage_key_.origin(); } // Returns the type part of this URL. See the class comment for details. FileSystemType type() const { return type_; } @@ -157,12 +156,13 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemURL { friend class ExternalMountPoints; friend class IsolatedContext; - explicit FileSystemURL(const GURL& filesystem_url); - FileSystemURL(const url::Origin& origin, + FileSystemURL(const GURL& filesystem_url, + const blink::StorageKey& storage_key); + FileSystemURL(const blink::StorageKey& storage_key, FileSystemType mount_type, const base::FilePath& virtual_path); // Creates a cracked FileSystemURL. - FileSystemURL(const url::Origin& origin, + FileSystemURL(const blink::StorageKey& storage_key, FileSystemType mount_type, const base::FilePath& virtual_path, const std::string& mount_filesystem_id, @@ -177,7 +177,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemURL { bool is_valid_; // Values parsed from the original URL. - url::Origin origin_; + blink::StorageKey storage_key_; FileSystemType mount_type_; base::FilePath virtual_path_; diff --git a/chromium/storage/browser/file_system/file_system_url_unittest.cc b/chromium/storage/browser/file_system/file_system_url_unittest.cc index 8a60e905d9c..71f21789163 100644 --- a/chromium/storage/browser/file_system/file_system_url_unittest.cc +++ b/chromium/storage/browser/file_system/file_system_url_unittest.cc @@ -8,12 +8,13 @@ #include <utility> +#include "base/cxx17_backports.h" #include "base/files/file_path.h" #include "base/macros.h" -#include "base/stl_util.h" #include "storage/common/file_system/file_system_types.h" #include "storage/common/file_system/file_system_util.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "url/gurl.h" #define FPL FILE_PATH_LITERAL @@ -182,11 +183,11 @@ TEST(FileSystemURLTest, ToGURL) { } TEST(FileSystemURLTest, DebugString) { - const GURL kOrigin("http://example.com"); const base::FilePath kPath(FPL("dir/file")); const FileSystemURL kURL1 = FileSystemURL::CreateForTest( - url::Origin::Create(kOrigin), kFileSystemTypeTemporary, kPath); + blink::StorageKey::CreateFromStringForTesting("http://example.com"), + kFileSystemTypeTemporary, kPath); EXPECT_EQ( "filesystem:http://example.com/temporary/" + NormalizedUTF8Path(kPath), kURL1.DebugString()); @@ -194,20 +195,20 @@ TEST(FileSystemURLTest, DebugString) { TEST(FileSystemURLTest, IsInSameFileSystem) { FileSystemURL url_foo_temp_a = FileSystemURL::CreateForTest( - url::Origin::Create(GURL("http://foo")), kFileSystemTypeTemporary, - base::FilePath::FromUTF8Unsafe("a")); + blink::StorageKey::CreateFromStringForTesting("http://foo"), + kFileSystemTypeTemporary, base::FilePath::FromUTF8Unsafe("a")); FileSystemURL url_foo_temp_b = FileSystemURL::CreateForTest( - url::Origin::Create(GURL("http://foo")), kFileSystemTypeTemporary, - base::FilePath::FromUTF8Unsafe("b")); + blink::StorageKey::CreateFromStringForTesting("http://foo"), + kFileSystemTypeTemporary, base::FilePath::FromUTF8Unsafe("b")); FileSystemURL url_foo_perm_a = FileSystemURL::CreateForTest( - url::Origin::Create(GURL("http://foo")), kFileSystemTypePersistent, - base::FilePath::FromUTF8Unsafe("a")); + blink::StorageKey::CreateFromStringForTesting("http://foo"), + kFileSystemTypePersistent, base::FilePath::FromUTF8Unsafe("a")); FileSystemURL url_bar_temp_a = FileSystemURL::CreateForTest( - url::Origin::Create(GURL("http://bar")), kFileSystemTypeTemporary, - base::FilePath::FromUTF8Unsafe("a")); + blink::StorageKey::CreateFromStringForTesting("http://bar"), + kFileSystemTypeTemporary, base::FilePath::FromUTF8Unsafe("a")); FileSystemURL url_bar_perm_a = FileSystemURL::CreateForTest( - url::Origin::Create(GURL("http://bar")), kFileSystemTypePersistent, - base::FilePath::FromUTF8Unsafe("a")); + blink::StorageKey::CreateFromStringForTesting("http://bar"), + kFileSystemTypePersistent, base::FilePath::FromUTF8Unsafe("a")); EXPECT_TRUE(url_foo_temp_a.IsInSameFileSystem(url_foo_temp_a)); EXPECT_TRUE(url_foo_temp_a.IsInSameFileSystem(url_foo_temp_b)); @@ -220,8 +221,8 @@ TEST(FileSystemURLTest, ValidAfterMoves) { // Move constructor. { FileSystemURL original = FileSystemURL::CreateForTest( - url::Origin::Create(GURL("http://foo")), kFileSystemTypeTemporary, - base::FilePath::FromUTF8Unsafe("a")); + blink::StorageKey::CreateFromStringForTesting("http://foo"), + kFileSystemTypeTemporary, base::FilePath::FromUTF8Unsafe("a")); EXPECT_TRUE(original.is_valid()); FileSystemURL new_url(std::move(original)); EXPECT_TRUE(new_url.is_valid()); @@ -231,8 +232,8 @@ TEST(FileSystemURLTest, ValidAfterMoves) { // Move operator. { FileSystemURL original = FileSystemURL::CreateForTest( - url::Origin::Create(GURL("http://foo")), kFileSystemTypeTemporary, - base::FilePath::FromUTF8Unsafe("a")); + blink::StorageKey::CreateFromStringForTesting("http://foo"), + kFileSystemTypeTemporary, base::FilePath::FromUTF8Unsafe("a")); EXPECT_TRUE(original.is_valid()); FileSystemURL new_url; new_url = std::move(std::move(original)); diff --git a/chromium/storage/browser/file_system/file_system_util.cc b/chromium/storage/browser/file_system/file_system_util.cc new file mode 100644 index 00000000000..95b190f68b3 --- /dev/null +++ b/chromium/storage/browser/file_system/file_system_util.cc @@ -0,0 +1,29 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "storage/browser/file_system/file_system_util.h" + +#include "storage/common/file_system/file_system_types.h" +#include "third_party/blink/public/mojom/quota/quota_types.mojom.h" + +namespace storage { + +blink::mojom::StorageType FileSystemTypeToQuotaStorageType( + FileSystemType type) { + switch (type) { + case kFileSystemTypeTemporary: + return blink::mojom::StorageType::kTemporary; + case kFileSystemTypePersistent: + return blink::mojom::StorageType::kPersistent; + case kFileSystemTypeSyncable: + case kFileSystemTypeSyncableForInternalSync: + return blink::mojom::StorageType::kSyncable; + case kFileSystemTypePluginPrivate: + return blink::mojom::StorageType::kQuotaNotManaged; + default: + return blink::mojom::StorageType::kUnknown; + } +} + +} // namespace storage diff --git a/chromium/storage/browser/file_system/file_system_util.h b/chromium/storage/browser/file_system/file_system_util.h new file mode 100644 index 00000000000..e065d814ea3 --- /dev/null +++ b/chromium/storage/browser/file_system/file_system_util.h @@ -0,0 +1,20 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef STORAGE_BROWSER_FILE_SYSTEM_FILE_SYSTEM_UTIL_H_ +#define STORAGE_BROWSER_FILE_SYSTEM_FILE_SYSTEM_UTIL_H_ + +#include "base/component_export.h" +#include "storage/common/file_system/file_system_types.h" +#include "third_party/blink/public/mojom/quota/quota_types.mojom.h" + +namespace storage { + +// Maps a FileSystemType to the quota type that backs it. +COMPONENT_EXPORT(STORAGE_BROWSER) +blink::mojom::StorageType FileSystemTypeToQuotaStorageType(FileSystemType type); + +} // namespace storage + +#endif // STORAGE_BROWSER_FILE_SYSTEM_FILE_SYSTEM_UTIL_H_ diff --git a/chromium/storage/browser/file_system/file_writer_delegate_unittest.cc b/chromium/storage/browser/file_system/file_writer_delegate_unittest.cc index 645791fb470..116317b8a10 100644 --- a/chromium/storage/browser/file_system/file_writer_delegate_unittest.cc +++ b/chromium/storage/browser/file_system/file_writer_delegate_unittest.cc @@ -10,13 +10,13 @@ #include "base/bind.h" #include "base/callback_helpers.h" +#include "base/cxx17_backports.h" #include "base/files/scoped_temp_dir.h" #include "base/location.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" -#include "base/stl_util.h" #include "base/test/task_environment.h" #include "base/threading/thread_task_runner_handle.h" #include "net/base/io_buffer.h" @@ -33,10 +33,12 @@ #include "storage/browser/file_system/file_system_quota_util.h" #include "storage/browser/file_system/file_writer_delegate.h" #include "storage/browser/file_system/sandbox_file_stream_writer.h" +#include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/test/async_file_test_helper.h" #include "storage/browser/test/test_file_system_context.h" #include "storage/common/file_system/file_system_mount_option.h" #include "testing/platform_test.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "url/gurl.h" #include "url/origin.h" @@ -118,7 +120,7 @@ class FileWriterDelegateTest : public PlatformTest { FileSystemURL GetFileSystemURL(const char* file_name) const { return file_system_context_->CreateCrackedFileSystemURL( - url::Origin::Create(GURL(kOrigin)), kFileSystemType, + blink::StorageKey::CreateFromStringForTesting(kOrigin), kFileSystemType, base::FilePath().FromUTF8Unsafe(file_name)); } @@ -175,8 +177,8 @@ class FileWriterDelegateTest : public PlatformTest { void FileWriterDelegateTest::SetUp() { ASSERT_TRUE(dir_.CreateUniqueTempDir()); - file_system_context_ = - CreateFileSystemContextForTesting(nullptr, dir_.GetPath()); + file_system_context_ = CreateFileSystemContextForTesting( + /*quota_manager_proxy=*/nullptr, dir_.GetPath()); ASSERT_EQ(base::File::FILE_OK, AsyncFileTestHelper::CreateFile(file_system_context_.get(), GetFileSystemURL("test"))); diff --git a/chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader.cc b/chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader.cc index 632bc6a43c5..988daa1e14a 100644 --- a/chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader.cc +++ b/chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader.cc @@ -30,7 +30,7 @@ const int kOpenFlagsForRead = using GetFileInfoCallback = base::OnceCallback<void(base::File::Error, const base::File::Info&)>; -FileErrorOr<base::File::Info> DoGetFileInfo( +base::FileErrorOr<base::File::Info> DoGetFileInfo( const base::FilePath& path, scoped_refptr<FilesystemProxyFileStreamReader::SharedFilesystemProxy> shared_filesystem_proxy) { @@ -47,7 +47,7 @@ FileErrorOr<base::File::Info> DoGetFileInfo( return std::move(*info); } -FileErrorOr<base::File> DoOpenFile( +base::FileErrorOr<base::File> DoOpenFile( const base::FilePath& path, scoped_refptr<FilesystemProxyFileStreamReader::SharedFilesystemProxy> shared_filesystem_proxy) { @@ -158,7 +158,7 @@ void FilesystemProxyFileStreamReader::DidVerifyForOpen( } void FilesystemProxyFileStreamReader::DidOpenFile( - FileErrorOr<base::File> open_result) { + base::FileErrorOr<base::File> open_result) { if (open_result.is_error()) { std::move(callback_).Run(open_result.error()); return; @@ -212,7 +212,7 @@ void FilesystemProxyFileStreamReader::DidOpenForRead( void FilesystemProxyFileStreamReader::DidGetFileInfoForGetLength( net::Int64CompletionOnceCallback callback, - FileErrorOr<base::File::Info> result) { + base::FileErrorOr<base::File::Info> result) { // TODO(enne): track rate of missing blobs for http://crbug.com/1131151 if (emit_metrics_) { bool file_was_found = !result.is_error() || diff --git a/chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader.h b/chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader.h index 10222e0d032..440909b5576 100644 --- a/chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader.h +++ b/chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader.h @@ -60,7 +60,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FilesystemProxyFileStreamReader // Callbacks that are chained from Open for Read. void DidVerifyForOpen(net::CompletionOnceCallback callback, int64_t get_length_result); - void DidOpenFile(FileErrorOr<base::File> result); + void DidOpenFile(base::FileErrorOr<base::File> result); void DidSeekFileStream(int64_t seek_result); void DidOpenForRead(net::IOBuffer* buf, @@ -70,7 +70,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FilesystemProxyFileStreamReader void OnRead(int read_result); void DidGetFileInfoForGetLength(net::Int64CompletionOnceCallback callback, - FileErrorOr<base::File::Info> result); + base::FileErrorOr<base::File::Info> result); net::CompletionOnceCallback callback_; scoped_refptr<base::TaskRunner> task_runner_; diff --git a/chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader_unittest.cc b/chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader_unittest.cc index 1019e272a9a..e9180f6b2a3 100644 --- a/chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader_unittest.cc +++ b/chromium/storage/browser/file_system/filesystem_proxy_file_stream_reader_unittest.cc @@ -20,7 +20,6 @@ #include "base/macros.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" -#include "base/stl_util.h" #include "base/test/task_environment.h" #include "base/threading/thread.h" #include "net/base/io_buffer.h" diff --git a/chromium/storage/browser/file_system/isolated_context.cc b/chromium/storage/browser/file_system/isolated_context.cc index 6bf7acbe685..c6ba0a167b4 100644 --- a/chromium/storage/browser/file_system/isolated_context.cc +++ b/chromium/storage/browser/file_system/isolated_context.cc @@ -17,6 +17,7 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "storage/browser/file_system/file_system_url.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" namespace storage { @@ -388,8 +389,11 @@ bool IsolatedContext::CrackVirtualPath( return true; } +// TODO(https://crbug.com/1221308): creating StorageKey from url is +// temporary; StorageKey will be added in future CL FileSystemURL IsolatedContext::CrackURL(const GURL& url) const { - FileSystemURL filesystem_url = FileSystemURL(url); + FileSystemURL filesystem_url = + FileSystemURL(url, blink::StorageKey(url::Origin::Create(url))); if (!filesystem_url.is_valid()) return FileSystemURL(); return CrackFileSystemURL(filesystem_url); @@ -399,7 +403,10 @@ FileSystemURL IsolatedContext::CreateCrackedFileSystemURL( const url::Origin& origin, FileSystemType type, const base::FilePath& virtual_path) const { - return CrackFileSystemURL(FileSystemURL(origin, type, virtual_path)); + // TODO(https://crbug.com/1221308): function will have StorageKey param in + // future CL; conversion from url::Origin is temporary + return CrackFileSystemURL( + FileSystemURL(blink::StorageKey(origin), type, virtual_path)); } void IsolatedContext::RevokeFileSystemByPath(const base::FilePath& path_in) { @@ -474,7 +481,7 @@ FileSystemURL IsolatedContext::CrackFileSystemURL( } return FileSystemURL( - url.origin(), url.mount_type(), url.virtual_path(), + url.storage_key(), url.mount_type(), url.virtual_path(), !url.filesystem_id().empty() ? url.filesystem_id() : mount_name, cracked_type, cracked_path, cracked_mount_name.empty() ? mount_name : cracked_mount_name, diff --git a/chromium/storage/browser/file_system/isolated_context_unittest.cc b/chromium/storage/browser/file_system/isolated_context_unittest.cc index b8544bdb494..8c514f11d97 100644 --- a/chromium/storage/browser/file_system/isolated_context_unittest.cc +++ b/chromium/storage/browser/file_system/isolated_context_unittest.cc @@ -6,8 +6,8 @@ #include <string> +#include "base/cxx17_backports.h" #include "base/macros.h" -#include "base/stl_util.h" #include "storage/browser/file_system/file_system_url.h" #include "storage/browser/file_system/isolated_context.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chromium/storage/browser/file_system/local_file_stream_reader.cc b/chromium/storage/browser/file_system/local_file_stream_reader.cc index 89db58c714d..8ede6afb3a1 100644 --- a/chromium/storage/browser/file_system/local_file_stream_reader.cc +++ b/chromium/storage/browser/file_system/local_file_stream_reader.cc @@ -27,7 +27,7 @@ namespace { const int kOpenFlagsForRead = base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_ASYNC; -FileErrorOr<base::File::Info> DoGetFileInfo(const base::FilePath& path) { +base::FileErrorOr<base::File::Info> DoGetFileInfo(const base::FilePath& path) { if (!base::PathExists(path)) return base::File::FILE_ERROR_NOT_FOUND; @@ -167,7 +167,7 @@ void LocalFileStreamReader::DidOpenForRead(net::IOBuffer* buf, void LocalFileStreamReader::DidGetFileInfoForGetLength( net::Int64CompletionOnceCallback callback, - FileErrorOr<base::File::Info> result) { + base::FileErrorOr<base::File::Info> result) { if (result.is_error()) { std::move(callback).Run(net::FileErrorToNetError(result.error())); return; diff --git a/chromium/storage/browser/file_system/local_file_stream_reader.h b/chromium/storage/browser/file_system/local_file_stream_reader.h index e9f5866f513..62e85305ee0 100644 --- a/chromium/storage/browser/file_system/local_file_stream_reader.h +++ b/chromium/storage/browser/file_system/local_file_stream_reader.h @@ -63,7 +63,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) LocalFileStreamReader void OnRead(int read_result); void DidGetFileInfoForGetLength(net::Int64CompletionOnceCallback callback, - FileErrorOr<base::File::Info> result); + base::FileErrorOr<base::File::Info> result); net::CompletionOnceCallback callback_; scoped_refptr<base::TaskRunner> task_runner_; diff --git a/chromium/storage/browser/file_system/local_file_stream_reader_unittest.cc b/chromium/storage/browser/file_system/local_file_stream_reader_unittest.cc index d5f477f68cc..aceebc879a3 100644 --- a/chromium/storage/browser/file_system/local_file_stream_reader_unittest.cc +++ b/chromium/storage/browser/file_system/local_file_stream_reader_unittest.cc @@ -20,7 +20,6 @@ #include "base/macros.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" -#include "base/stl_util.h" #include "base/test/task_environment.h" #include "base/threading/thread.h" #include "net/base/io_buffer.h" diff --git a/chromium/storage/browser/file_system/local_file_util_unittest.cc b/chromium/storage/browser/file_system/local_file_util_unittest.cc index 2bdd61caedc..669f4b6e135 100644 --- a/chromium/storage/browser/file_system/local_file_util_unittest.cc +++ b/chromium/storage/browser/file_system/local_file_util_unittest.cc @@ -21,10 +21,12 @@ #include "storage/browser/file_system/file_system_operation_context.h" #include "storage/browser/file_system/local_file_util.h" #include "storage/browser/file_system/native_file_util.h" +#include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/test/async_file_test_helper.h" #include "storage/browser/test/test_file_system_context.h" #include "storage/common/file_system/file_system_types.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "url/gurl.h" #include "url/origin.h" @@ -42,8 +44,8 @@ class LocalFileUtilTest : public testing::Test { void SetUp() override { ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); - file_system_context_ = - CreateFileSystemContextForTesting(nullptr, data_dir_.GetPath()); + file_system_context_ = CreateFileSystemContextForTesting( + /*quota_manager_proxy=*/nullptr, data_dir_.GetPath()); } void TearDown() override { @@ -68,8 +70,8 @@ class LocalFileUtilTest : public testing::Test { FileSystemURL CreateURL(const std::string& file_name) { return file_system_context_->CreateCrackedFileSystemURL( - url::Origin::Create(GURL("http://foo/")), kFileSystemType, - base::FilePath().FromUTF8Unsafe(file_name)); + blink::StorageKey::CreateFromStringForTesting("http://foo/"), + kFileSystemType, base::FilePath().FromUTF8Unsafe(file_name)); } base::FilePath LocalPath(const char* file_name) { diff --git a/chromium/storage/browser/file_system/mount_points.h b/chromium/storage/browser/file_system/mount_points.h index c803364cc7c..f8bca3aa17b 100644 --- a/chromium/storage/browser/file_system/mount_points.h +++ b/chromium/storage/browser/file_system/mount_points.h @@ -10,7 +10,6 @@ #include "base/component_export.h" #include "base/files/file_path.h" -#include "base/macros.h" #include "storage/common/file_system/file_system_util.h" class GURL; @@ -43,8 +42,10 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) MountPoints { } }; - MountPoints() {} - virtual ~MountPoints() {} + MountPoints() = default; + MountPoints(const MountPoints&) = delete; + MountPoints& operator=(const MountPoints&) = delete; + virtual ~MountPoints() = default; // Revokes a mount point identified by |mount_name|. // Returns false if the |mount_name| is not (no longer) registered. @@ -98,9 +99,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) MountPoints { // instantiated as the FileSystemURL class. This is internally used for nested // URL cracking in FileSystemContext. virtual FileSystemURL CrackFileSystemURL(const FileSystemURL& url) const = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(MountPoints); }; } // namespace storage diff --git a/chromium/storage/browser/file_system/obfuscated_file_util.cc b/chromium/storage/browser/file_system/obfuscated_file_util.cc index bc180ebfb4d..05726e8a451 100644 --- a/chromium/storage/browser/file_system/obfuscated_file_util.cc +++ b/chromium/storage/browser/file_system/obfuscated_file_util.cc @@ -258,14 +258,14 @@ class ObfuscatedOriginEnumerator }; ObfuscatedFileUtil::ObfuscatedFileUtil( - SpecialStoragePolicy* special_storage_policy, + scoped_refptr<SpecialStoragePolicy> special_storage_policy, const base::FilePath& file_system_directory, leveldb::Env* env_override, GetTypeStringForURLCallback get_type_string_for_url, const std::set<std::string>& known_type_strings, SandboxFileSystemBackendDelegate* sandbox_delegate, bool is_incognito) - : special_storage_policy_(special_storage_policy), + : special_storage_policy_(std::move(special_storage_policy)), file_system_directory_(file_system_directory), env_override_(env_override), is_incognito_(is_incognito), diff --git a/chromium/storage/browser/file_system/obfuscated_file_util.h b/chromium/storage/browser/file_system/obfuscated_file_util.h index 372d35fa205..98d8db7c525 100644 --- a/chromium/storage/browser/file_system/obfuscated_file_util.h +++ b/chromium/storage/browser/file_system/obfuscated_file_util.h @@ -18,6 +18,7 @@ #include "base/files/file.h" #include "base/files/file_path.h" #include "base/macros.h" +#include "base/memory/scoped_refptr.h" #include "base/sequence_checker.h" #include "base/timer/timer.h" #include "storage/browser/blob/shareable_file_reference.h" @@ -95,7 +96,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) ObfuscatedFileUtil // for any known type exists the origin directory may get deleted when // one origin/type pair is deleted. // - ObfuscatedFileUtil(SpecialStoragePolicy* special_storage_policy, + ObfuscatedFileUtil(scoped_refptr<SpecialStoragePolicy> special_storage_policy, const base::FilePath& file_system_directory, leveldb::Env* env_override, GetTypeStringForURLCallback get_type_string_for_url, @@ -214,8 +215,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) ObfuscatedFileUtil // Helper method to create an obfuscated file util for regular // (temporary, persistent) file systems. Used only for testing. // Note: this is implemented in sandbox_file_system_backend_delegate.cc. - static ObfuscatedFileUtil* CreateForTesting( - SpecialStoragePolicy* special_storage_policy, + static std::unique_ptr<ObfuscatedFileUtil> CreateForTesting( + scoped_refptr<SpecialStoragePolicy> special_storage_policy, const base::FilePath& file_system_directory, leveldb::Env* env_override, bool is_incognito); diff --git a/chromium/storage/browser/file_system/obfuscated_file_util_disk_delegate.cc b/chromium/storage/browser/file_system/obfuscated_file_util_disk_delegate.cc index 26c4f625452..ae1cdcf13fe 100644 --- a/chromium/storage/browser/file_system/obfuscated_file_util_disk_delegate.cc +++ b/chromium/storage/browser/file_system/obfuscated_file_util_disk_delegate.cc @@ -9,9 +9,9 @@ namespace storage { -ObfuscatedFileUtilDiskDelegate::ObfuscatedFileUtilDiskDelegate() {} +ObfuscatedFileUtilDiskDelegate::ObfuscatedFileUtilDiskDelegate() = default; -ObfuscatedFileUtilDiskDelegate::~ObfuscatedFileUtilDiskDelegate() {} +ObfuscatedFileUtilDiskDelegate::~ObfuscatedFileUtilDiskDelegate() = default; bool ObfuscatedFileUtilDiskDelegate::DirectoryExists( const base::FilePath& path) { diff --git a/chromium/storage/browser/file_system/obfuscated_file_util_disk_delegate.h b/chromium/storage/browser/file_system/obfuscated_file_util_disk_delegate.h index 44b83fb201c..c5615c94f08 100644 --- a/chromium/storage/browser/file_system/obfuscated_file_util_disk_delegate.h +++ b/chromium/storage/browser/file_system/obfuscated_file_util_disk_delegate.h @@ -19,6 +19,10 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) ObfuscatedFileUtilDiskDelegate : public ObfuscatedFileUtilDelegate { public: ObfuscatedFileUtilDiskDelegate(); + ObfuscatedFileUtilDiskDelegate(const ObfuscatedFileUtilDiskDelegate&) = + delete; + ObfuscatedFileUtilDiskDelegate& operator=( + const ObfuscatedFileUtilDiskDelegate&) = delete; ~ObfuscatedFileUtilDiskDelegate() override; bool DirectoryExists(const base::FilePath& path) override; @@ -55,8 +59,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) ObfuscatedFileUtilDiskDelegate FileSystemOperation::CopyOrMoveOption option, NativeFileUtil::CopyOrMoveMode mode) override; base::File::Error DeleteFile(const base::FilePath& path) override; - - DISALLOW_COPY_AND_ASSIGN(ObfuscatedFileUtilDiskDelegate); }; } // namespace storage diff --git a/chromium/storage/browser/file_system/obfuscated_file_util_unittest.cc b/chromium/storage/browser/file_system/obfuscated_file_util_unittest.cc index 4290aa4ec38..8049ff3377a 100644 --- a/chromium/storage/browser/file_system/obfuscated_file_util_unittest.cc +++ b/chromium/storage/browser/file_system/obfuscated_file_util_unittest.cc @@ -14,6 +14,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" +#include "base/cxx17_backports.h" #include "base/files/file.h" #include "base/files/file_path.h" #include "base/files/file_util.h" @@ -21,7 +22,6 @@ #include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "base/run_loop.h" -#include "base/stl_util.h" #include "base/test/task_environment.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" @@ -31,6 +31,7 @@ #include "storage/browser/file_system/file_system_backend.h" #include "storage/browser/file_system/file_system_context.h" #include "storage/browser/file_system/file_system_operation_context.h" +#include "storage/browser/file_system/file_system_url.h" #include "storage/browser/file_system/file_system_usage_cache.h" #include "storage/browser/file_system/obfuscated_file_util.h" #include "storage/browser/file_system/obfuscated_file_util_memory_delegate.h" @@ -38,6 +39,7 @@ #include "storage/browser/file_system/sandbox_file_system_backend_delegate.h" #include "storage/browser/file_system/sandbox_origin_database.h" #include "storage/browser/quota/quota_manager.h" +#include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/test/async_file_test_helper.h" #include "storage/browser/test/file_system_test_file_set.h" #include "storage/browser/test/mock_file_change_observer.h" @@ -45,7 +47,9 @@ #include "storage/browser/test/sandbox_file_system_test_helper.h" #include "storage/browser/test/test_file_system_context.h" #include "storage/common/database/database_identifier.h" +#include "storage/common/file_system/file_system_types.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/leveldatabase/leveldb_chrome.h" #include "url/gurl.h" #include "url/origin.h" @@ -116,19 +120,19 @@ const OriginEnumerationTestRecord kOriginEnumerationTestRecords[] = { FileSystemURL FileSystemURLAppend(const FileSystemURL& url, const base::FilePath::StringType& child) { - return FileSystemURL::CreateForTest(url.origin(), url.mount_type(), + return FileSystemURL::CreateForTest(url.storage_key(), url.mount_type(), url.virtual_path().Append(child)); } FileSystemURL FileSystemURLAppendUTF8(const FileSystemURL& url, const std::string& child) { return FileSystemURL::CreateForTest( - url.origin(), url.mount_type(), + url.storage_key(), url.mount_type(), url.virtual_path().Append(base::FilePath::FromUTF8Unsafe(child))); } FileSystemURL FileSystemURLDirName(const FileSystemURL& url) { - return FileSystemURL::CreateForTest(url.origin(), url.mount_type(), + return FileSystemURL::CreateForTest(url.storage_key(), url.mount_type(), VirtualPath::DirName(url.virtual_path())); } @@ -158,6 +162,11 @@ class ObfuscatedFileUtilTest : public testing::Test, quota_status_(blink::mojom::QuotaStatusCode::kUnknown), usage_(-1) {} + ObfuscatedFileUtilTest(const ObfuscatedFileUtilTest&) = delete; + ObfuscatedFileUtilTest& operator=(const ObfuscatedFileUtilTest&) = delete; + + ~ObfuscatedFileUtilTest() override = default; + bool is_incognito() { return GetParam() == TestMode::kIncognito; } void SetUp() override { @@ -167,8 +176,8 @@ class ObfuscatedFileUtilTest : public testing::Test, quota_manager_ = base::MakeRefCounted<QuotaManager>( is_incognito(), data_dir_.GetPath(), - base::ThreadTaskRunnerHandle::Get().get(), - /*quota_change_callback=*/base::DoNothing(), storage_policy_.get(), + base::ThreadTaskRunnerHandle::Get(), + /*quota_change_callback=*/base::DoNothing(), storage_policy_, GetQuotaSettingsFunc()); QuotaSettings settings; settings.per_host_quota = 25 * 1024 * 1024; @@ -189,7 +198,7 @@ class ObfuscatedFileUtilTest : public testing::Test, : CreateFileSystemContextForTesting( quota_manager_->proxy(), data_dir_.GetPath()); - sandbox_file_system_.SetUp(file_system_context_.get()); + sandbox_file_system_.SetUp(file_system_context_); change_observers_ = MockFileChangeObserver::CreateList(&change_observer_); @@ -242,22 +251,22 @@ class ObfuscatedFileUtilTest : public testing::Test, // and obfuscated_file_util_. // Use this for tests which need to run in multiple origins; we need a test // helper per origin. - SandboxFileSystemTestHelper* NewFileSystem(const Origin& origin, - FileSystemType type) { - SandboxFileSystemTestHelper* file_system = - new SandboxFileSystemTestHelper(origin, type); + std::unique_ptr<SandboxFileSystemTestHelper> NewFileSystem( + const Origin& origin, + FileSystemType type) { + auto file_system = + std::make_unique<SandboxFileSystemTestHelper>(origin, type); - file_system->SetUp(file_system_context_.get()); + file_system->SetUp(file_system_context_); return file_system; } std::unique_ptr<ObfuscatedFileUtil> CreateObfuscatedFileUtil( - SpecialStoragePolicy* storage_policy) { - return std::unique_ptr<ObfuscatedFileUtil>( - ObfuscatedFileUtil::CreateForTesting( - storage_policy, data_dir_path(), - is_incognito() ? incognito_leveldb_environment_.get() : nullptr, - is_incognito())); + scoped_refptr<SpecialStoragePolicy> storage_policy) { + return ObfuscatedFileUtil::CreateForTesting( + std::move(storage_policy), data_dir_path(), + is_incognito() ? incognito_leveldb_environment_.get() : nullptr, + is_incognito()); } ObfuscatedFileUtil* ofu() { @@ -304,7 +313,7 @@ class ObfuscatedFileUtilTest : public testing::Test, } bool PathExists(const FileSystemURL& url) { - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); base::File::Info file_info; base::FilePath platform_path; base::File::Error error = @@ -313,7 +322,7 @@ class ObfuscatedFileUtilTest : public testing::Test, } int64_t GetPathSize(const FileSystemURL& url) { - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); base::File::Info file_info; base::FilePath platform_path; EXPECT_EQ( @@ -344,7 +353,7 @@ class ObfuscatedFileUtilTest : public testing::Test, } void CheckFile(const FileSystemURL& url) { - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); base::FilePath local_path; EXPECT_EQ(base::File::FILE_OK, ofu()->GetLocalFilePath(context.get(), url, &local_path)); @@ -539,7 +548,7 @@ class ObfuscatedFileUtilTest : public testing::Test, base::Time last_access_time = base::Time::Now(); base::Time last_modified_time = base::Time::Now(); - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); EXPECT_EQ( base::File::FILE_OK, ofu()->Touch(context.get(), url, last_access_time, last_modified_time)); @@ -631,14 +640,14 @@ class ObfuscatedFileUtilTest : public testing::Test, } void ClearTimestamp(const FileSystemURL& url) { - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); EXPECT_EQ(base::File::FILE_OK, ofu()->Touch(context.get(), url, base::Time(), base::Time())); EXPECT_EQ(base::Time(), GetModifiedTime(url)); } base::Time GetModifiedTime(const FileSystemURL& url) { - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); base::FilePath data_path; base::File::Info file_info; context = NewContext(nullptr); @@ -695,7 +704,7 @@ class ObfuscatedFileUtilTest : public testing::Test, void MaybeDropDatabasesAliveCaseTestBody() { std::unique_ptr<ObfuscatedFileUtil> file_util = - CreateObfuscatedFileUtil(nullptr); + CreateObfuscatedFileUtil(/*storage_policy=*/nullptr); file_util->InitOriginDatabase(Origin(), true /*create*/); ASSERT_TRUE(file_util->origin_database_ != nullptr); @@ -713,7 +722,7 @@ class ObfuscatedFileUtilTest : public testing::Test, // doesn't cause a crash for use after free. { std::unique_ptr<ObfuscatedFileUtil> file_util = - CreateObfuscatedFileUtil(nullptr); + CreateObfuscatedFileUtil(/*storage_policy=*/nullptr); file_util->InitOriginDatabase(Origin(), true /*create*/); file_util->db_flush_delay_seconds_ = 0; file_util->MarkUsed(); @@ -726,9 +735,10 @@ class ObfuscatedFileUtilTest : public testing::Test, void DestroyDirectoryDatabase_IsolatedTestBody() { storage_policy_->AddIsolated(origin_.GetURL()); std::unique_ptr<ObfuscatedFileUtil> file_util = - CreateObfuscatedFileUtil(storage_policy_.get()); + CreateObfuscatedFileUtil(/*storage_policy=*/storage_policy_); const FileSystemURL url = FileSystemURL::CreateForTest( - origin_, kFileSystemTypePersistent, base::FilePath()); + blink::StorageKey(url::Origin(origin_)), kFileSystemTypePersistent, + base::FilePath()); // Create DirectoryDatabase for isolated origin. SandboxDirectoryDatabase* db = @@ -744,9 +754,10 @@ class ObfuscatedFileUtilTest : public testing::Test, void GetDirectoryDatabase_IsolatedTestBody() { storage_policy_->AddIsolated(origin_.GetURL()); std::unique_ptr<ObfuscatedFileUtil> file_util = - CreateObfuscatedFileUtil(storage_policy_.get()); + CreateObfuscatedFileUtil(storage_policy_); const FileSystemURL url = FileSystemURL::CreateForTest( - origin_, kFileSystemTypePersistent, base::FilePath()); + blink::StorageKey(url::Origin(origin_)), kFileSystemTypePersistent, + base::FilePath()); // Create DirectoryDatabase for isolated origin. SandboxDirectoryDatabase* db = @@ -797,9 +808,6 @@ class ObfuscatedFileUtilTest : public testing::Test, MockFileChangeObserver change_observer_; ChangeObserverList change_observers_; base::WeakPtrFactory<ObfuscatedFileUtilTest> weak_factory_{this}; - - private: - DISALLOW_COPY_AND_ASSIGN(ObfuscatedFileUtilTest); }; INSTANTIATE_TEST_SUITE_P(All, @@ -809,7 +817,7 @@ INSTANTIATE_TEST_SUITE_P(All, TEST_P(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) { FileSystemURL url = CreateURLFromUTF8("fake/file"); - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); bool created; base::File::Error result = @@ -897,7 +905,7 @@ TEST_P(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) { TEST_P(ObfuscatedFileUtilTest, TestTruncate) { bool created = false; FileSystemURL url = CreateURLFromUTF8("file"); - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, ofu()->Truncate(context.get(), url, 4)); @@ -983,8 +991,8 @@ TEST_P(ObfuscatedFileUtilTest, TestQuotaOnTruncation) { EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, ofu()->Truncate(LimitedContext(1234).get(), url, 1234)); } else { - EXPECT_EQ(base::File::FILE_OK, - ofu()->DeleteFile(NewContext(nullptr).get(), url)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); + EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), url)); } ASSERT_EQ(0, ComputeTotalFileSize()); } @@ -992,7 +1000,7 @@ TEST_P(ObfuscatedFileUtilTest, TestQuotaOnTruncation) { TEST_P(ObfuscatedFileUtilTest, TestEnsureFileExists) { FileSystemURL url = CreateURLFromUTF8("fake/file"); bool created = false; - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, ofu()->EnsureFileExists(context.get(), url, &created)); EXPECT_TRUE(change_observer()->HasNoChange()); @@ -1045,7 +1053,7 @@ TEST_P(ObfuscatedFileUtilTest, TestEnsureFileExists) { } TEST_P(ObfuscatedFileUtilTest, TestDirectoryOps) { - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); bool exclusive = false; bool recursive = false; @@ -1186,7 +1194,7 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryOps) { } TEST_P(ObfuscatedFileUtilTest, TestReadDirectory) { - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); bool exclusive = true; bool recursive = true; FileSystemURL url = CreateURLFromUTF8("directory/to/use"); @@ -1205,7 +1213,7 @@ TEST_P(ObfuscatedFileUtilTest, TestReadRootWithEmptyString) { TEST_P(ObfuscatedFileUtilTest, TestReadDirectoryOnFile) { FileSystemURL url = CreateURLFromUTF8("file"); - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); bool created = false; ASSERT_EQ(base::File::FILE_OK, @@ -1222,7 +1230,7 @@ TEST_P(ObfuscatedFileUtilTest, TestReadDirectoryOnFile) { TEST_P(ObfuscatedFileUtilTest, TestTouch) { FileSystemURL url = CreateURLFromUTF8("file"); - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); base::Time last_access_time = base::Time::Now(); base::Time last_modified_time = base::Time::Now(); @@ -1252,7 +1260,7 @@ TEST_P(ObfuscatedFileUtilTest, TestTouch) { TEST_P(ObfuscatedFileUtilTest, TestPathQuotas) { FileSystemURL url = CreateURLFromUTF8("fake/file"); - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); url = CreateURLFromUTF8("file name"); context->set_allowed_bytes_growth(5); @@ -1288,7 +1296,7 @@ TEST_P(ObfuscatedFileUtilTest, TestPathQuotas) { TEST_P(ObfuscatedFileUtilTest, TestCopyOrMoveFileNotFound) { FileSystemURL source_url = CreateURLFromUTF8("path0.txt"); FileSystemURL dest_url = CreateURLFromUTF8("path1.txt"); - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); bool is_copy_not_move = false; EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, @@ -1341,7 +1349,7 @@ TEST_P(ObfuscatedFileUtilTest, TestCopyOrMoveFileSuccess) { SCOPED_TRACE(testing::Message() << "\t dest_path " << test_case.dest_path); SCOPED_TRACE(testing::Message() << "\t cause_overwrite " << test_case.cause_overwrite); - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); bool exclusive = false; bool recursive = true; @@ -1416,7 +1424,7 @@ TEST_P(ObfuscatedFileUtilTest, TestCopyOrMoveFileSuccess) { TEST_P(ObfuscatedFileUtilTest, TestCopyPathQuotas) { FileSystemURL src_url = CreateURLFromUTF8("src path"); FileSystemURL dest_url = CreateURLFromUTF8("destination path"); - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); bool created = false; ASSERT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), src_url, &created)); @@ -1446,7 +1454,7 @@ TEST_P(ObfuscatedFileUtilTest, TestCopyPathQuotas) { TEST_P(ObfuscatedFileUtilTest, TestMovePathQuotasWithRename) { FileSystemURL src_url = CreateURLFromUTF8("src path"); FileSystemURL dest_url = CreateURLFromUTF8("destination path"); - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); bool created = false; ASSERT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), src_url, &created)); @@ -1482,7 +1490,7 @@ TEST_P(ObfuscatedFileUtilTest, TestMovePathQuotasWithRename) { TEST_P(ObfuscatedFileUtilTest, TestMovePathQuotasWithoutRename) { FileSystemURL src_url = CreateURLFromUTF8("src path"); - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); bool created = false; ASSERT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), src_url, &created)); @@ -1526,7 +1534,7 @@ TEST_P(ObfuscatedFileUtilTest, TestCopyInForeignFile) { } TEST_P(ObfuscatedFileUtilTest, TestEnumerator) { - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); FileSystemURL src_url = CreateURLFromUTF8("source dir"); bool exclusive = true; bool recursive = false; @@ -1554,8 +1562,8 @@ TEST_P(ObfuscatedFileUtilTest, TestEnumerator) { } TEST_P(ObfuscatedFileUtilTest, TestOriginEnumerator) { - std::unique_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enumerator( - ofu()->CreateOriginEnumerator()); + std::unique_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enumerator = + ofu()->CreateOriginEnumerator(); // The test helper starts out with a single filesystem. EXPECT_TRUE(enumerator.get()); EXPECT_EQ(origin(), enumerator->Next()); @@ -1577,8 +1585,8 @@ TEST_P(ObfuscatedFileUtilTest, TestOriginEnumerator) { Origin origin = Origin::Create(GURL(record.origin_url)); origins_expected.insert(origin); if (record.has_temporary) { - std::unique_ptr<SandboxFileSystemTestHelper> file_system( - NewFileSystem(origin, kFileSystemTypeTemporary)); + std::unique_ptr<SandboxFileSystemTestHelper> file_system = + NewFileSystem(origin, kFileSystemTypeTemporary); std::unique_ptr<FileSystemOperationContext> context( NewContext(file_system.get())); bool created = false; @@ -1589,8 +1597,8 @@ TEST_P(ObfuscatedFileUtilTest, TestOriginEnumerator) { EXPECT_TRUE(created); } if (record.has_persistent) { - std::unique_ptr<SandboxFileSystemTestHelper> file_system( - NewFileSystem(origin, kFileSystemTypePersistent)); + std::unique_ptr<SandboxFileSystemTestHelper> file_system = + NewFileSystem(origin, kFileSystemTypePersistent); std::unique_ptr<FileSystemOperationContext> context( NewContext(file_system.get())); bool created = false; @@ -1639,7 +1647,7 @@ TEST_P(ObfuscatedFileUtilTest, TestOriginEnumerator) { } TEST_P(ObfuscatedFileUtilTest, TestRevokeUsageCache) { - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); int64_t expected_quota = 0; @@ -1784,7 +1792,7 @@ TEST_P(ObfuscatedFileUtilTest, TestIncompleteDirectoryReading) { } TEST_P(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) { - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); const FileSystemURL dir_url = CreateURLFromUTF8("foo_dir"); // Create working directory. @@ -1900,7 +1908,7 @@ TEST_P(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) { } TEST_P(ObfuscatedFileUtilTest, TestDirectoryTimestampForDeletion) { - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); const FileSystemURL dir_url = CreateURLFromUTF8("foo_dir"); // Create working directory. @@ -1970,7 +1978,7 @@ TEST_P(ObfuscatedFileUtilTest, TestFileEnumeratorTimestamp) { FileSystemURL url1 = FileSystemURLAppendUTF8(dir, "bar"); FileSystemURL url2 = FileSystemURLAppendUTF8(dir, "baz"); - std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); + std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr); EXPECT_EQ(base::File::FILE_OK, ofu()->CreateDirectory(context.get(), dir, false, false)); @@ -2006,12 +2014,12 @@ TEST_P(ObfuscatedFileUtilTest, TestFileEnumeratorTimestamp) { context = NewContext(nullptr); base::File::Info file_info; base::FilePath file_path; - EXPECT_EQ( - base::File::FILE_OK, - ofu()->GetFileInfo(context.get(), - FileSystemURL::CreateForTest( - dir.origin(), dir.mount_type(), file_path_each), - &file_info, &file_path)); + EXPECT_EQ(base::File::FILE_OK, + ofu()->GetFileInfo( + context.get(), + FileSystemURL::CreateForTest( + dir.storage_key(), dir.mount_type(), file_path_each), + &file_info, &file_path)); EXPECT_EQ(file_info.is_directory, file_enum->IsDirectory()); EXPECT_EQ(file_info.last_modified, file_enum->LastModifiedTime()); EXPECT_EQ(file_info.size, file_enum->Size()); @@ -2388,14 +2396,14 @@ TEST_P(ObfuscatedFileUtilTest, DeleteDirectoryForOriginAndType) { const Origin origin3 = Origin::Create(GURL("http://nope.example.com")); // Create origin directories. - std::unique_ptr<SandboxFileSystemTestHelper> fs1( - NewFileSystem(origin1, kFileSystemTypeTemporary)); - std::unique_ptr<SandboxFileSystemTestHelper> fs2( - NewFileSystem(origin1, kFileSystemTypePersistent)); - std::unique_ptr<SandboxFileSystemTestHelper> fs3( - NewFileSystem(origin2, kFileSystemTypeTemporary)); - std::unique_ptr<SandboxFileSystemTestHelper> fs4( - NewFileSystem(origin2, kFileSystemTypePersistent)); + std::unique_ptr<SandboxFileSystemTestHelper> fs1 = + NewFileSystem(origin1, kFileSystemTypeTemporary); + std::unique_ptr<SandboxFileSystemTestHelper> fs2 = + NewFileSystem(origin1, kFileSystemTypePersistent); + std::unique_ptr<SandboxFileSystemTestHelper> fs3 = + NewFileSystem(origin2, kFileSystemTypeTemporary); + std::unique_ptr<SandboxFileSystemTestHelper> fs4 = + NewFileSystem(origin2, kFileSystemTypePersistent); // Make sure directories for origin1 exist. base::File::Error error = base::File::FILE_ERROR_FAILED; @@ -2465,14 +2473,14 @@ TEST_P(ObfuscatedFileUtilTest, DeleteDirectoryForOriginAndType_DeleteAll) { const Origin origin2 = Origin::Create(GURL("http://www.example.com:1234")); // Create origin directories. - std::unique_ptr<SandboxFileSystemTestHelper> fs1( - NewFileSystem(origin1, kFileSystemTypeTemporary)); - std::unique_ptr<SandboxFileSystemTestHelper> fs2( - NewFileSystem(origin1, kFileSystemTypePersistent)); - std::unique_ptr<SandboxFileSystemTestHelper> fs3( - NewFileSystem(origin2, kFileSystemTypeTemporary)); - std::unique_ptr<SandboxFileSystemTestHelper> fs4( - NewFileSystem(origin2, kFileSystemTypePersistent)); + std::unique_ptr<SandboxFileSystemTestHelper> fs1 = + NewFileSystem(origin1, kFileSystemTypeTemporary); + std::unique_ptr<SandboxFileSystemTestHelper> fs2 = + NewFileSystem(origin1, kFileSystemTypePersistent); + std::unique_ptr<SandboxFileSystemTestHelper> fs3 = + NewFileSystem(origin2, kFileSystemTypeTemporary); + std::unique_ptr<SandboxFileSystemTestHelper> fs4 = + NewFileSystem(origin2, kFileSystemTypePersistent); // Make sure directories for origin1 exist. base::File::Error error = base::File::FILE_ERROR_FAILED; diff --git a/chromium/storage/browser/file_system/plugin_private_file_system_backend.cc b/chromium/storage/browser/file_system/plugin_private_file_system_backend.cc index 94f3ccccf23..ebad1e2a749 100644 --- a/chromium/storage/browser/file_system/plugin_private_file_system_backend.cc +++ b/chromium/storage/browser/file_system/plugin_private_file_system_backend.cc @@ -14,6 +14,7 @@ #include "base/containers/contains.h" #include "base/files/file_enumerator.h" #include "base/files/file_path.h" +#include "base/memory/scoped_refptr.h" #include "base/synchronization/lock.h" #include "base/task_runner_util.h" #include "base/threading/thread_task_runner_handle.h" @@ -27,15 +28,18 @@ #include "storage/browser/file_system/quota/quota_reservation.h" #include "storage/browser/file_system/sandbox_file_stream_reader.h" #include "storage/browser/file_system/sandbox_file_stream_writer.h" +#include "storage/browser/quota/special_storage_policy.h" #include "storage/common/file_system/file_system_util.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "url/origin.h" namespace storage { class PluginPrivateFileSystemBackend::FileSystemIDToPluginMap { public: - explicit FileSystemIDToPluginMap(base::SequencedTaskRunner* task_runner) - : task_runner_(task_runner) {} + explicit FileSystemIDToPluginMap( + scoped_refptr<base::SequencedTaskRunner> task_runner) + : task_runner_(std::move(task_runner)) {} ~FileSystemIDToPluginMap() = default; std::string GetPluginIDForURL(const FileSystemURL& url) { @@ -63,7 +67,7 @@ class PluginPrivateFileSystemBackend::FileSystemIDToPluginMap { private: using Map = std::map<std::string, std::string>; - scoped_refptr<base::SequencedTaskRunner> task_runner_; + const scoped_refptr<base::SequencedTaskRunner> task_runner_; Map map_; }; @@ -92,19 +96,19 @@ base::File::Error OpenFileSystemOnFileTaskRunner( } // namespace PluginPrivateFileSystemBackend::PluginPrivateFileSystemBackend( - base::SequencedTaskRunner* file_task_runner, + scoped_refptr<base::SequencedTaskRunner> file_task_runner, const base::FilePath& profile_path, - SpecialStoragePolicy* special_storage_policy, + scoped_refptr<SpecialStoragePolicy> special_storage_policy, const FileSystemOptions& file_system_options, leveldb::Env* env_override) - : file_task_runner_(file_task_runner), + : file_task_runner_(std::move(file_task_runner)), file_system_options_(file_system_options), base_path_(profile_path.Append(kFileSystemDirectory) .Append(kPluginPrivateDirectory)), - plugin_map_(new FileSystemIDToPluginMap(file_task_runner)) { + plugin_map_(new FileSystemIDToPluginMap(file_task_runner_)) { file_util_ = std::make_unique<AsyncFileUtilAdapter>( std::make_unique<ObfuscatedFileUtil>( - special_storage_policy, base_path_, env_override, + std::move(special_storage_policy), base_path_, env_override, base::BindRepeating(&FileSystemIDToPluginMap::GetPluginIDForURL, base::Owned(plugin_map_)), std::set<std::string>(), nullptr, @@ -343,9 +347,14 @@ void PluginPrivateFileSystemBackend::GetOriginDetailsOnFileTaskRunner( continue; } + // TODO(https://crbug.com/1231162): determine whether EME/CDM/plugin private + // file system will be partitioned and use the appropriate StorageKey std::unique_ptr<FileSystemFileUtil::AbstractFileEnumerator> enumerator( obfuscated_file_util()->CreateFileEnumerator( - operation_context.get(), context->CrackURL(GURL(root)), true)); + operation_context.get(), + context->CrackURL( + GURL(root), blink::StorageKey(url::Origin::Create(GURL(root)))), + true)); while (!enumerator->Next().empty()) { *total_size += enumerator->Size(); diff --git a/chromium/storage/browser/file_system/plugin_private_file_system_backend.h b/chromium/storage/browser/file_system/plugin_private_file_system_backend.h index 21d29a8d5fe..0394ffbae24 100644 --- a/chromium/storage/browser/file_system/plugin_private_file_system_backend.h +++ b/chromium/storage/browser/file_system/plugin_private_file_system_backend.h @@ -46,11 +46,12 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) PluginPrivateFileSystemBackend class FileSystemIDToPluginMap; using StatusCallback = base::OnceCallback<void(base::File::Error result)>; - PluginPrivateFileSystemBackend(base::SequencedTaskRunner* file_task_runner, - const base::FilePath& profile_path, - SpecialStoragePolicy* special_storage_policy, - const FileSystemOptions& file_system_options, - leveldb::Env* env_override); + PluginPrivateFileSystemBackend( + scoped_refptr<base::SequencedTaskRunner> file_task_runner, + const base::FilePath& profile_path, + scoped_refptr<SpecialStoragePolicy> special_storage_policy, + const FileSystemOptions& file_system_options, + leveldb::Env* env_override); ~PluginPrivateFileSystemBackend() override; // This must be used to open 'private' filesystem instead of regular @@ -139,7 +140,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) PluginPrivateFileSystemBackend ObfuscatedFileUtil* obfuscated_file_util(); const base::FilePath& base_path() const { return base_path_; } - scoped_refptr<base::SequencedTaskRunner> file_task_runner_; + const scoped_refptr<base::SequencedTaskRunner> file_task_runner_; const FileSystemOptions file_system_options_; const base::FilePath base_path_; std::unique_ptr<AsyncFileUtil> file_util_; diff --git a/chromium/storage/browser/file_system/plugin_private_file_system_backend_unittest.cc b/chromium/storage/browser/file_system/plugin_private_file_system_backend_unittest.cc index 654664010ab..56495593a65 100644 --- a/chromium/storage/browser/file_system/plugin_private_file_system_backend_unittest.cc +++ b/chromium/storage/browser/file_system/plugin_private_file_system_backend_unittest.cc @@ -13,11 +13,14 @@ #include "storage/browser/file_system/isolated_context.h" #include "storage/browser/file_system/obfuscated_file_util.h" #include "storage/browser/file_system/plugin_private_file_system_backend.h" +#include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/test/async_file_test_helper.h" #include "storage/browser/test/test_file_system_context.h" #include "storage/browser/test/test_file_system_options.h" #include "storage/common/file_system/file_system_util.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" +#include "url/gurl.h" #include "url/origin.h" using url::Origin; @@ -39,13 +42,16 @@ class PluginPrivateFileSystemBackendTest : public testing::Test { void SetUp() override { ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); context_ = CreateFileSystemContextForTesting( - nullptr /* quota_manager_proxy */, data_dir_.GetPath()); + /*quota_manager_proxy=*/nullptr, data_dir_.GetPath()); } + // TODO(https://crbug.com/1231162): determine whether EME/CDM/plugin private + // file system will be partitioned and use the appropriate StorageKey FileSystemURL CreateURL(const GURL& root_url, const std::string& relative) { - FileSystemURL root = context_->CrackURL(root_url); + FileSystemURL root = context_->CrackURL( + root_url, blink::StorageKey(url::Origin::Create(root_url))); return context_->CreateCrackedFileSystemURL( - root.origin(), root.mount_type(), + root.storage_key(), root.mount_type(), root.virtual_path().AppendASCII(relative)); } diff --git a/chromium/storage/browser/file_system/quota/quota_backend_impl.cc b/chromium/storage/browser/file_system/quota/quota_backend_impl.cc index 9a3af570aca..d079fd2d12f 100644 --- a/chromium/storage/browser/file_system/quota/quota_backend_impl.cc +++ b/chromium/storage/browser/file_system/quota/quota_backend_impl.cc @@ -16,22 +16,24 @@ #include "base/numerics/safe_conversions.h" #include "base/sequenced_task_runner.h" #include "storage/browser/file_system/file_system_usage_cache.h" -#include "storage/browser/quota/quota_client.h" +#include "storage/browser/file_system/file_system_util.h" +#include "storage/browser/quota/quota_client_type.h" #include "storage/browser/quota/quota_manager_proxy.h" #include "storage/common/file_system/file_system_util.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "url/origin.h" namespace storage { QuotaBackendImpl::QuotaBackendImpl( - base::SequencedTaskRunner* file_task_runner, + scoped_refptr<base::SequencedTaskRunner> file_task_runner, ObfuscatedFileUtil* obfuscated_file_util, FileSystemUsageCache* file_system_usage_cache, - QuotaManagerProxy* quota_manager_proxy) - : file_task_runner_(file_task_runner), + scoped_refptr<QuotaManagerProxy> quota_manager_proxy) + : file_task_runner_(std::move(file_task_runner)), obfuscated_file_util_(obfuscated_file_util), file_system_usage_cache_(file_system_usage_cache), - quota_manager_proxy_(quota_manager_proxy) {} + quota_manager_proxy_(std::move(quota_manager_proxy)) {} QuotaBackendImpl::~QuotaBackendImpl() = default; @@ -47,7 +49,8 @@ void QuotaBackendImpl::ReserveQuota(const url::Origin& origin, } DCHECK(quota_manager_proxy_.get()); quota_manager_proxy_->GetUsageAndQuota( - origin, FileSystemTypeToQuotaStorageType(type), file_task_runner_, + blink::StorageKey(origin), FileSystemTypeToQuotaStorageType(type), + file_task_runner_, base::BindOnce(&QuotaBackendImpl::DidGetUsageAndQuotaForReserveQuota, weak_ptr_factory_.GetWeakPtr(), QuotaReservationInfo(origin, type, delta), @@ -140,7 +143,7 @@ void QuotaBackendImpl::ReserveQuotaInternal(const QuotaReservationInfo& info) { DCHECK(!info.origin.opaque()); DCHECK(quota_manager_proxy_.get()); quota_manager_proxy_->NotifyStorageModified( - QuotaClientType::kFileSystem, info.origin, + QuotaClientType::kFileSystem, blink::StorageKey(info.origin), FileSystemTypeToQuotaStorageType(info.type), info.delta, base::Time::Now()); } diff --git a/chromium/storage/browser/file_system/quota/quota_backend_impl.h b/chromium/storage/browser/file_system/quota/quota_backend_impl.h index 9103bcf97dc..151b4d6e7da 100644 --- a/chromium/storage/browser/file_system/quota/quota_backend_impl.h +++ b/chromium/storage/browser/file_system/quota/quota_backend_impl.h @@ -32,10 +32,10 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaBackendImpl public: using ReserveQuotaCallback = QuotaReservationManager::ReserveQuotaCallback; - QuotaBackendImpl(base::SequencedTaskRunner* file_task_runner, + QuotaBackendImpl(scoped_refptr<base::SequencedTaskRunner> file_task_runner, ObfuscatedFileUtil* obfuscated_file_util, FileSystemUsageCache* file_system_usage_cache, - QuotaManagerProxy* quota_manager_proxy); + scoped_refptr<QuotaManagerProxy> quota_manager_proxy); ~QuotaBackendImpl() override; // QuotaReservationManager::QuotaBackend overrides. @@ -79,13 +79,13 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaBackendImpl FileSystemType type, base::FilePath* usage_file_path); - scoped_refptr<base::SequencedTaskRunner> file_task_runner_; + const scoped_refptr<base::SequencedTaskRunner> file_task_runner_; // Owned by SandboxFileSystemBackendDelegate. - ObfuscatedFileUtil* obfuscated_file_util_; - FileSystemUsageCache* file_system_usage_cache_; + ObfuscatedFileUtil* const obfuscated_file_util_; + FileSystemUsageCache* const file_system_usage_cache_; - scoped_refptr<QuotaManagerProxy> quota_manager_proxy_; + const scoped_refptr<QuotaManagerProxy> quota_manager_proxy_; base::WeakPtrFactory<QuotaBackendImpl> weak_ptr_factory_{this}; diff --git a/chromium/storage/browser/file_system/quota/quota_backend_impl_unittest.cc b/chromium/storage/browser/file_system/quota/quota_backend_impl_unittest.cc index 84dc3a1af71..b48a4d0e74c 100644 --- a/chromium/storage/browser/file_system/quota/quota_backend_impl_unittest.cc +++ b/chromium/storage/browser/file_system/quota/quota_backend_impl_unittest.cc @@ -50,16 +50,14 @@ class MockQuotaManagerProxy : public QuotaManagerProxy { quota_(0) {} // We don't mock them. - void NotifyOriginInUse(const url::Origin& origin) override {} - void NotifyOriginNoLongerInUse(const url::Origin& origin) override {} void SetUsageCacheEnabled(QuotaClientType client_id, - const url::Origin& origin, + const blink::StorageKey& storage_key, blink::mojom::StorageType type, bool enabled) override {} void NotifyStorageModified( QuotaClientType client_id, - const url::Origin& origin, + const blink::StorageKey& storage_key, blink::mojom::StorageType type, int64_t delta, base::Time modification_time, @@ -73,7 +71,7 @@ class MockQuotaManagerProxy : public QuotaManagerProxy { } void GetUsageAndQuota( - const url::Origin& origin, + const blink::StorageKey& storage_key, blink::mojom::StorageType type, scoped_refptr<base::SequencedTaskRunner> callback_task_runner, UsageAndQuotaCallback callback) override { @@ -110,8 +108,9 @@ class QuotaBackendImplTest : public testing::Test, void SetUp() override { ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); in_memory_env_ = leveldb_chrome::NewMemEnv("quota"); - file_util_.reset(ObfuscatedFileUtil::CreateForTesting( - nullptr, data_dir_.GetPath(), in_memory_env_.get(), is_incognito())); + file_util_ = ObfuscatedFileUtil::CreateForTesting( + /*special_storage_policy=*/nullptr, data_dir_.GetPath(), + in_memory_env_.get(), is_incognito()); backend_ = std::make_unique<QuotaBackendImpl>( file_task_runner(), file_util_.get(), &file_system_usage_cache_, quota_manager_proxy_.get()); diff --git a/chromium/storage/browser/file_system/recursive_operation_delegate.cc b/chromium/storage/browser/file_system/recursive_operation_delegate.cc index 5d3229244da..33179820392 100644 --- a/chromium/storage/browser/file_system/recursive_operation_delegate.cc +++ b/chromium/storage/browser/file_system/recursive_operation_delegate.cc @@ -111,7 +111,7 @@ void RecursiveOperationDelegate::DidReadDirectory(const FileSystemURL& parent, for (size_t i = 0; i < entries.size(); i++) { FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL( - parent.origin(), parent.mount_type(), + parent.storage_key(), parent.mount_type(), parent.virtual_path().Append(entries[i].name)); if (entries[i].type == filesystem::mojom::FsFileType::DIRECTORY) pending_directory_stack_.top().push(url); diff --git a/chromium/storage/browser/file_system/sandbox_directory_database.cc b/chromium/storage/browser/file_system/sandbox_directory_database.cc index 602dfc02a71..c4976a5ec09 100644 --- a/chromium/storage/browser/file_system/sandbox_directory_database.cc +++ b/chromium/storage/browser/file_system/sandbox_directory_database.cc @@ -13,13 +13,13 @@ #include <set> #include "base/containers/stack.h" +#include "base/cxx17_backports.h" #include "base/files/file_enumerator.h" #include "base/files/file_util.h" #include "base/location.h" #include "base/macros.h" #include "base/metrics/histogram_macros.h" #include "base/pickle.h" -#include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "storage/browser/file_system/file_system_usage_cache.h" diff --git a/chromium/storage/browser/file_system/sandbox_file_stream_reader_unittest.cc b/chromium/storage/browser/file_system/sandbox_file_stream_reader_unittest.cc index 105920bce2d..ffc9dc6d58b 100644 --- a/chromium/storage/browser/file_system/sandbox_file_stream_reader_unittest.cc +++ b/chromium/storage/browser/file_system/sandbox_file_stream_reader_unittest.cc @@ -15,7 +15,6 @@ #include "base/files/scoped_temp_dir.h" #include "base/macros.h" #include "base/run_loop.h" -#include "base/stl_util.h" #include "base/test/task_environment.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" @@ -25,9 +24,11 @@ #include "storage/browser/file_system/file_stream_test_utils.h" #include "storage/browser/file_system/file_system_context.h" #include "storage/browser/file_system/file_system_file_util.h" +#include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/test/async_file_test_helper.h" #include "storage/browser/test/test_file_system_context.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "url/gurl.h" #include "url/origin.h" @@ -44,12 +45,12 @@ class SandboxFileStreamReaderTest : public FileStreamReaderTest { void SetUp() override { ASSERT_TRUE(dir_.CreateUniqueTempDir()); - file_system_context_ = - CreateFileSystemContextForTesting(nullptr, dir_.GetPath()); + file_system_context_ = CreateFileSystemContextForTesting( + /*quota_manager_proxy=*/nullptr, dir_.GetPath()); file_system_context_->OpenFileSystem( - url::Origin::Create(GURL(kURLOrigin)), kFileSystemTypeTemporary, - OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, + blink::StorageKey::CreateFromStringForTesting(kURLOrigin), + kFileSystemTypeTemporary, OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, base::BindOnce([](const GURL& root_url, const std::string& name, base::File::Error result) { ASSERT_EQ(base::File::FILE_OK, result); @@ -101,8 +102,8 @@ class SandboxFileStreamReaderTest : public FileStreamReaderTest { FileSystemURL GetFileSystemURL(const std::string& file_name) { return file_system_context_->CreateCrackedFileSystemURL( - url::Origin::Create(GURL(kURLOrigin)), kFileSystemTypeTemporary, - base::FilePath().AppendASCII(file_name)); + blink::StorageKey::CreateFromStringForTesting(kURLOrigin), + kFileSystemTypeTemporary, base::FilePath().AppendASCII(file_name)); } private: 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 d08773d17d5..4e8fafcac34 100644 --- a/chromium/storage/browser/file_system/sandbox_file_stream_writer.cc +++ b/chromium/storage/browser/file_system/sandbox_file_stream_writer.cc @@ -19,11 +19,13 @@ #include "storage/browser/file_system/file_observers.h" #include "storage/browser/file_system/file_system_context.h" #include "storage/browser/file_system/file_system_operation_runner.h" +#include "storage/browser/file_system/file_system_util.h" #include "storage/browser/file_system/memory_file_stream_writer.h" #include "storage/browser/file_system/obfuscated_file_util_memory_delegate.h" #include "storage/browser/file_system/plugin_private_file_system_backend.h" #include "storage/browser/quota/quota_manager_proxy.h" #include "storage/common/file_system/file_system_util.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" namespace storage { @@ -177,7 +179,8 @@ void SandboxFileStreamWriter::DidCreateSnapshotFile( DCHECK(quota_manager_proxy); quota_manager_proxy->GetUsageAndQuota( - url_.origin(), FileSystemTypeToQuotaStorageType(url_.type()), + blink::StorageKey(url_.origin()), + FileSystemTypeToQuotaStorageType(url_.type()), base::SequencedTaskRunnerHandle::Get(), base::BindOnce(&SandboxFileStreamWriter::DidGetUsageAndQuota, weak_factory_.GetWeakPtr(), std::move(callback))); @@ -228,7 +231,7 @@ void SandboxFileStreamWriter::DidWrite(int write_response) { QuotaManagerProxy* quota_manager_proxy = file_system_context_->quota_manager_proxy(); if (quota_manager_proxy) { - quota_manager_proxy->NotifyWriteFailed(url_.origin()); + quota_manager_proxy->NotifyWriteFailed(blink::StorageKey(url_.origin())); } if (CancelIfRequested()) return; diff --git a/chromium/storage/browser/file_system/sandbox_file_stream_writer_unittest.cc b/chromium/storage/browser/file_system/sandbox_file_stream_writer_unittest.cc index 8678c9f22ca..f133512f99d 100644 --- a/chromium/storage/browser/file_system/sandbox_file_stream_writer_unittest.cc +++ b/chromium/storage/browser/file_system/sandbox_file_stream_writer_unittest.cc @@ -22,11 +22,13 @@ #include "storage/browser/file_system/file_stream_test_utils.h" #include "storage/browser/file_system/file_stream_writer.h" #include "storage/browser/file_system/file_system_context.h" +#include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/test/async_file_test_helper.h" #include "storage/browser/test/mock_quota_manager_proxy.h" #include "storage/browser/test/mock_special_storage_policy.h" #include "storage/browser/test/test_file_system_context.h" #include "storage/common/file_system/file_system_types.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" namespace storage { @@ -51,8 +53,8 @@ class SandboxFileStreamWriterTest : public FileStreamWriterTest { CreateFileSystemContext(quota_manager_proxy_.get(), dir_); file_system_context_->OpenFileSystem( - url::Origin::Create(GURL(kURLOrigin)), kFileSystemTypeTemporary, - OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, + blink::StorageKey::CreateFromStringForTesting(kURLOrigin), + kFileSystemTypeTemporary, OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, base::BindOnce([](const GURL& root_url, const std::string& name, base::File::Error result) { ASSERT_EQ(base::File::FILE_OK, result); @@ -63,8 +65,8 @@ class SandboxFileStreamWriterTest : public FileStreamWriterTest { } void TearDown() override { - quota_manager_proxy_->SimulateQuotaManagerDestroyed(); - quota_manager_.reset(); + quota_manager_proxy_ = nullptr; + quota_manager_ = nullptr; base::RunLoop().RunUntilIdle(); } @@ -80,7 +82,7 @@ class SandboxFileStreamWriterTest : public FileStreamWriterTest { int64_t quota; }; - virtual FileSystemContext* CreateFileSystemContext( + virtual scoped_refptr<FileSystemContext> CreateFileSystemContext( QuotaManagerProxy* quota_manager_proxy, const base::ScopedTempDir& dir) { return CreateFileSystemContextForTesting(quota_manager_proxy, @@ -91,8 +93,8 @@ class SandboxFileStreamWriterTest : public FileStreamWriterTest { FileSystemURL GetFileSystemURL(const std::string& file_name) { return file_system_context_->CreateCrackedFileSystemURL( - url::Origin::Create(GURL(kURLOrigin)), kFileSystemTypeTemporary, - base::FilePath().AppendASCII(file_name)); + blink::StorageKey::CreateFromStringForTesting(kURLOrigin), + kFileSystemTypeTemporary, base::FilePath().AppendASCII(file_name)); } bool CreateFileWithContent(const std::string& name, @@ -148,7 +150,7 @@ class SandboxFileStreamWriterTest : public FileStreamWriterTest { quota_usage_and_info GetUsageAndQuotaSync() { quota_usage_and_info info; quota_manager_->GetUsageAndQuota( - url::Origin::Create(GURL(kURLOrigin)), + blink::StorageKey::CreateFromStringForTesting(kURLOrigin), blink::mojom::StorageType::kTemporary, base::BindLambdaForTesting([&](blink::mojom::QuotaStatusCode status, int64_t usage, int64_t quota) { @@ -160,8 +162,9 @@ class SandboxFileStreamWriterTest : public FileStreamWriterTest { } void SetQuota(int64_t quota) { - quota_manager_->SetQuota(url::Origin::Create(GURL(kURLOrigin)), - blink::mojom::StorageType::kTemporary, quota); + quota_manager_->SetQuota( + blink::StorageKey::CreateFromStringForTesting(kURLOrigin), + blink::mojom::StorageType::kTemporary, quota); } int64_t GetFreeQuota() { @@ -320,7 +323,7 @@ class SandboxFileStreamWriterIncognitoTest SandboxFileStreamWriterIncognitoTest() = default; protected: - FileSystemContext* CreateFileSystemContext( + scoped_refptr<FileSystemContext> CreateFileSystemContext( QuotaManagerProxy* quota_manager_proxy, const base::ScopedTempDir& dir) override { return CreateIncognitoFileSystemContextForTesting( @@ -364,4 +367,4 @@ INSTANTIATE_TYPED_TEST_SUITE_P(SandboxIncognito, FileStreamWriterTypedTest, SandboxFileStreamWriterIncognitoTest); -} // namespace storage
\ No newline at end of file +} // namespace storage diff --git a/chromium/storage/browser/file_system/sandbox_file_system_backend_delegate.cc b/chromium/storage/browser/file_system/sandbox_file_system_backend_delegate.cc index 9402dc66a1a..7db7a96717d 100644 --- a/chromium/storage/browser/file_system/sandbox_file_system_backend_delegate.cc +++ b/chromium/storage/browser/file_system/sandbox_file_system_backend_delegate.cc @@ -24,6 +24,7 @@ #include "storage/browser/file_system/file_system_operation_context.h" #include "storage/browser/file_system/file_system_url.h" #include "storage/browser/file_system/file_system_usage_cache.h" +#include "storage/browser/file_system/file_system_util.h" #include "storage/browser/file_system/obfuscated_file_util.h" #include "storage/browser/file_system/obfuscated_file_util_memory_delegate.h" #include "storage/browser/file_system/quota/quota_backend_impl.h" @@ -35,6 +36,8 @@ #include "storage/browser/file_system/sandbox_quota_observer.h" #include "storage/browser/quota/quota_manager_proxy.h" #include "storage/common/file_system/file_system_util.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" +#include "url/gurl.h" #include "url/origin.h" namespace storage { @@ -177,14 +180,14 @@ std::string SandboxFileSystemBackendDelegate::GetTypeString( } SandboxFileSystemBackendDelegate::SandboxFileSystemBackendDelegate( - QuotaManagerProxy* quota_manager_proxy, - base::SequencedTaskRunner* file_task_runner, + scoped_refptr<QuotaManagerProxy> quota_manager_proxy, + scoped_refptr<base::SequencedTaskRunner> file_task_runner, const base::FilePath& profile_path, - SpecialStoragePolicy* special_storage_policy, + scoped_refptr<SpecialStoragePolicy> special_storage_policy, const FileSystemOptions& file_system_options, leveldb::Env* env_override) - : file_task_runner_(file_task_runner), - quota_manager_proxy_(quota_manager_proxy), + : file_task_runner_(std::move(file_task_runner)), + quota_manager_proxy_(std::move(quota_manager_proxy)), sandbox_file_util_(std::make_unique<AsyncFileUtilAdapter>( std::make_unique<ObfuscatedFileUtil>( special_storage_policy, @@ -197,19 +200,18 @@ SandboxFileSystemBackendDelegate::SandboxFileSystemBackendDelegate( file_system_usage_cache_(std::make_unique<FileSystemUsageCache>( file_system_options.is_incognito())), quota_observer_( - std::make_unique<SandboxQuotaObserver>(quota_manager_proxy, - file_task_runner, + std::make_unique<SandboxQuotaObserver>(quota_manager_proxy_, + file_task_runner_, obfuscated_file_util(), usage_cache())), quota_reservation_manager_(std::make_unique<QuotaReservationManager>( - std::make_unique<QuotaBackendImpl>(file_task_runner_.get(), + std::make_unique<QuotaBackendImpl>(file_task_runner_, obfuscated_file_util(), usage_cache(), - quota_manager_proxy))), - special_storage_policy_(special_storage_policy), + quota_manager_proxy_))), + special_storage_policy_(std::move(special_storage_policy)), file_system_options_(file_system_options), - is_filesystem_opened_(false) { -} + is_filesystem_opened_(false) {} SandboxFileSystemBackendDelegate::~SandboxFileSystemBackendDelegate() { DETACH_FROM_THREAD(io_thread_checker_); @@ -258,7 +260,7 @@ void SandboxFileSystemBackendDelegate::OpenFileSystem( base::OnceClosure quota_callback = (quota_manager_proxy_.get()) ? base::BindOnce(&QuotaManagerProxy::NotifyStorageAccessed, - quota_manager_proxy_, origin, + quota_manager_proxy_, blink::StorageKey(origin), FileSystemTypeToQuotaStorageType(type), base::Time::Now()) : base::DoNothing(); @@ -337,9 +339,9 @@ SandboxFileSystemBackendDelegate::DeleteOriginDataOnFileTaskRunner( bool result = obfuscated_file_util()->DeleteDirectoryForOriginAndType( origin, GetTypeString(type)); if (result && proxy && usage) { - proxy->NotifyStorageModified(QuotaClientType::kFileSystem, origin, - FileSystemTypeToQuotaStorageType(type), -usage, - base::Time::Now()); + proxy->NotifyStorageModified( + QuotaClientType::kFileSystem, blink::StorageKey(origin), + FileSystemTypeToQuotaStorageType(type), -usage, base::Time::Now()); } if (result) @@ -612,8 +614,8 @@ int64_t SandboxFileSystemBackendDelegate::RecalculateUsage( const url::Origin& origin, FileSystemType type) { FileSystemOperationContext operation_context(context); - FileSystemURL url = - context->CreateCrackedFileSystemURL(origin, type, base::FilePath()); + FileSystemURL url = context->CreateCrackedFileSystemURL( + blink::StorageKey(origin), type, base::FilePath()); std::unique_ptr<FileSystemFileUtil::AbstractFileEnumerator> enumerator( obfuscated_file_util()->CreateFileEnumerator(&operation_context, url, true)); @@ -706,15 +708,15 @@ SandboxFileSystemBackendDelegate::memory_file_util_delegate() { // Declared in obfuscated_file_util.h. // static -ObfuscatedFileUtil* ObfuscatedFileUtil::CreateForTesting( - SpecialStoragePolicy* special_storage_policy, +std::unique_ptr<ObfuscatedFileUtil> ObfuscatedFileUtil::CreateForTesting( + scoped_refptr<SpecialStoragePolicy> special_storage_policy, const base::FilePath& file_system_directory, leveldb::Env* env_override, bool is_incognito) { - return new ObfuscatedFileUtil(special_storage_policy, file_system_directory, - env_override, - base::BindRepeating(&GetTypeStringForURL), - GetKnownTypeStrings(), nullptr, is_incognito); + return std::make_unique<ObfuscatedFileUtil>( + std::move(special_storage_policy), file_system_directory, env_override, + base::BindRepeating(&GetTypeStringForURL), GetKnownTypeStrings(), + /*sandbox_delegate=*/nullptr, is_incognito); } } // namespace storage diff --git a/chromium/storage/browser/file_system/sandbox_file_system_backend_delegate.h b/chromium/storage/browser/file_system/sandbox_file_system_backend_delegate.h index e8d445e1c9e..1c730d79450 100644 --- a/chromium/storage/browser/file_system/sandbox_file_system_backend_delegate.h +++ b/chromium/storage/browser/file_system/sandbox_file_system_backend_delegate.h @@ -16,7 +16,6 @@ #include "base/component_export.h" #include "base/files/file_path.h" -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" @@ -25,6 +24,7 @@ #include "storage/browser/file_system/file_system_options.h" #include "storage/browser/file_system/file_system_quota_util.h" #include "storage/browser/file_system/task_runner_bound_observer_list.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { class SequencedTaskRunner; @@ -73,7 +73,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) SandboxFileSystemBackendDelegate // An instance of this interface is assumed to be called on the file thread. class OriginEnumerator { public: - virtual ~OriginEnumerator() {} + OriginEnumerator(const OriginEnumerator&) = delete; + OriginEnumerator& operator=(const OriginEnumerator&) = delete; + virtual ~OriginEnumerator() = default; // Returns the next origin. Returns absl::nullopt if there are no more // origins. @@ -81,18 +83,26 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) SandboxFileSystemBackendDelegate // Returns the current origin's information. virtual bool HasFileSystemType(FileSystemType type) const = 0; + + protected: + OriginEnumerator() = default; }; // Returns the type directory name in sandbox directory for given |type|. static std::string GetTypeString(FileSystemType type); - SandboxFileSystemBackendDelegate(QuotaManagerProxy* quota_manager_proxy, - base::SequencedTaskRunner* file_task_runner, - const base::FilePath& profile_path, - SpecialStoragePolicy* special_storage_policy, - const FileSystemOptions& file_system_options, - leveldb::Env* env_override); - + SandboxFileSystemBackendDelegate( + scoped_refptr<QuotaManagerProxy> quota_manager_proxy, + scoped_refptr<base::SequencedTaskRunner> file_task_runner, + const base::FilePath& profile_path, + scoped_refptr<SpecialStoragePolicy> special_storage_policy, + const FileSystemOptions& file_system_options, + leveldb::Env* env_override); + + SandboxFileSystemBackendDelegate(const SandboxFileSystemBackendDelegate&) = + delete; + SandboxFileSystemBackendDelegate& operator=( + const SandboxFileSystemBackendDelegate&) = delete; ~SandboxFileSystemBackendDelegate() override; // Returns an origin enumerator of sandbox filesystem. @@ -237,15 +247,15 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) SandboxFileSystemBackendDelegate ObfuscatedFileUtil* obfuscated_file_util(); - scoped_refptr<base::SequencedTaskRunner> file_task_runner_; - scoped_refptr<QuotaManagerProxy> quota_manager_proxy_; + const scoped_refptr<base::SequencedTaskRunner> file_task_runner_; + const scoped_refptr<QuotaManagerProxy> quota_manager_proxy_; std::unique_ptr<AsyncFileUtil> sandbox_file_util_; std::unique_ptr<FileSystemUsageCache> file_system_usage_cache_; std::unique_ptr<SandboxQuotaObserver> quota_observer_; std::unique_ptr<QuotaReservationManager> quota_reservation_manager_; - scoped_refptr<SpecialStoragePolicy> special_storage_policy_; + const scoped_refptr<SpecialStoragePolicy> special_storage_policy_; FileSystemOptions file_system_options_; @@ -264,8 +274,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) SandboxFileSystemBackendDelegate base::Time next_release_time_for_open_filesystem_stat_; base::WeakPtrFactory<SandboxFileSystemBackendDelegate> weak_factory_{this}; - - DISALLOW_COPY_AND_ASSIGN(SandboxFileSystemBackendDelegate); }; } // namespace storage diff --git a/chromium/storage/browser/file_system/sandbox_file_system_backend_delegate_unittest.cc b/chromium/storage/browser/file_system/sandbox_file_system_backend_delegate_unittest.cc index b480ff2e4a6..941c8495296 100644 --- a/chromium/storage/browser/file_system/sandbox_file_system_backend_delegate_unittest.cc +++ b/chromium/storage/browser/file_system/sandbox_file_system_backend_delegate_unittest.cc @@ -16,6 +16,7 @@ #include "storage/browser/test/mock_quota_manager_proxy.h" #include "storage/browser/test/test_file_system_options.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "url/gurl.h" #include "url/origin.h" @@ -24,10 +25,9 @@ namespace storage { namespace { FileSystemURL CreateFileSystemURL(const char* path) { - const GURL kOrigin("http://foo/"); - return FileSystemURL::CreateForTest(url::Origin::Create(kOrigin), - kFileSystemTypeTemporary, - base::FilePath::FromUTF8Unsafe(path)); + return FileSystemURL::CreateForTest( + blink::StorageKey::CreateFromStringForTesting("http://foo/"), + kFileSystemTypeTemporary, base::FilePath::FromUTF8Unsafe(path)); } } // namespace @@ -94,8 +94,8 @@ TEST_F(SandboxFileSystemBackendDelegateTest, IsAccessValid) { // Access from non-allowed scheme should be disallowed. EXPECT_FALSE(IsAccessValid(FileSystemURL::CreateForTest( - url::Origin::Create(GURL("unknown://bar")), kFileSystemTypeTemporary, - base::FilePath::FromUTF8Unsafe("foo")))); + blink::StorageKey::CreateFromStringForTesting("unknown://bar"), + kFileSystemTypeTemporary, base::FilePath::FromUTF8Unsafe("foo")))); // Access with restricted name should be disallowed. EXPECT_FALSE(IsAccessValid(CreateFileSystemURL("."))); @@ -131,8 +131,8 @@ TEST_F(SandboxFileSystemBackendDelegateTest, OpenFileSystemAccessesStorage) { EXPECT_EQ(callback_count(), 1); EXPECT_EQ(last_error(), base::File::FILE_OK); EXPECT_EQ(quota_manager_proxy()->notify_storage_accessed_count(), 1); - EXPECT_EQ(quota_manager_proxy()->last_notified_origin(), - url::Origin::Create(origin)); + EXPECT_EQ(quota_manager_proxy()->last_notified_storage_key(), + blink::StorageKey(url::Origin::Create(origin))); EXPECT_EQ(quota_manager_proxy()->last_notified_type(), blink::mojom::StorageType::kTemporary); } diff --git a/chromium/storage/browser/file_system/sandbox_file_system_backend_unittest.cc b/chromium/storage/browser/file_system/sandbox_file_system_backend_unittest.cc index 76b7c845fb6..2a6cb0ec661 100644 --- a/chromium/storage/browser/file_system/sandbox_file_system_backend_unittest.cc +++ b/chromium/storage/browser/file_system/sandbox_file_system_backend_unittest.cc @@ -11,11 +11,11 @@ #include <vector> #include "base/bind.h" +#include "base/cxx17_backports.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/macros.h" #include "base/run_loop.h" -#include "base/stl_util.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "base/threading/thread_task_runner_handle.h" @@ -23,9 +23,11 @@ #include "storage/browser/file_system/file_system_features.h" #include "storage/browser/file_system/file_system_url.h" #include "storage/browser/file_system/sandbox_file_system_backend_delegate.h" +#include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/test/test_file_system_options.h" #include "storage/common/file_system/file_system_util.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/leveldatabase/leveldb_chrome.h" #include "url/gurl.h" #include "url/origin.h" @@ -92,9 +94,9 @@ class SandboxFileSystemBackendTest void SetUpNewDelegate(const FileSystemOptions& options) { incognito_env_override_ = leveldb_chrome::NewMemEnv("FileSystem"); delegate_ = std::make_unique<SandboxFileSystemBackendDelegate>( - nullptr /* quota_manager_proxy */, - base::ThreadTaskRunnerHandle::Get().get(), data_dir_.GetPath(), - nullptr /* special_storage_policy */, options, + /*quota_manager_proxy=*/nullptr, base::ThreadTaskRunnerHandle::Get(), + data_dir_.GetPath(), + /*special_storage_policy=*/nullptr, options, options.is_in_memory() ? incognito_env_override_.get() : nullptr); } @@ -121,8 +123,9 @@ class SandboxFileSystemBackendTest base::FilePath* root_path) { base::File::Error error = base::File::FILE_OK; backend_->ResolveURL( - FileSystemURL::CreateForTest(url::Origin::Create(GURL(origin_url)), - type, base::FilePath()), + FileSystemURL::CreateForTest( + blink::StorageKey::CreateFromStringForTesting(origin_url), type, + base::FilePath()), mode, base::BindOnce(&DidOpenFileSystem, &error)); base::RunLoop().RunUntilIdle(); if (error != base::File::FILE_OK) diff --git a/chromium/storage/browser/file_system/sandbox_origin_database_interface.h b/chromium/storage/browser/file_system/sandbox_origin_database_interface.h index 478cfdacdf5..694d8318de7 100644 --- a/chromium/storage/browser/file_system/sandbox_origin_database_interface.h +++ b/chromium/storage/browser/file_system/sandbox_origin_database_interface.h @@ -24,7 +24,11 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) SandboxOriginDatabaseInterface { ~OriginRecord(); }; - virtual ~SandboxOriginDatabaseInterface() {} + SandboxOriginDatabaseInterface(const SandboxOriginDatabaseInterface&) = + delete; + SandboxOriginDatabaseInterface& operator=( + const SandboxOriginDatabaseInterface&) = delete; + virtual ~SandboxOriginDatabaseInterface() = default; // Returns true if the origin's path is included in this database. virtual bool HasOriginPath(const std::string& origin) = 0; @@ -50,7 +54,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) SandboxOriginDatabaseInterface { virtual void RewriteDatabase() = 0; protected: - SandboxOriginDatabaseInterface() {} + SandboxOriginDatabaseInterface() = default; }; } // namespace storage diff --git a/chromium/storage/browser/file_system/sandbox_origin_database_unittest.cc b/chromium/storage/browser/file_system/sandbox_origin_database_unittest.cc index f9b1aa4e493..5b99ecd11eb 100644 --- a/chromium/storage/browser/file_system/sandbox_origin_database_unittest.cc +++ b/chromium/storage/browser/file_system/sandbox_origin_database_unittest.cc @@ -11,12 +11,12 @@ #include <string> #include <vector> +#include "base/cxx17_backports.h" #include "base/files/file.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/macros.h" -#include "base/stl_util.h" #include "storage/browser/file_system/sandbox_origin_database.h" #include "storage/browser/test/sandbox_database_test_helper.h" #include "storage/common/file_system/file_system_util.h" diff --git a/chromium/storage/browser/file_system/sandbox_quota_observer.cc b/chromium/storage/browser/file_system/sandbox_quota_observer.cc index 10b0616eb76..9e43d5e6e5f 100644 --- a/chromium/storage/browser/file_system/sandbox_quota_observer.cc +++ b/chromium/storage/browser/file_system/sandbox_quota_observer.cc @@ -7,22 +7,25 @@ #include <stdint.h> #include "base/bind.h" +#include "base/memory/scoped_refptr.h" #include "base/sequenced_task_runner.h" #include "storage/browser/file_system/file_system_usage_cache.h" +#include "storage/browser/file_system/file_system_util.h" #include "storage/browser/file_system/sandbox_file_system_backend_delegate.h" -#include "storage/browser/quota/quota_client.h" +#include "storage/browser/quota/quota_client_type.h" #include "storage/browser/quota/quota_manager_proxy.h" #include "storage/common/file_system/file_system_util.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" namespace storage { SandboxQuotaObserver::SandboxQuotaObserver( - QuotaManagerProxy* quota_manager_proxy, - base::SequencedTaskRunner* update_notify_runner, + scoped_refptr<QuotaManagerProxy> quota_manager_proxy, + scoped_refptr<base::SequencedTaskRunner> update_notify_runner, ObfuscatedFileUtil* sandbox_file_util, FileSystemUsageCache* file_system_usage_cache) - : quota_manager_proxy_(quota_manager_proxy), - update_notify_runner_(update_notify_runner), + : quota_manager_proxy_(std::move(quota_manager_proxy)), + update_notify_runner_(std::move(update_notify_runner)), sandbox_file_util_(sandbox_file_util), file_system_usage_cache_(file_system_usage_cache) {} @@ -41,7 +44,7 @@ void SandboxQuotaObserver::OnUpdate(const FileSystemURL& url, int64_t delta) { if (quota_manager_proxy_.get()) { quota_manager_proxy_->NotifyStorageModified( - QuotaClientType::kFileSystem, url.origin(), + QuotaClientType::kFileSystem, blink::StorageKey(url.origin()), FileSystemTypeToQuotaStorageType(url.type()), delta, base::Time::Now()); } @@ -78,8 +81,8 @@ void SandboxQuotaObserver::OnEndUpdate(const FileSystemURL& url) { void SandboxQuotaObserver::OnAccess(const FileSystemURL& url) { if (quota_manager_proxy_.get()) { quota_manager_proxy_->NotifyStorageAccessed( - url.origin(), FileSystemTypeToQuotaStorageType(url.type()), - base::Time::Now()); + blink::StorageKey(url.origin()), + FileSystemTypeToQuotaStorageType(url.type()), base::Time::Now()); } } @@ -88,7 +91,7 @@ void SandboxQuotaObserver::SetUsageCacheEnabled(const url::Origin& origin, bool enabled) { if (quota_manager_proxy_.get()) { quota_manager_proxy_->SetUsageCacheEnabled( - QuotaClientType::kFileSystem, origin, + QuotaClientType::kFileSystem, blink::StorageKey(origin), FileSystemTypeToQuotaStorageType(type), enabled); } } diff --git a/chromium/storage/browser/file_system/sandbox_quota_observer.h b/chromium/storage/browser/file_system/sandbox_quota_observer.h index 37110196568..2be5fe4b505 100644 --- a/chromium/storage/browser/file_system/sandbox_quota_observer.h +++ b/chromium/storage/browser/file_system/sandbox_quota_observer.h @@ -13,6 +13,7 @@ #include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/timer/timer.h" #include "storage/browser/file_system/file_observers.h" @@ -36,10 +37,11 @@ class QuotaManagerProxy; class SandboxQuotaObserver : public FileUpdateObserver, public FileAccessObserver { public: - SandboxQuotaObserver(QuotaManagerProxy* quota_manager_proxy, - base::SequencedTaskRunner* update_notify_runner, - ObfuscatedFileUtil* sandbox_file_util, - FileSystemUsageCache* file_system_usage_cache_); + SandboxQuotaObserver( + scoped_refptr<QuotaManagerProxy> quota_manager_proxy, + scoped_refptr<base::SequencedTaskRunner> update_notify_runner, + ObfuscatedFileUtil* sandbox_file_util, + FileSystemUsageCache* file_system_usage_cache_); ~SandboxQuotaObserver() override; // FileUpdateObserver overrides. @@ -61,14 +63,14 @@ class SandboxQuotaObserver : public FileUpdateObserver, base::FilePath GetUsageCachePath(const FileSystemURL& url); - scoped_refptr<QuotaManagerProxy> quota_manager_proxy_; - scoped_refptr<base::SequencedTaskRunner> update_notify_runner_; + const scoped_refptr<QuotaManagerProxy> quota_manager_proxy_; + const scoped_refptr<base::SequencedTaskRunner> update_notify_runner_; // Not owned; sandbox_file_util_ should have identical lifetime with this. - ObfuscatedFileUtil* sandbox_file_util_; + ObfuscatedFileUtil* const sandbox_file_util_; // Not owned; file_system_usage_cache_ should have longer lifetime than this. - FileSystemUsageCache* file_system_usage_cache_; + FileSystemUsageCache* const file_system_usage_cache_; std::map<base::FilePath, int64_t> pending_update_notification_; base::OneShotTimer delayed_cache_update_helper_; diff --git a/chromium/storage/browser/file_system/task_runner_bound_observer_list.h b/chromium/storage/browser/file_system/task_runner_bound_observer_list.h index d5cd1d7f286..52831803d04 100644 --- a/chromium/storage/browser/file_system/task_runner_bound_observer_list.h +++ b/chromium/storage/browser/file_system/task_runner_bound_observer_list.h @@ -30,13 +30,16 @@ class TaskRunnerBoundObserverList { std::map<Observer*, scoped_refptr<base::SequencedTaskRunner>>; // Creates an empty list. - TaskRunnerBoundObserverList() {} + TaskRunnerBoundObserverList() = default; // Creates a new list with given |observers|. explicit TaskRunnerBoundObserverList(const ObserversListMap& observers) : observers_(observers) {} - virtual ~TaskRunnerBoundObserverList() {} + TaskRunnerBoundObserverList(const TaskRunnerBoundObserverList&) = default; + TaskRunnerBoundObserverList& operator=(const TaskRunnerBoundObserverList&) = + default; + virtual ~TaskRunnerBoundObserverList() = default; // Returns a new observer list with given observer. // It is valid to give nullptr as |runner_to_notify|, and in that case diff --git a/chromium/storage/browser/file_system/transient_file_util_unittest.cc b/chromium/storage/browser/file_system/transient_file_util_unittest.cc index 29f61d9d334..3d4fa9490a0 100644 --- a/chromium/storage/browser/file_system/transient_file_util_unittest.cc +++ b/chromium/storage/browser/file_system/transient_file_util_unittest.cc @@ -16,10 +16,11 @@ #include "storage/browser/file_system/file_system_operation_context.h" #include "storage/browser/file_system/isolated_context.h" #include "storage/browser/file_system/transient_file_util.h" +#include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/test/test_file_system_context.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "url/gurl.h" -#include "url/origin.h" namespace storage { @@ -30,7 +31,8 @@ class TransientFileUtilTest : public testing::Test { void SetUp() override { file_system_context_ = CreateFileSystemContextForTesting( - nullptr, base::FilePath(FILE_PATH_LITERAL("dummy"))); + /*quota_manager_proxy=*/nullptr, + base::FilePath(FILE_PATH_LITERAL("dummy"))); transient_file_util_ = std::make_unique<TransientFileUtil>(); ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); @@ -55,8 +57,8 @@ class TransientFileUtilTest : public testing::Test { isolated_context->CreateVirtualRootPath(filesystem->id()) .AppendASCII(name); *file_url = file_system_context_->CreateCrackedFileSystemURL( - url::Origin::Create(GURL("http://foo")), kFileSystemTypeIsolated, - virtual_path); + blink::StorageKey::CreateFromStringForTesting("http://foo"), + kFileSystemTypeIsolated, virtual_path); } std::unique_ptr<FileSystemOperationContext> NewOperationContext() { diff --git a/chromium/storage/browser/file_system/watcher_manager.h b/chromium/storage/browser/file_system/watcher_manager.h index 5d6ad91d7f7..5e30baca26f 100644 --- a/chromium/storage/browser/file_system/watcher_manager.h +++ b/chromium/storage/browser/file_system/watcher_manager.h @@ -28,7 +28,9 @@ class WatcherManager { using NotificationCallback = base::RepeatingCallback<void(ChangeType change_type)>; - virtual ~WatcherManager() {} + WatcherManager(const WatcherManager&) = delete; + WatcherManager& operator=(const WatcherManager&) = delete; + virtual ~WatcherManager() = default; // Adds an entry watcher. If the |recursive| mode is not supported then // FILE_ERROR_INVALID_OPERATION must be returned as an error. If the |url| is @@ -50,6 +52,9 @@ class WatcherManager { virtual void RemoveWatcher(const FileSystemURL& url, bool recursive, StatusCallback callback) = 0; + + protected: + WatcherManager() = default; }; } // namespace storage diff --git a/chromium/storage/browser/quota/DIR_METADATA b/chromium/storage/browser/quota/DIR_METADATA index 58c664b8940..f3365fa6fce 100644 --- a/chromium/storage/browser/quota/DIR_METADATA +++ b/chromium/storage/browser/quota/DIR_METADATA @@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Blink>Storage>Quota" diff --git a/chromium/storage/browser/quota/OWNERS b/chromium/storage/browser/quota/OWNERS index fc8d259ae9c..8e88df27dc1 100644 --- a/chromium/storage/browser/quota/OWNERS +++ b/chromium/storage/browser/quota/OWNERS @@ -6,5 +6,4 @@ jarrydg@chromium.org jsbell@chromium.org kinuko@chromium.org mek@chromium.org -nhiroki@chromium.org pwnall@chromium.org diff --git a/chromium/storage/browser/quota/client_usage_tracker.cc b/chromium/storage/browser/quota/client_usage_tracker.cc index d6f715da30b..879748f212b 100644 --- a/chromium/storage/browser/quota/client_usage_tracker.cc +++ b/chromium/storage/browser/quota/client_usage_tracker.cc @@ -10,12 +10,13 @@ #include "base/callback_helpers.h" #include "base/containers/contains.h" #include "base/metrics/histogram_macros.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" namespace storage { namespace { -using OriginSetByHost = ClientUsageTracker::OriginSetByHost; +using StorageKeySetByHost = ClientUsageTracker::StorageKeySetByHost; void DidGetHostUsage(UsageCallback callback, int64_t limited_usage, @@ -25,26 +26,26 @@ void DidGetHostUsage(UsageCallback callback, std::move(callback).Run(limited_usage + unlimited_usage); } -bool EraseOriginFromOriginSet(OriginSetByHost* origins_by_host, - const std::string& host, - const url::Origin& origin) { - auto it = origins_by_host->find(host); - if (it == origins_by_host->end()) +bool EraseStorageKeyFromStorageKeySet(StorageKeySetByHost* storage_keys_by_host, + const std::string& host, + const blink::StorageKey& storage_key) { + auto it = storage_keys_by_host->find(host); + if (it == storage_keys_by_host->end()) return false; - if (!it->second.erase(origin)) + if (!it->second.erase(storage_key)) return false; if (it->second.empty()) - origins_by_host->erase(host); + storage_keys_by_host->erase(host); return true; } -bool OriginSetContainsOrigin(const OriginSetByHost& origins, - const std::string& host, - const url::Origin& origin) { - auto itr = origins.find(host); - return itr != origins.end() && base::Contains(itr->second, origin); +bool StorageKeySetContainsStorageKey(const StorageKeySetByHost& storage_keys, + const std::string& host, + const blink::StorageKey& storage_key) { + auto itr = storage_keys.find(host); + return itr != storage_keys.end() && base::Contains(itr->second, storage_key); } void RecordSkippedOriginHistogram(const InvalidOriginReason reason) { @@ -67,10 +68,10 @@ struct ClientUsageTracker::AccumulateInfo { ClientUsageTracker::ClientUsageTracker( UsageTracker* tracker, - scoped_refptr<QuotaClient> client, + mojom::QuotaClient* client, blink::mojom::StorageType type, scoped_refptr<SpecialStoragePolicy> special_storage_policy) - : client_(std::move(client)), + : client_(client), type_(type), global_limited_usage_(0), global_unlimited_usage_(0), @@ -90,24 +91,25 @@ ClientUsageTracker::~ClientUsageTracker() { void ClientUsageTracker::GetGlobalUsage(GlobalUsageCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (global_usage_retrieved_ && - non_cached_limited_origins_by_host_.empty() && - non_cached_unlimited_origins_by_host_.empty()) { + non_cached_limited_storage_keys_by_host_.empty() && + non_cached_unlimited_storage_keys_by_host_.empty()) { std::move(callback).Run(global_limited_usage_ + global_unlimited_usage_, global_unlimited_usage_); return; } - client_->GetOriginsForType( - type_, base::BindOnce(&ClientUsageTracker::DidGetOriginsForGlobalUsage, - weak_factory_.GetWeakPtr(), std::move(callback))); + client_->GetStorageKeysForType( + type_, + base::BindOnce(&ClientUsageTracker::DidGetStorageKeysForGlobalUsage, + weak_factory_.GetWeakPtr(), std::move(callback))); } void ClientUsageTracker::GetHostUsage(const std::string& host, UsageCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (base::Contains(cached_hosts_, host) && - !base::Contains(non_cached_limited_origins_by_host_, host) && - !base::Contains(non_cached_unlimited_origins_by_host_, host)) { + !base::Contains(non_cached_limited_storage_keys_by_host_, host) && + !base::Contains(non_cached_unlimited_storage_keys_by_host_, host)) { // TODO(kinuko): Drop host_usage_map_ cache periodically. std::move(callback).Run(GetCachedHostUsage(host)); return; @@ -116,26 +118,27 @@ void ClientUsageTracker::GetHostUsage(const std::string& host, if (!host_usage_accumulators_.Add( host, base::BindOnce(&DidGetHostUsage, std::move(callback)))) return; - client_->GetOriginsForHost( + client_->GetStorageKeysForHost( type_, host, - base::BindOnce(&ClientUsageTracker::DidGetOriginsForHostUsage, + base::BindOnce(&ClientUsageTracker::DidGetStorageKeysForHostUsage, weak_factory_.GetWeakPtr(), host)); } -void ClientUsageTracker::UpdateUsageCache(const url::Origin& origin, +void ClientUsageTracker::UpdateUsageCache(const blink::StorageKey& storage_key, int64_t delta) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - const std::string& host = origin.host(); + const std::string& host = storage_key.origin().host(); if (base::Contains(cached_hosts_, host)) { - if (!IsUsageCacheEnabledForOrigin(origin)) + if (!IsUsageCacheEnabledForStorageKey(storage_key)) return; // Constrain |delta| to avoid negative usage values. // TODO(michaeln): crbug/463729 - delta = std::max(delta, -cached_usage_by_host_[host][origin]); - cached_usage_by_host_[host][origin] += delta; - UpdateGlobalUsageValue(IsStorageUnlimited(origin) ? &global_unlimited_usage_ - : &global_limited_usage_, + delta = std::max(delta, -cached_usage_by_host_[host][storage_key]); + cached_usage_by_host_[host][storage_key] += delta; + UpdateGlobalUsageValue(IsStorageUnlimited(storage_key) + ? &global_unlimited_usage_ + : &global_limited_usage_, delta); return; @@ -150,8 +153,8 @@ int64_t ClientUsageTracker::GetCachedUsage() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); int64_t usage = 0; for (const auto& host_and_usage_map : cached_usage_by_host_) { - for (const auto& origin_and_usage : host_and_usage_map.second) - usage += origin_and_usage.second; + for (const auto& storage_key_and_usage : host_and_usage_map.second) + usage += storage_key_and_usage.second; } return usage; } @@ -166,42 +169,44 @@ std::map<std::string, int64_t> ClientUsageTracker::GetCachedHostsUsage() const { return host_usage; } -std::map<url::Origin, int64_t> ClientUsageTracker::GetCachedOriginsUsage() - const { +std::map<blink::StorageKey, int64_t> +ClientUsageTracker::GetCachedStorageKeysUsage() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - std::map<url::Origin, int64_t> origin_usage; + std::map<blink::StorageKey, int64_t> storage_key_usage; for (const auto& host_and_usage_map : cached_usage_by_host_) { - for (const auto& origin_and_usage : host_and_usage_map.second) - origin_usage[origin_and_usage.first] += origin_and_usage.second; + for (const auto& storage_key_and_usage : host_and_usage_map.second) + storage_key_usage[storage_key_and_usage.first] += + storage_key_and_usage.second; } - return origin_usage; + return storage_key_usage; } -std::set<url::Origin> ClientUsageTracker::GetCachedOrigins() const { +std::set<blink::StorageKey> ClientUsageTracker::GetCachedStorageKeys() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - std::set<url::Origin> origins; + std::set<blink::StorageKey> storage_keys; for (const auto& host_and_usage_map : cached_usage_by_host_) { - for (const auto& origin_and_usage : host_and_usage_map.second) - origins.insert(origin_and_usage.first); + for (const auto& storage_key_and_usage : host_and_usage_map.second) + storage_keys.insert(storage_key_and_usage.first); } - return origins; + return storage_keys; } -void ClientUsageTracker::SetUsageCacheEnabled(const url::Origin& origin, - bool enabled) { +void ClientUsageTracker::SetUsageCacheEnabled( + const blink::StorageKey& storage_key, + bool enabled) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - const std::string& host = origin.host(); + const std::string& host = storage_key.origin().host(); if (!enabled) { - // Erase |origin| from cache and subtract its usage. + // Erase `storage_key` from cache and subtract its usage. auto host_it = cached_usage_by_host_.find(host); if (host_it != cached_usage_by_host_.end()) { UsageMap& cached_usage_for_host = host_it->second; - auto origin_it = cached_usage_for_host.find(origin); - if (origin_it != cached_usage_for_host.end()) { - int64_t usage = origin_it->second; - UpdateUsageCache(origin, -usage); - cached_usage_for_host.erase(origin_it); + auto storage_key_it = cached_usage_for_host.find(storage_key); + if (storage_key_it != cached_usage_for_host.end()) { + int64_t usage = storage_key_it->second; + UpdateUsageCache(storage_key, -usage); + cached_usage_for_host.erase(storage_key_it); if (cached_usage_for_host.empty()) { cached_usage_by_host_.erase(host_it); cached_hosts_.erase(host); @@ -209,30 +214,30 @@ void ClientUsageTracker::SetUsageCacheEnabled(const url::Origin& origin, } } - if (IsStorageUnlimited(origin)) - non_cached_unlimited_origins_by_host_[host].insert(origin); + if (IsStorageUnlimited(storage_key)) + non_cached_unlimited_storage_keys_by_host_[host].insert(storage_key); else - non_cached_limited_origins_by_host_[host].insert(origin); + non_cached_limited_storage_keys_by_host_[host].insert(storage_key); } else { - // Erase |origin| from |non_cached_origins_| and invalidate the usage cache - // for the host. - if (EraseOriginFromOriginSet(&non_cached_limited_origins_by_host_, - host, origin) || - EraseOriginFromOriginSet(&non_cached_unlimited_origins_by_host_, - host, origin)) { + // Erase `storage_key` from `non_cached_storage_keys_` and invalidate the + // usage cache for the host. + if (EraseStorageKeyFromStorageKeySet( + &non_cached_limited_storage_keys_by_host_, host, storage_key) || + EraseStorageKeyFromStorageKeySet( + &non_cached_unlimited_storage_keys_by_host_, host, storage_key)) { cached_hosts_.erase(host); global_usage_retrieved_ = false; } } } -void ClientUsageTracker::DidGetOriginsForGlobalUsage( +void ClientUsageTracker::DidGetStorageKeysForGlobalUsage( GlobalUsageCallback callback, - const std::vector<url::Origin>& origins) { + const std::vector<blink::StorageKey>& storage_keys) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - std::map<std::string, std::vector<url::Origin>> origins_by_host; - for (const auto& origin : origins) - origins_by_host[origin.host()].push_back(origin); + std::map<std::string, std::vector<blink::StorageKey>> storage_keys_by_host; + for (const auto& storage_key : storage_keys) + storage_keys_by_host[storage_key.origin().host()].push_back(storage_key); AccumulateInfo* info = new AccumulateInfo; // Getting host usage may synchronously return the result if the usage is @@ -240,28 +245,30 @@ void ClientUsageTracker::DidGetOriginsForGlobalUsage( // looping over all hosts (because info->pending_jobs may reach 0 during the // loop). To avoid this, we add one more pending host as a sentinel and // fire the sentinel callback at the end. - info->pending_jobs = origins_by_host.size() + 1; + info->pending_jobs = storage_keys_by_host.size() + 1; auto accumulator = base::BindRepeating( &ClientUsageTracker::AccumulateHostUsage, weak_factory_.GetWeakPtr(), base::Owned(info), // The `accumulator` is called multiple times, but the `callback` inside // of it will only be called a single time, so we give ownership to the // `accumulator` itself. - base::Owned(std::make_unique<GlobalUsageCallback>(std::move(callback)))); + base::OwnedRef(std::move(callback))); - for (const auto& host_and_origins : origins_by_host) { - const std::string& host = host_and_origins.first; - const std::vector<url::Origin>& origins = host_and_origins.second; + for (const auto& host_and_storage_keys : storage_keys_by_host) { + const std::string& host = host_and_storage_keys.first; + const std::vector<blink::StorageKey>& storage_keys = + host_and_storage_keys.second; if (host_usage_accumulators_.Add(host, accumulator)) - GetUsageForOrigins(host, origins); + GetUsageForStorageKeys(host, storage_keys); } - // Fire the sentinel as we've now called GetUsageForOrigins for all clients. + // Fire the sentinel as we've now called GetUsageForStorageKeys for all + // clients. std::move(accumulator).Run(0, 0); } void ClientUsageTracker::AccumulateHostUsage(AccumulateInfo* info, - GlobalUsageCallback* callback, + GlobalUsageCallback& callback, int64_t limited_usage, int64_t unlimited_usage) { DCHECK_GT(info->pending_jobs, 0U); @@ -275,74 +282,74 @@ void ClientUsageTracker::AccumulateHostUsage(AccumulateInfo* info, DCHECK_GE(info->unlimited_usage, 0); global_usage_retrieved_ = true; - std::move(*callback).Run(info->limited_usage + info->unlimited_usage, - info->unlimited_usage); + std::move(callback).Run(info->limited_usage + info->unlimited_usage, + info->unlimited_usage); } -void ClientUsageTracker::DidGetOriginsForHostUsage( +void ClientUsageTracker::DidGetStorageKeysForHostUsage( const std::string& host, - const std::vector<url::Origin>& origins) { + const std::vector<blink::StorageKey>& storage_keys) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - GetUsageForOrigins(host, origins); + GetUsageForStorageKeys(host, storage_keys); } -void ClientUsageTracker::GetUsageForOrigins( +void ClientUsageTracker::GetUsageForStorageKeys( const std::string& host, - const std::vector<url::Origin>& origins) { + const std::vector<blink::StorageKey>& storage_keys) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); AccumulateInfo* info = new AccumulateInfo; - // Getting origin usage may synchronously return the result if the usage is - // cached, which may in turn dispatch the completion callback before we finish - // looping over all origins (because info->pending_jobs may reach 0 during the - // loop). To avoid this, we add one more pending origin as a sentinel and - // fire the sentinel callback at the end. - info->pending_jobs = origins.size() + 1; + // Getting storage_key usage may synchronously return the result if the usage + // is cached, which may in turn dispatch the completion callback before we + // finish looping over all storage_keys (because info->pending_jobs may reach + // 0 during the loop). To avoid this, we add one more pending storage_key as + // a sentinel and fire the sentinel callback at the end. + info->pending_jobs = storage_keys.size() + 1; auto accumulator = - base::BindRepeating(&ClientUsageTracker::AccumulateOriginUsage, + base::BindRepeating(&ClientUsageTracker::AccumulateStorageKeyUsage, weak_factory_.GetWeakPtr(), base::Owned(info), host); - for (const auto& origin : origins) { - DCHECK_EQ(host, origin.host()); + for (const auto& storage_key : storage_keys) { + DCHECK_EQ(host, storage_key.origin().host()); - int64_t origin_usage = 0; - if (GetCachedOriginUsage(origin, &origin_usage)) { - accumulator.Run(origin, origin_usage); + int64_t storage_key_usage = 0; + if (GetCachedStorageKeyUsage(storage_key, &storage_key_usage)) { + accumulator.Run(storage_key, storage_key_usage); } else { - client_->GetOriginUsage(origin, type_, - base::BindOnce(accumulator, origin)); + client_->GetStorageKeyUsage(storage_key, type_, + base::BindOnce(accumulator, storage_key)); } } - // Fire the sentinel as we've now called GetOriginUsage for all clients. + // Fire the sentinel as we've now called GetStorageKeyUsage for all clients. accumulator.Run(absl::nullopt, 0); } -void ClientUsageTracker::AccumulateOriginUsage( +void ClientUsageTracker::AccumulateStorageKeyUsage( AccumulateInfo* info, const std::string& host, - const absl::optional<url::Origin>& origin, + const absl::optional<blink::StorageKey>& storage_key, int64_t usage) { DCHECK_GT(info->pending_jobs, 0U); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (origin.has_value()) { - // TODO(https://crbug.com/941480): |origin| should not be opaque or have an - // empty url, but sometimes it is. - if (origin->opaque()) { - DVLOG(1) << "AccumulateOriginUsage for opaque origin!"; + if (storage_key.has_value()) { + // TODO(https://crbug.com/941480): `storage_key` should not be opaque or + // have an empty url, but sometimes it is. + if (storage_key->origin().opaque()) { + DVLOG(1) << "AccumulateStorageKeyUsage for opaque storage_key!"; RecordSkippedOriginHistogram(InvalidOriginReason::kIsOpaque); - } else if (origin->GetURL().is_empty()) { - DVLOG(1) << "AccumulateOriginUsage for origin with empty url!"; + } else if (storage_key->origin().GetURL().is_empty()) { + DVLOG(1) << "AccumulateStorageKeyUsage for storage_key with empty url!"; RecordSkippedOriginHistogram(InvalidOriginReason::kIsEmpty); } else { if (usage < 0) usage = 0; - if (IsStorageUnlimited(*origin)) + if (IsStorageUnlimited(*storage_key)) info->unlimited_usage += usage; else info->limited_usage += usage; - if (IsUsageCacheEnabledForOrigin(*origin)) - AddCachedOrigin(*origin, usage); + if (IsUsageCacheEnabledForStorageKey(*storage_key)) + AddCachedStorageKey(*storage_key, usage); } } if (--info->pending_jobs) @@ -353,18 +360,20 @@ void ClientUsageTracker::AccumulateOriginUsage( host, info->limited_usage, info->unlimited_usage); } -void ClientUsageTracker::AddCachedOrigin(const url::Origin& origin, - int64_t new_usage) { +void ClientUsageTracker::AddCachedStorageKey( + const blink::StorageKey& storage_key, + int64_t new_usage) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(IsUsageCacheEnabledForOrigin(origin)); + DCHECK(IsUsageCacheEnabledForStorageKey(storage_key)); - const std::string& host = origin.host(); - int64_t* usage = &cached_usage_by_host_[host][origin]; + const std::string& host = storage_key.origin().host(); + int64_t* usage = &cached_usage_by_host_[host][storage_key]; int64_t delta = new_usage - *usage; *usage = new_usage; if (delta) { - UpdateGlobalUsageValue(IsStorageUnlimited(origin) ? &global_unlimited_usage_ - : &global_limited_usage_, + UpdateGlobalUsageValue(IsStorageUnlimited(storage_key) + ? &global_unlimited_usage_ + : &global_limited_usage_, delta); } } @@ -382,69 +391,76 @@ int64_t ClientUsageTracker::GetCachedHostUsage(const std::string& host) const { int64_t usage = 0; const UsageMap& usage_map = it->second; - for (const auto& origin_and_usage : usage_map) - usage += origin_and_usage.second; + for (const auto& storage_key_and_usage : usage_map) + usage += storage_key_and_usage.second; return usage; } -bool ClientUsageTracker::GetCachedOriginUsage(const url::Origin& origin, - int64_t* usage) const { +bool ClientUsageTracker::GetCachedStorageKeyUsage( + const blink::StorageKey& storage_key, + int64_t* usage) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - const std::string& host = origin.host(); + const std::string& host = storage_key.origin().host(); auto host_it = cached_usage_by_host_.find(host); if (host_it == cached_usage_by_host_.end()) return false; - auto origin_it = host_it->second.find(origin); - if (origin_it == host_it->second.end()) + auto storage_key_it = host_it->second.find(storage_key); + if (storage_key_it == host_it->second.end()) return false; - DCHECK(IsUsageCacheEnabledForOrigin(origin)); - *usage = origin_it->second; + DCHECK(IsUsageCacheEnabledForStorageKey(storage_key)); + *usage = storage_key_it->second; return true; } -bool ClientUsageTracker::IsUsageCacheEnabledForOrigin( - const url::Origin& origin) const { +bool ClientUsageTracker::IsUsageCacheEnabledForStorageKey( + const blink::StorageKey& storage_key) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - const std::string& host = origin.host(); - return !OriginSetContainsOrigin(non_cached_limited_origins_by_host_, - host, origin) && - !OriginSetContainsOrigin(non_cached_unlimited_origins_by_host_, - host, origin); + const std::string& host = storage_key.origin().host(); + return !StorageKeySetContainsStorageKey( + non_cached_limited_storage_keys_by_host_, host, storage_key) && + !StorageKeySetContainsStorageKey( + non_cached_unlimited_storage_keys_by_host_, host, storage_key); } -void ClientUsageTracker::OnGranted(const url::Origin& origin, +void ClientUsageTracker::OnGranted(const url::Origin& origin_url, int change_flags) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // TODO(crbug.com/1215208): Remove this conversion once the storage policy + // APIs are converted to use StorageKey instead of Origin. + const blink::StorageKey storage_key(origin_url); if (change_flags & SpecialStoragePolicy::STORAGE_UNLIMITED) { int64_t usage = 0; - if (GetCachedOriginUsage(origin, &usage)) { + if (GetCachedStorageKeyUsage(storage_key, &usage)) { global_unlimited_usage_ += usage; global_limited_usage_ -= usage; } - const std::string& host = origin.host(); - if (EraseOriginFromOriginSet(&non_cached_limited_origins_by_host_, - host, origin)) - non_cached_unlimited_origins_by_host_[host].insert(origin); + const std::string& host = storage_key.origin().host(); + if (EraseStorageKeyFromStorageKeySet( + &non_cached_limited_storage_keys_by_host_, host, storage_key)) + non_cached_unlimited_storage_keys_by_host_[host].insert(storage_key); } } -void ClientUsageTracker::OnRevoked(const url::Origin& origin, +void ClientUsageTracker::OnRevoked(const url::Origin& origin_url, int change_flags) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // TODO(crbug.com/1215208): Remove this conversion once the storage policy + // APIs are converted to use StorageKey instead of Origin. + const blink::StorageKey storage_key(origin_url); if (change_flags & SpecialStoragePolicy::STORAGE_UNLIMITED) { int64_t usage = 0; - if (GetCachedOriginUsage(origin, &usage)) { + if (GetCachedStorageKeyUsage(storage_key, &usage)) { global_unlimited_usage_ -= usage; global_limited_usage_ += usage; } - const std::string& host = origin.host(); - if (EraseOriginFromOriginSet(&non_cached_unlimited_origins_by_host_, - host, origin)) - non_cached_limited_origins_by_host_[host].insert(origin); + const std::string& host = storage_key.origin().host(); + if (EraseStorageKeyFromStorageKeySet( + &non_cached_unlimited_storage_keys_by_host_, host, storage_key)) + non_cached_limited_storage_keys_by_host_[host].insert(storage_key); } } @@ -453,12 +469,13 @@ void ClientUsageTracker::OnCleared() { global_limited_usage_ += global_unlimited_usage_; global_unlimited_usage_ = 0; - for (const auto& host_and_origins : non_cached_unlimited_origins_by_host_) { - const auto& host = host_and_origins.first; - for (const auto& origin : host_and_origins.second) - non_cached_limited_origins_by_host_[host].insert(origin); + for (const auto& host_and_storage_keys : + non_cached_unlimited_storage_keys_by_host_) { + const auto& host = host_and_storage_keys.first; + for (const auto& storage_key : host_and_storage_keys.second) + non_cached_limited_storage_keys_by_host_[host].insert(storage_key); } - non_cached_unlimited_origins_by_host_.clear(); + non_cached_unlimited_storage_keys_by_host_.clear(); } void ClientUsageTracker::UpdateGlobalUsageValue(int64_t* usage_value, @@ -473,21 +490,23 @@ void ClientUsageTracker::UpdateGlobalUsageValue(int64_t* usage_value, global_limited_usage_ = 0; global_unlimited_usage_ = 0; for (const auto& host_and_usage_map : cached_usage_by_host_) { - for (const auto& origin_and_usage : host_and_usage_map.second) { - if (IsStorageUnlimited(origin_and_usage.first)) - global_unlimited_usage_ += origin_and_usage.second; + for (const auto& storage_key_and_usage : host_and_usage_map.second) { + if (IsStorageUnlimited(storage_key_and_usage.first)) + global_unlimited_usage_ += storage_key_and_usage.second; else - global_limited_usage_ += origin_and_usage.second; + global_limited_usage_ += storage_key_and_usage.second; } } } -bool ClientUsageTracker::IsStorageUnlimited(const url::Origin& origin) const { +bool ClientUsageTracker::IsStorageUnlimited( + const blink::StorageKey& storage_key) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (type_ == blink::mojom::StorageType::kSyncable) return false; return special_storage_policy_.get() && - special_storage_policy_->IsStorageUnlimited(origin.GetURL()); + special_storage_policy_->IsStorageUnlimited( + storage_key.origin().GetURL()); } } // namespace storage diff --git a/chromium/storage/browser/quota/client_usage_tracker.h b/chromium/storage/browser/quota/client_usage_tracker.h index 63bd56025de..d8c79b7f549 100644 --- a/chromium/storage/browser/quota/client_usage_tracker.h +++ b/chromium/storage/browser/quota/client_usage_tracker.h @@ -15,14 +15,18 @@ #include "base/callback.h" #include "base/sequence_checker.h" +#include "components/services/storage/public/mojom/quota_client.mojom.h" #include "storage/browser/quota/quota_callbacks.h" -#include "storage/browser/quota/quota_client.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" #include "url/gurl.h" #include "url/origin.h" +namespace blink { +class StorageKey; +} // namespace blink + namespace storage { class UsageTracker; @@ -44,11 +48,13 @@ enum class InvalidOriginReason { // called on the same sequence. class ClientUsageTracker : public SpecialStoragePolicy::Observer { public: - using OriginSetByHost = std::map<std::string, std::set<url::Origin>>; + using StorageKeySetByHost = + std::map<std::string, std::set<blink::StorageKey>>; + // The caller must ensure that `client` outlives this instance. ClientUsageTracker( UsageTracker* tracker, - scoped_refptr<QuotaClient> client, + mojom::QuotaClient* client, blink::mojom::StorageType type, scoped_refptr<SpecialStoragePolicy> special_storage_policy); @@ -59,54 +65,62 @@ class ClientUsageTracker : public SpecialStoragePolicy::Observer { void GetGlobalUsage(GlobalUsageCallback callback); void GetHostUsage(const std::string& host, UsageCallback callback); - void UpdateUsageCache(const url::Origin& origin, int64_t delta); + void UpdateUsageCache(const blink::StorageKey& storage_key, int64_t delta); int64_t GetCachedUsage() const; std::map<std::string, int64_t> GetCachedHostsUsage() const; - std::map<url::Origin, int64_t> GetCachedOriginsUsage() const; - std::set<url::Origin> GetCachedOrigins() const; - bool IsUsageCacheEnabledForOrigin(const url::Origin& origin) const; - void SetUsageCacheEnabled(const url::Origin& origin, bool enabled); + std::map<blink::StorageKey, int64_t> GetCachedStorageKeysUsage() const; + std::set<blink::StorageKey> GetCachedStorageKeys() const; + bool IsUsageCacheEnabledForStorageKey( + const blink::StorageKey& storage_key) const; + void SetUsageCacheEnabled(const blink::StorageKey& storage_key, bool enabled); + private: - using UsageMap = std::map<url::Origin, int64_t>; + using UsageMap = std::map<blink::StorageKey, int64_t>; struct AccumulateInfo; - void DidGetOriginsForGlobalUsage(GlobalUsageCallback callback, - const std::vector<url::Origin>& origins); + void DidGetStorageKeysForGlobalUsage( + GlobalUsageCallback callback, + const std::vector<blink::StorageKey>& storage_keys); void AccumulateHostUsage(AccumulateInfo* info, - GlobalUsageCallback* callback, + GlobalUsageCallback& callback, int64_t limited_usage, int64_t unlimited_usage); - void DidGetOriginsForHostUsage(const std::string& host, - const std::vector<url::Origin>& origins); + void DidGetStorageKeysForHostUsage( + const std::string& host, + const std::vector<blink::StorageKey>& storage_keys); - void GetUsageForOrigins(const std::string& host, - const std::vector<url::Origin>& origins); - void AccumulateOriginUsage(AccumulateInfo* info, - const std::string& host, - const absl::optional<url::Origin>& origin, - int64_t usage); + void GetUsageForStorageKeys( + const std::string& host, + const std::vector<blink::StorageKey>& storage_keys); + void AccumulateStorageKeyUsage( + AccumulateInfo* info, + const std::string& host, + const absl::optional<blink::StorageKey>& storage_key, + int64_t usage); // Methods used by our GatherUsage tasks, as a task makes progress - // origins and hosts are added incrementally to the cache. - void AddCachedOrigin(const url::Origin& origin, int64_t usage); + // storage keys and hosts are added incrementally to the cache. + void AddCachedStorageKey(const blink::StorageKey& storage_key, int64_t usage); void AddCachedHost(const std::string& host); int64_t GetCachedHostUsage(const std::string& host) const; - int64_t GetCachedGlobalUnlimitedUsage(); - bool GetCachedOriginUsage(const url::Origin& origin, int64_t* usage) const; + bool GetCachedStorageKeyUsage(const blink::StorageKey& storage_key, + int64_t* usage) const; // SpecialStoragePolicy::Observer overrides + // TODO(crbug.com/1215208): Migrate to use StorageKey when the StoragePolicy + // is migrated to use StorageKey instead of Origin. void OnGranted(const url::Origin& origin_url, int change_flags) override; void OnRevoked(const url::Origin& origin_url, int change_flags) override; void OnCleared() override; void UpdateGlobalUsageValue(int64_t* usage_value, int64_t delta); - bool IsStorageUnlimited(const url::Origin& origin) const; + bool IsStorageUnlimited(const blink::StorageKey& storage_key) const; - scoped_refptr<QuotaClient> client_; + mojom::QuotaClient* client_; const blink::mojom::StorageType type_; int64_t global_limited_usage_; @@ -115,8 +129,8 @@ class ClientUsageTracker : public SpecialStoragePolicy::Observer { std::set<std::string> cached_hosts_; std::map<std::string, UsageMap> cached_usage_by_host_; - OriginSetByHost non_cached_limited_origins_by_host_; - OriginSetByHost non_cached_unlimited_origins_by_host_; + StorageKeySetByHost non_cached_limited_storage_keys_by_host_; + StorageKeySetByHost non_cached_unlimited_storage_keys_by_host_; CallbackQueueMap< base::OnceCallback<void(int64_t limited_usage, int64_t unlimited_usage)>, diff --git a/chromium/storage/browser/quota/mojo_quota_client_wrapper.cc b/chromium/storage/browser/quota/mojo_quota_client_wrapper.cc deleted file mode 100644 index 59ea75264d7..00000000000 --- a/chromium/storage/browser/quota/mojo_quota_client_wrapper.cc +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "storage/browser/quota/mojo_quota_client_wrapper.h" - -#include <utility> - -#include "base/check.h" -#include "base/sequence_checker.h" -#include "components/services/storage/public/mojom/quota_client.mojom.h" -#include "url/origin.h" - -namespace storage { - -MojoQuotaClientWrapper::MojoQuotaClientWrapper( - mojom::QuotaClient* wrapped_client) - : wrapped_client_(wrapped_client) { - DCHECK(wrapped_client); - DETACH_FROM_SEQUENCE(sequence_checker_); -} - -MojoQuotaClientWrapper::~MojoQuotaClientWrapper() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); -} - -void MojoQuotaClientWrapper::GetOriginUsage(const url::Origin& origin, - blink::mojom::StorageType type, - GetOriginUsageCallback callback) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - wrapped_client_->GetOriginUsage(origin, type, std::move(callback)); -} - -void MojoQuotaClientWrapper::GetOriginsForType( - blink::mojom::StorageType type, - GetOriginsForTypeCallback callback) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - wrapped_client_->GetOriginsForType(type, std::move(callback)); -} - -void MojoQuotaClientWrapper::GetOriginsForHost( - blink::mojom::StorageType type, - const std::string& host, - GetOriginsForHostCallback callback) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - wrapped_client_->GetOriginsForHost(type, host, std::move(callback)); -} - -void MojoQuotaClientWrapper::DeleteOriginData( - const url::Origin& origin, - blink::mojom::StorageType type, - DeleteOriginDataCallback callback) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - wrapped_client_->DeleteOriginData(origin, type, std::move(callback)); -} - -void MojoQuotaClientWrapper::PerformStorageCleanup( - blink::mojom::StorageType type, - PerformStorageCleanupCallback callback) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - wrapped_client_->PerformStorageCleanup(type, std::move(callback)); -} - -void MojoQuotaClientWrapper::OnQuotaManagerDestroyed() {} - -} // namespace storage diff --git a/chromium/storage/browser/quota/mojo_quota_client_wrapper.h b/chromium/storage/browser/quota/mojo_quota_client_wrapper.h deleted file mode 100644 index 9b598ed47c0..00000000000 --- a/chromium/storage/browser/quota/mojo_quota_client_wrapper.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef STORAGE_BROWSER_QUOTA_MOJO_QUOTA_CLIENT_WRAPPER_H_ -#define STORAGE_BROWSER_QUOTA_MOJO_QUOTA_CLIENT_WRAPPER_H_ - -#include <string> - -#include "base/component_export.h" -#include "base/sequence_checker.h" -#include "base/thread_annotations.h" -#include "components/services/storage/public/mojom/quota_client.mojom.h" -#include "storage/browser/quota/quota_client.h" -#include "third_party/blink/public/mojom/quota/quota_types.mojom.h" - -namespace url { -class Origin; -} // namespace url - -namespace storage { - -// TODO(crbug.com/1163009): Remove this class after all QuotaClients have been -// mojofied. -class COMPONENT_EXPORT(STORAGE_BROWSER) MojoQuotaClientWrapper - : public storage::QuotaClient { - public: - // `wrapped_client` must outlive this instance. - explicit MojoQuotaClientWrapper(storage::mojom::QuotaClient* wrapped_client); - - MojoQuotaClientWrapper(const MojoQuotaClientWrapper&) = delete; - MojoQuotaClientWrapper& operator=(const MojoQuotaClientWrapper&) = delete; - - // QuotaClient. - void GetOriginUsage(const url::Origin& origin, - blink::mojom::StorageType type, - GetOriginUsageCallback callback) override; - void GetOriginsForType(blink::mojom::StorageType type, - GetOriginsForTypeCallback callback) override; - void GetOriginsForHost(blink::mojom::StorageType type, - const std::string& host, - GetOriginsForHostCallback callback) override; - void DeleteOriginData(const url::Origin& origin, - blink::mojom::StorageType type, - DeleteOriginDataCallback callback) override; - void PerformStorageCleanup(blink::mojom::StorageType type, - PerformStorageCleanupCallback callback) override; - void OnQuotaManagerDestroyed() override; - - private: - ~MojoQuotaClientWrapper() override; - - SEQUENCE_CHECKER(sequence_checker_); - - storage::mojom::QuotaClient* const wrapped_client_ - GUARDED_BY_CONTEXT(sequence_checker_); -}; - -} // namespace storage - -#endif // STORAGE_BROWSER_QUOTA_MOJO_QUOTA_CLIENT_WRAPPER_H_ diff --git a/chromium/storage/browser/quota/quota_callbacks.h b/chromium/storage/browser/quota/quota_callbacks.h index 1f8877f79f7..36013d114c3 100644 --- a/chromium/storage/browser/quota/quota_callbacks.h +++ b/chromium/storage/browser/quota/quota_callbacks.h @@ -15,11 +15,12 @@ #include "base/callback.h" #include "base/containers/contains.h" +#include "components/services/storage/public/cpp/buckets/bucket_info.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom-forward.h" -namespace url { -class Origin; +namespace blink { +class StorageKey; } namespace storage { @@ -41,12 +42,14 @@ using UsageWithBreakdownCallback = using AvailableSpaceCallback = base::OnceCallback<void(blink::mojom::QuotaStatusCode, int64_t)>; using StatusCallback = base::OnceCallback<void(blink::mojom::QuotaStatusCode)>; -using GetOriginsCallback = - base::OnceCallback<void(const std::set<url::Origin>& origins, +using GetBucketsCallback = + base::OnceCallback<void(const std::set<BucketInfo>& buckets, blink::mojom::StorageType type)>; +using GetStorageKeysCallback = + base::OnceCallback<void(const std::set<blink::StorageKey>& storage_keys)>; using GetUsageInfoCallback = base::OnceCallback<void(UsageInfoEntries)>; -using GetOriginCallback = - base::OnceCallback<void(const absl::optional<url::Origin>&)>; +using GetBucketCallback = + base::OnceCallback<void(const absl::optional<BucketInfo>& bucket_info)>; // Simple template wrapper for a callback queue. template <typename CallbackType, typename... Args> diff --git a/chromium/storage/browser/quota/quota_client.h b/chromium/storage/browser/quota/quota_client.h deleted file mode 100644 index aa25e1372f2..00000000000 --- a/chromium/storage/browser/quota/quota_client.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef STORAGE_BROWSER_QUOTA_QUOTA_CLIENT_H_ -#define STORAGE_BROWSER_QUOTA_QUOTA_CLIENT_H_ - -#include <stdint.h> - -#include "base/callback.h" -#include "base/component_export.h" -#include "components/services/storage/public/mojom/quota_client.mojom.h" -#include "storage/browser/quota/quota_client_type.h" -#include "third_party/blink/public/mojom/quota/quota_types.mojom.h" -#include "url/origin.h" - -namespace storage { - -// Interface between the legacy quota clients and the QuotaManager. -// -// Implementations of this class will be transitioned to inherit from -// storage::mojom::QuotaClient and talk to the QuotaManager via mojo. -// -// This inherits from storage::mojom::QuotaClient so that MockQuotaClient -// instances can be passed to QuotaManger::RegisterLegacyClient(), -// as well as used via mojo with QuotaManager::RegisterClient(). -// -// TODO(crbug.com/1163009): Remove this class after all QuotaClients have -// been mojofied. -class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaClient - : public base::RefCountedThreadSafe<QuotaClient>, - public storage::mojom::QuotaClient { - public: - // Called when the QuotaManager is destroyed. - virtual void OnQuotaManagerDestroyed() = 0; - - protected: - friend class RefCountedThreadSafe<QuotaClient>; - - ~QuotaClient() override = default; -}; - -} // namespace storage - -#endif // STORAGE_BROWSER_QUOTA_QUOTA_CLIENT_H_ diff --git a/chromium/storage/browser/quota/quota_database.cc b/chromium/storage/browser/quota/quota_database.cc index 075ca3a072d..f93459db71c 100644 --- a/chromium/storage/browser/quota/quota_database.cc +++ b/chromium/storage/browser/quota/quota_database.cc @@ -16,7 +16,7 @@ #include "base/containers/contains.h" #include "base/dcheck_is_on.h" #include "base/files/file_util.h" -#include "base/metrics/histogram_macros.h" +#include "base/metrics/histogram_functions.h" #include "sql/database.h" #include "sql/meta_table.h" #include "sql/statement.h" @@ -25,7 +25,8 @@ #include "storage/browser/quota/special_storage_policy.h" #include "url/gurl.h" -using blink::mojom::StorageType; +using ::blink::StorageKey; +using ::blink::mojom::StorageType; namespace storage { namespace { @@ -37,26 +38,27 @@ namespace { // razed. // // Version 1 - 2011-03-17 - http://crrev.com/78521 (unsupported) -// Version 2 - 2010-04-25 - http://crrev.com/82847 (unsupported) +// Version 2 - 2011-04-25 - http://crrev.com/82847 (unsupported) // Version 3 - 2011-07-08 - http://crrev.com/91835 (unsupported) // Version 4 - 2011-10-17 - http://crrev.com/105822 (unsupported) // Version 5 - 2015-10-19 - https://crrev.com/354932 // Version 6 - 2021-04-27 - https://crrev.com/c/2757450 -const int kQuotaDatabaseCurrentSchemaVersion = 6; -const int kQuotaDatabaseCompatibleVersion = 6; +// Version 7 - 2021-05-20 - https://crrev.com/c/2910136 +const int kQuotaDatabaseCurrentSchemaVersion = 7; +const int kQuotaDatabaseCompatibleVersion = 7; // Definitions for database schema. const char kHostQuotaTable[] = "quota"; const char kBucketTable[] = "buckets"; -const char kEvictionInfoTable[] = "eviction_info"; const char kIsOriginTableBootstrapped[] = "IsOriginTableBootstrapped"; const int kCommitIntervalMs = 30000; -} // anonymous namespace +void RecordDatabaseResetHistogram(const DatabaseResetReason reason) { + base::UmaHistogramEnumeration("Quota.QuotaDatabaseReset", reason); +} -// static -const char QuotaDatabase::kDefaultBucket[] = "default"; +} // anonymous namespace const QuotaDatabase::TableSchema QuotaDatabase::kTables[] = { {kHostQuotaTable, @@ -67,6 +69,8 @@ const QuotaDatabase::TableSchema QuotaDatabase::kTables[] = { " WITHOUT ROWID"}, {kBucketTable, "(id INTEGER PRIMARY KEY," + // TODO(crbug.com/1215208): Rename column to storage_key and create a DB + // migration for it. " origin TEXT NOT NULL," " type INTEGER NOT NULL," " name TEXT NOT NULL," @@ -74,12 +78,7 @@ const QuotaDatabase::TableSchema QuotaDatabase::kTables[] = { " last_accessed INTEGER NOT NULL," " last_modified INTEGER NOT NULL," " expiration INTEGER NOT NULL," - " quota INTEGER NOT NULL)"}, - {kEvictionInfoTable, - "(origin TEXT NOT NULL," - " type INTEGER NOT NULL," - " last_eviction_time INTEGER NOT NULL," - " PRIMARY KEY(origin, type))"}}; + " quota INTEGER NOT NULL)"}}; const size_t QuotaDatabase::kTableCount = base::size(QuotaDatabase::kTables); // static @@ -93,21 +92,23 @@ const size_t QuotaDatabase::kIndexCount = base::size(QuotaDatabase::kIndexes); QuotaDatabase::BucketTableEntry::BucketTableEntry() = default; +QuotaDatabase::BucketTableEntry::~BucketTableEntry() = default; + QuotaDatabase::BucketTableEntry::BucketTableEntry(const BucketTableEntry&) = default; QuotaDatabase::BucketTableEntry& QuotaDatabase::BucketTableEntry::operator=( const QuotaDatabase::BucketTableEntry&) = default; QuotaDatabase::BucketTableEntry::BucketTableEntry( - const int64_t bucket_id, - url::Origin origin, + BucketId bucket_id, + StorageKey storage_key, StorageType type, std::string name, int use_count, const base::Time& last_accessed, const base::Time& last_modified) - : bucket_id(bucket_id), - origin(std::move(origin)), + : bucket_id(std::move(bucket_id)), + storage_key(std::move(storage_key)), type(type), name(std::move(name)), use_count(use_count), @@ -134,7 +135,7 @@ bool QuotaDatabase::GetHostQuota(const std::string& host, int64_t* quota) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(quota); - if (!LazyOpen(false)) + if (LazyOpen(LazyOpenMode::kFailIfNotFound) != QuotaError::kNone) return false; static constexpr char kSql[] = @@ -155,8 +156,9 @@ bool QuotaDatabase::SetHostQuota(const std::string& host, int64_t quota) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_GE(quota, 0); - if (!LazyOpen(true)) + if (LazyOpen(LazyOpenMode::kCreateIfNotFound) != QuotaError::kNone) return false; + if (quota == 0) return DeleteHostQuota(host, type); if (!InsertOrReplaceHostQuota(host, type, quota)) @@ -165,124 +167,104 @@ bool QuotaDatabase::SetHostQuota(const std::string& host, return true; } -QuotaErrorOr<BucketId> QuotaDatabase::CreateBucket( - const url::Origin& origin, +QuotaErrorOr<BucketInfo> QuotaDatabase::GetOrCreateBucket( + const StorageKey& storage_key, const std::string& bucket_name) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // TODO(crbug/1210259): Add DCHECKs for input validation. - if (!LazyOpen(/*create_if_needed=*/true)) - return QuotaError::kDatabaseError; - // TODO(crbug/1210252): Update to not execute 2 sql statements on creation. - QuotaErrorOr<BucketId> bucket_result = GetBucketId(origin, bucket_name); - if (!bucket_result.ok()) - return bucket_result.error(); + QuotaErrorOr<BucketInfo> bucket_result = + GetBucket(storage_key, bucket_name, StorageType::kTemporary); - if (!bucket_result.value().is_null()) - return QuotaError::kEntryExistsError; + if (bucket_result.ok()) + return bucket_result; + + if (bucket_result.error() != QuotaError::kNotFound) + return bucket_result.error(); base::Time now = base::Time::Now(); - static constexpr char kSql[] = - // clang-format off - "INSERT INTO buckets(" - "origin," - "type," - "name," - "use_count," - "last_accessed," - "last_modified," - "expiration," - "quota) " - "VALUES (?, 0, ?, 0, ?, ?, ?, 0)"; - // clang-format on - sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - // Bucket usage is only for temporary storage types. - static_assert(static_cast<int>(StorageType::kTemporary) == 0, - "The type value baked in the SQL statement above is wrong."); - statement.BindString(0, origin.GetURL().spec()); - statement.BindString(1, bucket_name); - statement.BindTime(2, now); - statement.BindTime(3, now); - statement.BindTime(4, base::Time::Max()); + return CreateBucketInternal(storage_key, StorageType::kTemporary, bucket_name, + /*use_count=*/0, now, now); +} - if (!statement.Run()) - return QuotaError::kDatabaseError; +QuotaErrorOr<BucketInfo> QuotaDatabase::CreateBucketForTesting( + const StorageKey& storage_key, + const std::string& bucket_name, + blink::mojom::StorageType storage_type) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - ScheduleCommit(); + // TODO(crbug/1210252): Update to not execute 2 sql statements on creation. + QuotaErrorOr<BucketInfo> bucket_result = + GetBucket(storage_key, bucket_name, storage_type); - int64_t bucket_id = db_->GetLastInsertRowId(); - DCHECK_GT(bucket_id, 0); - return BucketId(bucket_id); + if (bucket_result.ok()) + return QuotaError::kEntryExistsError; + + if (bucket_result.error() != QuotaError::kNotFound) + return bucket_result.error(); + + base::Time now = base::Time::Now(); + return CreateBucketInternal(storage_key, storage_type, bucket_name, + /*use_count=*/0, now, now); } -QuotaErrorOr<BucketId> QuotaDatabase::GetBucketId( - const url::Origin& origin, - const std::string& bucket_name) { +QuotaErrorOr<BucketInfo> QuotaDatabase::GetBucket( + const StorageKey& storage_key, + const std::string& bucket_name, + blink::mojom::StorageType storage_type) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyOpen(/*create_if_needed=*/true)) - return QuotaError::kDatabaseError; + QuotaError open_error = LazyOpen(LazyOpenMode::kFailIfNotFound); + if (open_error != QuotaError::kNone) + return open_error; static constexpr char kSql[] = - "SELECT id FROM buckets WHERE origin = ? AND type = ? AND name = ?"; + // clang-format off + "SELECT id, expiration, quota " + "FROM buckets " + "WHERE origin = ? AND type = ? AND name = ?"; + // clang-format on sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindString(0, origin.GetURL().spec()); - // Bucket usage is only for temporary storage types. - statement.BindInt(1, static_cast<int>(StorageType::kTemporary)); + statement.BindString(0, storage_key.Serialize()); + statement.BindInt(1, static_cast<int>(storage_type)); statement.BindString(2, bucket_name); if (!statement.Step()) { - return statement.Succeeded() - ? QuotaErrorOr<BucketId>(BucketId()) - : QuotaErrorOr<BucketId>(QuotaError::kDatabaseError); + return statement.Succeeded() ? QuotaError::kNotFound + : QuotaError::kDatabaseError; } - return BucketId(statement.ColumnInt64(0)); + + return BucketInfo(BucketId(statement.ColumnInt64(0)), storage_key, + storage_type, bucket_name, statement.ColumnTime(1), + statement.ColumnInt(2)); } -bool QuotaDatabase::SetOriginLastAccessTime(const url::Origin& origin, - StorageType type, - base::Time last_accessed) { +bool QuotaDatabase::SetStorageKeyLastAccessTime(const StorageKey& storage_key, + StorageType type, + base::Time last_accessed) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyOpen(true)) + if (LazyOpen(LazyOpenMode::kCreateIfNotFound) != QuotaError::kNone) return false; - sql::Statement statement; - BucketTableEntry entry; - if (GetOriginInfo(origin, type, &entry)) { - ++entry.use_count; - static constexpr char kSql[] = - // clang-format off - "UPDATE buckets " - "SET use_count = ?, last_accessed = ? " - "WHERE origin = ? AND type = ? AND name = ?"; - // clang-format on - statement.Assign(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - } else { - entry.use_count = 1; - // INSERT statement column ordering matches UPDATE statement above for - // reuse of binding values. - static constexpr char kSql[] = - // clang-format off - "INSERT INTO buckets(" - "use_count," - "last_accessed," - "origin," - "type," - "name," - "last_modified," - "expiration," - "quota) " - "VALUES (?, ?, ?, ?, ?, ?, ?, 0)"; - // clang-format on - statement.Assign(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindTime(5, last_accessed); - statement.BindTime(6, base::Time::Max()); + if (!GetStorageKeyInfo(storage_key, type, &entry)) { + QuotaErrorOr<BucketInfo> result = + CreateBucketInternal(storage_key, type, kDefaultBucketName, + /*use_count=*/1, last_accessed, last_accessed); + return result.ok(); } + + ++entry.use_count; + static constexpr char kSql[] = + // clang-format off + "UPDATE buckets " + "SET use_count = ?, last_accessed = ? " + "WHERE origin = ? AND type = ? AND name = ?"; + // clang-format on + sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); statement.BindInt(0, entry.use_count); statement.BindTime(1, last_accessed); - statement.BindString(2, origin.GetURL().spec()); + statement.BindString(2, storage_key.Serialize()); statement.BindInt(3, static_cast<int>(type)); - statement.BindString(4, kDefaultBucket); + statement.BindString(4, kDefaultBucketName); if (!statement.Run()) return false; @@ -291,10 +273,11 @@ bool QuotaDatabase::SetOriginLastAccessTime(const url::Origin& origin, return true; } -bool QuotaDatabase::SetBucketLastAccessTime(const int64_t bucket_id, +bool QuotaDatabase::SetBucketLastAccessTime(const BucketId bucket_id, base::Time last_accessed) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyOpen(true)) + DCHECK(!bucket_id.is_null()); + if (LazyOpen(LazyOpenMode::kCreateIfNotFound) != QuotaError::kNone) return false; BucketTableEntry entry; @@ -307,7 +290,7 @@ bool QuotaDatabase::SetBucketLastAccessTime(const int64_t bucket_id, sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); statement.BindInt(0, entry.use_count); statement.BindTime(1, last_accessed); - statement.BindInt64(2, bucket_id); + statement.BindInt64(2, bucket_id.value()); if (!statement.Run()) return false; @@ -316,47 +299,32 @@ bool QuotaDatabase::SetBucketLastAccessTime(const int64_t bucket_id, return true; } -bool QuotaDatabase::SetOriginLastModifiedTime(const url::Origin& origin, - StorageType type, - base::Time last_modified) { +bool QuotaDatabase::SetStorageKeyLastModifiedTime(const StorageKey& storage_key, + StorageType type, + base::Time last_modified) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyOpen(true)) + if (LazyOpen(LazyOpenMode::kCreateIfNotFound) != QuotaError::kNone) return false; - sql::Statement statement; - BucketTableEntry entry; - if (GetOriginInfo(origin, type, &entry)) { - static constexpr char kSql[] = - // clang-format off - "UPDATE buckets " - "SET last_modified = ? " - "WHERE origin = ? AND type = ? AND name = ?"; - // clang-format on - statement.Assign(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - } else { - static constexpr char kSql[] = - // clang-format off - "INSERT INTO buckets(" - "last_modified," - "origin," - "type," - "name," - "last_accessed," - "use_count," - "expiration," - "quota) " - "VALUES (?, ?, ?, ?, ?, 0, ?, 0)"; - // clang-format on - statement.Assign(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindTime(4, last_modified); - statement.BindTime(5, base::Time::Max()); + if (!GetStorageKeyInfo(storage_key, type, &entry)) { + QuotaErrorOr<BucketInfo> result = + CreateBucketInternal(storage_key, type, kDefaultBucketName, + /*use_count=*/0, last_modified, last_modified); + return result.ok(); } - statement.BindTime(0, last_modified); - statement.BindString(1, origin.GetURL().spec()); + static constexpr char kSql[] = + // clang-format off + "UPDATE buckets " + "SET last_modified = ? " + "WHERE origin = ? AND type = ? AND name = ?"; + // clang-format on + sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); + statement.BindTime(0, last_modified); + statement.BindString(1, storage_key.Serialize()); statement.BindInt(2, static_cast<int>(type)); - statement.BindString(3, kDefaultBucket); + statement.BindString(3, kDefaultBucketName); if (!statement.Run()) return false; @@ -365,10 +333,11 @@ bool QuotaDatabase::SetOriginLastModifiedTime(const url::Origin& origin, return true; } -bool QuotaDatabase::SetBucketLastModifiedTime(const int64_t bucket_id, +bool QuotaDatabase::SetBucketLastModifiedTime(const BucketId bucket_id, base::Time last_modified) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyOpen(true)) + DCHECK(!bucket_id.is_null()); + if (LazyOpen(LazyOpenMode::kCreateIfNotFound) != QuotaError::kNone) return false; BucketTableEntry entry; @@ -379,56 +348,7 @@ bool QuotaDatabase::SetBucketLastModifiedTime(const int64_t bucket_id, "UPDATE buckets SET last_modified = ? WHERE id = ?"; sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); statement.BindTime(0, last_modified); - statement.BindInt64(1, bucket_id); - - if (!statement.Run()) - return false; - - ScheduleCommit(); - return true; -} - -bool QuotaDatabase::GetOriginLastEvictionTime(const url::Origin& origin, - StorageType type, - base::Time* last_modified) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(last_modified); - if (!LazyOpen(false)) - return false; - - static constexpr char kSql[] = - // clang-format off - "SELECT last_eviction_time " - "FROM eviction_info " - "WHERE origin = ? AND type = ?"; - // clang-format on - sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindString(0, origin.GetURL().spec()); - statement.BindInt(1, static_cast<int>(type)); - - if (!statement.Step()) - return false; - - *last_modified = statement.ColumnTime(0); - return true; -} - -bool QuotaDatabase::SetOriginLastEvictionTime(const url::Origin& origin, - StorageType type, - base::Time last_modified) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyOpen(true)) - return false; - - static constexpr char kSql[] = - // clang-format off - "INSERT OR REPLACE INTO eviction_info(last_eviction_time, origin, type) " - "VALUES (?, ?, ?)"; - // clang-format on - sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindTime(0, last_modified); - statement.BindString(1, origin.GetURL().spec()); - statement.BindInt(2, static_cast<int>(type)); + statement.BindInt64(1, bucket_id.value()); if (!statement.Run()) return false; @@ -437,33 +357,14 @@ bool QuotaDatabase::SetOriginLastEvictionTime(const url::Origin& origin, return true; } -bool QuotaDatabase::DeleteOriginLastEvictionTime(const url::Origin& origin, - StorageType type) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyOpen(false)) - return false; - - static constexpr char kSql[] = - "DELETE FROM eviction_info WHERE origin = ? AND type = ?"; - sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindString(0, origin.GetURL().spec()); - statement.BindInt(1, static_cast<int>(type)); - - if (!statement.Run()) - return false; - - ScheduleCommit(); - return true; -} - -bool QuotaDatabase::RegisterInitialOriginInfo( - const std::set<url::Origin>& origins, +bool QuotaDatabase::RegisterInitialStorageKeyInfo( + const std::set<StorageKey>& storage_keys, StorageType type) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyOpen(true)) + if (LazyOpen(LazyOpenMode::kCreateIfNotFound) != QuotaError::kNone) return false; - for (const auto& origin : origins) { + for (const auto& storage_key : storage_keys) { static constexpr char kSql[] = // clang-format off "INSERT OR IGNORE INTO buckets(" @@ -478,9 +379,9 @@ bool QuotaDatabase::RegisterInitialOriginInfo( "VALUES (?, ?, ?, 0, 0, 0, ?, 0)"; // clang-format on sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindString(0, origin.GetURL().spec()); + statement.BindString(0, storage_key.Serialize()); statement.BindInt(1, static_cast<int>(type)); - statement.BindString(2, kDefaultBucket); + statement.BindString(2, kDefaultBucketName); statement.BindTime(3, base::Time::Max()); if (!statement.Run()) @@ -491,11 +392,11 @@ bool QuotaDatabase::RegisterInitialOriginInfo( return true; } -bool QuotaDatabase::GetOriginInfo(const url::Origin& origin, - StorageType type, - QuotaDatabase::BucketTableEntry* entry) { +bool QuotaDatabase::GetStorageKeyInfo(const StorageKey& storage_key, + StorageType type, + QuotaDatabase::BucketTableEntry* entry) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyOpen(false)) + if (LazyOpen(LazyOpenMode::kFailIfNotFound) != QuotaError::kNone) return false; static constexpr char kSql[] = @@ -509,24 +410,24 @@ bool QuotaDatabase::GetOriginInfo(const url::Origin& origin, "WHERE origin = ? AND type = ? AND name = ?"; // clang-format on sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindString(0, origin.GetURL().spec()); + statement.BindString(0, storage_key.Serialize()); statement.BindInt(1, static_cast<int>(type)); - statement.BindString(2, kDefaultBucket); + statement.BindString(2, kDefaultBucketName); if (!statement.Step()) return false; - // TODO(crbug.com/889590): Use helper for url::Origin creation from string. - *entry = BucketTableEntry(statement.ColumnInt64(0), origin, type, - kDefaultBucket, statement.ColumnInt(1), + *entry = BucketTableEntry(BucketId(statement.ColumnInt64(0)), storage_key, + type, kDefaultBucketName, statement.ColumnInt(1), statement.ColumnTime(2), statement.ColumnTime(3)); return true; } -bool QuotaDatabase::GetBucketInfo(const int64_t bucket_id, +bool QuotaDatabase::GetBucketInfo(const BucketId bucket_id, QuotaDatabase::BucketTableEntry* entry) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyOpen(false)) + DCHECK(!bucket_id.is_null()); + if (LazyOpen(LazyOpenMode::kFailIfNotFound) != QuotaError::kNone) return false; static constexpr char kSql[] = @@ -542,24 +443,27 @@ bool QuotaDatabase::GetBucketInfo(const int64_t bucket_id, "WHERE id = ?"; // clang-format on sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindInt64(0, bucket_id); + statement.BindInt64(0, bucket_id.value()); if (!statement.Step()) return false; - // TODO(crbug.com/889590): Use helper for url::Origin creation from string. - *entry = BucketTableEntry( - bucket_id, url::Origin::Create(GURL(statement.ColumnString(0))), - static_cast<StorageType>(statement.ColumnInt(1)), - statement.ColumnString(2), statement.ColumnInt(3), - statement.ColumnTime(4), statement.ColumnTime(5)); + absl::optional<StorageKey> storage_key = + StorageKey::Deserialize(statement.ColumnString(0)); + if (!storage_key.has_value()) + return false; + + *entry = BucketTableEntry(bucket_id, std::move(storage_key).value(), + static_cast<StorageType>(statement.ColumnInt(1)), + statement.ColumnString(2), statement.ColumnInt(3), + statement.ColumnTime(4), statement.ColumnTime(5)); return true; } bool QuotaDatabase::DeleteHostQuota( const std::string& host, StorageType type) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyOpen(false)) + if (LazyOpen(LazyOpenMode::kFailIfNotFound) != QuotaError::kNone) return false; static constexpr char kSql[] = @@ -575,18 +479,17 @@ bool QuotaDatabase::DeleteHostQuota( return true; } -bool QuotaDatabase::DeleteOriginInfo(const url::Origin& origin, - StorageType type) { +bool QuotaDatabase::DeleteStorageKeyInfo(const StorageKey& storage_key, + StorageType type) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyOpen(false)) + if (LazyOpen(LazyOpenMode::kFailIfNotFound) != QuotaError::kNone) return false; static constexpr char kSql[] = - "DELETE FROM buckets WHERE origin = ? AND type = ? AND name = ?"; + "DELETE FROM buckets WHERE origin = ? AND type = ?"; sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindString(0, origin.GetURL().spec()); + statement.BindString(0, storage_key.Serialize()); statement.BindInt(1, static_cast<int>(type)); - statement.BindString(2, kDefaultBucket); if (!statement.Run()) return false; @@ -595,14 +498,15 @@ bool QuotaDatabase::DeleteOriginInfo(const url::Origin& origin, return true; } -bool QuotaDatabase::DeleteBucketInfo(const int64_t bucket_id) { +bool QuotaDatabase::DeleteBucketInfo(const BucketId bucket_id) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyOpen(false)) + DCHECK(!bucket_id.is_null()); + if (LazyOpen(LazyOpenMode::kFailIfNotFound) != QuotaError::kNone) return false; static constexpr char kSql[] = "DELETE FROM buckets WHERE id = ?"; sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindInt64(0, bucket_id); + statement.BindInt64(0, bucket_id.value()); if (!statement.Run()) return false; @@ -611,135 +515,89 @@ bool QuotaDatabase::DeleteBucketInfo(const int64_t bucket_id) { return true; } -bool QuotaDatabase::GetLRUOrigin(StorageType type, - const std::set<url::Origin>& exceptions, - SpecialStoragePolicy* special_storage_policy, - absl::optional<url::Origin>* origin) { +QuotaErrorOr<BucketInfo> QuotaDatabase::GetLRUBucket( + StorageType type, + const std::set<BucketId>& bucket_exceptions, + SpecialStoragePolicy* special_storage_policy) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(origin); - if (!LazyOpen(false)) - return false; + QuotaError open_error = LazyOpen(LazyOpenMode::kFailIfNotFound); + if (open_error != QuotaError::kNone) + return open_error; + // clang-format off static constexpr char kSql[] = - // clang-format off - "SELECT origin FROM buckets " - "WHERE type = ? AND name = ? " + "SELECT id, origin, name, expiration, quota " + "FROM buckets " + "WHERE type = ? " "ORDER BY last_accessed"; // clang-format on sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); statement.BindInt(0, static_cast<int>(type)); - statement.BindString(1, kDefaultBucket); while (statement.Step()) { - url::Origin read_origin = - url::Origin::Create(GURL(statement.ColumnString(0))); - if (base::Contains(exceptions, read_origin)) - continue; - - GURL read_gurl = read_origin.GetURL(); - if (special_storage_policy && - (special_storage_policy->IsStorageDurable(read_gurl) || - special_storage_policy->IsStorageUnlimited(read_gurl))) { + absl::optional<StorageKey> read_storage_key = + StorageKey::Deserialize(statement.ColumnString(1)); + if (!read_storage_key.has_value()) continue; - } - - *origin = read_origin; - return true; - } - - origin->reset(); - return statement.Succeeded(); -} -bool QuotaDatabase::GetLRUBucket(StorageType type, - const std::set<url::Origin>& exceptions, - SpecialStoragePolicy* special_storage_policy, - absl::optional<int64_t>* bucket_id) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(bucket_id); - if (!LazyOpen(false)) - return false; - - static constexpr char kSql[] = - // clang-format off - "SELECT id, origin FROM buckets " - "WHERE type = ? " - "ORDER BY last_accessed"; - // clang-format on - - sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindInt(0, static_cast<int>(type)); - - while (statement.Step()) { - int64_t read_bucket_id = statement.ColumnInt64(0); - url::Origin read_origin = - url::Origin::Create(GURL(statement.ColumnString(1))); - if (base::Contains(exceptions, read_origin)) + BucketId read_bucket_id = BucketId(statement.ColumnInt64(0)); + if (base::Contains(bucket_exceptions, read_bucket_id)) continue; // TODO(crbug/1176774): Once BucketTable holds bucket durability info, // add logic to allow durable buckets to also bypass eviction. - GURL read_gurl = read_origin.GetURL(); + GURL read_gurl = read_storage_key->origin().GetURL(); if (special_storage_policy && (special_storage_policy->IsStorageDurable(read_gurl) || special_storage_policy->IsStorageUnlimited(read_gurl))) { continue; } - - *bucket_id = read_bucket_id; - return true; + return BucketInfo(read_bucket_id, std::move(read_storage_key).value(), type, + statement.ColumnString(2), statement.ColumnTime(3), + statement.ColumnInt(4)); } - - bucket_id->reset(); - return statement.Succeeded(); + return QuotaError::kNotFound; } -bool QuotaDatabase::GetOriginsModifiedBetween(StorageType type, - std::set<url::Origin>* origins, - base::Time begin, - base::Time end) { +QuotaErrorOr<std::set<StorageKey>> QuotaDatabase::GetStorageKeysForType( + StorageType type) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(origins); - if (!LazyOpen(false)) - return false; + QuotaError open_error = LazyOpen(LazyOpenMode::kFailIfNotFound); + if (open_error != QuotaError::kNone) + return open_error; - DCHECK(!begin.is_max()); - DCHECK(end != base::Time()); static constexpr char kSql[] = - // clang-format off - "SELECT origin FROM buckets " - "WHERE type = ? AND name = ?" - "AND last_modified >= ? AND last_modified < ?"; - // clang-format on + "SELECT DISTINCT origin FROM buckets WHERE type = ?"; sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); statement.BindInt(0, static_cast<int>(type)); - statement.BindString(1, kDefaultBucket); - statement.BindTime(2, begin); - statement.BindTime(3, end); - origins->clear(); - while (statement.Step()) - origins->insert(url::Origin::Create(GURL(statement.ColumnString(0)))); - - return statement.Succeeded(); + std::set<StorageKey> storage_keys; + while (statement.Step()) { + absl::optional<StorageKey> read_storage_key = + StorageKey::Deserialize(statement.ColumnString(0)); + if (!read_storage_key.has_value()) + continue; + storage_keys.insert(read_storage_key.value()); + } + return storage_keys; } -bool QuotaDatabase::GetBucketsModifiedBetween(StorageType type, - std::set<int64_t>* bucket_ids, - base::Time begin, - base::Time end) { +QuotaErrorOr<std::set<BucketInfo>> QuotaDatabase::GetBucketsModifiedBetween( + StorageType type, + base::Time begin, + base::Time end) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(bucket_ids); - if (!LazyOpen(false)) - return false; + QuotaError open_error = LazyOpen(LazyOpenMode::kFailIfNotFound); + if (open_error != QuotaError::kNone) + return open_error; DCHECK(!begin.is_max()); DCHECK(end != base::Time()); + // clang-format off static constexpr char kSql[] = - // clang-format off - "SELECT id FROM buckets " + "SELECT id, origin, name, expiration, quota FROM buckets " "WHERE type = ? AND last_modified >= ? AND last_modified < ?"; // clang-format on @@ -748,25 +606,32 @@ bool QuotaDatabase::GetBucketsModifiedBetween(StorageType type, statement.BindTime(1, begin); statement.BindTime(2, end); - bucket_ids->clear(); - while (statement.Step()) - bucket_ids->insert(statement.ColumnInt64(0)); - - return statement.Succeeded(); + std::set<BucketInfo> buckets; + while (statement.Step()) { + absl::optional<StorageKey> read_storage_key = + StorageKey::Deserialize(statement.ColumnString(1)); + if (!read_storage_key.has_value()) + continue; + buckets.emplace( + BucketInfo(BucketId(statement.ColumnInt64(0)), read_storage_key.value(), + type, statement.ColumnString(2), statement.ColumnTime(3), + statement.ColumnInt(4))); + } + return buckets; } -bool QuotaDatabase::IsOriginDatabaseBootstrapped() { +bool QuotaDatabase::IsBootstrappedForEviction() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyOpen(true)) + if (LazyOpen(LazyOpenMode::kCreateIfNotFound) != QuotaError::kNone) return false; int flag = 0; return meta_table_->GetValue(kIsOriginTableBootstrapped, &flag) && flag; } -bool QuotaDatabase::SetOriginDatabaseBootstrapped(bool bootstrap_flag) { +bool QuotaDatabase::SetBootstrappedForEviction(bool bootstrap_flag) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyOpen(true)) + if (LazyOpen(LazyOpenMode::kCreateIfNotFound) != QuotaError::kNone) return false; return meta_table_->SetValue(kIsOriginTableBootstrapped, bootstrap_flag); @@ -795,73 +660,98 @@ void QuotaDatabase::ScheduleCommit() { this, &QuotaDatabase::Commit); } -bool QuotaDatabase::LazyOpen(bool create_if_needed) { +QuotaError QuotaDatabase::LazyOpen(LazyOpenMode mode) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (db_) - return true; + return QuotaError::kNone; // If we tried and failed once, don't try again in the same session // to avoid creating an incoherent mess on disk. if (is_disabled_) - return false; + return QuotaError::kDatabaseError; bool in_memory_only = db_file_path_.empty(); - if (!create_if_needed && + if (mode == LazyOpenMode::kFailIfNotFound && (in_memory_only || !base::PathExists(db_file_path_))) { - return false; + return QuotaError::kNotFound; } - db_ = std::make_unique<sql::Database>(); + db_ = std::make_unique<sql::Database>(sql::DatabaseOptions{ + .exclusive_locking = true, + .page_size = 4096, + .cache_size = 500, + }); meta_table_ = std::make_unique<sql::MetaTable>(); db_->set_histogram_tag("Quota"); - bool opened = false; - if (in_memory_only) { - opened = db_->OpenInMemory(); - } else if (!base::CreateDirectory(db_file_path_.DirName())) { - LOG(ERROR) << "Failed to create quota database directory."; - } else { - opened = db_->Open(db_file_path_); - if (opened) - db_->Preload(); - } - - if (!opened || !EnsureDatabaseVersion()) { + if (!OpenDatabase() || !EnsureDatabaseVersion()) { LOG(ERROR) << "Could not open the quota database, resetting."; if (!ResetSchema()) { LOG(ERROR) << "Failed to reset the quota database."; is_disabled_ = true; db_.reset(); meta_table_.reset(); - return false; + return QuotaError::kDatabaseError; } } // Start a long-running transaction. db_->BeginTransaction(); + return QuotaError::kNone; +} + +bool QuotaDatabase::OpenDatabase() { + // Open in memory database. + if (db_file_path_.empty()) { + if (db_->OpenInMemory()) + return true; + RecordDatabaseResetHistogram(DatabaseResetReason::kOpenInMemoryDatabase); + return false; + } + + if (!base::CreateDirectory(db_file_path_.DirName())) { + RecordDatabaseResetHistogram(DatabaseResetReason::kCreateDirectory); + return false; + } + + if (!db_->Open(db_file_path_)) { + RecordDatabaseResetHistogram(DatabaseResetReason::kOpenDatabase); + return false; + } + + db_->Preload(); return true; } bool QuotaDatabase::EnsureDatabaseVersion() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!sql::MetaTable::DoesTableExist(db_.get())) - return CreateSchema(); + if (!sql::MetaTable::DoesTableExist(db_.get())) { + if (CreateSchema()) + return true; + RecordDatabaseResetHistogram(DatabaseResetReason::kCreateSchema); + return false; + } if (!meta_table_->Init(db_.get(), kQuotaDatabaseCurrentSchemaVersion, - kQuotaDatabaseCompatibleVersion)) + kQuotaDatabaseCompatibleVersion)) { + RecordDatabaseResetHistogram(DatabaseResetReason::kInitMetaTable); return false; + } if (meta_table_->GetCompatibleVersionNumber() > kQuotaDatabaseCurrentSchemaVersion) { + RecordDatabaseResetHistogram(DatabaseResetReason::kDatabaseVersionTooNew); LOG(WARNING) << "Quota database is too new."; return false; } if (meta_table_->GetVersionNumber() < kQuotaDatabaseCurrentSchemaVersion) { - if (!QuotaDatabaseMigrations::UpgradeSchema(*this)) - return ResetSchema(); + if (!QuotaDatabaseMigrations::UpgradeSchema(*this)) { + RecordDatabaseResetHistogram(DatabaseResetReason::kDatabaseMigration); + return false; + } } #if DCHECK_IS_ON() @@ -943,7 +833,7 @@ bool QuotaDatabase::ResetSchema() { return false; base::AutoReset<bool> auto_reset(&is_recreating_, true); - return LazyOpen(true); + return LazyOpen(LazyOpenMode::kCreateIfNotFound) == QuotaError::kNone; } bool QuotaDatabase::InsertOrReplaceHostQuota(const std::string& host, @@ -965,7 +855,7 @@ bool QuotaDatabase::InsertOrReplaceHostQuota(const std::string& host, bool QuotaDatabase::DumpQuotaTable(const QuotaTableCallback& callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyOpen(true)) + if (LazyOpen(LazyOpenMode::kCreateIfNotFound) != QuotaError::kNone) return false; static constexpr char kSql[] = "SELECT * FROM quota"; @@ -987,7 +877,7 @@ bool QuotaDatabase::DumpQuotaTable(const QuotaTableCallback& callback) { bool QuotaDatabase::DumpBucketTable(const BucketTableCallback& callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyOpen(true)) + if (LazyOpen(LazyOpenMode::kCreateIfNotFound) != QuotaError::kNone) return false; static constexpr char kSql[] = @@ -1005,8 +895,13 @@ bool QuotaDatabase::DumpBucketTable(const BucketTableCallback& callback) { sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); while (statement.Step()) { - BucketTableEntry entry(statement.ColumnInt64(0), - url::Origin::Create(GURL(statement.ColumnString(1))), + BucketId bucket_id = BucketId(statement.ColumnInt64(0)); + absl::optional<StorageKey> storage_key = + StorageKey::Deserialize(statement.ColumnString(1)); + if (!storage_key.has_value()) + continue; + + BucketTableEntry entry(std::move(bucket_id), std::move(storage_key).value(), static_cast<StorageType>(statement.ColumnInt(2)), statement.ColumnString(3), statement.ColumnInt(4), statement.ColumnTime(5), statement.ColumnTime(6)); @@ -1018,6 +913,58 @@ bool QuotaDatabase::DumpBucketTable(const BucketTableCallback& callback) { return statement.Succeeded(); } +QuotaErrorOr<BucketInfo> QuotaDatabase::CreateBucketInternal( + const blink::StorageKey& storage_key, + StorageType type, + const std::string& bucket_name, + int use_count, + base::Time last_accessed, + base::Time last_modified) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // TODO(crbug/1210259): Add DCHECKs for input validation. + QuotaError open_error = LazyOpen(LazyOpenMode::kCreateIfNotFound); + if (open_error != QuotaError::kNone) + return open_error; + + static constexpr char kSql[] = + // clang-format off + "INSERT INTO buckets(" + "origin," + "type," + "name," + "use_count," + "last_accessed," + "last_modified," + "expiration," + "quota) " + "VALUES (?, ?, ?, ?, ?, ?, ?, 0)"; + // clang-format on + sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); + statement.BindString(0, storage_key.Serialize()); + statement.BindInt(1, static_cast<int>(type)); + statement.BindString(2, bucket_name); + statement.BindInt(3, use_count); + statement.BindTime(4, last_accessed); + statement.BindTime(5, last_modified); + statement.BindTime(6, base::Time::Max()); + + if (!statement.Run()) + return QuotaError::kDatabaseError; + + ScheduleCommit(); + + int64_t bucket_id = db_->GetLastInsertRowId(); + DCHECK_GT(bucket_id, 0); + return BucketInfo(BucketId(bucket_id), storage_key, type, bucket_name, + base::Time::Max(), 0); +} + +bool operator==(const QuotaDatabase::QuotaTableEntry& lhs, + const QuotaDatabase::QuotaTableEntry& rhs) { + return std::tie(lhs.host, lhs.type, lhs.quota) == + std::tie(rhs.host, rhs.type, rhs.quota); +} + bool operator<(const QuotaDatabase::QuotaTableEntry& lhs, const QuotaDatabase::QuotaTableEntry& rhs) { return std::tie(lhs.host, lhs.type, lhs.quota) < @@ -1026,8 +973,8 @@ bool operator<(const QuotaDatabase::QuotaTableEntry& lhs, bool operator<(const QuotaDatabase::BucketTableEntry& lhs, const QuotaDatabase::BucketTableEntry& rhs) { - return std::tie(lhs.origin, lhs.type, lhs.use_count, lhs.last_accessed) < - std::tie(rhs.origin, rhs.type, rhs.use_count, rhs.last_accessed); + return std::tie(lhs.storage_key, lhs.type, lhs.use_count, lhs.last_accessed) < + std::tie(rhs.storage_key, rhs.type, rhs.use_count, rhs.last_accessed); } } // namespace storage diff --git a/chromium/storage/browser/quota/quota_database.h b/chromium/storage/browser/quota/quota_database.h index 416d068b920..a9ce00f1c7d 100644 --- a/chromium/storage/browser/quota/quota_database.h +++ b/chromium/storage/browser/quota/quota_database.h @@ -19,10 +19,14 @@ #include "base/sequence_checker.h" #include "base/time/time.h" #include "base/timer/timer.h" -#include "base/util/type_safety/id_type.h" +#include "base/types/id_type.h" +#include "components/services/storage/public/cpp/buckets/bucket_id.h" +#include "components/services/storage/public/cpp/buckets/bucket_info.h" +#include "components/services/storage/public/cpp/buckets/constants.h" #include "components/services/storage/public/cpp/quota_error_or.h" +#include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h" -#include "url/origin.h" namespace sql { class Database; @@ -33,8 +37,19 @@ namespace storage { class SpecialStoragePolicy; -// IDs will always be generated by SQLite, and all valid BucketIds are positive. -using BucketId = util::IdType64<class BucketTag>; +// These values are logged to UMA. Entries should not be renumbered and numeric +// values should never be reused. Please keep in sync with "DatabaseResetReason" +// in tools/metrics/histograms/enums.xml. +enum class DatabaseResetReason { + kOpenDatabase = 0, + kOpenInMemoryDatabase = 1, + kCreateSchema = 2, + kDatabaseMigration = 3, + kDatabaseVersionTooNew = 4, + kInitMetaTable = 5, + kCreateDirectory = 6, + kMaxValue = kCreateDirectory +}; // Stores all quota managed origin bucket data and metadata. // @@ -45,19 +60,20 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDatabase { public: struct COMPONENT_EXPORT(STORAGE_BROWSER) BucketTableEntry { BucketTableEntry(); - BucketTableEntry(int64_t bucket_id, - url::Origin origin, + BucketTableEntry(BucketId bucket_id, + blink::StorageKey storage_key, blink::mojom::StorageType type, std::string name, int use_count, const base::Time& last_accessed, const base::Time& last_modified); + ~BucketTableEntry(); BucketTableEntry(const BucketTableEntry&); BucketTableEntry& operator=(const BucketTableEntry&); - int64_t bucket_id = -1; - url::Origin origin; + BucketId bucket_id; + blink::StorageKey storage_key; blink::mojom::StorageType type = blink::mojom::StorageType::kUnknown; std::string name; int use_count = 0; @@ -65,6 +81,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDatabase { base::Time last_modified; }; + enum class LazyOpenMode { kCreateIfNotFound, kFailIfNotFound }; + // If 'path' is empty, an in memory database will be used. explicit QuotaDatabase(const base::FilePath& path); ~QuotaDatabase(); @@ -80,117 +98,103 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDatabase { int64_t quota); bool DeleteHostQuota(const std::string& host, blink::mojom::StorageType type); - // Creates a bucket with `bucket_name` for the `origin` and returns the bucket - // id. Returns an QuotaError if a bucket with the same `bucket_name` for an - // `origin` already exists or if the operation has failed. + // Gets the bucket with `bucket_name` for the `storage_key` for StorageType + // kTemporary and returns the BucketInfo. If one doesn't exist, it creates + // a new bucket with the specified policies. Returns a QuotaError if the + // operation has failed. // TODO(crbug/1203467): Include more policies when supported. - QuotaErrorOr<BucketId> CreateBucket(const url::Origin& origin, - const std::string& bucket_name); - - // Retrieves the bucket id of the bucket with `bucket_name` for `origin`. - // If one does not exist, it will return an empty BucketId. Returns an error - // if the operation has failed. - QuotaErrorOr<BucketId> GetBucketId(const url::Origin& origin, - const std::string& bucket_name); + QuotaErrorOr<BucketInfo> GetOrCreateBucket( + const blink::StorageKey& storage_key, + const std::string& bucket_name); + + // TODO(crbug.com/1208141): Remove `storage_type` when the only supported + // StorageType is kTemporary. + QuotaErrorOr<BucketInfo> CreateBucketForTesting( + const blink::StorageKey& storage_key, + const std::string& bucket_name, + blink::mojom::StorageType storage_type); + + // Retrieves BucketInfo of the bucket with `bucket_name` for `storage_key`. + // Returns a QuotaError::kEntryNotFound if the bucket does not exist, or + // a QuotaError::kDatabaseError if the operation has failed. + QuotaErrorOr<BucketInfo> GetBucket(const blink::StorageKey& storage_key, + const std::string& bucket_name, + blink::mojom::StorageType storage_type); // TODO(crbug.com/1202167): Remove once all usages have updated to use // SetBucketLastAccessTime. - bool SetOriginLastAccessTime(const url::Origin& origin, - blink::mojom::StorageType type, - base::Time last_accessed); + bool SetStorageKeyLastAccessTime(const blink::StorageKey& storage_key, + blink::mojom::StorageType type, + base::Time last_accessed); // Called by QuotaClient implementers to update when the bucket was last - // accessed. - bool SetBucketLastAccessTime(int64_t bucket_id, base::Time last_accessed); + // accessed. If `bucket_id` refers to a bucket with an opaque StorageKey, the + // bucket's last access time will not be updated and the function will return + // false. + bool SetBucketLastAccessTime(BucketId bucket_id, base::Time last_accessed); // TODO(crbug.com/1202167): Remove once all usages have updated to use // SetBucketLastModifiedTime. - bool SetOriginLastModifiedTime(const url::Origin& origin, - blink::mojom::StorageType type, - base::Time last_modified); + bool SetStorageKeyLastModifiedTime(const blink::StorageKey& storage_key, + blink::mojom::StorageType type, + base::Time last_modified); // Called by QuotaClient implementers to update when the bucket was last // modified. - bool SetBucketLastModifiedTime(int64_t bucket_id, base::Time last_modified); - - bool GetOriginLastEvictionTime(const url::Origin& origin, - blink::mojom::StorageType type, - base::Time* last_eviction_time); + bool SetBucketLastModifiedTime(BucketId bucket_id, base::Time last_modified); - // Sets the time the origin was last evicted. Returns whether the operation - // succeeded. - bool SetOriginLastEvictionTime(const url::Origin& origin, - blink::mojom::StorageType type, - base::Time last_eviction_time); - bool DeleteOriginLastEvictionTime(const url::Origin& origin, - blink::mojom::StorageType type); - - // Register initial `origins` info `type` to the database. + // Register initial `storage_keys` info `type` to the database. // This method is assumed to be called only after the installation or // the database schema reset. - bool RegisterInitialOriginInfo(const std::set<url::Origin>& origins, - blink::mojom::StorageType type); + bool RegisterInitialStorageKeyInfo( + const std::set<blink::StorageKey>& storage_keys, + blink::mojom::StorageType type); // TODO(crbug.com/1202167): Remove once all usages have been updated to use - // GetBucketInfo. Gets the BucketTableEntry for `origin`. Returns whether the - // record for an origin's default bucket could be found. - bool GetOriginInfo(const url::Origin& origin, - blink::mojom::StorageType type, - BucketTableEntry* entry); + // GetBucketInfo. Gets the BucketTableEntry for `storage_key`. Returns whether + // the record for a storage key's default bucket could be found. + bool GetStorageKeyInfo(const blink::StorageKey& storage_key, + blink::mojom::StorageType type, + BucketTableEntry* entry); // Gets the table entry for `bucket`. Returns whether the record for an // origin bucket can be found. - bool GetBucketInfo(int64_t bucket_id, BucketTableEntry* entry); + bool GetBucketInfo(BucketId bucket_id, BucketTableEntry* entry); - // TODO(crbug.com/1202167): Remove once all usages have been updated to use - // DeleteBucketInfo. Deletes the default bucket for `origin`. - bool DeleteOriginInfo(const url::Origin& origin, - blink::mojom::StorageType type); + // Removes all buckets for `storage_key` with `type`. + bool DeleteStorageKeyInfo(const blink::StorageKey& storage_key, + blink::mojom::StorageType type); // Deletes the specified bucket. - bool DeleteBucketInfo(int64_t bucket_id); - - // TODO(crbug.com/1202167): Remove once all usages have been updated to use - // GetLRUBucket. Sets `origin` to the least recently used origin of origins - // not included in `exceptions` and not granted the special unlimited storage - // right. Returns false when it fails in accessing the database. - // `origin` is set to nullopt when there is no matching origin. - // This is limited to the origin's default bucket. - bool GetLRUOrigin(blink::mojom::StorageType type, - const std::set<url::Origin>& exceptions, - SpecialStoragePolicy* special_storage_policy, - absl::optional<url::Origin>* origin); - - // Sets `bucket_id` to the least recently used bucket from origins not - // included in `exceptions` and not granted special unlimited storage right. - // Returns false when it fails in accessing the database. `bucket_id` is - // set to nullopt when there is no matching bucket. - bool GetLRUBucket(blink::mojom::StorageType type, - const std::set<url::Origin>& exceptions, - SpecialStoragePolicy* special_storage_policy, - absl::optional<int64_t>* bucket_id); - - // TODO(crbug.com/1202167): Remove once all usages have been updated to use - // GetBucketsModifiedBetween. Populates `origins` with the ones that have had - // their default bucket modified since the `begin` and until the `end`. - // Returns whether the operation succeeded. - bool GetOriginsModifiedBetween(blink::mojom::StorageType type, - std::set<url::Origin>* origins, - base::Time begin, - base::Time end); - - // Populates `bucket_ids` with the buckets that have been modified since the - // `begin` and until the `end`. Returns whether the operation succeeded. - bool GetBucketsModifiedBetween(blink::mojom::StorageType type, - std::set<int64_t>* bucket_ids, - base::Time begin, - base::Time end); - - // Returns false if SetOriginDatabaseBootstrapped has never - // been called before, which means existing origins may not have been + bool DeleteBucketInfo(BucketId bucket_id); + + // Returns the BucketInfo for the least recently used bucket. Will exclude + // buckets with ids in `bucket_exceptions` and origins that have the special + // unlimited storage policy. Returns a QuotaError if the operation has failed. + QuotaErrorOr<BucketInfo> GetLRUBucket( + blink::mojom::StorageType type, + const std::set<BucketId>& bucket_exceptions, + SpecialStoragePolicy* special_storage_policy); + + // Returns all storage keys for `type` in the bucket database. + QuotaErrorOr<std::set<blink::StorageKey>> GetStorageKeysForType( + blink::mojom::StorageType type); + + // Returns a set of buckets that have been modified since the `begin` and + // until the `end`. Returns a QuotaError if the operations has failed. + QuotaErrorOr<std::set<BucketInfo>> GetBucketsModifiedBetween( + blink::mojom::StorageType type, + base::Time begin, + base::Time end); + + // Returns false if SetBootstrappedForEviction() has never + // been called before, which means existing storage keys may not have been // registered. - bool IsOriginDatabaseBootstrapped(); - bool SetOriginDatabaseBootstrapped(bool bootstrap_flag); + bool IsBootstrappedForEviction(); + bool SetBootstrappedForEviction(bool bootstrap_flag); + + // Manually disable database to test database error scenarios for testing. + void SetDisabledForTesting(bool disable) { is_disabled_ = disable; } private: struct COMPONENT_EXPORT(STORAGE_BROWSER) QuotaTableEntry { @@ -198,6 +202,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDatabase { blink::mojom::StorageType type = blink::mojom::StorageType::kUnknown; int64_t quota = 0; }; + friend COMPONENT_EXPORT(STORAGE_BROWSER) bool operator==( + const QuotaTableEntry& lhs, + const QuotaTableEntry& rhs); friend COMPONENT_EXPORT(STORAGE_BROWSER) bool operator<( const QuotaTableEntry& lhs, const QuotaTableEntry& rhs); @@ -229,7 +236,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDatabase { void Commit(); void ScheduleCommit(); - bool LazyOpen(bool create_if_needed); + QuotaError LazyOpen(LazyOpenMode mode); + bool OpenDatabase(); bool EnsureDatabaseVersion(); bool ResetSchema(); bool UpgradeSchema(int current_version); @@ -245,6 +253,16 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDatabase { bool DumpQuotaTable(const QuotaTableCallback& callback); bool DumpBucketTable(const BucketTableCallback& callback); + // Adds a new bucket entry in the buckets table. Will return a + // QuotaError::kDatabaseError if the query fails. + QuotaErrorOr<BucketInfo> CreateBucketInternal( + const blink::StorageKey& storage_key, + blink::mojom::StorageType type, + const std::string& bucket_name, + int use_count, + base::Time last_accessed, + base::Time last_modified); + const base::FilePath db_file_path_; std::unique_ptr<sql::Database> db_; @@ -259,7 +277,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDatabase { friend class QuotaDatabaseMigrationsTest; friend class QuotaManagerImpl; - static const char kDefaultBucket[]; static const TableSchema kTables[]; static const size_t kTableCount; static const IndexSchema kIndexes[]; diff --git a/chromium/storage/browser/quota/quota_database_migrations.cc b/chromium/storage/browser/quota/quota_database_migrations.cc index 44f892a0667..f4c78254c91 100644 --- a/chromium/storage/browser/quota/quota_database_migrations.cc +++ b/chromium/storage/browser/quota/quota_database_migrations.cc @@ -23,14 +23,20 @@ bool QuotaDatabaseMigrations::UpgradeSchema(QuotaDatabase& quota_database) { return quota_database.ResetSchema(); if (quota_database.meta_table_->GetVersionNumber() == 5) { - if (!MigrateToVersion6(quota_database)) + if (!MigrateFromVersion5ToVersion7(quota_database)) return false; } - return quota_database.meta_table_->GetVersionNumber() == 6; + if (quota_database.meta_table_->GetVersionNumber() == 6) { + if (!MigrateFromVersion6ToVersion7(quota_database)) + return false; + } + + return quota_database.meta_table_->GetVersionNumber() == 7; } -bool QuotaDatabaseMigrations::MigrateToVersion6(QuotaDatabase& quota_database) { +bool QuotaDatabaseMigrations::MigrateFromVersion5ToVersion7( + QuotaDatabase& quota_database) { sql::Database* db = quota_database.db_.get(); sql::Transaction transaction(db); if (!transaction.Begin()) @@ -73,7 +79,7 @@ bool QuotaDatabaseMigrations::MigrateToVersion6(QuotaDatabase& quota_database) { // clang-format on sql::Statement import_origin_info_statement( db->GetCachedStatement(SQL_FROM_HERE, kImportOriginInfoSql)); - import_origin_info_statement.BindString(0, QuotaDatabase::kDefaultBucket); + import_origin_info_statement.BindString(0, kDefaultBucketName); import_origin_info_statement.BindTime(1, base::Time::Max()); if (!import_origin_info_statement.Run()) return false; @@ -100,24 +106,30 @@ bool QuotaDatabaseMigrations::MigrateToVersion6(QuotaDatabase& quota_database) { if (!db->Execute(kDeleteQuotaHostTableSql)) return false; - // Copy EvictionInfoTable data into the new eviction_info table. - const char kImportEvictionInfoSql[] = - // clang-format off - "INSERT INTO eviction_info(origin, type, last_eviction_time) " - "SELECT origin, type, last_eviction_time " - "FROM EvictionInfoTable"; - // clang-format on - sql::Statement import_eviction_info_statement( - db->GetCachedStatement(SQL_FROM_HERE, kImportEvictionInfoSql)); - if (!import_eviction_info_statement.Run()) - return false; - // Delete EvictionInfoTable. const char kDeleteEvictionInfoTableSql[] = "DROP TABLE EvictionInfoTable"; if (!db->Execute(kDeleteEvictionInfoTableSql)) return false; - quota_database.meta_table_->SetVersionNumber(6); + // Upgrade to version 7 since it already deletes EvictionInfoTable. + quota_database.meta_table_->SetVersionNumber(7); + quota_database.meta_table_->SetCompatibleVersionNumber(7); + return transaction.Commit(); +} + +bool QuotaDatabaseMigrations::MigrateFromVersion6ToVersion7( + QuotaDatabase& quota_database) { + sql::Database* db = quota_database.db_.get(); + sql::Transaction transaction(db); + if (!transaction.Begin()) + return false; + + const char kDeleteEvictionInfoTableSql[] = "DROP TABLE eviction_info"; + if (!db->Execute(kDeleteEvictionInfoTableSql)) + return false; + + quota_database.meta_table_->SetVersionNumber(7); + quota_database.meta_table_->SetCompatibleVersionNumber(7); return transaction.Commit(); } diff --git a/chromium/storage/browser/quota/quota_database_migrations.h b/chromium/storage/browser/quota/quota_database_migrations.h index 97a5b1ac581..b30f6362a2c 100644 --- a/chromium/storage/browser/quota/quota_database_migrations.h +++ b/chromium/storage/browser/quota/quota_database_migrations.h @@ -23,7 +23,8 @@ class QuotaDatabaseMigrations { static bool UpgradeSchema(QuotaDatabase& quota_database); private: - static bool MigrateToVersion6(QuotaDatabase& quota_database); + static bool MigrateFromVersion5ToVersion7(QuotaDatabase& quota_database); + static bool MigrateFromVersion6ToVersion7(QuotaDatabase& quota_database); }; } // namespace storage diff --git a/chromium/storage/browser/quota/quota_database_migrations_unittest.cc b/chromium/storage/browser/quota/quota_database_migrations_unittest.cc index 0752382b1f5..d5970f19d72 100644 --- a/chromium/storage/browser/quota/quota_database_migrations_unittest.cc +++ b/chromium/storage/browser/quota/quota_database_migrations_unittest.cc @@ -14,6 +14,13 @@ namespace storage { +namespace { + +const int kCurrentSchemaVersion = 7; +const int kCurrentCompatibleVersion = 7; + +} // namespace + class QuotaDatabaseMigrationsTest : public testing::Test { public: void SetUp() override { ASSERT_TRUE(temp_directory_.CreateUniqueTempDir()); } @@ -52,14 +59,15 @@ class QuotaDatabaseMigrationsTest : public testing::Test { void MigrateDatabase() { QuotaDatabase db(DbPath()); - EXPECT_TRUE(db.LazyOpen(true)); + EXPECT_EQ(db.LazyOpen(QuotaDatabase::LazyOpenMode::kCreateIfNotFound), + QuotaError::kNone); EXPECT_TRUE(db.db_.get()); } std::string GetCurrentSchema() { base::FilePath current_version_path = temp_directory_.GetPath().AppendASCII("current_version.db"); - EXPECT_TRUE(LoadDatabase("version_6.sql", current_version_path)); + EXPECT_TRUE(LoadDatabase("version_7.sql", current_version_path)); sql::Database db; EXPECT_TRUE(db.Open(current_version_path)); return db.GetSchema(); @@ -75,6 +83,13 @@ TEST_F(QuotaDatabaseMigrationsTest, UpgradeSchemaFromV5) { sql::Database db; ASSERT_TRUE(db.Open(DbPath())); + ASSERT_TRUE(sql::MetaTable::DoesTableExist(&db)); + sql::MetaTable meta_table; + ASSERT_TRUE( + meta_table.Init(&db, kCurrentSchemaVersion, kCurrentCompatibleVersion)); + ASSERT_EQ(meta_table.GetVersionNumber(), 5); + ASSERT_EQ(meta_table.GetCompatibleVersionNumber(), 2); + ASSERT_TRUE(db.DoesTableExist("HostQuotaTable")); ASSERT_TRUE(db.DoesTableExist("EvictionInfoTable")); ASSERT_TRUE(db.DoesTableExist("OriginInfoTable")); @@ -101,8 +116,14 @@ TEST_F(QuotaDatabaseMigrationsTest, UpgradeSchemaFromV5) { sql::Database db; ASSERT_TRUE(db.Open(DbPath())); + ASSERT_TRUE(sql::MetaTable::DoesTableExist(&db)); + sql::MetaTable meta_table; + ASSERT_TRUE( + meta_table.Init(&db, kCurrentSchemaVersion, kCurrentCompatibleVersion)); + ASSERT_EQ(meta_table.GetVersionNumber(), kCurrentSchemaVersion); + ASSERT_EQ(meta_table.GetCompatibleVersionNumber(), kCurrentSchemaVersion); + ASSERT_TRUE(db.DoesTableExist("quota")); - ASSERT_TRUE(db.DoesTableExist("eviction_info")); ASSERT_TRUE(db.DoesTableExist("buckets")); ASSERT_FALSE(db.DoesTableExist("HostQuotaTable")); ASSERT_FALSE(db.DoesTableExist("EvictionInfoTable")); @@ -128,4 +149,76 @@ TEST_F(QuotaDatabaseMigrationsTest, UpgradeSchemaFromV5) { } } +TEST_F(QuotaDatabaseMigrationsTest, UpgradeSchemaFromV6) { + ASSERT_TRUE(LoadDatabase("version_6.sql", DbPath())); + + { + sql::Database db; + ASSERT_TRUE(db.Open(DbPath())); + + ASSERT_TRUE(sql::MetaTable::DoesTableExist(&db)); + sql::MetaTable meta_table; + ASSERT_TRUE( + meta_table.Init(&db, kCurrentSchemaVersion, kCurrentCompatibleVersion)); + ASSERT_EQ(meta_table.GetVersionNumber(), 6); + ASSERT_EQ(meta_table.GetCompatibleVersionNumber(), 6); + + ASSERT_TRUE(db.DoesTableExist("quota")); + ASSERT_TRUE(db.DoesTableExist("buckets")); + ASSERT_TRUE(db.DoesTableExist("eviction_info")); + + // Check populated data. + EXPECT_EQ( + "1|http://a/|0|bucket_a|123|13260644621105493|13242931862595604|" + "9223372036854775807|0," + "2|http://b/|0|bucket_b|111|13250042735631065|13260999511438890|" + "9223372036854775807|1000," + "3|http://c/|1|bucket_c|321|13261163582572088|13261079941303629|" + "9223372036854775807|10000", + sql::test::ExecuteWithResults( + &db, "SELECT * FROM buckets ORDER BY origin ASC", "|", ",")); + + EXPECT_EQ("a.com,b.com,c.com", + sql::test::ExecuteWithResults( + &db, "SELECT host FROM quota ORDER BY host ASC", "|", ",")); + } + + MigrateDatabase(); + + // Verify upgraded schema. + { + sql::Database db; + ASSERT_TRUE(db.Open(DbPath())); + + ASSERT_TRUE(sql::MetaTable::DoesTableExist(&db)); + sql::MetaTable meta_table; + ASSERT_TRUE( + meta_table.Init(&db, kCurrentSchemaVersion, kCurrentCompatibleVersion)); + ASSERT_EQ(meta_table.GetVersionNumber(), kCurrentSchemaVersion); + ASSERT_EQ(meta_table.GetCompatibleVersionNumber(), kCurrentSchemaVersion); + + ASSERT_TRUE(db.DoesTableExist("quota")); + ASSERT_TRUE(db.DoesTableExist("buckets")); + ASSERT_FALSE(db.DoesTableExist("eviction_info")); + + // Check that buckets data is still present. + EXPECT_EQ( + "1|http://a/|0|bucket_a|123|13260644621105493|13242931862595604|" + "9223372036854775807|0," + "2|http://b/|0|bucket_b|111|13250042735631065|13260999511438890|" + "9223372036854775807|1000," + "3|http://c/|1|bucket_c|321|13261163582572088|13261079941303629|" + "9223372036854775807|10000", + sql::test::ExecuteWithResults( + &db, "SELECT * FROM buckets ORDER BY origin ASC", "|", ",")); + + // Check that quota data is still present. + EXPECT_EQ("a.com,b.com,c.com", + sql::test::ExecuteWithResults( + &db, "SELECT host FROM quota ORDER BY host ASC", "|", ",")); + + EXPECT_EQ(GetCurrentSchema(), db.GetSchema()); + } +} + } // namespace storage diff --git a/chromium/storage/browser/quota/quota_database_unittest.cc b/chromium/storage/browser/quota/quota_database_unittest.cc index 62028a519c3..008b65e426f 100644 --- a/chromium/storage/browser/quota/quota_database_unittest.cc +++ b/chromium/storage/browser/quota/quota_database_unittest.cc @@ -11,10 +11,13 @@ #include "base/bind.h" #include "base/callback.h" +#include "base/containers/contains.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" -#include "base/stl_util.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/task_environment.h" +#include "build/build_config.h" +#include "components/services/storage/public/cpp/buckets/constants.h" #include "sql/database.h" #include "sql/meta_table.h" #include "sql/statement.h" @@ -26,6 +29,8 @@ #include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h" #include "url/gurl.h" +using ::blink::StorageKey; + namespace storage { namespace { @@ -36,13 +41,6 @@ static const blink::mojom::StorageType kTemp = static const blink::mojom::StorageType kPerm = blink::mojom::StorageType::kPersistent; -const char kDefaultBucket[] = "default"; - -// TODO(crbug.com/889590): Replace with common converter. -url::Origin ToOrigin(const std::string& url) { - return url::Origin::Create(GURL(url)); -} - } // namespace // Test parameter indicates if the database should be created for incognito @@ -51,6 +49,7 @@ class QuotaDatabaseTest : public testing::TestWithParam<bool> { protected: using QuotaTableEntry = QuotaDatabase::QuotaTableEntry; using BucketTableEntry = QuotaDatabase::BucketTableEntry; + using LazyOpenMode = QuotaDatabase::LazyOpenMode; void SetUp() override { ASSERT_TRUE(temp_directory_.CreateUniqueTempDir()); } @@ -62,8 +61,8 @@ class QuotaDatabaseTest : public testing::TestWithParam<bool> { return temp_directory_.GetPath().AppendASCII("quota_manager.db"); } - bool LazyOpen(QuotaDatabase* db, bool create_if_needed) { - return db->LazyOpen(create_if_needed); + bool LazyOpen(QuotaDatabase* db, LazyOpenMode mode) { + return db->LazyOpen(mode) == QuotaError::kNone; } template <typename EntryType> @@ -135,8 +134,8 @@ class QuotaDatabaseTest : public testing::TestWithParam<bool> { quota_database->db_->GetCachedStatement(SQL_FROM_HERE, kSql)); ASSERT_TRUE(statement.is_valid()); - statement.BindInt64(0, entry.bucket_id); - statement.BindString(1, entry.origin.GetURL().spec()); + statement.BindInt64(0, entry.bucket_id.value()); + statement.BindString(1, entry.storage_key.Serialize()); statement.BindInt(2, static_cast<int>(entry.type)); statement.BindString(3, entry.name); statement.BindInt(4, entry.use_count); @@ -154,8 +153,8 @@ class QuotaDatabaseTest : public testing::TestWithParam<bool> { TEST_P(QuotaDatabaseTest, LazyOpen) { QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath()); - EXPECT_FALSE(LazyOpen(&db, /*create_if_needed=*/false)); - EXPECT_TRUE(LazyOpen(&db, /*create_if_needed=*/true)); + EXPECT_FALSE(LazyOpen(&db, LazyOpenMode::kFailIfNotFound)); + EXPECT_TRUE(LazyOpen(&db, LazyOpenMode::kCreateIfNotFound)); if (GetParam()) { // Path should not exist for incognito mode. @@ -167,7 +166,7 @@ TEST_P(QuotaDatabaseTest, LazyOpen) { TEST_P(QuotaDatabaseTest, HostQuota) { QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath()); - EXPECT_TRUE(LazyOpen(&db, /*create_if_needed=*/true)); + EXPECT_TRUE(LazyOpen(&db, LazyOpenMode::kCreateIfNotFound)); const char* kHost = "foo.com"; const int kQuota1 = 13579; @@ -199,136 +198,171 @@ TEST_P(QuotaDatabaseTest, HostQuota) { EXPECT_FALSE(db.GetHostQuota(kHost, kPerm, "a)); } -TEST_P(QuotaDatabaseTest, CreateBucket) { +TEST_P(QuotaDatabaseTest, GetOrCreateBucket) { QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath()); - EXPECT_TRUE(LazyOpen(&db, /*create_if_needed=*/true)); - url::Origin origin = ToOrigin("http://google/"); + EXPECT_TRUE(LazyOpen(&db, LazyOpenMode::kCreateIfNotFound)); + StorageKey storage_key = + StorageKey::CreateFromStringForTesting("http://google/"); std::string bucket_name = "google_bucket"; - QuotaErrorOr<BucketId> result = db.CreateBucket(origin, bucket_name); + QuotaErrorOr<BucketInfo> result = + db.GetOrCreateBucket(storage_key, bucket_name); ASSERT_TRUE(result.ok()); - ASSERT_FALSE(result.value().is_null()); - // Trying to create an existing bucket should return false. - result = db.CreateBucket(origin, bucket_name); - ASSERT_FALSE(result.ok()); - EXPECT_EQ(result.error(), QuotaError::kEntryExistsError); + BucketInfo created_bucket = result.value(); + ASSERT_GT(created_bucket.id.value(), 0); + ASSERT_EQ(created_bucket.name, bucket_name); + ASSERT_EQ(created_bucket.storage_key, storage_key); + ASSERT_EQ(created_bucket.type, kTemp); + + // Should return the same bucket when querying again. + result = db.GetOrCreateBucket(storage_key, bucket_name); + ASSERT_TRUE(result.ok()); + + BucketInfo retrieved_bucket = result.value(); + ASSERT_EQ(retrieved_bucket.id, created_bucket.id); + ASSERT_EQ(retrieved_bucket.name, created_bucket.name); + ASSERT_EQ(retrieved_bucket.storage_key, created_bucket.storage_key); + ASSERT_EQ(retrieved_bucket.type, created_bucket.type); } -TEST_P(QuotaDatabaseTest, GetBucketId) { +TEST_P(QuotaDatabaseTest, GetBucket) { QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath()); - EXPECT_TRUE(LazyOpen(&db, /*create_if_needed=*/true)); + EXPECT_TRUE(LazyOpen(&db, LazyOpenMode::kCreateIfNotFound)); // Add a bucket entry into the bucket table. - url::Origin origin = ToOrigin("http://google/"); + StorageKey storage_key = + StorageKey::CreateFromStringForTesting("http://google/"); std::string bucket_name = "google_bucket"; - QuotaErrorOr<BucketId> result = db.CreateBucket(origin, bucket_name); + QuotaErrorOr<BucketInfo> result = + db.CreateBucketForTesting(storage_key, bucket_name, kPerm); ASSERT_TRUE(result.ok()); - BucketId created_bucket_id = result.value(); - ASSERT_FALSE(created_bucket_id.is_null()); + BucketInfo created_bucket = result.value(); + ASSERT_GT(created_bucket.id.value(), 0); + ASSERT_EQ(created_bucket.name, bucket_name); + ASSERT_EQ(created_bucket.storage_key, storage_key); + ASSERT_EQ(created_bucket.type, kPerm); - db.GetBucketId(origin, bucket_name); + result = db.GetBucket(storage_key, bucket_name, kPerm); ASSERT_TRUE(result.ok()); - EXPECT_EQ(result.value(), created_bucket_id); + EXPECT_EQ(result.value().id, created_bucket.id); + EXPECT_EQ(result.value().name, created_bucket.name); + EXPECT_EQ(result.value().storage_key, created_bucket.storage_key); + ASSERT_EQ(result.value().type, created_bucket.type); // Can't retrieve buckets with name mismatch. - result = db.GetBucketId(origin, "does_not_exist"); - ASSERT_TRUE(result.ok()); - EXPECT_TRUE(result.value().is_null()); + result = db.GetBucket(storage_key, "does_not_exist", kPerm); + ASSERT_FALSE(result.ok()); + EXPECT_EQ(result.error(), QuotaError::kNotFound); - // Can't retrieve buckets with origin mismatch. - result = db.GetBucketId(ToOrigin("http://example/"), bucket_name); - ASSERT_TRUE(result.ok()); - EXPECT_TRUE(result.value().is_null()); + // Can't retrieve buckets with StorageKey mismatch. + result = + db.GetBucket(StorageKey::CreateFromStringForTesting("http://example/"), + bucket_name, kPerm); + ASSERT_FALSE(result.ok()); + EXPECT_EQ(result.error(), QuotaError::kNotFound); } -TEST_P(QuotaDatabaseTest, OriginLastAccessTimeLRU) { +TEST_P(QuotaDatabaseTest, GetBucketWithNoDb) { QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath()); - EXPECT_TRUE(LazyOpen(&db, /*create_if_needed=*/true)); + EXPECT_FALSE(LazyOpen(&db, LazyOpenMode::kFailIfNotFound)); - std::set<url::Origin> exceptions; - absl::optional<url::Origin> origin; - EXPECT_TRUE(db.GetLRUOrigin(kTemp, exceptions, nullptr, &origin)); - EXPECT_FALSE(origin.has_value()); + StorageKey storage_key = + StorageKey::CreateFromStringForTesting("http://google/"); + std::string bucket_name = "google_bucket"; + QuotaErrorOr<BucketInfo> result = + db.GetBucket(storage_key, bucket_name, kTemp); + ASSERT_FALSE(result.ok()); + EXPECT_EQ(result.error(), QuotaError::kNotFound); +} - const url::Origin kOrigin1 = ToOrigin("http://a/"); - const url::Origin kOrigin2 = ToOrigin("http://b/"); - const url::Origin kOrigin3 = ToOrigin("http://c/"); - const url::Origin kOrigin4 = ToOrigin("http://p/"); +// TODO(crbug.com/1216094): Update test to have its behavior on Fuchsia/Win +// match with other platforms, and enable test on all platforms. +#if !defined(OS_FUCHSIA) && !defined(OS_WIN) +TEST_F(QuotaDatabaseTest, GetBucketWithOpenDatabaseError) { + base::HistogramTester histograms; + sql::test::ScopedErrorExpecter expecter; + expecter.ExpectError(SQLITE_CANTOPEN); - // Adding three temporary storages, and - EXPECT_TRUE(db.SetOriginLastAccessTime(kOrigin1, kTemp, - base::Time::FromJavaTime(10))); - EXPECT_TRUE(db.SetOriginLastAccessTime(kOrigin2, kTemp, - base::Time::FromJavaTime(20))); - EXPECT_TRUE(db.SetOriginLastAccessTime(kOrigin3, kTemp, - base::Time::FromJavaTime(30))); + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + QuotaDatabase db(temp_dir.GetPath()); - // one persistent. - EXPECT_TRUE(db.SetOriginLastAccessTime(kOrigin4, kPerm, - base::Time::FromJavaTime(40))); + StorageKey storage_key = + StorageKey::CreateFromStringForTesting("http://google/"); + std::string bucket_name = "google_bucket"; + QuotaErrorOr<BucketInfo> result = + db.GetBucket(storage_key, bucket_name, kTemp); + ASSERT_FALSE(result.ok()); + EXPECT_EQ(result.error(), QuotaError::kDatabaseError); - EXPECT_TRUE(db.GetLRUOrigin(kTemp, exceptions, nullptr, &origin)); - EXPECT_EQ(kOrigin1, origin); + EXPECT_TRUE(expecter.SawExpectedErrors()); + histograms.ExpectTotalCount("Quota.QuotaDatabaseReset", 1); + histograms.ExpectBucketCount("Quota.QuotaDatabaseReset", + DatabaseResetReason::kOpenDatabase, 1); +} +#endif // !defined(OS_FUCHSIA) && !defined(OS_WIN) - // Test that unlimited origins are excluded from eviction, but - // protected origins are not excluded. - scoped_refptr<MockSpecialStoragePolicy> policy(new MockSpecialStoragePolicy); - policy->AddUnlimited(kOrigin1.GetURL()); - policy->AddProtected(kOrigin2.GetURL()); - EXPECT_TRUE(db.GetLRUOrigin(kTemp, exceptions, policy.get(), &origin)); - EXPECT_EQ(kOrigin2, origin); +TEST_P(QuotaDatabaseTest, DeleteStorageKeyInfo) { + QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath()); + EXPECT_TRUE(LazyOpen(&db, LazyOpenMode::kCreateIfNotFound)); - // Test that durable origins are excluded from eviction. - policy->AddDurable(kOrigin2.GetURL()); - EXPECT_TRUE(db.GetLRUOrigin(kTemp, exceptions, policy.get(), &origin)); - EXPECT_EQ(kOrigin3, origin); + const StorageKey storage_key = + StorageKey::CreateFromStringForTesting("http://example-a/"); + QuotaErrorOr<BucketInfo> temp_bucket1 = + db.CreateBucketForTesting(storage_key, "temp1", kTemp); + QuotaErrorOr<BucketInfo> temp_bucket2 = + db.CreateBucketForTesting(storage_key, "temp2", kTemp); + QuotaErrorOr<BucketInfo> perm_bucket = + db.CreateBucketForTesting(storage_key, "perm", kPerm); - exceptions.insert(kOrigin1); - EXPECT_TRUE(db.GetLRUOrigin(kTemp, exceptions, nullptr, &origin)); - EXPECT_EQ(kOrigin2, origin); + db.DeleteStorageKeyInfo(storage_key, kTemp); - exceptions.insert(kOrigin2); - EXPECT_TRUE(db.GetLRUOrigin(kTemp, exceptions, nullptr, &origin)); - EXPECT_EQ(kOrigin3, origin); + QuotaErrorOr<BucketInfo> result = + db.GetBucket(storage_key, temp_bucket1->name, kTemp); + ASSERT_FALSE(result.ok()); + ASSERT_EQ(result.error(), QuotaError::kNotFound); - exceptions.insert(kOrigin3); - EXPECT_TRUE(db.GetLRUOrigin(kTemp, exceptions, nullptr, &origin)); - EXPECT_FALSE(origin.has_value()); + result = db.GetBucket(storage_key, temp_bucket2->name, kTemp); + ASSERT_FALSE(result.ok()); + ASSERT_EQ(result.error(), QuotaError::kNotFound); - EXPECT_TRUE(db.SetOriginLastAccessTime(kOrigin1, kTemp, base::Time::Now())); + result = db.GetBucket(storage_key, perm_bucket->name, kPerm); + ASSERT_TRUE(result.ok()); - // Delete origin/type last access time information. - EXPECT_TRUE(db.DeleteOriginInfo(kOrigin3, kTemp)); + db.DeleteStorageKeyInfo(storage_key, kPerm); - // Querying again to see if the deletion has worked. - exceptions.clear(); - EXPECT_TRUE(db.GetLRUOrigin(kTemp, exceptions, nullptr, &origin)); - EXPECT_EQ(kOrigin2, origin); - - exceptions.insert(kOrigin1); - exceptions.insert(kOrigin2); - EXPECT_TRUE(db.GetLRUOrigin(kTemp, exceptions, nullptr, &origin)); - EXPECT_FALSE(origin.has_value()); + result = db.GetBucket(storage_key, perm_bucket->name, kPerm); + ASSERT_FALSE(result.ok()); + ASSERT_EQ(result.error(), QuotaError::kNotFound); } TEST_P(QuotaDatabaseTest, BucketLastAccessTimeLRU) { QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath()); - EXPECT_TRUE(LazyOpen(&db, /*create_if_needed=*/true)); + EXPECT_TRUE(LazyOpen(&db, LazyOpenMode::kCreateIfNotFound)); - std::set<url::Origin> exceptions; - absl::optional<int64_t> bucket_id; - EXPECT_TRUE(db.GetLRUBucket(kTemp, exceptions, nullptr, &bucket_id)); - EXPECT_FALSE(bucket_id.has_value()); + std::set<BucketId> bucket_exceptions; + QuotaErrorOr<BucketInfo> result = + db.GetLRUBucket(kTemp, bucket_exceptions, nullptr); + EXPECT_FALSE(result.ok()); + EXPECT_EQ(result.error(), QuotaError::kNotFound); // Insert bucket entries into BucketTable. - base::Time now(base::Time::Now()); + base::Time now = base::Time::Now(); using Entry = QuotaDatabase::BucketTableEntry; - Entry bucket1 = Entry(0, ToOrigin("http://a/"), kTemp, "A", 99, now, now); - Entry bucket2 = Entry(1, ToOrigin("http://b/"), kTemp, "B", 0, now, now); - Entry bucket3 = Entry(2, ToOrigin("http://c/"), kTemp, "C", 1, now, now); - Entry bucket4 = Entry(3, ToOrigin("http://d/"), kPerm, "D", 5, now, now); + Entry bucket1 = Entry( + BucketId(1), StorageKey::CreateFromStringForTesting("http://example-a/"), + kTemp, kDefaultBucketName, 99, now, now); + Entry bucket2 = Entry( + BucketId(2), StorageKey::CreateFromStringForTesting("http://example-b/"), + kTemp, kDefaultBucketName, 0, now, now); + Entry bucket3 = Entry( + BucketId(3), StorageKey::CreateFromStringForTesting("http://example-c/"), + kTemp, "bucket_c", 1, now, now); + Entry bucket4 = Entry( + BucketId(4), StorageKey::CreateFromStringForTesting("http://example-d/"), + kPerm, "bucket_d", 5, now, now); Entry kTableEntries[] = {bucket1, bucket2, bucket3, bucket4}; AssignBucketTable(&db, kTableEntries); @@ -344,304 +378,229 @@ TEST_P(QuotaDatabaseTest, BucketLastAccessTimeLRU) { EXPECT_TRUE(db.SetBucketLastAccessTime(bucket4.bucket_id, base::Time::FromJavaTime(40))); - EXPECT_TRUE(db.GetLRUBucket(kTemp, exceptions, nullptr, &bucket_id)); - EXPECT_EQ(bucket1.bucket_id, bucket_id); + result = db.GetLRUBucket(kTemp, bucket_exceptions, nullptr); + EXPECT_TRUE(result.ok()); + EXPECT_EQ(bucket1.bucket_id, result.value().id); // Test that unlimited origins are excluded from eviction, but // protected origins are not excluded. scoped_refptr<MockSpecialStoragePolicy> policy(new MockSpecialStoragePolicy); - policy->AddUnlimited(bucket1.origin.GetURL()); - policy->AddProtected(bucket2.origin.GetURL()); - EXPECT_TRUE(db.GetLRUBucket(kTemp, exceptions, policy.get(), &bucket_id)); - EXPECT_EQ(bucket2.bucket_id, bucket_id); + policy->AddUnlimited(bucket1.storage_key.origin().GetURL()); + policy->AddProtected(bucket2.storage_key.origin().GetURL()); + result = db.GetLRUBucket(kTemp, bucket_exceptions, policy.get()); + EXPECT_TRUE(result.ok()); + EXPECT_EQ(bucket2.bucket_id, result.value().id); // Test that durable origins are excluded from eviction. - policy->AddDurable(bucket2.origin.GetURL()); - EXPECT_TRUE(db.GetLRUBucket(kTemp, exceptions, policy.get(), &bucket_id)); - EXPECT_EQ(bucket3.bucket_id, bucket_id); - - exceptions.insert(bucket1.origin); - EXPECT_TRUE(db.GetLRUBucket(kTemp, exceptions, nullptr, &bucket_id)); - EXPECT_EQ(bucket2.bucket_id, bucket_id); - - exceptions.insert(bucket2.origin); - EXPECT_TRUE(db.GetLRUBucket(kTemp, exceptions, nullptr, &bucket_id)); - EXPECT_EQ(bucket3.bucket_id, bucket_id); - - exceptions.insert(bucket3.origin); - EXPECT_TRUE(db.GetLRUBucket(kTemp, exceptions, nullptr, &bucket_id)); - EXPECT_FALSE(bucket_id.has_value()); + policy->AddDurable(bucket2.storage_key.origin().GetURL()); + result = db.GetLRUBucket(kTemp, bucket_exceptions, policy.get()); + EXPECT_TRUE(result.ok()); + EXPECT_EQ(bucket3.bucket_id, result.value().id); + + // Bucket exceptions exclude specified buckets. + bucket_exceptions.insert(bucket1.bucket_id); + result = db.GetLRUBucket(kTemp, bucket_exceptions, nullptr); + EXPECT_TRUE(result.ok()); + EXPECT_EQ(bucket2.bucket_id, result.value().id); + + bucket_exceptions.insert(bucket2.bucket_id); + result = db.GetLRUBucket(kTemp, bucket_exceptions, nullptr); + EXPECT_TRUE(result.ok()); + EXPECT_EQ(bucket3.bucket_id, result.value().id); + + bucket_exceptions.insert(bucket3.bucket_id); + result = db.GetLRUBucket(kTemp, bucket_exceptions, nullptr); + EXPECT_FALSE(result.ok()); + EXPECT_EQ(result.error(), QuotaError::kNotFound); EXPECT_TRUE(db.SetBucketLastAccessTime(bucket1.bucket_id, base::Time::Now())); - // Delete origin/type last access time information. + // Delete storage_key/type last access time information. EXPECT_TRUE(db.DeleteBucketInfo(bucket3.bucket_id)); // Querying again to see if the deletion has worked. - exceptions.clear(); - EXPECT_TRUE(db.GetLRUBucket(kTemp, exceptions, nullptr, &bucket_id)); - EXPECT_EQ(bucket2.bucket_id, bucket_id); - - exceptions.insert(bucket1.origin); - exceptions.insert(bucket2.origin); - EXPECT_TRUE(db.GetLRUBucket(kTemp, exceptions, nullptr, &bucket_id)); - EXPECT_FALSE(bucket_id.has_value()); + bucket_exceptions.clear(); + result = db.GetLRUBucket(kTemp, bucket_exceptions, nullptr); + EXPECT_TRUE(result.ok()); + EXPECT_EQ(bucket2.bucket_id, result.value().id); + + bucket_exceptions.insert(bucket1.bucket_id); + bucket_exceptions.insert(bucket2.bucket_id); + result = db.GetLRUBucket(kTemp, bucket_exceptions, nullptr); + EXPECT_FALSE(result.ok()); + EXPECT_EQ(result.error(), QuotaError::kNotFound); } -TEST_P(QuotaDatabaseTest, OriginLastModifiedBetween) { +TEST_P(QuotaDatabaseTest, GetStorageKeysForType) { QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath()); - EXPECT_TRUE(LazyOpen(&db, /*create_if_needed=*/true)); - - std::set<url::Origin> origins; - EXPECT_TRUE(db.GetOriginsModifiedBetween(kTemp, &origins, base::Time(), - base::Time::Max())); - EXPECT_TRUE(origins.empty()); - - const url::Origin kOrigin1 = ToOrigin("http://a/"); - const url::Origin kOrigin2 = ToOrigin("http://b/"); - const url::Origin kOrigin3 = ToOrigin("http://c/"); - - // Report last mod time for the test origins. - EXPECT_TRUE(db.SetOriginLastModifiedTime(kOrigin1, kTemp, - base::Time::FromJavaTime(0))); - EXPECT_TRUE(db.SetOriginLastModifiedTime(kOrigin2, kTemp, - base::Time::FromJavaTime(10))); - EXPECT_TRUE(db.SetOriginLastModifiedTime(kOrigin3, kTemp, - base::Time::FromJavaTime(20))); - - EXPECT_TRUE(db.GetOriginsModifiedBetween(kTemp, &origins, base::Time(), - base::Time::Max())); - EXPECT_EQ(3U, origins.size()); - EXPECT_EQ(1U, origins.count(kOrigin1)); - EXPECT_EQ(1U, origins.count(kOrigin2)); - EXPECT_EQ(1U, origins.count(kOrigin3)); - - EXPECT_TRUE(db.GetOriginsModifiedBetween( - kTemp, &origins, base::Time::FromJavaTime(5), base::Time::Max())); - EXPECT_EQ(2U, origins.size()); - EXPECT_EQ(0U, origins.count(kOrigin1)); - EXPECT_EQ(1U, origins.count(kOrigin2)); - EXPECT_EQ(1U, origins.count(kOrigin3)); - - EXPECT_TRUE(db.GetOriginsModifiedBetween( - kTemp, &origins, base::Time::FromJavaTime(15), base::Time::Max())); - EXPECT_EQ(1U, origins.size()); - EXPECT_EQ(0U, origins.count(kOrigin1)); - EXPECT_EQ(0U, origins.count(kOrigin2)); - EXPECT_EQ(1U, origins.count(kOrigin3)); - - EXPECT_TRUE(db.GetOriginsModifiedBetween( - kTemp, &origins, base::Time::FromJavaTime(25), base::Time::Max())); - EXPECT_TRUE(origins.empty()); - - EXPECT_TRUE(db.GetOriginsModifiedBetween(kTemp, &origins, - base::Time::FromJavaTime(5), - base::Time::FromJavaTime(15))); - EXPECT_EQ(1U, origins.size()); - EXPECT_EQ(0U, origins.count(kOrigin1)); - EXPECT_EQ(1U, origins.count(kOrigin2)); - EXPECT_EQ(0U, origins.count(kOrigin3)); - - EXPECT_TRUE(db.GetOriginsModifiedBetween(kTemp, &origins, - base::Time::FromJavaTime(0), - base::Time::FromJavaTime(20))); - EXPECT_EQ(2U, origins.size()); - EXPECT_EQ(1U, origins.count(kOrigin1)); - EXPECT_EQ(1U, origins.count(kOrigin2)); - EXPECT_EQ(0U, origins.count(kOrigin3)); - - // Update origin1's mod time but for persistent storage. - EXPECT_TRUE(db.SetOriginLastModifiedTime(kOrigin1, kPerm, - base::Time::FromJavaTime(30))); - - // Must have no effects on temporary origins info. - EXPECT_TRUE(db.GetOriginsModifiedBetween( - kTemp, &origins, base::Time::FromJavaTime(5), base::Time::Max())); - EXPECT_EQ(2U, origins.size()); - EXPECT_EQ(0U, origins.count(kOrigin1)); - EXPECT_EQ(1U, origins.count(kOrigin2)); - EXPECT_EQ(1U, origins.count(kOrigin3)); - - // One more update for persistent origin2. - EXPECT_TRUE(db.SetOriginLastModifiedTime(kOrigin2, kPerm, - base::Time::FromJavaTime(40))); - - EXPECT_TRUE(db.GetOriginsModifiedBetween( - kPerm, &origins, base::Time::FromJavaTime(25), base::Time::Max())); - EXPECT_EQ(2U, origins.size()); - EXPECT_EQ(1U, origins.count(kOrigin1)); - EXPECT_EQ(1U, origins.count(kOrigin2)); - EXPECT_EQ(0U, origins.count(kOrigin3)); - - EXPECT_TRUE(db.GetOriginsModifiedBetween( - kPerm, &origins, base::Time::FromJavaTime(35), base::Time::Max())); - EXPECT_EQ(1U, origins.size()); - EXPECT_EQ(0U, origins.count(kOrigin1)); - EXPECT_EQ(1U, origins.count(kOrigin2)); - EXPECT_EQ(0U, origins.count(kOrigin3)); -} - -TEST_P(QuotaDatabaseTest, BucketLastModifiedBetween) { - QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath()); - EXPECT_TRUE(LazyOpen(&db, /*create_if_needed=*/true)); - - std::set<int64_t> bucket_ids; - EXPECT_TRUE(db.GetBucketsModifiedBetween(kTemp, &bucket_ids, base::Time(), - base::Time::Max())); - EXPECT_TRUE(bucket_ids.empty()); - - // Insert bucket entries into BucketTable. - base::Time now(base::Time::Now()); - using Entry = QuotaDatabase::BucketTableEntry; - Entry bucket1 = Entry(0, ToOrigin("http://a/"), kTemp, "A", 0, now, now); - Entry bucket2 = Entry(1, ToOrigin("http://b/"), kTemp, "B", 0, now, now); - Entry bucket3 = Entry(2, ToOrigin("http://c/"), kTemp, "C", 0, now, now); - Entry bucket4 = Entry(3, ToOrigin("http://d/"), kPerm, "D", 0, now, now); - Entry kTableEntries[] = {bucket1, bucket2, bucket3, bucket4}; - AssignBucketTable(&db, kTableEntries); + EXPECT_TRUE(LazyOpen(&db, LazyOpenMode::kCreateIfNotFound)); + + const StorageKey storage_key1 = + StorageKey::CreateFromStringForTesting("http://example-a/"); + const StorageKey storage_key2 = + StorageKey::CreateFromStringForTesting("http://example-b/"); + const StorageKey storage_key3 = + StorageKey::CreateFromStringForTesting("http://example-c/"); + + QuotaErrorOr<BucketInfo> temp_bucket1 = + db.CreateBucketForTesting(storage_key1, "bucket_a", kTemp); + QuotaErrorOr<BucketInfo> temp_bucket2 = + db.CreateBucketForTesting(storage_key2, "bucket_b", kTemp); + QuotaErrorOr<BucketInfo> perm_bucket1 = + db.CreateBucketForTesting(storage_key2, "bucket_b", kPerm); + QuotaErrorOr<BucketInfo> perm_bucket2 = + db.CreateBucketForTesting(storage_key3, "bucket_b", kPerm); + + QuotaErrorOr<std::set<StorageKey>> result = db.GetStorageKeysForType(kTemp); + ASSERT_TRUE(result.ok()); + ASSERT_TRUE(base::Contains(result.value(), storage_key1)); + ASSERT_TRUE(base::Contains(result.value(), storage_key2)); + ASSERT_FALSE(base::Contains(result.value(), storage_key3)); - // Report last mod time for the buckets. - EXPECT_TRUE(db.SetBucketLastModifiedTime(bucket1.bucket_id, - base::Time::FromJavaTime(0))); - EXPECT_TRUE(db.SetBucketLastModifiedTime(bucket2.bucket_id, - base::Time::FromJavaTime(10))); - EXPECT_TRUE(db.SetBucketLastModifiedTime(bucket3.bucket_id, - base::Time::FromJavaTime(20))); - EXPECT_TRUE(db.SetBucketLastModifiedTime(bucket4.bucket_id, - base::Time::FromJavaTime(30))); - - EXPECT_TRUE(db.GetBucketsModifiedBetween(kTemp, &bucket_ids, base::Time(), - base::Time::Max())); - EXPECT_EQ(3U, bucket_ids.size()); - EXPECT_EQ(1U, bucket_ids.count(bucket1.bucket_id)); - EXPECT_EQ(1U, bucket_ids.count(bucket2.bucket_id)); - EXPECT_EQ(1U, bucket_ids.count(bucket3.bucket_id)); - EXPECT_EQ(0U, bucket_ids.count(bucket4.bucket_id)); - - EXPECT_TRUE(db.GetBucketsModifiedBetween( - kTemp, &bucket_ids, base::Time::FromJavaTime(5), base::Time::Max())); - EXPECT_EQ(2U, bucket_ids.size()); - EXPECT_EQ(0U, bucket_ids.count(bucket1.bucket_id)); - EXPECT_EQ(1U, bucket_ids.count(bucket2.bucket_id)); - EXPECT_EQ(1U, bucket_ids.count(bucket3.bucket_id)); - EXPECT_EQ(0U, bucket_ids.count(bucket4.bucket_id)); - - EXPECT_TRUE(db.GetBucketsModifiedBetween( - kTemp, &bucket_ids, base::Time::FromJavaTime(15), base::Time::Max())); - EXPECT_EQ(1U, bucket_ids.size()); - EXPECT_EQ(0U, bucket_ids.count(bucket1.bucket_id)); - EXPECT_EQ(0U, bucket_ids.count(bucket2.bucket_id)); - EXPECT_EQ(1U, bucket_ids.count(bucket3.bucket_id)); - EXPECT_EQ(0U, bucket_ids.count(bucket4.bucket_id)); - - EXPECT_TRUE(db.GetBucketsModifiedBetween( - kTemp, &bucket_ids, base::Time::FromJavaTime(25), base::Time::Max())); - EXPECT_TRUE(bucket_ids.empty()); - - EXPECT_TRUE(db.GetBucketsModifiedBetween(kTemp, &bucket_ids, - base::Time::FromJavaTime(5), - base::Time::FromJavaTime(15))); - EXPECT_EQ(1U, bucket_ids.size()); - EXPECT_EQ(0U, bucket_ids.count(bucket1.bucket_id)); - EXPECT_EQ(1U, bucket_ids.count(bucket2.bucket_id)); - EXPECT_EQ(0U, bucket_ids.count(bucket3.bucket_id)); - EXPECT_EQ(0U, bucket_ids.count(bucket4.bucket_id)); - - EXPECT_TRUE(db.GetBucketsModifiedBetween(kTemp, &bucket_ids, - base::Time::FromJavaTime(0), - base::Time::FromJavaTime(20))); - EXPECT_EQ(2U, bucket_ids.size()); - EXPECT_EQ(1U, bucket_ids.count(bucket1.bucket_id)); - EXPECT_EQ(1U, bucket_ids.count(bucket2.bucket_id)); - EXPECT_EQ(0U, bucket_ids.count(bucket3.bucket_id)); - EXPECT_EQ(0U, bucket_ids.count(bucket4.bucket_id)); - - EXPECT_TRUE(db.GetBucketsModifiedBetween(kPerm, &bucket_ids, - base::Time::FromJavaTime(0), - base::Time::FromJavaTime(35))); - EXPECT_EQ(1U, bucket_ids.size()); - EXPECT_EQ(0U, bucket_ids.count(bucket1.bucket_id)); - EXPECT_EQ(0U, bucket_ids.count(bucket2.bucket_id)); - EXPECT_EQ(0U, bucket_ids.count(bucket3.bucket_id)); - EXPECT_EQ(1U, bucket_ids.count(bucket4.bucket_id)); + result = db.GetStorageKeysForType(kPerm); + ASSERT_TRUE(result.ok()); + ASSERT_FALSE(base::Contains(result.value(), storage_key1)); + ASSERT_TRUE(base::Contains(result.value(), storage_key2)); + ASSERT_TRUE(base::Contains(result.value(), storage_key3)); } -TEST_P(QuotaDatabaseTest, OriginLastEvicted) { +TEST_P(QuotaDatabaseTest, BucketLastModifiedBetween) { QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath()); - EXPECT_TRUE(LazyOpen(&db, /*create_if_needed=*/true)); - - const url::Origin kOrigin1 = ToOrigin("http://a/"); - const url::Origin kOrigin2 = ToOrigin("http://b/"); - const url::Origin kOrigin3 = ToOrigin("http://c/"); - - base::Time last_eviction_time; - EXPECT_FALSE( - db.GetOriginLastEvictionTime(kOrigin1, kTemp, &last_eviction_time)); - EXPECT_EQ(base::Time(), last_eviction_time); - - // Report last eviction time for the test origins. - EXPECT_TRUE(db.SetOriginLastEvictionTime(kOrigin1, kTemp, - base::Time::FromJavaTime(10))); - EXPECT_TRUE(db.SetOriginLastEvictionTime(kOrigin2, kTemp, - base::Time::FromJavaTime(20))); - EXPECT_TRUE(db.SetOriginLastEvictionTime(kOrigin3, kTemp, - base::Time::FromJavaTime(30))); - + EXPECT_TRUE(LazyOpen(&db, LazyOpenMode::kCreateIfNotFound)); + + QuotaErrorOr<std::set<BucketInfo>> result = + db.GetBucketsModifiedBetween(kTemp, base::Time(), base::Time::Max()); + EXPECT_TRUE(result.ok()); + std::set<BucketInfo> buckets = result.value(); + EXPECT_TRUE(buckets.empty()); + + QuotaErrorOr<BucketInfo> result1 = db.CreateBucketForTesting( + StorageKey::CreateFromStringForTesting("http://example-a/"), "bucket_a", + kTemp); + EXPECT_TRUE(result1.ok()); + BucketInfo bucket1 = result1.value(); + QuotaErrorOr<BucketInfo> result2 = db.CreateBucketForTesting( + StorageKey::CreateFromStringForTesting("http://example-b/"), "bucket_b", + kTemp); + EXPECT_TRUE(result2.ok()); + BucketInfo bucket2 = result2.value(); + QuotaErrorOr<BucketInfo> result3 = db.CreateBucketForTesting( + StorageKey::CreateFromStringForTesting("http://example-c/"), "bucket_c", + kTemp); + EXPECT_TRUE(result3.ok()); + BucketInfo bucket3 = result3.value(); + QuotaErrorOr<BucketInfo> result4 = db.CreateBucketForTesting( + StorageKey::CreateFromStringForTesting("http://example-d/"), "bucket_d", + kPerm); + EXPECT_TRUE(result4.ok()); + BucketInfo bucket4 = result4.value(); + + // Report last modified time for the buckets. EXPECT_TRUE( - db.GetOriginLastEvictionTime(kOrigin1, kTemp, &last_eviction_time)); - EXPECT_EQ(base::Time::FromJavaTime(10), last_eviction_time); + db.SetBucketLastModifiedTime(bucket1.id, base::Time::FromJavaTime(0))); EXPECT_TRUE( - db.GetOriginLastEvictionTime(kOrigin2, kTemp, &last_eviction_time)); - EXPECT_EQ(base::Time::FromJavaTime(20), last_eviction_time); + db.SetBucketLastModifiedTime(bucket2.id, base::Time::FromJavaTime(10))); EXPECT_TRUE( - db.GetOriginLastEvictionTime(kOrigin3, kTemp, &last_eviction_time)); - EXPECT_EQ(base::Time::FromJavaTime(30), last_eviction_time); - - // Delete last eviction times for the test origins. - EXPECT_TRUE(db.DeleteOriginLastEvictionTime(kOrigin1, kTemp)); - EXPECT_TRUE(db.DeleteOriginLastEvictionTime(kOrigin2, kTemp)); - EXPECT_TRUE(db.DeleteOriginLastEvictionTime(kOrigin3, kTemp)); - - last_eviction_time = base::Time(); - EXPECT_FALSE( - db.GetOriginLastEvictionTime(kOrigin1, kTemp, &last_eviction_time)); - EXPECT_EQ(base::Time(), last_eviction_time); - EXPECT_FALSE( - db.GetOriginLastEvictionTime(kOrigin2, kTemp, &last_eviction_time)); - EXPECT_EQ(base::Time(), last_eviction_time); - EXPECT_FALSE( - db.GetOriginLastEvictionTime(kOrigin3, kTemp, &last_eviction_time)); - EXPECT_EQ(base::Time(), last_eviction_time); - - // Deleting an origin that is not present should not fail. - EXPECT_TRUE(db.DeleteOriginLastEvictionTime(ToOrigin("http://notpresent.com"), - kTemp)); + db.SetBucketLastModifiedTime(bucket3.id, base::Time::FromJavaTime(20))); + EXPECT_TRUE( + db.SetBucketLastModifiedTime(bucket4.id, base::Time::FromJavaTime(30))); + + result = db.GetBucketsModifiedBetween(kTemp, base::Time(), base::Time::Max()); + EXPECT_TRUE(result.ok()); + buckets = result.value(); + EXPECT_EQ(3U, buckets.size()); + EXPECT_EQ(1U, buckets.count(bucket1)); + EXPECT_EQ(1U, buckets.count(bucket2)); + EXPECT_EQ(1U, buckets.count(bucket3)); + EXPECT_EQ(0U, buckets.count(bucket4)); + + result = db.GetBucketsModifiedBetween(kTemp, base::Time::FromJavaTime(5), + base::Time::Max()); + EXPECT_TRUE(result.ok()); + buckets = result.value(); + EXPECT_EQ(2U, buckets.size()); + EXPECT_EQ(0U, buckets.count(bucket1)); + EXPECT_EQ(1U, buckets.count(bucket2)); + EXPECT_EQ(1U, buckets.count(bucket3)); + EXPECT_EQ(0U, buckets.count(bucket4)); + + result = db.GetBucketsModifiedBetween(kTemp, base::Time::FromJavaTime(15), + base::Time::Max()); + EXPECT_TRUE(result.ok()); + buckets = result.value(); + EXPECT_EQ(1U, buckets.size()); + EXPECT_EQ(0U, buckets.count(bucket1)); + EXPECT_EQ(0U, buckets.count(bucket2)); + EXPECT_EQ(1U, buckets.count(bucket3)); + EXPECT_EQ(0U, buckets.count(bucket4)); + + result = db.GetBucketsModifiedBetween(kTemp, base::Time::FromJavaTime(25), + base::Time::Max()); + EXPECT_TRUE(result.ok()); + buckets = result.value(); + EXPECT_TRUE(buckets.empty()); + + result = db.GetBucketsModifiedBetween(kTemp, base::Time::FromJavaTime(5), + base::Time::FromJavaTime(15)); + EXPECT_TRUE(result.ok()); + buckets = result.value(); + EXPECT_EQ(1U, buckets.size()); + EXPECT_EQ(0U, buckets.count(bucket1)); + EXPECT_EQ(1U, buckets.count(bucket2)); + EXPECT_EQ(0U, buckets.count(bucket3)); + EXPECT_EQ(0U, buckets.count(bucket4)); + + result = db.GetBucketsModifiedBetween(kTemp, base::Time::FromJavaTime(0), + base::Time::FromJavaTime(20)); + EXPECT_TRUE(result.ok()); + buckets = result.value(); + EXPECT_EQ(2U, buckets.size()); + EXPECT_EQ(1U, buckets.count(bucket1)); + EXPECT_EQ(1U, buckets.count(bucket2)); + EXPECT_EQ(0U, buckets.count(bucket3)); + EXPECT_EQ(0U, buckets.count(bucket4)); + + result = db.GetBucketsModifiedBetween(kPerm, base::Time::FromJavaTime(0), + base::Time::FromJavaTime(35)); + EXPECT_TRUE(result.ok()); + buckets = result.value(); + EXPECT_EQ(1U, buckets.size()); + EXPECT_EQ(0U, buckets.count(bucket1)); + EXPECT_EQ(0U, buckets.count(bucket2)); + EXPECT_EQ(0U, buckets.count(bucket3)); + EXPECT_EQ(1U, buckets.count(bucket4)); } -TEST_P(QuotaDatabaseTest, RegisterInitialOriginInfo) { +TEST_P(QuotaDatabaseTest, RegisterInitialStorageKeyInfo) { QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath()); - const url::Origin kOrigins[] = {ToOrigin("http://a/"), ToOrigin("http://b/"), - ToOrigin("http://c/")}; - std::set<url::Origin> origins(kOrigins, std::end(kOrigins)); + const StorageKey kStorageKeys[] = { + StorageKey::CreateFromStringForTesting("http://a/"), + StorageKey::CreateFromStringForTesting("http://b/"), + StorageKey::CreateFromStringForTesting("http://c/")}; + std::set<StorageKey> storage_keys(kStorageKeys, std::end(kStorageKeys)); - EXPECT_TRUE(db.RegisterInitialOriginInfo(origins, kTemp)); + EXPECT_TRUE(db.RegisterInitialStorageKeyInfo(storage_keys, kTemp)); QuotaDatabase::BucketTableEntry info; info.use_count = -1; - EXPECT_TRUE(db.GetOriginInfo(ToOrigin("http://a/"), kTemp, &info)); + EXPECT_TRUE(db.GetStorageKeyInfo( + StorageKey::CreateFromStringForTesting("http://a/"), kTemp, &info)); EXPECT_EQ(0, info.use_count); - EXPECT_TRUE(db.SetOriginLastAccessTime(ToOrigin("http://a/"), kTemp, - base::Time::FromDoubleT(1.0))); + EXPECT_TRUE(db.SetStorageKeyLastAccessTime( + StorageKey::CreateFromStringForTesting("http://a/"), kTemp, + base::Time::FromDoubleT(1.0))); info.use_count = -1; - EXPECT_TRUE(db.GetOriginInfo(ToOrigin("http://a/"), kTemp, &info)); + EXPECT_TRUE(db.GetStorageKeyInfo( + StorageKey::CreateFromStringForTesting("http://a/"), kTemp, &info)); EXPECT_EQ(1, info.use_count); - EXPECT_TRUE(db.RegisterInitialOriginInfo(origins, kTemp)); + EXPECT_TRUE(db.RegisterInitialStorageKeyInfo(storage_keys, kTemp)); info.use_count = -1; - EXPECT_TRUE(db.GetOriginInfo(ToOrigin("http://a/"), kTemp, &info)); + EXPECT_TRUE(db.GetStorageKeyInfo( + StorageKey::CreateFromStringForTesting("http://a/"), kTemp, &info)); EXPECT_EQ(1, info.use_count); } @@ -652,7 +611,7 @@ TEST_P(QuotaDatabaseTest, DumpQuotaTable) { {.host = "http://gle/", .type = kPerm, .quota = 3}}; QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath()); - EXPECT_TRUE(LazyOpen(&db, /*create_if_needed=*/true)); + EXPECT_TRUE(LazyOpen(&db, LazyOpenMode::kCreateIfNotFound)); AssignQuotaTable(&db, kTableEntries); using Verifier = EntryVerifier<QuotaTableEntry>; @@ -663,17 +622,19 @@ TEST_P(QuotaDatabaseTest, DumpQuotaTable) { } TEST_P(QuotaDatabaseTest, DumpBucketTable) { - base::Time now(base::Time::Now()); + base::Time now = base::Time::Now(); using Entry = QuotaDatabase::BucketTableEntry; Entry kTableEntries[] = { - Entry(0, ToOrigin("http://go/"), kTemp, kDefaultBucket, 2147483647, now, - now), - Entry(1, ToOrigin("http://oo/"), kTemp, kDefaultBucket, 0, now, now), - Entry(2, ToOrigin("http://gle/"), kTemp, kDefaultBucket, 1, now, now), + Entry(BucketId(1), StorageKey::CreateFromStringForTesting("http://go/"), + kTemp, kDefaultBucketName, 2147483647, now, now), + Entry(BucketId(2), StorageKey::CreateFromStringForTesting("http://oo/"), + kTemp, kDefaultBucketName, 0, now, now), + Entry(BucketId(3), StorageKey::CreateFromStringForTesting("http://gle/"), + kTemp, kDefaultBucketName, 1, now, now), }; QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath()); - EXPECT_TRUE(LazyOpen(&db, /*create_if_needed=*/true)); + EXPECT_TRUE(LazyOpen(&db, LazyOpenMode::kCreateIfNotFound)); AssignBucketTable(&db, kTableEntries); using Verifier = EntryVerifier<Entry>; @@ -683,21 +644,23 @@ TEST_P(QuotaDatabaseTest, DumpBucketTable) { EXPECT_TRUE(verifier.table.empty()); } -TEST_P(QuotaDatabaseTest, GetOriginInfo) { - const url::Origin kOrigin = ToOrigin("http://go/"); +TEST_P(QuotaDatabaseTest, GetStorageKeyInfo) { + const StorageKey kStorageKey = + StorageKey::CreateFromStringForTesting("http://go/"); using Entry = QuotaDatabase::BucketTableEntry; - Entry kTableEntries[] = {Entry(0, kOrigin, kTemp, kDefaultBucket, 100, - base::Time(), base::Time())}; + Entry kTableEntries[] = {Entry(BucketId(1), kStorageKey, kTemp, + kDefaultBucketName, 100, base::Time(), + base::Time())}; QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath()); - EXPECT_TRUE(LazyOpen(&db, /*create_if_needed=*/true)); + EXPECT_TRUE(LazyOpen(&db, LazyOpenMode::kCreateIfNotFound)); AssignBucketTable(&db, kTableEntries); { Entry entry; - EXPECT_TRUE(db.GetOriginInfo(kOrigin, kTemp, &entry)); + EXPECT_TRUE(db.GetStorageKeyInfo(kStorageKey, kTemp, &entry)); EXPECT_EQ(kTableEntries[0].type, entry.type); - EXPECT_EQ(kTableEntries[0].origin, entry.origin); + EXPECT_EQ(kTableEntries[0].storage_key, entry.storage_key); EXPECT_EQ(kTableEntries[0].name, entry.name); EXPECT_EQ(kTableEntries[0].use_count, entry.use_count); EXPECT_EQ(kTableEntries[0].last_accessed, entry.last_accessed); @@ -706,19 +669,20 @@ TEST_P(QuotaDatabaseTest, GetOriginInfo) { { Entry entry; - EXPECT_FALSE( - db.GetOriginInfo(ToOrigin("http://notpresent.org/"), kTemp, &entry)); + EXPECT_FALSE(db.GetStorageKeyInfo( + StorageKey::CreateFromStringForTesting("http://notpresent.org/"), kTemp, + &entry)); } } TEST_P(QuotaDatabaseTest, GetBucketInfo) { using Entry = QuotaDatabase::BucketTableEntry; - Entry kTableEntries[] = {Entry(123, ToOrigin("http://go/"), kTemp, - "TestBucket", 100, base::Time(), - base::Time())}; + Entry kTableEntries[] = { + Entry(BucketId(123), StorageKey::CreateFromStringForTesting("http://go/"), + kTemp, "test_bucket", 100, base::Time(), base::Time())}; QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath()); - EXPECT_TRUE(LazyOpen(&db, /*create_if_needed=*/true)); + EXPECT_TRUE(LazyOpen(&db, LazyOpenMode::kCreateIfNotFound)); AssignBucketTable(&db, kTableEntries); { @@ -726,7 +690,7 @@ TEST_P(QuotaDatabaseTest, GetBucketInfo) { EXPECT_TRUE(db.GetBucketInfo(kTableEntries[0].bucket_id, &entry)); EXPECT_EQ(kTableEntries[0].bucket_id, entry.bucket_id); EXPECT_EQ(kTableEntries[0].type, entry.type); - EXPECT_EQ(kTableEntries[0].origin, entry.origin); + EXPECT_EQ(kTableEntries[0].storage_key, entry.storage_key); EXPECT_EQ(kTableEntries[0].name, entry.name); EXPECT_EQ(kTableEntries[0].use_count, entry.use_count); EXPECT_EQ(kTableEntries[0].last_accessed, entry.last_accessed); @@ -734,27 +698,29 @@ TEST_P(QuotaDatabaseTest, GetBucketInfo) { } { + // BucketId 456 is not in the database. Entry entry; - EXPECT_FALSE(db.GetBucketInfo(456, &entry)); + EXPECT_FALSE(db.GetBucketInfo(BucketId(456), &entry)); } } // Non-parameterized tests. -TEST_F(QuotaDatabaseTest, BootstrapFlag) { +TEST_F(QuotaDatabaseTest, BootstrapForEvictionFlag) { QuotaDatabase db(DbPath()); - EXPECT_FALSE(db.IsOriginDatabaseBootstrapped()); - EXPECT_TRUE(db.SetOriginDatabaseBootstrapped(true)); - EXPECT_TRUE(db.IsOriginDatabaseBootstrapped()); - EXPECT_TRUE(db.SetOriginDatabaseBootstrapped(false)); - EXPECT_FALSE(db.IsOriginDatabaseBootstrapped()); + EXPECT_FALSE(db.IsBootstrappedForEviction()); + EXPECT_TRUE(db.SetBootstrappedForEviction(true)); + EXPECT_TRUE(db.IsBootstrappedForEviction()); + EXPECT_TRUE(db.SetBootstrappedForEviction(false)); + EXPECT_FALSE(db.IsBootstrappedForEviction()); } TEST_F(QuotaDatabaseTest, OpenCorruptedDatabase) { + base::HistogramTester histograms; // Create database, force corruption and close db by leaving scope. { QuotaDatabase db(DbPath()); - ASSERT_TRUE(LazyOpen(&db, /*create_if_needed=*/true)); + ASSERT_TRUE(LazyOpen(&db, LazyOpenMode::kCreateIfNotFound)); ASSERT_TRUE(sql::test::CorruptSizeInHeader(DbPath())); } // Reopen database and verify schema reset on reopen. @@ -762,9 +728,13 @@ TEST_F(QuotaDatabaseTest, OpenCorruptedDatabase) { sql::test::ScopedErrorExpecter expecter; expecter.ExpectError(SQLITE_CORRUPT); QuotaDatabase db(DbPath()); - ASSERT_TRUE(LazyOpen(&db, /*create_if_needed=*/false)); + ASSERT_TRUE(LazyOpen(&db, LazyOpenMode::kFailIfNotFound)); EXPECT_TRUE(expecter.SawExpectedErrors()); } + + histograms.ExpectTotalCount("Quota.QuotaDatabaseReset", 1); + histograms.ExpectBucketCount("Quota.QuotaDatabaseReset", + DatabaseResetReason::kCreateSchema, 1); } INSTANTIATE_TEST_SUITE_P(All, diff --git a/chromium/storage/browser/quota/quota_device_info_helper.h b/chromium/storage/browser/quota/quota_device_info_helper.h index 5a2fdd17e1a..c55220f790c 100644 --- a/chromium/storage/browser/quota/quota_device_info_helper.h +++ b/chromium/storage/browser/quota/quota_device_info_helper.h @@ -4,7 +4,6 @@ #include "base/component_export.h" #include "base/macros.h" -#include "base/no_destructor.h" #include "base/system/sys_info.h" #ifndef STORAGE_BROWSER_QUOTA_QUOTA_DEVICE_INFO_HELPER_H_ diff --git a/chromium/storage/browser/quota/quota_manager_impl.cc b/chromium/storage/browser/quota/quota_manager_impl.cc index 017884bd927..3ae98700cdb 100644 --- a/chromium/storage/browser/quota/quota_manager_impl.cc +++ b/chromium/storage/browser/quota/quota_manager_impl.cc @@ -6,6 +6,7 @@ #include <stddef.h> #include <stdint.h> +#include <sstream> #include <algorithm> #include <functional> @@ -20,6 +21,7 @@ #include "base/files/file_util.h" #include "base/macros.h" #include "base/memory/scoped_refptr.h" +#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/numerics/safe_conversions.h" #include "base/rand_util.h" @@ -39,7 +41,6 @@ #include "components/services/storage/public/mojom/quota_client.mojom.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "storage/browser/quota/client_usage_tracker.h" -#include "storage/browser/quota/mojo_quota_client_wrapper.h" #include "storage/browser/quota/quota_client_type.h" #include "storage/browser/quota/quota_features.h" #include "storage/browser/quota/quota_macros.h" @@ -47,9 +48,12 @@ #include "storage/browser/quota/quota_override_handle.h" #include "storage/browser/quota/quota_temporary_storage_evictor.h" #include "storage/browser/quota/usage_tracker.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h" +#include "url/origin.h" -using blink::mojom::StorageType; +using ::blink::StorageKey; +using ::blink::mojom::StorageType; namespace storage { @@ -90,18 +94,46 @@ bool IsSupportedIncognitoType(StorageType type) { return type == StorageType::kTemporary || type == StorageType::kPersistent; } -QuotaErrorOr<BucketId> CreateBucketOnDBThread(const url::Origin& origin, - const std::string& bucket_name, - QuotaDatabase* database) { +QuotaErrorOr<BucketInfo> GetOrCreateBucketOnDBThread( + const StorageKey& storage_key, + const std::string& bucket_name, + QuotaDatabase* database) { + DCHECK(database); + return database->GetOrCreateBucket(storage_key, bucket_name); +} + +QuotaErrorOr<BucketInfo> CreateBucketOnDBThread( + const StorageKey& storage_key, + const std::string& bucket_name, + blink::mojom::StorageType storage_type, + QuotaDatabase* database) { DCHECK(database); - return database->CreateBucket(origin, bucket_name); + return database->CreateBucketForTesting(storage_key, bucket_name, // IN-TEST + storage_type); } -QuotaErrorOr<BucketId> GetBucketIdOnDBThread(const url::Origin& origin, +QuotaErrorOr<BucketInfo> GetBucketOnDBThread(const StorageKey& storage_key, const std::string& bucket_name, + blink::mojom::StorageType type, QuotaDatabase* database) { DCHECK(database); - return database->GetBucketId(origin, bucket_name); + return database->GetBucket(storage_key, bucket_name, type); +} + +QuotaErrorOr<std::set<StorageKey>> GetStorageKeysForTypeOnDBThread( + StorageType type, + QuotaDatabase* database) { + DCHECK(database); + return database->GetStorageKeysForType(type); +} + +QuotaErrorOr<std::set<BucketInfo>> GetModifiedBetweenOnDBThread( + StorageType type, + base::Time begin, + base::Time end, + QuotaDatabase* database) { + DCHECK(database); + return database->GetBucketsModifiedBetween(type, begin, end); } bool GetPersistentHostQuotaOnDBThread(const std::string& host, @@ -122,83 +154,87 @@ bool SetPersistentHostQuotaOnDBThread(const std::string& host, return false; } -bool GetLRUOriginOnDBThread(StorageType type, - const std::set<url::Origin>& exceptions, - SpecialStoragePolicy* policy, - absl::optional<url::Origin>* origin, - QuotaDatabase* database) { +QuotaErrorOr<BucketInfo> GetLRUBucketOnDBThread( + StorageType type, + const std::set<BucketId>& bucket_exceptions, + SpecialStoragePolicy* policy, + QuotaDatabase* database) { DCHECK(database); - database->GetLRUOrigin(type, exceptions, policy, origin); - return true; + return database->GetLRUBucket(type, bucket_exceptions, policy); } -bool DeleteOriginInfoOnDBThread(const url::Origin& origin, - StorageType type, +bool DeleteStorageKeyInfoOnDBThread(const StorageKey& storage_key, + StorageType type, + QuotaDatabase* database) { + DCHECK(database); + return database->DeleteStorageKeyInfo(storage_key, type); +} + +bool DeleteBucketInfoOnDBThread(const BucketId bucket_id, bool is_eviction, QuotaDatabase* database) { DCHECK(database); - base::Time now = base::Time::Now(); - if (is_eviction) { + base::Time now = base::Time::Now(); QuotaDatabase::BucketTableEntry entry; - database->GetOriginInfo(origin, type, &entry); - UMA_HISTOGRAM_COUNTS_1M( - QuotaManagerImpl::kEvictedOriginAccessedCountHistogram, + database->GetBucketInfo(bucket_id, &entry); + base::UmaHistogramCounts1M( + QuotaManagerImpl::kEvictedBucketAccessedCountHistogram, entry.use_count); - UMA_HISTOGRAM_COUNTS_1000( - QuotaManagerImpl::kEvictedOriginDaysSinceAccessHistogram, + base::UmaHistogramCounts1000( + QuotaManagerImpl::kEvictedBucketDaysSinceAccessHistogram, (now - entry.last_accessed).InDays()); } - if (!database->DeleteOriginInfo(origin, type)) - return false; - - // If the deletion is not due to an eviction, delete the entry in the eviction - // table as well due to privacy concerns. - if (!is_eviction) - return database->DeleteOriginLastEvictionTime(origin, type); - - base::Time last_eviction_time; - database->GetOriginLastEvictionTime(origin, type, &last_eviction_time); - - if (last_eviction_time != base::Time()) { - UMA_HISTOGRAM_COUNTS_1000( - QuotaManagerImpl::kDaysBetweenRepeatedOriginEvictionsHistogram, - (now - last_eviction_time).InDays()); - } - - return database->SetOriginLastEvictionTime(origin, type, now); + return database->DeleteBucketInfo(bucket_id); } -bool BootstrapDatabaseOnDBThread(std::set<url::Origin> origins, +bool BootstrapDatabaseOnDBThread(std::set<StorageKey> storage_keys, QuotaDatabase* database) { DCHECK(database); - if (database->IsOriginDatabaseBootstrapped()) + if (database->IsBootstrappedForEviction()) return true; - // Register existing origins with 0 last time access. - if (database->RegisterInitialOriginInfo(origins, StorageType::kTemporary)) { - database->SetOriginDatabaseBootstrapped(true); + // Register existing storage keys with 0 last time access. + if (database->RegisterInitialStorageKeyInfo(storage_keys, + StorageType::kTemporary)) { + database->SetBootstrappedForEviction(true); return true; } return false; } -bool UpdateAccessTimeOnDBThread(const url::Origin& origin, +bool UpdateAccessTimeOnDBThread(const StorageKey& storage_key, StorageType type, base::Time accessed_time, QuotaDatabase* database) { DCHECK(database); - return database->SetOriginLastAccessTime(origin, type, accessed_time); + return database->SetStorageKeyLastAccessTime(storage_key, type, + accessed_time); +} + +bool UpdateBucketAccessTimeOnDBThread(const BucketId bucket_id, + base::Time accessed_time, + QuotaDatabase* database) { + DCHECK(database); + return database->SetBucketLastAccessTime(bucket_id, accessed_time); } -bool UpdateModifiedTimeOnDBThread(const url::Origin& origin, +bool UpdateModifiedTimeOnDBThread(const StorageKey& storage_key, StorageType type, base::Time modified_time, QuotaDatabase* database) { DCHECK(database); - return database->SetOriginLastModifiedTime(origin, type, modified_time); + return database->SetStorageKeyLastModifiedTime(storage_key, type, + modified_time); +} + +bool UpdateBucketModifiedTimeOnDBThread(const BucketId bucket_id, + base::Time modified_time, + QuotaDatabase* database) { + DCHECK(database); + return database->SetBucketLastModifiedTime(bucket_id, modified_time); } void DidGetUsageAndQuotaStripBreakdown( @@ -229,9 +265,8 @@ constexpr int QuotaManagerImpl::kEvictionIntervalInMilliSeconds; constexpr int QuotaManagerImpl::kThresholdOfErrorsToBeDenylisted; constexpr int QuotaManagerImpl::kThresholdRandomizationPercent; constexpr char QuotaManagerImpl::kDatabaseName[]; -constexpr char QuotaManagerImpl::kDaysBetweenRepeatedOriginEvictionsHistogram[]; -constexpr char QuotaManagerImpl::kEvictedOriginAccessedCountHistogram[]; -constexpr char QuotaManagerImpl::kEvictedOriginDaysSinceAccessHistogram[]; +constexpr char QuotaManagerImpl::kEvictedBucketAccessedCountHistogram[]; +constexpr char QuotaManagerImpl::kEvictedBucketDaysSinceAccessHistogram[]; QuotaManagerImpl::QuotaOverride::QuotaOverride() = default; QuotaManagerImpl::QuotaOverride::~QuotaOverride() = default; @@ -239,7 +274,7 @@ QuotaManagerImpl::QuotaOverride::~QuotaOverride() = default; class QuotaManagerImpl::UsageAndQuotaInfoGatherer : public QuotaTask { public: UsageAndQuotaInfoGatherer(QuotaManagerImpl* manager, - const url::Origin& origin, + const StorageKey& storage_key, StorageType type, bool is_unlimited, bool is_session_only, @@ -247,7 +282,7 @@ class QuotaManagerImpl::UsageAndQuotaInfoGatherer : public QuotaTask { absl::optional<int64_t> quota_override_size, UsageAndQuotaForDevtoolsCallback callback) : QuotaTask(manager), - origin_(origin), + storage_key_(storage_key), callback_(std::move(callback)), type_(type), is_unlimited_(is_unlimited), @@ -266,7 +301,7 @@ class QuotaManagerImpl::UsageAndQuotaInfoGatherer : public QuotaTask { 4, base::BindOnce(&UsageAndQuotaInfoGatherer::OnBarrierComplete, weak_factory_.GetWeakPtr())); - const std::string& host = origin_.host(); + const std::string& host = storage_key_.origin().host(); manager()->GetQuotaSettings( base::BindOnce(&UsageAndQuotaInfoGatherer::OnGotSettings, @@ -388,7 +423,7 @@ class QuotaManagerImpl::UsageAndQuotaInfoGatherer : public QuotaTask { void OnBarrierComplete() { CallCompleted(); } - const url::Origin origin_; + const StorageKey storage_key_; QuotaManagerImpl::UsageAndQuotaForDevtoolsCallback callback_; const StorageType type_; const bool is_unlimited_; @@ -558,22 +593,20 @@ class QuotaManagerImpl::GetUsageInfoTask : public QuotaTask { base::WeakPtrFactory<GetUsageInfoTask> weak_factory_{this}; }; -class QuotaManagerImpl::OriginDataDeleter : public QuotaTask { +class QuotaManagerImpl::StorageKeyDataDeleter : public QuotaTask { public: - OriginDataDeleter(QuotaManagerImpl* manager, - const url::Origin& origin, - StorageType type, - QuotaClientTypes quota_client_types, - bool is_eviction, - StatusCallback callback) + StorageKeyDataDeleter(QuotaManagerImpl* manager, + const StorageKey& storage_key, + StorageType type, + QuotaClientTypes quota_client_types, + StatusCallback callback) : QuotaTask(manager), - origin_(origin), + storage_key_(storage_key), type_(type), quota_client_types_(std::move(quota_client_types)), error_count_(0), remaining_clients_(0), skipped_clients_(0), - is_eviction_(is_eviction), callback_(std::move(callback)) {} protected: @@ -582,17 +615,17 @@ class QuotaManagerImpl::OriginDataDeleter : public QuotaTask { remaining_clients_ = manager()->client_types_[type_].size(); for (const auto& client_and_type : manager()->client_types_[type_]) { - QuotaClient* client = client_and_type.first; + mojom::QuotaClient* client = client_and_type.first; QuotaClientType client_type = client_and_type.second; if (quota_client_types_.contains(client_type)) { static int tracing_id = 0; - TRACE_EVENT_ASYNC_BEGIN2("browsing_data", - "QuotaManagerImpl::OriginDataDeleter", - ++tracing_id, "client_type", client_type, - "origin", origin_.Serialize()); - client->DeleteOriginData( - origin_, type_, - base::BindOnce(&OriginDataDeleter::DidDeleteOriginData, + TRACE_EVENT_NESTABLE_ASYNC_BEGIN2( + "browsing_data", "QuotaManagerImpl::StorageKeyDataDeleter", + ++tracing_id, "client_type", client_type, "storage_key", + storage_key_.Serialize()); + client->DeleteStorageKeyData( + storage_key_, type_, + base::BindOnce(&StorageKeyDataDeleter::DidDeleteStorageKeyData, weak_factory_.GetWeakPtr(), tracing_id)); } else { ++skipped_clients_; @@ -606,9 +639,9 @@ class QuotaManagerImpl::OriginDataDeleter : public QuotaTask { void Completed() override { if (error_count_ == 0) { - // Only remove the entire origin if we didn't skip any client types. + // Only remove the entire storage key if we didn't skip any client types. if (skipped_clients_ == 0) - manager()->DeleteOriginFromDatabase(origin_, type_, is_eviction_); + manager()->DeleteStorageKeyFromDatabase(storage_key_, type_); std::move(callback_).Run(blink::mojom::QuotaStatusCode::kOk); } else { std::move(callback_).Run( @@ -623,11 +656,11 @@ class QuotaManagerImpl::OriginDataDeleter : public QuotaTask { } private: - void DidDeleteOriginData(int tracing_id, - blink::mojom::QuotaStatusCode status) { + void DidDeleteStorageKeyData(int tracing_id, + blink::mojom::QuotaStatusCode status) { DCHECK_GT(remaining_clients_, 0U); - TRACE_EVENT_ASYNC_END0("browsing_data", - "QuotaManagerImpl::OriginDataDeleter", tracing_id); + TRACE_EVENT_NESTABLE_ASYNC_END0( + "browsing_data", "QuotaManagerImpl::StorageKeyDataDeleter", tracing_id); if (status != blink::mojom::QuotaStatusCode::kOk) ++error_count_; @@ -640,16 +673,124 @@ class QuotaManagerImpl::OriginDataDeleter : public QuotaTask { return static_cast<QuotaManagerImpl*>(observer()); } - const url::Origin origin_; + const StorageKey storage_key_; const StorageType type_; const QuotaClientTypes quota_client_types_; int error_count_; size_t remaining_clients_; int skipped_clients_; + StatusCallback callback_; + + base::WeakPtrFactory<StorageKeyDataDeleter> weak_factory_{this}; +}; + +// Calls all QuotaClients for the bucket StorageType to delete bucket data. +// Keeps track of operations that have failed, and will only complete the +// task if all operations have succeeded. This is currently only for the default +// bucket. If a non-default bucket is to be evicted, it will immediately +// complete the task since non-default bucket usage is not being tracked by +// QuotaClients yet. +// TODO(crbug.com/1199417): Update to call QuotaClients to clear data for +// non-default buckets when QuotaClient is migrated to operate on buckets. +class QuotaManagerImpl::BucketDataDeleter : public QuotaTask { + public: + BucketDataDeleter(QuotaManagerImpl* manager, + const BucketInfo& bucket, + QuotaClientTypes quota_client_types, + bool is_eviction, + StatusCallback callback) + : QuotaTask(manager), + bucket_(bucket), + quota_client_types_(std::move(quota_client_types)), + is_eviction_(is_eviction), + callback_(std::move(callback)) {} + + protected: + void Run() override { + DCHECK(manager()->client_types_.contains(bucket_.type)); + + // If bucket is not the default bucket, skip calls to the QuotaClient since + // they are not being tracked yet. + // TODO(crbug.com/1199417): Update to call for all buckets once QuotaClient + // is migrated to operate on buckets. + if (!bucket_.is_default()) { + CallCompleted(); + return; + } + + remaining_clients_ = manager()->client_types_[bucket_.type].size(); + + for (const auto& client_and_type : manager()->client_types_[bucket_.type]) { + mojom::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; + std::ostringstream bucket_params; + bucket_params << "storage_key: " << bucket_.storage_key.Serialize() + << ", name: " << bucket_.name << ", id: " << bucket_.id; + TRACE_EVENT_NESTABLE_ASYNC_BEGIN2( + "browsing_data", "QuotaManagerImpl::BucketDataDeleter", + ++tracing_id, "client_type", client_type, "bucket", + bucket_params.str()); + client->DeleteStorageKeyData( + bucket_.storage_key, bucket_.type, + base::BindOnce(&BucketDataDeleter::DidDeleteBucketData, + weak_factory_.GetWeakPtr(), tracing_id)); + } else { + ++skipped_clients_; + --remaining_clients_; + } + } + + if (remaining_clients_ == 0) + CallCompleted(); + } + + void Completed() override { + if (error_count_ == 0) { + // Only remove the bucket if we didn't skip any client types. + if (skipped_clients_ == 0) + manager()->DeleteBucketFromDatabase(bucket_.id, is_eviction_); + std::move(callback_).Run(blink::mojom::QuotaStatusCode::kOk); + } else { + std::move(callback_).Run( + blink::mojom::QuotaStatusCode::kErrorInvalidModification); + } + DeleteSoon(); + } + + void Aborted() override { + std::move(callback_).Run(blink::mojom::QuotaStatusCode::kErrorAbort); + DeleteSoon(); + } + + private: + void DidDeleteBucketData(int tracing_id, + blink::mojom::QuotaStatusCode status) { + DCHECK_GT(remaining_clients_, 0U); + TRACE_EVENT_NESTABLE_ASYNC_END0( + "browsing_data", "QuotaManagerImpl::BucketDataDeleter", tracing_id); + + if (status != blink::mojom::QuotaStatusCode::kOk) + ++error_count_; + + if (--remaining_clients_ == 0) + CallCompleted(); + } + + QuotaManagerImpl* manager() const { + return static_cast<QuotaManagerImpl*>(observer()); + } + + const BucketInfo bucket_; + const QuotaClientTypes quota_client_types_; + int error_count_ = 0; + size_t remaining_clients_ = 0; + int skipped_clients_ = 0; const bool is_eviction_; StatusCallback callback_; - base::WeakPtrFactory<OriginDataDeleter> weak_factory_{this}; + base::WeakPtrFactory<BucketDataDeleter> weak_factory_{this}; }; class QuotaManagerImpl::HostDataDeleter : public QuotaTask { @@ -674,9 +815,9 @@ class QuotaManagerImpl::HostDataDeleter : public QuotaTask { remaining_clients_ = manager()->client_types_[type_].size(); for (const auto& client_and_type : manager()->client_types_[type_]) { - client_and_type.first->GetOriginsForHost( + client_and_type.first->GetStorageKeysForHost( type_, host_, - base::BindOnce(&HostDataDeleter::DidGetOriginsForHost, + base::BindOnce(&HostDataDeleter::DidGetStorageKeysForHost, weak_factory_.GetWeakPtr())); } } @@ -697,32 +838,31 @@ class QuotaManagerImpl::HostDataDeleter : public QuotaTask { } private: - void DidGetOriginsForHost(const std::vector<url::Origin>& origins) { + void DidGetStorageKeysForHost(const std::vector<StorageKey>& storage_keys) { DCHECK_GT(remaining_clients_, 0U); - for (const auto& origin : origins) - origins_.insert(origin); + storage_keys_.insert(storage_keys.begin(), storage_keys.end()); if (--remaining_clients_ == 0) { - if (!origins_.empty()) - ScheduleOriginsDeletion(); + if (!storage_keys_.empty()) + ScheduleStorageKeysDeletion(); else CallCompleted(); } } - void ScheduleOriginsDeletion() { - remaining_deleters_ = origins_.size(); - for (const auto& origin : origins_) { - OriginDataDeleter* deleter = new OriginDataDeleter( - manager(), origin, type_, std::move(quota_client_types_), false, - base::BindOnce(&HostDataDeleter::DidDeleteOriginData, + void ScheduleStorageKeysDeletion() { + remaining_deleters_ = storage_keys_.size(); + for (const auto& storage_key : storage_keys_) { + StorageKeyDataDeleter* deleter = new StorageKeyDataDeleter( + manager(), storage_key, type_, std::move(quota_client_types_), + base::BindOnce(&HostDataDeleter::DidDeleteStorageKeyData, weak_factory_.GetWeakPtr())); deleter->Start(); } } - void DidDeleteOriginData(blink::mojom::QuotaStatusCode status) { + void DidDeleteStorageKeyData(blink::mojom::QuotaStatusCode status) { DCHECK_GT(remaining_deleters_, 0U); if (status != blink::mojom::QuotaStatusCode::kOk) @@ -739,7 +879,7 @@ class QuotaManagerImpl::HostDataDeleter : public QuotaTask { const std::string host_; const StorageType type_; const QuotaClientTypes quota_client_types_; - std::set<url::Origin> origins_; + std::set<StorageKey> storage_keys_; int error_count_; size_t remaining_clients_; size_t remaining_deleters_; @@ -772,7 +912,7 @@ class QuotaManagerImpl::StorageCleanupHelper : public QuotaTask { // This may synchronously trigger |callback_| at the end of the for loop, // make sure we do nothing after this block. for (const auto& client_and_type : manager()->client_types_[type_]) { - QuotaClient* client = client_and_type.first; + mojom::QuotaClient* client = client_and_type.first; QuotaClientType client_type = client_and_type.second; if (quota_client_types_.contains(client_type)) { client->PerformStorageCleanup(type_, barrier); @@ -805,42 +945,7 @@ class QuotaManagerImpl::StorageCleanupHelper : public QuotaTask { base::WeakPtrFactory<StorageCleanupHelper> weak_factory_{this}; }; -// Fetch origins that have been modified since the specified time. This is used -// to clear data for origins that have been modified within the user specified -// time frame. -// -// This class is granted ownership of itself when it is passed to -// DidGetModifiedBetween() via base::Owned(). When the closure for said -// function goes out of scope, the object is deleted. This is a thread-safe -// class. -class QuotaManagerImpl::GetModifiedSinceHelper { - public: - bool GetModifiedBetweenOnDBThread(StorageType type, - base::Time begin, - base::Time end, - QuotaDatabase* database) { - DCHECK(database); - return database->GetOriginsModifiedBetween(type, &origins_, begin, end); - } - - void DidGetModifiedBetween(const base::WeakPtr<QuotaManagerImpl>& manager, - GetOriginsCallback callback, - StorageType type, - bool success) { - if (!manager) { - // The operation was aborted. - std::move(callback).Run(std::set<url::Origin>(), type); - return; - } - manager->DidDatabaseWork(success); - std::move(callback).Run(origins_, type); - } - - private: - std::set<url::Origin> origins_; -}; - -// Gather origin info table for quota-internals page. +// Gather storage key info table for quota-internals page. // // This class is granted ownership of itself when it is passed to // DidDumpQuotaTable() via base::Owned(). When the closure for said function @@ -876,7 +981,7 @@ class QuotaManagerImpl::DumpQuotaTableHelper { QuotaTableEntries entries_; }; -// Gather origin info table for quota-internals page. +// Gather storage key info table for quota-internals page. // // This class is granted ownership of itself when it is passed to // DidDumpQuotaTable() via base::Owned(). When the closure for said function @@ -933,7 +1038,6 @@ QuotaManagerImpl::QuotaManagerImpl( base::TaskShutdownBehavior::BLOCK_SHUTDOWN})), get_settings_function_(get_settings_function), quota_change_callback_(std::move(quota_change_callback)), - is_getting_eviction_origin_(false), special_storage_policy_(std::move(special_storage_policy)), get_volume_info_fn_(&QuotaManagerImpl::GetVolumeInfo) { DCHECK_EQ(settings_.refresh_interval, base::TimeDelta::Max()); @@ -953,62 +1057,89 @@ void QuotaManagerImpl::SetQuotaSettings(const QuotaSettings& settings) { settings_timestamp_ = base::TimeTicks::Now(); } -void QuotaManagerImpl::CreateBucket( - const url::Origin& origin, +void QuotaManagerImpl::GetOrCreateBucket( + const StorageKey& storage_key, + const std::string& bucket_name, + base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + EnsureDatabaseOpened(); + + PostTaskAndReplyWithResultForDBThread( + base::BindOnce(&GetOrCreateBucketOnDBThread, storage_key, bucket_name), + base::BindOnce(&QuotaManagerImpl::DidGetBucket, + weak_factory_.GetWeakPtr(), std::move(callback))); +} + +void QuotaManagerImpl::CreateBucketForTesting( + const StorageKey& storage_key, const std::string& bucket_name, - base::OnceCallback<void(QuotaErrorOr<BucketId>)> callback) { + blink::mojom::StorageType storage_type, + base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - LazyInitialize(); + EnsureDatabaseOpened(); PostTaskAndReplyWithResultForDBThread( - base::BindOnce(&CreateBucketOnDBThread, origin, bucket_name), - base::BindOnce(&QuotaManagerImpl::DidGetBucketId, + base::BindOnce(&CreateBucketOnDBThread, storage_key, bucket_name, + storage_type), + base::BindOnce(&QuotaManagerImpl::DidGetBucket, weak_factory_.GetWeakPtr(), std::move(callback))); } -void QuotaManagerImpl::GetBucketId( - const url::Origin& origin, +void QuotaManagerImpl::GetBucket( + const StorageKey& storage_key, const std::string& bucket_name, - base::OnceCallback<void(QuotaErrorOr<BucketId>)> callback) { + blink::mojom::StorageType type, + base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - LazyInitialize(); + EnsureDatabaseOpened(); PostTaskAndReplyWithResultForDBThread( - base::BindOnce(&GetBucketIdOnDBThread, origin, bucket_name), - base::BindOnce(&QuotaManagerImpl::DidGetBucketId, + base::BindOnce(&GetBucketOnDBThread, storage_key, bucket_name, type), + base::BindOnce(&QuotaManagerImpl::DidGetBucket, + weak_factory_.GetWeakPtr(), std::move(callback))); +} + +void QuotaManagerImpl::GetStorageKeysForType(blink::mojom::StorageType type, + GetStorageKeysCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + EnsureDatabaseOpened(); + + PostTaskAndReplyWithResultForDBThread( + base::BindOnce(&GetStorageKeysForTypeOnDBThread, type), + base::BindOnce(&QuotaManagerImpl::DidGetStorageKeys, weak_factory_.GetWeakPtr(), std::move(callback))); } void QuotaManagerImpl::GetUsageInfo(GetUsageInfoCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - LazyInitialize(); + EnsureDatabaseOpened(); GetUsageInfoTask* get_usage_info = new GetUsageInfoTask(this, std::move(callback)); get_usage_info->Start(); } void QuotaManagerImpl::GetUsageAndQuotaForWebApps( - const url::Origin& origin, + const StorageKey& storage_key, StorageType type, UsageAndQuotaCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); GetUsageAndQuotaWithBreakdown( - origin, type, + storage_key, type, base::BindOnce(&DidGetUsageAndQuotaStripBreakdown, std::move(callback))); } void QuotaManagerImpl::GetUsageAndQuotaWithBreakdown( - const url::Origin& origin, + const StorageKey& storage_key, StorageType type, UsageAndQuotaWithBreakdownCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); GetUsageAndQuotaForDevtools( - origin, type, + storage_key, type, base::BindOnce(&DidGetUsageAndQuotaStripOverride, std::move(callback))); } void QuotaManagerImpl::GetUsageAndQuotaForDevtools( - const url::Origin& origin, + const StorageKey& storage_key, StorageType type, UsageAndQuotaForDevtoolsCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -1021,25 +1152,27 @@ void QuotaManagerImpl::GetUsageAndQuotaForDevtools( /*usage_breakdown=*/nullptr); return; } - LazyInitialize(); + EnsureDatabaseOpened(); - bool is_session_only = - type == StorageType::kTemporary && special_storage_policy_ && - special_storage_policy_->IsStorageSessionOnly(origin.GetURL()); + bool is_session_only = type == StorageType::kTemporary && + special_storage_policy_ && + special_storage_policy_->IsStorageSessionOnly( + storage_key.origin().GetURL()); - absl::optional<int64_t> quota_override = GetQuotaOverrideForOrigin(origin); + absl::optional<int64_t> quota_override = + GetQuotaOverrideForStorageKey(storage_key); UsageAndQuotaInfoGatherer* helper = new UsageAndQuotaInfoGatherer( - this, origin, type, IsStorageUnlimited(origin, type), is_session_only, - is_incognito_, quota_override, std::move(callback)); + this, storage_key, type, IsStorageUnlimited(storage_key, type), + is_session_only, is_incognito_, quota_override, std::move(callback)); helper->Start(); } -void QuotaManagerImpl::GetUsageAndQuota(const url::Origin& origin, +void QuotaManagerImpl::GetUsageAndQuota(const StorageKey& storage_key, StorageType type, UsageAndQuotaCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (IsStorageUnlimited(origin, type)) { + if (IsStorageUnlimited(storage_key, type)) { // TODO(michaeln): This seems like a non-obvious odd behavior, probably for // apps/extensions, but it would be good to eliminate this special case. std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk, 0, kNoLimit); @@ -1054,24 +1187,26 @@ void QuotaManagerImpl::GetUsageAndQuota(const url::Origin& origin, /*quota*/ 0); return; } - LazyInitialize(); + EnsureDatabaseOpened(); - bool is_session_only = - type == StorageType::kTemporary && special_storage_policy_ && - special_storage_policy_->IsStorageSessionOnly(origin.GetURL()); + bool is_session_only = type == StorageType::kTemporary && + special_storage_policy_ && + special_storage_policy_->IsStorageSessionOnly( + storage_key.origin().GetURL()); - absl::optional<int64_t> quota_override = GetQuotaOverrideForOrigin(origin); + absl::optional<int64_t> quota_override = + GetQuotaOverrideForStorageKey(storage_key); UsageAndQuotaInfoGatherer* helper = new UsageAndQuotaInfoGatherer( - this, origin, type, IsStorageUnlimited(origin, type), is_session_only, - is_incognito_, quota_override, + this, storage_key, type, IsStorageUnlimited(storage_key, type), + is_session_only, is_incognito_, quota_override, base::BindOnce(&DidGetUsageAndQuotaStripOverride, base::BindOnce(&DidGetUsageAndQuotaStripBreakdown, std::move(callback)))); helper->Start(); } -void QuotaManagerImpl::NotifyWriteFailed(const url::Origin& origin) { +void QuotaManagerImpl::NotifyWriteFailed(const StorageKey& storage_key) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); auto age_of_disk_stats = base::TimeTicks::Now() - @@ -1083,45 +1218,38 @@ void QuotaManagerImpl::NotifyWriteFailed(const url::Origin& origin) { int64_t total_space = std::get<1>(cached_disk_stats_for_storage_pressure_); int64_t available_space = std::get<2>(cached_disk_stats_for_storage_pressure_); - MaybeRunStoragePressureCallback(origin, total_space, available_space); + MaybeRunStoragePressureCallback(storage_key, total_space, available_space); } GetStorageCapacity( base::BindOnce(&QuotaManagerImpl::MaybeRunStoragePressureCallback, - weak_factory_.GetWeakPtr(), origin)); -} - -void QuotaManagerImpl::NotifyOriginInUse(const url::Origin& origin) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(io_thread_->BelongsToCurrentThread()); - origins_in_use_[origin]++; -} - -void QuotaManagerImpl::NotifyOriginNoLongerInUse(const url::Origin& origin) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(io_thread_->BelongsToCurrentThread()); - DCHECK(IsOriginInUse(origin)); - int& count = origins_in_use_[origin]; - if (--count == 0) - origins_in_use_.erase(origin); + weak_factory_.GetWeakPtr(), storage_key)); } void QuotaManagerImpl::SetUsageCacheEnabled(QuotaClientType client_id, - const url::Origin& origin, + const StorageKey& storage_key, StorageType type, bool enabled) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - LazyInitialize(); + EnsureDatabaseOpened(); DCHECK(GetUsageTracker(type)); - GetUsageTracker(type)->SetUsageCacheEnabled(client_id, origin, enabled); + GetUsageTracker(type)->SetUsageCacheEnabled(client_id, storage_key, enabled); } -void QuotaManagerImpl::DeleteOriginData(const url::Origin& origin, - StorageType type, +void QuotaManagerImpl::DeleteStorageKeyData(const StorageKey& storage_key, + StorageType type, + QuotaClientTypes quota_client_types, + StatusCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DeleteStorageKeyDataInternal(storage_key, type, std::move(quota_client_types), + std::move(callback)); +} + +void QuotaManagerImpl::DeleteBucketData(const BucketInfo& bucket, QuotaClientTypes quota_client_types, StatusCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DeleteOriginDataInternal(origin, type, std::move(quota_client_types), false, + DeleteBucketDataInternal(bucket, std::move(quota_client_types), false, std::move(callback)); } @@ -1140,7 +1268,7 @@ void QuotaManagerImpl::DeleteHostData(const std::string& host, QuotaClientTypes quota_client_types, StatusCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - LazyInitialize(); + EnsureDatabaseOpened(); DCHECK(client_types_.contains(type)); if (host.empty() || client_types_[type].empty()) { @@ -1156,7 +1284,7 @@ void QuotaManagerImpl::DeleteHostData(const std::string& host, void QuotaManagerImpl::GetPersistentHostQuota(const std::string& host, QuotaCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - LazyInitialize(); + EnsureDatabaseOpened(); if (host.empty()) { // This could happen if we are called on file:///. // TODO(kinuko) We may want to respect --allow-file-access-from-files @@ -1181,7 +1309,7 @@ void QuotaManagerImpl::SetPersistentHostQuota(const std::string& host, int64_t new_quota, QuotaCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - LazyInitialize(); + EnsureDatabaseOpened(); if (host.empty()) { // This could happen if we are called on file:///. std::move(callback).Run(blink::mojom::QuotaStatusCode::kErrorNotSupported, @@ -1217,7 +1345,7 @@ void QuotaManagerImpl::SetPersistentHostQuota(const std::string& host, void QuotaManagerImpl::GetGlobalUsage(StorageType type, GlobalUsageCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - LazyInitialize(); + EnsureDatabaseOpened(); DCHECK(GetUsageTracker(type)); GetUsageTracker(type)->GetGlobalUsage(std::move(callback)); } @@ -1227,7 +1355,7 @@ void QuotaManagerImpl::GetHostUsageWithBreakdown( StorageType type, UsageWithBreakdownCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - LazyInitialize(); + EnsureDatabaseOpened(); DCHECK(GetUsageTracker(type)); GetUsageTracker(type)->GetHostUsageWithBreakdown(host, std::move(callback)); } @@ -1238,15 +1366,15 @@ std::map<std::string, std::string> QuotaManagerImpl::GetStatistics() { if (temporary_storage_evictor_) { std::map<std::string, int64_t> stats; temporary_storage_evictor_->GetStatistics(&stats); - for (const auto& origin_usage_pair : stats) { - statistics[origin_usage_pair.first] = - base::NumberToString(origin_usage_pair.second); + for (const auto& storage_key_usage_pair : stats) { + statistics[storage_key_usage_pair.first] = + base::NumberToString(storage_key_usage_pair.second); } } return statistics; } -bool QuotaManagerImpl::IsStorageUnlimited(const url::Origin& origin, +bool QuotaManagerImpl::IsStorageUnlimited(const StorageKey& storage_key, StorageType type) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // For syncable storage we should always enforce quota (since the @@ -1256,23 +1384,20 @@ bool QuotaManagerImpl::IsStorageUnlimited(const url::Origin& origin, if (type == StorageType::kQuotaNotManaged) return true; return special_storage_policy_.get() && - special_storage_policy_->IsStorageUnlimited(origin.GetURL()); + special_storage_policy_->IsStorageUnlimited( + storage_key.origin().GetURL()); } -void QuotaManagerImpl::GetOriginsModifiedBetween(StorageType type, +void QuotaManagerImpl::GetBucketsModifiedBetween(StorageType type, base::Time begin, base::Time end, - GetOriginsCallback callback) { + GetBucketsCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - LazyInitialize(); - GetModifiedSinceHelper* helper = new GetModifiedSinceHelper; + EnsureDatabaseOpened(); PostTaskAndReplyWithResultForDBThread( - FROM_HERE, - base::BindOnce(&GetModifiedSinceHelper::GetModifiedBetweenOnDBThread, - base::Unretained(helper), type, begin, end), - base::BindOnce(&GetModifiedSinceHelper::DidGetModifiedBetween, - base::Owned(helper), weak_factory_.GetWeakPtr(), - std::move(callback), type)); + base::BindOnce(&GetModifiedBetweenOnDBThread, type, begin, end), + base::BindOnce(&QuotaManagerImpl::DidGetModifiedBetween, + weak_factory_.GetWeakPtr(), std::move(callback), type)); } bool QuotaManagerImpl::ResetUsageTracker(StorageType type) { @@ -1302,21 +1427,14 @@ bool QuotaManagerImpl::ResetUsageTracker(StorageType type) { QuotaManagerImpl::~QuotaManagerImpl() { proxy_->InvalidateQuotaManagerImpl(base::PassKey<QuotaManagerImpl>()); - // Iterating over `legacy_clients_for_ownership_` is correct here because we - // want to call OnQuotaManagerDestroyed() once per QuotaClient. - for (const auto& client : legacy_clients_for_ownership_) - client->OnQuotaManagerDestroyed(); - if (database_) db_runner_->DeleteSoon(FROM_HERE, database_.release()); } -QuotaManagerImpl::EvictionContext::EvictionContext() - : evicted_type(StorageType::kUnknown) {} - +QuotaManagerImpl::EvictionContext::EvictionContext() = default; QuotaManagerImpl::EvictionContext::~EvictionContext() = default; -void QuotaManagerImpl::LazyInitialize() { +void QuotaManagerImpl::EnsureDatabaseOpened() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(io_thread_->BelongsToCurrentThread()); if (database_) { @@ -1347,41 +1465,42 @@ void QuotaManagerImpl::LazyInitialize() { base::PostTaskAndReplyWithResult( db_runner_.get(), FROM_HERE, - base::BindOnce(&QuotaDatabase::IsOriginDatabaseBootstrapped, + base::BindOnce(&QuotaDatabase::IsBootstrappedForEviction, base::Unretained(database_.get())), - base::BindOnce(&QuotaManagerImpl::FinishLazyInitialize, + base::BindOnce(&QuotaManagerImpl::DidOpenDatabase, weak_factory_.GetWeakPtr())); } -void QuotaManagerImpl::FinishLazyInitialize(bool is_database_bootstrapped) { +void QuotaManagerImpl::DidOpenDatabase(bool is_database_bootstrapped) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - is_database_bootstrapped_ = is_database_bootstrapped; + is_database_bootstrapped_for_eviction_ = is_database_bootstrapped; StartEviction(); } void QuotaManagerImpl::BootstrapDatabaseForEviction( - GetOriginCallback did_get_origin_callback, + GetBucketCallback did_get_bucket_callback, int64_t usage, int64_t unlimited_usage) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // The usage cache should be fully populated now so we can - // seed the database with origins we know about. - std::set<url::Origin> origins = temporary_usage_tracker_->GetCachedOrigins(); + // seed the database with storage keys we know about. + std::set<StorageKey> storage_keys = + temporary_usage_tracker_->GetCachedStorageKeys(); PostTaskAndReplyWithResultForDBThread( FROM_HERE, - base::BindOnce(&BootstrapDatabaseOnDBThread, std::move(origins)), - base::BindOnce(&QuotaManagerImpl::DidBootstrapDatabase, + base::BindOnce(&BootstrapDatabaseOnDBThread, std::move(storage_keys)), + base::BindOnce(&QuotaManagerImpl::DidBootstrapDatabaseForEviction, weak_factory_.GetWeakPtr(), - std::move(did_get_origin_callback))); + std::move(did_get_bucket_callback))); } -void QuotaManagerImpl::DidBootstrapDatabase( - GetOriginCallback did_get_origin_callback, +void QuotaManagerImpl::DidBootstrapDatabaseForEviction( + GetBucketCallback did_get_bucket_callback, bool success) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - is_database_bootstrapped_ = success; + is_database_bootstrapped_for_eviction_ = success; DidDatabaseWork(success); - GetLRUOrigin(StorageType::kTemporary, std::move(did_get_origin_callback)); + GetLRUBucket(StorageType::kTemporary, std::move(did_get_bucket_callback)); } void QuotaManagerImpl::RegisterClient( @@ -1395,30 +1514,8 @@ void QuotaManagerImpl::RegisterClient( clients_for_ownership_.emplace_back(std::move(client)); mojom::QuotaClient* client_ptr = clients_for_ownership_.back().get(); - // TODO(crbug.com/1163009): Remove this block after all QuotaClients have been - // mojofied. - legacy_clients_for_ownership_.push_back( - base::MakeRefCounted<MojoQuotaClientWrapper>(client_ptr)); - QuotaClient* legacy_client_ptr = legacy_clients_for_ownership_.back().get(); - - // TODO(crbug.com/1163009): Use client_ptr instead of legacy_client_ptr after - // all QuotaClients have been mojofied. for (blink::mojom::StorageType storage_type : storage_types) - client_types_[storage_type].insert({legacy_client_ptr, client_type}); -} - -void QuotaManagerImpl::RegisterLegacyClient( - scoped_refptr<QuotaClient> client, - QuotaClientType client_type, - const std::vector<blink::mojom::StorageType>& storage_types) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!database_.get()) - << "All clients must be registered before the database is initialized"; - DCHECK(client.get()); - - for (blink::mojom::StorageType storage_type : storage_types) - client_types_[storage_type].insert({client.get(), client_type}); - legacy_clients_for_ownership_.push_back(std::move(client)); + client_types_[storage_type].insert({client_ptr, client_type}); } UsageTracker* QuotaManagerImpl::GetUsageTracker(StorageType type) const { @@ -1438,43 +1535,63 @@ UsageTracker* QuotaManagerImpl::GetUsageTracker(StorageType type) const { return nullptr; } -std::set<url::Origin> QuotaManagerImpl::GetCachedOrigins(StorageType type) { +std::set<StorageKey> QuotaManagerImpl::GetCachedStorageKeys(StorageType type) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - LazyInitialize(); + EnsureDatabaseOpened(); DCHECK(GetUsageTracker(type)); - return GetUsageTracker(type)->GetCachedOrigins(); + return GetUsageTracker(type)->GetCachedStorageKeys(); } -void QuotaManagerImpl::NotifyStorageAccessed(const url::Origin& origin, +void QuotaManagerImpl::NotifyStorageAccessed(const StorageKey& storage_key, StorageType type, base::Time access_time) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - LazyInitialize(); - if (type == StorageType::kTemporary && is_getting_eviction_origin_) { - // Record the accessed origins while GetLRUOrigin task is runing + EnsureDatabaseOpened(); + if (type == StorageType::kTemporary && is_getting_eviction_bucket_) { + // Record the accessed storage keys while GetLRUBucket task is running + // to filter out them from eviction. + access_notified_storage_keys_.insert(storage_key); + } + + if (db_disabled_) + return; + PostTaskAndReplyWithResultForDBThread( + FROM_HERE, + base::BindOnce(&UpdateAccessTimeOnDBThread, storage_key, type, + access_time), + base::BindOnce(&QuotaManagerImpl::DidDatabaseWork, + weak_factory_.GetWeakPtr())); +} + +void QuotaManagerImpl::NotifyBucketAccessed(const BucketId bucket_id, + base::Time access_time) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + EnsureDatabaseOpened(); + if (is_getting_eviction_bucket_) { + // Record the accessed buckets while GetLRUStorageKey task is running // to filter out them from eviction. - access_notified_origins_.insert(origin); + access_notified_buckets_.insert(bucket_id); } if (db_disabled_) return; PostTaskAndReplyWithResultForDBThread( FROM_HERE, - base::BindOnce(&UpdateAccessTimeOnDBThread, origin, type, access_time), + base::BindOnce(&UpdateBucketAccessTimeOnDBThread, bucket_id, access_time), base::BindOnce(&QuotaManagerImpl::DidDatabaseWork, weak_factory_.GetWeakPtr())); } void QuotaManagerImpl::NotifyStorageModified(QuotaClientType client_id, - const url::Origin& origin, + const StorageKey& storage_key, StorageType type, int64_t delta, base::Time modification_time, base::OnceClosure callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - LazyInitialize(); + EnsureDatabaseOpened(); DCHECK(GetUsageTracker(type)); - GetUsageTracker(type)->UpdateUsageCache(client_id, origin, delta); + GetUsageTracker(type)->UpdateUsageCache(client_id, storage_key, delta); if (callback) std::move(callback).Run(); @@ -1484,7 +1601,32 @@ void QuotaManagerImpl::NotifyStorageModified(QuotaClientType client_id, PostTaskAndReplyWithResultForDBThread( FROM_HERE, - base::BindOnce(&UpdateModifiedTimeOnDBThread, origin, type, + base::BindOnce(&UpdateModifiedTimeOnDBThread, storage_key, type, + modification_time), + base::BindOnce(&QuotaManagerImpl::DidDatabaseWork, + weak_factory_.GetWeakPtr())); +} + +void QuotaManagerImpl::NotifyBucketModified(QuotaClientType client_id, + const BucketId bucket_id, + int64_t delta, + base::Time modification_time, + base::OnceClosure callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + EnsureDatabaseOpened(); + + // TODO(crbug.com/1199417): Update bucket usage in UsageTracker once + // QuotaClient & UsageTracker operate by bucket. + + if (callback) + std::move(callback).Run(); + + if (db_disabled_) + return; + + PostTaskAndReplyWithResultForDBThread( + FROM_HERE, + base::BindOnce(&UpdateBucketModifiedTimeOnDBThread, bucket_id, modification_time), base::BindOnce(&QuotaManagerImpl::DidDatabaseWork, weak_factory_.GetWeakPtr())); @@ -1524,53 +1666,80 @@ void QuotaManagerImpl::StartEviction() { temporary_storage_evictor_->Start(); } -void QuotaManagerImpl::DeleteOriginFromDatabase(const url::Origin& origin, - StorageType type, +void QuotaManagerImpl::DeleteStorageKeyFromDatabase( + const StorageKey& storage_key, + StorageType type) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + EnsureDatabaseOpened(); + if (db_disabled_) + return; + + PostTaskAndReplyWithResultForDBThread( + FROM_HERE, + base::BindOnce(&DeleteStorageKeyInfoOnDBThread, storage_key, type), + base::BindOnce(&QuotaManagerImpl::DidDatabaseWork, + weak_factory_.GetWeakPtr())); +} + +void QuotaManagerImpl::DeleteBucketFromDatabase(BucketId bucket_id, bool is_eviction) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - LazyInitialize(); + EnsureDatabaseOpened(); if (db_disabled_) return; PostTaskAndReplyWithResultForDBThread( FROM_HERE, - base::BindOnce(&DeleteOriginInfoOnDBThread, origin, type, is_eviction), + base::BindOnce(&DeleteBucketInfoOnDBThread, bucket_id, is_eviction), base::BindOnce(&QuotaManagerImpl::DidDatabaseWork, weak_factory_.GetWeakPtr())); } -void QuotaManagerImpl::DidOriginDataEvicted( +void QuotaManagerImpl::DidBucketDataEvicted( blink::mojom::QuotaStatusCode status) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(io_thread_->BelongsToCurrentThread()); - // We only try evict origins that are not in use, so basically - // deletion attempt for eviction should not fail. Let's record - // the origin if we get error and exclude it from future eviction - // if the error happens consistently (> kThresholdOfErrorsToBeDenylisted). + // We only try to evict buckets that are not in use, so basically deletion + // attempt for eviction should not fail. Let's record the bucket if we get + // an error and exclude it from future eviction if the error happens + // consistently (> kThresholdOfErrorsToBeDenylisted). if (status != blink::mojom::QuotaStatusCode::kOk) - origins_in_error_[eviction_context_.evicted_origin]++; + buckets_in_error_[eviction_context_.evicted_bucket.id]++; - std::move(eviction_context_.evict_origin_data_callback).Run(status); + std::move(eviction_context_.evict_bucket_data_callback).Run(status); } -void QuotaManagerImpl::DeleteOriginDataInternal( - const url::Origin& origin, - StorageType type, +void QuotaManagerImpl::DeleteBucketDataInternal( + const BucketInfo& bucket, QuotaClientTypes quota_client_types, bool is_eviction, StatusCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - LazyInitialize(); + EnsureDatabaseOpened(); - OriginDataDeleter* deleter = - new OriginDataDeleter(this, origin, type, std::move(quota_client_types), + BucketDataDeleter* deleter = + new BucketDataDeleter(this, bucket, std::move(quota_client_types), is_eviction, std::move(callback)); deleter->Start(); } +void QuotaManagerImpl::DeleteStorageKeyDataInternal( + const StorageKey& storage_key, + StorageType type, + QuotaClientTypes quota_client_types, + StatusCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + EnsureDatabaseOpened(); + + StorageKeyDataDeleter* deleter = new StorageKeyDataDeleter( + this, storage_key, type, std::move(quota_client_types), + std::move(callback)); + deleter->Start(); +} + void QuotaManagerImpl::MaybeRunStoragePressureCallback( - const url::Origin& origin, + const StorageKey& storage_key, int64_t total_space, int64_t available_space) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -1582,17 +1751,17 @@ void QuotaManagerImpl::MaybeRunStoragePressureCallback( if (!storage_pressure_callback_) { // Quota will hold onto a storage pressure notification if no storage // pressure callback is set. - origin_for_pending_storage_pressure_callback_ = std::move(origin); + storage_key_for_pending_storage_pressure_callback_ = std::move(storage_key); return; } if (available_space < kStoragePressureThresholdRatio * total_space) { - storage_pressure_callback_.Run(std::move(origin)); + storage_pressure_callback_.Run(std::move(storage_key)); } } -void QuotaManagerImpl::SimulateStoragePressure(const url::Origin origin) { - storage_pressure_callback_.Run(origin); +void QuotaManagerImpl::SimulateStoragePressure(const StorageKey& storage_key) { + storage_pressure_callback_.Run(storage_key); } void QuotaManagerImpl::DetermineStoragePressure(int64_t total_space, @@ -1614,12 +1783,12 @@ void QuotaManagerImpl::DetermineStoragePressure(int64_t total_space, } void QuotaManagerImpl::SetStoragePressureCallback( - base::RepeatingCallback<void(url::Origin)> storage_pressure_callback) { + base::RepeatingCallback<void(StorageKey)> storage_pressure_callback) { storage_pressure_callback_ = storage_pressure_callback; - if (origin_for_pending_storage_pressure_callback_.has_value()) { + if (storage_key_for_pending_storage_pressure_callback_.has_value()) { storage_pressure_callback_.Run( - std::move(origin_for_pending_storage_pressure_callback_.value())); - origin_for_pending_storage_pressure_callback_ = absl::nullopt; + std::move(storage_key_for_pending_storage_pressure_callback_.value())); + storage_key_for_pending_storage_pressure_callback_ = absl::nullopt; } } @@ -1628,48 +1797,49 @@ int QuotaManagerImpl::GetOverrideHandleId() { return ++next_override_handle_id_; } -void QuotaManagerImpl::OverrideQuotaForOrigin( +void QuotaManagerImpl::OverrideQuotaForStorageKey( int handle_id, - const url::Origin& origin, + const StorageKey& storage_key, absl::optional<int64_t> quota_size) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (quota_size.has_value()) { DCHECK_GE(next_override_handle_id_, handle_id); // Bracket notation is safe here because we want to construct a new - // QuotaOverride in the case that one does not exist for origin. - devtools_overrides_[origin].active_override_session_ids.insert(handle_id); - devtools_overrides_[origin].quota_size = quota_size.value(); + // QuotaOverride in the case that one does not exist for storage key. + devtools_overrides_[storage_key].active_override_session_ids.insert( + handle_id); + devtools_overrides_[storage_key].quota_size = quota_size.value(); } else { - devtools_overrides_.erase(origin); + devtools_overrides_.erase(storage_key); } } void QuotaManagerImpl::WithdrawOverridesForHandle(int handle_id) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - std::vector<url::Origin> origins_to_clear; + std::vector<StorageKey> storage_keys_to_clear; for (auto& devtools_override : devtools_overrides_) { auto& quota_override = devtools_override.second; - auto& origin = devtools_override.first; + auto& storage_key = devtools_override.first; quota_override.active_override_session_ids.erase(handle_id); if (!quota_override.active_override_session_ids.size()) { - origins_to_clear.push_back(origin); + storage_keys_to_clear.push_back(storage_key); } } - for (auto& origin : origins_to_clear) { - devtools_overrides_.erase(origin); + for (auto& storage_key : storage_keys_to_clear) { + devtools_overrides_.erase(storage_key); } } -absl::optional<int64_t> QuotaManagerImpl::GetQuotaOverrideForOrigin( - const url::Origin& origin) { +absl::optional<int64_t> QuotaManagerImpl::GetQuotaOverrideForStorageKey( + const StorageKey& storage_key) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!base::Contains(devtools_overrides_, origin)) { + if (!base::Contains(devtools_overrides_, storage_key)) { return absl::nullopt; } - return devtools_overrides_[origin].quota_size; + return devtools_overrides_[storage_key].quota_size; } void QuotaManagerImpl::SetQuotaChangeCallbackForTesting( @@ -1731,16 +1901,16 @@ void QuotaManagerImpl::DidGetPersistentGlobalUsageForHistogram( void QuotaManagerImpl::DidDumpBucketTableForHistogram( const BucketTableEntries& entries) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - std::map<url::Origin, int64_t> usage_map = - GetUsageTracker(StorageType::kTemporary)->GetCachedOriginsUsage(); + std::map<StorageKey, int64_t> usage_map = + GetUsageTracker(StorageType::kTemporary)->GetCachedStorageKeysUsage(); base::Time now = base::Time::Now(); for (const auto& info : entries) { if (info.type != StorageType::kTemporary) continue; - // Ignore stale database entries. If there is no map entry, the origin's - // data has been deleted. - auto it = usage_map.find(info.origin); + // Ignore stale database entries. If there is no map entry, the storage + // key's data has been deleted. + auto it = usage_map.find(info.storage_key); if (it == usage_map.end() || it->second == 0) continue; @@ -1757,15 +1927,10 @@ void QuotaManagerImpl::DidDumpBucketTableForHistogram( } } -std::set<url::Origin> QuotaManagerImpl::GetEvictionOriginExceptions() { +std::set<BucketId> QuotaManagerImpl::GetEvictionBucketExceptions() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - std::set<url::Origin> exceptions; - for (const auto& p : origins_in_use_) { - if (p.second > 0) - exceptions.insert(p.first); - } - - for (const auto& p : origins_in_error_) { + std::set<BucketId> exceptions; + for (const auto& p : buckets_in_error_) { if (p.second > QuotaManagerImpl::kThresholdOfErrorsToBeDenylisted) exceptions.insert(p.first); } @@ -1773,65 +1938,70 @@ std::set<url::Origin> QuotaManagerImpl::GetEvictionOriginExceptions() { return exceptions; } -void QuotaManagerImpl::DidGetEvictionOrigin( - GetOriginCallback callback, - const absl::optional<url::Origin>& origin) { +void QuotaManagerImpl::DidGetEvictionBucket( + GetBucketCallback callback, + const absl::optional<BucketInfo>& bucket) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // Make sure the returned origin is (still) not in the origin_in_use_ set - // and has not been accessed since we posted the task. - DCHECK(!origin.has_value() || !origin->GetURL().is_empty()); - if (origin.has_value() && - (base::Contains(origins_in_use_, *origin) || - base::Contains(access_notified_origins_, *origin))) { + // Make sure the returned bucket has not been accessed since we posted the + // eviction task. + DCHECK(!bucket.has_value() || + !bucket->storage_key.origin().GetURL().is_empty()); + // TODO(crbug.com/1208141): Remove this evaluation for storage key once + // QuotaClient is migrated to operate on buckets and NotifyStorageAccessed + // no longer used. + if (bucket.has_value() && bucket->is_default() && + base::Contains(access_notified_storage_keys_, bucket->storage_key)) { + std::move(callback).Run(absl::nullopt); + } else if (bucket.has_value() && + base::Contains(access_notified_buckets_, bucket->id)) { std::move(callback).Run(absl::nullopt); } else { - std::move(callback).Run(origin); + std::move(callback).Run(bucket); } - access_notified_origins_.clear(); + access_notified_storage_keys_.clear(); + access_notified_buckets_.clear(); - is_getting_eviction_origin_ = false; + is_getting_eviction_bucket_ = false; } -void QuotaManagerImpl::GetEvictionOrigin(StorageType type, +void QuotaManagerImpl::GetEvictionBucket(StorageType type, int64_t global_quota, - GetOriginCallback callback) { + GetBucketCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - LazyInitialize(); + EnsureDatabaseOpened(); // This must not be called while there's an in-flight task. - DCHECK(!is_getting_eviction_origin_); - is_getting_eviction_origin_ = true; + DCHECK(!is_getting_eviction_bucket_); + is_getting_eviction_bucket_ = true; - auto did_get_origin_callback = - base::BindOnce(&QuotaManagerImpl::DidGetEvictionOrigin, + auto did_get_bucket_callback = + base::BindOnce(&QuotaManagerImpl::DidGetEvictionBucket, weak_factory_.GetWeakPtr(), std::move(callback)); - if (!is_database_bootstrapped_ && !eviction_disabled_) { - // Once bootstrapped, GetLRUOrigin will be called. + if (!is_database_bootstrapped_for_eviction_ && !eviction_disabled_) { + // Once bootstrapped, GetLRUBucket will be called. GetGlobalUsage( StorageType::kTemporary, base::BindOnce(&QuotaManagerImpl::BootstrapDatabaseForEviction, weak_factory_.GetWeakPtr(), - std::move(did_get_origin_callback))); + std::move(did_get_bucket_callback))); return; } - GetLRUOrigin(type, std::move(did_get_origin_callback)); + GetLRUBucket(type, std::move(did_get_bucket_callback)); } -void QuotaManagerImpl::EvictOriginData(const url::Origin& origin, - StorageType type, +void QuotaManagerImpl::EvictBucketData(const BucketInfo& bucket, StatusCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(io_thread_->BelongsToCurrentThread()); - DCHECK_EQ(type, StorageType::kTemporary); + DCHECK_EQ(bucket.type, StorageType::kTemporary); - eviction_context_.evicted_origin = origin; - eviction_context_.evicted_type = type; - eviction_context_.evict_origin_data_callback = std::move(callback); + eviction_context_.evicted_bucket = bucket; + eviction_context_.evict_bucket_data_callback = std::move(callback); - DeleteOriginDataInternal( - origin, type, AllQuotaClientTypes(), true, - base::BindOnce(&QuotaManagerImpl::DidOriginDataEvicted, + DeleteBucketDataInternal( + bucket, AllQuotaClientTypes(), true, + base::BindOnce(&QuotaManagerImpl::DidBucketDataEvicted, weak_factory_.GetWeakPtr())); } @@ -1839,34 +2009,30 @@ void QuotaManagerImpl::GetEvictionRoundInfo( EvictionRoundInfoCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(io_thread_->BelongsToCurrentThread()); - LazyInitialize(); + EnsureDatabaseOpened(); EvictionRoundInfoHelper* helper = new EvictionRoundInfoHelper(this, std::move(callback)); helper->Start(); } -void QuotaManagerImpl::GetLRUOrigin(StorageType type, - GetOriginCallback callback) { +void QuotaManagerImpl::GetLRUBucket(StorageType type, + GetBucketCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - LazyInitialize(); + EnsureDatabaseOpened(); // This must not be called while there's an in-flight task. - DCHECK(lru_origin_callback_.is_null()); - lru_origin_callback_ = std::move(callback); + DCHECK(lru_bucket_callback_.is_null()); + lru_bucket_callback_ = std::move(callback); if (db_disabled_) { - std::move(lru_origin_callback_).Run(absl::nullopt); + std::move(lru_bucket_callback_).Run(absl::nullopt); return; } - auto origin = std::make_unique<absl::optional<url::Origin>>(); - auto* origin_ptr = origin.get(); PostTaskAndReplyWithResultForDBThread( - FROM_HERE, - base::BindOnce(&GetLRUOriginOnDBThread, type, - GetEvictionOriginExceptions(), - base::RetainedRef(special_storage_policy_), - base::Unretained(origin_ptr)), - base::BindOnce(&QuotaManagerImpl::DidGetLRUOrigin, - weak_factory_.GetWeakPtr(), std::move(origin))); + base::BindOnce(&GetLRUBucketOnDBThread, type, + GetEvictionBucketExceptions(), + base::RetainedRef(special_storage_policy_)), + base::BindOnce(&QuotaManagerImpl::DidGetLRUBucket, + weak_factory_.GetWeakPtr())); } void QuotaManagerImpl::DidGetPersistentHostQuota(const std::string& host, @@ -1891,13 +2057,16 @@ void QuotaManagerImpl::DidSetPersistentHostQuota(const std::string& host, *new_quota); } -void QuotaManagerImpl::DidGetLRUOrigin( - std::unique_ptr<absl::optional<url::Origin>> origin, - bool success) { +void QuotaManagerImpl::DidGetLRUBucket(QuotaErrorOr<BucketInfo> result) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DidDatabaseWork(success); + DidDatabaseWork(result.ok() || result.error() != QuotaError::kDatabaseError); - std::move(lru_origin_callback_).Run(*origin); + if (result.ok()) { + std::move(lru_bucket_callback_) + .Run(absl::make_optional(std::move(result.value()))); + } else { + std::move(lru_bucket_callback_).Run(absl::nullopt); + } } namespace { @@ -1990,14 +2159,39 @@ void QuotaManagerImpl::DidDatabaseWork(bool success) { db_disabled_ = !success; } -void QuotaManagerImpl::DidGetBucketId( - base::OnceCallback<void(QuotaErrorOr<BucketId>)> callback, - QuotaErrorOr<BucketId> result) { +void QuotaManagerImpl::DidGetBucket( + base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback, + QuotaErrorOr<BucketInfo> result) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DidDatabaseWork(result.ok()); + DidDatabaseWork(result.ok() || result.error() != QuotaError::kDatabaseError); std::move(callback).Run(std::move(result)); } +void QuotaManagerImpl::DidGetStorageKeys( + GetStorageKeysCallback callback, + QuotaErrorOr<std::set<StorageKey>> result) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DidDatabaseWork(result.ok() || result.error() != QuotaError::kDatabaseError); + if (!result.ok()) { + std::move(callback).Run(std::set<StorageKey>()); + return; + } + std::move(callback).Run(std::move(result.value())); +} + +void QuotaManagerImpl::DidGetModifiedBetween( + GetBucketsCallback callback, + StorageType type, + QuotaErrorOr<std::set<BucketInfo>> result) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DidDatabaseWork(result.ok() || result.error() != QuotaError::kDatabaseError); + if (!result.ok()) { + std::move(callback).Run(std::set<BucketInfo>(), type); + return; + } + std::move(callback).Run(result.value(), type); +} + void QuotaManagerImpl::PostTaskAndReplyWithResultForDBThread( const base::Location& from_here, base::OnceCallback<bool(QuotaDatabase*)> task, diff --git a/chromium/storage/browser/quota/quota_manager_impl.h b/chromium/storage/browser/quota/quota_manager_impl.h index 01701a0c9db..2dfaf62a7f4 100644 --- a/chromium/storage/browser/quota/quota_manager_impl.h +++ b/chromium/storage/browser/quota/quota_manager_impl.h @@ -19,7 +19,6 @@ #include "base/callback.h" #include "base/component_export.h" #include "base/containers/contains.h" -#include "base/containers/flat_set.h" #include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/ref_counted.h" @@ -28,21 +27,21 @@ #include "base/sequence_checker.h" #include "base/time/time.h" #include "base/timer/timer.h" +#include "components/services/storage/public/cpp/buckets/bucket_info.h" #include "components/services/storage/public/cpp/quota_error_or.h" #include "components/services/storage/public/mojom/quota_client.mojom.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" #include "storage/browser/quota/quota_callbacks.h" -#include "storage/browser/quota/quota_client.h" #include "storage/browser/quota/quota_client_type.h" #include "storage/browser/quota/quota_database.h" #include "storage/browser/quota/quota_settings.h" #include "storage/browser/quota/quota_task.h" #include "storage/browser/quota/special_storage_policy.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom-forward.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h" -#include "url/origin.h" namespace base { class SequencedTaskRunner; @@ -78,15 +77,14 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaEvictionHandler { // the current settings, capacity, and usage. virtual void GetEvictionRoundInfo(EvictionRoundInfoCallback callback) = 0; - // Returns next origin to evict, or nullopt if there are no evictable - // origins. - virtual void GetEvictionOrigin(blink::mojom::StorageType type, + // Returns the next bucket to evict, or nullopt if there are no evictable + // buckets. + virtual void GetEvictionBucket(blink::mojom::StorageType type, int64_t global_quota, - GetOriginCallback callback) = 0; + GetBucketCallback callback) = 0; - // Called to evict an origin. - virtual void EvictOriginData(const url::Origin& origin, - blink::mojom::StorageType type, + // Called to evict a bucket. + virtual void EvictBucketData(const BucketInfo& bucket, StatusCallback callback) = 0; protected: @@ -99,6 +97,17 @@ struct UsageInfo { const std::string host; const blink::mojom::StorageType type; const int64_t usage; + + bool operator==(const UsageInfo& that) const { + return std::tie(host, usage, type) == + std::tie(that.host, that.usage, that.type); + } + + friend std::ostream& operator<<(std::ostream& os, + const UsageInfo& usage_info) { + return os << "{\"" << usage_info.host << "\", " << usage_info.type << ", " + << usage_info.usage << "}"; + } }; // Entry point into the Quota System @@ -161,49 +170,69 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl // Returns a proxy object that can be used on any thread. QuotaManagerProxy* proxy() { return proxy_.get(); } - // Creates a bucket for `origin` with `bucket_name` and returns the BucketId - // to the callback. Will return a QuotaError to the callback on failure. - void CreateBucket(const url::Origin& origin, - const std::string& bucket_name, - base::OnceCallback<void(QuotaErrorOr<BucketId>)>); - - // Retrieves the BucketId of the bucket with `bucket_name` for `origin` and - // returns it to the callback. Will return an empty BucketId if a bucket does - // not exist. Will return a QuotaError on operation failure. - void GetBucketId(const url::Origin& origin, - const std::string& bucket_name, - base::OnceCallback<void(QuotaErrorOr<BucketId>)>); + // Gets the bucket with `bucket_name` for the `storage_key` for StorageType + // kTemporary and returns the BucketInfo. If one doesn't exist, it creates + // a new bucket with the specified policies. Returns a QuotaError if the + // operation has failed. + void GetOrCreateBucket(const blink::StorageKey& storage_key, + const std::string& bucket_name, + base::OnceCallback<void(QuotaErrorOr<BucketInfo>)>); + + // Creates a bucket for `origin` with `bucket_name` and returns BucketInfo + // to the callback. Will return a QuotaError to the callback on operation + // failure. + // + // TODO(crbug.com/1208141): Remove `storage_type` when the only supported + // StorageType is kTemporary. + void CreateBucketForTesting( + const blink::StorageKey& storage_key, + const std::string& bucket_name, + blink::mojom::StorageType storage_type, + base::OnceCallback<void(QuotaErrorOr<BucketInfo>)>); + + // Retrieves the BucketInfo of the bucket with `bucket_name` for `storage_key` + // and returns it to the callback. Will return a QuotaError if the bucket does + // not exist or on operation failure. + void GetBucket(const blink::StorageKey& storage_key, + const std::string& bucket_name, + blink::mojom::StorageType type, + base::OnceCallback<void(QuotaErrorOr<BucketInfo>)>); + + // Retrieves all storage keys for `type` that are in the bucket database. + // Used for listing storage keys when showing storage key quota usage. + void GetStorageKeysForType(blink::mojom::StorageType type, + GetStorageKeysCallback callback); // Called by clients or webapps. Returns usage per host. void GetUsageInfo(GetUsageInfoCallback callback); // Called by Web Apps (deprecated quota API). // This method is declared as virtual to allow test code to override it. - virtual void GetUsageAndQuotaForWebApps(const url::Origin& origin, + virtual void GetUsageAndQuotaForWebApps(const blink::StorageKey& storage_key, blink::mojom::StorageType type, UsageAndQuotaCallback callback); // Called by Web Apps (navigator.storage.estimate()) // This method is declared as virtual to allow test code to override it. virtual void GetUsageAndQuotaWithBreakdown( - const url::Origin& origin, + const blink::StorageKey& storage_key, blink::mojom::StorageType type, UsageAndQuotaWithBreakdownCallback callback); // Called by DevTools. virtual void GetUsageAndQuotaForDevtools( - const url::Origin& origin, + const blink::StorageKey& storage_key, blink::mojom::StorageType type, UsageAndQuotaForDevtoolsCallback callback); // Called by storage backends. // - // For UnlimitedStorage origins, this version skips usage and quota handling - // to avoid extra query cost. Do not call this method for apps/user-facing - // code. + // For UnlimitedStorage storage keys, this version skips usage and quota + // handling to avoid extra query cost. Do not call this method for + // apps/user-facing code. // // This method is declared as virtual to allow test code to override it. - virtual void GetUsageAndQuota(const url::Origin& origin, + virtual void GetUsageAndQuota(const blink::StorageKey& storage_key, blink::mojom::StorageType type, UsageAndQuotaCallback callback); @@ -211,16 +240,26 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl // // Quota-managed storage backends should call this method when storage is // accessed. Used to maintain LRU ordering. - void NotifyStorageAccessed(const url::Origin& origin, + // TODO(crbug.com/1199417): Remove when all usages have updated to use + // NotifyBucketAccessed. + void NotifyStorageAccessed(const blink::StorageKey& storage_key, blink::mojom::StorageType type, base::Time access_time); // Called by storage backends via proxy. // + // Quota-managed storage backends should call this method when a bucket is + // accessed. Used to maintain LRU ordering. + void NotifyBucketAccessed(BucketId bucket_id, base::Time access_time); + + // Called by storage backends via proxy. + // // Quota-managed storage backends must call this method when they have made // any modifications that change the amount of data stored in their storage. + // TODO(crbug.com/1199417): Remove when all usages have updated to use + // NotifyBucketModified. void NotifyStorageModified(QuotaClientType client_id, - const url::Origin& origin, + const blink::StorageKey& storage_key, blink::mojom::StorageType type, int64_t delta, base::Time modification_time, @@ -228,36 +267,38 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl // 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 a bucket. + void NotifyBucketModified(QuotaClientType client_id, + BucketId bucket_id, + int64_t delta, + base::Time modification_time, + base::OnceClosure callback); + // Client storage must call this method whenever they run into disk // write errors. Used as a hint to determine if the storage partition is out // of space, and trigger actions if deemed appropriate. // // This method is declared as virtual to allow test code to override it. - virtual void NotifyWriteFailed(const url::Origin& origin); - - // Used to avoid evicting origins with open pages. - // A call to NotifyOriginInUse must be balanced by a later call - // to NotifyOriginNoLongerInUse. - void NotifyOriginInUse(const url::Origin& origin); - void NotifyOriginNoLongerInUse(const url::Origin& origin); - bool IsOriginInUse(const url::Origin& origin) const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return base::Contains(origins_in_use_, origin); - } + virtual void NotifyWriteFailed(const blink::StorageKey& storage_key); void SetUsageCacheEnabled(QuotaClientType client_id, - const url::Origin& origin, + const blink::StorageKey& storage_key, blink::mojom::StorageType type, bool enabled); - // DeleteOriginData and DeleteHostData (surprisingly enough) delete data of a - // particular blink::mojom::StorageType associated with either a specific - // origin or set of origins. Each method additionally requires a - // |quota_client_types| which specifies the types of QuotaClients to delete - // from the origin. Pass in QuotaClientType::AllClients() to remove all - // clients from the origin, regardless of type. - virtual void DeleteOriginData(const url::Origin& origin, - blink::mojom::StorageType type, + // DeleteStorageKeyData and DeleteHostData (surprisingly enough) delete data + // of a particular blink::mojom::StorageType associated with either a specific + // storage key or set of storage keys. DeleteBucketData will delete only the + // specified bucket. Each method additionally requires a |quota_client_types| + // which specifies the types of QuotaClients to delete from the storage key. + // Pass in QuotaClientType::AllClients() to remove all clients from the + // storage key, regardless of type. + virtual void DeleteStorageKeyData(const blink::StorageKey& storage_key, + blink::mojom::StorageType type, + QuotaClientTypes quota_client_types, + StatusCallback callback); + virtual void DeleteBucketData(const BucketInfo& bucket, QuotaClientTypes quota_client_types, StatusCallback callback); void DeleteHostData(const std::string& host, @@ -284,29 +325,30 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl std::map<std::string, std::string> GetStatistics(); - bool IsStorageUnlimited(const url::Origin& origin, + bool IsStorageUnlimited(const blink::StorageKey& storage_key, blink::mojom::StorageType type) const; - virtual void GetOriginsModifiedBetween(blink::mojom::StorageType type, + virtual void GetBucketsModifiedBetween(blink::mojom::StorageType type, base::Time begin, base::Time end, - GetOriginsCallback callback); + GetBucketsCallback callback); bool ResetUsageTracker(blink::mojom::StorageType type); // Called when StoragePartition is initialized if embedder has an // implementation of StorageNotificationService. void SetStoragePressureCallback( - base::RepeatingCallback<void(url::Origin)> storage_pressure_callback); + base::RepeatingCallback<void(blink::StorageKey)> + storage_pressure_callback); // DevTools Quota Override methods: int GetOverrideHandleId(); - void OverrideQuotaForOrigin(int handle_id, - const url::Origin& origin, - absl::optional<int64_t> quota_size); + void OverrideQuotaForStorageKey(int handle_id, + const blink::StorageKey& storage_key, + absl::optional<int64_t> quota_size); // Called when a DevTools client releases all overrides, however, overrides - // will not be disabled for any origins for which there are other DevTools - // clients/QuotaOverrideHandle with an active override. + // will not be disabled for any storage keys for which there are other + // DevTools clients/QuotaOverrideHandle with an active override. void WithdrawOverridesForHandle(int handle_id); // Cap size for per-host persistent quota determined by the histogram. @@ -322,12 +364,11 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl static constexpr int kThresholdRandomizationPercent = 5; static constexpr char kDatabaseName[] = "QuotaManager"; - static constexpr char kDaysBetweenRepeatedOriginEvictionsHistogram[] = - "Quota.DaysBetweenRepeatedOriginEvictions"; - static constexpr char kEvictedOriginAccessedCountHistogram[] = - "Quota.EvictedOriginAccessCount"; - static constexpr char kEvictedOriginDaysSinceAccessHistogram[] = - "Quota.EvictedOriginDaysSinceAccess"; + + static constexpr char kEvictedBucketAccessedCountHistogram[] = + "Quota.EvictedBucketAccessCount"; + static constexpr char kEvictedBucketDaysSinceAccessHistogram[] = + "Quota.EvictedBucketDaysSinceAccess"; // Kept non-const so that test code can change the value. // TODO(kinuko): Make this a real const value and add a proper way to set @@ -358,9 +399,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl class EvictionRoundInfoHelper; class UsageAndQuotaInfoGatherer; class GetUsageInfoTask; - class OriginDataDeleter; + class BucketDataDeleter; + class StorageKeyDataDeleter; class HostDataDeleter; - class GetModifiedSinceHelper; class DumpQuotaTableHelper; class DumpBucketTableHelper; class StorageCleanupHelper; @@ -396,22 +437,22 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl struct EvictionContext { EvictionContext(); ~EvictionContext(); - url::Origin evicted_origin; - blink::mojom::StorageType evicted_type; - StatusCallback evict_origin_data_callback; + BucketInfo evicted_bucket; + StatusCallback evict_bucket_data_callback; }; // Lazily called on the IO thread when the first quota manager API is called. // // Initialize() must be called after all quota clients are added to the // manager by RegisterClient(). - void LazyInitialize(); - void FinishLazyInitialize(bool is_database_bootstraped); - void BootstrapDatabaseForEviction(GetOriginCallback did_get_origin_callback, + void EnsureDatabaseOpened(); + void DidOpenDatabase(bool is_database_bootstraped); + void BootstrapDatabaseForEviction(GetBucketCallback did_get_bucket_callback, int64_t unused_usage, int64_t unused_unlimited_usage); - void DidBootstrapDatabase(GetOriginCallback did_get_origin_callback, - bool success); + void DidBootstrapDatabaseForEviction( + GetBucketCallback did_get_bucket_callback, + bool success); // Called by clients via proxy. // Registers a quota client to the manager. @@ -420,37 +461,39 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl QuotaClientType client_type, const std::vector<blink::mojom::StorageType>& storage_types); - // Legacy overload for QuotaClients that have not been mojofied yet. - // - // TODO(crbug.com/1163009): Remove this overload after all QuotaClients have - // been mojofied. - void RegisterLegacyClient( - scoped_refptr<QuotaClient> client, - QuotaClientType client_type, - const std::vector<blink::mojom::StorageType>& storage_types); - UsageTracker* GetUsageTracker(blink::mojom::StorageType type) const; - // Extract cached origins list from the usage tracker. - // (Might return empty list if no origin is tracked by the tracker.) - std::set<url::Origin> GetCachedOrigins(blink::mojom::StorageType type); + // Extract cached storage keys list from the usage tracker. + // (Might return empty list if no storage key is tracked by the tracker.) + std::set<blink::StorageKey> GetCachedStorageKeys( + blink::mojom::StorageType type); void DumpQuotaTable(DumpQuotaTableCallback callback); void DumpBucketTable(DumpBucketTableCallback callback); - void DeleteOriginDataInternal(const url::Origin& origin, - blink::mojom::StorageType type, + // Runs BucketDataDeleter which calls QuotaClients to clear data for the + // bucket. Once the task is complete, calls the QuotaDatabase to delete the + // bucket from the bucket table. + void DeleteBucketDataInternal(const BucketInfo& bucket, QuotaClientTypes quota_client_types, bool is_eviction, StatusCallback callback); + // Runs StorageKeyDataDeleter which calls QuotaClients to clear all data for + // the storage key. Once the task is complete, calls the QuotaDatabase to + // delete buckets for the storage key & storage type from the bucket table. + void DeleteStorageKeyDataInternal(const blink::StorageKey& storage_key, + blink::mojom::StorageType type, + QuotaClientTypes quota_client_types, + StatusCallback callback); + // Methods for eviction logic. void StartEviction(); - void DeleteOriginFromDatabase(const url::Origin& origin, - blink::mojom::StorageType type, - bool is_eviction); + void DeleteStorageKeyFromDatabase(const blink::StorageKey& storage_key, + blink::mojom::StorageType type); + void DeleteBucketFromDatabase(BucketId bucket_id, bool is_eviction); - void DidOriginDataEvicted(blink::mojom::QuotaStatusCode status); + void DidBucketDataEvicted(blink::mojom::QuotaStatusCode status); void ReportHistogram(); void DidGetTemporaryGlobalUsageForHistogram(int64_t usage, @@ -462,20 +505,21 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl int64_t unlimited_usage); void DidDumpBucketTableForHistogram(const BucketTableEntries& entries); - std::set<url::Origin> GetEvictionOriginExceptions(); - void DidGetEvictionOrigin(GetOriginCallback callback, - const absl::optional<url::Origin>& origin); + // Returns the list of bucket ids that should be excluded from eviction due to + // consistent errors after multiple attempts. + std::set<BucketId> GetEvictionBucketExceptions(); + void DidGetEvictionBucket(GetBucketCallback callback, + const absl::optional<BucketInfo>& bucket); // QuotaEvictionHandler. - void GetEvictionOrigin(blink::mojom::StorageType type, + void GetEvictionBucket(blink::mojom::StorageType type, int64_t global_quota, - GetOriginCallback callback) override; - void EvictOriginData(const url::Origin& origin, - blink::mojom::StorageType type, + GetBucketCallback callback) override; + void EvictBucketData(const BucketInfo& bucket, StatusCallback callback) override; void GetEvictionRoundInfo(EvictionRoundInfoCallback callback) override; - void GetLRUOrigin(blink::mojom::StorageType type, GetOriginCallback callback); + void GetLRUBucket(blink::mojom::StorageType type, GetBucketCallback callback); void DidGetPersistentHostQuota(const std::string& host, const int64_t* quota, @@ -484,8 +528,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl QuotaCallback callback, const int64_t* new_quota, bool success); - void DidGetLRUOrigin(std::unique_ptr<absl::optional<url::Origin>> origin, - bool success); + void DidGetLRUBucket(QuotaErrorOr<BucketInfo> result); void GetQuotaSettings(QuotaSettingsCallback callback); void DidGetSettings(absl::optional<QuotaSettings> settings); void GetStorageCapacity(StorageCapacityCallback callback); @@ -495,17 +538,22 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl void DidDatabaseWork(bool success); - void DidGetBucketId(base::OnceCallback<void(QuotaErrorOr<BucketId>)> callback, - QuotaErrorOr<BucketId> result); + void DidGetBucket(base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback, + QuotaErrorOr<BucketInfo> result); + void DidGetStorageKeys(GetStorageKeysCallback callback, + QuotaErrorOr<std::set<blink::StorageKey>> result); + void DidGetModifiedBetween(GetBucketsCallback callback, + blink::mojom::StorageType type, + QuotaErrorOr<std::set<BucketInfo>> result); void DeleteOnCorrectThread() const; - void MaybeRunStoragePressureCallback(const url::Origin& origin, + void MaybeRunStoragePressureCallback(const blink::StorageKey& storage_key, int64_t total_space, int64_t available_space); // Used from quota-internals page to test behavior of the storage pressure // callback. - void SimulateStoragePressure(const url::Origin origin); + void SimulateStoragePressure(const blink::StorageKey& storage_key); // Evaluates disk statistics to identify storage pressure // (low disk space availability) and starts the storage @@ -515,7 +563,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl // TODO(crbug.com/1102433): Define and explain StoragePressure in the README. void DetermineStoragePressure(int64_t free_space, int64_t total_space); - absl::optional<int64_t> GetQuotaOverrideForOrigin(const url::Origin&); + absl::optional<int64_t> GetQuotaOverrideForStorageKey( + const blink::StorageKey&); // TODO(ayui): Replace instances to use result with QuotaErrorOr. void PostTaskAndReplyWithResultForDBThread( @@ -543,15 +592,16 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl bool db_disabled_; bool eviction_disabled_; - absl::optional<url::Origin> origin_for_pending_storage_pressure_callback_; + absl::optional<blink::StorageKey> + storage_key_for_pending_storage_pressure_callback_; scoped_refptr<base::SingleThreadTaskRunner> io_thread_; scoped_refptr<base::SequencedTaskRunner> db_runner_; mutable std::unique_ptr<QuotaDatabase> database_; - bool is_database_bootstrapped_ = false; + bool is_database_bootstrapped_for_eviction_ = false; GetQuotaSettingsFunc get_settings_function_; scoped_refptr<base::TaskRunner> get_settings_task_runner_; - base::RepeatingCallback<void(url::Origin)> storage_pressure_callback_; + base::RepeatingCallback<void(blink::StorageKey)> storage_pressure_callback_; base::RepeatingClosure quota_change_callback_; QuotaSettings settings_; base::TimeTicks settings_timestamp_; @@ -562,10 +612,16 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl CallbackQueue<StorageCapacityCallback, int64_t, int64_t> storage_capacity_callbacks_; - GetOriginCallback lru_origin_callback_; - std::set<url::Origin> access_notified_origins_; + GetBucketCallback lru_bucket_callback_; + + // Keeps track of storage keys that have been accessed during an eviction task + // so they can be filtered out from eviction. + std::set<blink::StorageKey> access_notified_storage_keys_; + // Buckets that have been notified of access during LRU task to exclude from + // eviction. + std::set<BucketId> access_notified_buckets_; - std::map<url::Origin, QuotaOverride> devtools_overrides_; + std::map<blink::StorageKey, QuotaOverride> devtools_overrides_; int next_override_handle_id_ = 0; // Owns the QuotaClient remotes registered via RegisterClient(). @@ -577,22 +633,12 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl // using a mojo::RemoteSet here. std::vector<mojo::Remote<mojom::QuotaClient>> clients_for_ownership_; - // Owns the QuotaClient instances registered by RegisterLegacyClient() and - // their wrappers. - // - // TODO(crbug.com/1163009): Remove this member after all QuotaClients have - // been mojofied. - std::vector<scoped_refptr<QuotaClient>> legacy_clients_for_ownership_; - // Maps QuotaClient instances to client types. // // The QuotaClient instances pointed to by the map keys are guaranteed to be // alive, because they are owned by `legacy_clients_for_ownership_`. - // - // TODO(crbug.com/1163009): Replace the map key with mojom::QuotaClient* after - // all QuotaClients have been mojofied. base::flat_map<blink::mojom::StorageType, - base::flat_map<QuotaClient*, QuotaClientType>> + base::flat_map<mojom::QuotaClient*, QuotaClientType>> client_types_; std::unique_ptr<UsageTracker> temporary_usage_tracker_; @@ -603,7 +649,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl std::unique_ptr<QuotaTemporaryStorageEvictor> temporary_storage_evictor_; EvictionContext eviction_context_; - bool is_getting_eviction_origin_; + // Set when there is an eviction task in-flight. + bool is_getting_eviction_bucket_ = false; CallbackQueueMap<QuotaCallback, std::string, @@ -611,10 +658,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerImpl int64_t> persistent_host_quota_callbacks_; - // Map from origin to count. - std::map<url::Origin, int> origins_in_use_; - // Map from origin to error count. - std::map<url::Origin, int> origins_in_error_; + // Map from bucket id to eviction error count. + std::map<BucketId, int> buckets_in_error_; scoped_refptr<SpecialStoragePolicy> special_storage_policy_; diff --git a/chromium/storage/browser/quota/quota_manager_proxy.cc b/chromium/storage/browser/quota/quota_manager_proxy.cc index 44cdffebcae..9e7d0886a35 100644 --- a/chromium/storage/browser/quota/quota_manager_proxy.cc +++ b/chromium/storage/browser/quota/quota_manager_proxy.cc @@ -7,6 +7,7 @@ #include <stdint.h> #include <memory> +#include <string> #include <utility> #include <vector> @@ -19,21 +20,21 @@ #include "base/time/time.h" #include "components/services/storage/public/mojom/quota_client.mojom.h" #include "mojo/public/cpp/bindings/pending_remote.h" -#include "storage/browser/quota/quota_client.h" #include "storage/browser/quota/quota_client_type.h" #include "storage/browser/quota/quota_manager_impl.h" #include "storage/browser/quota/quota_override_handle.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" -#include "url/origin.h" + +using ::blink::StorageKey; namespace storage { namespace { -void DidGetBucketId( - scoped_refptr<base::SequencedTaskRunner> callback_task_runner, - base::OnceCallback<void(QuotaErrorOr<BucketId>)> callback, - QuotaErrorOr<BucketId> result) { +void DidGetBucket(scoped_refptr<base::SequencedTaskRunner> callback_task_runner, + base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback, + QuotaErrorOr<BucketInfo> result) { if (callback_task_runner->RunsTasksInCurrentSequence()) { std::move(callback).Run(std::move(result)); return; @@ -55,118 +56,140 @@ QuotaManagerProxy::QuotaManagerProxy( DETACH_FROM_SEQUENCE(quota_manager_impl_sequence_checker_); } -void QuotaManagerProxy::RegisterLegacyClient( - scoped_refptr<QuotaClient> client, +void QuotaManagerProxy::RegisterClient( + mojo::PendingRemote<mojom::QuotaClient> client, QuotaClientType client_type, const std::vector<blink::mojom::StorageType>& storage_types) { if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) { quota_manager_impl_task_runner_->PostTask( FROM_HERE, - base::BindOnce(&QuotaManagerProxy::RegisterLegacyClient, this, + base::BindOnce(&QuotaManagerProxy::RegisterClient, this, std::move(client), client_type, storage_types)); return; } DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_); - if (!quota_manager_impl_) { - client->OnQuotaManagerDestroyed(); - return; + if (quota_manager_impl_) { + quota_manager_impl_->RegisterClient(std::move(client), client_type, + storage_types); } - - quota_manager_impl_->RegisterLegacyClient(std::move(client), client_type, - storage_types); } -void QuotaManagerProxy::RegisterClient( - mojo::PendingRemote<mojom::QuotaClient> client, - QuotaClientType client_type, - const std::vector<blink::mojom::StorageType>& storage_types) { +void QuotaManagerProxy::GetOrCreateBucket( + const StorageKey& storage_key, + const std::string& bucket_name, + scoped_refptr<base::SequencedTaskRunner> callback_task_runner, + base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback) { if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) { quota_manager_impl_task_runner_->PostTask( FROM_HERE, - base::BindOnce(&QuotaManagerProxy::RegisterClient, this, - std::move(client), client_type, storage_types)); + base::BindOnce(&QuotaManagerProxy::GetOrCreateBucket, this, storage_key, + bucket_name, std::move(callback_task_runner), + std::move(callback))); return; } DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_); - if (quota_manager_impl_) { - quota_manager_impl_->RegisterClient(std::move(client), client_type, - storage_types); + if (!quota_manager_impl_) { + DidGetBucket(std::move(callback_task_runner), std::move(callback), + QuotaErrorOr<BucketInfo>(QuotaError::kUnknownError)); + return; } + + quota_manager_impl_->GetOrCreateBucket( + storage_key, bucket_name, + base::BindOnce(&DidGetBucket, std::move(callback_task_runner), + std::move(callback))); } -void QuotaManagerProxy::CreateBucket( - const url::Origin& origin, +void QuotaManagerProxy::CreateBucketForTesting( + const StorageKey& storage_key, const std::string& bucket_name, + blink::mojom::StorageType storage_type, scoped_refptr<base::SequencedTaskRunner> callback_task_runner, - base::OnceCallback<void(QuotaErrorOr<BucketId>)> callback) { + base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback) { if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) { quota_manager_impl_task_runner_->PostTask( FROM_HERE, - base::BindOnce(&QuotaManagerProxy::CreateBucket, this, origin, - bucket_name, std::move(callback_task_runner), - std::move(callback))); + base::BindOnce(&QuotaManagerProxy::CreateBucketForTesting, this, + storage_key, bucket_name, storage_type, + std::move(callback_task_runner), std::move(callback))); return; } DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_); if (!quota_manager_impl_) { - DidGetBucketId(std::move(callback_task_runner), std::move(callback), - QuotaErrorOr<BucketId>(QuotaError::kUnknownError)); + DidGetBucket(std::move(callback_task_runner), std::move(callback), + QuotaErrorOr<BucketInfo>(QuotaError::kUnknownError)); return; } - quota_manager_impl_->CreateBucket( - origin, bucket_name, - base::BindOnce(&DidGetBucketId, std::move(callback_task_runner), + quota_manager_impl_->CreateBucketForTesting( // IN-TEST + storage_key, bucket_name, storage_type, + base::BindOnce(&DidGetBucket, std::move(callback_task_runner), std::move(callback))); } -void QuotaManagerProxy::GetBucketId( - const url::Origin& origin, +void QuotaManagerProxy::GetBucket( + const StorageKey& storage_key, const std::string& bucket_name, + blink::mojom::StorageType type, scoped_refptr<base::SequencedTaskRunner> callback_task_runner, - base::OnceCallback<void(QuotaErrorOr<BucketId>)> callback) { + base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback) { if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) { quota_manager_impl_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&QuotaManagerProxy::GetBucketId, this, origin, - bucket_name, std::move(callback_task_runner), - std::move(callback))); + FROM_HERE, + base::BindOnce(&QuotaManagerProxy::GetBucket, this, storage_key, + bucket_name, type, std::move(callback_task_runner), + std::move(callback))); return; } DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_); if (!quota_manager_impl_) { - DidGetBucketId(std::move(callback_task_runner), std::move(callback), - QuotaErrorOr<BucketId>(QuotaError::kUnknownError)); + DidGetBucket(std::move(callback_task_runner), std::move(callback), + QuotaErrorOr<BucketInfo>(QuotaError::kUnknownError)); return; } - quota_manager_impl_->GetBucketId( - origin, bucket_name, - base::BindOnce(&DidGetBucketId, std::move(callback_task_runner), + quota_manager_impl_->GetBucket( + storage_key, bucket_name, type, + base::BindOnce(&DidGetBucket, std::move(callback_task_runner), std::move(callback))); } -void QuotaManagerProxy::NotifyStorageAccessed(const url::Origin& origin, +void QuotaManagerProxy::NotifyStorageAccessed(const StorageKey& storage_key, blink::mojom::StorageType type, base::Time access_time) { if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) { quota_manager_impl_task_runner_->PostTask( FROM_HERE, base::BindOnce(&QuotaManagerProxy::NotifyStorageAccessed, - this, origin, type, access_time)); + this, storage_key, type, access_time)); + return; + } + + DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_); + if (quota_manager_impl_) + quota_manager_impl_->NotifyStorageAccessed(storage_key, type, access_time); +} + +void QuotaManagerProxy::NotifyBucketAccessed(const BucketId bucket_id, + base::Time access_time) { + if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) { + quota_manager_impl_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&QuotaManagerProxy::NotifyBucketAccessed, + this, bucket_id, access_time)); return; } DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_); if (quota_manager_impl_) - quota_manager_impl_->NotifyStorageAccessed(origin, type, access_time); + quota_manager_impl_->NotifyBucketAccessed(bucket_id, access_time); } void QuotaManagerProxy::NotifyStorageModified( QuotaClientType client_id, - const url::Origin& origin, + const StorageKey& storage_key, blink::mojom::StorageType type, int64_t delta, base::Time modification_time, @@ -177,7 +200,7 @@ void QuotaManagerProxy::NotifyStorageModified( quota_manager_impl_task_runner_->PostTask( FROM_HERE, base::BindOnce(&QuotaManagerProxy::NotifyStorageModified, this, - client_id, origin, type, delta, modification_time, + client_id, storage_key, type, delta, modification_time, std::move(callback_task_runner), std::move(callback))); return; } @@ -197,65 +220,78 @@ void QuotaManagerProxy::NotifyStorageModified( }, std::move(callback_task_runner), std::move(callback)); } - quota_manager_impl_->NotifyStorageModified(client_id, origin, type, delta, - modification_time, + quota_manager_impl_->NotifyStorageModified(client_id, storage_key, type, + delta, modification_time, std::move(manager_callback)); } } -void QuotaManagerProxy::NotifyOriginInUse(const url::Origin& origin) { +void QuotaManagerProxy::NotifyBucketModified( + QuotaClientType client_id, + const BucketId bucket_id, + int64_t delta, + base::Time modification_time, + scoped_refptr<base::SequencedTaskRunner> callback_task_runner, + base::OnceClosure callback) { + DCHECK(!callback || callback_task_runner); if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) { quota_manager_impl_task_runner_->PostTask( FROM_HERE, - base::BindOnce(&QuotaManagerProxy::NotifyOriginInUse, this, origin)); + base::BindOnce(&QuotaManagerProxy::NotifyBucketModified, this, + client_id, bucket_id, delta, modification_time, + std::move(callback_task_runner), std::move(callback))); return; } DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_); - if (quota_manager_impl_) - quota_manager_impl_->NotifyOriginInUse(origin); -} - -void QuotaManagerProxy::NotifyOriginNoLongerInUse(const url::Origin& origin) { - if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) { - quota_manager_impl_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&QuotaManagerProxy::NotifyOriginNoLongerInUse, - this, origin)); - return; + if (quota_manager_impl_) { + base::OnceClosure manager_callback; + if (callback) { + manager_callback = base::BindOnce( + [](scoped_refptr<base::SequencedTaskRunner> callback_task_runner, + base::OnceClosure callback) { + if (callback_task_runner->RunsTasksInCurrentSequence()) { + std::move(callback).Run(); + return; + } + callback_task_runner->PostTask(FROM_HERE, std::move(callback)); + }, + std::move(callback_task_runner), std::move(callback)); + } + quota_manager_impl_->NotifyBucketModified(client_id, bucket_id, delta, + modification_time, + std::move(manager_callback)); } - - DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_); - if (quota_manager_impl_) - quota_manager_impl_->NotifyOriginNoLongerInUse(origin); } -void QuotaManagerProxy::NotifyWriteFailed(const url::Origin& origin) { +void QuotaManagerProxy::NotifyWriteFailed(const StorageKey& storage_key) { if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) { quota_manager_impl_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&QuotaManagerProxy::NotifyWriteFailed, this, origin)); + FROM_HERE, base::BindOnce(&QuotaManagerProxy::NotifyWriteFailed, this, + storage_key)); return; } DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_); if (quota_manager_impl_) - quota_manager_impl_->NotifyWriteFailed(origin); + quota_manager_impl_->NotifyWriteFailed(storage_key); } void QuotaManagerProxy::SetUsageCacheEnabled(QuotaClientType client_id, - const url::Origin& origin, + const StorageKey& storage_key, blink::mojom::StorageType type, bool enabled) { if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) { quota_manager_impl_task_runner_->PostTask( FROM_HERE, base::BindOnce(&QuotaManagerProxy::SetUsageCacheEnabled, - this, client_id, origin, type, enabled)); + this, client_id, storage_key, type, enabled)); return; } DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_); if (quota_manager_impl_) - quota_manager_impl_->SetUsageCacheEnabled(client_id, origin, type, enabled); + quota_manager_impl_->SetUsageCacheEnabled(client_id, storage_key, type, + enabled); } namespace { @@ -277,15 +313,16 @@ void DidGetUsageAndQuota( } // namespace void QuotaManagerProxy::GetUsageAndQuota( - const url::Origin& origin, + const StorageKey& storage_key, blink::mojom::StorageType type, scoped_refptr<base::SequencedTaskRunner> callback_task_runner, UsageAndQuotaCallback callback) { if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) { quota_manager_impl_task_runner_->PostTask( FROM_HERE, - base::BindOnce(&QuotaManagerProxy::GetUsageAndQuota, this, origin, type, - std::move(callback_task_runner), std::move(callback))); + base::BindOnce(&QuotaManagerProxy::GetUsageAndQuota, this, storage_key, + type, std::move(callback_task_runner), + std::move(callback))); return; } @@ -297,28 +334,29 @@ void QuotaManagerProxy::GetUsageAndQuota( } quota_manager_impl_->GetUsageAndQuota( - origin, type, + storage_key, type, base::BindOnce(&DidGetUsageAndQuota, std::move(callback_task_runner), std::move(callback))); } void QuotaManagerProxy::IsStorageUnlimited( - const url::Origin& origin, + const StorageKey& storage_key, blink::mojom::StorageType type, scoped_refptr<base::SequencedTaskRunner> callback_task_runner, base::OnceCallback<void(bool)> callback) { if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) { quota_manager_impl_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&QuotaManagerProxy::IsStorageUnlimited, this, - origin, type, std::move(callback_task_runner), - std::move(callback))); + FROM_HERE, + base::BindOnce(&QuotaManagerProxy::IsStorageUnlimited, this, + storage_key, type, std::move(callback_task_runner), + std::move(callback))); return; } DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_); bool is_storage_unlimited = quota_manager_impl_ - ? quota_manager_impl_->IsStorageUnlimited(origin, type) + ? quota_manager_impl_->IsStorageUnlimited(storage_key, type) : false; if (callback_task_runner->RunsTasksInCurrentSequence()) { @@ -334,24 +372,25 @@ QuotaManagerProxy::GetQuotaOverrideHandle() { return std::make_unique<QuotaOverrideHandle>(this); } -void QuotaManagerProxy::OverrideQuotaForOrigin( +void QuotaManagerProxy::OverrideQuotaForStorageKey( int handle_id, - url::Origin origin, + const StorageKey& storage_key, absl::optional<int64_t> quota_size, scoped_refptr<base::SequencedTaskRunner> callback_task_runner, base::OnceClosure callback) { if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) { quota_manager_impl_task_runner_->PostTask( FROM_HERE, - base::BindOnce(&QuotaManagerProxy::OverrideQuotaForOrigin, this, - handle_id, origin, quota_size, + base::BindOnce(&QuotaManagerProxy::OverrideQuotaForStorageKey, this, + handle_id, storage_key, quota_size, std::move(callback_task_runner), std::move(callback))); return; } DCHECK_CALLED_ON_VALID_SEQUENCE(quota_manager_impl_sequence_checker_); if (quota_manager_impl_) - quota_manager_impl_->OverrideQuotaForOrigin(handle_id, origin, quota_size); + quota_manager_impl_->OverrideQuotaForStorageKey(handle_id, storage_key, + quota_size); if (callback_task_runner->RunsTasksInCurrentSequence()) { std::move(callback).Run(); diff --git a/chromium/storage/browser/quota/quota_manager_proxy.h b/chromium/storage/browser/quota/quota_manager_proxy.h index f5452f146cb..038a414439c 100644 --- a/chromium/storage/browser/quota/quota_manager_proxy.h +++ b/chromium/storage/browser/quota/quota_manager_proxy.h @@ -24,23 +24,19 @@ #include "storage/browser/quota/quota_callbacks.h" #include "storage/browser/quota/quota_client_type.h" #include "storage/browser/quota/quota_manager_impl.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" -namespace base { +namespace blink { +class StorageKey; +} // namespace blink +namespace base { class SequencedTaskRunner; - } // namespace base -namespace url { - -class Origin; - -} // namespace url - namespace storage { -class QuotaClient; class QuotaOverrideHandle; // Thread-safe proxy for QuotaManagerImpl. @@ -65,70 +61,97 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerProxy QuotaManagerProxy(const QuotaManagerProxy&) = delete; QuotaManagerProxy& operator=(const QuotaManagerProxy&) = delete; - // TODO(crbug.com/1163009): Remove this method after all QuotaClients have - // been mojofied. - virtual void RegisterLegacyClient( - scoped_refptr<QuotaClient> client, - QuotaClientType client_type, - const std::vector<blink::mojom::StorageType>& storage_types); - virtual void RegisterClient( mojo::PendingRemote<mojom::QuotaClient> client, QuotaClientType client_type, const std::vector<blink::mojom::StorageType>& storage_types); - // Creates a bucket for `origin` with `bucket_name` and returns the BucketId - // to the callback. Will return an QuotaError to the callback on failure. - virtual void CreateBucket( - const url::Origin& origin, + // Gets the bucket with `bucket_name` for the `storage_key` for StorageType + // kTemporary and returns the BucketInfo. If one doesn't exist, it creates + // a new bucket with the specified policies. Returns a QuotaError if the + // operation has failed. + virtual void GetOrCreateBucket( + const blink::StorageKey& storage_key, + const std::string& bucket_name, + scoped_refptr<base::SequencedTaskRunner> callback_task_runner, + base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback); + + // Creates a bucket for `origin` with `bucket_name` and returns the + // BucketInfo to the callback. Returns a QuotaError to the callback + // on operation failure. + // + // TODO(crbug.com/1208141): Remove `storage_type` when the only supported + // StorageType is kTemporary. + virtual void CreateBucketForTesting( + const blink::StorageKey& storage_key, const std::string& bucket_name, + blink::mojom::StorageType storage_type, scoped_refptr<base::SequencedTaskRunner> callback_task_runner, - base::OnceCallback<void(QuotaErrorOr<BucketId>)> callback); + base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback); - // Retrieves the BucketId of the bucket with `bucket_name` for `origin` and - // returns it to the callback. Will return an empty BucketId if a bucket does - // not exist. Will return a QuotaError on operation failure. - virtual void GetBucketId( - const url::Origin& origin, + // Retrieves the BucketInfo of the bucket with `bucket_name` for + // `storage_key` and returns it to the callback. Will return a QuotaError if a + // bucket does not exist or on operation failure. + virtual void GetBucket( + const blink::StorageKey& storage_key, const std::string& bucket_name, + blink::mojom::StorageType type, scoped_refptr<base::SequencedTaskRunner> callback_task_runner, - base::OnceCallback<void(QuotaErrorOr<BucketId>)> callback); + base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback); - virtual void NotifyStorageAccessed(const url::Origin& origin, + virtual void NotifyStorageAccessed(const blink::StorageKey& storage_key, blink::mojom::StorageType type, base::Time access_time); + // Notifies the quota manager that a bucket has been accessed to maintain LRU + // ordering. + virtual void NotifyBucketAccessed(BucketId bucket_id, base::Time access_time); + // Notify the quota manager that storage has been modified for the given - // client. A |callback| may be optionally provided to be invoked on the + // client. A `callback` may be optionally provided to be invoked on the // given task runner when the quota system's state in memory has been - // updated. If a |callback| is provided then |callback_task_runner| must - // also be provided. If the quota manager runs on |callback_task_runner|, - // then the |callback| may be invoked synchronously. + // updated. If a `callback` is provided then `callback_task_runner` must + // also be provided. If the quota manager runs on `callback_task_runner`, + // then the `callback` may be invoked synchronously. + // TODO(crbug.com/1208141): Remove when all usages have updated to use + // NotifyBucketModified. virtual void NotifyStorageModified( QuotaClientType client_id, - const url::Origin& origin, + const blink::StorageKey& storage_key, blink::mojom::StorageType type, int64_t delta, base::Time modification_time, scoped_refptr<base::SequencedTaskRunner> callback_task_runner = nullptr, base::OnceClosure callback = base::OnceClosure()); - virtual void NotifyOriginInUse(const url::Origin& origin); - virtual void NotifyOriginNoLongerInUse(const url::Origin& origin); - virtual void NotifyWriteFailed(const url::Origin& origin); + // Notifies the quota manager that a bucket has been modified for the given + // client. A `callback` may be optionally provided to be invoked on the + // given task runner when the quota system's state in memory has been + // updated. If a `callback` is provided then `callback_task_runner` must + // also be provided. If the quota manager runs on `callback_task_runner`, + // then the `callback` may be invoked synchronously. + virtual void NotifyBucketModified( + QuotaClientType client_id, + BucketId bucket_id, + int64_t delta, + base::Time modification_time, + scoped_refptr<base::SequencedTaskRunner> callback_task_runner = nullptr, + base::OnceClosure callback = base::OnceClosure()); + + virtual void NotifyWriteFailed(const blink::StorageKey& storage_key); virtual void SetUsageCacheEnabled(QuotaClientType client_id, - const url::Origin& origin, + const blink::StorageKey& storage_key, blink::mojom::StorageType type, bool enabled); virtual void GetUsageAndQuota( - const url::Origin& origin, + const blink::StorageKey& storage_key, blink::mojom::StorageType type, scoped_refptr<base::SequencedTaskRunner> callback_task_runner, UsageAndQuotaCallback callback); virtual void IsStorageUnlimited( - const url::Origin& origin, + const blink::StorageKey& storage_key, blink::mojom::StorageType type, scoped_refptr<base::SequencedTaskRunner> callback_task_runner, base::OnceCallback<void(bool)> callback); @@ -140,9 +163,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManagerProxy void GetOverrideHandleId( scoped_refptr<base::SequencedTaskRunner> callback_task_runner, base::OnceCallback<void(int)> callback); - void OverrideQuotaForOrigin( + void OverrideQuotaForStorageKey( int handle_id, - url::Origin origin, + const blink::StorageKey& storage_key, absl::optional<int64_t> quota_size, scoped_refptr<base::SequencedTaskRunner> callback_task_runner, base::OnceClosure callback); diff --git a/chromium/storage/browser/quota/quota_manager_unittest.cc b/chromium/storage/browser/quota/quota_manager_unittest.cc index b36e087c850..3772cfe8a15 100644 --- a/chromium/storage/browser/quota/quota_manager_unittest.cc +++ b/chromium/storage/browser/quota/quota_manager_unittest.cc @@ -33,7 +33,6 @@ #include "components/services/storage/public/mojom/quota_client.mojom.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" -#include "storage/browser/quota/mojo_quota_client_wrapper.h" #include "storage/browser/quota/quota_client_type.h" #include "storage/browser/quota/quota_database.h" #include "storage/browser/quota/quota_features.h" @@ -42,13 +41,15 @@ #include "storage/browser/quota/quota_override_handle.h" #include "storage/browser/test/mock_quota_client.h" #include "storage/browser/test/mock_special_storage_policy.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h" #include "url/gurl.h" -#include "url/origin.h" -using blink::mojom::QuotaStatusCode; -using blink::mojom::StorageType; +using ::blink::StorageKey; +using ::blink::mojom::QuotaStatusCode; +using ::blink::mojom::StorageType; namespace storage { @@ -78,9 +79,15 @@ std::tuple<int64_t, int64_t> GetVolumeInfoForTests( return std::make_tuple(total, available); } -// TODO(crbug.com/889590): Replace with common converter. -url::Origin ToOrigin(const std::string& url) { - return url::Origin::Create(GURL(url)); +StorageKey ToStorageKey(const std::string& url) { + return StorageKey::CreateFromStringForTesting(url); +} + +MATCHER_P3(MatchesBucketTableEntry, storage_key, type, use_count, "") { + return testing::ExplainMatchResult(storage_key, arg.storage_key, + result_listener) && + testing::ExplainMatchResult(type, arg.type, result_listener) && + testing::ExplainMatchResult(use_count, arg.use_count, result_listener); } } // namespace @@ -125,7 +132,7 @@ class QuotaManagerImplTest : public testing::Test { } MockQuotaClient* CreateAndRegisterClient( - base::span<const MockOriginData> mock_data, + base::span<const MockStorageKeyData> mock_data, QuotaClientType client_type, const std::vector<blink::mojom::StorageType> storage_types) { auto mock_quota_client = std::make_unique<storage::MockQuotaClient>( @@ -140,37 +147,47 @@ class QuotaManagerImplTest : public testing::Test { return mock_quota_client_ptr; } - // TODO(crbug.com/1163009): Remove this method and replace all calls with - // CreateAndRegisterClient() after all QuotaClients - // have been mojofied. - MockQuotaClient* CreateAndRegisterLegacyClient( - base::span<const MockOriginData> mock_data, - QuotaClientType client_type, - const std::vector<blink::mojom::StorageType> storage_types) { - auto mock_quota_client = std::make_unique<storage::MockQuotaClient>( - quota_manager_impl_->proxy(), mock_data, client_type); - MockQuotaClient* mock_quota_client_ptr = mock_quota_client.get(); - legacy_clients_.push_back(std::move(mock_quota_client)); + void OpenDatabase() { quota_manager_impl_->EnsureDatabaseOpened(); } - scoped_refptr<QuotaClient> legacy_client = - base::MakeRefCounted<MojoQuotaClientWrapper>(mock_quota_client_ptr); - quota_manager_impl_->proxy()->RegisterLegacyClient( - std::move(legacy_client), client_type, storage_types); - return mock_quota_client_ptr; + void GetOrCreateBucket(const StorageKey& storage_key, + const std::string& bucket_name) { + base::RunLoop run_loop; + quota_manager_impl_->GetOrCreateBucket( + storage_key, bucket_name, + base::BindOnce(&QuotaManagerImplTest::DidGetBucket, + weak_factory_.GetWeakPtr(), run_loop.QuitClosure())); + run_loop.Run(); } - void CreateBucket(const url::Origin& origin, const std::string& bucket_name) { - quota_manager_impl_->CreateBucket( - origin, bucket_name, - base::BindOnce(&QuotaManagerImplTest::DidGetBucketId, - weak_factory_.GetWeakPtr())); + void CreateBucketForTesting(const StorageKey& storage_key, + const std::string& bucket_name, + blink::mojom::StorageType storage_type) { + base::RunLoop run_loop; + quota_manager_impl_->CreateBucketForTesting( + storage_key, bucket_name, storage_type, + base::BindOnce(&QuotaManagerImplTest::DidGetBucket, + weak_factory_.GetWeakPtr(), run_loop.QuitClosure())); + run_loop.Run(); } - void GetBucketId(const url::Origin& origin, const std::string& bucket_name) { - quota_manager_impl_->GetBucketId( - origin, bucket_name, - base::BindOnce(&QuotaManagerImplTest::DidGetBucketId, - weak_factory_.GetWeakPtr())); + void GetBucket(const StorageKey& storage_key, + const std::string& bucket_name, + blink::mojom::StorageType storage_type) { + base::RunLoop run_loop; + quota_manager_impl_->GetBucket( + storage_key, bucket_name, storage_type, + base::BindOnce(&QuotaManagerImplTest::DidGetBucket, + weak_factory_.GetWeakPtr(), run_loop.QuitClosure())); + run_loop.Run(); + } + + void GetStorageKeysForType(blink::mojom::StorageType storage_type) { + base::RunLoop run_loop; + quota_manager_impl_->GetStorageKeysForType( + storage_type, + base::BindOnce(&QuotaManagerImplTest::DidGetStorageKeys, + weak_factory_.GetWeakPtr(), run_loop.QuitClosure())); + run_loop.Run(); } void GetUsageInfo() { @@ -179,35 +196,36 @@ class QuotaManagerImplTest : public testing::Test { &QuotaManagerImplTest::DidGetUsageInfo, weak_factory_.GetWeakPtr())); } - void GetUsageAndQuotaForWebApps(const url::Origin& origin, StorageType type) { + void GetUsageAndQuotaForWebApps(const StorageKey& storage_key, + StorageType type) { quota_status_ = QuotaStatusCode::kUnknown; usage_ = -1; quota_ = -1; quota_manager_impl_->GetUsageAndQuotaForWebApps( - origin, type, + storage_key, type, base::BindOnce(&QuotaManagerImplTest::DidGetUsageAndQuota, weak_factory_.GetWeakPtr())); } - void GetUsageAndQuotaWithBreakdown(const url::Origin& origin, + void GetUsageAndQuotaWithBreakdown(const StorageKey& storage_key, StorageType type) { quota_status_ = QuotaStatusCode::kUnknown; usage_ = -1; quota_ = -1; usage_breakdown_ = nullptr; quota_manager_impl_->GetUsageAndQuotaWithBreakdown( - origin, type, + storage_key, type, base::BindOnce(&QuotaManagerImplTest::DidGetUsageAndQuotaWithBreakdown, weak_factory_.GetWeakPtr())); } - void GetUsageAndQuotaForStorageClient(const url::Origin& origin, + void GetUsageAndQuotaForStorageClient(const StorageKey& storage_key, StorageType type) { quota_status_ = QuotaStatusCode::kUnknown; usage_ = -1; quota_ = -1; quota_manager_impl_->GetUsageAndQuota( - origin, type, + storage_key, type, base::BindOnce(&QuotaManagerImplTest::DidGetUsageAndQuota, weak_factory_.GetWeakPtr())); } @@ -265,39 +283,47 @@ class QuotaManagerImplTest : public testing::Test { weak_factory_.GetWeakPtr())); } - void RunAdditionalUsageAndQuotaTask(const url::Origin& origin, + void RunAdditionalUsageAndQuotaTask(const StorageKey& storage_key, StorageType type) { quota_manager_impl_->GetUsageAndQuota( - origin, type, + storage_key, type, base::BindOnce(&QuotaManagerImplTest::DidGetUsageAndQuotaAdditional, weak_factory_.GetWeakPtr())); } - void DeleteClientOriginData(mojom::QuotaClient* client, - const url::Origin& origin, - StorageType type) { + void DeleteClientStorageKeyData(mojom::QuotaClient* client, + const StorageKey& storage_key, + StorageType type) { DCHECK(client); quota_status_ = QuotaStatusCode::kUnknown; - client->DeleteOriginData( - origin, type, + client->DeleteStorageKeyData( + storage_key, type, base::BindOnce(&QuotaManagerImplTest::StatusCallback, weak_factory_.GetWeakPtr())); } - void EvictOriginData(const url::Origin& origin, StorageType type) { + void EvictBucketData(const BucketInfo& bucket) { + quota_status_ = QuotaStatusCode::kUnknown; + quota_manager_impl_->EvictBucketData( + bucket, base::BindOnce(&QuotaManagerImplTest::StatusCallback, + weak_factory_.GetWeakPtr())); + } + + void DeleteStorageKeyData(const StorageKey& storage_key, + StorageType type, + QuotaClientTypes quota_client_types) { quota_status_ = QuotaStatusCode::kUnknown; - quota_manager_impl_->EvictOriginData( - origin, type, + quota_manager_impl_->DeleteStorageKeyData( + storage_key, type, std::move(quota_client_types), base::BindOnce(&QuotaManagerImplTest::StatusCallback, weak_factory_.GetWeakPtr())); } - void DeleteOriginData(const url::Origin& origin, - StorageType type, + void DeleteBucketData(const BucketInfo& bucket, QuotaClientTypes quota_client_types) { quota_status_ = QuotaStatusCode::kUnknown; - quota_manager_impl_->DeleteOriginData( - origin, type, std::move(quota_client_types), + quota_manager_impl_->DeleteBucketData( + bucket, std::move(quota_client_types), base::BindOnce(&QuotaManagerImplTest::StatusCallback, weak_factory_.GetWeakPtr())); } @@ -331,46 +357,44 @@ class QuotaManagerImplTest : public testing::Test { weak_factory_.GetWeakPtr())); } - std::set<url::Origin> GetCachedOrigins(StorageType type) { - return quota_manager_impl_->GetCachedOrigins(type); + std::set<StorageKey> GetCachedStorageKeys(StorageType type) { + return quota_manager_impl_->GetCachedStorageKeys(type); } - void NotifyStorageAccessed(const url::Origin& origin, StorageType type) { - quota_manager_impl_->NotifyStorageAccessed(origin, type, + void NotifyStorageAccessed(const StorageKey& storage_key, StorageType type) { + quota_manager_impl_->NotifyStorageAccessed(storage_key, type, IncrementMockTime()); } - void DeleteOriginFromDatabase(const url::Origin& origin, StorageType type) { - quota_manager_impl_->DeleteOriginFromDatabase(origin, type, false); + void NotifyBucketAccessed(const BucketId bucket_id) { + quota_manager_impl_->NotifyBucketAccessed(bucket_id, IncrementMockTime()); + } + + void DeleteBucketFromDatabase(BucketId bucket_id) { + quota_manager_impl_->DeleteBucketFromDatabase(bucket_id, false); } - void GetEvictionOrigin(StorageType type) { - eviction_origin_.reset(); + void GetEvictionBucket(StorageType type) { + eviction_bucket_.reset(); // The quota manager's default eviction policy is to use an LRU eviction // policy. - quota_manager_impl_->GetEvictionOrigin( + quota_manager_impl_->GetEvictionBucket( type, 0, - base::BindOnce(&QuotaManagerImplTest::DidGetEvictionOrigin, + base::BindOnce(&QuotaManagerImplTest::DidGetEvictionBucket, weak_factory_.GetWeakPtr())); } - void NotifyOriginInUse(const url::Origin& origin) { - quota_manager_impl_->NotifyOriginInUse(origin); - } - - void NotifyOriginNoLongerInUse(const url::Origin& origin) { - quota_manager_impl_->NotifyOriginNoLongerInUse(origin); - } - - void GetOriginsModifiedBetween(StorageType type, + void GetBucketsModifiedBetween(StorageType type, base::Time begin, base::Time end) { - modified_origins_.clear(); - modified_origins_type_ = StorageType::kUnknown; - quota_manager_impl_->GetOriginsModifiedBetween( + modified_buckets_.clear(); + modified_buckets_type_ = StorageType::kUnknown; + base::RunLoop run_loop; + quota_manager_impl_->GetBucketsModifiedBetween( type, begin, end, - base::BindOnce(&QuotaManagerImplTest::DidGetModifiedOrigins, - weak_factory_.GetWeakPtr())); + base::BindOnce(&QuotaManagerImplTest::DidGetModifiedBuckets, + weak_factory_.GetWeakPtr(), run_loop.QuitClosure())); + run_loop.Run(); } void DumpQuotaTable() { @@ -385,8 +409,16 @@ class QuotaManagerImplTest : public testing::Test { &QuotaManagerImplTest::DidDumpBucketTable, weak_factory_.GetWeakPtr())); } - void DidGetBucketId(QuotaErrorOr<BucketId> result) { - bucket_id_ = std::move(result); + void DidGetBucket(base::OnceClosure quit_closure, + QuotaErrorOr<BucketInfo> result) { + bucket_ = std::move(result); + std::move(quit_closure).Run(); + } + + void DidGetStorageKeys(base::OnceClosure quit_closure, + const std::set<StorageKey>& storage_keys) { + storage_keys_ = std::move(storage_keys); + std::move(quit_closure).Run(); } void DidGetUsageInfo(UsageInfoEntries entries) { @@ -459,15 +491,18 @@ class QuotaManagerImplTest : public testing::Test { usage_ = global_usage; } - void DidGetEvictionOrigin(const absl::optional<url::Origin>& origin) { - eviction_origin_ = origin; - DCHECK(!origin.has_value() || !origin->GetURL().is_empty()); + void DidGetEvictionBucket(const absl::optional<BucketInfo>& bucket) { + eviction_bucket_ = bucket; + DCHECK(!bucket.has_value() || + !bucket->storage_key.origin().GetURL().is_empty()); } - void DidGetModifiedOrigins(const std::set<url::Origin>& origins, + void DidGetModifiedBuckets(base::OnceClosure quit_closure, + const std::set<BucketInfo>& buckets, StorageType type) { - modified_origins_ = origins; - modified_origins_type_ = type; + modified_buckets_ = buckets; + modified_buckets_type_ = type; + std::move(quit_closure).Run(); } void DidDumpQuotaTable(const QuotaTableEntries& entries) { @@ -481,14 +516,14 @@ class QuotaManagerImplTest : public testing::Test { void GetUsage_WithModifyTestBody(const StorageType type); void SetStoragePressureCallback( - base::RepeatingCallback<void(url::Origin)> callback) { + base::RepeatingCallback<void(StorageKey)> callback) { quota_manager_impl_->SetStoragePressureCallback(std::move(callback)); } - void MaybeRunStoragePressureCallback(const url::Origin& origin, + void MaybeRunStoragePressureCallback(const StorageKey& storage_key, int64_t total, int64_t available) { - quota_manager_impl_->MaybeRunStoragePressureCallback(origin, total, + quota_manager_impl_->MaybeRunStoragePressureCallback(storage_key, total, available); } @@ -519,6 +554,12 @@ class QuotaManagerImplTest : public testing::Test { quota_manager_impl_->SetQuotaChangeCallbackForTesting(std::move(cb)); } + bool is_db_disabled() { return quota_manager_impl_->db_disabled_; } + + void disable_quota_database(bool disable) { + quota_manager_impl_->database_->SetDisabledForTesting(disable); + } + QuotaStatusCode status() const { return quota_status_; } const UsageInfoEntries& usage_info() const { return usage_info_; } int64_t usage() const { return usage_; } @@ -529,13 +570,13 @@ class QuotaManagerImplTest : public testing::Test { int64_t quota() const { return quota_; } int64_t total_space() const { return total_space_; } int64_t available_space() const { return available_space_; } - const absl::optional<url::Origin>& eviction_origin() const { - return eviction_origin_; + const absl::optional<BucketInfo>& eviction_bucket() const { + return eviction_bucket_; } - const std::set<url::Origin>& modified_origins() const { - return modified_origins_; + const std::set<BucketInfo>& modified_buckets() const { + return modified_buckets_; } - StorageType modified_origins_type() const { return modified_origins_type_; } + StorageType modified_buckets_type() const { return modified_buckets_type_; } const QuotaTableEntries& quota_entries() const { return quota_entries_; } const BucketTableEntries& bucket_entries() const { return bucket_entries_; } const QuotaSettings& settings() const { return settings_; } @@ -545,7 +586,8 @@ class QuotaManagerImplTest : public testing::Test { protected: base::test::ScopedFeatureList scoped_feature_list_; base::test::TaskEnvironment task_environment_; - QuotaErrorOr<BucketId> bucket_id_; + QuotaErrorOr<BucketInfo> bucket_; + QuotaErrorOr<std::set<StorageKey>> storage_keys_; static std::vector<QuotaClientType> AllClients() { // TODO(pwnall): Implement using something other than an empty vector? @@ -571,9 +613,9 @@ class QuotaManagerImplTest : public testing::Test { int64_t quota_; int64_t total_space_; int64_t available_space_; - absl::optional<url::Origin> eviction_origin_; - std::set<url::Origin> modified_origins_; - StorageType modified_origins_type_; + absl::optional<BucketInfo> eviction_bucket_; + std::set<BucketInfo> modified_buckets_; + StorageType modified_buckets_type_; QuotaTableEntries quota_entries_; BucketTableEntries bucket_entries_; QuotaSettings settings_; @@ -583,112 +625,134 @@ class QuotaManagerImplTest : public testing::Test { int mock_time_counter_; - // TODO(crbug.com/1163009): Remove this member after all QuotaClients have - // been mojofied. - std::vector<std::unique_ptr<MockQuotaClient>> legacy_clients_; - base::WeakPtrFactory<QuotaManagerImplTest> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(QuotaManagerImplTest); }; TEST_F(QuotaManagerImplTest, GetUsageInfo) { - static const MockOriginData kData1[] = { - { "http://foo.com/", kTemp, 10 }, - { "http://foo.com:8080/", kTemp, 15 }, - { "http://bar.com/", kTemp, 20 }, - { "http://bar.com/", kPerm, 50 }, - }; - static const MockOriginData kData2[] = { - { "https://foo.com/", kTemp, 30 }, - { "https://foo.com:8081/", kTemp, 35 }, - { "http://bar.com/", kPerm, 40 }, - { "http://example.com/", kPerm, 40 }, - }; - CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem, - {blink::mojom::StorageType::kTemporary, - blink::mojom::StorageType::kPersistent}); - CreateAndRegisterLegacyClient(kData2, QuotaClientType::kDatabase, - {blink::mojom::StorageType::kTemporary, - blink::mojom::StorageType::kPersistent}); + static const MockStorageKeyData kData1[] = { + {"http://foo.com/", kTemp, 10}, + {"http://foo.com:8080/", kTemp, 15}, + {"http://bar.com/", kTemp, 20}, + {"http://bar.com/", kPerm, 50}, + }; + static const MockStorageKeyData kData2[] = { + {"https://foo.com/", kTemp, 30}, + {"https://foo.com:8081/", kTemp, 35}, + {"http://bar.com/", kPerm, 40}, + {"http://example.com/", kPerm, 40}, + }; + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); + CreateAndRegisterClient(kData2, QuotaClientType::kDatabase, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); GetUsageInfo(); task_environment_.RunUntilIdle(); - EXPECT_EQ(4U, usage_info().size()); - for (const UsageInfo& info : usage_info()) { - if (info.host == "foo.com" && info.type == kTemp) { - EXPECT_EQ(10 + 15 + 30 + 35, info.usage); - } else if (info.host == "bar.com" && info.type == kTemp) { - EXPECT_EQ(20, info.usage); - } else if (info.host == "bar.com" && info.type == kPerm) { - EXPECT_EQ(50 + 40, info.usage); - } else if (info.host == "example.com" && info.type == kPerm) { - EXPECT_EQ(40, info.usage); - } else { - ADD_FAILURE() << "Unexpected host, type: " << info.host << ", " - << static_cast<int>(info.type); - } - } + EXPECT_THAT(usage_info(), testing::UnorderedElementsAre( + UsageInfo("foo.com", kTemp, 10 + 15 + 30 + 35), + UsageInfo("bar.com", kTemp, 20), + UsageInfo("bar.com", kPerm, 40 + 50), + UsageInfo("example.com", kPerm, 40))); } -TEST_F(QuotaManagerImplTest, CreateBucket) { - url::Origin origin = ToOrigin("http://a.com/"); - std::string bucket_name = "BucketA"; +TEST_F(QuotaManagerImplTest, GetOrCreateBucket) { + StorageKey storage_key = ToStorageKey("http://a.com/"); + std::string bucket_name = "bucket_a"; - CreateBucket(origin, bucket_name); - task_environment_.RunUntilIdle(); - ASSERT_TRUE(bucket_id_.ok()); + GetOrCreateBucket(storage_key, bucket_name); + ASSERT_TRUE(bucket_.ok()); - // Try creating a bucket with the same name. - CreateBucket(origin, bucket_name); - task_environment_.RunUntilIdle(); - EXPECT_FALSE(bucket_id_.ok()); + BucketId created_bucket_id = bucket_.value().id; + + GetOrCreateBucket(storage_key, bucket_name); + EXPECT_TRUE(bucket_.ok()); + EXPECT_EQ(bucket_.value().id, created_bucket_id); } -TEST_F(QuotaManagerImplTest, GetBucketId) { - url::Origin origin = ToOrigin("http://a.com/"); - std::string bucket_name = "BucketA"; +TEST_F(QuotaManagerImplTest, GetBucket) { + StorageKey storage_key = ToStorageKey("http://a.com/"); + std::string bucket_name = "bucket_a"; - CreateBucket(origin, bucket_name); - task_environment_.RunUntilIdle(); - ASSERT_TRUE(bucket_id_.ok()); - BucketId created_bucket_id = bucket_id_.value(); + CreateBucketForTesting(storage_key, bucket_name, kTemp); + ASSERT_TRUE(bucket_.ok()); + BucketInfo created_bucket = bucket_.value(); - GetBucketId(origin, bucket_name); - task_environment_.RunUntilIdle(); - ASSERT_TRUE(bucket_id_.ok()); - BucketId retrieved_bucket_id = bucket_id_.value(); - EXPECT_EQ(created_bucket_id, retrieved_bucket_id); + GetBucket(storage_key, bucket_name, kTemp); + ASSERT_TRUE(bucket_.ok()); + BucketInfo retrieved_bucket = bucket_.value(); + EXPECT_EQ(created_bucket.id, retrieved_bucket.id); - GetBucketId(origin, "BucketB"); - task_environment_.RunUntilIdle(); - EXPECT_TRUE(bucket_id_.value().is_null()); + GetBucket(storage_key, "bucket_b", kTemp); + ASSERT_FALSE(bucket_.ok()); + EXPECT_EQ(bucket_.error(), QuotaError::kNotFound); + ASSERT_FALSE(is_db_disabled()); +} + +TEST_F(QuotaManagerImplTest, GetStorageKeysForType) { + StorageKey storage_key_a = ToStorageKey("http://a.com/"); + StorageKey storage_key_b = ToStorageKey("http://b.com/"); + StorageKey storage_key_c = ToStorageKey("http://c.com/"); + + CreateBucketForTesting(storage_key_a, "bucket_a", kTemp); + EXPECT_TRUE(bucket_.ok()); + BucketInfo bucket_a = bucket_.value(); + + CreateBucketForTesting(storage_key_b, "bucket_b", kTemp); + EXPECT_TRUE(bucket_.ok()); + BucketInfo bucket_b = bucket_.value(); + + CreateBucketForTesting(storage_key_c, "bucket_c", kPerm); + EXPECT_TRUE(bucket_.ok()); + BucketInfo bucket_c = bucket_.value(); + + GetStorageKeysForType(kTemp); + EXPECT_THAT(storage_keys_.value(), + testing::UnorderedElementsAre(storage_key_a, storage_key_b)); + + GetStorageKeysForType(kPerm); + EXPECT_THAT(storage_keys_.value(), + testing::UnorderedElementsAre(storage_key_c)); +} + +TEST_F(QuotaManagerImplTest, GetStorageKeysForTypeWithDatabaseError) { + OpenDatabase(); + + // Disable quota database for database error behavior. + disable_quota_database(true); + + // Return empty set when error is encountered. + GetStorageKeysForType(kTemp); + EXPECT_TRUE(storage_keys_.value().empty()); } TEST_F(QuotaManagerImplTest, GetUsageAndQuota_Simple) { - static const MockOriginData kData[] = { - { "http://foo.com/", kTemp, 10 }, - { "http://foo.com/", kPerm, 80 }, + static const MockStorageKeyData kData[] = { + {"http://foo.com/", kTemp, 10}, + {"http://foo.com/", kPerm, 80}, }; CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, {blink::mojom::StorageType::kTemporary, blink::mojom::StorageType::kPersistent}); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(80, usage()); EXPECT_EQ(0, quota()); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10, usage()); EXPECT_LE(0, quota()); int64_t quota_returned_for_foo = quota(); - GetUsageAndQuotaForWebApps(ToOrigin("http://bar.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://bar.com/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); @@ -696,12 +760,12 @@ TEST_F(QuotaManagerImplTest, GetUsageAndQuota_Simple) { } TEST_F(QuotaManagerImplTest, GetUsage_NoClient) { - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); @@ -726,16 +790,17 @@ TEST_F(QuotaManagerImplTest, GetUsage_NoClient) { } TEST_F(QuotaManagerImplTest, GetUsage_EmptyClient) { - CreateAndRegisterLegacyClient(base::span<MockOriginData>(), - QuotaClientType::kFileSystem, - {blink::mojom::StorageType::kTemporary, - blink::mojom::StorageType::kPersistent}); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); + CreateAndRegisterClient(base::span<MockStorageKeyData>(), + QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); + + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); @@ -759,14 +824,11 @@ TEST_F(QuotaManagerImplTest, GetUsage_EmptyClient) { EXPECT_EQ(0, unlimited_usage()); } -TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_MultiOrigins) { - static const MockOriginData kData[] = { - { "http://foo.com/", kTemp, 10 }, - { "http://foo.com:8080/", kTemp, 20 }, - { "http://bar.com/", kTemp, 5 }, - { "https://bar.com/", kTemp, 7 }, - { "http://baz.com/", kTemp, 30 }, - { "http://foo.com/", kPerm, 40 }, +TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_MultiStorageKeys) { + static const MockStorageKeyData kData[] = { + {"http://foo.com/", kTemp, 10}, {"http://foo.com:8080/", kTemp, 20}, + {"http://bar.com/", kTemp, 5}, {"https://bar.com/", kTemp, 7}, + {"http://baz.com/", kTemp, 30}, {"http://foo.com/", kPerm, 40}, }; CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, {blink::mojom::StorageType::kTemporary, @@ -777,7 +839,7 @@ TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_MultiOrigins) { const int kPerHostQuota = 20; SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10 + 20, usage()); @@ -786,7 +848,7 @@ TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_MultiOrigins) { // since there's plenty of diskspace. EXPECT_EQ(kPerHostQuota, quota()); - GetUsageAndQuotaForWebApps(ToOrigin("http://bar.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://bar.com/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(5 + 7, usage()); @@ -794,49 +856,49 @@ TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_MultiOrigins) { } TEST_F(QuotaManagerImplTest, GetUsage_MultipleClients) { - static const MockOriginData kData1[] = { - { "http://foo.com/", kTemp, 1 }, - { "http://bar.com/", kTemp, 2 }, - { "http://bar.com/", kPerm, 4 }, - { "http://unlimited/", kPerm, 8 }, + static const MockStorageKeyData kData1[] = { + {"http://foo.com/", kTemp, 1}, + {"http://bar.com/", kTemp, 2}, + {"http://bar.com/", kPerm, 4}, + {"http://unlimited/", kPerm, 8}, }; - static const MockOriginData kData2[] = { - { "https://foo.com/", kTemp, 128 }, - { "http://example.com/", kPerm, 256 }, - { "http://unlimited/", kTemp, 512 }, + static const MockStorageKeyData kData2[] = { + {"https://foo.com/", kTemp, 128}, + {"http://example.com/", kPerm, 256}, + {"http://unlimited/", kTemp, 512}, }; mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/")); GetStorageCapacity(); CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, {blink::mojom::StorageType::kTemporary, blink::mojom::StorageType::kPersistent}); - CreateAndRegisterLegacyClient(kData2, QuotaClientType::kDatabase, - {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; SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(1 + 128, usage()); EXPECT_EQ(kPerHostQuota, quota()); - GetUsageAndQuotaForWebApps(ToOrigin("http://bar.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToStorageKey("http://bar.com/"), kPerm); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(4, usage()); EXPECT_EQ(0, quota()); - GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://unlimited/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(512, usage()); EXPECT_EQ(available_space() + usage(), quota()); - GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kPerm); + GetUsageAndQuotaForWebApps(ToStorageKey("http://unlimited/"), kPerm); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(8, usage()); @@ -858,24 +920,25 @@ TEST_F(QuotaManagerImplTest, GetUsage_MultipleClients) { TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_Simple) { blink::mojom::UsageBreakdown usage_breakdown_expected = blink::mojom::UsageBreakdown(); - static const MockOriginData kData1[] = { - {"http://foo.com/", kTemp, 1}, {"http://foo.com/", kPerm, 80}, + static const MockStorageKeyData kData1[] = { + {"http://foo.com/", kTemp, 1}, + {"http://foo.com/", kPerm, 80}, }; - static const MockOriginData kData2[] = { + static const MockStorageKeyData kData2[] = { {"http://foo.com/", kTemp, 4}, }; - static const MockOriginData kData3[] = { + static const MockStorageKeyData kData3[] = { {"http://foo.com/", kTemp, 8}, }; - CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem, - {blink::mojom::StorageType::kTemporary, - blink::mojom::StorageType::kPersistent}); + 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); + GetUsageAndQuotaWithBreakdown(ToStorageKey("http://foo.com/"), kPerm); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(80, usage()); @@ -884,7 +947,7 @@ TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_Simple) { usage_breakdown_expected.appcache = 0; EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown())); - GetUsageAndQuotaWithBreakdown(ToOrigin("http://foo.com/"), kTemp); + GetUsageAndQuotaWithBreakdown(ToStorageKey("http://foo.com/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(1 + 4 + 8, usage()); @@ -893,7 +956,7 @@ TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_Simple) { usage_breakdown_expected.appcache = 8; EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown())); - GetUsageAndQuotaWithBreakdown(ToOrigin("http://bar.com/"), kTemp); + GetUsageAndQuotaWithBreakdown(ToStorageKey("http://bar.com/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); @@ -907,13 +970,13 @@ TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_NoClient) { blink::mojom::UsageBreakdown usage_breakdown_expected = blink::mojom::UsageBreakdown(); - GetUsageAndQuotaWithBreakdown(ToOrigin("http://foo.com/"), kTemp); + GetUsageAndQuotaWithBreakdown(ToStorageKey("http://foo.com/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown())); - GetUsageAndQuotaWithBreakdown(ToOrigin("http://foo.com/"), kPerm); + GetUsageAndQuotaWithBreakdown(ToStorageKey("http://foo.com/"), kPerm); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); @@ -930,10 +993,10 @@ TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_NoClient) { EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown())); } -TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_MultiOrigins) { +TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_MultiStorageKeys) { blink::mojom::UsageBreakdown usage_breakdown_expected = blink::mojom::UsageBreakdown(); - static const MockOriginData kData[] = { + static const MockStorageKeyData kData[] = { {"http://foo.com/", kTemp, 10}, {"http://foo.com:8080/", kTemp, 20}, {"http://bar.com/", kTemp, 5}, {"https://bar.com/", kTemp, 7}, {"http://baz.com/", kTemp, 30}, {"http://foo.com/", kPerm, 40}, @@ -942,14 +1005,14 @@ TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_MultiOrigins) { {blink::mojom::StorageType::kTemporary, blink::mojom::StorageType::kPersistent}); - GetUsageAndQuotaWithBreakdown(ToOrigin("http://foo.com/"), kTemp); + GetUsageAndQuotaWithBreakdown(ToStorageKey("http://foo.com/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10 + 20, usage()); usage_breakdown_expected.fileSystem = 10 + 20; EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown())); - GetUsageAndQuotaWithBreakdown(ToOrigin("http://bar.com/"), kTemp); + GetUsageAndQuotaWithBreakdown(ToStorageKey("http://bar.com/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(5 + 7, usage()); @@ -960,26 +1023,26 @@ TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_MultiOrigins) { TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_MultipleClients) { blink::mojom::UsageBreakdown usage_breakdown_expected = blink::mojom::UsageBreakdown(); - static const MockOriginData kData1[] = { + static const MockStorageKeyData kData1[] = { {"http://foo.com/", kTemp, 1}, {"http://bar.com/", kTemp, 2}, {"http://bar.com/", kPerm, 4}, {"http://unlimited/", kPerm, 8}, }; - static const MockOriginData kData2[] = { + static const MockStorageKeyData kData2[] = { {"https://foo.com/", kTemp, 128}, {"http://example.com/", kPerm, 256}, {"http://unlimited/", kTemp, 512}, }; mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/")); - CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem, - {blink::mojom::StorageType::kTemporary, - blink::mojom::StorageType::kPersistent}); + 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); + GetUsageAndQuotaWithBreakdown(ToStorageKey("http://foo.com/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(1 + 128, usage()); @@ -987,7 +1050,7 @@ TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_MultipleClients) { usage_breakdown_expected.webSql = 128; EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown())); - GetUsageAndQuotaWithBreakdown(ToOrigin("http://bar.com/"), kPerm); + GetUsageAndQuotaWithBreakdown(ToStorageKey("http://bar.com/"), kPerm); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(4, usage()); @@ -995,7 +1058,7 @@ TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_MultipleClients) { usage_breakdown_expected.webSql = 0; EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown())); - GetUsageAndQuotaWithBreakdown(ToOrigin("http://unlimited/"), kTemp); + GetUsageAndQuotaWithBreakdown(ToStorageKey("http://unlimited/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(512, usage()); @@ -1003,7 +1066,7 @@ TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_MultipleClients) { usage_breakdown_expected.webSql = 512; EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown())); - GetUsageAndQuotaWithBreakdown(ToOrigin("http://unlimited/"), kPerm); + GetUsageAndQuotaWithBreakdown(ToStorageKey("http://unlimited/"), kPerm); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(8, usage()); @@ -1013,30 +1076,31 @@ TEST_F(QuotaManagerImplTest, GetUsageWithBreakdown_MultipleClients) { } void QuotaManagerImplTest::GetUsage_WithModifyTestBody(const StorageType type) { - const MockOriginData data[] = { - { "http://foo.com/", type, 10 }, - { "http://foo.com:1/", type, 20 }, + const MockStorageKeyData data[] = { + {"http://foo.com/", type, 10}, + {"http://foo.com:1/", type, 20}, }; MockQuotaClient* client = CreateAndRegisterClient(data, QuotaClientType::kFileSystem, {type}); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), type); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), type); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10 + 20, usage()); - client->ModifyOriginAndNotify(ToOrigin("http://foo.com/"), type, 30); - client->ModifyOriginAndNotify(ToOrigin("http://foo.com:1/"), type, -5); - client->AddOriginAndNotify(ToOrigin("https://foo.com/"), type, 1); + client->ModifyStorageKeyAndNotify(ToStorageKey("http://foo.com/"), type, 30); + client->ModifyStorageKeyAndNotify(ToStorageKey("http://foo.com:1/"), type, + -5); + client->AddStorageKeyAndNotify(ToStorageKey("https://foo.com/"), type, 1); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), type); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), type); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10 + 20 + 30 - 5 + 1, usage()); int foo_usage = usage(); - client->AddOriginAndNotify(ToOrigin("http://bar.com/"), type, 40); - GetUsageAndQuotaForWebApps(ToOrigin("http://bar.com/"), type); + client->AddStorageKeyAndNotify(ToStorageKey("http://bar.com/"), type, 40); + GetUsageAndQuotaForWebApps(ToStorageKey("http://bar.com/"), type); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(40, usage()); @@ -1052,11 +1116,11 @@ TEST_F(QuotaManagerImplTest, GetTemporaryUsage_WithModify) { } TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_WithAdditionalTasks) { - static const MockOriginData kData[] = { - { "http://foo.com/", kTemp, 10 }, - { "http://foo.com:8080/", kTemp, 20 }, - { "http://bar.com/", kTemp, 13 }, - { "http://foo.com/", kPerm, 40 }, + static const MockStorageKeyData kData[] = { + {"http://foo.com/", kTemp, 10}, + {"http://foo.com:8080/", kTemp, 20}, + {"http://bar.com/", kTemp, 13}, + {"http://foo.com/", kPerm, 40}, }; CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, {blink::mojom::StorageType::kTemporary, @@ -1066,18 +1130,18 @@ TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_WithAdditionalTasks) { const int kPerHostQuota = 20; SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10 + 20, usage()); EXPECT_EQ(kPerHostQuota, quota()); set_additional_callback_count(0); - RunAdditionalUsageAndQuotaTask(ToOrigin("http://foo.com/"), kTemp); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); - RunAdditionalUsageAndQuotaTask(ToOrigin("http://bar.com/"), kTemp); + RunAdditionalUsageAndQuotaTask(ToStorageKey("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp); + RunAdditionalUsageAndQuotaTask(ToStorageKey("http://bar.com/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10 + 20, usage()); @@ -1086,56 +1150,28 @@ TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_WithAdditionalTasks) { } TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_NukeManager) { - static const MockOriginData kData[] = { - { "http://foo.com/", kTemp, 10 }, - { "http://foo.com:8080/", kTemp, 20 }, - { "http://bar.com/", kTemp, 13 }, - { "http://foo.com/", kPerm, 40 }, - }; - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, - {blink::mojom::StorageType::kTemporary, - blink::mojom::StorageType::kPersistent}); - const int kPoolSize = 100; - const int kPerHostQuota = 20; - SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem); - - set_additional_callback_count(0); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); - RunAdditionalUsageAndQuotaTask(ToOrigin("http://foo.com/"), kTemp); - RunAdditionalUsageAndQuotaTask(ToOrigin("http://bar.com/"), kTemp); - - DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, AllQuotaClientTypes()); - DeleteOriginData(ToOrigin("http://bar.com/"), kTemp, AllQuotaClientTypes()); - - // Nuke before waiting for callbacks. - set_quota_manager_impl(nullptr); - task_environment_.RunUntilIdle(); - EXPECT_EQ(QuotaStatusCode::kErrorAbort, status()); -} - -// TODO(crbug.com/1163009): Remove this test after all QuotaClients have been -// mojofied -TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_NukeManager_Legacy) { - static const MockOriginData kData[] = { + static const MockStorageKeyData kData[] = { {"http://foo.com/", kTemp, 10}, {"http://foo.com:8080/", kTemp, 20}, {"http://bar.com/", kTemp, 13}, {"http://foo.com/", kPerm, 40}, }; - CreateAndRegisterLegacyClient(kData, QuotaClientType::kFileSystem, - {blink::mojom::StorageType::kTemporary, - blink::mojom::StorageType::kPersistent}); + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); const int kPoolSize = 100; const int kPerHostQuota = 20; SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem); set_additional_callback_count(0); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); - RunAdditionalUsageAndQuotaTask(ToOrigin("http://foo.com/"), kTemp); - RunAdditionalUsageAndQuotaTask(ToOrigin("http://bar.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp); + RunAdditionalUsageAndQuotaTask(ToStorageKey("http://foo.com/"), kTemp); + RunAdditionalUsageAndQuotaTask(ToStorageKey("http://bar.com/"), kTemp); - DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, AllQuotaClientTypes()); - DeleteOriginData(ToOrigin("http://bar.com/"), kTemp, AllQuotaClientTypes()); + DeleteStorageKeyData(ToStorageKey("http://foo.com/"), kTemp, + AllQuotaClientTypes()); + DeleteStorageKeyData(ToStorageKey("http://bar.com/"), kTemp, + AllQuotaClientTypes()); // Nuke before waiting for callbacks. set_quota_manager_impl(nullptr); @@ -1144,10 +1180,10 @@ TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_NukeManager_Legacy) { } TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_Overbudget) { - static const MockOriginData kData[] = { - { "http://usage1/", kTemp, 1 }, - { "http://usage10/", kTemp, 10 }, - { "http://usage200/", kTemp, 200 }, + static const MockStorageKeyData kData[] = { + {"http://usage1/", kTemp, 1}, + {"http://usage10/", kTemp, 10}, + {"http://usage200/", kTemp, 200}, }; CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, {blink::mojom::StorageType::kTemporary}); @@ -1156,25 +1192,25 @@ TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_Overbudget) { SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem); // Provided diskspace is not tight, global usage does not affect the - // quota calculations for an individual origin, so despite global usage + // quota calculations for an individual storage key, so despite global usage // in excess of our poolsize, we still get the nominal quota value. GetStorageCapacity(); task_environment_.RunUntilIdle(); EXPECT_LE(kMustRemainAvailableForSystem, available_space()); - GetUsageAndQuotaForWebApps(ToOrigin("http://usage1/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://usage1/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(1, usage()); EXPECT_EQ(kPerHostQuota, quota()); - GetUsageAndQuotaForWebApps(ToOrigin("http://usage10/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://usage10/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10, usage()); EXPECT_EQ(kPerHostQuota, quota()); - GetUsageAndQuotaForWebApps(ToOrigin("http://usage200/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://usage200/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(200, usage()); @@ -1182,10 +1218,10 @@ TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_Overbudget) { } TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_Unlimited) { - static const MockOriginData kData[] = { - { "http://usage10/", kTemp, 10 }, - { "http://usage50/", kTemp, 50 }, - { "http://unlimited/", kTemp, 4000 }, + static const MockStorageKeyData kData[] = { + {"http://usage10/", kTemp, 10}, + {"http://usage50/", kTemp, 50}, + {"http://unlimited/", kTemp, 4000}, }; mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/")); GetStorageCapacity(); @@ -1200,25 +1236,25 @@ TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_Unlimited) { EXPECT_EQ(10 + 50 + 4000, usage()); EXPECT_EQ(4000, unlimited_usage()); - GetUsageAndQuotaForWebApps(ToOrigin("http://usage10/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://usage10/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10, usage()); EXPECT_EQ(kPerHostQuotaFor1000, quota()); - GetUsageAndQuotaForWebApps(ToOrigin("http://usage50/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://usage50/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(50, usage()); EXPECT_EQ(kPerHostQuotaFor1000, quota()); - GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://unlimited/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(4000, usage()); EXPECT_EQ(available_space() + usage(), quota()); - GetUsageAndQuotaForStorageClient(ToOrigin("http://unlimited/"), kTemp); + GetUsageAndQuotaForStorageClient(ToStorageKey("http://unlimited/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); @@ -1228,25 +1264,25 @@ TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_Unlimited) { const int kPerHostQuotaFor100 = 20; SetQuotaSettings(100, kPerHostQuotaFor100, kMustRemainAvailableForSystem); - GetUsageAndQuotaForWebApps(ToOrigin("http://usage10/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://usage10/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10, usage()); EXPECT_EQ(kPerHostQuotaFor100, quota()); - GetUsageAndQuotaForWebApps(ToOrigin("http://usage50/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://usage50/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(50, usage()); EXPECT_EQ(kPerHostQuotaFor100, quota()); - GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://unlimited/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(4000, usage()); EXPECT_EQ(available_space() + usage(), quota()); - GetUsageAndQuotaForStorageClient(ToOrigin("http://unlimited/"), kTemp); + GetUsageAndQuotaForStorageClient(ToStorageKey("http://unlimited/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); @@ -1261,55 +1297,33 @@ TEST_F(QuotaManagerImplTest, GetTemporaryUsageAndQuota_Unlimited) { EXPECT_EQ(10 + 50 + 4000, usage()); EXPECT_EQ(0, unlimited_usage()); - GetUsageAndQuotaForWebApps(ToOrigin("http://usage10/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://usage10/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10, usage()); EXPECT_EQ(kPerHostQuotaFor100, quota()); - GetUsageAndQuotaForWebApps(ToOrigin("http://usage50/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://usage50/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(50, usage()); EXPECT_EQ(kPerHostQuotaFor100, quota()); - GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://unlimited/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(4000, usage()); EXPECT_EQ(kPerHostQuotaFor100, quota()); - GetUsageAndQuotaForStorageClient(ToOrigin("http://unlimited/"), kTemp); + GetUsageAndQuotaForStorageClient(ToStorageKey("http://unlimited/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(4000, usage()); EXPECT_EQ(kPerHostQuotaFor100, quota()); } -TEST_F(QuotaManagerImplTest, OriginInUse) { - const url::Origin kFooOrigin = ToOrigin("http://foo.com/"); - const url::Origin kBarOrigin = ToOrigin("http://bar.com/"); - - EXPECT_FALSE(quota_manager_impl()->IsOriginInUse(kFooOrigin)); - quota_manager_impl()->NotifyOriginInUse(kFooOrigin); // count of 1 - EXPECT_TRUE(quota_manager_impl()->IsOriginInUse(kFooOrigin)); - quota_manager_impl()->NotifyOriginInUse(kFooOrigin); // count of 2 - EXPECT_TRUE(quota_manager_impl()->IsOriginInUse(kFooOrigin)); - quota_manager_impl()->NotifyOriginNoLongerInUse(kFooOrigin); // count of 1 - EXPECT_TRUE(quota_manager_impl()->IsOriginInUse(kFooOrigin)); - - EXPECT_FALSE(quota_manager_impl()->IsOriginInUse(kBarOrigin)); - quota_manager_impl()->NotifyOriginInUse(kBarOrigin); - EXPECT_TRUE(quota_manager_impl()->IsOriginInUse(kBarOrigin)); - quota_manager_impl()->NotifyOriginNoLongerInUse(kBarOrigin); - EXPECT_FALSE(quota_manager_impl()->IsOriginInUse(kBarOrigin)); - - quota_manager_impl()->NotifyOriginNoLongerInUse(kFooOrigin); - EXPECT_FALSE(quota_manager_impl()->IsOriginInUse(kFooOrigin)); -} - TEST_F(QuotaManagerImplTest, GetAndSetPerststentHostQuota) { - CreateAndRegisterClient(base::span<MockOriginData>(), + CreateAndRegisterClient(base::span<MockStorageKeyData>(), QuotaClientType::kFileSystem, {blink::mojom::StorageType::kTemporary, blink::mojom::StorageType::kPersistent}); @@ -1341,40 +1355,41 @@ TEST_F(QuotaManagerImplTest, GetAndSetPerststentHostQuota) { TEST_F(QuotaManagerImplTest, GetAndSetPersistentUsageAndQuota) { GetStorageCapacity(); - CreateAndRegisterClient(base::span<MockOriginData>(), + CreateAndRegisterClient(base::span<MockStorageKeyData>(), QuotaClientType::kFileSystem, {blink::mojom::StorageType::kTemporary, blink::mojom::StorageType::kPersistent}); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); EXPECT_EQ(0, quota()); SetPersistentHostQuota("foo.com", 100); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); EXPECT_EQ(100, quota()); - // The actual space avaialble is given to 'unlimited' origins as their quota. + // The actual space available is given to 'unlimited' storage keys as their + // quota. mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/")); - GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kPerm); + GetUsageAndQuotaForWebApps(ToStorageKey("http://unlimited/"), kPerm); task_environment_.RunUntilIdle(); EXPECT_EQ(available_space() + usage(), quota()); // GetUsageAndQuotaForStorageClient should just return 0 usage and // kNoLimit quota. - GetUsageAndQuotaForStorageClient(ToOrigin("http://unlimited/"), kPerm); + GetUsageAndQuotaForStorageClient(ToStorageKey("http://unlimited/"), kPerm); task_environment_.RunUntilIdle(); EXPECT_EQ(0, usage()); EXPECT_EQ(QuotaManagerImpl::kNoLimit, quota()); } TEST_F(QuotaManagerImplTest, GetQuotaLowAvailableDiskSpace) { - static const MockOriginData kData[] = { + static const MockStorageKeyData kData[] = { {"http://foo.com/", kTemp, 100000}, {"http://unlimited/", kTemp, 4000000}, }; @@ -1393,7 +1408,7 @@ TEST_F(QuotaManagerImplTest, GetQuotaLowAvailableDiskSpace) { static_cast<int>(GetAvailableDiskSpaceForTest() - 65536); SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailable); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(100000, usage()); @@ -1401,7 +1416,7 @@ TEST_F(QuotaManagerImplTest, GetQuotaLowAvailableDiskSpace) { } TEST_F(QuotaManagerImplTest, GetSyncableQuota) { - CreateAndRegisterClient(base::span<MockOriginData>(), + CreateAndRegisterClient(base::span<MockStorageKeyData>(), QuotaClientType::kFileSystem, {blink::mojom::StorageType::kTemporary, blink::mojom::StorageType::kSyncable}); @@ -1414,34 +1429,30 @@ TEST_F(QuotaManagerImplTest, GetSyncableQuota) { // The quota manager should return // QuotaManagerImpl::kSyncableStorageDefaultHostQuota as syncable quota, // despite available space being less than the desired quota. Only - // origins with unlimited storage, which is never the case for syncable + // storage keys with unlimited storage, which is never the case for syncable // storage, shall have their quota calculation take into account the amount of // available disk space. mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/")); - GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kSync); + GetUsageAndQuotaForWebApps(ToStorageKey("http://unlimited/"), kSync); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); EXPECT_EQ(QuotaManagerImpl::kSyncableStorageDefaultHostQuota, quota()); } -TEST_F(QuotaManagerImplTest, GetPersistentUsageAndQuota_MultiOrigins) { - static const MockOriginData kData[] = { - { "http://foo.com/", kPerm, 10 }, - { "http://foo.com:8080/", kPerm, 20 }, - { "https://foo.com/", kPerm, 13 }, - { "https://foo.com:8081/", kPerm, 19 }, - { "http://bar.com/", kPerm, 5 }, - { "https://bar.com/", kPerm, 7 }, - { "http://baz.com/", kPerm, 30 }, - { "http://foo.com/", kTemp, 40 }, +TEST_F(QuotaManagerImplTest, GetPersistentUsageAndQuota_MultiStorageKeys) { + static const MockStorageKeyData kData[] = { + {"http://foo.com/", kPerm, 10}, {"http://foo.com:8080/", kPerm, 20}, + {"https://foo.com/", kPerm, 13}, {"https://foo.com:8081/", kPerm, 19}, + {"http://bar.com/", kPerm, 5}, {"https://bar.com/", kPerm, 7}, + {"http://baz.com/", kPerm, 30}, {"http://foo.com/", kTemp, 40}, }; CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, {blink::mojom::StorageType::kTemporary, blink::mojom::StorageType::kPersistent}); SetPersistentHostQuota("foo.com", 100); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10 + 20 + 13 + 19, usage()); @@ -1453,109 +1464,51 @@ TEST_F(QuotaManagerImplTest, GetPersistentUsage_WithModify) { } TEST_F(QuotaManagerImplTest, GetPersistentUsageAndQuota_WithAdditionalTasks) { - static const MockOriginData kData[] = { - { "http://foo.com/", kPerm, 10 }, - { "http://foo.com:8080/", kPerm, 20 }, - { "http://bar.com/", kPerm, 13 }, - { "http://foo.com/", kTemp, 40 }, + static const MockStorageKeyData kData[] = { + {"http://foo.com/", kPerm, 10}, + {"http://foo.com:8080/", kPerm, 20}, + {"http://bar.com/", kPerm, 13}, + {"http://foo.com/", kTemp, 40}, }; CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, {blink::mojom::StorageType::kTemporary, blink::mojom::StorageType::kPersistent}); SetPersistentHostQuota("foo.com", 100); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10 + 20, usage()); EXPECT_EQ(100, quota()); set_additional_callback_count(0); - RunAdditionalUsageAndQuotaTask(ToOrigin("http://foo.com/"), kPerm); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); - RunAdditionalUsageAndQuotaTask(ToOrigin("http://bar.com/"), kPerm); + RunAdditionalUsageAndQuotaTask(ToStorageKey("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm); + RunAdditionalUsageAndQuotaTask(ToStorageKey("http://bar.com/"), kPerm); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10 + 20, usage()); EXPECT_EQ(2, additional_callback_count()); } -// TODO(crbug.com/1163009): Remove this test after all QuotaClients have been -// mojofied -TEST_F(QuotaManagerImplTest, - GetPersistentUsageAndQuota_WithAdditionalTasks_Legacy) { - static const MockOriginData kData[] = { +TEST_F(QuotaManagerImplTest, GetPersistentUsageAndQuota_NukeManager) { + static const MockStorageKeyData kData[] = { {"http://foo.com/", kPerm, 10}, {"http://foo.com:8080/", kPerm, 20}, {"http://bar.com/", kPerm, 13}, {"http://foo.com/", kTemp, 40}, }; - CreateAndRegisterLegacyClient(kData, QuotaClientType::kFileSystem, - {blink::mojom::StorageType::kTemporary, - blink::mojom::StorageType::kPersistent}); - SetPersistentHostQuota("foo.com", 100); - - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); - task_environment_.RunUntilIdle(); - EXPECT_EQ(QuotaStatusCode::kOk, status()); - EXPECT_EQ(10 + 20, usage()); - EXPECT_EQ(100, quota()); - - set_additional_callback_count(0); - RunAdditionalUsageAndQuotaTask(ToOrigin("http://foo.com/"), kPerm); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); - RunAdditionalUsageAndQuotaTask(ToOrigin("http://bar.com/"), kPerm); - task_environment_.RunUntilIdle(); - EXPECT_EQ(QuotaStatusCode::kOk, status()); - EXPECT_EQ(10 + 20, usage()); - EXPECT_EQ(2, additional_callback_count()); -} - -TEST_F(QuotaManagerImplTest, GetPersistentUsageAndQuota_NukeManager) { - static const MockOriginData kData[] = { - { "http://foo.com/", kPerm, 10 }, - { "http://foo.com:8080/", kPerm, 20 }, - { "http://bar.com/", kPerm, 13 }, - { "http://foo.com/", kTemp, 40 }, - }; CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, {blink::mojom::StorageType::kTemporary, blink::mojom::StorageType::kPersistent}); SetPersistentHostQuota("foo.com", 100); set_additional_callback_count(0); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); - RunAdditionalUsageAndQuotaTask(ToOrigin("http://foo.com/"), kPerm); - RunAdditionalUsageAndQuotaTask(ToOrigin("http://bar.com/"), kPerm); - - // Nuke before waiting for callbacks. - set_quota_manager_impl(nullptr); - task_environment_.RunUntilIdle(); - EXPECT_EQ(QuotaStatusCode::kErrorAbort, status()); -} - -// TODO(crbug.com/1163009): Remove this test after all QuotaClients have been -// mojofied -TEST_F(QuotaManagerImplTest, GetPersistentUsageAndQuota_NukeManager_Legacy) { - static const MockOriginData kData[] = { - {"http://foo.com/", kPerm, 10}, - {"http://foo.com:8080/", kPerm, 20}, - {"http://bar.com/", kPerm, 13}, - {"http://foo.com/", kTemp, 40}, - }; - CreateAndRegisterLegacyClient(kData, QuotaClientType::kFileSystem, - {blink::mojom::StorageType::kTemporary, - blink::mojom::StorageType::kPersistent}); - SetPersistentHostQuota("foo.com", 100); - - set_additional_callback_count(0); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); - RunAdditionalUsageAndQuotaTask(ToOrigin("http://foo.com/"), kPerm); - RunAdditionalUsageAndQuotaTask(ToOrigin("http://bar.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm); + RunAdditionalUsageAndQuotaTask(ToStorageKey("http://foo.com/"), kPerm); + RunAdditionalUsageAndQuotaTask(ToStorageKey("http://bar.com/"), kPerm); // Nuke before waiting for callbacks. set_quota_manager_impl(nullptr); @@ -1564,14 +1517,11 @@ TEST_F(QuotaManagerImplTest, GetPersistentUsageAndQuota_NukeManager_Legacy) { } TEST_F(QuotaManagerImplTest, GetUsage_Simple) { - static const MockOriginData kData[] = { - { "http://foo.com/", kPerm, 1 }, - { "http://foo.com:1/", kPerm, 20 }, - { "http://bar.com/", kTemp, 300 }, - { "https://buz.com/", kTemp, 4000 }, - { "http://buz.com/", kTemp, 50000 }, - { "http://bar.com:1/", kPerm, 600000 }, - { "http://foo.com/", kTemp, 7000000 }, + static const MockStorageKeyData kData[] = { + {"http://foo.com/", kPerm, 1}, {"http://foo.com:1/", kPerm, 20}, + {"http://bar.com/", kTemp, 300}, {"https://buz.com/", kTemp, 4000}, + {"http://buz.com/", kTemp, 50000}, {"http://bar.com:1/", kPerm, 600000}, + {"http://foo.com/", kTemp, 7000000}, }; CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, {blink::mojom::StorageType::kTemporary, @@ -1597,14 +1547,11 @@ TEST_F(QuotaManagerImplTest, GetUsage_Simple) { } TEST_F(QuotaManagerImplTest, GetUsage_WithModification) { - static const MockOriginData kData[] = { - { "http://foo.com/", kPerm, 1 }, - { "http://foo.com:1/", kPerm, 20 }, - { "http://bar.com/", kTemp, 300 }, - { "https://buz.com/", kTemp, 4000 }, - { "http://buz.com/", kTemp, 50000 }, - { "http://bar.com:1/", kPerm, 600000 }, - { "http://foo.com/", kTemp, 7000000 }, + static const MockStorageKeyData kData[] = { + {"http://foo.com/", kPerm, 1}, {"http://foo.com:1/", kPerm, 20}, + {"http://bar.com/", kTemp, 300}, {"https://buz.com/", kTemp, 4000}, + {"http://buz.com/", kTemp, 50000}, {"http://bar.com:1/", kPerm, 600000}, + {"http://foo.com/", kTemp, 7000000}, }; MockQuotaClient* client = @@ -1617,7 +1564,8 @@ TEST_F(QuotaManagerImplTest, GetUsage_WithModification) { EXPECT_EQ(usage(), 1 + 20 + 600000); EXPECT_EQ(0, unlimited_usage()); - client->ModifyOriginAndNotify(ToOrigin("http://foo.com/"), kPerm, 80000000); + client->ModifyStorageKeyAndNotify(ToStorageKey("http://foo.com/"), kPerm, + 80000000); GetGlobalUsage(kPerm); task_environment_.RunUntilIdle(); @@ -1629,7 +1577,7 @@ TEST_F(QuotaManagerImplTest, GetUsage_WithModification) { EXPECT_EQ(usage(), 300 + 4000 + 50000 + 7000000); EXPECT_EQ(0, unlimited_usage()); - client->ModifyOriginAndNotify(ToOrigin("http://foo.com/"), kTemp, 1); + client->ModifyStorageKeyAndNotify(ToStorageKey("http://foo.com/"), kTemp, 1); GetGlobalUsage(kTemp); task_environment_.RunUntilIdle(); @@ -1640,19 +1588,20 @@ TEST_F(QuotaManagerImplTest, GetUsage_WithModification) { task_environment_.RunUntilIdle(); EXPECT_EQ(usage(), 4000 + 50000); - client->ModifyOriginAndNotify(ToOrigin("http://buz.com/"), kTemp, 900000000); + client->ModifyStorageKeyAndNotify(ToStorageKey("http://buz.com/"), kTemp, + 900000000); GetHostUsageWithBreakdown("buz.com", kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(usage(), 4000 + 50000 + 900000000); } -TEST_F(QuotaManagerImplTest, GetUsage_WithDeleteOrigin) { - static const MockOriginData kData[] = { - { "http://foo.com/", kTemp, 1 }, - { "http://foo.com:1/", kTemp, 20 }, - { "http://foo.com/", kPerm, 300 }, - { "http://bar.com/", kTemp, 4000 }, +TEST_F(QuotaManagerImplTest, GetUsage_WithDeleteStorageKey) { + static const MockStorageKeyData kData[] = { + {"http://foo.com/", kTemp, 1}, + {"http://foo.com:1/", kTemp, 20}, + {"http://foo.com/", kPerm, 300}, + {"http://bar.com/", kTemp, 4000}, }; MockQuotaClient* client = CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, @@ -1671,7 +1620,7 @@ TEST_F(QuotaManagerImplTest, GetUsage_WithDeleteOrigin) { task_environment_.RunUntilIdle(); int64_t predelete_host_pers = usage(); - DeleteClientOriginData(client, ToOrigin("http://foo.com/"), kTemp); + DeleteClientStorageKeyData(client, ToStorageKey("http://foo.com/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); @@ -1695,23 +1644,21 @@ TEST_F(QuotaManagerImplTest, GetStorageCapacity) { EXPECT_LE(0, available_space()); } -TEST_F(QuotaManagerImplTest, EvictOriginData) { - static const MockOriginData kData1[] = { - { "http://foo.com/", kTemp, 1 }, - { "http://foo.com:1/", kTemp, 20 }, - { "http://foo.com/", kPerm, 300 }, - { "http://bar.com/", kTemp, 4000 }, +TEST_F(QuotaManagerImplTest, EvictBucketData) { + static const MockStorageKeyData kData1[] = { + {"http://foo.com/", kTemp, 1}, + {"http://foo.com:1/", kTemp, 20}, + {"http://foo.com/", kPerm, 300}, + {"http://bar.com/", kTemp, 4000}, }; - static const MockOriginData kData2[] = { - { "http://foo.com/", kTemp, 50000 }, - { "http://foo.com:1/", kTemp, 6000 }, - { "http://foo.com/", kPerm, 700 }, - { "https://foo.com/", kTemp, 80 }, - { "http://bar.com/", kTemp, 9 }, + static const MockStorageKeyData kData2[] = { + {"http://foo.com/", kTemp, 50000}, {"http://foo.com:1/", kTemp, 6000}, + {"http://foo.com/", kPerm, 700}, {"https://foo.com/", kTemp, 80}, + {"http://bar.com/", kTemp, 9}, }; - CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem, - {blink::mojom::StorageType::kTemporary, - blink::mojom::StorageType::kPersistent}); + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); CreateAndRegisterClient(kData2, QuotaClientType::kDatabase, {blink::mojom::StorageType::kTemporary, blink::mojom::StorageType::kPersistent}); @@ -1728,25 +1675,30 @@ TEST_F(QuotaManagerImplTest, EvictOriginData) { task_environment_.RunUntilIdle(); int64_t predelete_host_pers = usage(); - for (const MockOriginData& data : kData1) { - quota_manager_impl()->NotifyStorageAccessed(ToOrigin(data.origin), + for (const MockStorageKeyData& data : kData1) { + quota_manager_impl()->NotifyStorageAccessed(ToStorageKey(data.origin), data.type, base::Time::Now()); } - for (const MockOriginData& data : kData2) { - quota_manager_impl()->NotifyStorageAccessed(ToOrigin(data.origin), + for (const MockStorageKeyData& data : kData2) { + quota_manager_impl()->NotifyStorageAccessed(ToStorageKey(data.origin), data.type, base::Time::Now()); } task_environment_.RunUntilIdle(); - EvictOriginData(ToOrigin("http://foo.com/"), kTemp); + GetBucket(ToStorageKey("http://foo.com/"), kDefaultBucketName, kTemp); + ASSERT_TRUE(bucket_.ok()); + + EvictBucketData(bucket_.value()); task_environment_.RunUntilIdle(); DumpBucketTable(); task_environment_.RunUntilIdle(); for (const auto& entry : bucket_entries()) { - if (entry.type == kTemp) - EXPECT_NE(std::string("http://foo.com/"), entry.origin.GetURL().spec()); + if (entry.type == kTemp) { + EXPECT_NE(std::string("http://foo.com/"), + entry.storage_key.origin().GetURL().spec()); + } } GetGlobalUsage(kTemp); @@ -1762,9 +1714,71 @@ TEST_F(QuotaManagerImplTest, EvictOriginData) { EXPECT_EQ(predelete_host_pers, usage()); } -TEST_F(QuotaManagerImplTest, EvictOriginDataHistogram) { - const url::Origin kOrigin = ToOrigin("http://foo.com/"); - static const MockOriginData kData[] = { +TEST_F(QuotaManagerImplTest, EvictNonDefaultBucketData) { + static const MockStorageKeyData kData[] = {{"http://foo.com/", kTemp, 100}}; + CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, {kTemp}); + + GetGlobalUsage(kTemp); + task_environment_.RunUntilIdle(); + int64_t predelete_global_tmp = usage(); + + GetHostUsageWithBreakdown("foo.com", kTemp); + task_environment_.RunUntilIdle(); + int64_t predelete_host_tmp = usage(); + + StorageKey storage_key = ToStorageKey("http://foo.com/"); + quota_manager_impl()->NotifyStorageAccessed(storage_key, kTemp, + base::Time::Now()); + task_environment_.RunUntilIdle(); + + CreateBucketForTesting(storage_key, "foo_bucket", kTemp); + ASSERT_TRUE(bucket_.ok()); + BucketInfo created_bucket = bucket_.value(); + + EvictBucketData(created_bucket); + task_environment_.RunUntilIdle(); + + EXPECT_EQ(QuotaStatusCode::kOk, status()); + + DumpBucketTable(); + task_environment_.RunUntilIdle(); + + for (const auto& entry : bucket_entries()) { + if (entry.type == kTemp) + EXPECT_NE(created_bucket.id, entry.bucket_id); + } + + // Evicting non-default bucket should not change usage. + GetGlobalUsage(kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_global_tmp, usage()); + + GetHostUsageWithBreakdown("foo.com", kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_host_tmp, usage()); + + GetBucket(storage_key, kDefaultBucketName, kTemp); + ASSERT_TRUE(bucket_.ok()); + BucketInfo default_bucket = bucket_.value(); + + EvictBucketData(default_bucket); + task_environment_.RunUntilIdle(); + + EXPECT_EQ(QuotaStatusCode::kOk, status()); + + // Evicting default bucket should remove usage. + GetGlobalUsage(kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ(usage(), 0); + + GetHostUsageWithBreakdown("foo.com", kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ(usage(), 0); +} + +TEST_F(QuotaManagerImplTest, EvictBucketDataHistogram) { + const StorageKey kStorageKey = ToStorageKey("http://foo.com/"); + static const MockStorageKeyData kData[] = { {"http://foo.com/", kTemp, 1}, }; @@ -1776,66 +1790,50 @@ TEST_F(QuotaManagerImplTest, EvictOriginDataHistogram) { GetGlobalUsage(kTemp); task_environment_.RunUntilIdle(); - EvictOriginData(kOrigin, kTemp); + CreateBucketForTesting(kStorageKey, kDefaultBucketName, kTemp); + ASSERT_TRUE(bucket_.ok()); + + EvictBucketData(bucket_.value()); task_environment_.RunUntilIdle(); - // Ensure used count and time since access are recorded. + // Ensure use count and time since access are recorded. histograms.ExpectTotalCount( - QuotaManagerImpl::kEvictedOriginAccessedCountHistogram, 1); + QuotaManagerImpl::kEvictedBucketAccessedCountHistogram, 1); histograms.ExpectBucketCount( - QuotaManagerImpl::kEvictedOriginAccessedCountHistogram, 0, 1); - histograms.ExpectTotalCount( - QuotaManagerImpl::kEvictedOriginDaysSinceAccessHistogram, 1); - - // First eviction has no 'last' time to compare to. + QuotaManagerImpl::kEvictedBucketAccessedCountHistogram, 0, 1); histograms.ExpectTotalCount( - QuotaManagerImpl::kDaysBetweenRepeatedOriginEvictionsHistogram, 0); + QuotaManagerImpl::kEvictedBucketDaysSinceAccessHistogram, 1); - client->AddOriginAndNotify(kOrigin, kTemp, 100); + client->AddStorageKeyAndNotify(kStorageKey, kTemp, 100); - // Change the used count of the origin. - quota_manager_impl()->NotifyStorageAccessed(kOrigin, kTemp, + // Change the use count of the storage key. + quota_manager_impl()->NotifyStorageAccessed(kStorageKey, kTemp, base::Time::Now()); task_environment_.RunUntilIdle(); GetGlobalUsage(kTemp); task_environment_.RunUntilIdle(); - EvictOriginData(kOrigin, kTemp); + EvictBucketData(bucket_.value()); task_environment_.RunUntilIdle(); - // The new used count should be logged. + // The new use count should be logged. histograms.ExpectTotalCount( - QuotaManagerImpl::kEvictedOriginAccessedCountHistogram, 2); + QuotaManagerImpl::kEvictedBucketAccessedCountHistogram, 2); histograms.ExpectBucketCount( - QuotaManagerImpl::kEvictedOriginAccessedCountHistogram, 1, 1); - histograms.ExpectTotalCount( - QuotaManagerImpl::kEvictedOriginDaysSinceAccessHistogram, 2); - - // Second eviction should log a 'time between repeated eviction' sample. - histograms.ExpectTotalCount( - QuotaManagerImpl::kDaysBetweenRepeatedOriginEvictionsHistogram, 1); - - client->AddOriginAndNotify(kOrigin, kTemp, 100); - - GetGlobalUsage(kTemp); - task_environment_.RunUntilIdle(); - - DeleteOriginFromDatabase(kOrigin, kTemp); - - // Deletion from non-eviction source should not log a histogram sample. + QuotaManagerImpl::kEvictedBucketAccessedCountHistogram, 1, 1); histograms.ExpectTotalCount( - QuotaManagerImpl::kDaysBetweenRepeatedOriginEvictionsHistogram, 1); + QuotaManagerImpl::kEvictedBucketDaysSinceAccessHistogram, 2); } -TEST_F(QuotaManagerImplTest, EvictOriginDataWithDeletionError) { - static const MockOriginData kData[] = { - { "http://foo.com/", kTemp, 1 }, - { "http://foo.com:1/", kTemp, 20 }, - { "http://foo.com/", kPerm, 300 }, - { "http://bar.com/", kTemp, 4000 }, +TEST_F(QuotaManagerImplTest, EvictBucketDataWithDeletionError) { + static const MockStorageKeyData kData[] = { + {"http://foo.com/", kTemp, 1}, + {"http://foo.com:1/", kTemp, 20}, + {"http://foo.com/", kPerm, 300}, + {"http://bar.com/", kTemp, 4000}, }; - static const int kNumberOfTemporaryOrigins = 3; + static const int kNumberOfTemporaryBuckets = 3; MockQuotaClient* client = CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, {blink::mojom::StorageType::kTemporary, @@ -1853,15 +1851,18 @@ TEST_F(QuotaManagerImplTest, EvictOriginDataWithDeletionError) { task_environment_.RunUntilIdle(); int64_t predelete_host_pers = usage(); - for (const MockOriginData& data : kData) - NotifyStorageAccessed(ToOrigin(data.origin), data.type); + for (const MockStorageKeyData& data : kData) + NotifyStorageAccessed(ToStorageKey(data.origin), data.type); task_environment_.RunUntilIdle(); - client->AddOriginToErrorSet(ToOrigin("http://foo.com/"), kTemp); + client->AddStorageKeyToErrorSet(ToStorageKey("http://foo.com/"), kTemp); + + GetBucket(ToStorageKey("http://foo.com/"), kDefaultBucketName, kTemp); + ASSERT_TRUE(bucket_.ok()); for (int i = 0; i < QuotaManagerImpl::kThresholdOfErrorsToBeDenylisted + 1; ++i) { - EvictOriginData(ToOrigin("http://foo.com/"), kTemp); + EvictBucketData(bucket_.value()); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kErrorInvalidModification, status()); } @@ -1869,33 +1870,34 @@ TEST_F(QuotaManagerImplTest, EvictOriginDataWithDeletionError) { DumpBucketTable(); task_environment_.RunUntilIdle(); - bool found_origin_in_database = false; + bool found_storage_key_in_database = false; for (const auto& entry : bucket_entries()) { - if (entry.type == kTemp && entry.origin == ToOrigin("http://foo.com/")) { - found_origin_in_database = true; + if (entry.type == kTemp && entry.name == kDefaultBucketName && + entry.storage_key == ToStorageKey("http://foo.com/")) { + found_storage_key_in_database = true; break; } } - // The origin "http://foo.com/" should be in the database. - EXPECT_TRUE(found_origin_in_database); + // The default bucket for "http://foo.com/" should be in the database. + EXPECT_TRUE(found_storage_key_in_database); - for (size_t i = 0; i < kNumberOfTemporaryOrigins - 1; ++i) { - GetEvictionOrigin(kTemp); + for (size_t i = 0; i < kNumberOfTemporaryBuckets - 1; ++i) { + GetEvictionBucket(kTemp); task_environment_.RunUntilIdle(); - EXPECT_TRUE(eviction_origin().has_value()); - // The origin "http://foo.com/" should not be in the LRU list. + EXPECT_TRUE(eviction_bucket().has_value()); + // "http://foo.com/" should not be in the LRU list. EXPECT_NE(std::string("http://foo.com/"), - eviction_origin()->GetURL().spec()); - DeleteOriginFromDatabase(*eviction_origin(), kTemp); + eviction_bucket()->storage_key.origin().GetURL().spec()); + DeleteBucketFromDatabase(eviction_bucket()->id); task_environment_.RunUntilIdle(); } // Now the LRU list must be empty. - GetEvictionOrigin(kTemp); + GetEvictionBucket(kTemp); task_environment_.RunUntilIdle(); - EXPECT_FALSE(eviction_origin().has_value()); + EXPECT_FALSE(eviction_bucket().has_value()); - // Deleting origins from the database should not affect the results of the + // Deleting buckets from the database should not affect the results of the // following checks. GetGlobalUsage(kTemp); task_environment_.RunUntilIdle(); @@ -1911,11 +1913,11 @@ TEST_F(QuotaManagerImplTest, EvictOriginDataWithDeletionError) { } TEST_F(QuotaManagerImplTest, GetEvictionRoundInfo) { - static const MockOriginData kData[] = { - { "http://foo.com/", kTemp, 1 }, - { "http://foo.com:1/", kTemp, 20 }, - { "http://foo.com/", kPerm, 300 }, - { "http://unlimited/", kTemp, 4000 }, + static const MockStorageKeyData kData[] = { + {"http://foo.com/", kTemp, 1}, + {"http://foo.com:1/", kTemp, 20}, + {"http://foo.com/", kPerm, 300}, + {"http://unlimited/", kTemp, 4000}, }; mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/")); @@ -1942,8 +1944,8 @@ TEST_F(QuotaManagerImplTest, DeleteHostDataNoClients) { } TEST_F(QuotaManagerImplTest, DeleteHostDataSimple) { - static const MockOriginData kData[] = { - { "http://foo.com/", kTemp, 1 }, + static const MockStorageKeyData kData[] = { + {"http://foo.com/", kTemp, 1}, }; CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, {blink::mojom::StorageType::kTemporary, @@ -1995,22 +1997,20 @@ TEST_F(QuotaManagerImplTest, DeleteHostDataSimple) { } TEST_F(QuotaManagerImplTest, DeleteHostDataMultiple) { - static const MockOriginData kData1[] = { - { "http://foo.com/", kTemp, 1 }, - { "http://foo.com:1/", kTemp, 20 }, - { "http://foo.com/", kPerm, 300 }, - { "http://bar.com/", kTemp, 4000 }, - }; - static const MockOriginData kData2[] = { - { "http://foo.com/", kTemp, 50000 }, - { "http://foo.com:1/", kTemp, 6000 }, - { "http://foo.com/", kPerm, 700 }, - { "https://foo.com/", kTemp, 80 }, - { "http://bar.com/", kTemp, 9 }, - }; - CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem, - {blink::mojom::StorageType::kTemporary, - blink::mojom::StorageType::kPersistent}); + static const MockStorageKeyData kData1[] = { + {"http://foo.com/", kTemp, 1}, + {"http://foo.com:1/", kTemp, 20}, + {"http://foo.com/", kPerm, 300}, + {"http://bar.com/", kTemp, 4000}, + }; + static const MockStorageKeyData kData2[] = { + {"http://foo.com/", kTemp, 50000}, {"http://foo.com:1/", kTemp, 6000}, + {"http://foo.com/", kPerm, 700}, {"https://foo.com/", kTemp, 80}, + {"http://bar.com/", kTemp, 9}, + }; + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); CreateAndRegisterClient(kData2, QuotaClientType::kDatabase, {blink::mojom::StorageType::kTemporary, blink::mojom::StorageType::kPersistent}); @@ -2050,10 +2050,14 @@ TEST_F(QuotaManagerImplTest, DeleteHostDataMultiple) { 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()); + EXPECT_NE(std::string("http://foo.com/"), + entry.storage_key.origin().GetURL().spec()); + EXPECT_NE(std::string("http://foo.com:1/"), + entry.storage_key.origin().GetURL().spec()); + EXPECT_NE(std::string("https://foo.com/"), + entry.storage_key.origin().GetURL().spec()); + EXPECT_NE(std::string("http://bar.com/"), + entry.storage_key.origin().GetURL().spec()); } GetGlobalUsage(kTemp); @@ -2079,21 +2083,21 @@ TEST_F(QuotaManagerImplTest, DeleteHostDataMultiple) { } TEST_F(QuotaManagerImplTest, DeleteHostDataMultipleClientsDifferentTypes) { - static const MockOriginData kData1[] = { + static const MockStorageKeyData 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[] = { + static const MockStorageKeyData kData2[] = { {"http://foo.com/", kTemp, 10000}, {"http://foo.com:1/", kTemp, 100000}, {"https://foo.com/", kTemp, 1000000}, {"http://bar.com/", kTemp, 10000000}, }; - CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem, - {blink::mojom::StorageType::kTemporary, - blink::mojom::StorageType::kPersistent}); + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); CreateAndRegisterClient(kData2, QuotaClientType::kDatabase, {blink::mojom::StorageType::kTemporary}); @@ -2135,10 +2139,14 @@ TEST_F(QuotaManagerImplTest, DeleteHostDataMultipleClientsDifferentTypes) { 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()); + EXPECT_NE(std::string("http://foo.com/"), + entry.storage_key.origin().GetURL().spec()); + EXPECT_NE(std::string("http://foo.com:1/"), + entry.storage_key.origin().GetURL().spec()); + EXPECT_NE(std::string("https://foo.com/"), + entry.storage_key.origin().GetURL().spec()); + EXPECT_NE(std::string("http://bar.com/"), + entry.storage_key.origin().GetURL().spec()); } GetGlobalUsage(kTemp); @@ -2166,31 +2174,28 @@ TEST_F(QuotaManagerImplTest, DeleteHostDataMultipleClientsDifferentTypes) { EXPECT_EQ(predelete_bar_pers - 1000, usage()); } -TEST_F(QuotaManagerImplTest, DeleteOriginDataNoClients) { - DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, AllQuotaClientTypes()); +TEST_F(QuotaManagerImplTest, DeleteStorageKeyDataNoClients) { + DeleteStorageKeyData(ToStorageKey("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(QuotaManagerImplTest, DeleteOriginDataMultiple) { - static const MockOriginData kData1[] = { - { "http://foo.com/", kTemp, 1 }, - { "http://foo.com:1/", kTemp, 20 }, - { "http://foo.com/", kPerm, 300 }, - { "http://bar.com/", kTemp, 4000 }, +TEST_F(QuotaManagerImplTest, DeleteStorageKeyDataMultiple) { + static const MockStorageKeyData kData1[] = { + {"http://foo.com/", kTemp, 1}, + {"http://foo.com:1/", kTemp, 20}, + {"http://foo.com/", kPerm, 300}, + {"http://bar.com/", kTemp, 4000}, }; - static const MockOriginData kData2[] = { - { "http://foo.com/", kTemp, 50000 }, - { "http://foo.com:1/", kTemp, 6000 }, - { "http://foo.com/", kPerm, 700 }, - { "https://foo.com/", kTemp, 80 }, - { "http://bar.com/", kTemp, 9 }, + static const MockStorageKeyData kData2[] = { + {"http://foo.com/", kTemp, 50000}, {"http://foo.com:1/", kTemp, 6000}, + {"http://foo.com/", kPerm, 700}, {"https://foo.com/", kTemp, 80}, + {"http://bar.com/", kTemp, 9}, }; - CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem, - {blink::mojom::StorageType::kTemporary, - blink::mojom::StorageType::kPersistent}); + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); CreateAndRegisterClient(kData2, QuotaClientType::kDatabase, {blink::mojom::StorageType::kTemporary, blink::mojom::StorageType::kPersistent}); @@ -2215,20 +2220,23 @@ TEST_F(QuotaManagerImplTest, DeleteOriginDataMultiple) { task_environment_.RunUntilIdle(); const int64_t predelete_bar_pers = usage(); - for (const MockOriginData& data : kData1) { - quota_manager_impl()->NotifyStorageAccessed(ToOrigin(data.origin), + for (const MockStorageKeyData& data : kData1) { + quota_manager_impl()->NotifyStorageAccessed(ToStorageKey(data.origin), data.type, base::Time::Now()); } - for (const MockOriginData& data : kData2) { - quota_manager_impl()->NotifyStorageAccessed(ToOrigin(data.origin), + for (const MockStorageKeyData& data : kData2) { + quota_manager_impl()->NotifyStorageAccessed(ToStorageKey(data.origin), data.type, base::Time::Now()); } task_environment_.RunUntilIdle(); reset_status_callback_count(); - DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, AllQuotaClientTypes()); - DeleteOriginData(ToOrigin("http://bar.com/"), kTemp, AllQuotaClientTypes()); - DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, AllQuotaClientTypes()); + DeleteStorageKeyData(ToStorageKey("http://foo.com/"), kTemp, + AllQuotaClientTypes()); + DeleteStorageKeyData(ToStorageKey("http://bar.com/"), kTemp, + AllQuotaClientTypes()); + DeleteStorageKeyData(ToStorageKey("http://foo.com/"), kTemp, + AllQuotaClientTypes()); task_environment_.RunUntilIdle(); EXPECT_EQ(3, status_callback_count()); @@ -2240,8 +2248,10 @@ TEST_F(QuotaManagerImplTest, DeleteOriginDataMultiple) { if (entry.type != kTemp) continue; - EXPECT_NE(std::string("http://foo.com/"), entry.origin.GetURL().spec()); - EXPECT_NE(std::string("http://bar.com/"), entry.origin.GetURL().spec()); + EXPECT_NE(std::string("http://foo.com/"), + entry.storage_key.origin().GetURL().spec()); + EXPECT_NE(std::string("http://bar.com/"), + entry.storage_key.origin().GetURL().spec()); } GetGlobalUsage(kTemp); @@ -2265,22 +2275,23 @@ TEST_F(QuotaManagerImplTest, DeleteOriginDataMultiple) { EXPECT_EQ(predelete_bar_pers, usage()); } -TEST_F(QuotaManagerImplTest, DeleteOriginDataMultipleClientsDifferentTypes) { - static const MockOriginData kData1[] = { +TEST_F(QuotaManagerImplTest, + DeleteStorageKeyDataMultipleClientsDifferentTypes) { + static const MockStorageKeyData 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[] = { + static const MockStorageKeyData kData2[] = { {"http://foo.com/", kTemp, 10000}, {"http://foo.com:1/", kTemp, 100000}, {"https://foo.com/", kTemp, 1000000}, {"http://bar.com/", kTemp, 10000000}, }; - CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem, - {blink::mojom::StorageType::kTemporary, - blink::mojom::StorageType::kPersistent}); + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); CreateAndRegisterClient(kData2, QuotaClientType::kDatabase, {blink::mojom::StorageType::kTemporary}); @@ -2308,19 +2319,21 @@ TEST_F(QuotaManagerImplTest, DeleteOriginDataMultipleClientsDifferentTypes) { task_environment_.RunUntilIdle(); const int64_t predelete_bar_pers = usage(); - for (const MockOriginData& data : kData1) { - quota_manager_impl()->NotifyStorageAccessed(ToOrigin(data.origin), + for (const MockStorageKeyData& data : kData1) { + quota_manager_impl()->NotifyStorageAccessed(ToStorageKey(data.origin), data.type, base::Time::Now()); } - for (const MockOriginData& data : kData2) { - quota_manager_impl()->NotifyStorageAccessed(ToOrigin(data.origin), + for (const MockStorageKeyData& data : kData2) { + quota_manager_impl()->NotifyStorageAccessed(ToStorageKey(data.origin), data.type, base::Time::Now()); } task_environment_.RunUntilIdle(); reset_status_callback_count(); - DeleteOriginData(ToOrigin("http://foo.com/"), kPerm, AllQuotaClientTypes()); - DeleteOriginData(ToOrigin("http://bar.com/"), kPerm, AllQuotaClientTypes()); + DeleteStorageKeyData(ToStorageKey("http://foo.com/"), kPerm, + AllQuotaClientTypes()); + DeleteStorageKeyData(ToStorageKey("http://bar.com/"), kPerm, + AllQuotaClientTypes()); task_environment_.RunUntilIdle(); EXPECT_EQ(2, status_callback_count()); @@ -2332,8 +2345,10 @@ TEST_F(QuotaManagerImplTest, DeleteOriginDataMultipleClientsDifferentTypes) { 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()); + EXPECT_NE(std::string("http://foo.com/"), + entry.storage_key.origin().GetURL().spec()); + EXPECT_NE(std::string("http://bar.com/"), + entry.storage_key.origin().GetURL().spec()); } GetGlobalUsage(kTemp); @@ -2361,198 +2376,420 @@ TEST_F(QuotaManagerImplTest, DeleteOriginDataMultipleClientsDifferentTypes) { EXPECT_EQ(predelete_bar_pers - 1000, usage()); } -TEST_F(QuotaManagerImplTest, GetCachedOrigins) { - static const MockOriginData kData[] = { - { "http://a.com/", kTemp, 1 }, - { "http://a.com:1/", kTemp, 20 }, - { "http://b.com/", kPerm, 300 }, - { "http://c.com/", kTemp, 4000 }, +TEST_F(QuotaManagerImplTest, DeleteBucketNoClients) { + CreateBucketForTesting(ToStorageKey("http://foo.com"), kDefaultBucketName, + kTemp); + ASSERT_TRUE(bucket_.ok()); + + DeleteBucketData(bucket_.value(), AllQuotaClientTypes()); + task_environment_.RunUntilIdle(); + EXPECT_EQ(QuotaStatusCode::kOk, status()); +} + +TEST_F(QuotaManagerImplTest, DeleteBucketDataMultiple) { + static const MockStorageKeyData kData1[] = { + {"http://foo.com/", kTemp, 1}, + {"http://foo.com:1/", kTemp, 20}, + {"http://foo.com/", kPerm, 300}, + {"http://bar.com/", kTemp, 4000}, }; - CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, + static const MockStorageKeyData kData2[] = { + {"http://foo.com/", kTemp, 50000}, {"http://foo.com:1/", kTemp, 6000}, + {"http://foo.com/", kPerm, 700}, {"https://foo.com/", kTemp, 80}, + {"http://bar.com/", kTemp, 9}, + }; + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary, + blink::mojom::StorageType::kPersistent}); + CreateAndRegisterClient(kData2, QuotaClientType::kDatabase, {blink::mojom::StorageType::kTemporary, blink::mojom::StorageType::kPersistent}); - // TODO(kinuko): Be careful when we add cache pruner. + CreateBucketForTesting(ToStorageKey("http://foo.com"), kDefaultBucketName, + kTemp); + ASSERT_TRUE(bucket_.ok()); + BucketInfo foo_temp_bucket = bucket_.value(); - std::set<url::Origin> origins = GetCachedOrigins(kTemp); - EXPECT_TRUE(origins.empty()); + CreateBucketForTesting(ToStorageKey("http://bar.com"), kDefaultBucketName, + kTemp); + ASSERT_TRUE(bucket_.ok()); + BucketInfo bar_temp_bucket = bucket_.value(); - GetHostUsageWithBreakdown("a.com", kTemp); + GetGlobalUsage(kTemp); task_environment_.RunUntilIdle(); - origins = GetCachedOrigins(kTemp); - EXPECT_EQ(2U, origins.size()); + const int64_t predelete_global_tmp = usage(); - GetHostUsageWithBreakdown("b.com", kTemp); + GetHostUsageWithBreakdown("foo.com", kTemp); task_environment_.RunUntilIdle(); - origins = GetCachedOrigins(kTemp); - EXPECT_EQ(2U, origins.size()); + const int64_t predelete_foo_tmp = usage(); - GetHostUsageWithBreakdown("c.com", kTemp); + GetHostUsageWithBreakdown("bar.com", kTemp); + task_environment_.RunUntilIdle(); + const int64_t predelete_bar_tmp = usage(); + + GetHostUsageWithBreakdown("foo.com", kPerm); task_environment_.RunUntilIdle(); - origins = GetCachedOrigins(kTemp); - EXPECT_EQ(3U, origins.size()); + const int64_t predelete_foo_pers = usage(); - origins = GetCachedOrigins(kPerm); - EXPECT_TRUE(origins.empty()); + GetHostUsageWithBreakdown("bar.com", kPerm); + task_environment_.RunUntilIdle(); + const int64_t predelete_bar_pers = usage(); + + for (const MockStorageKeyData& data : kData1) { + quota_manager_impl()->NotifyStorageAccessed(ToStorageKey(data.origin), + data.type, base::Time::Now()); + } + for (const MockStorageKeyData& data : kData2) { + quota_manager_impl()->NotifyStorageAccessed(ToStorageKey(data.origin), + data.type, base::Time::Now()); + } + task_environment_.RunUntilIdle(); + + reset_status_callback_count(); + DeleteBucketData(foo_temp_bucket, AllQuotaClientTypes()); + DeleteBucketData(bar_temp_bucket, AllQuotaClientTypes()); + DeleteBucketData(foo_temp_bucket, AllQuotaClientTypes()); + task_environment_.RunUntilIdle(); + + EXPECT_EQ(3, status_callback_count()); + + DumpBucketTable(); + task_environment_.RunUntilIdle(); + + for (const auto& entry : bucket_entries()) { + if (entry.type != kTemp) + continue; + + EXPECT_NE(std::string("http://foo.com/"), + entry.storage_key.origin().GetURL().spec()); + EXPECT_NE(std::string("http://bar.com/"), + entry.storage_key.origin().GetURL().spec()); + } GetGlobalUsage(kTemp); task_environment_.RunUntilIdle(); - origins = GetCachedOrigins(kTemp); - EXPECT_EQ(3U, origins.size()); + EXPECT_EQ(predelete_global_tmp - (1 + 4000 + 50000 + 9), usage()); + + GetHostUsageWithBreakdown("foo.com", kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_foo_tmp - (1 + 50000), usage()); - for (const MockOriginData& data : kData) { - if (data.type == kTemp) - EXPECT_TRUE(base::Contains(origins, ToOrigin(data.origin))); + GetHostUsageWithBreakdown("bar.com", kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_bar_tmp - (4000 + 9), usage()); + + GetHostUsageWithBreakdown("foo.com", kPerm); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_foo_pers, usage()); + + GetHostUsageWithBreakdown("bar.com", kPerm); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_bar_pers, usage()); +} + +TEST_F(QuotaManagerImplTest, DeleteBucketDataMultipleClientsDifferentTypes) { + static const MockStorageKeyData kData1[] = { + {"http://foo.com/", kPerm, 1}, + {"http://foo.com:1/", kPerm, 10}, + {"http://foo.com/", kTemp, 100}, + {"http://bar.com/", kPerm, 1000}, + }; + static const MockStorageKeyData 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}); + + CreateBucketForTesting(ToStorageKey("http://foo.com/"), kDefaultBucketName, + kPerm); + ASSERT_TRUE(bucket_.ok()); + BucketInfo foo_perm_bucket = bucket_.value(); + + CreateBucketForTesting(ToStorageKey("http://bar.com/"), kDefaultBucketName, + kPerm); + ASSERT_TRUE(bucket_.ok()); + BucketInfo bar_perm_bucket = bucket_.value(); + + GetGlobalUsage(kTemp); + task_environment_.RunUntilIdle(); + const int64_t predelete_global_tmp = usage(); + + GetHostUsageWithBreakdown("foo.com", kTemp); + task_environment_.RunUntilIdle(); + const int64_t predelete_foo_tmp = usage(); + + GetHostUsageWithBreakdown("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(); + + GetHostUsageWithBreakdown("foo.com", kPerm); + task_environment_.RunUntilIdle(); + const int64_t predelete_foo_pers = usage(); + + GetHostUsageWithBreakdown("bar.com", kPerm); + task_environment_.RunUntilIdle(); + const int64_t predelete_bar_pers = usage(); + + for (const MockStorageKeyData& data : kData1) { + quota_manager_impl()->NotifyStorageAccessed(ToStorageKey(data.origin), + data.type, base::Time::Now()); + } + for (const MockStorageKeyData& data : kData2) { + quota_manager_impl()->NotifyStorageAccessed(ToStorageKey(data.origin), + data.type, base::Time::Now()); + } + task_environment_.RunUntilIdle(); + + reset_status_callback_count(); + DeleteBucketData(foo_perm_bucket, AllQuotaClientTypes()); + DeleteBucketData(bar_perm_bucket, AllQuotaClientTypes()); + task_environment_.RunUntilIdle(); + + EXPECT_EQ(2, status_callback_count()); + + DumpBucketTable(); + task_environment_.RunUntilIdle(); + + for (const auto& entry : bucket_entries()) { + if (entry.type != kPerm) + continue; + + EXPECT_NE(std::string("http://foo.com/"), + entry.storage_key.origin().GetURL().spec()); + EXPECT_NE(std::string("http://bar.com/"), + entry.storage_key.origin().GetURL().spec()); } + + GetGlobalUsage(kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_global_tmp, usage()); + + GetHostUsageWithBreakdown("foo.com", kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_foo_tmp, usage()); + + GetHostUsageWithBreakdown("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()); + + GetHostUsageWithBreakdown("foo.com", kPerm); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_foo_pers - 1, usage()); + + GetHostUsageWithBreakdown("bar.com", kPerm); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_bar_pers - 1000, usage()); } -TEST_F(QuotaManagerImplTest, NotifyAndLRUOrigin) { - static const MockOriginData kData[] = { - { "http://a.com/", kTemp, 0 }, - { "http://a.com:1/", kTemp, 0 }, - { "https://a.com/", kTemp, 0 }, - { "http://b.com/", kPerm, 0 }, // persistent - { "http://c.com/", kTemp, 0 }, +TEST_F(QuotaManagerImplTest, GetCachedStorageKeys) { + static const MockStorageKeyData kData[] = { + {"http://a.com/", kTemp, 1}, + {"http://a.com:1/", kTemp, 20}, + {"http://b.com/", kPerm, 300}, + {"http://c.com/", kTemp, 4000}, }; CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, {blink::mojom::StorageType::kTemporary, blink::mojom::StorageType::kPersistent}); - GURL origin; - GetEvictionOrigin(kTemp); - task_environment_.RunUntilIdle(); - EXPECT_FALSE(eviction_origin().has_value()); + // TODO(kinuko): Be careful when we add cache pruner. + + std::set<StorageKey> storage_keys = GetCachedStorageKeys(kTemp); + EXPECT_TRUE(storage_keys.empty()); - NotifyStorageAccessed(ToOrigin("http://a.com/"), kTemp); - GetEvictionOrigin(kTemp); + GetHostUsageWithBreakdown("a.com", kTemp); task_environment_.RunUntilIdle(); - EXPECT_EQ("http://a.com/", eviction_origin()->GetURL().spec()); + storage_keys = GetCachedStorageKeys(kTemp); + EXPECT_EQ(2U, storage_keys.size()); - NotifyStorageAccessed(ToOrigin("http://b.com/"), kPerm); - NotifyStorageAccessed(ToOrigin("https://a.com/"), kTemp); - NotifyStorageAccessed(ToOrigin("http://c.com/"), kTemp); - GetEvictionOrigin(kTemp); + GetHostUsageWithBreakdown("b.com", kTemp); task_environment_.RunUntilIdle(); - EXPECT_EQ("http://a.com/", eviction_origin()->GetURL().spec()); + storage_keys = GetCachedStorageKeys(kTemp); + EXPECT_EQ(2U, storage_keys.size()); - DeleteOriginFromDatabase(*eviction_origin(), kTemp); - GetEvictionOrigin(kTemp); + GetHostUsageWithBreakdown("c.com", kTemp); task_environment_.RunUntilIdle(); - EXPECT_EQ("https://a.com/", eviction_origin()->GetURL().spec()); + storage_keys = GetCachedStorageKeys(kTemp); + EXPECT_EQ(3U, storage_keys.size()); + + storage_keys = GetCachedStorageKeys(kPerm); + EXPECT_TRUE(storage_keys.empty()); - DeleteOriginFromDatabase(*eviction_origin(), kTemp); - GetEvictionOrigin(kTemp); + GetGlobalUsage(kTemp); task_environment_.RunUntilIdle(); - EXPECT_EQ("http://c.com/", eviction_origin()->GetURL().spec()); + storage_keys = GetCachedStorageKeys(kTemp); + EXPECT_THAT(storage_keys, + testing::UnorderedElementsAre(ToStorageKey("http://a.com"), + ToStorageKey("http://c.com"), + ToStorageKey("http://a.com:1"))); } -TEST_F(QuotaManagerImplTest, GetLRUOriginWithOriginInUse) { - static const MockOriginData kData[] = { - { "http://a.com/", kTemp, 0 }, - { "http://a.com:1/", kTemp, 0 }, - { "https://a.com/", kTemp, 0 }, - { "http://b.com/", kPerm, 0 }, // persistent - { "http://c.com/", kTemp, 0 }, +TEST_F(QuotaManagerImplTest, NotifyAndLRUBucket) { + static const MockStorageKeyData kData[] = { + {"http://a.com/", kTemp, 0}, {"http://a.com:1/", kTemp, 0}, + {"https://a.com/", kTemp, 0}, {"http://b.com/", kPerm, 0}, // persistent + {"http://c.com/", kTemp, 0}, }; CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, {blink::mojom::StorageType::kTemporary, blink::mojom::StorageType::kPersistent}); - GURL origin; - GetEvictionOrigin(kTemp); + GetEvictionBucket(kTemp); task_environment_.RunUntilIdle(); - EXPECT_FALSE(eviction_origin().has_value()); + EXPECT_FALSE(eviction_bucket().has_value()); - NotifyStorageAccessed(ToOrigin("http://a.com/"), kTemp); - NotifyStorageAccessed(ToOrigin("http://b.com/"), kPerm); - NotifyStorageAccessed(ToOrigin("https://a.com/"), kTemp); - NotifyStorageAccessed(ToOrigin("http://c.com/"), kTemp); + NotifyStorageAccessed(ToStorageKey("http://a.com/"), kTemp); + GetEvictionBucket(kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ("http://a.com/", + eviction_bucket()->storage_key.origin().GetURL().spec()); - GetEvictionOrigin(kTemp); + NotifyStorageAccessed(ToStorageKey("http://b.com/"), kPerm); + NotifyStorageAccessed(ToStorageKey("https://a.com/"), kTemp); + NotifyStorageAccessed(ToStorageKey("http://c.com/"), kTemp); + GetEvictionBucket(kTemp); task_environment_.RunUntilIdle(); - EXPECT_EQ(ToOrigin("http://a.com/"), *eviction_origin()); + EXPECT_EQ("http://a.com/", + eviction_bucket()->storage_key.origin().GetURL().spec()); - // Notify origin http://a.com is in use. - NotifyOriginInUse(ToOrigin("http://a.com/")); - GetEvictionOrigin(kTemp); + DeleteBucketFromDatabase(eviction_bucket()->id); + GetEvictionBucket(kTemp); task_environment_.RunUntilIdle(); - EXPECT_EQ(ToOrigin("https://a.com/"), *eviction_origin()); + EXPECT_EQ("https://a.com/", + eviction_bucket()->storage_key.origin().GetURL().spec()); - // Notify origin https://a.com is in use while GetEvictionOrigin is running. - GetEvictionOrigin(kTemp); - NotifyOriginInUse(ToOrigin("https://a.com/")); + DeleteBucketFromDatabase(eviction_bucket()->id); + GetEvictionBucket(kTemp); task_environment_.RunUntilIdle(); - // Post-filtering must have excluded the returned origin, so we will - // see empty result here. - EXPECT_FALSE(eviction_origin().has_value()); + EXPECT_EQ("http://c.com/", + eviction_bucket()->storage_key.origin().GetURL().spec()); +} + +TEST_F(QuotaManagerImplTest, GetLRUBucket) { + StorageKey storage_key_a = ToStorageKey("http://a.com/"); + StorageKey storage_key_b = ToStorageKey("http://b.com/"); + StorageKey storage_key_c = ToStorageKey("http://c.com/"); + + CreateBucketForTesting(storage_key_a, kDefaultBucketName, kTemp); + ASSERT_TRUE(bucket_.ok()); + BucketInfo bucket_a = bucket_.value(); + + CreateBucketForTesting(storage_key_b, kDefaultBucketName, kTemp); + ASSERT_TRUE(bucket_.ok()); + BucketInfo bucket_b = bucket_.value(); + + // Persistent bucket. + CreateBucketForTesting(storage_key_c, kDefaultBucketName, kPerm); + ASSERT_TRUE(bucket_.ok()); + BucketInfo bucket_c = bucket_.value(); - // Notify access for http://c.com while GetEvictionOrigin is running. - GetEvictionOrigin(kTemp); - NotifyStorageAccessed(ToOrigin("http://c.com/"), kTemp); + NotifyBucketAccessed(bucket_a.id); + NotifyBucketAccessed(bucket_b.id); + NotifyBucketAccessed(bucket_c.id); + + GetEvictionBucket(kTemp); task_environment_.RunUntilIdle(); - // Post-filtering must have excluded the returned origin, so we will - // see empty result here. - EXPECT_FALSE(eviction_origin().has_value()); + EXPECT_EQ(bucket_a, eviction_bucket()); + + // Notify that the `bucket_a` is accessed. + NotifyBucketAccessed(bucket_a.id); + GetEvictionBucket(kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ(bucket_b, eviction_bucket()); - NotifyOriginNoLongerInUse(ToOrigin("http://a.com/")); - NotifyOriginNoLongerInUse(ToOrigin("https://a.com/")); - GetEvictionOrigin(kTemp); + // Notify that the `bucket_b` is accessed while GetEvictionBucket is running. + GetEvictionBucket(kTemp); + NotifyBucketAccessed(bucket_b.id); task_environment_.RunUntilIdle(); - EXPECT_EQ(ToOrigin("http://a.com/"), *eviction_origin()); + // Post-filtering must have excluded the returned storage key, so we will + // see empty result here. + EXPECT_FALSE(eviction_bucket().has_value()); } -TEST_F(QuotaManagerImplTest, GetOriginsModifiedBetween) { - static const MockOriginData kData[] = { - { "http://a.com/", kTemp, 0 }, - { "http://a.com:1/", kTemp, 0 }, - { "https://a.com/", kTemp, 0 }, - { "http://b.com/", kPerm, 0 }, // persistent - { "http://c.com/", kTemp, 0 }, +TEST_F(QuotaManagerImplTest, GetBucketsModifiedBetween) { + static const MockStorageKeyData kData[] = { + {"http://a.com/", kTemp, 0}, {"http://a.com:1/", kTemp, 0}, + {"https://a.com/", kTemp, 0}, {"http://b.com/", kPerm, 0}, // persistent + {"http://c.com/", kTemp, 0}, }; MockQuotaClient* client = CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, {blink::mojom::StorageType::kTemporary, blink::mojom::StorageType::kPersistent}); - GetOriginsModifiedBetween(kTemp, base::Time(), base::Time::Max()); + GetBucketsModifiedBetween(kTemp, base::Time(), base::Time::Max()); task_environment_.RunUntilIdle(); - EXPECT_TRUE(modified_origins().empty()); - EXPECT_EQ(modified_origins_type(), kTemp); + EXPECT_TRUE(modified_buckets().empty()); + EXPECT_EQ(modified_buckets_type(), kTemp); base::Time time1 = client->IncrementMockTime(); - client->ModifyOriginAndNotify(ToOrigin("http://a.com/"), kTemp, 10); - client->ModifyOriginAndNotify(ToOrigin("http://a.com:1/"), kTemp, 10); - client->ModifyOriginAndNotify(ToOrigin("http://b.com/"), kPerm, 10); + client->ModifyStorageKeyAndNotify(ToStorageKey("http://a.com/"), kTemp, 10); + client->ModifyStorageKeyAndNotify(ToStorageKey("http://a.com:1/"), kTemp, 10); + client->ModifyStorageKeyAndNotify(ToStorageKey("http://b.com/"), kPerm, 10); base::Time time2 = client->IncrementMockTime(); - client->ModifyOriginAndNotify(ToOrigin("https://a.com/"), kTemp, 10); - client->ModifyOriginAndNotify(ToOrigin("http://c.com/"), kTemp, 10); + client->ModifyStorageKeyAndNotify(ToStorageKey("https://a.com/"), kTemp, 10); + client->ModifyStorageKeyAndNotify(ToStorageKey("http://c.com/"), kTemp, 10); base::Time time3 = client->IncrementMockTime(); - GetOriginsModifiedBetween(kTemp, time1, base::Time::Max()); + GetBucketsModifiedBetween(kTemp, time1, base::Time::Max()); task_environment_.RunUntilIdle(); - EXPECT_EQ(4U, modified_origins().size()); - EXPECT_EQ(modified_origins_type(), kTemp); - for (const MockOriginData& data : kData) { - if (data.type == kTemp) - EXPECT_EQ(1U, modified_origins().count(ToOrigin(data.origin))); - } + EXPECT_EQ(modified_buckets_type(), kTemp); + EXPECT_THAT(modified_buckets(), + testing::UnorderedElementsAre( + testing::Field(&BucketInfo::storage_key, + ToStorageKey("http://a.com")), + testing::Field(&BucketInfo::storage_key, + ToStorageKey("http://a.com:1")), + testing::Field(&BucketInfo::storage_key, + ToStorageKey("https://a.com")), + testing::Field(&BucketInfo::storage_key, + ToStorageKey("http://c.com")))); + + GetBucketsModifiedBetween(kTemp, time2, base::Time::Max()); + task_environment_.RunUntilIdle(); + EXPECT_EQ(2U, modified_buckets().size()); - GetOriginsModifiedBetween(kTemp, time2, base::Time::Max()); + GetBucketsModifiedBetween(kTemp, time3, base::Time::Max()); task_environment_.RunUntilIdle(); - EXPECT_EQ(2U, modified_origins().size()); + EXPECT_TRUE(modified_buckets().empty()); + EXPECT_EQ(modified_buckets_type(), kTemp); - GetOriginsModifiedBetween(kTemp, time3, base::Time::Max()); + client->ModifyStorageKeyAndNotify(ToStorageKey("http://a.com/"), kTemp, 10); + + GetBucketsModifiedBetween(kTemp, time3, base::Time::Max()); task_environment_.RunUntilIdle(); - EXPECT_TRUE(modified_origins().empty()); - EXPECT_EQ(modified_origins_type(), kTemp); + EXPECT_THAT(modified_buckets(), + testing::UnorderedElementsAre(testing::Field( + &BucketInfo::storage_key, ToStorageKey("http://a.com/")))); + EXPECT_EQ(modified_buckets_type(), kTemp); +} - client->ModifyOriginAndNotify(ToOrigin("http://a.com/"), kTemp, 10); +TEST_F(QuotaManagerImplTest, GetBucketsModifiedBetweenWithDatabaseError) { + OpenDatabase(); - GetOriginsModifiedBetween(kTemp, time3, base::Time::Max()); + // Disable quota database for database error behavior. + disable_quota_database(true); + + GetBucketsModifiedBetween(kTemp, base::Time(), base::Time::Max()); task_environment_.RunUntilIdle(); - EXPECT_EQ(1U, modified_origins().size()); - EXPECT_EQ(1U, modified_origins().count(ToOrigin("http://a.com/"))); - EXPECT_EQ(modified_origins_type(), kTemp); + + // Return empty set when error is encountered. + EXPECT_TRUE(modified_buckets().empty()); + EXPECT_EQ(modified_buckets_type(), kTemp); } TEST_F(QuotaManagerImplTest, DumpQuotaTable) { @@ -2564,52 +2801,33 @@ TEST_F(QuotaManagerImplTest, DumpQuotaTable) { DumpQuotaTable(); task_environment_.RunUntilIdle(); - const QuotaTableEntry kEntries[] = { - {.host = "example1.com", .type = kPerm, .quota = 1}, - {.host = "example2.com", .type = kPerm, .quota = 20}, - {.host = "example3.com", .type = kPerm, .quota = 300}}; - std::set<QuotaTableEntry> entries(kEntries, kEntries + base::size(kEntries)); - - for (const auto& quota_entry : quota_entries()) { - SCOPED_TRACE(testing::Message() << "host = " << quota_entry.host << ", " - << "quota = " << quota_entry.quota); - EXPECT_EQ(1u, entries.erase(quota_entry)); - } - EXPECT_TRUE(entries.empty()); + EXPECT_THAT( + quota_entries(), + testing::UnorderedElementsAre( + QuotaTableEntry{.host = "example1.com", .type = kPerm, .quota = 1}, + QuotaTableEntry{.host = "example2.com", .type = kPerm, .quota = 20}, + QuotaTableEntry{ + .host = "example3.com", .type = kPerm, .quota = 300})); } TEST_F(QuotaManagerImplTest, DumpBucketTable) { - using std::make_pair; - - quota_manager_impl()->NotifyStorageAccessed(ToOrigin("http://example.com/"), - kTemp, base::Time::Now()); - quota_manager_impl()->NotifyStorageAccessed(ToOrigin("http://example.com/"), - kPerm, base::Time::Now()); - quota_manager_impl()->NotifyStorageAccessed(ToOrigin("http://example.com/"), - kPerm, base::Time::Now()); + quota_manager_impl()->NotifyStorageAccessed( + ToStorageKey("http://example.com/"), kTemp, base::Time::Now()); + quota_manager_impl()->NotifyStorageAccessed( + ToStorageKey("http://example.com/"), kPerm, base::Time::Now()); + quota_manager_impl()->NotifyStorageAccessed( + ToStorageKey("http://example.com/"), kPerm, base::Time::Now()); task_environment_.RunUntilIdle(); DumpBucketTable(); task_environment_.RunUntilIdle(); - using TypedOrigin = std::pair<GURL, StorageType>; - using Entry = std::pair<TypedOrigin, int>; - const Entry kEntries[] = { - make_pair(make_pair(GURL("http://example.com/"), kTemp), 1), - make_pair(make_pair(GURL("http://example.com/"), kPerm), 2), - }; - std::set<Entry> entries(kEntries, kEntries + base::size(kEntries)); - - for (const auto& entry : bucket_entries()) { - SCOPED_TRACE(testing::Message() - << "host = " << entry.origin << ", " - << "type = " << static_cast<int>(entry.type) << ", " - << "use_count = " << entry.use_count); - EXPECT_EQ(1u, entries.erase( - make_pair(make_pair(entry.origin.GetURL(), entry.type), - entry.use_count))); - } - EXPECT_TRUE(entries.empty()); + EXPECT_THAT(bucket_entries(), + testing::UnorderedElementsAre( + MatchesBucketTableEntry(ToStorageKey("http://example.com/"), + kTemp, 1), + MatchesBucketTableEntry(ToStorageKey("http://example.com/"), + kPerm, 2))); } TEST_F(QuotaManagerImplTest, QuotaForEmptyHost) { @@ -2623,25 +2841,25 @@ TEST_F(QuotaManagerImplTest, QuotaForEmptyHost) { EXPECT_EQ(QuotaStatusCode::kErrorNotSupported, status()); } -TEST_F(QuotaManagerImplTest, DeleteSpecificClientTypeSingleOrigin) { - static const MockOriginData kData1[] = { - { "http://foo.com/", kTemp, 1 }, +TEST_F(QuotaManagerImplTest, DeleteSpecificClientTypeSingleStorageKey) { + static const MockStorageKeyData kData1[] = { + {"http://foo.com/", kTemp, 1}, }; - static const MockOriginData kData2[] = { - { "http://foo.com/", kTemp, 2 }, + static const MockStorageKeyData kData2[] = { + {"http://foo.com/", kTemp, 2}, }; - static const MockOriginData kData3[] = { - { "http://foo.com/", kTemp, 4 }, + static const MockStorageKeyData kData3[] = { + {"http://foo.com/", kTemp, 4}, }; - static const MockOriginData kData4[] = { - { "http://foo.com/", kTemp, 8 }, + static const MockStorageKeyData kData4[] = { + {"http://foo.com/", kTemp, 8}, }; - CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem, - {blink::mojom::StorageType::kTemporary}); + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary}); CreateAndRegisterClient(kData2, QuotaClientType::kAppcache, {blink::mojom::StorageType::kTemporary}); - CreateAndRegisterLegacyClient(kData3, QuotaClientType::kDatabase, - {blink::mojom::StorageType::kTemporary}); + CreateAndRegisterClient(kData3, QuotaClientType::kDatabase, + {blink::mojom::StorageType::kTemporary}); CreateAndRegisterClient(kData4, QuotaClientType::kIndexedDatabase, {blink::mojom::StorageType::kTemporary}); @@ -2649,29 +2867,85 @@ TEST_F(QuotaManagerImplTest, DeleteSpecificClientTypeSingleOrigin) { task_environment_.RunUntilIdle(); const int64_t predelete_foo_tmp = usage(); - DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, - {QuotaClientType::kFileSystem}); + DeleteStorageKeyData(ToStorageKey("http://foo.com/"), kTemp, + {QuotaClientType::kFileSystem}); task_environment_.RunUntilIdle(); GetHostUsageWithBreakdown("foo.com", kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - 1, usage()); - DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, - {QuotaClientType::kAppcache}); + DeleteStorageKeyData(ToStorageKey("http://foo.com/"), kTemp, + {QuotaClientType::kAppcache}); task_environment_.RunUntilIdle(); GetHostUsageWithBreakdown("foo.com", kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - 2 - 1, usage()); - DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, - {QuotaClientType::kDatabase}); + DeleteStorageKeyData(ToStorageKey("http://foo.com/"), kTemp, + {QuotaClientType::kDatabase}); task_environment_.RunUntilIdle(); GetHostUsageWithBreakdown("foo.com", kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - 4 - 2 - 1, usage()); - DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, - {QuotaClientType::kIndexedDatabase}); + DeleteStorageKeyData(ToStorageKey("http://foo.com/"), kTemp, + {QuotaClientType::kIndexedDatabase}); + task_environment_.RunUntilIdle(); + GetHostUsageWithBreakdown("foo.com", kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage()); +} + +TEST_F(QuotaManagerImplTest, DeleteSpecificClientTypeSingleBucket) { + static const MockStorageKeyData kData1[] = { + {"http://foo.com/", kTemp, 1}, + }; + static const MockStorageKeyData kData2[] = { + {"http://foo.com/", kTemp, 2}, + }; + static const MockStorageKeyData kData3[] = { + {"http://foo.com/", kTemp, 4}, + }; + static const MockStorageKeyData kData4[] = { + {"http://foo.com/", kTemp, 8}, + }; + 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}); + + CreateBucketForTesting(ToStorageKey("http://foo.com"), kDefaultBucketName, + kTemp); + ASSERT_TRUE(bucket_.ok()); + BucketInfo foo_bucket = bucket_.value(); + + GetHostUsageWithBreakdown("foo.com", kTemp); + task_environment_.RunUntilIdle(); + const int64_t predelete_foo_tmp = usage(); + + DeleteBucketData(foo_bucket, {QuotaClientType::kFileSystem}); + task_environment_.RunUntilIdle(); + GetHostUsageWithBreakdown("foo.com", kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_foo_tmp - 1, usage()); + + DeleteBucketData(foo_bucket, {QuotaClientType::kAppcache}); + task_environment_.RunUntilIdle(); + GetHostUsageWithBreakdown("foo.com", kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_foo_tmp - 2 - 1, usage()); + + DeleteBucketData(foo_bucket, {QuotaClientType::kDatabase}); + task_environment_.RunUntilIdle(); + GetHostUsageWithBreakdown("foo.com", kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_foo_tmp - 4 - 2 - 1, usage()); + + DeleteBucketData(foo_bucket, {QuotaClientType::kIndexedDatabase}); task_environment_.RunUntilIdle(); GetHostUsageWithBreakdown("foo.com", kTemp); task_environment_.RunUntilIdle(); @@ -2679,24 +2953,24 @@ TEST_F(QuotaManagerImplTest, DeleteSpecificClientTypeSingleOrigin) { } TEST_F(QuotaManagerImplTest, DeleteSpecificClientTypeSingleHost) { - static const MockOriginData kData1[] = { - { "http://foo.com:1111/", kTemp, 1 }, + static const MockStorageKeyData kData1[] = { + {"http://foo.com:1111/", kTemp, 1}, }; - static const MockOriginData kData2[] = { - { "http://foo.com:2222/", kTemp, 2 }, + static const MockStorageKeyData kData2[] = { + {"http://foo.com:2222/", kTemp, 2}, }; - static const MockOriginData kData3[] = { - { "http://foo.com:3333/", kTemp, 4 }, + static const MockStorageKeyData kData3[] = { + {"http://foo.com:3333/", kTemp, 4}, }; - static const MockOriginData kData4[] = { - { "http://foo.com:4444/", kTemp, 8 }, + static const MockStorageKeyData kData4[] = { + {"http://foo.com:4444/", kTemp, 8}, }; - CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem, - {blink::mojom::StorageType::kTemporary}); + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary}); CreateAndRegisterClient(kData2, QuotaClientType::kAppcache, {blink::mojom::StorageType::kTemporary}); - CreateAndRegisterLegacyClient(kData3, QuotaClientType::kDatabase, - {blink::mojom::StorageType::kTemporary}); + CreateAndRegisterClient(kData3, QuotaClientType::kDatabase, + {blink::mojom::StorageType::kTemporary}); CreateAndRegisterClient(kData4, QuotaClientType::kIndexedDatabase, {blink::mojom::StorageType::kTemporary}); @@ -2729,25 +3003,25 @@ TEST_F(QuotaManagerImplTest, DeleteSpecificClientTypeSingleHost) { EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage()); } -TEST_F(QuotaManagerImplTest, DeleteMultipleClientTypesSingleOrigin) { - static const MockOriginData kData1[] = { - { "http://foo.com/", kTemp, 1 }, +TEST_F(QuotaManagerImplTest, DeleteMultipleClientTypesSingleStorageKey) { + static const MockStorageKeyData kData1[] = { + {"http://foo.com/", kTemp, 1}, }; - static const MockOriginData kData2[] = { - { "http://foo.com/", kTemp, 2 }, + static const MockStorageKeyData kData2[] = { + {"http://foo.com/", kTemp, 2}, }; - static const MockOriginData kData3[] = { - { "http://foo.com/", kTemp, 4 }, + static const MockStorageKeyData kData3[] = { + {"http://foo.com/", kTemp, 4}, }; - static const MockOriginData kData4[] = { - { "http://foo.com/", kTemp, 8 }, + static const MockStorageKeyData kData4[] = { + {"http://foo.com/", kTemp, 8}, }; - CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem, - {blink::mojom::StorageType::kTemporary}); + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary}); CreateAndRegisterClient(kData2, QuotaClientType::kAppcache, {blink::mojom::StorageType::kTemporary}); - CreateAndRegisterLegacyClient(kData3, QuotaClientType::kDatabase, - {blink::mojom::StorageType::kTemporary}); + CreateAndRegisterClient(kData3, QuotaClientType::kDatabase, + {blink::mojom::StorageType::kTemporary}); CreateAndRegisterClient(kData4, QuotaClientType::kIndexedDatabase, {blink::mojom::StorageType::kTemporary}); @@ -2755,15 +3029,16 @@ TEST_F(QuotaManagerImplTest, DeleteMultipleClientTypesSingleOrigin) { task_environment_.RunUntilIdle(); const int64_t predelete_foo_tmp = usage(); - DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, - {QuotaClientType::kFileSystem, QuotaClientType::kDatabase}); + DeleteStorageKeyData( + ToStorageKey("http://foo.com/"), kTemp, + {QuotaClientType::kFileSystem, QuotaClientType::kDatabase}); task_environment_.RunUntilIdle(); GetHostUsageWithBreakdown("foo.com", kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - 4 - 1, usage()); - DeleteOriginData( - ToOrigin("http://foo.com/"), kTemp, + DeleteStorageKeyData( + ToStorageKey("http://foo.com/"), kTemp, {QuotaClientType::kAppcache, QuotaClientType::kIndexedDatabase}); task_environment_.RunUntilIdle(); GetHostUsageWithBreakdown("foo.com", kTemp); @@ -2771,25 +3046,71 @@ TEST_F(QuotaManagerImplTest, DeleteMultipleClientTypesSingleOrigin) { EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage()); } +TEST_F(QuotaManagerImplTest, DeleteMultipleClientTypesSingleBucket) { + static const MockStorageKeyData kData1[] = { + {"http://foo.com/", kTemp, 1}, + }; + static const MockStorageKeyData kData2[] = { + {"http://foo.com/", kTemp, 2}, + }; + static const MockStorageKeyData kData3[] = { + {"http://foo.com/", kTemp, 4}, + }; + static const MockStorageKeyData kData4[] = { + {"http://foo.com/", kTemp, 8}, + }; + 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}); + + CreateBucketForTesting(ToStorageKey("http://foo.com/"), kDefaultBucketName, + kTemp); + ASSERT_TRUE(bucket_.ok()); + BucketInfo foo_bucket = bucket_.value(); + + GetHostUsageWithBreakdown("foo.com", kTemp); + task_environment_.RunUntilIdle(); + const int64_t predelete_foo_tmp = usage(); + + DeleteBucketData(foo_bucket, + {QuotaClientType::kFileSystem, QuotaClientType::kDatabase}); + task_environment_.RunUntilIdle(); + GetHostUsageWithBreakdown("foo.com", kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_foo_tmp - 4 - 1, usage()); + + DeleteBucketData(foo_bucket, {QuotaClientType::kAppcache, + QuotaClientType::kIndexedDatabase}); + task_environment_.RunUntilIdle(); + GetHostUsageWithBreakdown("foo.com", kTemp); + task_environment_.RunUntilIdle(); + EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage()); +} + TEST_F(QuotaManagerImplTest, DeleteMultipleClientTypesSingleHost) { - static const MockOriginData kData1[] = { - { "http://foo.com:1111/", kTemp, 1 }, + static const MockStorageKeyData kData1[] = { + {"http://foo.com:1111/", kTemp, 1}, }; - static const MockOriginData kData2[] = { - { "http://foo.com:2222/", kTemp, 2 }, + static const MockStorageKeyData kData2[] = { + {"http://foo.com:2222/", kTemp, 2}, }; - static const MockOriginData kData3[] = { - { "http://foo.com:3333/", kTemp, 4 }, + static const MockStorageKeyData kData3[] = { + {"http://foo.com:3333/", kTemp, 4}, }; - static const MockOriginData kData4[] = { - { "http://foo.com:4444/", kTemp, 8 }, + static const MockStorageKeyData kData4[] = { + {"http://foo.com:4444/", kTemp, 8}, }; - CreateAndRegisterLegacyClient(kData1, QuotaClientType::kFileSystem, - {blink::mojom::StorageType::kTemporary}); + CreateAndRegisterClient(kData1, QuotaClientType::kFileSystem, + {blink::mojom::StorageType::kTemporary}); CreateAndRegisterClient(kData2, QuotaClientType::kAppcache, {blink::mojom::StorageType::kTemporary}); - CreateAndRegisterLegacyClient(kData3, QuotaClientType::kDatabase, - {blink::mojom::StorageType::kTemporary}); + CreateAndRegisterClient(kData3, QuotaClientType::kDatabase, + {blink::mojom::StorageType::kTemporary}); CreateAndRegisterClient(kData4, QuotaClientType::kIndexedDatabase, {blink::mojom::StorageType::kTemporary}); @@ -2816,9 +3137,9 @@ TEST_F(QuotaManagerImplTest, DeleteMultipleClientTypesSingleHost) { TEST_F(QuotaManagerImplTest, GetUsageAndQuota_Incognito) { ResetQuotaManagerImpl(true); - static const MockOriginData kData[] = { - { "http://foo.com/", kTemp, 10 }, - { "http://foo.com/", kPerm, 80 }, + static const MockStorageKeyData kData[] = { + {"http://foo.com/", kTemp, 10}, + {"http://foo.com/", kPerm, 80}, }; CreateAndRegisterClient(kData, QuotaClientType::kFileSystem, {blink::mojom::StorageType::kTemporary, @@ -2829,7 +3150,7 @@ TEST_F(QuotaManagerImplTest, GetUsageAndQuota_Incognito) { GetGlobalUsage(kPerm); task_environment_.RunUntilIdle(); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(80, usage()); @@ -2844,20 +3165,20 @@ TEST_F(QuotaManagerImplTest, GetUsageAndQuota_Incognito) { EXPECT_EQ(kPoolSize, total_space()); EXPECT_EQ(kPoolSize - 80 - 10, available_space()); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10, usage()); EXPECT_LE(kPerHostQuota, quota()); mock_special_storage_policy()->AddUnlimited(GURL("http://foo.com/")); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kPerm); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(80, usage()); EXPECT_EQ(available_space() + usage(), quota()); - GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToStorageKey("http://foo.com/"), kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10, usage()); @@ -2865,15 +3186,16 @@ TEST_F(QuotaManagerImplTest, GetUsageAndQuota_Incognito) { } TEST_F(QuotaManagerImplTest, GetUsageAndQuota_SessionOnly) { - const url::Origin kEpheremalOrigin = ToOrigin("http://ephemeral/"); - mock_special_storage_policy()->AddSessionOnly(kEpheremalOrigin.GetURL()); + const StorageKey kEpheremalStorageKey = ToStorageKey("http://ephemeral/"); + mock_special_storage_policy()->AddSessionOnly( + kEpheremalStorageKey.origin().GetURL()); - GetUsageAndQuotaForWebApps(kEpheremalOrigin, kTemp); + GetUsageAndQuotaForWebApps(kEpheremalStorageKey, kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(quota_manager_impl()->settings().session_only_per_host_quota, quota()); - GetUsageAndQuotaForWebApps(kEpheremalOrigin, kPerm); + GetUsageAndQuotaForWebApps(kEpheremalStorageKey, kPerm); task_environment_.RunUntilIdle(); EXPECT_EQ(0, quota()); } @@ -2881,95 +3203,100 @@ TEST_F(QuotaManagerImplTest, GetUsageAndQuota_SessionOnly) { TEST_F(QuotaManagerImplTest, MaybeRunStoragePressureCallback) { bool callback_ran = false; auto cb = base::BindRepeating( - [](bool* callback_ran, url::Origin origin) { *callback_ran = true; }, + [](bool* callback_ran, StorageKey storage_key) { *callback_ran = true; }, &callback_ran); SetStoragePressureCallback(std::move(cb)); int64_t kGBytes = QuotaManagerImpl::kMBytes * 1024; - MaybeRunStoragePressureCallback(url::Origin(), 100 * kGBytes, 2 * kGBytes); + MaybeRunStoragePressureCallback(StorageKey(), 100 * kGBytes, 2 * kGBytes); task_environment_.RunUntilIdle(); EXPECT_FALSE(callback_ran); - MaybeRunStoragePressureCallback(url::Origin(), 100 * kGBytes, kGBytes); + MaybeRunStoragePressureCallback(StorageKey(), 100 * kGBytes, kGBytes); task_environment_.RunUntilIdle(); EXPECT_TRUE(callback_ran); } -TEST_F(QuotaManagerImplTest, OverrideQuotaForOrigin) { - url::Origin origin = ToOrigin("https://foo.com"); +TEST_F(QuotaManagerImplTest, OverrideQuotaForStorageKey) { + StorageKey storage_key = ToStorageKey("https://foo.com"); std::unique_ptr<QuotaOverrideHandle> handle = GetQuotaOverrideHandle(); base::RunLoop run_loop; - handle->OverrideQuotaForOrigin( - origin, 5000, base::BindLambdaForTesting([&]() { run_loop.Quit(); })); + handle->OverrideQuotaForStorageKey( + storage_key, 5000, + base::BindLambdaForTesting([&]() { run_loop.Quit(); })); run_loop.Run(); - GetUsageAndQuotaForWebApps(origin, kTemp); + GetUsageAndQuotaForWebApps(storage_key, kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); EXPECT_EQ(5000, quota()); } -TEST_F(QuotaManagerImplTest, OverrideQuotaForOrigin_Disable) { - url::Origin origin = ToOrigin("https://foo.com"); +TEST_F(QuotaManagerImplTest, OverrideQuotaForStorageKey_Disable) { + StorageKey storage_key = ToStorageKey("https://foo.com"); std::unique_ptr<QuotaOverrideHandle> handle1 = GetQuotaOverrideHandle(); std::unique_ptr<QuotaOverrideHandle> handle2 = GetQuotaOverrideHandle(); base::RunLoop run_loop1; - handle1->OverrideQuotaForOrigin( - origin, 5000, base::BindLambdaForTesting([&]() { run_loop1.Quit(); })); + handle1->OverrideQuotaForStorageKey( + storage_key, 5000, + base::BindLambdaForTesting([&]() { run_loop1.Quit(); })); run_loop1.Run(); - GetUsageAndQuotaForWebApps(origin, kTemp); + GetUsageAndQuotaForWebApps(storage_key, kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(5000, quota()); base::RunLoop run_loop2; - handle2->OverrideQuotaForOrigin( - origin, 9000, base::BindLambdaForTesting([&]() { run_loop2.Quit(); })); + handle2->OverrideQuotaForStorageKey( + storage_key, 9000, + base::BindLambdaForTesting([&]() { run_loop2.Quit(); })); run_loop2.Run(); - GetUsageAndQuotaForWebApps(origin, kTemp); + GetUsageAndQuotaForWebApps(storage_key, kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(9000, quota()); base::RunLoop run_loop3; - handle2->OverrideQuotaForOrigin( - origin, absl::nullopt, + handle2->OverrideQuotaForStorageKey( + storage_key, absl::nullopt, base::BindLambdaForTesting([&]() { run_loop3.Quit(); })); run_loop3.Run(); - GetUsageAndQuotaForWebApps(origin, kTemp); + GetUsageAndQuotaForWebApps(storage_key, kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(kDefaultPerHostQuota, quota()); } TEST_F(QuotaManagerImplTest, WithdrawQuotaOverride) { - url::Origin origin = ToOrigin("https://foo.com"); + StorageKey storage_key = ToStorageKey("https://foo.com"); std::unique_ptr<QuotaOverrideHandle> handle1 = GetQuotaOverrideHandle(); std::unique_ptr<QuotaOverrideHandle> handle2 = GetQuotaOverrideHandle(); base::RunLoop run_loop1; - handle1->OverrideQuotaForOrigin( - origin, 5000, base::BindLambdaForTesting([&]() { run_loop1.Quit(); })); + handle1->OverrideQuotaForStorageKey( + storage_key, 5000, + base::BindLambdaForTesting([&]() { run_loop1.Quit(); })); run_loop1.Run(); - GetUsageAndQuotaForWebApps(origin, kTemp); + GetUsageAndQuotaForWebApps(storage_key, kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(5000, quota()); base::RunLoop run_loop2; - handle1->OverrideQuotaForOrigin( - origin, 8000, base::BindLambdaForTesting([&]() { run_loop2.Quit(); })); + handle1->OverrideQuotaForStorageKey( + storage_key, 8000, + base::BindLambdaForTesting([&]() { run_loop2.Quit(); })); run_loop2.Run(); - GetUsageAndQuotaForWebApps(origin, kTemp); + GetUsageAndQuotaForWebApps(storage_key, kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(8000, quota()); @@ -2977,14 +3304,14 @@ TEST_F(QuotaManagerImplTest, WithdrawQuotaOverride) { // Quota should remain overridden if only one of the two handles withdraws // it's overrides handle2.reset(); - GetUsageAndQuotaForWebApps(origin, kTemp); + GetUsageAndQuotaForWebApps(storage_key, kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(8000, quota()); handle1.reset(); task_environment_.RunUntilIdle(); - GetUsageAndQuotaForWebApps(origin, kTemp); + GetUsageAndQuotaForWebApps(storage_key, kTemp); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(kDefaultPerHostQuota, quota()); diff --git a/chromium/storage/browser/quota/quota_override_handle.cc b/chromium/storage/browser/quota/quota_override_handle.cc index 333387cd7fe..f460d44ce0b 100644 --- a/chromium/storage/browser/quota/quota_override_handle.cc +++ b/chromium/storage/browser/quota/quota_override_handle.cc @@ -8,6 +8,7 @@ #include "base/sequence_checker.h" #include "base/threading/sequenced_task_runner_handle.h" #include "storage/browser/quota/quota_manager_proxy.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" namespace storage { @@ -28,8 +29,8 @@ QuotaOverrideHandle::~QuotaOverrideHandle() { } } -void QuotaOverrideHandle::OverrideQuotaForOrigin( - url::Origin origin, +void QuotaOverrideHandle::OverrideQuotaForStorageKey( + const blink::StorageKey& storage_key, absl::optional<int64_t> quota_size, base::OnceClosure callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -38,13 +39,13 @@ void QuotaOverrideHandle::OverrideQuotaForOrigin( // and the callbacks within, so it's guaranteed to be alive when the // callback is dispatched. override_callback_queue_.push_back(base::BindOnce( - &QuotaOverrideHandle::OverrideQuotaForOrigin, base::Unretained(this), - origin, quota_size, std::move(callback))); + &QuotaOverrideHandle::OverrideQuotaForStorageKey, + base::Unretained(this), storage_key, quota_size, std::move(callback))); return; } - quota_manager_proxy_->OverrideQuotaForOrigin( - id_.value(), origin, quota_size, base::SequencedTaskRunnerHandle::Get(), - std::move(callback)); + quota_manager_proxy_->OverrideQuotaForStorageKey( + id_.value(), storage_key, quota_size, + base::SequencedTaskRunnerHandle::Get(), std::move(callback)); } void QuotaOverrideHandle::DidGetOverrideHandleId(int id) { diff --git a/chromium/storage/browser/quota/quota_override_handle.h b/chromium/storage/browser/quota/quota_override_handle.h index 71531db7541..065e8acf574 100644 --- a/chromium/storage/browser/quota/quota_override_handle.h +++ b/chromium/storage/browser/quota/quota_override_handle.h @@ -11,14 +11,14 @@ #include "base/sequence_checker.h" #include "base/sequenced_task_runner.h" #include "base/thread_annotations.h" -#include "url/origin.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" namespace storage { class QuotaManagerProxy; // Used by DevTools clients and exposes the API to override and/or -// manage an active override for storage quota on a per-origin basis. +// manage an active override for storage quota on a per-storage-key basis. // QuotaOverrideHandle instances are owned by StorageHandler (DevTools client), // and each DevTools session will have at most 1 instance. // This class is not thread-safe. An instance must always be used from the same @@ -30,9 +30,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaOverrideHandle { ~QuotaOverrideHandle(); QuotaOverrideHandle(const QuotaOverrideHandle&) = delete; - void OverrideQuotaForOrigin(url::Origin origin, - absl::optional<int64_t> quota_size, - base::OnceClosure callback); + void OverrideQuotaForStorageKey(const blink::StorageKey& storage_key, + absl::optional<int64_t> quota_size, + base::OnceClosure callback); private: void GetUniqueId(); diff --git a/chromium/storage/browser/quota/quota_settings.cc b/chromium/storage/browser/quota/quota_settings.cc index 13958ce112c..4830c83de5b 100644 --- a/chromium/storage/browser/quota/quota_settings.cc +++ b/chromium/storage/browser/quota/quota_settings.cc @@ -10,6 +10,7 @@ #include <utility> #include "base/bind.h" +#include "base/no_destructor.h" #include "base/rand_util.h" #include "base/system/sys_info.h" #include "base/task/post_task.h" diff --git a/chromium/storage/browser/quota/quota_temporary_storage_evictor.cc b/chromium/storage/browser/quota/quota_temporary_storage_evictor.cc index b9e36ed9b03..9aa65c076ea 100644 --- a/chromium/storage/browser/quota/quota_temporary_storage_evictor.cc +++ b/chromium/storage/browser/quota/quota_temporary_storage_evictor.cc @@ -10,36 +10,27 @@ #include "base/auto_reset.h" #include "base/bind.h" -#include "storage/browser/quota/quota_macros.h" +#include "base/metrics/histogram_functions.h" #include "storage/browser/quota/quota_manager_impl.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" #include "url/gurl.h" -#define UMA_HISTOGRAM_MINUTES(name, sample) \ - UMA_HISTOGRAM_CUSTOM_TIMES( \ - (name), (sample), \ - base::TimeDelta::FromMinutes(1), \ - base::TimeDelta::FromDays(1), 50) - namespace { constexpr int64_t kMBytes = 1024 * 1024; constexpr double kUsageRatioToStartEviction = 0.7; constexpr int kThresholdOfErrorsToStopEviction = 5; constexpr int kHistogramReportIntervalMinutes = 60; constexpr double kDiskSpaceShortageAllowanceRatio = 0.5; + +void UmaHistogramMbytes(const std::string& name, int sample) { + base::UmaHistogramCustomCounts(name, sample / kMBytes, 1, + 10 * 1024 * 1024 /* 10 TB */, 100); +} } namespace storage { -QuotaTemporaryStorageEvictor::EvictionRoundStatistics::EvictionRoundStatistics() - : in_round(false), - is_initialized(false), - diskspace_shortage_at_round(-1), - usage_on_beginning_of_round(-1), - usage_on_end_of_round(-1), - num_evicted_origins_in_round(0) { -} - QuotaTemporaryStorageEvictor::QuotaTemporaryStorageEvictor( QuotaEvictionHandler* quota_eviction_handler, int64_t interval_ms) @@ -60,8 +51,7 @@ void QuotaTemporaryStorageEvictor::GetStatistics( (*statistics)["errors-on-getting-usage-and-quota"] = statistics_.num_errors_on_getting_usage_and_quota; - (*statistics)["evicted-origins"] = - statistics_.num_evicted_origins; + (*statistics)["evicted-buckets"] = statistics_.num_evicted_buckets; (*statistics)["eviction-rounds"] = statistics_.num_eviction_rounds; (*statistics)["skipped-eviction-rounds"] = @@ -74,21 +64,22 @@ void QuotaTemporaryStorageEvictor::ReportPerRoundHistogram() { DCHECK(round_statistics_.is_initialized); base::Time now = base::Time::Now(); - UMA_HISTOGRAM_TIMES("Quota.TimeSpentToAEvictionRound", - now - round_statistics_.start_time); + base::UmaHistogramTimes("Quota.TimeSpentToAEvictionRound", + now - round_statistics_.start_time); if (!time_of_end_of_last_round_.is_null()) { - UMA_HISTOGRAM_MINUTES("Quota.TimeDeltaOfEvictionRounds", - now - time_of_end_of_last_round_); + base::UmaHistogramCustomTimes( + "Quota.TimeDeltaOfEvictionRounds", now - time_of_end_of_last_round_, + base::TimeDelta::FromMinutes(1), base::TimeDelta::FromDays(1), 50); } time_of_end_of_last_round_ = now; - UMA_HISTOGRAM_MBYTES("Quota.DiskspaceShortage", - round_statistics_.diskspace_shortage_at_round); - UMA_HISTOGRAM_MBYTES("Quota.EvictedBytesPerRound", - round_statistics_.usage_on_beginning_of_round - - round_statistics_.usage_on_end_of_round); - UMA_HISTOGRAM_COUNTS_1M("Quota.NumberOfEvictedOriginsPerRound", - round_statistics_.num_evicted_origins_in_round); + UmaHistogramMbytes("Quota.DiskspaceShortage", + round_statistics_.diskspace_shortage_at_round); + UmaHistogramMbytes("Quota.EvictedBytesPerRound", + round_statistics_.usage_on_beginning_of_round - + round_statistics_.usage_on_end_of_round); + base::UmaHistogramCounts1M("Quota.NumberOfEvictedBucketsPerRound", + round_statistics_.num_evicted_buckets_in_round); } void QuotaTemporaryStorageEvictor::ReportPerHourHistogram() { @@ -97,12 +88,12 @@ void QuotaTemporaryStorageEvictor::ReportPerHourHistogram() { stats_in_hour.subtract_assign(previous_statistics_); previous_statistics_ = statistics_; - UMA_HISTOGRAM_COUNTS_1M("Quota.EvictedOriginsPerHour", - stats_in_hour.num_evicted_origins); - UMA_HISTOGRAM_COUNTS_1M("Quota.EvictionRoundsPerHour", - stats_in_hour.num_eviction_rounds); - UMA_HISTOGRAM_COUNTS_1M("Quota.SkippedEvictionRoundsPerHour", - stats_in_hour.num_skipped_eviction_rounds); + base::UmaHistogramCounts1M("Quota.EvictedBucketsPerHour", + stats_in_hour.num_evicted_buckets); + base::UmaHistogramCounts1M("Quota.EvictionRoundsPerHour", + stats_in_hour.num_eviction_rounds); + base::UmaHistogramCounts1M("Quota.SkippedEvictionRoundsPerHour", + stats_in_hour.num_skipped_eviction_rounds); } void QuotaTemporaryStorageEvictor::OnEvictionRoundStarted() { @@ -118,7 +109,7 @@ void QuotaTemporaryStorageEvictor::OnEvictionRoundFinished() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Check if skipped round - if (round_statistics_.num_evicted_origins_in_round) { + if (round_statistics_.num_evicted_buckets_in_round) { ReportPerRoundHistogram(); time_of_end_of_last_nonskipped_round_ = base::Time::Now(); } else { @@ -200,12 +191,13 @@ void QuotaTemporaryStorageEvictor::OnGotEvictionRoundInfo( int64_t amount_to_evict = std::max(usage_overage, diskspace_shortage); if (status == blink::mojom::QuotaStatusCode::kOk && amount_to_evict > 0) { - // Space is getting tight. Get the least recently used origin and continue. + // Space is getting tight. Get the least recently used storage key and + // continue. // TODO(michaeln): if the reason for eviction is low physical disk space, - // make 'unlimited' origins subject to eviction too. - quota_eviction_handler_->GetEvictionOrigin( + // make 'unlimited' storage keys subject to eviction too. + quota_eviction_handler_->GetEvictionBucket( blink::mojom::StorageType::kTemporary, settings.pool_size, - base::BindOnce(&QuotaTemporaryStorageEvictor::OnGotEvictionOrigin, + base::BindOnce(&QuotaTemporaryStorageEvictor::OnGotEvictionBucket, weak_factory_.GetWeakPtr())); return; } @@ -223,20 +215,20 @@ void QuotaTemporaryStorageEvictor::OnGotEvictionRoundInfo( OnEvictionRoundFinished(); } -void QuotaTemporaryStorageEvictor::OnGotEvictionOrigin( - const absl::optional<url::Origin>& origin) { +void QuotaTemporaryStorageEvictor::OnGotEvictionBucket( + const absl::optional<BucketInfo>& bucket) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!origin.has_value()) { + if (!bucket.has_value()) { StartEvictionTimerWithDelay(interval_ms_); OnEvictionRoundFinished(); return; } - DCHECK(!origin->GetURL().is_empty()); + DCHECK(!bucket->storage_key.origin().GetURL().is_empty()); - quota_eviction_handler_->EvictOriginData( - *origin, blink::mojom::StorageType::kTemporary, + quota_eviction_handler_->EvictBucketData( + bucket.value(), base::BindOnce(&QuotaTemporaryStorageEvictor::OnEvictionComplete, weak_factory_.GetWeakPtr())); } @@ -246,14 +238,14 @@ void QuotaTemporaryStorageEvictor::OnEvictionComplete( DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Just calling ConsiderEviction() or StartEvictionTimerWithDelay() here is - // ok. No need to deal with the case that all of the Delete operations fail - // for a certain origin. It doesn't result in trying to evict the same - // origin permanently. The evictor skips origins which had deletion errors - // a few times. + // ok. No need to deal with the case that all of the Delete operations fail + // for a certain bucket. It doesn't result in trying to evict the same bucket + // permanently. The evictor skips buckets which had deletion errors a few + // times. if (status == blink::mojom::QuotaStatusCode::kOk) { - ++statistics_.num_evicted_origins; - ++round_statistics_.num_evicted_origins_in_round; + ++statistics_.num_evicted_buckets; + ++round_statistics_.num_evicted_buckets_in_round; // We many need to get rid of more space so reconsider immediately. ConsiderEviction(); } else { diff --git a/chromium/storage/browser/quota/quota_temporary_storage_evictor.h b/chromium/storage/browser/quota/quota_temporary_storage_evictor.h index 7503ffd2ca6..7eecc08f6f6 100644 --- a/chromium/storage/browser/quota/quota_temporary_storage_evictor.h +++ b/chromium/storage/browser/quota/quota_temporary_storage_evictor.h @@ -16,13 +16,10 @@ #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "base/timer/timer.h" +#include "components/services/storage/public/cpp/buckets/bucket_info.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" -namespace url { -class Origin; -} - namespace storage { class QuotaEvictionHandler; @@ -31,37 +28,30 @@ struct QuotaSettings; class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaTemporaryStorageEvictor { public: struct Statistics { - Statistics() - : num_errors_on_getting_usage_and_quota(0), - num_evicted_origins(0), - num_eviction_rounds(0), - num_skipped_eviction_rounds(0) {} - int64_t num_errors_on_getting_usage_and_quota; - int64_t num_evicted_origins; - int64_t num_eviction_rounds; - int64_t num_skipped_eviction_rounds; + int64_t num_errors_on_getting_usage_and_quota = 0; + int64_t num_evicted_buckets = 0; + int64_t num_eviction_rounds = 0; + int64_t num_skipped_eviction_rounds = 0; void subtract_assign(const Statistics& rhs) { num_errors_on_getting_usage_and_quota -= rhs.num_errors_on_getting_usage_and_quota; - num_evicted_origins -= rhs.num_evicted_origins; + num_evicted_buckets -= rhs.num_evicted_buckets; num_eviction_rounds -= rhs.num_eviction_rounds; num_skipped_eviction_rounds -= rhs.num_skipped_eviction_rounds; } }; struct EvictionRoundStatistics { - EvictionRoundStatistics(); - - bool in_round; - bool is_initialized; + bool in_round = false; + bool is_initialized = false; base::Time start_time; - int64_t diskspace_shortage_at_round; + int64_t diskspace_shortage_at_round = -1; - int64_t usage_on_beginning_of_round; - int64_t usage_on_end_of_round; - int64_t num_evicted_origins_in_round; + int64_t usage_on_beginning_of_round = -1; + int64_t usage_on_end_of_round = -1; + int64_t num_evicted_buckets_in_round = 0; }; QuotaTemporaryStorageEvictor(QuotaEvictionHandler* quota_eviction_handler, @@ -84,7 +74,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaTemporaryStorageEvictor { int64_t total_space, int64_t current_usage, bool current_usage_is_complete); - void OnGotEvictionOrigin(const absl::optional<url::Origin>& origin); + void OnGotEvictionBucket(const absl::optional<BucketInfo>& bucket); void OnEvictionComplete(blink::mojom::QuotaStatusCode status); void OnEvictionRoundStarted(); diff --git a/chromium/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc b/chromium/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc index 4624ff1ca11..89ffbc6d1c7 100644 --- a/chromium/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc +++ b/chromium/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc @@ -16,12 +16,13 @@ #include "base/memory/weak_ptr.h" #include "base/run_loop.h" #include "base/test/task_environment.h" +#include "components/services/storage/public/cpp/buckets/bucket_id.h" +#include "components/services/storage/public/cpp/buckets/bucket_info.h" #include "storage/browser/quota/quota_manager_impl.h" #include "storage/browser/quota/quota_temporary_storage_evictor.h" #include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" -using blink::mojom::StorageType; +using ::blink::mojom::StorageType; namespace storage { @@ -29,29 +30,23 @@ class QuotaTemporaryStorageEvictorTest; namespace { -// TODO(crbug.com/889590): Replace with common converter. -url::Origin ToOrigin(const std::string& url) { - return url::Origin::Create(GURL(url)); -} - class MockQuotaEvictionHandler : public QuotaEvictionHandler { public: explicit MockQuotaEvictionHandler(QuotaTemporaryStorageEvictorTest* test) : available_space_(0), - error_on_evict_origin_data_(false), + error_on_evict_buckets_data_(false), error_on_get_usage_and_quota_(false) {} - void EvictOriginData(const url::Origin& origin, - StorageType type, + void EvictBucketData(const BucketInfo& bucket, StatusCallback callback) override { - if (error_on_evict_origin_data_) { + if (error_on_evict_buckets_data_) { std::move(callback).Run( blink::mojom::QuotaStatusCode::kErrorInvalidModification); return; } - int64_t origin_usage = EnsureOriginRemoved(origin); - if (origin_usage >= 0) - available_space_ += origin_usage; + int64_t bucket_usage = EnsureBucketRemoved(bucket); + if (bucket_usage >= 0) + available_space_ += bucket_usage; std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk); } @@ -68,19 +63,20 @@ class MockQuotaEvictionHandler : public QuotaEvictionHandler { true); } - void GetEvictionOrigin(StorageType type, + void GetEvictionBucket(StorageType type, int64_t global_quota, - GetOriginCallback callback) override { - if (origin_order_.empty()) + GetBucketCallback callback) override { + if (bucket_order_.empty()) { std::move(callback).Run(absl::nullopt); - else - std::move(callback).Run(origin_order_.front()); + } else { + std::move(callback).Run(bucket_order_.front()); + } } int64_t GetUsage() const { int64_t total_usage = 0; - for (const auto& origin_usage_pair : origins_) - total_usage += origin_usage_pair.second; + for (const auto& bucket_usage_pair : buckets_) + total_usage += bucket_usage_pair.second; return total_usage; } @@ -98,48 +94,48 @@ class MockQuotaEvictionHandler : public QuotaEvictionHandler { void set_task_for_get_usage_and_quota(base::RepeatingClosure task) { task_for_get_usage_and_quota_ = std::move(task); } - void set_error_on_evict_origin_data(bool error_on_evict_origin_data) { - error_on_evict_origin_data_ = error_on_evict_origin_data; + void set_error_on_evict_buckets_data(bool error_on_evict_buckets_data) { + error_on_evict_buckets_data_ = error_on_evict_buckets_data; } void set_error_on_get_usage_and_quota(bool error_on_get_usage_and_quota) { error_on_get_usage_and_quota_ = error_on_get_usage_and_quota; } - // Simulates an access to |origin|. It reorders the internal LRU list. - // It internally uses AddOrigin(). - void AccessOrigin(const url::Origin& origin) { - const auto& it = origins_.find(origin); - EXPECT_TRUE(origins_.end() != it); - AddOrigin(origin, it->second); + // Simulates an access to `bucket`. It reorders the internal LRU list. + // It internally uses AddBucket(). + void AccessBucket(const BucketInfo& bucket) { + const auto& it = buckets_.find(bucket.id); + EXPECT_TRUE(buckets_.end() != it); + AddBucket(bucket, it->second); } - // Simulates adding or overwriting the |origin| to the internal origin set - // with the |usage|. It also adds or moves the |origin| to the end of the - // LRU list. - void AddOrigin(const url::Origin& origin, int64_t usage) { - EnsureOriginRemoved(origin); - origin_order_.push_back(origin); - origins_[origin] = usage; + // Simulates adding or overwriting the `bucket` to the internal bucket set + // with the `usage`. It also adds or moves the `bucket` to the + // end of the LRU list. + void AddBucket(const BucketInfo& bucket, int64_t usage) { + EnsureBucketRemoved(bucket); + bucket_order_.push_back(bucket); + buckets_[bucket.id] = usage; } private: - int64_t EnsureOriginRemoved(const url::Origin& origin) { - int64_t origin_usage; - if (!base::Contains(origins_, origin)) + int64_t EnsureBucketRemoved(const BucketInfo& bucket) { + int64_t bucket_usage; + if (!base::Contains(buckets_, bucket.id)) return -1; else - origin_usage = origins_[origin]; + bucket_usage = buckets_[bucket.id]; - origins_.erase(origin); - origin_order_.remove(origin); - return origin_usage; + buckets_.erase(bucket.id); + bucket_order_.remove(bucket); + return bucket_usage; } QuotaSettings settings_; int64_t available_space_; - std::list<url::Origin> origin_order_; - std::map<url::Origin, int64_t> origins_; - bool error_on_evict_origin_data_; + std::list<BucketInfo> bucket_order_; + std::map<BucketId, int64_t> buckets_; + bool error_on_evict_buckets_data_; bool error_on_get_usage_and_quota_; base::RepeatingClosure task_for_get_usage_and_quota_; @@ -167,8 +163,8 @@ class QuotaTemporaryStorageEvictorTest : public testing::Test { } void TaskForRepeatedEvictionTest( - const std::pair<absl::optional<url::Origin>, int64_t>& origin_to_be_added, - const absl::optional<url::Origin>& origin_to_be_accessed, + const std::pair<absl::optional<BucketInfo>, int64_t>& bucket_to_be_added, + const absl::optional<BucketInfo> bucket_to_be_accessed, int expected_usage_after_first, int expected_usage_after_second) { EXPECT_GE(4, num_get_usage_and_quota_for_eviction_); @@ -176,11 +172,11 @@ class QuotaTemporaryStorageEvictorTest : public testing::Test { case 2: EXPECT_EQ(expected_usage_after_first, quota_eviction_handler()->GetUsage()); - if (origin_to_be_added.first.has_value()) - quota_eviction_handler()->AddOrigin(*origin_to_be_added.first, - origin_to_be_added.second); - if (origin_to_be_accessed.has_value()) - quota_eviction_handler()->AccessOrigin(*origin_to_be_accessed); + if (bucket_to_be_added.first.has_value()) + quota_eviction_handler()->AddBucket(*bucket_to_be_added.first, + bucket_to_be_added.second); + if (bucket_to_be_accessed.has_value()) + quota_eviction_handler()->AccessBucket(*bucket_to_be_accessed); break; case 3: EXPECT_EQ(expected_usage_after_second, @@ -191,6 +187,13 @@ class QuotaTemporaryStorageEvictorTest : public testing::Test { ++num_get_usage_and_quota_for_eviction_; } + BucketInfo CreateBucket(const std::string& url, const std::string& name) { + return BucketInfo(bucket_id_generator_.GenerateNextId(), + blink::StorageKey::CreateFromStringForTesting(url), + blink::mojom::StorageType::kTemporary, name, + /*expiration=*/base::Time::Max(), /*quota=*/0); + } + protected: MockQuotaEvictionHandler* quota_eviction_handler() const { return static_cast<MockQuotaEvictionHandler*>( @@ -213,6 +216,7 @@ class QuotaTemporaryStorageEvictorTest : public testing::Test { return num_get_usage_and_quota_for_eviction_; } + BucketId::Generator bucket_id_generator_; base::test::TaskEnvironment task_environment_; std::unique_ptr<MockQuotaEvictionHandler> quota_eviction_handler_; std::unique_ptr<QuotaTemporaryStorageEvictor> temporary_storage_evictor_; @@ -222,9 +226,12 @@ class QuotaTemporaryStorageEvictorTest : public testing::Test { }; TEST_F(QuotaTemporaryStorageEvictorTest, SimpleEvictionTest) { - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.z.com"), 3000); - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.y.com"), 200); - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.x.com"), 500); + quota_eviction_handler()->AddBucket(CreateBucket("http://www.z.com", "test"), + 3000); + quota_eviction_handler()->AddBucket(CreateBucket("http://www.y.com", "test"), + 200); + quota_eviction_handler()->AddBucket(CreateBucket("http://www.x.com", "test"), + 500); quota_eviction_handler()->SetPoolSize(4000); quota_eviction_handler()->set_available_space(1000000000); EXPECT_EQ(3000 + 200 + 500, quota_eviction_handler()->GetUsage()); @@ -234,16 +241,20 @@ TEST_F(QuotaTemporaryStorageEvictorTest, SimpleEvictionTest) { EXPECT_EQ(200 + 500, quota_eviction_handler()->GetUsage()); EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota); - EXPECT_EQ(1, statistics().num_evicted_origins); + EXPECT_EQ(1, statistics().num_evicted_buckets); EXPECT_EQ(1, statistics().num_eviction_rounds); EXPECT_EQ(0, statistics().num_skipped_eviction_rounds); } TEST_F(QuotaTemporaryStorageEvictorTest, MultipleEvictionTest) { - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.z.com"), 20); - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.y.com"), 2900); - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.x.com"), 450); - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.w.com"), 400); + quota_eviction_handler()->AddBucket( + CreateBucket("http://www.z.com", kDefaultBucketName), 20); + quota_eviction_handler()->AddBucket( + CreateBucket("http://www.y.com", kDefaultBucketName), 2900); + quota_eviction_handler()->AddBucket( + CreateBucket("http://www.x.com", kDefaultBucketName), 450); + quota_eviction_handler()->AddBucket( + CreateBucket("http://www.w.com", kDefaultBucketName), 400); quota_eviction_handler()->SetPoolSize(4000); quota_eviction_handler()->set_available_space(1000000000); EXPECT_EQ(20 + 2900 + 450 + 400, quota_eviction_handler()->GetUsage()); @@ -253,7 +264,7 @@ TEST_F(QuotaTemporaryStorageEvictorTest, MultipleEvictionTest) { EXPECT_EQ(450 + 400, quota_eviction_handler()->GetUsage()); EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota); - EXPECT_EQ(2, statistics().num_evicted_origins); + EXPECT_EQ(2, statistics().num_evicted_buckets); EXPECT_EQ(1, statistics().num_eviction_rounds); EXPECT_EQ(0, statistics().num_skipped_eviction_rounds); } @@ -266,18 +277,22 @@ TEST_F(QuotaTemporaryStorageEvictorTest, RepeatedEvictionTest) { const int64_t initial_total_size = a_size + b_size + c_size + d_size; const int64_t e_size = 275; - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.d.com"), d_size); - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.c.com"), c_size); - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.b.com"), b_size); - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.a.com"), a_size); + quota_eviction_handler()->AddBucket(CreateBucket("http://www.d.com", "test"), + d_size); + quota_eviction_handler()->AddBucket(CreateBucket("http://www.c.com", "test"), + c_size); + quota_eviction_handler()->AddBucket(CreateBucket("http://www.b.com", "test"), + b_size); + quota_eviction_handler()->AddBucket(CreateBucket("http://www.a.com", "test"), + a_size); quota_eviction_handler()->SetPoolSize(1000); quota_eviction_handler()->set_available_space(1000000000); quota_eviction_handler()->set_task_for_get_usage_and_quota( base::BindRepeating( &QuotaTemporaryStorageEvictorTest::TaskForRepeatedEvictionTest, weak_factory_.GetWeakPtr(), - std::make_pair(ToOrigin("http://www.e.com"), e_size), absl::nullopt, - initial_total_size - d_size, + std::make_pair(CreateBucket("http://www.e.com", "test"), e_size), + absl::nullopt, initial_total_size - d_size, initial_total_size - d_size + e_size - c_size)); EXPECT_EQ(initial_total_size, quota_eviction_handler()->GetUsage()); temporary_storage_evictor()->Start(); @@ -287,7 +302,7 @@ TEST_F(QuotaTemporaryStorageEvictorTest, RepeatedEvictionTest) { EXPECT_EQ(5, num_get_usage_and_quota_for_eviction()); EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota); - EXPECT_EQ(3, statistics().num_evicted_origins); + EXPECT_EQ(3, statistics().num_evicted_buckets); EXPECT_EQ(2, statistics().num_eviction_rounds); EXPECT_EQ(0, statistics().num_skipped_eviction_rounds); } @@ -299,10 +314,14 @@ TEST_F(QuotaTemporaryStorageEvictorTest, RepeatedEvictionSkippedTest) { const int64_t d_size = 292; const int64_t initial_total_size = a_size + b_size + c_size + d_size; - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.d.com"), d_size); - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.c.com"), c_size); - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.b.com"), b_size); - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.a.com"), a_size); + quota_eviction_handler()->AddBucket( + CreateBucket("http://www.d.com", kDefaultBucketName), d_size); + quota_eviction_handler()->AddBucket( + CreateBucket("http://www.c.com", kDefaultBucketName), c_size); + quota_eviction_handler()->AddBucket( + CreateBucket("http://www.b.com", kDefaultBucketName), b_size); + quota_eviction_handler()->AddBucket( + CreateBucket("http://www.a.com", kDefaultBucketName), a_size); quota_eviction_handler()->SetPoolSize(1000); quota_eviction_handler()->set_available_space(1000000000); quota_eviction_handler()->set_task_for_get_usage_and_quota( @@ -319,12 +338,12 @@ TEST_F(QuotaTemporaryStorageEvictorTest, RepeatedEvictionSkippedTest) { EXPECT_EQ(4, num_get_usage_and_quota_for_eviction()); EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota); - EXPECT_EQ(1, statistics().num_evicted_origins); + EXPECT_EQ(1, statistics().num_evicted_buckets); EXPECT_EQ(3, statistics().num_eviction_rounds); EXPECT_EQ(2, statistics().num_skipped_eviction_rounds); } -TEST_F(QuotaTemporaryStorageEvictorTest, RepeatedEvictionWithAccessOriginTest) { +TEST_F(QuotaTemporaryStorageEvictorTest, RepeatedEvictionWithAccessBucketTest) { const int64_t a_size = 400; const int64_t b_size = 150; const int64_t c_size = 120; @@ -332,18 +351,23 @@ TEST_F(QuotaTemporaryStorageEvictorTest, RepeatedEvictionWithAccessOriginTest) { const int64_t initial_total_size = a_size + b_size + c_size + d_size; const int64_t e_size = 275; - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.d.com"), d_size); - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.c.com"), c_size); - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.b.com"), b_size); - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.a.com"), a_size); + BucketInfo a_bucket = CreateBucket("http://www.a.com", kDefaultBucketName); + BucketInfo b_bucket = CreateBucket("http://www.b.com", kDefaultBucketName); + BucketInfo c_bucket = CreateBucket("http://www.c.com", kDefaultBucketName); + BucketInfo d_bucket = CreateBucket("http://www.d.com", kDefaultBucketName); + BucketInfo e_bucket = CreateBucket("http://www.e.com", kDefaultBucketName); + + quota_eviction_handler()->AddBucket(d_bucket, d_size); + quota_eviction_handler()->AddBucket(c_bucket, c_size); + quota_eviction_handler()->AddBucket(b_bucket, b_size); + quota_eviction_handler()->AddBucket(a_bucket, a_size); quota_eviction_handler()->SetPoolSize(1000); quota_eviction_handler()->set_available_space(1000000000); quota_eviction_handler()->set_task_for_get_usage_and_quota( base::BindRepeating( &QuotaTemporaryStorageEvictorTest::TaskForRepeatedEvictionTest, - weak_factory_.GetWeakPtr(), - std::make_pair(ToOrigin("http://www.e.com"), e_size), - ToOrigin("http://www.c.com"), initial_total_size - d_size, + weak_factory_.GetWeakPtr(), std::make_pair(e_bucket, e_size), + c_bucket, initial_total_size - d_size, initial_total_size - d_size + e_size - b_size)); EXPECT_EQ(initial_total_size, quota_eviction_handler()->GetUsage()); temporary_storage_evictor()->Start(); @@ -353,7 +377,7 @@ TEST_F(QuotaTemporaryStorageEvictorTest, RepeatedEvictionWithAccessOriginTest) { EXPECT_EQ(5, num_get_usage_and_quota_for_eviction()); EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota); - EXPECT_EQ(3, statistics().num_evicted_origins); + EXPECT_EQ(3, statistics().num_evicted_buckets); EXPECT_EQ(2, statistics().num_eviction_rounds); EXPECT_EQ(0, statistics().num_skipped_eviction_rounds); } @@ -361,8 +385,10 @@ TEST_F(QuotaTemporaryStorageEvictorTest, RepeatedEvictionWithAccessOriginTest) { TEST_F(QuotaTemporaryStorageEvictorTest, DiskSpaceNonEvictionTest) { // If we're using so little that evicting all of it wouldn't // do enough to alleviate a diskspace shortage, we don't evict. - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.z.com"), 10); - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.x.com"), 20); + quota_eviction_handler()->AddBucket( + CreateBucket("http://www.z.com", kDefaultBucketName), 10); + quota_eviction_handler()->AddBucket( + CreateBucket("http://www.x.com", kDefaultBucketName), 20); quota_eviction_handler()->SetPoolSize(10000); quota_eviction_handler()->set_available_space( quota_eviction_handler()->settings().should_remain_available - 350); @@ -373,16 +399,20 @@ TEST_F(QuotaTemporaryStorageEvictorTest, DiskSpaceNonEvictionTest) { EXPECT_EQ(10 + 20, quota_eviction_handler()->GetUsage()); EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota); - EXPECT_EQ(0, statistics().num_evicted_origins); + EXPECT_EQ(0, statistics().num_evicted_buckets); EXPECT_EQ(1, statistics().num_eviction_rounds); EXPECT_EQ(1, statistics().num_skipped_eviction_rounds); } TEST_F(QuotaTemporaryStorageEvictorTest, DiskSpaceEvictionTest) { - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.z.com"), 294); - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.y.com"), 120); - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.x.com"), 150); - quota_eviction_handler()->AddOrigin(ToOrigin("http://www.w.com"), 300); + quota_eviction_handler()->AddBucket( + CreateBucket("http://www.z.com", kDefaultBucketName), 294); + quota_eviction_handler()->AddBucket( + CreateBucket("http://www.y.com", kDefaultBucketName), 120); + quota_eviction_handler()->AddBucket( + CreateBucket("http://www.x.com", kDefaultBucketName), 150); + quota_eviction_handler()->AddBucket( + CreateBucket("http://www.w.com", kDefaultBucketName), 300); quota_eviction_handler()->SetPoolSize(10000); quota_eviction_handler()->set_available_space( quota_eviction_handler()->settings().should_remain_available - 350); @@ -393,7 +423,7 @@ TEST_F(QuotaTemporaryStorageEvictorTest, DiskSpaceEvictionTest) { EXPECT_EQ(150 + 300, quota_eviction_handler()->GetUsage()); EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota); - EXPECT_EQ(2, statistics().num_evicted_origins); + EXPECT_EQ(2, statistics().num_evicted_buckets); EXPECT_EQ(1, statistics().num_eviction_rounds); EXPECT_EQ(0, statistics().num_skipped_eviction_rounds); // FIXME? } diff --git a/chromium/storage/browser/quota/usage_tracker.cc b/chromium/storage/browser/quota/usage_tracker.cc index af66268abeb..8d702005fd3 100644 --- a/chromium/storage/browser/quota/usage_tracker.cc +++ b/chromium/storage/browser/quota/usage_tracker.cc @@ -13,6 +13,7 @@ #include "base/bind.h" #include "storage/browser/quota/client_usage_tracker.h" #include "storage/browser/quota/quota_client_type.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" namespace storage { @@ -28,14 +29,14 @@ struct UsageTracker::AccumulateInfo { }; UsageTracker::UsageTracker( - const base::flat_map<QuotaClient*, QuotaClientType>& client_types, + const base::flat_map<mojom::QuotaClient*, QuotaClientType>& client_types, blink::mojom::StorageType type, scoped_refptr<SpecialStoragePolicy> special_storage_policy) : type_(type) { size_t client_count = 0; for (const auto& client_and_type : client_types) { - QuotaClient* client = client_and_type.first; + mojom::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, @@ -105,12 +106,12 @@ void UsageTracker::GetHostUsageWithBreakdown( } void UsageTracker::UpdateUsageCache(QuotaClientType client_type, - const url::Origin& origin, + const blink::StorageKey& storage_key, int64_t delta) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(client_tracker_map_.count(client_type)); for (const auto& client_tracker : client_tracker_map_[client_type]) - client_tracker->UpdateUsageCache(origin, delta); + client_tracker->UpdateUsageCache(storage_key, delta); } int64_t UsageTracker::GetCachedUsage() const { @@ -137,40 +138,43 @@ std::map<std::string, int64_t> UsageTracker::GetCachedHostsUsage() const { return host_usage; } -std::map<url::Origin, int64_t> UsageTracker::GetCachedOriginsUsage() const { +std::map<blink::StorageKey, int64_t> UsageTracker::GetCachedStorageKeysUsage() + const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - std::map<url::Origin, int64_t> origin_usage; + std::map<blink::StorageKey, int64_t> storage_key_usage; 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; + std::map<blink::StorageKey, int64_t> client_storage_key_usage = + client_tracker->GetCachedStorageKeysUsage(); + for (const auto& storage_key_and_usage : client_storage_key_usage) + storage_key_usage[storage_key_and_usage.first] += + storage_key_and_usage.second; } } - return origin_usage; + return storage_key_usage; } -std::set<url::Origin> UsageTracker::GetCachedOrigins() const { +std::set<blink::StorageKey> UsageTracker::GetCachedStorageKeys() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - std::set<url::Origin> origins; + std::set<blink::StorageKey> storage_keys; 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); + std::set<blink::StorageKey> client_storage_keys = + client_tracker->GetCachedStorageKeys(); + for (const auto& client_storage_key : client_storage_keys) + storage_keys.insert(client_storage_key); } } - return origins; + return storage_keys; } void UsageTracker::SetUsageCacheEnabled(QuotaClientType client_type, - const url::Origin& origin, + const blink::StorageKey& storage_key, bool enabled) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(client_tracker_map_.count(client_type)); for (const auto& client_tracker : client_tracker_map_[client_type]) - client_tracker->SetUsageCacheEnabled(origin, enabled); + client_tracker->SetUsageCacheEnabled(storage_key, enabled); } void UsageTracker::AccumulateClientGlobalUsage(AccumulateInfo* info, diff --git a/chromium/storage/browser/quota/usage_tracker.h b/chromium/storage/browser/quota/usage_tracker.h index a2bdbf4c0b3..7c300eae9cb 100644 --- a/chromium/storage/browser/quota/usage_tracker.h +++ b/chromium/storage/browser/quota/usage_tracker.h @@ -18,13 +18,16 @@ #include "base/containers/flat_map.h" #include "base/memory/scoped_refptr.h" #include "base/sequence_checker.h" +#include "components/services/storage/public/mojom/quota_client.mojom.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" -#include "url/origin.h" + +namespace blink { +class StorageKey; +} // namespace blink namespace storage { @@ -39,11 +42,10 @@ class ClientUsageTracker; class COMPONENT_EXPORT(STORAGE_BROWSER) UsageTracker : public QuotaTaskObserver { public: - // TODO(crbug.com/1163009): Switch the map key type in `client_types` to - // mojom::QuotaClient* after all QuotaClients have - // been mojofied. + // The caller must ensure that all mojo::QuotaClient instances outlive this + // instance. UsageTracker( - const base::flat_map<QuotaClient*, QuotaClientType>& client_types, + const base::flat_map<mojom::QuotaClient*, QuotaClientType>& client_types, blink::mojom::StorageType type, scoped_refptr<SpecialStoragePolicy> special_storage_policy); @@ -61,19 +63,19 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) UsageTracker void GetHostUsageWithBreakdown(const std::string& host, UsageWithBreakdownCallback callback); void UpdateUsageCache(QuotaClientType client_type, - const url::Origin& origin, + const blink::StorageKey& storage_key, int64_t delta); int64_t GetCachedUsage() const; std::map<std::string, int64_t> GetCachedHostsUsage() const; - std::map<url::Origin, int64_t> GetCachedOriginsUsage() const; - std::set<url::Origin> GetCachedOrigins() const; + std::map<blink::StorageKey, int64_t> GetCachedStorageKeysUsage() const; + std::set<blink::StorageKey> GetCachedStorageKeys() const; bool IsWorking() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return !global_usage_callbacks_.empty() || !host_usage_callbacks_.empty(); } void SetUsageCacheEnabled(QuotaClientType client_type, - const url::Origin& origin, + const blink::StorageKey& storage_key, bool enabled); private: diff --git a/chromium/storage/browser/quota/usage_tracker_unittest.cc b/chromium/storage/browser/quota/usage_tracker_unittest.cc index c3016b801d0..92bd1711213 100644 --- a/chromium/storage/browser/quota/usage_tracker_unittest.cc +++ b/chromium/storage/browser/quota/usage_tracker_unittest.cc @@ -15,13 +15,16 @@ #include "base/single_thread_task_runner.h" #include "base/test/task_environment.h" #include "base/threading/thread_task_runner_handle.h" +#include "components/services/storage/public/mojom/quota_client.mojom.h" #include "storage/browser/quota/quota_client_type.h" #include "storage/browser/quota/usage_tracker.h" #include "storage/browser/test/mock_special_storage_policy.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" -using blink::mojom::QuotaStatusCode; -using blink::mojom::StorageType; +using ::blink::StorageKey; +using ::blink::mojom::QuotaStatusCode; +using ::blink::mojom::StorageType; namespace storage { @@ -38,49 +41,49 @@ void DidGetGlobalUsage(bool* done, *unlimited_usage_out = unlimited_usage; } -class UsageTrackerTestQuotaClient : public QuotaClient { +class UsageTrackerTestQuotaClient : public mojom::QuotaClient { public: UsageTrackerTestQuotaClient() = default; - void OnQuotaManagerDestroyed() override {} - - void GetOriginUsage(const url::Origin& origin, - StorageType type, - GetOriginUsageCallback callback) override { + void GetStorageKeyUsage(const StorageKey& storage_key, + StorageType type, + GetStorageKeyUsageCallback callback) override { EXPECT_EQ(StorageType::kTemporary, type); - int64_t usage = GetUsage(origin); + int64_t usage = GetUsage(storage_key); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), usage)); } - void GetOriginsForType(StorageType type, - GetOriginsForTypeCallback callback) override { + void GetStorageKeysForType(StorageType type, + GetStorageKeysForTypeCallback callback) override { EXPECT_EQ(StorageType::kTemporary, type); - std::vector<url::Origin> origins; - for (const auto& origin_usage_pair : origin_usage_map_) - origins.push_back(origin_usage_pair.first); + std::vector<StorageKey> storage_keys; + for (const auto& storage_key_usage_pair : storage_key_usage_map_) + storage_keys.push_back(storage_key_usage_pair.first); base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), std::move(origins))); + FROM_HERE, + base::BindOnce(std::move(callback), std::move(storage_keys))); } - void GetOriginsForHost(StorageType type, - const std::string& host, - GetOriginsForHostCallback callback) override { + void GetStorageKeysForHost(StorageType type, + const std::string& host, + GetStorageKeysForHostCallback callback) override { EXPECT_EQ(StorageType::kTemporary, type); - std::vector<url::Origin> origins; - for (const auto& origin_usage_pair : origin_usage_map_) { - if (origin_usage_pair.first.host() == host) - origins.push_back(origin_usage_pair.first); + std::vector<StorageKey> storage_keys; + for (const auto& storage_key_usage_pair : storage_key_usage_map_) { + if (storage_key_usage_pair.first.origin().host() == host) + storage_keys.push_back(storage_key_usage_pair.first); } base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), std::move(origins))); + FROM_HERE, + base::BindOnce(std::move(callback), std::move(storage_keys))); } - void DeleteOriginData(const url::Origin& origin, - StorageType type, - DeleteOriginDataCallback callback) override { + void DeleteStorageKeyData(const StorageKey& storage_key, + StorageType type, + DeleteStorageKeyDataCallback callback) override { EXPECT_EQ(StorageType::kTemporary, type); - origin_usage_map_.erase(origin); + storage_key_usage_map_.erase(storage_key); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), QuotaStatusCode::kOk)); } @@ -90,25 +93,23 @@ class UsageTrackerTestQuotaClient : public QuotaClient { std::move(callback).Run(); } - int64_t GetUsage(const url::Origin& origin) { - auto it = origin_usage_map_.find(origin); - if (it == origin_usage_map_.end()) + int64_t GetUsage(const StorageKey& storage_key) { + auto it = storage_key_usage_map_.find(storage_key); + if (it == storage_key_usage_map_.end()) return 0; return it->second; } - void SetUsage(const url::Origin& origin, int64_t usage) { - origin_usage_map_[origin] = usage; + void SetUsage(const StorageKey& storage_key, int64_t usage) { + storage_key_usage_map_[storage_key] = usage; } - int64_t UpdateUsage(const url::Origin& origin, int64_t delta) { - return origin_usage_map_[origin] += delta; + int64_t UpdateUsage(const StorageKey& storage_key, int64_t delta) { + return storage_key_usage_map_[storage_key] += delta; } private: - ~UsageTrackerTestQuotaClient() override = default; - - std::map<url::Origin, int64_t> origin_usage_map_; + std::map<StorageKey, int64_t> storage_key_usage_map_; DISALLOW_COPY_AND_ASSIGN(UsageTrackerTestQuotaClient); }; @@ -119,7 +120,7 @@ class UsageTrackerTest : public testing::Test { public: UsageTrackerTest() : storage_policy_(base::MakeRefCounted<MockSpecialStoragePolicy>()), - quota_client_(base::MakeRefCounted<UsageTrackerTestQuotaClient>()), + quota_client_(std::make_unique<UsageTrackerTestQuotaClient>()), usage_tracker_(GetQuotaClientMap(), StorageType::kTemporary, storage_policy_.get()) {} @@ -142,16 +143,16 @@ class UsageTrackerTest : public testing::Test { *done = true; } - void UpdateUsage(const url::Origin& origin, int64_t delta) { - quota_client_->UpdateUsage(origin, delta); - usage_tracker_.UpdateUsageCache(QuotaClientType::kFileSystem, origin, + void UpdateUsage(const StorageKey& storage_key, int64_t delta) { + quota_client_->UpdateUsage(storage_key, delta); + usage_tracker_.UpdateUsageCache(QuotaClientType::kFileSystem, storage_key, delta); base::RunLoop().RunUntilIdle(); } - void UpdateUsageWithoutNotification(const url::Origin& origin, + void UpdateUsageWithoutNotification(const StorageKey& storage_key, int64_t delta) { - quota_client_->UpdateUsage(origin, delta); + quota_client_->UpdateUsage(storage_key, delta); } void GetGlobalUsage(int64_t* usage, int64_t* unlimited_usage) { @@ -177,30 +178,30 @@ class UsageTrackerTest : public testing::Test { return std::make_pair(usage, std::move(usage_breakdown)); } - void GrantUnlimitedStoragePolicy(const url::Origin& origin) { - if (!storage_policy_->IsStorageUnlimited(origin.GetURL())) { - storage_policy_->AddUnlimited(origin.GetURL()); - storage_policy_->NotifyGranted(origin, + void GrantUnlimitedStoragePolicy(const StorageKey& storage_key) { + if (!storage_policy_->IsStorageUnlimited(storage_key.origin().GetURL())) { + storage_policy_->AddUnlimited(storage_key.origin().GetURL()); + storage_policy_->NotifyGranted(storage_key.origin(), SpecialStoragePolicy::STORAGE_UNLIMITED); } } - void RevokeUnlimitedStoragePolicy(const url::Origin& origin) { - if (storage_policy_->IsStorageUnlimited(origin.GetURL())) { - storage_policy_->RemoveUnlimited(origin.GetURL()); - storage_policy_->NotifyRevoked(origin, + void RevokeUnlimitedStoragePolicy(const StorageKey& storage_key) { + if (storage_policy_->IsStorageUnlimited(storage_key.origin().GetURL())) { + storage_policy_->RemoveUnlimited(storage_key.origin().GetURL()); + storage_policy_->NotifyRevoked(storage_key.origin(), SpecialStoragePolicy::STORAGE_UNLIMITED); } } - void SetUsageCacheEnabled(const url::Origin& origin, bool enabled) { - usage_tracker_.SetUsageCacheEnabled(QuotaClientType::kFileSystem, origin, - enabled); + void SetUsageCacheEnabled(const StorageKey& storage_key, bool enabled) { + usage_tracker_.SetUsageCacheEnabled(QuotaClientType::kFileSystem, + storage_key, enabled); } private: - base::flat_map<QuotaClient*, QuotaClientType> GetQuotaClientMap() { - base::flat_map<QuotaClient*, QuotaClientType> client_map; + base::flat_map<mojom::QuotaClient*, QuotaClientType> GetQuotaClientMap() { + base::flat_map<mojom::QuotaClient*, QuotaClientType> client_map; client_map.insert( std::make_pair(quota_client_.get(), QuotaClientType::kFileSystem)); return client_map; @@ -209,7 +210,7 @@ class UsageTrackerTest : public testing::Test { base::test::TaskEnvironment task_environment_; scoped_refptr<MockSpecialStoragePolicy> storage_policy_; - scoped_refptr<UsageTrackerTestQuotaClient> quota_client_; + std::unique_ptr<UsageTrackerTestQuotaClient> quota_client_; UsageTracker usage_tracker_; DISALLOW_COPY_AND_ASSIGN(UsageTrackerTest); @@ -224,11 +225,11 @@ TEST_F(UsageTrackerTest, GrantAndRevokeUnlimitedStorage) { EXPECT_EQ(0, usage); EXPECT_EQ(0, unlimited_usage); - // TODO(crbug.com/889590): Use helper for url::Origin creation from string. - const url::Origin origin = url::Origin::Create(GURL("http://example.com")); - const std::string& host = origin.host(); + const StorageKey storage_key = + StorageKey::CreateFromStringForTesting("http://example.com"); + const std::string& host = storage_key.origin().host(); - UpdateUsage(origin, 100); + UpdateUsage(storage_key, 100); GetGlobalUsage(&usage, &unlimited_usage); EXPECT_EQ(100, usage); EXPECT_EQ(0, unlimited_usage); @@ -238,7 +239,7 @@ TEST_F(UsageTrackerTest, GrantAndRevokeUnlimitedStorage) { EXPECT_EQ(100, host_usage_breakdown.first); EXPECT_EQ(host_usage_breakdown_expected, host_usage_breakdown.second); - GrantUnlimitedStoragePolicy(origin); + GrantUnlimitedStoragePolicy(storage_key); GetGlobalUsage(&usage, &unlimited_usage); EXPECT_EQ(100, usage); EXPECT_EQ(100, unlimited_usage); @@ -246,7 +247,7 @@ TEST_F(UsageTrackerTest, GrantAndRevokeUnlimitedStorage) { EXPECT_EQ(100, host_usage_breakdown.first); EXPECT_EQ(host_usage_breakdown_expected, host_usage_breakdown.second); - RevokeUnlimitedStoragePolicy(origin); + RevokeUnlimitedStoragePolicy(storage_key); GetGlobalUsage(&usage, &unlimited_usage); EXPECT_EQ(100, usage); EXPECT_EQ(0, unlimited_usage); @@ -261,10 +262,11 @@ TEST_F(UsageTrackerTest, CacheDisabledClientTest) { blink::mojom::UsageBreakdownPtr host_usage_breakdown_expected = blink::mojom::UsageBreakdown::New(); - const url::Origin origin = url::Origin::Create(GURL("http://example.com")); - const std::string& host = origin.host(); + const StorageKey storage_key = + StorageKey::CreateFromStringForTesting("http://example.com"); + const std::string& host = storage_key.origin().host(); - UpdateUsage(origin, 100); + UpdateUsage(storage_key, 100); GetGlobalUsage(&usage, &unlimited_usage); EXPECT_EQ(100, usage); EXPECT_EQ(0, unlimited_usage); @@ -274,7 +276,7 @@ TEST_F(UsageTrackerTest, CacheDisabledClientTest) { EXPECT_EQ(100, host_usage_breakdown.first); EXPECT_EQ(host_usage_breakdown_expected, host_usage_breakdown.second); - UpdateUsageWithoutNotification(origin, 100); + UpdateUsageWithoutNotification(storage_key, 100); GetGlobalUsage(&usage, &unlimited_usage); EXPECT_EQ(100, usage); EXPECT_EQ(0, unlimited_usage); @@ -282,10 +284,10 @@ TEST_F(UsageTrackerTest, CacheDisabledClientTest) { EXPECT_EQ(100, host_usage_breakdown.first); EXPECT_EQ(host_usage_breakdown_expected, host_usage_breakdown.second); - GrantUnlimitedStoragePolicy(origin); - UpdateUsageWithoutNotification(origin, 100); - SetUsageCacheEnabled(origin, false); - UpdateUsageWithoutNotification(origin, 100); + GrantUnlimitedStoragePolicy(storage_key); + UpdateUsageWithoutNotification(storage_key, 100); + SetUsageCacheEnabled(storage_key, false); + UpdateUsageWithoutNotification(storage_key, 100); GetGlobalUsage(&usage, &unlimited_usage); EXPECT_EQ(400, usage); @@ -295,7 +297,7 @@ TEST_F(UsageTrackerTest, CacheDisabledClientTest) { EXPECT_EQ(400, host_usage_breakdown.first); EXPECT_EQ(host_usage_breakdown_expected, host_usage_breakdown.second); - RevokeUnlimitedStoragePolicy(origin); + RevokeUnlimitedStoragePolicy(storage_key); GetGlobalUsage(&usage, &unlimited_usage); EXPECT_EQ(400, usage); EXPECT_EQ(0, unlimited_usage); @@ -303,8 +305,8 @@ TEST_F(UsageTrackerTest, CacheDisabledClientTest) { EXPECT_EQ(400, host_usage_breakdown.first); EXPECT_EQ(host_usage_breakdown_expected, host_usage_breakdown.second); - SetUsageCacheEnabled(origin, true); - UpdateUsage(origin, 100); + SetUsageCacheEnabled(storage_key, true); + UpdateUsage(storage_key, 100); GetGlobalUsage(&usage, &unlimited_usage); EXPECT_EQ(500, usage); @@ -316,11 +318,14 @@ TEST_F(UsageTrackerTest, CacheDisabledClientTest) { } TEST_F(UsageTrackerTest, GlobalUsageUnlimitedUncached) { - const url::Origin kNormal = url::Origin::Create(GURL("http://normal")); - const url::Origin kUnlimited = url::Origin::Create(GURL("http://unlimited")); - const url::Origin kNonCached = url::Origin::Create(GURL("http://non_cached")); - const url::Origin kNonCachedUnlimited = - url::Origin::Create(GURL("http://non_cached-unlimited")); + const StorageKey kNormal = + StorageKey::CreateFromStringForTesting("http://normal"); + const StorageKey kUnlimited = + StorageKey::CreateFromStringForTesting("http://unlimited"); + const StorageKey kNonCached = + StorageKey::CreateFromStringForTesting("http://non_cached"); + const StorageKey kNonCachedUnlimited = + StorageKey::CreateFromStringForTesting("http://non_cached-unlimited"); GrantUnlimitedStoragePolicy(kUnlimited); GrantUnlimitedStoragePolicy(kNonCachedUnlimited); @@ -348,94 +353,98 @@ TEST_F(UsageTrackerTest, GlobalUsageUnlimitedUncached) { EXPECT_EQ(2 + 32, unlimited_usage); } -TEST_F(UsageTrackerTest, GlobalUsageMultipleOriginsPerHostCachedInit) { - const url::Origin kOrigin1 = url::Origin::Create(GURL("http://example.com")); - const url::Origin kOrigin2 = - url::Origin::Create(GURL("http://example.com:8080")); - ASSERT_EQ(kOrigin1.host(), kOrigin2.host()) - << "The test assumes that the two origins have the same host"; +TEST_F(UsageTrackerTest, GlobalUsageMultipleStorageKeysPerHostCachedInit) { + const StorageKey kStorageKey1 = + StorageKey::CreateFromStringForTesting("http://example.com"); + const StorageKey kStorageKey2 = + StorageKey::CreateFromStringForTesting("http://example.com:8080"); + ASSERT_EQ(kStorageKey1.origin().host(), kStorageKey2.origin().host()) + << "The test assumes that the two storage keys have the same host"; - UpdateUsageWithoutNotification(kOrigin1, 100); - UpdateUsageWithoutNotification(kOrigin2, 200); + UpdateUsageWithoutNotification(kStorageKey1, 100); + UpdateUsageWithoutNotification(kStorageKey2, 200); int64_t total_usage = 0; int64_t unlimited_usage = 0; // GetGlobalUsage() takes different code paths on the first call and on // subsequent calls. This test covers the code path used by the first call. - // Therefore, we introduce the origins before the first call. + // Therefore, we introduce the storage_keys before the first call. GetGlobalUsage(&total_usage, &unlimited_usage); EXPECT_EQ(100 + 200, total_usage); EXPECT_EQ(0, unlimited_usage); } -TEST_F(UsageTrackerTest, GlobalUsageMultipleOriginsPerHostCachedUpdate) { - const url::Origin kOrigin1 = url::Origin::Create(GURL("http://example.com")); - const url::Origin kOrigin2 = - url::Origin::Create(GURL("http://example.com:8080")); - ASSERT_EQ(kOrigin1.host(), kOrigin2.host()) - << "The test assumes that the two origins have the same host"; +TEST_F(UsageTrackerTest, GlobalUsageMultipleStorageKeysPerHostCachedUpdate) { + const StorageKey kStorageKey1 = + StorageKey::CreateFromStringForTesting("http://example.com"); + const StorageKey kStorageKey2 = + StorageKey::CreateFromStringForTesting("http://example.com:8080"); + ASSERT_EQ(kStorageKey1.origin().host(), kStorageKey2.origin().host()) + << "The test assumes that the two storage keys have the same host"; int64_t total_usage = 0; int64_t unlimited_usage = 0; // GetGlobalUsage() takes different code paths on the first call and on // subsequent calls. This test covers the code path used by subsequent calls. - // Therefore, we introduce the origins after the first call. + // Therefore, we introduce the storage keys after the first call. GetGlobalUsage(&total_usage, &unlimited_usage); EXPECT_EQ(0, total_usage); EXPECT_EQ(0, unlimited_usage); - UpdateUsage(kOrigin1, 100); - UpdateUsage(kOrigin2, 200); + UpdateUsage(kStorageKey1, 100); + UpdateUsage(kStorageKey2, 200); GetGlobalUsage(&total_usage, &unlimited_usage); EXPECT_EQ(100 + 200, total_usage); EXPECT_EQ(0, unlimited_usage); } -TEST_F(UsageTrackerTest, GlobalUsageMultipleOriginsPerHostUncachedInit) { - const url::Origin kOrigin1 = url::Origin::Create(GURL("http://example.com")); - const url::Origin kOrigin2 = - url::Origin::Create(GURL("http://example.com:8080")); - ASSERT_EQ(kOrigin1.host(), kOrigin2.host()) - << "The test assumes that the two origins have the same host"; +TEST_F(UsageTrackerTest, GlobalUsageMultipleStorageKeysPerHostUncachedInit) { + const StorageKey kStorageKey1 = + StorageKey::CreateFromStringForTesting("http://example.com"); + const StorageKey kStorageKey2 = + StorageKey::CreateFromStringForTesting("http://example.com:8080"); + ASSERT_EQ(kStorageKey1.origin().host(), kStorageKey2.origin().host()) + << "The test assumes that the two storage keys have the same host"; - SetUsageCacheEnabled(kOrigin1, false); - SetUsageCacheEnabled(kOrigin2, false); + SetUsageCacheEnabled(kStorageKey1, false); + SetUsageCacheEnabled(kStorageKey2, false); - UpdateUsageWithoutNotification(kOrigin1, 100); - UpdateUsageWithoutNotification(kOrigin2, 200); + UpdateUsageWithoutNotification(kStorageKey1, 100); + UpdateUsageWithoutNotification(kStorageKey2, 200); int64_t total_usage = 0; int64_t unlimited_usage = 0; // GetGlobalUsage() takes different code paths on the first call and on // subsequent calls. This test covers the code path used by the first call. - // Therefore, we introduce the origins before the first call. + // Therefore, we introduce the storage keys before the first call. GetGlobalUsage(&total_usage, &unlimited_usage); EXPECT_EQ(100 + 200, total_usage); EXPECT_EQ(0, unlimited_usage); } -TEST_F(UsageTrackerTest, GlobalUsageMultipleOriginsPerHostUncachedUpdate) { - const url::Origin kOrigin1 = url::Origin::Create(GURL("http://example.com")); - const url::Origin kOrigin2 = - url::Origin::Create(GURL("http://example.com:8080")); - ASSERT_EQ(kOrigin1.host(), kOrigin2.host()) - << "The test assumes that the two origins have the same host"; +TEST_F(UsageTrackerTest, GlobalUsageMultipleStorageKeysPerHostUncachedUpdate) { + const StorageKey kStorageKey1 = + StorageKey::CreateFromStringForTesting("http://example.com"); + const StorageKey kStorageKey2 = + StorageKey::CreateFromStringForTesting("http://example.com:8080"); + ASSERT_EQ(kStorageKey1.origin().host(), kStorageKey2.origin().host()) + << "The test assumes that the two storage keys have the same host"; int64_t total_usage = 0; int64_t unlimited_usage = 0; // GetGlobalUsage() takes different code paths on the first call and on // subsequent calls. This test covers the code path used by subsequent calls. - // Therefore, we introduce the origins after the first call. + // Therefore, we introduce the storage keys after the first call. GetGlobalUsage(&total_usage, &unlimited_usage); EXPECT_EQ(0, total_usage); EXPECT_EQ(0, unlimited_usage); - SetUsageCacheEnabled(kOrigin1, false); - SetUsageCacheEnabled(kOrigin2, false); + SetUsageCacheEnabled(kStorageKey1, false); + SetUsageCacheEnabled(kStorageKey2, false); - UpdateUsageWithoutNotification(kOrigin1, 100); - UpdateUsageWithoutNotification(kOrigin2, 200); + UpdateUsageWithoutNotification(kStorageKey1, 100); + UpdateUsageWithoutNotification(kStorageKey2, 200); GetGlobalUsage(&total_usage, &unlimited_usage); EXPECT_EQ(100 + 200, total_usage); diff --git a/chromium/storage/common/BUILD.gn b/chromium/storage/common/BUILD.gn index 26e2ec35062..24a966a951c 100644 --- a/chromium/storage/common/BUILD.gn +++ b/chromium/storage/common/BUILD.gn @@ -19,9 +19,7 @@ component("common") { "quota/padding_key.h", ] - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. configs += [ - "//build/config/compiler:no_size_t_to_int_warning", "//build/config/compiler:wexit_time_destructors", ] diff --git a/chromium/storage/common/database/DIR_METADATA b/chromium/storage/common/database/DIR_METADATA index 67bdd01e3be..5bb86736d89 100644 --- a/chromium/storage/common/database/DIR_METADATA +++ b/chromium/storage/common/database/DIR_METADATA @@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Blink>Storage>WebSQL" diff --git a/chromium/storage/common/database/database_identifier.cc b/chromium/storage/common/database/database_identifier.cc index 0de222ada39..29f58e75c8c 100644 --- a/chromium/storage/common/database/database_identifier.cc +++ b/chromium/storage/common/database/database_identifier.cc @@ -6,8 +6,8 @@ #include <stddef.h> +#include "base/cxx17_backports.h" #include "base/macros.h" -#include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "url/url_canon.h" @@ -20,8 +20,7 @@ namespace { // If the passed string is of the form "[1::2:3]", returns "[1__2_3]". std::string EscapeIPv6Hostname(const std::string& hostname) { // Shortest IPv6 hostname would be "[::1]". - if (hostname.length() < 5 || hostname.front() != '[' || - hostname.back() != ']') + if (hostname.size() < 5 || hostname.front() != '[' || hostname.back() != ']') return hostname; // Should be canonicalized before it gets this far. @@ -35,8 +34,7 @@ std::string EscapeIPv6Hostname(const std::string& hostname) { // If the passed string is of the form "[1__2_3]", returns "[1::2:3]". std::string UnescapeIPv6Hostname(const std::string& hostname) { - if (hostname.length() < 5 || hostname.front() != '[' || - hostname.back() != ']') + if (hostname.size() < 5 || hostname.front() != '[' || hostname.back() != ']') return hostname; std::string copy = hostname; @@ -88,9 +86,10 @@ DatabaseIdentifier DatabaseIdentifier::CreateFromOrigin( // static DatabaseIdentifier DatabaseIdentifier::CreateFromOrigin(const GURL& origin) { - if (!origin.is_valid() || origin.is_empty() || - !origin.IsStandard() || SchemeIsUnique(origin.scheme())) + if (!origin.is_valid() || origin.is_empty() || !origin.IsStandard() || + SchemeIsUnique(origin.scheme())) { return DatabaseIdentifier(); + } if (origin.SchemeIsFile()) return UniqueFileIdentifier(); @@ -117,8 +116,8 @@ DatabaseIdentifier DatabaseIdentifier::Parse(const std::string& identifier) { return DatabaseIdentifier(); if (identifier.find("..") != std::string::npos) return DatabaseIdentifier(); - char forbidden[] = {'\\', '/', ':' ,'\0'}; - if (identifier.find_first_of(forbidden, 0, base::size(forbidden)) != + static const char kForbidden[] = {'\\', '/', ':', '\0'}; + if (identifier.find_first_of(kForbidden, 0, base::size(kForbidden)) != std::string::npos) { return DatabaseIdentifier(); } @@ -130,8 +129,9 @@ DatabaseIdentifier DatabaseIdentifier::Parse(const std::string& identifier) { size_t last_underscore = identifier.find_last_of('_'); if (last_underscore == std::string::npos || last_underscore == first_underscore || - last_underscore == identifier.length() - 1) + last_underscore == identifier.size() - 1) { return DatabaseIdentifier(); + } std::string scheme(identifier.data(), first_underscore); if (scheme == "file") @@ -144,7 +144,8 @@ DatabaseIdentifier DatabaseIdentifier::Parse(const std::string& identifier) { auto port_str = base::MakeStringPiece( identifier.begin() + last_underscore + 1, identifier.end()); int port = 0; - if (!base::StringToInt(port_str, &port) || port < 0 || port >= 1 << 16) + constexpr int kMaxPort = 65535; + if (!base::StringToInt(port_str, &port) || port < 0 || port > kMaxPort) return DatabaseIdentifier(); std::string hostname = @@ -154,7 +155,7 @@ DatabaseIdentifier DatabaseIdentifier::Parse(const std::string& identifier) { GURL url(scheme + "://" + hostname + "/"); if (!url.IsStandard()) - hostname = ""; + hostname.clear(); // If a url doesn't parse cleanly or doesn't round trip, reject it. if (!url.is_valid() || url.scheme() != scheme || url.host() != hostname) diff --git a/chromium/storage/common/database/database_identifier_unittest.cc b/chromium/storage/common/database/database_identifier_unittest.cc index 18315f3f415..e85cbc9e07e 100644 --- a/chromium/storage/common/database/database_identifier_unittest.cc +++ b/chromium/storage/common/database/database_identifier_unittest.cc @@ -6,8 +6,8 @@ #include <stddef.h> +#include "base/cxx17_backports.h" #include "base/macros.h" -#include "base/stl_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" #include "url/origin.h" diff --git a/chromium/storage/common/file_system/DIR_METADATA b/chromium/storage/common/file_system/DIR_METADATA index a32478d8fb0..a6d562a2d2b 100644 --- a/chromium/storage/common/file_system/DIR_METADATA +++ b/chromium/storage/common/file_system/DIR_METADATA @@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Blink>Storage>FileSystem" diff --git a/chromium/storage/common/file_system/file_system_types.h b/chromium/storage/common/file_system/file_system_types.h index c171e0f1ad5..0677b34cdb9 100644 --- a/chromium/storage/common/file_system/file_system_types.h +++ b/chromium/storage/common/file_system/file_system_types.h @@ -103,9 +103,6 @@ enum FileSystemType { // given identifier in each origin. kFileSystemTypePluginPrivate, - // A filesystem that is mounted via the Privet storage protocol. - kFileSystemTypeCloudDevice, - // A filesystem that is mounted via the FileSystemProvider API. kFileSystemTypeProvided, diff --git a/chromium/storage/common/file_system/file_system_util.cc b/chromium/storage/common/file_system/file_system_util.cc index 1dba5ce3c44..e9402ff65aa 100644 --- a/chromium/storage/common/file_system/file_system_util.cc +++ b/chromium/storage/common/file_system/file_system_util.cc @@ -236,39 +236,6 @@ std::string GetFileSystemName(const GURL& origin_url, FileSystemType type) { return origin_identifier + ":" + type_string; } -FileSystemType QuotaStorageTypeToFileSystemType( - blink::mojom::StorageType storage_type) { - switch (storage_type) { - case blink::mojom::StorageType::kTemporary: - return kFileSystemTypeTemporary; - case blink::mojom::StorageType::kPersistent: - return kFileSystemTypePersistent; - case blink::mojom::StorageType::kSyncable: - return kFileSystemTypeSyncable; - case blink::mojom::StorageType::kQuotaNotManaged: - case blink::mojom::StorageType::kUnknown: - return kFileSystemTypeUnknown; - } - return kFileSystemTypeUnknown; -} - -blink::mojom::StorageType FileSystemTypeToQuotaStorageType( - FileSystemType type) { - switch (type) { - case kFileSystemTypeTemporary: - return blink::mojom::StorageType::kTemporary; - case kFileSystemTypePersistent: - return blink::mojom::StorageType::kPersistent; - case kFileSystemTypeSyncable: - case kFileSystemTypeSyncableForInternalSync: - return blink::mojom::StorageType::kSyncable; - case kFileSystemTypePluginPrivate: - return blink::mojom::StorageType::kQuotaNotManaged; - default: - return blink::mojom::StorageType::kUnknown; - } -} - std::string GetFileSystemTypeString(FileSystemType type) { switch (type) { case kFileSystemTypeTemporary: @@ -300,8 +267,6 @@ std::string GetFileSystemTypeString(FileSystemType type) { return "TransientFile"; case kFileSystemTypePluginPrivate: return "PluginPrivate"; - case kFileSystemTypeCloudDevice: - return "CloudDevice"; case kFileSystemTypeProvided: return "Provided"; case kFileSystemTypeDeviceMediaAsFileStorage: diff --git a/chromium/storage/common/file_system/file_system_util.h b/chromium/storage/common/file_system/file_system_util.h index c6f8fb7b756..954dcd26209 100644 --- a/chromium/storage/common/file_system/file_system_util.h +++ b/chromium/storage/common/file_system/file_system_util.h @@ -99,17 +99,6 @@ GURL GetFileSystemRootURI(const GURL& origin_url, FileSystemType type); COMPONENT_EXPORT(STORAGE_COMMON) std::string GetFileSystemName(const GURL& origin_url, FileSystemType type); -// Converts FileSystemType |type| to/from the StorageType |storage_type| that -// is used for the unified quota system. -// (Basically this naively maps TEMPORARY storage type to TEMPORARY filesystem -// type, PERSISTENT storage type to PERSISTENT filesystem type and vice versa.) -COMPONENT_EXPORT(STORAGE_COMMON) -FileSystemType QuotaStorageTypeToFileSystemType( - blink::mojom::StorageType storage_type); - -COMPONENT_EXPORT(STORAGE_COMMON) -blink::mojom::StorageType FileSystemTypeToQuotaStorageType(FileSystemType type); - // Returns the string representation of the given filesystem |type|. // Returns an empty string if the |type| is invalid. COMPONENT_EXPORT(STORAGE_COMMON) diff --git a/chromium/storage/common/file_system/file_system_util_unittest.cc b/chromium/storage/common/file_system/file_system_util_unittest.cc index d73536ef695..e146f09600f 100644 --- a/chromium/storage/common/file_system/file_system_util_unittest.cc +++ b/chromium/storage/common/file_system/file_system_util_unittest.cc @@ -8,7 +8,6 @@ #include "base/files/file_path.h" #include "base/macros.h" -#include "base/stl_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" diff --git a/chromium/storage/common/quota/padding_key.h b/chromium/storage/common/quota/padding_key.h index 58e9f0301e3..fea5f51e24f 100644 --- a/chromium/storage/common/quota/padding_key.h +++ b/chromium/storage/common/quota/padding_key.h @@ -39,6 +39,9 @@ int64_t ComputeRandomResponsePadding(); // |response_time| be the time stored in the cache and not just the current // time. The |side_data_size| should only be passed if padding is being // computed for a side data blob. +// +// TODO(https://crbug.com/1199077): Replace `url::Origin` with +// `blink::StorageKey` in the argument list. COMPONENT_EXPORT(STORAGE_COMMON) int64_t ComputeStableResponsePadding(const url::Origin& origin, const std::string& response_url, |